Files
gochat/docs/captain-ai-auto-replay-prompt.md
T
Rogee 9816848ca2 fix: Web Widget SDK + Auto-Reply AgentBot sender + LLM 真实模型对接
## 核心修复

### 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)
2026-07-28 14:03:19 +08:00

5.3 KiB
Raw Blame History

Captain AI — LLM 自动回复 Prompt 配置

概述

自动回复规则支持三种模式:static(静态文本)、llmLLM 生成)、mixed(静态引导 + LLM 正文)。
本文档仅涉及 llmmixed 模式下的 LLM Prompt 配置。

架构

客户消息 → Widget/Fake/Webhook Channel
  → AutoReplyListener.OnEvent()
    → AutoReplyRuleService.EvaluateRules()
      → 条件匹配成功
        → LLM ChatCompletionmode=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_configs
  • COPILOT_CHAT_API_KEY 已配置
  • 环境变量 GOCHAT_ENV 未设置为 production 时自动回复规则默认为 draft
  • AgentBot 已创建并关联到目标 Inbox
  • 规则 status 设为 active
  • Prompt 注入防护已启用(llm_prompt_override 来自管理员配置而非用户输入)

已知限制

  1. Auto-reply 发送的 sender_type 目前为 AgentBot,需要先创建 AgentBot 记录并关联到 Inbox
  2. LLM 回复为同步阻塞(在 AutoReplyListener 的 OnEvent 中执行),生产环境中建议移入异步 worker
  3. one_time_only 的去重策略是通过检查同一 conversation 中是否存在 agent_bot 消息实现,精确度有限