用“小智AI”做语音版《答案之书》:为什么AI答案总感觉不对劲? 📅 发布时间:2026/9/7 17:31:28 👁 浏览次数: 用“小智AI”做了一个语音版《答案之书》为什么她的答案总感觉怪怪的之前一直想做一个有意思的 AI 语音小玩具正好手边有“小智AI”聊天机器人的开发环境就决定做一个语音版《答案之书》。传统《答案之书》就是随机翻开一页给你一句模棱两可却又好像有点道理的话。比如“答案是肯定的”“再等等”“不要急”这类短句。但当我用大模型 语音识别 语音合成把整个流程跑通之后发现一个很典型的问题为什么 AI 给出的答案总觉得哪里不对劲明明语音识别也识别对了大模型也正常返回了TTS 也播报出来了但就是怪。这篇文章就以这个语音版《答案之书》为例完整拆解一下从“小智AI 语音交互 智能体”的搭建思路并且重点分析为什么 AI 的回答在“语音场景”下会显得不对劲。这不仅是《答案之书》的问题也是很多 AI 语音硬件、AI 伴侣、语音智能体开发中容易踩的坑。1. 项目背景为什么要做语音版《答案之书》1.1 《答案之书》本质是什么传统《答案之书》是一个实体书项目它的答案库其实非常讲究句子短一般不超过 15 个字。语气中性不带强烈判断。内容偏向“开放性解释”让提问者自己脑补。句子不使用否定开头也很少用绝对化表达。所以当你把一个《答案之书》改成 AI 大模型生成时如果提示词没有把这些规则写进去AI 就会按照“通用助手”的习惯回答给你一段 50 字甚至 100 字的分析。这在文字场景下没问题但在语音场景下就会变成“话痨”。1.2 小智AI 是什么这里提到的小智AI是一套面向 AI 聊天机器人、智能语音交互的本地化 / 嵌入式方案。它可以对接大模型也可以接入语音识别和语音合成模块。在开发者社区中小智AI 经常被用来做智能音箱 DIY语音陪伴机器人AI 桌面摆件语音控制中控儿童故事机它的整体流程一般是这样用户说话 → 语音识别ASR → 大模型LLM → 答案生成 → 语音合成TTS → 扬声器播放在这个流程里任何一个环节出问题都会影响最终听感。1.3 为什么先选《答案之书》做原型《答案之书》是一个非常典型的“语音交互 大模型约束输出”场景它的优点是交互逻辑简单不需要多轮对话管理。答案要求短特别适合 TTS 播报。答案风格固定方便验证提示词是否生效。用户期待感强“翻书”这个动作本身就很有仪式感。所以它很适合作为新手入门“小智AI 智能体”的第一个项目。它不复杂但五脏俱全。2. 整体架构设计在写代码之前先要把整体架构理清楚。我采用的方案是麦克风采集 → 本地唤醒词检测 → ASR 语音识别 → 小智AI 调度 → LLM 推理 → TTS 合成 → 播放如果用模块化描述大概是模块作用常见实现唤醒模块检测用户是否在叫 AI自定义唤醒词引擎ASR 模块将语音转为文字离线语音识别 / 云识别LLM 模块生成《答案之书》的答案大模型 API 或本地模型TTS 模块将文字转为语音离线 TTS / 云 TTS调度模块串联整个链路小智AI 智能体框架在这个架构中小智AI 主要负责“调度”和“对话状态管理”而大模型负责“思考”。3. 环境准备与版本说明3.1 基础环境我用的环境仅供参考版本不需要完全一致重点是理解思路。项目环境操作系统Windows 11 / Ubuntu 22.04 均可开发语言Python 3.10小智AI 端侧框架根据设备平台选择大模型 API支持 OpenAI 兼容接口即可语音识别短句识别优先语音合成中英文短句 TTS如果你是在 Windows 上做原型验证可以先把“语音识别 大模型 语音合成”拆开跑通再结合小智AI 做调度。3.2 项目结构我建议按下面的结构组织项目answer-book-ai/ ├── main.py # 主程序入口 ├── wakeup.py # 唤醒词检测 ├── asr.py # 语音识别模块 ├── llm.py # 大模型调用模块 ├── tts.py # 语音合成模块 ├── prompt.py # 提示词配置 ├── config.yaml # 配置文件 ├── audio/ # 临时音频文件 └── requirements.txt # 依赖列表这种拆分方式的好处是每个模块可以单独调试。后面你如果想换成其他语音识别 SDK只需要改asr.py一个文件即可。4. 核心模块拆解与实现4.1 提示词设计为什么答案不对劲的第一层原因先来看一个最简单的提示词# 文件路径prompt.py SYSTEM_PROMPT 你是一本《答案之书》。 请回答用户的问题。 如果你用这个提示词大模型可能会回答我觉得这件事需要你仔细考虑一下因为它涉及到很多因素比如你的目标、你的资源、以及你目前所处的环境。总之建议你冷静下来再想一想也许会有新的发现。这段话本身没有错但它不适合作为《答案之书》的语音答案。问题在于太长。语音播报超过 15 秒用户会失去耐心。太具体。它把“因素”列出来了破坏了《答案之书》的模糊美学。像建议不像“答案”。传统的答案之书不会给你分析过程。所以正确的提示词应该是SYSTEM_PROMPT 你是一本《答案之书》。用户会向你提出一个问题。 你需要在心里默默思考但不要输出分析过程。 直接输出一句 20 字以内的中文短句作为答案。 要求 1. 每次只输出一句话不要解释。 2. 答案使用中性、开放的语气。 3. 不要以“你应该”“你必须”“建议你”开头。 4. 不要出现“首先”“其次”“最后”等连接词。 5. 不要使用否定句尽量使用正面、留有余地的表达。 6. 可以参考这些风格“答案是肯定的”“再等一等”“放下执念”“跟着直觉走”“会有转机”“不如换个角度看看”。 只输出这一句话不要输出其他任何内容。 这个提示词最核心的改动是不要输出分析过程直接输出一句话。4.2 大模型调用模块大模型调用层我直接使用 OpenAI 兼容接口# 文件路径llm.py import json import urllib.request class AnswerBookLLM: def __init__(self, api_key, base_url, model_name): self.api_key api_key self.base_url base_url.rstrip(/) self.model_name model_name def ask(self, user_question: str, system_prompt: str, temperature: float 0.8) - str: url f{self.base_url}/chat/completions payload { model: self.model_name, messages: [ {role: system, content: system_prompt}, {role: user, content: user_question} ], temperature: temperature, max_tokens: 100, stream: False } headers { Content-Type: application/json, Authorization: fBearer {self.api_key} } req urllib.request.Request( url, datajson.dumps(payload).encode(utf-8), headersheaders, methodPOST ) with urllib.request.urlopen(req, timeout30) as resp: data json.loads(resp.read().decode(utf-8)) return data[choices][0][message][content].strip()这里要注意几个参数temperature控制随机性。《答案之书》需要一点点“翻书”的随机感所以设为 0.8 左右效果不错。如果设为 0每次答案会偏向固定套路。max_tokens限制输出长度。因为只需要一句话100 tokens 足够了也可以防止模型突然话痨。4.3 温度参数与“不对劲”的关系如果你发现答案虽然短但每次都很相似比如总是出现“答案是肯定的”那很可能是temperature太低。如果答案经常超出 20 字则是max_tokens限制不够、或者提示词约束力不强。另外有些模型对中文提示词遵循能力较弱这时可以在提示词末尾加一个“格式化”技巧USER_PROMPT f问题{question} 请只输出一句话不要输出任何解释。或者更直接USER_PROMPT f请用一句20字以内的话回答以下问题 {question} 回答关键点是让模型以一种“填空”的方式补全答案而不是让它自由发挥。4.4 语音识别模块语音识别负责把用户说的话转成文字。比如用户说“我该不该换工作”ASR 要转成我该不该换工作这样的文本。# 文件路径asr.py from typing import Optional class SimpleASR: def __init__(self, use_cloud: bool False, app_id: str , api_key: str ): self.use_cloud use_cloud self.app_id app_id self.api_key api_key def transcribe(self, audio_path: str) - Optional[str]: 将音频文件转为文字 if self.use_cloud: return self._cloud_asr(audio_path) else: return self._local_asr(audio_path) def _local_asr(self, audio_path: str) - Optional[str]: # 这里对接本地语音识别引擎 # 不同平台接口差异较大需要根据实际情况实现 pass def _cloud_asr(self, audio_path: str) - Optional[str]: # 这里对接云端语音识别服务 pass在实际项目中小智AI 往往已经把 ASR 集成好了开发者只需要关心拿到文字之后怎么做。但有一个点需要特别提醒ASR 的断句会影响大模型理解。比如用户说我该不该换工作大模型能正确理解。但如果用户说我该不该 换工作ASR 输出带了明显停顿部分大模型也能理解。最怕的是 ASR 把问题“修正”成了另一个意思比如把“换工作”识别为“换工做”。这时大模型给出的答案再正确也会显得驴唇不对马嘴。所以排错第一步不是看提示词而是先看 ASR 转出来的文字对不对。4.5 语音合成模块语音合成的坑和 ASR 类似原本大模型输出了一句话答案是肯定的但需要再等等。如果 TTS 合成出来语气平淡、语速过快用户就会觉得“AI 回答得很敷衍”。# 文件路径tts.py class SimpleTTS: def __init__(self, voice_type: str female, speed: float 1.0): self.voice_type voice_type self.speed speed def synthesize(self, text: str, output_path: str) - str: 将文本合成语音文件返回音频文件路径 # 这里对接离线或在线 TTS 引擎 return output_path在语音版《答案之书》中TTS 的建议参数参数推荐值原因语速0.9 ~ 1.0太快像敷衍太慢像卡带音量适中偏大语音交互时环境噪声干扰大停顿句子间稍作停顿给用户“品味答案”的时间音色温和、中性符合《答案之书》的神秘感4.6 主流程串联主程序的作用是串联整个链路。核心逻辑并不复杂# 文件路径main.py import time import os from wakeup import WakeupEngine from asr import SimpleASR from llm import AnswerBookLLM from tts import SimpleTTS from prompt import SYSTEM_PROMPT WAKE_WORD 小智小智 def main(): wakeup WakeupEngine() asr SimpleASR(use_cloudFalse) llm AnswerBookLLM( api_keyos.getenv(LLM_API_KEY, your-api-key), base_urlos.getenv(LLM_BASE_URL, https://api.openai.com/v1), model_nameos.getenv(LLM_MODEL, gpt-3.5-turbo), ) tts SimpleTTS() print(《答案之书》已启动唤醒词, WAKE_WORD) while True: wakeup.wait_for_wake_word() print(唤醒成功请说出你的问题...) audio_file asr.listen_and_save(timeout5) question asr.transcribe(audio_file) if not question: print(没有听清问题重新等待唤醒...) continue print(用户问题, question) answer llm.ask(问题 question, system_promptSYSTEM_PROMPT, temperature0.8) print(答案之书, answer) tts.synthesize_and_play(answer) time.sleep(1) if __name__ __main__: main()这里的listen_and_save和synthesize_and_play是简化示意实际项目中需要依赖具体的麦克风库和播放库。4.7 智能体思维的影响现在很多大模型应用都强调“智能体”也就是把任务拆解成多个步骤让模型自主规划、调用工具。但在《答案之书》这个场景里智能体思维是有反作用的。举例来说正常的问答链路是用户问题 → 模型直接输出答案但如果你接入了智能体框架模型可能会用户问题 → 模型分析“这个问题涉及职业规划我需要调用职场建议工具” → 模型规划步骤 → 生成建议 → 输出最终输出就会变得冗长充满了“首先、然后、最后”的痕迹。而《答案之书》的体验恰恰是不要分析不要理由不要建议只要一句“灵光一闪”般的短句所以在这个项目里我特意关掉了所有工具调用只保留最朴素的“短问答模式”。这也是很多 AI 伴侣、AI 陪伴设备容易犯的错——总想展示自己的“能力”结果反而破坏了产品该有的氛围。5. 实验对比不同参数下答案风格的差异下面我用同一个问题“我该不该换工作”对比不同提示词和参数下的输出。5.1 普通助手提示词输入“我该不该换工作” 输出“换工作是一个重要的决定建议你先评估自己的职业规划。如果你已经准备好了可以考虑尝试如果不确定可以再多做一些市场调研。”问题像职业规划师不像答案之书。播报超过 20 秒。5.2 加入短句限制但没限制“情感倾向”输入“我该不该换工作” 输出“从现实角度看这个决定风险较高。建议你三思而后行。”问题虽然短了但是“评判感”太重像是在给你下结论。5.3 完整版《答案之书》提示词输入“我该不该换工作” 输出“答案在风里等一等就会清晰。”问题短、开放、有余地适合语音播报。从这个对比可以看到大模型输出“怪不怪”很大程度上取决于你有没有给它一个明确的“体裁约束”。6. 为什么感觉“不对劲”排查清单与解决思路我把自己踩过的坑整理成了一张表建议按顺序排查。现象可能原因解决思路回答太长像在写文章提示词没有限定输出长度增加“20字以内”“只输出一句话”等限制回答太像建议没有让模型模拟《答案之书》的风格在提示词中加入风格示例回答内容很好但语音播报出来很怪TTS 语速 / 音色设置不合适调整 TTS 语速、增加句间停顿用户问 AAI 答 BASR 识别错误打印 ASR 转写文本确认是否识别正确每次答案都差不多temperature 太低适当调高 temperature答案偶尔完全偏离max_tokens 不足导致输出被截断增大 max_tokens或优化提示词长度限制唤醒后迟迟不回答大模型推理耗时过长考虑换更快的模型或使用流式输出回答听起来像“理中客”模型没有角色代入在提示词中强调“你就是一本实体书”连续提问答案相互矛盾上下文没有清空每次提问都只传 system prompt 和当前问题6.1 最容易被忽略的问题上下文污染如果你使用同一个会话多次调用大模型模型会“记住”之前的对话那么它就可能基于前面几轮的内容调整答案导致用户感觉 AI 不再像《答案之书》而像在“跟踪分析自己”。解决办法很简单每次提问都只传 system prompt 当前问题不传历史消息。# 错误示例传入了历史对话 messages [ {role: system, content: SYSTEM_PROMPT}, {role: user, content: 我该不该换工作}, {role: assistant, content: 答案是肯定的。}, {role: user, content: 我该不该买房}, ] # 正确示例每次独立 messages [ {role: system, content: SYSTEM_PROMPT}, {role: user, content: 我该不该买房}, ]6.2 另一个容易被忽略的点问题格式化如果用户直接说一句话比如我该不该换工作大模型可能理解成“请跟我讨论换工作这件事”而不是“请给我一个答案之书的短句”。所以在调用时不要只把用户原话丢给模型最好加一个固定的提问模板USER_PROMPT_TEMPLATE 请回答以下问题只输出一句话 问题{} 回答这样模型知道自己的任务是“回答”而不是“讨论”。7. 进阶优化让语音版《答案之书》更有“书感”基础版跑通之后可以做几个小优化让体验提升非常明显。7.1 加入“翻书”音效传统答案之书翻页有一种“纸页摩擦声”在 AI 版本里也可以模拟。流程改成用户问完问题 → 播放翻书音效 → 停顿 0.5 秒 → 播报答案 → 播放合书音效这个小细节会让用户觉得真的“翻了一本书”而不是在跟 AI 聊天。7.2 答案前缀与答案分离不要直接在 TTS 里播报大模型原文。可以设置一个固定前缀“答案之书说”比如大模型输出不要急等一等。合成语音时播报答案之书说不要急等一等。这样做的两个好处让用户明确知道这是《答案之书》的答案不是 AI 闲聊。给 TTS 增加一个自然的开头缓冲避免语气突兀。7.3 随机展示答案文字可以加一块小屏幕或者连接上位机把答案文字同步显示出来。因为部分用户更习惯“看文字”如果只看文字会觉得答案“模棱两可”但配合语音语气反而会觉得有格调。7.4 在提示词中固化经典答案风格如果你用的是参数较小的本地开源模型对复杂指令遵循能力较弱可以换一种方式不用大模型“自由生成”而是在提示词中列出 50 条经典《答案之书》风格短句让模型“从中选一句”。SYSTEM_PROMPT_V2 请从以下答案库中选择一句最合适的话回答用户。 答案库 1. 是的机会就在眼前。 2. 再等一等会有转机。 3. 不要急着做决定。 4. 跟着直觉走准没错。 5. 换个角度看看答案就清晰了。 6. 保持耐心静候佳音。 7. 现在不是时候。 8. 不必担心一切都会过去。 9. 答案是肯定的但需要你主动行动。 10. 放下执念顺其自然。 只输出你选择的那一句话不要输出数字不要输出其他解释。 这样做会牺牲一点“随机感”但换来的是极强的稳定性特别适合设备内存有限、模型较弱的场景。相对地如果使用云端强模型则推荐保留自由生成模式但一定要写好风格约束。7.5 离线 TTS 的选型建议离线 TTS 方案在语音智能体项目里很常见。Android 14 用户经常搜索“离线 TTS 语音引擎下载”本质上是因为在线 TTS 会有网络延迟和流量消耗。离线 TTS 的好处响应快适合本地智能音箱。不依赖公网稳定性高。隐私好语音数据不出设备。但离线语音引擎往往有字库限制。如果你的《答案之书》答案库是固定的建议直接用离线 TTS 引擎 固定答案库这是最快乐、最不容易出bug的组合方式。8. 问答环节关于语音 AI 项目的常见疑问8.1 语音 AI 和聊天机器人有什么区别传统聊天机器人只处理“文字进、文字出”。语音 AI 增加了“语音识别”和“语音合成”两个环节。这两个环节不只是搬运还会“改造”内容导致最终体验出现偏差。这也是为什么你往往在纯文字测试时觉得 AI 很正常一旦接入语音链路就觉得“不对劲”。8.2 智能体开发需要用复杂框架吗不一定。如果你是做本地小设备用轻量调度就够了如果你要处理复杂工具调用、多轮状态管理再考虑用智能体平台或框架。《答案之书》这个项目明显属于前者不要过度设计。8.3 AI 回答听起来很机械怎么办优先调整 TTS 音色、情感参数、语速其次是调整提示词。很多开发者只盯提示词忽略了 TTS 的渲染能力。同一句话用温柔音色慢慢读和用机器音快速读感受天差地别。8.4 为什么 AI 有时会输出“空话”比如输出“一切都会好起来的”“相信自己”。这些句子本质上没有错但《答案之书》的特点在于“和问题有模糊的相关性”。如果答案是万能金句用户会觉得“敷衍”。解决办法是提示词中增加一条答案要尽量结合用户问题中的关键词但不要直接复述问题和评价问题。例如用户问“我该不该换工作”模型可以输出新的方向正在向你招手。虽然没有直接说答案但“新方向”与“换工作”产生了隐含关联用户就会觉得“有点东西”。8.5 如何增强 AI 的神秘感可以增加随机制不要求每次答案都“正确”允许一定随机性。用代码实现的话可以对大模型返回的答案做二次风格化# 二次风格化示例 def stylize_answer(answer: str) - str: # 如果答案太长只取前面一句话 if len(answer) 20: first_sentence answer.split(。)[0] return first_sentence 。 return answer这种“截断 补句号”的方法在工程上很实用。它强行把长答案压成短答案播报出来的节奏感更好。9. 生产部署建议与安全边界如果你只是做个 Demo完全没问题。但如果想把它长期跑在家里或者做成产品原型建议注意以下几点。9.1 隐私与录音语音交互项目必然涉及录音而录音属于敏感个人信息。建议本地处理优先不要所有音频都上传云端。如果必须上传对音频进行处理和转写后再送入大模型。不要长期保存用户原始音频录音转文字后即可删除。固定答案库模式下可以完全离线不需要录音出设备。《答案之书》这个场景非常适合做成“本地固定答案库 本地 ASR 本地 TTS”的全离线方案既不卡顿又避免隐私问题。9.2 输出可控性大模型输出天然带有不可控性。如果产品面向儿童或希望长期无人值守运行建议不要走“自由生成”而走“固定答案库 大模型选句子”的模式。这个模式既能保留一点“智能感”又不会突然输出不安全内容。9.3 延迟判断语音交互中有一条体验红线用户说话结束后1 秒内最好有反馈。如果大模型推理时间超过 2 秒用户会怀疑设备卡死。解决思路在“识别完成”后立刻播放一句“嗯让我看看……”来缓解等待感。使用更快的模型、更小的 max_tokens。或干脆用固定答案库彻底消灭大模型推理时间。9.4 小智AI 本地化部署的简单思路如果你把整套方案跑在本地建议软件栈简化为唤醒词引擎 本地ASR 固定答案库 本地TTS这个组合的特点是无需联网响应速度极快。不受大模型 API 波动影响。答案库可控不会出现“AI 突然话痨”或“突然胡说”的情况。运维成本低适合长期运行。10. 最后想说的话做语音版《答案之书》的过程中我最大的感悟是感觉“不对劲”并不是玄学而是链路中某个环节和产品预期不一致的表现。如果提示词不约束长度AI 就会话痨。如果 TTS 语速太快用户就会觉得敷衍。如果上下文不隔离AI 就会从“答案之书”变成“人生导师”。如果 ASR 识别错了回答再美也没用。这些问题其实都有清晰的排查方向。希望这篇文章能给准备做“小智AI 语音聊天机器人”、AI 伴侣、语音智能体、乃至离线语音交互设备的朋友一些参考。如果你想复刻这个项目建议从“固定答案库 本地区域 TTS”入手先跑通一条最小可用链路再逐步换成大模型生成答案。这样每一步的结果都可控也更容易判断问题到底出在哪一环。如果这篇文章对你有帮助欢迎收藏备用。也欢迎在评论区分享你自己使用小智AI、语音智能体时的踩坑经历大家一起交流。