当前位置: 首页 > article >正文

山东大学软件学院创新项目实训 —— 基于UE与LLM的医患沟通模拟与评价系统(四)

文章目录前言一、场景列表接口实现1、get_all_scenarios_with_scenes()2、新增接口3、测试验证传参版本二、设计人物音色三、集成TTS语音合成功能1. 新建 app/services/tts_service.py2. 修改 endpoints.py3. 在 AudioResponse schema 里加 audio_path 字段4. 测试TTS前言本周完善了场景列表的接口后进行了一个新的任务设计了符合病例一王先生的音色并且将它集成到现在的项目中能够将AI回复的语句用音频输出。一、场景列表接口实现为前端提供所有已启用的临床剧本Scenario及其下属场景Scene的完整列表。目标是前端调用该接口后可动态生成场景选择界面下拉菜单、卡片列表或分类面板让用户选择具体的沟通场景。该接口实现了真正的热更新 —— 在数据库中新增或修改剧本后无需重启后端或重新打包 UE5即可在前端看到最新场景列表1、get_all_scenarios_with_scenes()在 scene_service.py 末尾追加一个新函数该函数是整个多场景配置系统的核心查询逻辑负责把数据库中的剧本与场景数据高效、安全地组织成前端友好的格式。async def get_all_scenarios_with_scenes()-list: async with AsyncSessionLocal()as session:# 查所有启用的剧本stmtselect(Scenario).where(Scenario.is_activeTrue)resultawait session.execute(stmt)scenariosresult.scalars().all()output[]forscenarioinscenarios:# 查该剧本下的所有场景按 sort 排序stmt2select(ScenarioScene).where(ScenarioScene.scenario_idscenario.id).order_by(ScenarioScene.sort)result2await session.execute(stmt2)scenesresult2.scalars().all()output.append({scenario_key:scenario.scenario_key,scenario_name:scenario.scenario_name,scenes:[{scene_key:scene.scene_key,scene_name:scene.scene_name,goal:scene.goal,sort:scene.sort}forsceneinscenes]})returnoutput作用查询所有 is_active True 的剧本Scenario为每个剧本查询其下属的所有场景ScenarioScene并按 sort 字段排序将数据组装成结构化的列表返回给 /api/scenes 接口2、新增接口在 app/api/endpoints.py 中新增了以下接口router.get(/scenes,response_modelScenesResponse)async def list_scenes(): try: dataawait get_all_scenarios_with_scenes()return{status:success,data:data}except Exception as e: raise HTTPException(status_code500,detailstr(e))在 app/schemas/chat.py 中新增了 SceneItem、ScenarioItem 和 ScenesResponse 三个 Pydantic 模型用于定义接口返回的数据结构使 Swagger 文档清晰可读。3、测试验证{status:success,data:[{scenario_key:heart_attack_wang,scenario_name:急性心梗沟通训练,scenes:[{scene_key:wang_explain,scene_name:解释病情,goal:开场建立信任、胸痛问诊、检查计划说明、吸烟风险沟通,sort:1},{scene_key:wang_decide,scene_name:共同决策,goal:检查结果通俗解读、治疗方案说明、造影与风险告知、共同决策治疗方案,sort:2}]},{scenario_key:coronary_sun,scenario_name:冠心病胸闷沟通训练,scenes:[{scene_key:sun_explain,scene_name:解释病情,goal:胸闷原因解释、检查项目说明、风险评估、生活方式指导,sort:1},{scene_key:sun_decide,scene_name:术前决策与共同沟通,goal:冠心病诊断解释、造影支架说明、手术风险告知、知情同意,sort:2}]}]}通过 Swagger UI 调用 GET /api/scenes接口成功返回 status: “success” 和 data 数组返回内容包含当前数据库中的剧本heart_attack_wang、coronary_sun及其下属多个具体场景wang_explain、wang_decide、sun_explain等每个场景均包含 scene_key、scene_name、goal 等关键信息。传参版本目前接口 /scenes 会返回所有数据经过小组讨论后我们希望能在 URL 后面加参数比如http://127.0.0.1:8000/api/scenes?scene_keysun_decide。这样接口就只返回 sun_decide 相关的数据而不是全部。需要在接口函数和get_all_scenarios_with_scenes函数中添加参数async def list_scenes(scene_key: Optional[str]Query(None,description要过滤的场景Key))async def get_all_scenarios_with_scenes(scene_key: strNone)结果如下二、设计人物音色在阿里云百炼大模型服务平台中可以直接通过输入提示词来设计想要的音色要抓住人物的特点来写提示词比如低沉粗糙的沙哑烟嗓因为心脏不好感到胸闷所以说话语速不能很快要有一些喘息声但是因为担心病情说话时语速也要有快慢的变化展示出病人的担心和害怕一定要避免中气十足的声音和非常正式的播音腔。我最后选择用 qwen3-tts-vd-2026-01-26 模型创建的音色 qwen-tts-vd-bailian-voice-20260417213012921-1c1d。随后我创建了一个新的代码文件tts_wang.py不启动FastAPI只进行单独测试写入了我的API Key以及模型和音色将输出的音频保存在了指定的文件夹。在这个代码中测试的文本是我指定的。importrequestsimportdashscope from fastapiimportFastAPI from fastapi.responsesimportFileResponseimporttempfile from dotenvimportload_dotenvimportos load_dotenv(dotenv_path.env.local)API_KEYos.getenv(DASHSCOPE_API_KEY)VOICE_IDqwen-tts-vd-bailian-voice-20260417213012921-1c1dMODELqwen3-tts-vd-2026-01-26# 北京地域的 base urldashscope.base_http_api_urlhttps://dashscope.aliyuncs.com/api/v1# # 核心函数文字 → 音频文件# def text_to_speech(text: str)-str: 调用阿里云百炼 TTS用王先生音色合成语音。 返回本地音频文件路径wav 格式。# Step 1调用 TTS非流式返回的是音频 URLresponsedashscope.MultiModalConversation.call(modelMODEL,api_keyAPI_KEY,texttext,voiceVOICE_ID,# ← 你设计的音色 IDlanguage_typeChinese,streamFalse,# 非流式)# Step 2从响应里取出音频 URL# 响应结构response.output.audio.urlifresponse.status_code!200: raise Exception(fTTS 调用失败: {response.code} - {response.message})audio_urlresponse.output.audio.urlifnot audio_url: raise Exception(响应中没有音频 URL请检查 voice_id 和 model 是否匹配)# Step 3下载音频到本地临时文件audio_responserequests.get(audio_url,timeout30)audio_response.raise_for_status()save_dirrD:\yinpin# 如果文件夹不存在自动创建ifnot os.path.exists(save_dir): os.makedirs(save_dir)# 生成唯一文件名避免覆盖importuuid filenameftts_{uuid.uuid4()}.wavaudio_pathos.path.join(save_dir, filename)# 保存音频with open(audio_path,wb)as f: f.write(audio_response.content)returnaudio_path# # FastAPI 接口示例# appFastAPI()app.post(/patient/speak)async def patient_speak(text: str): 接收 AI 病人王先生要说的文字返回音频文件。 前端收到后直接播放即可。 audio_pathtext_to_speech(text)returnFileResponse(pathaudio_path,media_typeaudio/wav,filenamepatient_response.wav)if__name____main__:test_text医生我昨天在厂里搬机器零件的时候突然胸口像被砸了一样疼疼得我直冒冷汗……现在还一直隐隐作痛有点喘不过气来。哎……我这是不是心脏出大问题了以后还能不能干重活啊我女儿马上高考我可不能拖累她呀……print(正在合成...)pathtext_to_speech(test_text)print(f合成成功音频文件保存在{path})三、集成TTS语音合成功能从gitee上拉取更新后的项目代码后我们目前想要实现的工作流程如下在更新的项目文件endpoints.py 的 /chat/audio_to_text 接口最后返回了 ai_replyAI 患者的文字回复现在已经实现了前两步我需要做的是在 audio_to_text 接口拿到 ai_reply 之后调用 TTS 把它转成音频返回音频文件路径给前端。1. 新建 app/services/tts_service.py把 TTS 逻辑封装成 tts_service.py# app/services/tts_service.pyimportosimportuuidimportasyncioimportrequestsimportdashscope from dotenvimportload_dotenv load_dotenv(dotenv_path.env.local)dashscope.base_http_api_urlhttps://dashscope.aliyuncs.com/api/v1VOICE_IDqwen-tts-vd-bailian-voice-20260417213012921-1c1dMODELqwen3-tts-vd-2026-01-26SAVE_DIRrD:\yinpindef _call_tts_sync(text: str)-str:同步调用阿里云 TTS返回本地音频路径。供 asyncio.to_thread 调用。 api_keyos.getenv(DASHSCOPE_API_KEY)responsedashscope.MultiModalConversation.call(modelMODEL,api_keyapi_key,texttext,voiceVOICE_ID,language_typeChinese,streamFalse,)ifresponse.status_code!200: raise Exception(fTTS 调用失败: {response.code} - {response.message})audio_urlresponse.output.audio.urlifnot audio_url: raise Exception(响应中没有音频 URL请检查 voice_id 和 model 是否匹配)audio_responserequests.get(audio_url,timeout30)audio_response.raise_for_status()os.makedirs(SAVE_DIR,exist_okTrue)audio_pathos.path.join(SAVE_DIR,patient_reply.wav)with open(audio_path,wb)as f: f.write(audio_response.content)returnaudio_path async def text_to_speech(text: str)-str:异步包装避免阻塞 FastAPI 主线程。returnawait asyncio.to_thread(_call_tts_sync, text)2. 修改 endpoints.py在 endpoints.py 顶部 import 区域加from app.services.tts_serviceimporttext_to_speech然后在 /chat/audio_to_text 加入 TTS 调用# 6. TTS将 AI 回复文字合成为音频保存到 D:\yinpinaudio_pathNone try: audio_pathawait text_to_speech(ai_reply)print(f[TTS 合成成功] 音频保存至: {audio_path})except Exception as tts_err: print(f[TTS 合成失败跳过] {tts_err})# 7. 返回识别结果给 UE5returnAudioResponse(statussuccess,recognized_textrecognized_text,replyai_reply,audio_pathaudio_path)3. 在 AudioResponse schema 里加 audio_path 字段在 app/schemas/chat.py 的 AudioResponse 里加一行class AudioResponse(BaseModel): status: str recognized_text: str reply: str audio_path: Optional[str]None# 新增TTS 失败时为 None4. 测试TTS在后端进行简单测试修改了/chat 接口改完之后在 Swagger UI 的 /chat 接口里发消息返回结果里不仅又回复的语句还有 audio_path同时 D:\yinpin 里会生成对应的音频文件。为了方便前端调用我们选择使用固定音频文件名。生成的音频与输出的文字相符合。

相关文章:

山东大学软件学院创新项目实训 —— 基于UE与LLM的医患沟通模拟与评价系统(四)

文章目录 前言一、场景列表接口实现1、get_all_scenarios_with_scenes()2、新增接口3、测试验证传参版本 二、设计人物音色三、集成TTS语音合成功能1. 新建 app/services/tts_service.py2. 修改 endpoints.py3. 在 AudioResponse schema 里加 audio_path 字段4. 测试TTS 前言 …...

FPGA----完美解决mmcx: Timeout waiting for hardware interrupt.

1、问题的出现:我在SD卡中有boot的fat分区和rootfs的ext4分区,以前每次启动经常性的出现sd卡无法加载的情况,我尝试了各种办法,甚至包括修改内核,一直无法解决。2、问题的解决: 开机时不要插入jtag线。这是…...

Java基础·第7篇:Java抽象类——把共性的先做了,剩下的你自己看着办

文章目录引入抽象方法和抽象类抽象类的使用抽象类的特征最后的话引入 假设我们要写一个员工管理系统。所有员工都有姓名、工号、薪水这些属性,也都需要打卡上班。这些代码每个子类都一样,如果让每个子类都写一遍,太麻烦了。 但是"工作…...

手把手教你解读华为服务器硬盘指示灯:绿灯黄灯怎么闪才算正常?

华为服务器硬盘指示灯全解析:从新手到精通的运维指南 当你第一次站在华为服务器机柜前,那些闪烁的绿光和黄光可能会让你感到困惑。作为一名刚接触华为服务器的新手运维人员,理解这些指示灯的含义就像学习一门新语言——它们用光信号讲述着硬盘…...

Windows Terminal —— 开发者/运维必备

Windows Terminal 深度评测:终端界的「六边形战士」一句话定位微软官方出品的现代化终端模拟器,集多标签页、多 Shell 环境(PowerShell / CMD / WSL)、GPU 加速渲染于一身,是颜值与性能并存的开发利器。优势清单性能卓…...

如何实现网盘全速下载:八大平台直链获取完整指南

如何实现网盘全速下载:八大平台直链获取完整指南 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云盘 …...

病理科医生和AI工程师都该懂:DICOM WSI标准(Supplement 145)如何重塑数字病理工作流

病理科医生和AI工程师都该懂:DICOM WSI标准(Supplement 145)如何重塑数字病理工作流 在病理诊断领域,一张玻片往往承载着患者生命健康的决定性信息。传统显微镜下,病理医生需要手动调节焦距、移动玻片,耗时…...

AI Agent 记忆系统设计 2026:从无状态到有记忆的工程实践

没有记忆的 Agent 就像一个每天醒来都失忆的人——能做事,但永远无法积累经验。 一、为什么 Agent 需要记忆当前大多数 AI Agent 的根本局限在于:它们是无状态的。每次对话结束,Agent 就"遗忘"了一切。下次对话,一切从头…...

华为交换机PoE配置保姆级教程:从基础使能到高级功率管理,手把手搞定AP和IPC供电

华为交换机PoE供电实战指南:从零配置到智能管理 当办公室新到一批华为无线AP时,网络工程师小张发现这些设备需要依赖交换机的PoE供电功能。与传统网络设备不同,PoE(Power over Ethernet)技术允许通过网线同时传输数据和…...

3分钟完成原神成就导出:YaeAchievement免费工具完整指南

3分钟完成原神成就导出:YaeAchievement免费工具完整指南 【免费下载链接】YaeAchievement 更快、更准的原神数据导出工具 项目地址: https://gitcode.com/gh_mirrors/ya/YaeAchievement 还在为手动记录原神成就而烦恼吗?YaeAchievement是一款专为…...

Qwen3-VL-8B本地部署实测:4090显卡5分钟搞定,开箱即用

Qwen3-VL-8B本地部署实测:4090显卡5分钟搞定,开箱即用 1. 为什么选择Qwen3-VL-8B? 在当今多模态AI领域,Qwen3-VL-8B以其卓越的视觉语言理解能力和高效的本地部署方案脱颖而出。作为一款专为消费级GPU优化的多模态模型&#xff0…...

终极指南:如何让CK2完美显示中文,告别乱码困扰!

终极指南:如何让CK2完美显示中文,告别乱码困扰! 【免费下载链接】CK2dll Crusader Kings II double byte patch /production : 3.3.4 /dev : 3.3.4 项目地址: https://gitcode.com/gh_mirrors/ck/CK2dll 你是否曾经在《十字军之王II》…...

不止于下载:用Python脚本把you-get和ffmpeg串起来,实现自动追更UP主音频合集

打造智能音频收藏系统:Python整合you-get与ffmpeg实现UP主作品自动归档 每次发现喜欢的知识分享UP主更新内容时,你是否也遇到过这样的困扰:想反复聆听其中的精华片段,却不得不反复打开视频平台;收藏的优质内容分散在不…...

SQL如何实现带条件的多表关联查询_利用CASE WHEN优化JOIN

WHERE条件放ON里控制连接逻辑,放WHERE里则过滤结果;LEFT JOIN需将右表过滤条件置于ON中,否则丢失左表记录。WHERE 条件写在 JOIN 里还是 ON 里,结果可能完全不同多表关联时加条件,最容易踩的坑就是把本该在 ON 子句里的…...

别用树莓派自带MC了!实测用HMCL启动器在Raspberry Pi OS 64位上安装Java版《我的世界》全流程

树莓派性能极限挑战:用HMCL启动器解锁完整Java版《我的世界》全流程实测 当树莓派遇到《我的世界》Java版,这场性能与情怀的碰撞会擦出怎样的火花?作为全球最畅销的沙盒游戏,《我的世界》Java版以其无限模组生态和完整游戏体验著称…...

低查重AI教材写作秘籍:必备AI工具推荐,快速完成教材编写!

许多教材编写者常常感到遗憾,虽然他们对正文内容进行了精心打磨,但配套资源的缺失却使得整体教学效果受到影响。设计课后练习时往往缺乏创新的思路,制作直观的教学课件又因为技术能力不足而举步维艰,而对于案例的深入解析则因为时…...

VisualCppRedist AIO:一站式解决Windows应用依赖难题的终极方案

VisualCppRedist AIO:一站式解决Windows应用依赖难题的终极方案 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾因"缺少msvcp140.dll&q…...

Hyperf方案 服务依赖分析与治理

Hyperf 服务依赖分析与治理,核心工具链:┌──────────────┬──────────────────────────────────┐│ 关注点 │ 方案 │ …...

ESP32串口通信保姆级教程:从Echo到RS485,手把手教你玩转ESP-IDF的UART驱动

ESP32串口通信实战指南:从基础配置到RS485工业应用 刚拿到ESP32开发板时,最让人兴奋的莫过于它的无线通信能力——Wi-Fi和蓝牙确实抢眼。但作为嵌入式开发者,我们往往忽略了这位"多面手"的另一项基本功:UART串口通信。无…...

SAP 清账凭证 底层完整生成逻辑(无冗余、纯原理 + 分录规则 + 边界场景)

SAP 清账凭证 底层完整生成逻辑(无冗余、纯原理 分录规则 边界场景)一、基础前置定义(决定能不能生成清账凭证)仅勾选【未清项管理】 的总账科目才可执行清账:应收账款、应付账款、GR/IR 暂估、其他往来、暂估科目等…...

【Dify国产化测试黄金标准】:12类中间件兼容矩阵、5轮压力测试阈值、4项国密SM4/SM2集成验证

第一章:Dify国产化部署测试的总体框架与合规基线 Dify作为开源大模型应用开发平台,其国产化部署需兼顾技术可行性、安全可控性与行业监管要求。总体框架以“信创适配层—平台运行层—数据治理层—合规验证层”四维协同为设计核心,覆盖从硬件基…...

告别CANtest和ECAN Tools:用Python脚本玩转ZLG/创芯CAN盒的自动化测试

用Python脚本实现ZLG/创芯CAN盒的自动化测试实战指南 记得第一次接触CAN总线测试时,我盯着ZCANPro软件界面反复点击"发送"按钮,手指都快抽筋了。那时就想,如果能用代码控制这些操作该多好。后来发现,其实大多数国产CAN盒…...

Blazor + WASM + WebGPU 实时渲染面试突击包:含WebAssembly SIMD加速、GPU缓冲区绑定、帧同步调试全流程(仅限Q2开放下载)

第一章:C# Blazor 2026 现代 Web 开发趋势 面试题汇总随着 .NET 9 的正式发布与 WebAssembly 运行时性能的持续优化,Blazor 已成为构建高性能、全栈式 C# Web 应用的核心范式。2026 年面试官更关注开发者对服务端预渲染(SSR)、混合…...

音频标注终极指南:免费开源工具Audio Annotator完整教程

音频标注终极指南:免费开源工具Audio Annotator完整教程 【免费下载链接】audio-annotator A JavaScript interface for annotating and labeling audio files. 项目地址: https://gitcode.com/gh_mirrors/au/audio-annotator Audio Annotator是一款基于Java…...

高薪诱惑!大厂AI实习生薪资暴涨6万,小白也能抓住未来机遇?速收藏!

大厂AI实习生薪资暴涨,顶尖学生月薪可达6万,是AI产业高速发展与人才短缺矛盾的结果。大厂争夺未来人才,实习生表现优异者几乎100%获高薪全职offer。高薪背后是供需失衡,大模型算法研发、AI Infra、AI应用研究等岗位最抢手。顶尖院…...

学会给AI搭系统,才是2026年最值钱的技能!收藏这份保姆级指南

文章对比了学习AI工具和使用AI系统两种方式,强调后者更具有长远价值。通过实例展示,搭建AI系统可以极大提高效率,且这种能力比单纯会使用AI工具更难掌握,因此更值得学习。文章提出“驾驭工程”概念,并给出普通人学习搭…...

收藏!小白程序员必看:大语言模型入门指南,轻松掌握未来AI核心技术!

大语言模型(LLM)是生成式AI的核心,本文概述其发展历程、应用流程及构建过程。从自监督预训练到指令微调,再到人类反馈强化学习,详细介绍LLM的训练与推理阶段。同时,深入探讨预训练技术在数据、模型和训练层…...

Xftp 7免费版隐藏功能大揭秘:从图像预览到OpenSSH证书认证,不止是传文件

Xftp 7进阶实战:解锁专业用户都在用的高效文件管理技巧 每次在服务器间来回传输日志文件时,我总忍不住想起第一次用Xftp 7的场景——那时我只把它当作普通FTP工具,直到偶然发现它的图像预览功能,才意识到自己错过了多少效率神器。…...

文档解析准确率从81.6%→99.2%:Dify v0.8.5+自定义Chunker调优全流程,仅限内部技术团队验证的7个关键参数

第一章:文档解析准确率从81.6%→99.2%:Dify v0.8.5自定义Chunker调优全流程,仅限内部技术团队验证的7个关键参数 在 Dify v0.8.5 版本中,原生文档解析器对多格式混合文档(含 PDF 表格嵌套、Markdown 代码块与中文段落混…...

【Dify插件开发黄金法则】:20年AI平台架构师亲授,从零构建可商用插件的5大核心步骤

第一章:Dify插件开发的底层逻辑与商业价值认知 Dify 插件系统并非简单的功能扩展接口,而是基于 LLM 应用编排范式重构的服务集成层。其底层依托于 OpenAPI 3.0 规范自动解析与运行时 Schema 校验机制,所有插件必须提供符合标准的 openapi.ya…...