docs(copilot): define global configuration
This commit is contained in:
@@ -0,0 +1,356 @@
|
||||
# Copilot 配置中心实施计划
|
||||
|
||||
> 日期:2026-07-12
|
||||
> 状态:待实施
|
||||
> 菜单名称:`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 明文落库,不增加应用层加密;接口只返回掩码、日志禁止记录,页面不提供查看明文能力。
|
||||
7. Copilot 在系统中全局永久启用,不提供总开关,也不允许通过环境变量、配置文件或页面关闭。
|
||||
8. Copilot Provider 参数只从数据库读取,不定义任何 Copilot/Captain 环境变量。
|
||||
9. 除 Embedding 维度变化外,配置保存后应运行时生效,不要求重启服务。
|
||||
|
||||
---
|
||||
|
||||
## 2. 当前实现缺口
|
||||
|
||||
当前仓库已经有 Captain/Copilot 页面、API 和 LLM Provider,但还不是一个可用的配置闭环:
|
||||
|
||||
- 设置侧栏中的 Captain AI 入口被注释。
|
||||
- 旧设置页仅允许 Cloud/Enterprise 安装类型访问,自托管 Community 配置为不可访问。
|
||||
- 旧设置页只能保存 `captain_models` 和 `captain_features`,没有 Provider、Base URL、API Key。
|
||||
- Provider 在 `bootstrap.go` 启动时一次性创建,页面配置无法替换运行中的 Provider。
|
||||
- `NewProviderFromConfig` 接收 `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` | enum:`openai` / `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` | Eino OpenAI |
|
||||
| Anthropic | `https://api.anthropic.com` | Anthropic Messages API |
|
||||
| OpenAI Compatible | 用户填写 | Eino OpenAI;适用于 DeepSeek、通义千问、豆包及自建网关 |
|
||||
|
||||
首期不单独增加 DeepSeek/Qwen/Doubao 枚举,避免把供应商宣传名称与真实协议实现绑死。
|
||||
|
||||
### 5.3 Embedding 模型
|
||||
|
||||
| 字段 | 配置键 | 类型/默认值 | 校验与交互 |
|
||||
|---|---|---|---|
|
||||
| Embedding 模式 | `embedding.mode` | enum:`reuse_chat_credentials` / `separate`;默认 `reuse_chat_credentials` | Chat Provider 为 Anthropic 时必须使用 `separate` |
|
||||
| Provider | `embedding.provider` | enum:`openai` / `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_models`、`captain_features` 和 `captain_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_API_KEY` | 明文 API Key |
|
||||
|
||||
### 8.2 API Key 处理要求
|
||||
|
||||
- 不对 Copilot API Key 使用 AES-256-GCM 或其他应用层加密。
|
||||
- API Key 以明文写入 `installation_configs.value`;数据库访问控制、备份权限和基础设施安全由部署方负责。
|
||||
- API 响应只返回:`configured: true/false`、`masked_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,不保存 |
|
||||
|
||||
连接测试返回:
|
||||
|
||||
```json
|
||||
{
|
||||
"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 设计
|
||||
|
||||
新增 `CopilotProviderManager`,替代 bootstrap 中固定注入单个 `llm.Provider`:
|
||||
|
||||
```text
|
||||
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 维度变化不自动替换在线索引;页面应先提示重新索引,完成后再切换。
|
||||
|
||||
---
|
||||
|
||||
## 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. 验证计划
|
||||
|
||||
### 后端
|
||||
|
||||
- 数据库配置读取、默认建议值和非法组合单元测试。
|
||||
- API Key 明文存储、API 掩码、保留、替换、清除测试。
|
||||
- SuperAdmin/Administrator/Agent 权限测试。
|
||||
- OpenAI-compatible 与 Anthropic 协议适配测试。
|
||||
- 使用本地 Fake LLM Server 验证 Chat、Streaming、Embedding、401、404、429、5xx、Timeout。
|
||||
- Provider 热切换测试:失败配置不替换旧 Provider,成功配置对新请求立即生效。
|
||||
- 检查所有 LLM Service 使用 resolver,不再硬编码模型。
|
||||
|
||||
### 前端
|
||||
|
||||
- 菜单和路由权限测试。
|
||||
- API Key 不回填、掩码状态、清除确认测试。
|
||||
- Provider 条件字段和无效组合校验测试。
|
||||
- Account Administrator 只读平台配置测试。
|
||||
- 保存、测试连接、错误提示和配置不完整状态测试。
|
||||
|
||||
### 回归
|
||||
|
||||
- `cd backend && GOCHAT_TEST_DB=sqlite go test ./internal/... ./pkg/... ./cmd/...`
|
||||
- `cd frontend && pnpm build`
|
||||
- 浏览器验证:SuperAdmin 配置 → 测试连接 → 保存 → Copilot 实际回复 → 请求使用所选模型。
|
||||
- 日志扫描确认不出现 API Key 或 Authorization Header。
|
||||
|
||||
---
|
||||
|
||||
## 14. 验收标准
|
||||
|
||||
1. 自托管 Community 安装可以进入“设置 → Copilot 配置”。
|
||||
2. 只有 SuperAdmin 可以修改平台 Provider 和 API Key。
|
||||
3. API Key 明文落库,所有读取接口只返回掩码/状态且日志不记录密钥。
|
||||
4. 页面可以独立测试 Chat 与 Embedding 连接。
|
||||
5. 保存有效配置后不重启即可让新 LLM 请求使用新 Provider。
|
||||
6. 页面选择的 editor/copilot/assistant 模型真实出现在对应 Provider 请求中。
|
||||
7. Anthropic Chat 可以搭配独立 OpenAI-compatible Embedding 配置。
|
||||
8. Provider 不可用或未配置时返回清晰错误,不出现空 Key 请求或模糊 500。
|
||||
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 配置页。
|
||||
Reference in New Issue
Block a user