KB Embodied Agent v1.0.0:把企业知识库接到会说话、能办事的数字人前台

2026-09-21 28 预计阅读时间: 1 分钟
来源: oschina.net AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:11 分钟

企业知识库通常只解决“查得到”,但前台接待、内部服务台和客户支持还要求系统“说得出、办得成”。KB Embodied Agent v1.0.0 尝试把私有知识检索、对话编排、数字人交互和业务动作放进一条完整链路:用户提出问题后,系统不仅生成回答,还可以按规则调用企业服务。

这是项目的首个语义化版本,采用 Apache-2.0 协议,并提供完整可运行工程,而不是只展示若干演示片段。值得关注的是,其对话主链路由 FastAPI 服务接管,不把“听、想、做”等核心编排逻辑锁进数字人渲染 SDK。

数字人只是交互层,FastAPI 才是控制面

传统数字人项目容易围绕某个渲染 SDK 搭建全部逻辑:SDK 收到语音、调用模型、播放回答,业务状态也跟着散落在回调函数里。演示阶段这样做很快,但接入工单、预约、CRM 或身份系统后,会遇到几个现实问题:

  • 更换数字人或语音供应商时,需要重写业务流程;
  • 文本入口、网页入口和语音入口难以复用同一套会话逻辑;
  • 工具调用发生在客户端或渲染进程中,不利于鉴权与审计;
  • 知识检索、模型推理和动作执行难以分别压测、降级和追踪。

KB Embodied Agent 把交互主链路放到 FastAPI 服务中,意味着可以将整个系统拆成更清晰的几层:

语音、网页或终端
        │
        ▼
输入适配层:ASR、文本规范化、会话标识
        │
        ▼
FastAPI 编排层:意图判断、知识检索、工具决策、状态管理
        │                    │
        ▼                    ▼
私有知识库              企业业务 API
        │                    │
        └─────────┬──────────┘
                  ▼
输出适配层:文本、TTS、数字人渲染

这种结构的关键收益不是“用了 FastAPI”,而是把数字人渲染变成可替换的输入输出适配器。知识库、权限规则与业务动作仍留在服务端,网页客服、实体终端和数字人前台可以共享同一套控制面。

“能回答”和“能办事”必须分成两条路径

知识问答属于相对低风险的读取操作,而创建工单、修改预约、查询个人信息属于业务动作。两者不能只靠一段提示词混在一起处理。

一条更适合企业场景的请求链路可以这样设计:

  1. :接收语音识别结果或文本输入,并关联会话、用户与终端;
  2. :识别意图,检索用户有权访问的知识,判断是否需要调用工具;
  3. 确认:对报修、预约、修改数据等动作展示参数并请求用户确认;
  4. :通过服务端白名单调用企业 API,记录参数、结果和耗时;
  5. :将知识答案或执行结果转成自然语言,再交给 TTS 与数字人渲染。

这里的“想”不应等同于让大模型自由决定一切。生产环境至少需要工具白名单、结构化参数校验、用户权限检查和超时控制。模型可以提出调用建议,但最终执行权应由确定性的服务端代码掌握。

一个可运行的最小编排服务

下面的示例不是项目官方 API,而是根据上述架构整理出的最小实践骨架。它从已经转写好的文本开始,演示知识查询和报修动作如何共用一个 FastAPI 入口。真正接入时,需要将内存知识与模拟工单函数替换成企业检索服务和业务 API。

新建 requirements.txt

fastapi==0.115.0
uvicorn[standard]==0.30.6
pydantic==2.9.2

新建 app.py

from typing import Literal
from uuid import uuid4

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field

app = FastAPI(title="Embodied Reception Control Plane")

KNOWLEDGE = {
    "访客": "访客请携带有效证件,在一楼前台完成登记。",
    "停车": "访客车辆需要由接待人在系统中提前提交车牌号。",
    "报修": "办公设备故障可以提交报修工单,紧急故障请联系值班人员。",
}


class ReceptionRequest(BaseModel):
    session_id: str = Field(min_length=1, max_length=64)
    user_id: str = Field(min_length=1, max_length=64)
    text: str = Field(min_length=1, max_length=1000)
    confirmed: bool = False


class ReceptionResponse(BaseModel):
    mode: Literal["answer", "confirmation_required", "action_result"]
    speech: str
    action_id: str | None = None


def retrieve_answer(text: str) -> str:
    for keyword, answer in KNOWLEDGE.items():
        if keyword in text:
            return answer
    return "知识库中暂时没有匹配内容,我可以为你转接人工服务。"


def create_repair_ticket(user_id: str, description: str) -> str:
    # 实际项目中应在这里调用工单 API,并传递服务身份、幂等键和审计信息。
    if not description.strip():
        raise HTTPException(status_code=400, detail="description is required")
    return f"REP-{uuid4().hex[:8].upper()}"


@app.post("/v1/reception", response_model=ReceptionResponse)
def reception(request: ReceptionRequest) -> ReceptionResponse:
    wants_repair = "报修" in request.text or "坏了" in request.text

    if wants_repair and not request.confirmed:
        return ReceptionResponse(
            mode="confirmation_required",
            speech="我可以根据当前描述创建报修工单。确认现在提交吗?",
        )

    if wants_repair:
        ticket_id = create_repair_ticket(request.user_id, request.text)
        return ReceptionResponse(
            mode="action_result",
            speech=f"报修工单已创建,编号是 {ticket_id}。",
            action_id=ticket_id,
        )

    return ReceptionResponse(
        mode="answer",
        speech=retrieve_answer(request.text),
    )

安装并启动:

python -m venv .venv
source .venv/bin/activate
# Windows PowerShell 使用:.venv\Scripts\Activate.ps1
pip install -r requirements.txt
uvicorn app:app --host 0.0.0.0 --port 8000 --reload

测试知识问答:

curl -s http://127.0.0.1:8000/v1/reception \
  -H 'Content-Type: application/json' \
  -d '{
    "session_id": "session-001",
    "user_id": "employee-42",
    "text": "访客到公司以后怎么登记?"
  }'

测试需要确认的业务动作:

curl -s http://127.0.0.1:8000/v1/reception \
  -H 'Content-Type: application/json' \
  -d '{
    "session_id": "session-002",
    "user_id": "employee-42",
    "text": "会议室投影仪坏了,帮我报修",
    "confirmed": false
  }'

用户确认后,将 confirmed 改为 true 再次提交。这个例子刻意没有让模型直接执行动作:即使以后增加 LLM 意图识别,confirmed 校验、工具白名单和权限检查也应该留在服务端。

接入真实数字人时,可以把接口响应中的 speech 交给 TTS 或渲染 SDK;语音识别结果则作为 text 输入。这样更换语音或形象供应商时,不需要迁移工单规则和知识权限。

从可运行工程走向生产系统

完整工程解决了“能跑起来”的问题,但企业落地还要补齐安全与运维边界。评估或二次开发时,可以按下面的清单逐项检查:

  • 身份与知识权限:检索前根据用户、部门和知识密级过滤,不能在生成答案后才遮盖敏感内容;
  • 引用与可追溯性:回答最好附带文档标识、版本和片段来源,便于纠错;
  • 动作确认:创建、修改、删除类操作必须展示关键参数,并按风险等级决定是否二次确认;
  • 幂等性:网络重试不能重复创建工单或预约,可使用会话 ID 与动作 ID 生成幂等键;
  • 审计日志:记录调用者、检索范围、工具参数、执行结果和模型版本,同时对个人信息脱敏;
  • 故障降级:模型、向量库、TTS 或渲染服务超时时,应能返回固定话术或转人工;
  • 延迟拆分:分别统计 ASR、检索、模型、工具、TTS 和渲染耗时,不要只观察总响应时间;
  • 许可证核查:项目采用 Apache-2.0,但部署前仍需分别检查模型、语音组件、字体、形象素材和其他依赖的许可证。

KB Embodied Agent v1.0.0 的实际价值,在于把数字人从单纯的展示外壳推进到企业服务入口。更稳妥的采用路径是先做只读知识问答,再开放低风险动作,随后逐步接入需要身份校验的核心系统。无论形象多逼真,真正决定系统能否上线的,仍然是权限、确认、审计、幂等与降级机制。


相关推荐