跳转到主要内容

概述

Shannon 使用特性开关来控制可选功能、实验性功能和企业扩展,无需修改代码。这实现了以下功能的清晰分离:
  • 开源核心功能(所有用户可用)
  • 企业/私有功能(通过开关控制)
  • 实验性功能(可切换以进行测试)

无需重新编译

启用/禁用功能无需重新构建服务

基于环境

开发/预发布/生产环境使用不同的开关配置

清晰分离

企业功能与开源核心隔离

渐进式发布

在全面部署前测试新功能

配置

配置文件

特性开关在 config/shannon.yamlfeatures 部分定义:
# config/shannon.yaml
features:
  # 企业工作流功能
  ads_research: false              # 广告研究工作流(企业版)
  advanced_synthesis: false        # 高级综合模板

  # 实验性功能
  parallel_streaming: true         # 多代理并行流式传输
  enhanced_memory: false           # 增强向量内存

  # 自定义集成
  vendor_tools_enabled: false      # 启用供应商特定工具

环境变量

可通过环境变量覆盖特性开关:
# .env
SHANNON_FEATURE_ADS_RESEARCH=true
SHANNON_FEATURE_PARALLEL_STREAMING=false
命名约定SHANNON_FEATURE_<开关名称大写>

优先级顺序

  1. 环境变量(最高优先级)
  2. 配置覆盖层config/overlays/shannon.{env}.yaml
  3. 基础配置config/shannon.yaml
  4. 代码默认值(最低优先级)

使用模式

在 Go 代码中(Orchestrator)

package main

import (
    "github.com/Kocoro-lab/Shannon/go/orchestrator/internal/config"
)

func routeWorkflow(ctx context.Context, req *pb.Request) error {
    cfg, _ := config.LoadShannon()

    // 检查特性开关
    if cfg.Features.AdsResearch {
        return routeToAdsResearchWorkflow(ctx, req)
    }

    return routeToStandardWorkflow(ctx, req)
}

在 Python 代码中(LLM Service)

from llm_service.config import load_shannon_config

config = load_shannon_config()

# 检查特性开关
if config.get("features", {}).get("vendor_tools_enabled"):
    from llm_service.tools.vendor import register_vendor_tools
    register_vendor_tools()

条件导入模式

使用特性开关与条件导入实现清晰分离:
# roles/presets.py
_PRESETS = {
    "general": GENERAL_PRESET,
    "research": RESEARCH_PRESET,
}

# 条件加载企业角色
if config.get("features", {}).get("ads_research"):
    try:
        from .enterprise.ads_analyst import ADS_ANALYST_PRESET
        _PRESETS["ads_analyst"] = ADS_ANALYST_PRESET
    except ImportError:
        pass  # 没有企业模块,Shannon 仍可正常工作

常用特性开关

开关名称类型描述默认值
ads_research企业版带市场分析的广告研究工作流false
parallel_streaming实验性多代理并行 SSE 流式传输true
advanced_synthesis企业版自定义综合模板false
vendor_tools_enabled集成启用供应商特定工具适配器false
enhanced_memory实验性具有混合搜索的高级向量内存false

最佳实践

1. 默认禁用

新功能应在基础配置中默认为 false
# config/shannon.yaml
features:
  new_feature: false  # ✅ 安全的默认值

2. 使用环境覆盖层

为不同部署创建特定于环境的覆盖层:
# config/overlays/shannon.production.yaml
features:
  ads_research: true
  parallel_streaming: true
  enhanced_memory: false  # 仍在测试中
加载方式:
SHANNON_CONFIG_PATH=config/overlays/shannon.production.yaml

3. 使用 Try/Except 保护

始终为企业/可选功能使用优雅降级:
if config.features.vendor_tools_enabled:
    try:
        from .vendor import CustomVendorTool
    except ImportError:
        logger.warning("供应商工具不可用,使用标准工具")

4. 记录功能要求

features:
  # 需要:GA4_SERVICE_ACCOUNT_KEY 环境变量
  # 供应商模块:llm_service/tools/vendor_adapters/ga4/
  ga4_integration: false

企业功能模式

Shannon 使用特性开关将开源核心企业扩展分离:

文件结构

Shannon/
├── config/
│   ├── shannon.yaml                    # 基础配置(开源)
│   └── overlays/
│       └── shannon.enterprise.yaml     # 企业开关
├── go/orchestrator/
│   └── internal/workflows/
│       ├── standard_workflow.go        # 开源工作流
│       └── enterprise/                 # 企业工作流
│           └── ads_research.go         # 由开关控制
└── python/llm-service/
    └── llm_service/
        ├── roles/
        │   ├── presets.py              # 开源角色 + 条件加载
        │   └── enterprise/             # 企业角色
        │       └── ads_analyst.py      # 由开关控制
        └── tools/
            └── vendor_adapters/        # 供应商工具(由开关控制)

条件工作流路由

// orchestrator/internal/workflows/router.go
func SelectWorkflow(ctx context.Context, cfg *config.Shannon, req *pb.Request) Workflow {
    // 检查企业特性开关
    if cfg.Features.AdsResearch && req.Context["workflow_type"] == "ads_research" {
        return NewAdsResearchWorkflow()
    }

    // 回退到开源工作流
    return NewStandardWorkflow()
}

使用特性开关进行测试

单元测试

func TestAdsResearchWorkflow(t *testing.T) {
    cfg := &config.Shannon{
        Features: config.FeatureFlagsConfig{
            AdsResearch: true,  // 为测试启用
        },
    }

    workflow := SelectWorkflow(context.Background(), cfg, testReq)
    assert.IsType(t, &AdsResearchWorkflow{}, workflow)
}

集成测试

# 启用功能运行测试
SHANNON_FEATURE_ADS_RESEARCH=true go test ./...

# 禁用功能运行测试(开源模式)
SHANNON_FEATURE_ADS_RESEARCH=false go test ./...

部署策略

金丝雀部署

为部分用户启用功能:
func isFeatureEnabled(userID string, featureName string) bool {
    // 检查用户特定的特性开关(例如,从数据库)
    if userHasAccess(userID, featureName) {
        return true
    }

    // 回退到全局配置
    return cfg.Features.Get(featureName)
}

A/B 测试

基于特性开关路由流量:
if experimentGroup(userID) == "variant_a" && cfg.Features.EnhancedMemory {
    return useEnhancedMemory(ctx, req)
}
return useStandardMemory(ctx, req)

监控与可观测性

记录特性开关使用情况以便调试:
logger.Info("特性开关检查",
    zap.String("feature", "ads_research"),
    zap.Bool("enabled", cfg.Features.AdsResearch),
    zap.String("user_id", userID),
)
添加指标:
featureFlagGauge.WithLabelValues("ads_research").Set(
    boolToFloat64(cfg.Features.AdsResearch),
)

迁移指南

添加新特性开关

1

在配置中定义开关

添加到 config/shannon.yaml
features:
  my_new_feature: false  # 默认禁用
2

更新 Go 结构

go/orchestrator/internal/config/shannon.go 中添加字段:
type FeatureFlagsConfig struct {
    // ... 现有开关
    MyNewFeature bool `json:"my_new_feature" yaml:"my_new_feature"`
}
3

在代码中使用

控制功能:
if cfg.Features.MyNewFeature {
    return newFeatureBehavior()
}
return existingBehavior()
4

添加测试

测试启用/禁用两种状态:
func TestMyNewFeature_Enabled(t *testing.T) { /* ... */ }
func TestMyNewFeature_Disabled(t *testing.T) { /* ... */ }
5

更新文档

更新本页和环境变量文档。

相关文档