Fay数字人QA功能详解
Fay项目为数字人交互提供了两套互补能力:大模型(LLM)用于生成开放式回答,QA功能则负责匹配预设回答、执行简单指令并解答人设相关问题。当用户提问时,系统会优先调用内置的 QA 服务;仅当无法命中 QA 时才转而使用大模型,从而减少无关回答并提升稳定性。本文将深入解析 Fay 中 QA 功能的结构、实现逻辑以及如何扩展定制。
QA 功能的三大类别
core/qa_service.py
定义了 QAService
类,用于根据用户输入返回预设答案或执行命令。构造函数中包含了两组关键字列表:
-
人设提问关键字
attribute_keyword
:用于回答数字人的姓名、性别、年龄、家乡、生肖、星座、职业、爱好和联系方式等问题GitHub。例如,如果用户问“你叫什么名字”,系统会认为该问题属于“name”类。 -
命令关键字
command_keyword
:用于识别控制指令,如关闭、静音、取消静音和换声音GitHub。这些指令会触发相应的系统行为,例如停止输出或切换音色。
QAService 还支持读取自定义问答库。当 question
方法的 query_type
为 'qa'
时,系统会从配置文件指定的 CSV 中加载问答对GitHub。CSV 第一列可以包含多个问题(用分号分隔),第二列为对应回答,第三列可选,用于存放动作命令。如此,用户的问题若匹配 CSV 中的问句即可得到指定回答或触发操作。
此外,question
支持两种特殊模式:
-
'Persona'
模式:使用attribute_keyword
列表匹配问题,返回关键字(如name
、gender
等)GitHub。后续模块会从config.json
的attribute
字段中读取对应属性值,例如名字为 Fay、年龄为“成年”、星座为水瓶座等。 -
'command'
模式:利用command_keyword
判断用户是否发送了控制指令GitHub。若匹配到命令,系统会执行预定义的 shell 操作(如静音),并返回命令关键字。
QAService 默认使用 'qa'
类型,具体类别由调用方决定。在 Fay 核心逻辑中,通过 'qa'
模式先匹配常用问答;再根据需要扩展人设或命令模式。
Fuzzy 匹配逻辑与候选选择
匹配算法位于 __get_keyword
方法。该函数遍历给定的关键字列表,利用 difflib.SequenceMatcher
计算相似度GitHub。若文本包含完整关键词,则额外增加 0.3 的相似度分,以提高匹配优先级GitHub。只有当相似度超过阈值 0.6 时,该候选才会被纳入选集GitHub。
匹配完成后,候选列表按相似度排序,保留前 10%(至少一个)GitHub。系统从这些候选中随机挑选一个答案和动作GitHub。这种策略避免了硬编码顺序的机械感,使数字人的回答更自然。
当 query_type
为 'qa'
且候选包含动作时,question
会新建线程执行该动作GitHub。例如在 CSV 中配置第三列为 say
等命令,可以让数字人在回答的同时触发外部脚本。
QA 数据源与配置
Fay 允许自定义问答对。config.json
中 interact.QnA
字段指定了 CSV 文件的名称或路径GitHub。qa_service.__read_qna
会逐行读取此文件,将每行拆分为 [问题集合, 答案, 动作]
形式GitHub。若用户问题与其中某个问题的相似度超过阈值,则返回对应回答或执行动作。
若希望动态扩展问答对,Fay 提供了采纳接口:/api/adopt-msg
。在管理界面中选中用户提问和机器人回答后,可以将该对话写入 CSV。该接口会调用 record_qapair
方法,将问题与答案追加到 CSV 文件末尾GitHubGitHub。若配置文件未指定 QnA
路径,采纳请求将返回错误提示GitHub。通过这种方式,运营人员可以迭代构建企业知识库,使数字人回答更加贴合业务需求。
Fay 核心对 QA 的调用流程
当 Fay 收到语音或文字交互请求时,核心逻辑(FeiFei.__process_interact
)首先调用 __get_answer
方法,尝试从 QAService 获取答案GitHub。如果返回的 answer
不为空且类型为 'qa'
,则认定命中了 QA,直接将该答案交给流式播报模块 __process_stream_output
,数字人会按短句播报回答GitHub。如果没有命中 QA,则进入大语言模型推理流程,并在思考阶段向用户提示“思考中...”GitHub。此时,Fay 会调用 LLM 生成回答,再由后续流程进行语音合成和表情同步。
Fay 的消息交互模式包括两类:
-
互动模式(
interact_type = 1
):用户发起提问。系统首先记录并广播用户内容,然后判断是否匹配 QA。若命中 QA,则直接播报预设答案;否则调用大模型回答GitHub。 -
透传模式(
interact_type = 2
):用于通知播报。若包含音频链接则仅播放音频,否则将文本分句播报GitHub。透传模式不参与 QA 匹配。
人设与命令问答
除了企业自定义问答外,Fay 还内置了“人设”问答与“命令”问答:
-
人设问答:当
query_type
为'Persona'
时,QAService
使用attribute_keyword
找到匹配类别GitHub。例如,问“你多大了”,系统会返回'age'
。随后,调用代码会从config.json
的attribute
部分获取具体值(如年龄为“成年”),并将其作为最终回答。通过修改配置,可快速更换数字人的个人设定而无需改动代码。 -
命令问答:命令关键词如“关闭”、“静音”等被映射为
stop
、mute
、unmute
和changeVoice
GitHub。当匹配成功时,question
返回指令关键字并可能附带动作。Fay 内部会根据指令改变播放状态或切换声音,从而实现用户对数字人的基本控制。
这些人设和命令的匹配逻辑与普通 QA 完全一致,都是通过字符串相似度和阈值筛选候选答案,只是词典不同。
如何扩展和优化 QA 功能
-
配置自定义知识库:把常见问答对写入 CSV,每行格式为
问题1;问题2,答案,动作(可省略)
。在config.json
中指定interact.QnA
文件名。系统会自动读取并匹配答案。建议针对企业场景将问题语句多样化,提升匹配成功率。 -
通过采纳功能完善 QA:使用
/api/adopt-msg
接口采纳对话,将实际用户提问和回答纳入知识库GitHub。这样能不断丰富 QA 数据,并减轻运营维护负担。 -
调整相似度阈值:默认阈值 0.6,完全包含关键字可加 0.3。可在代码中修改
threshold
以适配更宽或更严的匹配需求GitHub。 -
利用动作功能实现复杂流程:在 CSV 的第三列写入系统命令或脚本,
QAService
将异步执行这些动作GitHub。例如,当用户咨询“预定会议室”,可以在动作列调用后台接口处理预约并返回结果。 -
多语言支持:当前匹配逻辑基于中文关键字。若需支持多语言,可在 CSV 中添加不同语言的问句或扩展
attribute_keyword
与command_keyword
列表。
总结
Fay 的 QA 功能为数字人提供了稳定的“知识问答”能力,它通过三种类别的关键字匹配实现快速响应、个人设定和指令控制。QAService 既能读取自定义问答库,利用模糊匹配返回答案并执行动作,也能回答数字人的基础信息和接收用户的命令。核心逻辑在交互层判断是否命中 QA,未命中时才调用大模型,大幅提升了回答的准确性和效率。通过配置 QnA 文件、采纳会话和调整阈值,用户可以持续完善企业知识库,使 Fay 数字人更好地服务于各种场景。