#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 打断和恢复功能实现说明 此文件描述了完整的打断和恢复功能实现流程 """ """ 功能概述: 实现用户在数字人介绍过程中提问的功能: 1. 数字人开始播放介绍内容 2. 用户在介绍过程中可以随时提问 3. 数字人立即暂停介绍,优先回答用户问题 4. 回答完用户问题后,继续播放之前未完成的介绍内容 """ """ 系统组件及交互流程: 1. 前端 (dashboard.html) - 检测到用户提问时,发送带有以下参数的请求到 /human 接口: { "text": "用户问题", "type": "chat", "interrupt": true, # 表示需要打断当前播放 "during_intro": true, # 表示当前在介绍过程中 "sessionid": session_id, "knowledge_base": "知识库类型" } 2. 后端 (app.py) - human() 函数接收请求 - 检测到 interrupt=true 且 type='chat' - 调用 flush_talk() 中断当前播放 - 调用 llm_response() 处理用户问题 3. LLM处理 (llm.py) - llm_response() 函数 - 根据 during_intro 参数决定处理方式 - 如果 during_intro=True,调用 handle_interruption_during_intro() - 如果 during_intro=False,调用 put_user_question() 4. 播放控制 (basereal.py) - handle_interruption_during_intro() 方法: * 保存当前未完成的介绍内容到 interrupted_queue * 停止当前播放 * 将用户问题的回答放入高优先级队列播放 - put_user_question() 方法: * 中断当前播放 * 将用户问题的回答放入高优先级队列播放 5. 播放引擎 (ttsreal.py) - 处理高优先级队列和普通队列 - 优先播放高优先级队列中的内容 - 发送开始和结束事件通知 6. 自动恢复机制 (basereal.py) - notify() 方法检测到用户问题回答结束 - 启动定时器延时调用 _try_resume_after_qa() - _try_resume_after_qa() 检查是否有被中断的内容需要恢复 - 如果有,则调用 resume_interrupted() 恢复播放 7. 恢复播放 (basereal.py) - resume_interrupted() 方法将 interrupted_queue 中的内容移回 msg_queue - 继续播放之前未完成的介绍内容 """ """ API接口说明: 1. /human 接口 (app.py) - 用途:发送文本给数字人播放 - 参数: - text: 要播放的文本 - type: 'echo'(朗读) 或 'chat'(聊天) - interrupt: true/false,是否打断当前播放 - during_intro: true/false,是否在介绍过程中 - sessionid: 会话ID - knowledge_base: 知识库类型 2. /interrupt_talk 接口 (app.py) - 用途:专门用于打断数字人说话 - 参数: - sessionid: 会话ID 3. /resume_interrupted 接口 (app.py) - 用途:恢复被中断的内容 - 参数: - sessionid: 会话ID 4. /continue_after_qa 接口 (app.py) - 用途:问答后继续播放之前的内容 - 参数: - sessionid: 会话ID """ """ 关键方法说明: 1. BaseReal.flush_talk() - 中断当前播放并保存未完成的内容 2. BaseReal.handle_interruption_during_intro() - 处理介绍过程中的用户提问 3. BaseReal.put_user_question() - 处理用户问题(高优先级) 4. BaseReal.resume_interrupted() - 恢复被中断的内容 5. BaseReal.notify() - 处理播放事件通知,实现自动恢复 6. llm_response() - 处理用户问题并获取回答 """ """ 工作流程示例: 1. 数字人开始播放介绍:"欢迎使用本地生活App!我们提供丰富的商品和服务..." 2. 用户在播放过程中提问:"休闲娱乐有什么?" 3. 前端发送请求:{type:'chat', interrupt:true, during_intro:true, text:'休闲娱乐有什么?'} 4. 后端接收请求,调用 flush_talk() 中断当前播放 5. 系统保存未完成的介绍内容到中断队列 6. llm_response() 获取回答:"休闲娱乐包括电影院、KTV、游乐场等..." 7. 调用 handle_interruption_during_intro() 播放回答 8. 播放回答过程中,系统检测到回答结束事件 9. notify() 方法触发自动恢复机制 10. 系统从中断队列取出之前未完成的介绍内容继续播放 """ if __name__ == "__main__": print("打断和恢复功能实现说明") print("="*50) print("此实现确保了用户可以在数字人介绍过程中随时提问") print("系统会暂停介绍 -> 回答用户问题 -> 恢复介绍 的完整流程")