## 核心修复 ### 1. Auto-Reply Sender 修复(所有渠道) - AutoReplyListener.sendAutoReply() 通过 botInboxRepo 查询 inbox 关联的 AgentBot - 使用正确的 SenderType="AgentBot"(非小写 agent_bot)传递真实 AgentBot ID - bootstrap 注入 agentBotInboxRepo/agentBotRepo 依赖 ### 2. 事件数据 BUG 修复(影响所有 Webhook 渠道) - incoming_persister.dispatch(): 补全 sender_type/content 到 event.Data - channel/webhook.go: HandleWebhook 同步分发也补全 sender_type/content - 未补全前 AutoReplyListener 找不到字段直接跳过 ### 3. Web Widget SDK 生产验证修复 - cookie → localStorage token 同步(frontend/index.html) - 路由双注册修复(router.go) - Vite SPA 模式 + /widget 重写(vite.config.ts) - WidgetService 注入 Dispatcher 触发事件分发 ### 4. LLM 真实模型对接 - 配置 deepseek-v4-flash @ http://10.58.144.6:2014/v1 - LLM-mode auto-reply 规则创建并验证通过 - Prompt 文档落地: docs/captain-ai-auto-replay-prompt.md ### 5. 新增基础设施 - Helm chart (deploy/helm/) - Widget SDK 生产测试页面 - QA 报告 Closes: BUG-W2 (auth sync), BUG-W3 (route double-reg), BUG-WEBHOOK-EVENT (missing event data fields)
5.3 KiB
5.3 KiB
Captain AI — LLM 自动回复 Prompt 配置
概述
自动回复规则支持三种模式:static(静态文本)、llm(LLM 生成)、mixed(静态引导 + LLM 正文)。
本文档仅涉及 llm 和 mixed 模式下的 LLM Prompt 配置。
架构
客户消息 → Widget/Fake/Webhook Channel
→ AutoReplyListener.OnEvent()
→ AutoReplyRuleService.EvaluateRules()
→ 条件匹配成功
→ LLM ChatCompletion(mode=llm/mixed)
→ 生成回复内容
→ AutoReplyListener.sendAutoReply()
→ MessageService.Create() 生成消息
→ sender_type="AgentBot", sender_id=AgentBotID
LLM Provider 配置
Provider 通过 installation_configs 表持久化,key 如下:
| Key | 说明 |
|---|---|
COPILOT_PROVIDER_CONFIG |
JSON: chat/embedding/generation/request 设置 |
COPILOT_CHAT_API_KEY |
Chat API 密钥 |
COPILOT_EMBEDDING_API_KEY |
Embedding API 密钥 |
配置格式
{
"chat": {
"provider": "openai_compatible",
"base_url": "http://<host>:<port>/v1",
"model": "<model-name>"
},
"embedding": {
"mode": "reuse_chat_credentials",
"provider": "openai_compatible",
"base_url": "http://<host>:<port>/v1",
"model": "<model-name>",
"dimensions": 1024
},
"generation": {
"temperature": 0.7,
"max_tokens": 2048
},
"request": {
"timeout_seconds": 60,
"max_retries": 2
}
}
SQL 注入示例
DELETE FROM installation_configs WHERE name IN ('COPILOT_PROVIDER_CONFIG', 'COPILOT_CHAT_API_KEY', 'COPILOT_EMBEDDING_API_KEY');
INSERT INTO installation_configs (name, value, created_at, updated_at)
VALUES ('COPILOT_PROVIDER_CONFIG', '{"chat":{"provider":"openai_compatible","base_url":"http://<host>:<port>/v1","model":"<model>"},"embedding":{"mode":"reuse_chat_credentials","provider":"openai_compatible","base_url":"http://<host>:<port>/v1","model":"<model>","dimensions":1024},"generation":{"temperature":0.7,"max_tokens":2048},"request":{"timeout_seconds":60,"max_retries":2}}', NOW(), NOW());
INSERT INTO installation_configs (name, value, created_at, updated_at)
VALUES ('COPILOT_CHAT_API_KEY', '<api-key>', NOW(), NOW());
INSERT INTO installation_configs (name, value, created_at, updated_at)
VALUES ('COPILOT_EMBEDDING_API_KEY', '<api-key>', NOW(), NOW());
API 配置
也可以通过 Platform API 配置:
# Platform API 需要 platform_app access_token
curl -X PUT "http://localhost:3000/platform/api/v1/copilot/config" \
-H 'api_access_token: <platform-app-token>' \
-H 'Content-Type: application/json' \
-d '{
"chat": {
"provider": "openai_compatible",
"base_url": "http://<host>:<port>/v1",
"model": "<model>",
"api_key": "<api-key>"
},
"embedding": {
"mode": "reuse_chat_credentials",
"provider": "openai_compatible",
"base_url": "http://<host>:<port>/v1",
"model": "<model>",
"dimensions": 1024,
"api_key": "<api-key>"
}
}'
自动回复 Prompt 流程
规则评估(EvaluateRules)
文件: backend/internal/service/auto_reply_rule_service.go
EvaluateRules()
→ 按 priority 降序遍历 active 规则
→ matchConditions() 检查每条条件:
- message_content: contains / equals / regex / starts_with
- sender_type: Contact / User / AgentBot
- conversation_status: open / resolved / bot
- language: language_is
→ 匹配成功:
- static 模式: 直接返回 ResponseText
- llm 模式: composeLLMReply()
- mixed 模式: ResponseText + "\n\n" + composeLLMReply()
LLM 回复组装(composeLLMReply)
func (s *AutoReplyRuleService) composeLLMReply(ctx context.Context, rule *model.CaptainAutoReplyRule, evalCtx *AutoReplyEvaluationContext) (string, error) {
// 1. 加载 Assistant 配置(response_guidelines、config)
// 2. 构建 System Prompt:
// - 从 Assistant.ResponseGuidelines 获取行为指南
// - 从 rule.LLMPromptOverride 获取 prompt 覆盖
// 3. 构建历史消息上下文
// 4. 调用 llmProvider.ChatCompletion()
// 5. 返回生成的回复文本
}
System Prompt 构建
System: You are a helpful customer support assistant for {{account_name}}.
{{response_guidelines}}
{{llm_prompt_override}}
Context:
- Account: {{account_name}}
- Inbox: {{inbox_name}}
- Customer: {{contact_name}}
Previous conversation:
{{previous_messages_formatted}}
Current customer message: {{message_content}}
Please provide a helpful, concise response.
生产部署检查清单
- LLM Provider API 可访问(
curl http://<host>:<port>/v1/chat/completions) COPILOT_PROVIDER_CONFIG已写入installation_configsCOPILOT_CHAT_API_KEY已配置- 环境变量
GOCHAT_ENV未设置为production时自动回复规则默认为 draft - AgentBot 已创建并关联到目标 Inbox
- 规则
status设为active - Prompt 注入防护已启用(
llm_prompt_override来自管理员配置而非用户输入)
已知限制
- Auto-reply 发送的 sender_type 目前为
AgentBot,需要先创建 AgentBot 记录并关联到 Inbox - LLM 回复为同步阻塞(在 AutoReplyListener 的 OnEvent 中执行),生产环境中建议移入异步 worker
one_time_only的去重策略是通过检查同一 conversation 中是否存在agent_bot消息实现,精确度有限