构建本地运行的语音助手

2024年01月02日 由 alex 发表 401 0

在本文中,我将带领你经历构建一个助手的步骤,这个助手允许你与一个开源LLM进行语音互动。所有组件都在你的电脑上本地运行。


架构


架构涉及三个独立组件:


  • 唤醒词检测服务
  • 语音助手服务
  • 聊天服务


4


聊天服务


聊天服务运行一个名为HuggingFaceH4/zephyr-7b-alpha的开源大型语言模型(LLM)。该服务通过POST请求接收一个提示,经过LLM处理后,将输出作为请求响应返回。


在…/chat_service/server/目录下,将chat_server_config.xml.example重命名为chat_server_config.xml。


然后你可以使用以下命令启动聊天服务器:


python .\chat_server.py


当服务首次运行时,它需要几分钟才能启动,因为需要从HuggingFace网站下载大文件并存储在本地缓存目录中。


你将从终端获得一个确认,表明服务正在运行


5


将app_config.xml.example重命名为app_config.xml。启动网页聊天服务。


.\start_interface.sh


浏览到本地地址 localhost:8000


你应该能够通过文字界面与本地运行的LLM进行交互:


6


语音助手服务


语音助手服务是语音转文本和文本转语音转换发生的地方。


前往 …/voice_assistant/server/。


将 voice_assistant_service_config.xml.example 重命名为 voice_assistant_service_config.xml。


助手通过播放问候语开始,表明它正在听取用户的指令。问候语文本在 voice_assistant_config.xml 中配置,位于元素 <welcome_message> 下:


7


这个程序能够将文本转换为口语音频的文本转语音引擎是pyttsx3。根据我的经验,这个引擎用一种相当自然的语调说话,无论是英语还是法语。与依赖API调用的其他包不同,它在本地运行。


一个名为facebook/seamless-m4t-v2-large的模型执行语音到文本的推理。当第一次运行voice_assistant_service.py时,模型权重会被下载。


voice_assistant_service.main()中的主循环执行以下任务:


  • 从麦克风获取一个句子。使用语音到文本模型将其转换成文本。
  • 检查用户是否说出了配置文件中<end_of_conversation_text>元素定义的消息。在这种情况下,会话结束,并且程序在播放告别信息后终止。
  • 检查句子是否是胡言乱语。即使我什么都没说,语音到文本引擎经常输出有效的英语句子。偶然情况下,这些不期望的输出往往会重复自己。例如,胡言乱语的句子有时会以“[”或“i'm going to”开始。我在配置文件中的<gibberish_prefix_list>元素收集了一系列经常与胡言乱语句子相关联的前缀(这个列表对于另一个语音到文本模型可能会改变)。每当一个音频输入以列表中的前缀之一开始时,这个句子就会被忽略。
  • 如果句子似乎不是胡言乱语,就发送请求给聊天服务。播放回应。


end_of_conversation = False
    while not end_of_conversation:
        transcription = get_sentence(
            mic_stream, stt_processor, stt_model, device, config.sampling_rate,
            config
        )
        if transcription.lower().replace('.', '').replace('!', '') == config.end_of_conversation_text.lower():
            logging.info(f"voice_assistant_service.main(): End of conversation")
            end_of_conversation = True
        else:
            sentence_is_gibberish = False
            if transcription[0] == '[':
                sentence_is_gibberish = True
            for prefix in config.gibberish_prefix_list:
                if transcription.lower().startswith(prefix):
                    sentence_is_gibberish = True
            if len(transcription) > 15 and not sentence_is_gibberish:
                response = send_request_to_chat_service(config, transcription)
                logging.info(f"voice_assistant_service.main(): response = {response}")
                play_message(response, engine, config)
    goodbye(engine, config)


唤醒词服务


最后一个组件是一个持续监听用户麦克风的服务。当用户说出唤醒词时,系统调用会启动语音助手服务。唤醒词服务运行的模型比语音助手服务的模型小。因此,持续运行唤醒词服务是有意义的,而语音助手服务只在我们需要时才启动。


克隆项目后,移动到…/wakeword_service/server。


将 wakeword_service_gui_config.xml.example 重命名为 wakeword_service_gui_config.xml。


将 command.bat.example 重命名为 command.bat。你需要编辑 command.bat,使虚拟环境激活和调用 voice_assistant_service.py 与你的目录结构相对应。


你可以通过以下调用来启动服务:


python gui.py


唤醒词检测服务的核心是开源项目openwakeword。在几个唤醒词模型中,我选择了"hey jarvis"模型。我发现仅仅说"Jarvis?"就会触发检测。


每当唤醒词被检测到时,会根据配置文件中<command_on_wakeword>元素的指定调用一个命令文件。在我们的例子中,command.bat文件激活了虚拟环境并启动了语音助手服务。


8


如果你希望将唤醒词检测服务用于其他事物,你可以编辑 command.bat 文件以使其启动你想要的任何程序。


当检测到唤醒词时,唤醒词检测服务会发出两声哔哔的音频信号,以表明它已被触发。这种快速反馈告诉用户他们必须等待,因为文本到语音和语音到文本的模型加载到计算机的 GPU 中,这可能需要几秒钟。当两个模型都加载好后,语音助手服务播放问候语,对话就可以开始了。对话结束后,语音助手服务终止,唤醒词检测服务会发出另外两声哔哔信号。


当这三个组件安装并测试好之后,我们可以启动聊天和唤醒词检测服务。唤醒词检测服务将不断监听麦克风。当检测到唤醒词(“Jarvis?”)时,它会启动语音助手服务。你可以大声提问并收到口头答复。当检测到结束对话的短语(“谢谢再见”)时,语音助手服务结束。


与助手的互动示例


这是一个与语音助手互动的例子:


“Jarvis?” [哔-哔]
[加载语音助手模型时的几秒钟沉默]
“你好!我能帮你什么忙?”
“土星的环是由什么组成的?”
“土星的环主要由冰颗粒组成,大部分是由水冰制成。但是,环中还含有较少量的其他冰,如氨冰和岩石碎片。环的确切组成根据与土星的距离而有所不同,内环更加致密并且由较小颗粒组成,而外环更分散并包含较大的冰颗粒。”
“给我讲讲电影 '回到未来' 的情节。”
“电影‘回到未来’讲述了高中生马蒂·麦克弗莱的故事,他不小心被送回到1955年,乘坐着他那位古怪科学家朋友达克·布朗创造的时间旅行的德洛林汽车。马蒂必须在过去应对挑战,同时尝试修复对现在的损害,阻止他的青少年母亲爱上他的青少年父亲。一路上,马蒂交到了较年轻版本的达克·布朗,并帮他克服了一个个人悲剧。这部电影探索了命运、家庭以及改变过去的后果等主题。”
“谢谢再见”
“再见” [哔-哔]


结论


在这个项目中,我们实现了一个语音助手系统,包括唤醒词检测服务、语音助手服务和聊天服务。这些组件中的每一个都是可用于其他项目的独立构建块。


文章来源:https://medium.com/towards-data-science/build-a-locally-running-voice-assistant-2f2ead904fe9
欢迎关注ATYUN官方公众号
商务合作及内容投稿请联系邮箱:bd@atyun.com
评论 登录
写评论取消
回复取消