当前位置:AIGC资讯 > AIGC > 正文

构建本地运行的LLM语音助理

译者 | 朱先忠

审校 | 重楼

引言

我不得不承认,我最初对大型语言模型(LLM)生成实际有效的代码片段的能力持怀疑态度。我抱着最坏的打算尝试了一下,结果我感到很惊喜。就像与聊天机器人的任何互动一样,问题的格式很重要;但随着时间的推移,你会知道如何指定你需要帮助的问题的边界。

当我的老板发布了一项全公司范围的政策——禁止员工使用在线聊天机器人服务时,我已经习惯了在编写代码时始终可以使用这类服务。尽管我可以回到以前的谷歌搜索习惯,但我还是决定建立一个在本地运行的LLM服务;这样一来,我就可以在不将信息泄露到公司外面的情况下继续向机器人提出问题了。最后,多亏了HuggingFace网站(https://huggingface.co/)上的开源LLM产品和chailit项目(https://docs.chainlit.io/get-started/overview),我终于可以开发出一个能够提供编码辅助需求的服务程序。

随后的一个合乎逻辑的步骤就是添加一些语音交互功能。尽管语音不太适合作为编码辅助(你想看到生成的代码片段,而不是听到它们),但在某些情况下,你需要在创意项目中获得灵感,毕竟听他人讲故事的感觉总会进一步增加体验感。另一方面,你可能不愿意使用在线服务,因为你想保密你所做的工作。

在接下来的这个项目中,我将带您完成构建一个语音助理的所有步骤,该助理允许您与开源LLM进行语音交互。所有组件都将在您的计算机上以本地方式运行。

系统构架

这个项目的体系结构包括三个独立的组件:

  •  一个唤醒词检测服务
  •  一个语音助理服务
  •  一个聊天服务

由三部分组成的系统架构流程图(作者本人提供的图片)

注意,这三个组件是独立的项目,每个都有自己独立的Github存储仓库。下面,让我们分析一下每个组件,并了解一下它们是如何相互作用的。

聊天服务

该聊天服务运行一个名为HuggingFaceH4/zephyr-7b-alpha(https://huggingface.co/HuggingFaceH4/zephyr-7b-alpha)的开源LLM。该服务通过POST调用接收提示,通过LLM传递提示,并将输出作为调用响应返回。

你可以从链接https://github.com/sebastiengilbert73/chat_service处找到此服务相关代码。

在路径…/chat_service/server/中,我们将文件chat_server_config.xml.example重命名为chat_server/config.xml。

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

python .\chat_server.py

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

最后,您将从终端观察到服务正在运行的确认信息:

确认聊天服务正在运行(作者本人提供的图片)

如果您想测试与LLM的交互,请转到…/chat_service/chainlit_interface/路径下,将文件app_config.xml.example重命名为app_config.xml。然后,使用如下命令启动Web聊天服务:

.\start_interface.sh

然后,你可以从本地地址localhost:8000进行浏览。一切正常的话,您应该能够通过文本界面与本地运行的LLM进行交互:

与本地运行的LLM进行文本交互(作者本人提供的图片)

语音助理服务

语音助理服务是进行语音到文本和文本到语音转换的地方。你可以从链接https://github.com/sebastiengilbert73/voice_assistant处下载到这个语音助理服务完整的代码。

切换到如下路径:

…/voice_assistant/server/

然后,将文件voice_assistant_service_config.xml.example重命名为voice_aassistant_service-config.xml。

助理首先播放问候语,表示正在聆听用户说话。其中,问候语相应的文本配置在voice_assistant_config.xml中的元素<welcome_message>下:

voice_assistant_config.xml文件关键内容(作者本人提供的图片)

文本到语音引擎是pyttsx3(https://pypi.org/project/pyttsx3/),它允许程序将文本转换为您可以通过音频输出设备听到的口语音频。根据我的经验,无论是英语还是法语,这个引擎的声音都相当自然。与其他依赖API调用的软件包不同,它在本地运行。

一个名为facebook/seamless-m4t-v2-lage(https://huggingface.co/facebook/seamless-m4t-v2-large)的模型负责执行语音到文本的推理。首次运行voice_assistant_service.py时会下载模型权重。

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

  • 从麦克风中获取一句话。使用语音到文本模型将其转换为文本。
  • 检查用户是否说出了配置文件中<end_of_enversation_text>元素中定义的消息。在这种情况下,对话结束,并且程序在播放完再见消息后终止。
  • 检查句子是否是胡言乱语。语音转文本引擎通常会输出一个有效的英语句子,即使我什么都没说。在偶然的情况下,这些不受欢迎的输出往往会重复出现。例如,胡言乱语句子有时会以“[”或“i’m going to”开头。我在配置文件的<gibbish_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)

voice_assistant_service.main()函数中的主循环(作者本人编写的代码)

唤醒词服务

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

你可以从链接https://github.com/sebastiengilbert73/wakeword_service处找到唤醒词服务代码。

克隆完项目后,转到路径…/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项目(https://github.com/dscripka/openWakeWord)。在几个唤醒词模型中,我选择了“hey jarvis”模型。我发现简单地说“Jarvis?”就会触发检测。

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

唤醒词检测服务GUI的配置文件(作者本人提供的图片)

如果您想将唤醒词检测服务用于其他用途的话,可以编辑一下command.bat文件,使其启动您想要启动的任何程序即可。

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

当上述三个组件都安装并测试完成后,我们就可以启动聊天和唤醒词检测服务。唤醒词检测服务将不断收听麦克风。当检测到唤醒词(“Jarvis?”)时,它将启动语音助理服务。然后,你可以大声提问并得到口头回答。当检测到会话结束语(“Thank you and goodbye”)时,语音助理服务将结束。

与助理互动的示例

以下是与语音助理交互的示例:

“Jarvis?” [嘟嘟]

[语音助手模型加载时保持几秒钟的静音]

“Hello! How can I help you?”

[中文意思]“你好,我能帮你什么?”

“What are Saturn’s rings made of?”

[中文意思]“土星环是由什么组成的?”

“Saturn’s rings are primarily composed of ice particles, with the majority being made up of water ice. However, there are also smaller amounts of other ices, such as ammonia ice and rocky debris, in the rings. The exact composition of the rings varies depending on the distance from Saturn, with the inner rings being denser and made up of smaller particles, while the outer rings are more spread out and contain larger ice particles.”

[中文意思]“土星环主要由冰颗粒组成,大部分由水冰组成。然而,环中也有少量的其他冰,如氨冰和岩石碎片。环的确切组成取决于与土星的距离,内环密度更大,由更小的颗粒组成,而外环则更为分散并含有更大的冰粒。”

“Tell me the plot of the movie ‘Back to the Future’.”

[中文意思]“告诉我电影《回到未来》的情节。”

“The movie ‘Back to the Future’ follows the story of Marty McFly, a high school student who is accidentally transported back to 1955 in a time-traveling DeLorean car created by his eccentric scientist friend, Doc Brown. Marty must navigate the challenges of the past while trying to repair the damage to the present and prevent his teenage mother from falling in love with his teenage father. Along the way, Marty befriends a younger version of Doc Brown and helps him overcome a personal tragedy. The movie explores themes of fate, family, and the consequences of altering the past.”

[中文意思]“电影《回到未来》讲述了高中生Marty McFly的故事,他意外地被一辆由他古怪的科学家朋友Doc Brown驾驶的穿越DeLorean的汽车带回了1955年。Marty必须应对过去的挑战,同时努力修复对现在的伤害,防止他十几岁的母亲爱上他十多岁的父亲。一路上,Marty与年轻版的Doc Brown交上了朋友,并帮助他克服了一场个人悲剧。这部电影探讨了命运、家庭以及改变过去的后果等主题。”

“Thank you and goodbye”

[中文意思]“谢谢你,再见”

“Goodbye” [嘟嘟]

结论

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

在我开发这个语音助理时遇到的许多惊喜中,最让我印象深刻的是语音到文本转换的质量。如果你和我一样,你可能也遇到过自动语音识别系统无法转录简单命令(如“调低音量”)的问题!其实,我已经预计到语音到文本的转换将成为整个项目开发的主要障碍。在尝试了一些不很令人满意的模型后,我登陆到模型facebook/seamless-m4t-v2-lage(https://huggingface.co/facebook/seamless-m4t-v2-large),此模型输出结果的质量给我留下了深刻的印象。我甚至可以用法语说话,神经网络会自动将其翻译成英语。简直太神奇了!

最后,我希望你也能尝试一下这个有趣的项目,并让我知道你会用它做什么!

译者介绍

朱先忠,51CTO社区编辑,51CTO专家博客、讲师,潍坊一所高校计算机教师,自由编程界老兵一枚。

原文标题:Build a Locally Running Voice Assistant,作者:Sébastien Gilbert

链接:https://towardsdatascience.com/build-a-locally-running-voice-assistant-2f2ead904fe9

更新时间 2024-03-12