# kb-embodied-agent **Repository Path**: lvhaiyan/kb-embodied-agent ## Basic Information - **Project Name**: kb-embodied-agent - **Description**: 企业知识库具身客服:数字人员工 + 企业私有知识库 RAG + MCP 工具调用 + GB/T 47746—2026 合规自查与红队回归(上海开源软件应用创新大赛参赛作品,Apache-2.0) - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2026-09-22 - **Last Updated**: 2026-09-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # KB-Embodied-Agent · 企业知识库具身客服 > 2026 上海开源软件应用创新大赛 ·「开源 AI 工具赛道」· 魔珐科技企业命题参赛作品 > 命题:《让 AI「活」起来:基于魔珐星云具身交互智能的创新应用》 把**企业自己的知识库**变成一个可以在屏幕前面**面对面问答**的数字员工:有形象、能表达、 有大脑、会办事——客户不用打字,直接开口问;答不上来时它会**调工具办事**并把结果**当场显示成卡片**。 --- ## 1. 背景与痛点(为什么做这个) 小微企业的知识(产品手册、售后 SOP、补贴政策口径、报价规则)散落在微信文件、Excel、老员工脑子里。 现有"AI 客服"的形态是**网页对话框**: - 门店顾客、到店的中老年客户**不愿意在屏幕上打字**,也看不清密密麻麻的文字; - 纯语音方案"只闻其声",客户不知道它在说哪一个商品、哪一条政策,**无法"边讲边指"**; - 复杂问题需要**办事**(生成自查清单、算出报价),对话框只能给一段文字,客户还得自己去填、去算。 本作品把知识库问答从"文本框"升级为**具身交互**:数字人开口讲、有表情有动作、被打断能接住, 并能在对话中**调用工具**(MCP)把结果渲染成可读卡片。 ## 2. 技术方案(三层覆盖) | 命题自由度 | 本作品实现 | |---|---| | **表达层**(必须覆盖) | 魔珐星云 SDK(XmovAvatar)3D 形象 + TTS/SSML 播报 + 字幕 + 语音状态驱动口型/表情/关键动作 | | **交互层** | 自研 Agent 编排:企业知识库 RAG(仅答企业私有语料)+ DeepSeek 大模型 + 多轮上下文 + 聆听/思考/说话状态可视化 + **打断**(Listen/Think/Speak/Interrupt 与对话有机结合) | | **行动层** | **MCP 工具调用**(自研 MCP Server,非伪函数)+ Widget 实时呈现执行结果(合规自查清单 / 报价卡 / 转人工) | 关键设计:SDK 侧关闭 `auto_send_asr_to_llm`,**由我方 Agent 层接管"听→想→做→说"全链路**, 这样才能在回答前后插入 RAG 检索与工具调用(SDK 不提供 Function Calling,见 `docs/风险与边界.md`)。 详见 [`ARCHITECTURE.md`](ARCHITECTURE.md)。 ## 3. 目录结构 ``` backend/ Python(FastAPI) Agent 服务:会话签发、RAG、LLM、MCP 工具调用 web/ 前端:魔珐星云 SDK 接入 + 字幕/状态/Widget 渲染 deploy/ Docker Compose 一键部署所需脚本与说明 docs/ 参赛材料(介绍文档大纲、不可替代性论证、风险与边界) ``` ## 4. 快速开始(Docker Compose) > **在线体验环境的地址不公开**:我们另设了在线实时体验环境(数字人对话,无需登录),但该地址 > 仅按需提供给评审等特定对象,不在仓库、文档或任何公开渠道公示——体验环境占用的是有额度限制的 > 商用数字人资源,公开后会因围观迅速耗尽。**想体验请直接按下方步骤本地跑**:`docker compose up -d` > 后浏览器打开 8080;无密钥时用离线演示模式亦可复现交互与卡片渲染流程。 ```bash cp .env.example .env # 填入自己的密钥(切勿提交 .env) docker compose up --build # 浏览器打开 http://localhost:8080 ``` 无密钥时(评委快速体验):以 `DEMO_MODE=offline` 启动,前端进入**离线演示模式**, 用预置对话脚本展示界面与交互流程,不消耗任何积分。 ### 不用 Docker 的本地快速验证(开发用) ```bash # 1) 起后端(离线演示模式) cd backend && DEMO_MODE=offline KB_PATH=../kb python -m uvicorn app.main:app --port 8011 # 2) 另开一个终端:起前端静态页 + /api 反向代理 python scripts/dev_server.py --port 8080 --backend http://127.0.0.1:8011 # 3) 浏览器打开 http://127.0.0.1:8080 ``` 页面上的快捷问题按钮可依次触发四类行动层能力:知识检索、**合规自查清单卡**、 **报价卡**、**转人工卡**(`/api/chat` 返回 `widgets` 数组,前端按类型渲染)。 ### 体检与信任层(核心差异点:不只是"会说话的数字人") | 能力 | 端点 | 说明 | | --- | --- | --- | | 国标体检 | `POST /api/selfcheck` | 按 GB/T 47746—2026 逐项对表(61 项 = 48「应」+4「宜」+9「可」,含 5 项一票项),输出**达标判定 + 待整改清单**,可一键导出 Markdown | | 知识库体检 | `POST /api/kb-audit` | 用 12 条探针问题跑检索,输出**覆盖率**与**语料缺口清单**(未覆盖问题 = 补料待办) | | 操作留痕 | `GET /api/audit` | 每次问答/工具调用落盘 `logs/audit.jsonl` 并可回查——"出事了能说清" | | 一键停 | `POST /api/kill` | 停用后 AI 不再作答,所有请求直接转人工,可随时恢复 | | 可审计引用 | `/api/chat` 返回 `evidences` | 回答逐条给出依据原文,前端「📎 查看依据原文」可折叠展开 | ### 具身交互(表达层 / 交互层纵深) | 能力 | 实现 | 触发 | | --- | --- | --- | | 流式分段播报 | 按标点切分(单段 ≤60 字),逐段 `speak(ssml, is_start, is_end)` | 每次回答自动 | | 情绪表情 + 语调 | `speak(ssml, true, true, { emotion })`,按回答语义匹配(不达标→严肃、出卡片→开心、转人工→歉疚) | 每次回答自动 | | 关键动作(KA) | SSML `ka_intent…` 注入(抓重点 KeyPoints / 指屏幕 Pointscreen / 问候 Hello / 致歉 Apologize) | 每次回答自动 | | 语音输入(ASR) | `startASR()` / `stopASR()`,`features.auto_send_asr_to_llm=false` —— **识别文本交回我方 Agent**(RAG + 工具),不经过平台大脑;识别中间结果实时上屏,说完自动关麦(避免把数字人自己的声音再收进去) | 「🎤 语音输入」按钮 | | 语音对话模式 | 进入**全屏**即自动开启聆听,数字人答完自动回听,形成「你说 → 它答 → 你再说」的轮次对话;退出全屏自动关麦。适老化模式下同样自动进入语音优先 | 「⛶ 全屏」按钮 / 「👵 适老化」按钮 | | 客户端打断 | `interrupt('user_click')` 立即打断播报并回到聆听姿态 | 「✋ 打断」按钮 | | 具身状态协同 | SDK 状态机(running / speaking / listening)与本页 Listen / Think / Speak 三态及字幕联动 | 自动 | > 这些能力依赖星云实时会话(数字人开放时);文字 + 卡片版下按钮会给出明确引导而不是报错。 ### 密钥边界(实测结论:密钥永不出服务器) 星云 SDK 文档写明 `appSecret` 是"浏览器侧签名凭证",但**直接下发到前端在公网等于裸奔**。 本作品采用**自建网关代理**解决:浏览器把 SDK 的 `gatewayServer` 指向 `/api/xmov/gateway`, 由服务端完成签名(`md5(path + method + 紧凑JSON + appSecret + 时间戳)`)后转发给星云统一会话接口。 - 实测结果:`/api/session` 只下发 `gateway_proxy` 一个字段,**零密钥、零 token**; 浏览器侧 SDK 使用占位凭证(`appId/appSecret = "via-server-proxy"`),真实密钥只存在于服务端 `.env`; - 该路径已实机跑通:数字人渲染 + 问答 + 播报 + 卡片 + 依据溯源全链路正常; - 平台会话号由代理端回填到服务端槽位,因此"管理侧强制释放 / 心跳掉线释放"同样可用。 ### 部署与容量设计(B 方案:半开放) 数字人实时驱动**默认关闭**(`/api/admin/avatar` 后台开关控制);无论开或关, 访客始终能用**文字 + 卡片版**(零密钥、零积分、可并发)。开放时采用串行策略: | 机制 | 默认值 | 作用 | | --- | --- | --- | | 网关代理 | 强制 | SDK 的 `gatewayServer` 指向 `/api/xmov/gateway`,签名在服务端完成,浏览器零密钥 | | 单场限时 | 180 秒 | 到点自动结束并释放名额(实测约 0.5 积分/分钟 → 单场约 1.5 积分) | | 同时在线 | 1 人 | 账号侧驱动并发为 1(实测),占用时第二位访客自动降级为文字版并给出等待时间 | | 每日场次 / 积分上限 | 30 场 / 60 积分 | 防止公网被白嫖,触顶自动降级 | | 单 IP 每日场次 | 2 场 | 防止一人刷满 | | 管理侧强制释放 | `/api/admin/release` | 房间被占死时一键结束平台会话(走网关 DELETE) | | 一键停 | `/api/kill` | 出事立即全站停止 AI 作答并转人工 | **降级是设计的一部分**:任何一环失败(开关关闭、名额占用、网关不可达、字段未识别), 访客都会拿到文字 + 卡片版并看到真实原因,而不是白屏或报错。 **判定口径(诚实说明)**:达标判定规则(「应」项全满足=达标;「应」项未满足 ≤3 且不涉一票项=基本达标; 「应」项未满足 ≥4 或任一票项未满足=不达标)是**本项目依据标准条文的工程化口径,不是标准原文规定**, 可用于内部自查与整改排序,不构成合规结论。标准逐项数据见 `kb/standards/gbt47746-checklist.json`(可整体替换)。 ## 5. 密钥边界(诚实说明) 星云 SDK 的 `appSecret` 是**浏览器侧签名凭证**(厂商文档明示,前端必须持有才能建立实时会话)。 本项目的做法是把风险压到最小,而不是宣称"前端零密钥": - 仓库内**不含任何密钥**(`.env` 被 `.gitignore` 忽略,只提交 `.env.example`);CI 会扫描并拒绝疑似密钥。 - 密钥只存在于**服务端** `.env`,由 `/api/session` 在建会话时下发;会话有 TTL(默认 900s)。 - 生产环境的更高安全等级做法(本项目已预留、未实现):向星云后端换取**一次性 token**, 再下发给浏览器,避免长期凭证出现在前端。 - 前端**不内置**任何硬编码密钥;若 SDK 加载失败或未配置,自动回退离线表现,不影响演示。 | 变量 | 说明 | |---|---| | `XMOV_APP_ID` / `XMOV_APP_SECRET` | 魔珐星云应用凭证(控制台创建应用后获取,只在服务端) | | `XMOV_GATEWAY` | 公共网关固定值 `…/user/v1/ttsa_v2/session`(私有化部署才需改) | | `XMOV_SDK_URL` | 端到端版 SDK 地址(默认官方 CDN;留空则前端不加载,走离线表现) | | `LLM_BASE_URL` / `LLM_API_KEY` / `LLM_MODEL` | 大模型(OpenAI 兼容端点,默认 DeepSeek) | | `KB_PATH` | 企业知识库语料目录(默认 `./kb`,仓库内只放**示例语料**) | | `MCP_SERVER_URL` | 自研 MCP 工具服务地址 | | `DEMO_MODE` | `online` / `offline`(离线不消耗积分,供演示与评审体验) | ## 7. 评审维度对照(逐条给证据,不做形容词) > 对应大赛《评审维度》四个部分,每条指标都给出**仓库内可核验的实现**或**实测证据**。 ### 7.1 产品完成度与可用性(25%) | 细则 | 本作品实现 | 怎么验证 | | --- | --- | --- | | 功能完整性:端到端流程顺畅 | 对话/驱动发起 → 检索 → 生成 → 工具/卡片 → 语音播报 → 状态回落,全链路打通 | 打开 `http://localhost:8080` 直接对话;`docker compose logs -f backend` 可看每轮链路 | | 稳定性与容错:打断 | 客户端 `interrupt('user_click')` 立即停止播报与动作 | 演示页「✋ 打断」按钮;具身看板会记 `Interrupt` 事件 | | 稳定性与容错:断网自动降级 | 断网/弱网时数字人链路降级,**文字 + 卡片版照常可用**;SDK 内置重连(短重试 + 指数退避) | 演示页「🌐 弱网演练」按钮;`reconnect` 配置见 `web/index.html` | | 稳定性与容错:重连 | `reconnect: {enabled, maxAttempts: 6, initialDelayMs: 500, maxDelayMs: 8000}`;重连成功回到 `running` 后自动恢复能力 | 断网再恢复,看具身看板 `Reconnect` 事件 | | 部署与可复现 | **Docker Compose 一键部署**,健康检查 + 反向代理;镜像构建与容器健康已实跑 | `docker compose up -d --build` → `docker compose ps` 见 `Up (healthy)` | | 整体体验 | 数字人画面区可全屏、可横竖屏;字幕常驻;卡片/清单/工单可视化 | 演示页「⛶ 全屏」「⇄ 横屏/竖屏」 | ### 7.2 智能交互深度(25%) | 细则 | 本作品实现 | 怎么验证 | | --- | --- | --- | | 大模型理解与推理 | 接入 LLM,回答只依据检索资料;**资料不足不编造**,交上层「意图分诊」决定是据实作答、反问引导还是转人工 | `backend/app/main.py` 的 `_ask_llm()` + `_triage()` | | 记忆与个性化 | **会话级多轮上下文**(默认保留 12 轮)+ **个性化档案**(记住称呼/客户背景,不重复询问);提供 `/api/memory` 可查证 | 问「我叫×××」再问后续问题,页头「🧠 记忆 N 轮(已记住称呼:×××)」;`curl /api/memory?session_id=...` | | RAG 知识检索 | 企业知识库检索(数据驱动语料 + 国标逐项清单),回答带**来源**与**依据原文**可折叠查看 | 任意提问后展开「依据原文」 | | 具身智能协同 | Listen / Think / Speak / **emotion** / **KA 关键动作** / **interrupt 打断** 六类具身能力**与对话事件实时绑定**,页面「🎭 具身状态绑定」看板逐条打出时间戳 | 演示页具身看板;语义→情绪/动作映射见 `web/index.html` | | 行动能力延伸(Agent) | 工具调用 + MCP 通道:政策自查清单卡、报价卡、转人工工单卡;`/api/tools` 可列清单 | 演示页「可用工具(行动层)」;`curl /api/tools` | | **回答策略:不滥用转人工** | **三层路由**:① 知识库直答(关键词命中 → 语义兜底 → 参照会话记忆);② 未命中走**意图分诊**——通用概念据实作答 / 信息不足**反问引导**把客户真实需求问出来 / 闲聊得体回应并拉回业务;③ **仅 4 类转人工**(客户明确要求人工、投诉升级、法律纠纷/退款/身份核验等高风险、连续引导 2 次仍无法定位)。国标并未要求「随时转人工」,转人工是兜底不是默认动作 | 问「今天天气怎么样?」→ 得体回应 + 引导回业务,**不转人工**;连问 3 次含糊问题 → 第 3 轮才转人工 | | **解决率可自证** | `scripts/run_regression.py`:**60 条真实口语问句**(合规/知识库/交付报价/口语变体/通用概念/含糊/闲聊/高风险)逐条回归,输出**解决率**、误转人工、漏转人工、空回答数,并生成 `docs/解决率回归报告.md` | `python scripts/run_regression.py` | > 与「文本框 + 一个形象」的区别:本作品里**状态不是装饰**——`Think` 时才检索与生成、`Speak` 时逐句字幕与分段播报同步、 > 打断立即中止并保留文字、情绪与关键动作由回答语义决定、转人工时把上下文交给工单。六类能力全部可在看板上看到触发时刻。 ### 7.3 场景创意与价值(35%) | 细则 | 本作品实现 | 怎么验证 | | --- | --- | --- | | 需求真实性 | 面向小微企业知识服务/效率助手场景;痛点来自真实行业知识库落地(检索不准、答错无人担责、合规无从自证) | `docs/不可替代性论证.md` | | 不可替代性论证 | **约束性论证**(输入约束 = 口述模糊需求;认知约束 = 知识库内容必须听得懂;信任约束 = 出错要能说清),并给出「数字人 vs 纯文本/纯语音」逐项对比 | `docs/不可替代性论证.md` | | 创意新颖度 | ① **合规红队测试台**:`/audit.html` 由「红队客户」数字人按国标条款发难、AI 客服应答、自动出**可交付测试报告**(含防止「无脑转人工」的反向用例);② **可信执行者**定位:把国标 61 项/5 项一票项变成可自动回归的用例 | 打开 `/audit.html` → 「只跑一票项 5 条」→ 导出报告 | | 社会效益(普惠/无障碍/适老化) | 「👵 适老化/无障碍」一键切换:大字号 + 高对比 + 字幕常驻 + 语音优先(口述即可办事),让不会打字的老人也能办事;通用 MCP/标准接口,便于社区复用 | 演示页开关按钮 | | 商业与产业化路径 | 三步:① 单店/单企业私有化部署(本地化,按月监测);② 行业知识库 + AI 客服打包交付(小微企业为主的标准化产品);③ 把「合规体检 + 红队测试」做成独立服务(标准执行者可对外出报告) | 见下节 7.4 | ### 7.4 商业化与产业化落地路径 1. **私有化轻部署**:单机/单企业部署,知识库 + 具身客服一体交付,按月监测与内容维护计费; 2. **行业复制**:把知识库结构、国标自查清单、红队用例封装为**可替换数据包**(本仓库 `kb/` 即数据驱动),换行业只换语料与用例; 3. **合规服务化**:国标 61 项体检 + 红队测试报告本身可独立交付(面向需要自证合规的企业/集成商), 与「企业知识库 + AI 客服」形成**前端获客 + 后端承接**的组合。 ### 7.5 开源规范(15%) | 细则 | 本作品实现 | | --- | --- | | 协议合规 | Apache-2.0(`LICENSE`);第三方依赖见 `docs/dependencies.md`,均为宽松许可 | | 代码质量 | 后端按职责分层(`main.py` 服务与信任层 / `standard.py` 国标内核 / `redteam.py` 用例与判定引擎),前端纯静态无构建依赖 | | 文档标准化 | README 含背景、技术方案、部署指南、**配置项脱敏说明**(`.env.example`,密钥一律不入库);`docs/` 下有风险边界、不可替代性论证、演示脚本 | | 工程规范 | CI(`.github/workflows/ci.yml`:导入检查 + 密钥扫描);Issue / PR 模板齐备;提交按 feat/fix/docs 分类,单提交单一意图 | --- ## 6. 开源与许可 Apache-2.0(见 `LICENSE`)。第三方依赖与许可清单见 `docs/dependencies.md`; 能力边界与明确不做的清单见 `docs/风险与边界.md`。 > 本仓库不含任何真实客户数据、企业知识库原文与商业报价;示例语料均为虚构。