Files
gochat/docs/plans/2026-07-12-copilot-configuration.md
T

19 KiB
Raw Blame History

Copilot 配置中心实施计划

日期:2026-07-12 状态:已实施并验证(平台 Provider、账户模型/行为、Embedding 重建) 菜单名称:Copilot 配置 目标:为 GoChat 自托管部署提供可安全管理、可测试、可运行时生效的 Copilot/LLM 配置入口,并让页面选择的模型真正作用于 LLM 请求。


1. 已确认的产品决策

  1. 设置菜单统一命名为 Copilot 配置,不在用户界面继续使用“Captain AI 配置”作为供应商配置名称。
  2. Captain 仍保留为 AI 助手、知识库、场景、工具等业务模块的内部领域名称,不做全仓重命名。
  3. LLM Provider、Base URL、API Key 属于平台级配置,对整套 GoChat 安装生效。
  4. 功能开关、功能模型、回复风格属于账户级配置,只影响当前 Account。
  5. Assistant 的提示词、Guardrails、Response Guidelines、知识文档和 Inbox 绑定继续在 Assistant 页面管理,不塞入 Copilot 配置页。
  6. API Key 以明文写入 installation_configs.value;接口只返回配置状态和掩码,日志禁止记录 Key 或 Authorization Header,页面不提供查看明文能力。
  7. Copilot 在系统中全局永久启用,不提供总开关,也不允许通过环境变量、配置文件或页面关闭。
  8. Copilot Provider 参数只从数据库读取,不定义任何 Copilot/Captain 环境变量。
  9. 除 Embedding 维度变化外,配置保存后应运行时生效,不要求重启服务。

2. 实施前缺口

实施前仓库已经有 Captain/Copilot 页面、API 和 LLM Provider,但还不是一个可用的配置闭环:

  • 设置侧栏中的 Captain AI 入口被注释。
  • 旧设置页仅允许 Cloud/Enterprise 安装类型访问,自托管 Community 配置为不可访问。
  • 旧设置页只能保存 captain_modelscaptain_features,没有 Provider、Base URL、API Key。
  • Provider 在 bootstrap.go 启动时一次性创建,页面配置无法替换运行中的 Provider。
  • 旧启动配置工厂接收 provider 参数,但实际固定创建 OpenAI-compatible Eino ChatModel;该入口现已移除。
  • 多个 Service 仍使用硬编码模型或 Provider 默认模型,账户保存的模型选择没有完整进入请求链路。
  • installation_configs 已有平台级 CRUD,但目前是无类型字符串存储,不能直接安全暴露 LLM 密钥。

因此本任务不能只解开旧菜单;需要同时补齐配置存储、权限、运行时 Provider 和模型解析。


3. 页面入口与权限

3.1 菜单与路由

  • 菜单位置:设置 → Copilot 配置
  • 页面路由:/app/accounts/:accountId/settings/copilot
  • 前端路由名:copilot_settings_index
  • 移除旧路由的 Cloud/Enterprise 安装类型限制。
  • 不使用 captain_integration Feature Flag 或其他开关控制配置页和 Copilot 总体可用性。
  • Provider 尚未配置时页面展示“配置不完整”,而不是“未启用”。

3.2 权限分层

用户角色 平台 Provider 配置 账户功能配置 连接测试 API Key 状态
SuperAdmin 可读写 可读写 可执行 仅显示是否已配置和掩码
Account Administrator 只读状态 可读写 不可执行平台密钥测试 仅显示“已配置/未配置”
Agent 不可访问 不可访问 不可访问 不可访问

平台配置的写接口必须使用 SuperAdmin 中间件保护,不能仅依赖前端隐藏。


4. 页面信息架构

页面分为五个区块:

  1. 运行状态:当前 Provider、连接状态和配置完整性。Copilot 始终启用,不提供总开关。
  2. 对话模型Provider、Base URL、API Key、默认 Chat Model。
  3. Embedding 模型Embedding Provider、Key、Endpoint、Model、Dimensions。
  4. 生成与可靠性Temperature、Max Tokens、Timeout、Retry。
  5. 当前账户功能Editor、Copilot、Assistant、标签建议、知识库语义搜索的开关和模型。

“保存配置”和“测试连接”必须是两个独立动作:测试候选参数不落库;保存前后端均需再次校验。


5. 平台级参数规划

5.1 基础状态

字段 配置键 类型/默认值 页面规则 生效方式
配置状态 configured derived boolean 根据页面保存的 Provider、Model、Base URL 与 API Key 判断 只读

不定义 enabled 字段。Copilot 路由、菜单和服务始终注册;账户级功能开关只控制具体能力,不等价于关闭系统 Copilot。

5.2 对话模型

字段 配置键 类型/默认值 校验与交互
Provider chat.provider enumopenai / anthropic / openai_compatible;默认 openai 必填;决定请求协议,不再把所有 Provider 当 OpenAI 协议处理
Base URL chat.base_url URL openai/anthropic 自动提供官方默认值;openai_compatible 必填;禁止非 HTTP(S) URL
API Key chat.api_key secret 写入时允许空值表示“不修改”;清除必须单独确认;GET 永不返回明文
默认模型 chat.model string,默认 gpt-4o-mini 必填;支持手工输入,不能只依赖前端静态模型列表

Provider 预设只负责填充默认 Endpoint,不锁死模型:

Provider 默认 Base URL 协议实现
OpenAI https://api.openai.com/v1 llm.OpenAIProviderOpenAI Chat Completions API
Anthropic https://api.anthropic.com llm.AnthropicProviderAnthropic Messages API
OpenAI Compatible 用户填写 llm.OpenAIProvider + 自定义 Base URL;适用于 DeepSeek、通义千问、豆包及自建网关

EinoProvider 适配器仍保留给显式构造的 Eino ChatModel/Embedder 使用;数据库驱动的 ProviderManager 运行时配置链路不经过该适配器,而是按协议直接创建上述 Provider。

首期不单独增加 DeepSeek/Qwen/Doubao 枚举,避免把供应商宣传名称与真实协议实现绑死。

5.3 Embedding 模型

字段 配置键 类型/默认值 校验与交互
Embedding 模式 embedding.mode enumreuse_chat_credentials / separate;默认 reuse_chat_credentials Chat Provider 为 Anthropic 时必须使用 separate
Provider embedding.provider enumopenai / openai_compatible 仅在 separate 模式展示
Base URL embedding.base_url URL 自定义兼容 Provider 必填
API Key embedding.api_key secret 与 Chat Key 分开存储;允许复用但不能在响应中回显
模型 embedding.model string,默认 text-embedding-3-small 必填;连接测试必须实际调用 embeddings API
向量维度 embedding.dimensions integer,默认 1536 范围 1-4096;修改时二次确认,并通过重建接口迁移现有文章向量

Embedding 配置不能隐式依赖 Anthropic,因为 Anthropic 当前没有 Embeddings API。

5.4 生成与可靠性

字段 配置键 类型/默认值 校验 生效方式
Temperature generation.temperature number,默认 0.7 0-2 热生效
最大输出 Tokens generation.max_tokens integer,默认 1024 64-32768 热生效
请求超时 request.timeout_seconds integer,默认 60 5-300 秒 热生效
最大重试次数 request.max_retries integer,默认 3 0-5;只重试网络错误、429 和 5xx 热生效

首期不开放以下高风险或不稳定参数:关闭 TLS 校验、任意代理地址、任意请求 Header、完整请求/响应日志。


6. 账户级参数规划

账户配置继续存入 Account 的 captain_modelscaptain_featurescaptain_preferences,但 UI 名称统一为 Copilot。

6.1 功能开关和模型

功能 Feature Key Model Key 默认状态 说明
编辑器改写 editor editor 开启 润色、改写、语气调整
Copilot 对话 copilot copilot 开启 客服侧边栏问答与回复建议
AI Assistant assistant assistant 关闭 Assistant Playground、自动辅助能力
标签建议 label_suggestion label_suggestion 关闭 仅建议;自动应用由账户策略决定
知识库语义搜索 help_center_search 使用平台 Embedding 模型 关闭 开启前必须通过 Embedding 测试并完成索引

首期暂不在页面开放 audio_transcription,直到后端具有独立的语音转写 Provider 和真实调用链。

模型下拉选项应由后端根据当前 Provider 返回,且始终提供“手工填写模型 ID”。不可再返回无法由当前 Provider 调用的静态模型列表。

6.2 回复行为

字段 现有字段 默认值 说明
回复语气 tone professional professional / friendly / casual / formal
回复语言 language auto auto 表示跟随客户消息;同时允许明确语言代码
最大回复长度 max_response_length 500 范围 50-5000 字符
附加指令 custom_prompt_suffix 最大 1000 字;页面提示其作用范围
自动应用标签 auto_label_enabled false 与“标签建议”功能分开控制
自动创建跟进 auto_follow_up_enabled false 默认关闭
自动回复客户 auto_reply_enabled false 高风险开关,需二次确认并提示绑定 Assistant/Inbox

Assistant 自身的 Temperature、Guardrails、Response Guidelines 优先级高于账户默认值。


7. 配置来源

  • Copilot 始终启用,不存在部署级启用开关。
  • Provider、Base URL、API Key 与默认模型仅允许通过页面和对应 API 配置。
  • 不定义或读取任何 Captain/Copilot 环境变量,也不读取 config*.yaml 中的 Provider、模型或启用配置。
  • 数据库没有完整配置时,业务 API 返回“Provider 未配置”,不会使用空 Key 请求外部服务。
  • 页面、菜单、接口响应文案使用“Copilot”;内部 Captain 领域名保持不变。

8. 存储与密钥呈现

8.1 存储方案

复用 installation_configs,但通过专用 CopilotConfigService 管理以下固定键,不允许前端直接操作通用键值 CRUD:

InstallationConfig Name 内容
COPILOT_PROVIDER_CONFIG 不含密钥的 JSON 配置
COPILOT_CHAT_API_KEY Chat Provider API Key 明文
COPILOT_EMBEDDING_API_KEY 独立 Embedding Provider API Key 明文;复用 Chat 凭据时为空

8.2 API Key 处理要求

  • Copilot API Key 直接以明文写入 installation_configs.value,不做 AES-256-GCM 或其他应用层加密。
  • 数据库、备份和运维访问权限承担密钥保护责任;密钥不得进入普通配置导出、日志或错误响应。
  • API 响应只返回:configured: true/falsemasked_value: "sk-****abcd"
  • 更新请求中省略 api_key 表示保留原值;clear_api_key: true 才允许清除。
  • 错误日志、审计日志、连接测试响应均不得包含 Key、Authorization Header 或完整请求体。

9. 后端 API 规划

9.1 平台级接口(SuperAdmin

方法 路径 用途
GET /platform/api/v1/copilot/config 获取平台配置、掩码和状态
PUT /platform/api/v1/copilot/config 校验并保存平台配置
POST /platform/api/v1/copilot/config/test 用候选配置测试 Chat 和 Embedding,不保存
GET /platform/api/v1/copilot/embeddings/reindex 获取文章 Embedding 重建进度
POST /platform/api/v1/copilot/embeddings/reindex 后台启动文章 Embedding 重建

连接测试返回:

{
  "chat": { "ok": true, "latency_ms": 320, "model": "gpt-4o-mini" },
  "embedding": { "ok": true, "latency_ms": 180, "model": "text-embedding-3-small", "dimensions": 1536 }
}

失败响应仅返回归一化错误:认证失败、Endpoint 不可达、模型不存在、限流、超时、响应格式不兼容、Embedding 维度不匹配。

9.2 账户级接口(Administrator/SuperAdmin

方法 路径 用途
GET /api/v1/accounts/:account_id/copilot/config 返回平台只读状态 + 当前账户配置
PUT /api/v1/accounts/:account_id/copilot/config 更新账户功能、模型和回复行为

/captain/preferences 接口保留兼容,但新页面只调用 /copilot/config 聚合接口。


10. 运行时 Provider 设计

使用 llm.ProviderManager 替代 bootstrap 中固定注入单个 llm.Provider

CopilotConfigService
  → 解析有效平台配置
  → 构造候选 Chat Provider + Embedding Provider
  → 执行轻量健康校验
  → 原子替换 Provider Snapshot
  → 新请求使用新 Snapshot,进行中的请求继续完成

核心约束:

  1. 保存失败或 Provider 初始化失败时,不替换当前可用配置。
  2. Service 依赖 ProviderResolver,每次任务开始时获取不可变 Snapshot。
  3. Snapshot 包含 Chat Provider、Embedding Provider、默认模型和生成参数。
  4. 账户模型解析顺序:账户 feature model → 平台 chat.model → provider default
  5. 所有硬编码 gpt-4、静态模型和直接读取启动配置的调用都必须迁移到 resolver。
  6. Provider 配置不完整时返回明确业务错误,不向外部服务发请求。

Embedding 维度由迁移 000056_make_article_embedding_dimension_dynamic 改为动态 pgvector 列;保存维度变更后由 SuperAdmin 通过重建接口重新生成全部文章向量,页面展示进度和失败状态。


11. 前端交互要求

  • 菜单展示名称固定为“Copilot 配置”。
  • 页面顶部显示状态徽标:配置完整、配置不完整、连接正常、连接异常。
  • API Key 输入框默认空白并显示“已配置”;不把掩码当作真实值回传。
  • Provider 改变时自动填充推荐 Base URL,但不覆盖用户已经编辑的值。
  • Anthropic + 复用 Chat Embedding 凭证属于无效组合,前端即时提示,后端再次拒绝。
  • “测试连接”分别展示 Chat 与 Embedding 结果。
  • 保存成功后展示实际生效的 Provider、模型和时间。
  • 修改 Embedding Dimensions 时展示阻断式警告,不允许无确认保存。
  • Account Administrator 看到平台配置状态但不能看到 Endpoint 之外的敏感信息,也不能编辑平台配置。

12. 实施阶段

阶段 1:配置闭环(P0

  1. 新增 Copilot typed config DTO、Service 和平台/账户 API。
  2. 接入 InstallationConfig 明文密钥存储、API 掩码和不回显规则。
  3. 实现 Provider 工厂的 OpenAI、Anthropic、OpenAI-compatible 分支。
  4. 实现 CopilotProviderManager 和热切换。
  5. 新建“Copilot 配置”页面和菜单,移除安装类型限制。
  6. 接通 Chat/Embedding 连接测试。

阶段 2:运行链路统一(P0

  1. 清理 Service 中硬编码模型。
  2. 将账户 feature model 接入所有对应 LLM 请求。
  3. 统一 Temperature、Max Tokens、Timeout、Retry 的解析。
  4. Provider 未配置时返回统一错误码和前端提示。

阶段 3:账户策略与质量(P1

  1. 聚合现有 CaptainPreference 回复行为配置。
  2. 增加配置变更审计事件,但不记录密钥。
  3. 增加 Provider 健康状态和最近测试时间。
  4. 提供知识库 Embedding 重建入口和进度状态。

阶段 4:后续能力(P2

  • Provider 动态模型列表发现与缓存。
  • 独立语音转写 Provider。
  • Token 用量、成本和账户配额。
  • Langfuse/OpenTelemetry AI 调用观测。
  • 多 Provider fallback;首期不自动跨供应商降级,避免数据和成本不可控。

13. 验证结果

后端自动化

  • GOCHAT_TEST_DB=sqlite go test ./internal/... ./pkg/... ./cmd/... 通过。
  • go test ./... 通过。
  • 覆盖明文存储、掩码/不回显、保留/替换/清除、候选测试不落库、Provider 热切换、 OpenAI/OpenAI-compatible/Anthropic、超时/重试、统一安全错误、动态 Embedding 维度和重建状态。
  • Service → ProviderManager → Fake HTTP Provider 集成测试证明 editor、copilot、assistant、 label suggestion 分别使用账户配置的功能模型,未配置时由 Manager 回退平台默认模型。
  • Assistant 显式配置的 Temperature(包括 0)优先于平台默认值;未显式配置时继续使用平台值。
  • OpenAI-compatible 的错误响应与 malformed SSE chunk 不进入日志或健康检查响应;对外只返回稳定错误类别。
  • SuperAdmin 平台权限、Administrator 账户权限和 Agent 禁止访问均有 Handler/Middleware 回归测试。
  • 配置变更写入 audits,只记录 Provider、模型、维度、配置状态和是否变更 Key,不记录 Key 或掩码。

前端自动化

  • Vitest 覆盖菜单/路由、Pinia 平台与账户请求、SuperAdmin 识别、Provider 条件字段、 API Key 不回填/清除确认、清除 Key 时允许保存但禁止连接测试、Anthropic 非法组合、 维度确认、回复行为和自动回复确认。
  • pnpm build 通过。

真实运行验证

  • Playwright 在 http://127.0.0.1:3036/app/accounts/1/settings/copilot 验证页面名称、路由、 SuperAdmin 可编辑态、无框架错误覆盖,以及 1440×1000 和 390×844 布局。
  • 本地 Fake LLM Server 验证候选连接测试同时调用 Chat 与 Embedding;请求使用页面填写的 gpt-4o-minitext-embedding-3-small、Bearer Key 和 dimensions: 1536
  • 候选测试前数据库无 Copilot Key;保存后 COPILOT_CHAT_API_KEY 明文为测试 Key;刷新页面后 输入框为空,仅显示掩码,再次测试使用已保存 Key 成功。
  • PostgreSQL 审计记录包含 Account、SuperAdmin、Provider/模型/维度和 Key 变更布尔值, 不包含 API Key 或掩码。

14. 验收标准

  1. 自托管 Community 安装可以进入“设置 → Copilot 配置”。
  2. 只有 SuperAdmin 可以修改平台 Provider 和 API Key。
  3. API Key 明文落库,所有读取接口只返回掩码/状态且日志不记录密钥。
  4. 页面可以独立测试 Chat 与 Embedding 连接。
  5. 保存有效配置后不重启即可让新 LLM 请求使用新 Provider。
  6. editor/copilot/assistant/label suggestion 使用账户模型,未指定时回退平台默认模型。
  7. Anthropic Chat 可以搭配独立 OpenAI-compatible Embedding 配置。
  8. Provider 不可用或未配置时返回稳定错误码,不使用空 Key 请求外部服务。
  9. 候选测试和失败配置不会替换当前正在工作的 Provider。
  10. 相关后端测试、前端测试/构建和浏览器端到端验证通过。

15. 本次明确不做

  • 不将所有 Captain 代码、表名和 API 全量改名为 Copilot
  • 不允许普通 Agent 或任意 Account Administrator 修改平台 API Key。
  • 不提供 Copilot 总开关、环境变量配置或 YAML Provider 配置。
  • 不在首期支持任意 Header、关闭 TLS 校验或输出完整 LLM 请求日志。
  • 不展示或提供复制已保存 API Key 明文的能力。
  • 不在首期实现自动跨 Provider fallback。
  • 不把 Assistant 的知识库、工具、Guardrails 和 Inbox 绑定搬入 Copilot 配置页。