# 企业微信自动客服改造方案 ## 1. 目标概述 当前项目已经具备企业微信消息管理能力,后端 `helper.exe` 通过 DLL 注入、Socket 回调、本地 HTTP 服务和 `requestdata` / `eventdata` 模板,能够接收企业微信事件并发送企业微信消息。 本次需求是在现有能力上增加“自动客服”模块: - 前端提供一键开启入口。 - 后端自动监听企业微信消息。 - 私聊客户消息自动处理。 - 群聊消息仅在用户 @ 当前机器人时处理。 - 根据本地知识库检索内容。 - 调用 AI 根据知识库内容生成回复。 - 能回答则自动回复客户。 - 不能回答、AI 失败或知识库低匹配时,自动私信指定同事转人工处理。 ## 2. 当前项目基础 ### 2.1 技术结构 项目当前是: - 桌面端:Wails - 后端主程序:Go,`qiweimanager.exe` - 辅助进程:Go,`helper.exe` - 前端:Vue 3 + Vite + Element Plus - 本地 HTTP 服务:默认 `http://localhost:10001` - 企业微信底层通信:`Helper_4.1.33.6009.dll`、`Loader_4.1.33.6009.dll` - 发送消息模板:`requestdata/*.json` - 接收事件模板:`eventdata/*.json` ### 2.2 已有关键能力 现有项目已经支持: - 启动/注入企业微信:`type=10000` - 发送文本消息:`requestdata/sendVWorkTextMessage.json` - 群 @ 消息:`requestdata/sendVWorkGroupAtMessage.json` - 获取群列表:`requestdata/getVWorkGroupList.json` - 获取内部好友列表:`requestdata/getVWorkInternalFriendList.json` - 获取外部联系人列表:`requestdata/getVWorkExternalFriendList.json` - 接收企业微信消息回调:`helper.go` 中的 `MyRecvCallback` - 事件转换:`TransformData` 使用 `eventdata/.json` - 本地 HTTP 管理页面:`http://localhost:10001/` - 操作日志和前端配置管理 ### 2.3 最适合接入的位置 自动客服的核心入口建议放在: ```text helper/helper.go MyRecvCallback(...) ``` 原因: - 这里能拿到所有企业微信入站事件。 - 当前已经在这里做了消息解析、时间过滤、ResponseChannel 判断、回调转发。 - 自动客服需要的是“被动监听消息”,不是主动请求响应,所以这里最自然。 - 可保持现有 `/api/send-wxwork-data`、`/api/third-party-request` 和 callback 功能不被破坏。 ## 3. 总体架构设计 ### 3.1 新增模块 建议新增以下模块: ```text config/ types.go # 增加 AutoReplyConfig 配置结构 helper/ auto_reply.go # 自动客服主流程 auto_reply_ai.go # AI 调用适配 auto_reply_knowledge.go # 本地知识库解析、索引、检索 auto_reply_handoff.go # 转人工通知 auto_reply_status.go # 状态统计、运行记录 auto_reply_http.go # helper 侧自动客服 HTTP 接口 frontend/src/ components/AutoReply.vue # 自动客服配置和状态页面 ``` 如果希望少建文件,也可以把 helper 侧先合并为 2 到 3 个文件,但不建议全部塞进 `helper.go`,否则后续维护会变得很吃力。 ### 3.2 消息处理链路 整体链路如下: ```text 企业微信收到消息 ↓ DLL Socket 回调 ↓ helper.go / MyRecvCallback ↓ 解析原始 JSON ↓ 判断是否是主动请求响应 ↓ 如果是响应:继续走现有 ResponseChannel ↓ 如果是独立入站消息:进入自动客服判断 ↓ 转换 eventdata 结构 ↓ 判断是否需要处理 ↓ 知识库检索 ↓ AI 生成回复 ↓ 发送企业微信文本消息 ↓ 失败或无法回答时私信指定同事 ``` ### 3.3 不破坏现有功能的原则 自动客服必须做到: - 不影响当前前端“启动企微”。 - 不影响现有 requestdata 模板调用。 - 不影响第三方 callback。 - 不影响本地 dashboard。 - 不影响主动请求等待回调的逻辑。 - 自动客服出错不能导致 `helper.exe` 崩溃。 - 自动客服处理必须异步,不阻塞 `MyRecvCallback`。 ## 4. 配置设计 ### 4.1 在 config 中新增 autoReplyConfig 建议在 `config/types.go` 中新增: ```go type AutoReplyConfig struct { Enabled bool `json:"enabled"` Listen ListenConfig `json:"listen"` Knowledge KnowledgeConfig `json:"knowledge"` AI AIConfig `json:"ai"` Handoff HandoffConfig `json:"handoff"` ReplyPolicy ReplyPolicyConfig `json:"replyPolicy"` } type ListenConfig struct { EnablePrivateChat bool `json:"enablePrivateChat"` EnableGroupChat bool `json:"enableGroupChat"` GroupTriggerMode string `json:"groupTriggerMode"` IgnoreSelfMessage bool `json:"ignoreSelfMessage"` DeduplicateSeconds int `json:"deduplicateSeconds"` } type KnowledgeConfig struct { Directory string `json:"directory"` IndexPath string `json:"indexPath"` SupportedExtensions []string `json:"supportedExtensions"` TopK int `json:"topK"` MinScore float64 `json:"minScore"` AutoRebuildOnStart bool `json:"autoRebuildOnStart"` } type AIConfig struct { Provider string `json:"provider"` BaseURL string `json:"baseUrl"` APIKey string `json:"apiKey"` Model string `json:"model"` TimeoutSeconds int `json:"timeoutSeconds"` Temperature float64 `json:"temperature"` MaxTokens int `json:"maxTokens"` } type HandoffConfig struct { HumanUserID string `json:"humanUserId"` HumanConversationID string `json:"humanConversationId"` MessageTemplate string `json:"messageTemplate"` IncludeKnowledgeHits bool `json:"includeKnowledgeHits"` } type ReplyPolicyConfig struct { UnknownAnswerToken string `json:"unknownAnswerToken"` MaxQuestionLength int `json:"maxQuestionLength"` CooldownSeconds int `json:"cooldownSeconds"` } ``` 并把它挂到现有配置: ```go type Config struct { CallbackConfig CallbackConfig `json:"callbackConfig"` AutoReplyConfig AutoReplyConfig `json:"autoReplyConfig"` LastUpdated int64 `json:"lastUpdated"` } ``` ### 4.2 默认配置 默认值建议: ```json { "autoReplyConfig": { "enabled": false, "listen": { "enablePrivateChat": true, "enableGroupChat": true, "groupTriggerMode": "mention_only", "ignoreSelfMessage": true, "deduplicateSeconds": 300 }, "knowledge": { "directory": "config/knowledge", "indexPath": "config/knowledge/index.json", "supportedExtensions": [".md", ".txt", ".csv", ".xlsx", ".docx", ".pdf"], "topK": 5, "minScore": 0.35, "autoRebuildOnStart": false }, "ai": { "provider": "openai_compatible", "baseUrl": "", "apiKey": "", "model": "", "timeoutSeconds": 25, "temperature": 0.2, "maxTokens": 800 }, "handoff": { "humanUserId": "", "humanConversationId": "", "messageTemplate": "客户问题需要人工处理:\n客户:{{customerName}}\n问题:{{question}}\n来源:{{source}}\n会话:{{conversationId}}\n原因:{{reason}}", "includeKnowledgeHits": true }, "replyPolicy": { "unknownAnswerToken": "NO_ANSWER", "maxQuestionLength": 1000, "cooldownSeconds": 3 } } } ``` ## 5. 前端改造方案 ### 5.1 新增菜单 在 `frontend/src/App.vue` 左侧菜单新增: ```text 自动客服 ``` 建议位置: ```text 系统首页 企微账号 自动客服 操作记录 回调配置 ``` ### 5.2 新增 AutoReply.vue 页面 页面模块建议分为 6 块: 1. 运行状态 2. 一键开启/关闭 3. AI 配置 4. 知识库配置 5. 人工接管配置 6. 最近处理记录 ### 5.3 运行状态区 显示: - 自动客服状态:未开启 / 运行中 / 错误 - helper 连接状态 - 当前活跃企微账号数 - 知识库文件数 - 知识库切片数 - 今日处理消息数 - 今日自动回复数 - 今日转人工数 - 今日 AI 失败数 - 今日忽略消息数 ### 5.4 一键开启按钮 按钮行为: ```text 点击“一键开启自动客服” ↓ 保存当前自动客服配置 ↓ 调用启动企微 type=10000 ↓ 通知 helper reload 配置 ↓ 如果知识库索引不存在,提示并重建索引 ↓ 自动客服状态变为运行中 ``` 对应 Wails 方法: ```go SetAutoReplyEnabled(true) ``` ### 5.5 AI 配置区 字段: - AI 类型: - OpenAI 兼容接口 - 本地模型接口 - Base URL - API Key - Model - Timeout - Temperature - Max Tokens - 测试连接按钮 OpenAI 兼容接口示例: ```text https://api.openai.com/v1 https://api.deepseek.com/v1 http://localhost:1234/v1 ``` 本地模型接口示例: ```text http://localhost:11434 ``` ### 5.6 知识库配置区 字段: - 本地知识库目录 - 支持格式展示:md、txt、csv、xlsx、docx、pdf - TopK - 最低匹配分数 - 重建知识库索引按钮 - 上次索引时间 - 索引结果 ### 5.7 人工接管配置区 字段: - 指定同事 user_id - 指定同事 conversation_id - 转人工消息模板 - 是否附带知识库命中片段 - 测试发送按钮 说明: - 最稳妥方式是配置 `humanConversationId`。 - 如果只配置 `humanUserId`,后端按 `S:_` 推导 conversationId。 - 页面必须提供“测试发送”,确认能私信到指定同事。 ## 6. Wails 后端接口方案 在 `app.go` 中新增方法: ```go func (a *App) GetAutoReplyConfig() interface{} func (a *App) SaveAutoReplyConfig(jsonData string) (bool, string) func (a *App) SetAutoReplyEnabled(enabled bool) (bool, string) func (a *App) GetAutoReplyStatus() interface{} func (a *App) RebuildKnowledgeIndex() interface{} func (a *App) TestAIConnection() interface{} func (a *App) TestHumanHandoff() interface{} ``` 这些方法主要负责: - 读写 `config/config.json` - 转发请求到 `helper.exe` - 返回统一格式给前端 统一返回格式建议: ```json { "success": true, "message": "ok", "data": {} } ``` 失败时: ```json { "success": false, "message": "错误原因", "data": null } ``` ## 7. helper HTTP 接口方案 在 helper 本地 HTTP 服务中新增: ```text GET /api/auto-reply/status POST /api/auto-reply/reload POST /api/auto-reply/rebuild-knowledge POST /api/auto-reply/test-ai POST /api/auto-reply/test-handoff ``` ### 7.1 GET /api/auto-reply/status 返回: ```json { "success": true, "data": { "enabled": true, "running": true, "lastError": "", "knowledgeFileCount": 10, "knowledgeChunkCount": 320, "todayReceived": 100, "todayReplied": 60, "todayHandoff": 12, "todayIgnored": 28, "lastMessages": [] } } ``` ### 7.2 POST /api/auto-reply/reload 用途: - 重新加载 `config/config.json` - 重新初始化自动客服配置 - 不重启 helper ### 7.3 POST /api/auto-reply/rebuild-knowledge 用途: - 扫描本地知识库目录 - 解析文档 - 构建索引 - 写入 `config/knowledge/index.json` ### 7.4 POST /api/auto-reply/test-ai 用途: - 使用当前 AI 配置发起一次测试请求 - 不进入企业微信消息流程 ### 7.5 POST /api/auto-reply/test-handoff 用途: - 给指定同事发送一条测试私信 - 验证 `humanConversationId` 或 `humanUserId` 是否正确 ## 8. 自动客服消息判断规则 ### 8.1 只处理文本消息 当前文本消息模板主要是: ```text eventdata/11041.json event = 20002 ``` 自动客服初版只处理: ```json { "event": "20002", "data": { "message": "...", "conversationId": "...", "fromWxId": "...", "toWxId": "...", "fromNickName": "...", "atWxIdList": [] } } ``` 非文本消息处理策略: - 图片:转人工 - 文件:转人工 - 语音:转人工 - 视频:转人工 - 位置:转人工 - 链接:转人工 - 名片:转人工 ### 8.2 私聊处理规则 私聊消息满足: - 不是群聊 conversationId - 不是机器人自己发出的消息 - 文本内容不为空 - 没有重复处理过 则自动处理。 ### 8.3 群聊处理规则 群聊消息必须满足: - 是群聊 conversationId - 文本消息 - 不是机器人自己发出的消息 - `atWxIdList` 包含当前机器人 ID,或文本内容包含 @ 当前机器人昵称 - 未重复处理 未 @ 机器人时: - 不回复 - 计入 ignored - dashboard 可记录原因:`group message without mention` ### 8.4 自己消息过滤 如果满足以下任一条件,忽略: - `fromWxId == robotId` - `fromWxId == 当前登录企微 user_id` - 原始消息标记为自己发送 - `sender == receiver` 且能确认是本机消息 ### 8.5 去重策略 使用以下字段生成去重 key: ```text robotId + conversationId + serverId ``` 如果没有 `serverId`: ```text robotId + conversationId + localId + sendTime + fromWxId ``` 默认 300 秒内重复消息不处理。 ## 9. 知识库方案 ### 9.1 本地目录 默认目录: ```text config/knowledge/ ``` 建议结构: ```text config/knowledge/ faq.md product.md price.xlsx after-sales.docx policy.pdf index.json ``` ### 9.2 支持格式 用户选择“全都支持”,因此初版支持: - `.md` - `.txt` - `.csv` - `.xlsx` - `.docx` - `.pdf` ### 9.3 解析策略 不同文件策略: - Markdown/TXT:按标题和段落切分。 - CSV:按行切分,每行拼接字段名和值。 - Excel:按 sheet + 行切分。 - DOCX:提取段落文本后切分。 - PDF:提取页面文本后切分。 每个 chunk 建议结构: ```json { "id": "hash", "source": "faq.md", "title": "售后政策", "content": "具体内容", "line": 12, "page": 0, "updatedAt": 1710000000, "hash": "..." } ``` ### 9.4 检索策略 初版不引入向量库,使用本地关键词 / BM25 风格检索: - 中文分词可先用 rune bigram + keyword 简化实现。 - 英文按空格和标点切词。 - 计算 query 和 chunk 的相关度。 - 返回 topK。 - 最高分低于 `minScore` 时认为知识库无法回答。 默认: ```text topK = 5 minScore = 0.35 ``` ### 9.5 后续增强方向 后续可以升级为: - 本地 embedding - OpenAI embedding - SQLite FTS5 - 向量数据库 - 混合检索 但初版不建议一开始引入复杂依赖,先把闭环跑通。 ## 10. AI 调用方案 ### 10.1 OpenAI 兼容接口 请求: ```text POST {baseUrl}/chat/completions Authorization: Bearer {apiKey} ``` 如果用户填写的 `baseUrl` 是: ```text https://api.openai.com/v1 ``` 则最终请求: ```text https://api.openai.com/v1/chat/completions ``` 请求体: ```json { "model": "gpt-4.1-mini", "temperature": 0.2, "max_tokens": 800, "messages": [ { "role": "system", "content": "你是企业微信客服助手,只能基于知识库回答。知识库没有答案时输出 NO_ANSWER。" }, { "role": "user", "content": "客户问题 + 知识库片段" } ] } ``` ### 10.2 本地模型接口 默认适配 Ollama: ```text POST {baseUrl}/api/chat ``` 请求体: ```json { "model": "qwen2.5", "stream": false, "messages": [ { "role": "system", "content": "你是企业微信客服助手,只能基于知识库回答。知识库没有答案时输出 NO_ANSWER。" }, { "role": "user", "content": "客户问题 + 知识库片段" } ] } ``` 如果本地模型提供 OpenAI-compatible 接口,则用户直接选择 OpenAI 兼容模式即可。 ### 10.3 Prompt 约束 系统提示词建议: ```text 你是企业微信客服助手。 你只能根据提供的知识库片段回答客户问题。 如果知识库片段不能支持答案,必须只输出 NO_ANSWER。 不要编造政策、价格、承诺、库存、物流时效。 回答要简洁、礼貌、像真人客服。 如果客户要求人工、投诉、退款、合同、发票、价格特殊审批,也输出 NO_ANSWER。 ``` 用户消息格式: ```text 客户昵称:{{fromNickName}} 客户问题:{{question}} 知识库片段: [1] {{chunk1}} [2] {{chunk2}} [3] {{chunk3}} 请基于知识库回答。 ``` ### 10.4 AI 无法回答判定 以下情况触发转人工: - 知识库最高分低于阈值。 - AI 返回 `NO_ANSWER`。 - AI 返回空字符串。 - AI HTTP 调用失败。 - AI 超时。 - AI 返回结构无法解析。 - 消息是非文本。 - 客户明确要求人工客服。 - 客户问题超过最大长度。 - 命中敏感业务关键词,例如退款、投诉、合同、发票、赔偿等。 ## 11. 自动回复发送方案 ### 11.1 私聊回复 使用已有模板: ```text requestdata/sendVWorkTextMessage.json ``` 转换后的底层 type: ```json { "type": 11029, "data": { "conversation_id": "{{conversationId}}", "content": "{{answer}}" } } ``` 调用方式: ```go sendTextToConversation(clientId, conversationId, answer) ``` ### 11.2 群聊回复 群聊 @ 机器人后,默认回复到原群: ```text conversationId = 原消息 conversationId ``` 可选策略: - 默认不 @ 提问人,只回复文本。 - 后续可以增加 `replyWithAtSender` 开关,使用 `sendVWorkGroupAtMessage`。 初版建议默认不 @,避免 atList 字段兼容问题带来发送失败。 ## 12. 转人工私信方案 ### 12.1 私信对象配置 用户要求: ```text 直接发私信给指定同事的企业微信 ``` 因此配置: ```json { "humanUserId": "指定同事user_id", "humanConversationId": "指定同事私聊conversation_id" } ``` 优先级: 1. 如果配置了 `humanConversationId`,直接使用。 2. 如果没有配置,则使用 `S:_` 推导。 3. 如果推导失败或发送失败,记录错误并在前端状态展示。 ### 12.2 转人工消息内容 默认模板: ```text 客户问题需要人工处理 客户:{{customerName}} 客户ID:{{fromWxId}} 来源:{{source}} 会话ID:{{conversationId}} 问题:{{question}} 原因:{{reason}} 时间:{{time}} 请及时处理。 ``` 如果开启 `includeKnowledgeHits`,追加: ```text 知识库候选: 1. {{source}} / score={{score}} 2. {{source}} / score={{score}} ``` ### 12.3 转人工触发原因枚举 建议原因: ```text knowledge_low_score ai_no_answer ai_timeout ai_http_error ai_parse_error non_text_message manual_keyword send_reply_failed config_missing ``` 前端展示时转成中文。 ## 13. 状态统计和运行记录 新增内存状态对象: ```go type AutoReplyStatus struct { Enabled bool Running bool LastError string KnowledgeFileCount int KnowledgeChunkCount int KnowledgeLastIndexedAt int64 TodayReceived int TodayReplied int TodayHandoff int TodayIgnored int TodayAIFailed int LastMessages []AutoReplyRecord } ``` 运行记录: ```go type AutoReplyRecord struct { ID int64 Time string RobotID string ConversationID string Source string FromWxID string FromNickName string Question string Action string Reason string Answer string } ``` `Action` 可选: ```text ignored replied handoff failed ``` ## 14. 错误处理策略 ### 14.1 自动客服不能影响主流程 自动客服所有处理都必须: - `recover` panic - 写日志 - 更新状态 - 不向外抛出导致 `MyRecvCallback` 异常 ### 14.2 AI 超时 默认: ```text 25 秒 ``` 超时后: - 不继续等待。 - 转人工。 - 状态计入 `TodayAIFailed` 和 `TodayHandoff`。 ### 14.3 发送失败 自动回复发送失败时: - 记录失败。 - 转人工通知。 - 如果转人工也失败,写入 `LastError`。 ### 14.4 知识库索引失败 单个文件失败: - 不影响其他文件。 - 在前端显示失败文件。 - 写入日志。 全部失败: - 自动客服仍可开启。 - 所有问题都会因为知识库低分而转人工。 ## 15. 实施步骤 ### 阶段一:配置和接口骨架 1. 扩展 `config/types.go`,加入自动客服配置结构。 2. 修改默认配置生成逻辑。 3. 在 `app.go` 增加 Wails 方法: - `GetAutoReplyConfig` - `SaveAutoReplyConfig` - `SetAutoReplyEnabled` - `GetAutoReplyStatus` 4. 在 helper HTTP server 增加自动客服路由。 5. 确认现有编译不受影响。 ### 阶段二:前端自动客服页面 1. 新增 `frontend/src/components/AutoReply.vue`。 2. 修改 `App.vue` 侧边栏,增加“自动客服”菜单。 3. 实现配置读取、保存、开关、状态刷新。 4. 实现测试 AI、测试人工私信、重建知识库按钮。 5. 保持当前 UI 风格,不做大规模视觉重构。 ### 阶段三:知识库模块 1. 创建 `helper/auto_reply_knowledge.go`。 2. 实现本地目录扫描。 3. 实现 `.md/.txt/.csv` 解析。 4. 实现 `.xlsx/.docx/.pdf` 解析。 5. 实现 chunk 切分。 6. 实现索引保存和加载。 7. 实现关键词/BM25 风格检索。 8. 将统计信息暴露给状态接口。 ### 阶段四:AI 模块 1. 创建 `helper/auto_reply_ai.go`。 2. 实现 OpenAI-compatible 调用。 3. 实现 Ollama 本地模型调用。 4. 实现 prompt 构造。 5. 实现 `NO_ANSWER` 判断。 6. 实现 AI 测试接口。 ### 阶段五:消息监听和自动回复 1. 创建 `helper/auto_reply.go`。 2. 在 `MyRecvCallback` 中接入自动客服入口。 3. 确保 ResponseChannel 响应不触发自动客服。 4. 实现文本消息过滤。 5. 实现私聊自动处理。 6. 实现群聊 @ 机器人处理。 7. 实现去重。 8. 实现调用知识库 + AI + 发送回复。 ### 阶段六:转人工私信 1. 创建 `helper/auto_reply_handoff.go`。 2. 实现转人工消息模板渲染。 3. 实现指定同事私信发送。 4. 实现测试发送。 5. 自动回复失败时触发转人工。 ### 阶段七:测试和验证 1. 增加 Go 单元测试。 2. 增加 mock AI server 测试。 3. 前端执行 `npm run build`。 4. Go 执行 `go test ./...`。 5. 构建 helper。 6. 构建 Wails。 7. 实机验证私聊、群聊 @、群聊未 @、转人工。 ## 16. 测试用例 ### 16.1 私聊文本自动回复 输入: ```json { "event": "20002", "data": { "conversationId": "S:customer_robot", "fromWxId": "customer", "toWxId": "robot", "message": "你们营业时间是几点?" } } ``` 预期: - 检索知识库。 - 调用 AI。 - 发送回复到原 conversationId。 - 状态 `TodayReplied +1`。 ### 16.2 群聊未 @ 不回复 输入: ```json { "event": "20002", "data": { "conversationId": "R:group", "fromWxId": "customer", "message": "你们营业时间是几点?", "atWxIdList": [] } } ``` 预期: - 不调用 AI。 - 不发送消息。 - 状态 `TodayIgnored +1`。 ### 16.3 群聊 @ 机器人自动回复 输入: ```json { "event": "20002", "data": { "conversationId": "R:group", "fromWxId": "customer", "message": "@机器人 你们营业时间是几点?", "atWxIdList": ["robot"] } } ``` 预期: - 调用知识库。 - 调用 AI。 - 回复到原群。 ### 16.4 知识库无答案转人工 输入: ```text 你们能不能帮我办理完全无关的问题? ``` 预期: - 检索低分。 - 不调用或不采纳 AI。 - 私信指定同事。 - 状态 `TodayHandoff +1`。 ### 16.5 AI 返回 NO_ANSWER 转人工 AI 输出: ```text NO_ANSWER ``` 预期: - 不回复客户。 - 私信指定同事。 - 状态 `TodayAIFailed +1`、`TodayHandoff +1`。 ### 16.6 AI 超时转人工 预期: - 超过 timeout 后触发转人工。 - 不阻塞后续消息处理。 ### 16.7 重复消息不重复回复 同一个 `serverId` 连续进入两次。 预期: - 第一次处理。 - 第二次忽略。 ## 17. 验收标准 完成后应满足: - 前端有“自动客服”页面。 - 能一键开启/关闭自动客服。 - 能配置 AI 接口。 - 能配置本地知识库目录。 - 能重建知识库索引。 - 能测试 AI 连接。 - 能配置指定人工同事并测试私信。 - 私聊客户文本消息能自动回复。 - 群聊只有 @ 机器人时才自动回复。 - 未 @ 的群消息不会回复。 - AI 无法回答时能私信指定同事。 - 自动客服处理失败不影响现有企业微信管理能力。 - 原有 `http://localhost:10001/` dashboard 和 requestdata 接口保持可用。 ## 18. 风险点和注意事项 ### 18.1 conversationId 推导风险 私信指定同事最好配置明确的 `humanConversationId`。 如果只配置 `humanUserId`,按 `S:_` 推导可能因企业微信内部规则不同而失败,因此必须提供“测试发送”。 ### 18.2 群聊 @ 判断风险 有些事件可能 `atWxIdList` 不完整,因此群聊触发判断应同时支持: - `atWxIdList` 包含机器人 ID - 文本内容包含 `@机器人昵称` ### 18.3 AI 胡答风险 必须强制 AI 只基于知识库回答。 如果知识库没有答案,AI 必须输出 `NO_ANSWER`。 ### 18.4 文件解析依赖风险 `.xlsx/.docx/.pdf` 支持会引入新依赖或额外解析逻辑。 如果希望第一版更稳,可以先实现 `.md/.txt/.csv`,但本需求要求“全都支持”,因此计划里按全格式支持实现。 ### 18.5 不阻塞 DLL 回调 AI 调用和知识库检索都不能直接阻塞 `MyRecvCallback`。 应通过 goroutine + 队列处理。 ## 19. 建议的默认上线策略 第一版建议: - 先只开启私聊自动回复。 - 群聊只开 @ 机器人触发。 - 最低知识库分数先设置偏高,例如 `0.4`。 - AI 无答案严格转人工。 - 所有转人工消息都附带原始 conversationId 和客户 ID。 - 开启详细日志,方便回放和排查。 ## 20. 后续增强方向 后续可以继续增加: - 多机器人分别配置知识库。 - 不同群使用不同知识库。 - 客户画像和历史上下文。 - 工单系统对接。 - 向量检索。 - 对话记忆。 - 人工接管后暂停自动回复。 - 黑名单/白名单群配置。 - 敏感词和合规审核。 - 前端消息实时流展示。