譯者 | 朱先忠
審校 | 重樓
引言
我不得不承認(rèn),我最初對大型語言模型(LLM)生成實(shí)際有效的代碼片段的能力持懷疑態(tài)度。我抱著最壞的打算嘗試了一下,結(jié)果我感到很驚喜。就像與聊天機(jī)器人的任何互動(dòng)一樣,問題的格式很重要;但隨著時(shí)間的推移,你會(huì)知道如何指定你需要幫助的問題的邊界。
當(dāng)我的老板發(fā)布了一項(xiàng)全公司范圍的政策——禁止員工使用在線聊天機(jī)器人服務(wù)時(shí),我已經(jīng)習(xí)慣了在編寫代碼時(shí)始終可以使用這類服務(wù)。盡管我可以回到以前的谷歌搜索習(xí)慣,但我還是決定建立一個(gè)在本地運(yùn)行的LLM服務(wù);這樣一來,我就可以在不將信息泄露到公司外面的情況下繼續(xù)向機(jī)器人提出問題了。最后,多虧了HuggingFace網(wǎng)站(https://huggingface.co/)上的開源LLM產(chǎn)品和chailit項(xiàng)目(https://docs.chainlit.io/get-started/overview),我終于可以開發(fā)出一個(gè)能夠提供編碼輔助需求的服務(wù)程序。
隨后的一個(gè)合乎邏輯的步驟就是添加一些語音交互功能。盡管語音不太適合作為編碼輔助(你想看到生成的代碼片段,而不是聽到它們),但在某些情況下,你需要在創(chuàng)意項(xiàng)目中獲得靈感,畢竟聽他人講故事的感覺總會(huì)進(jìn)一步增加體驗(yàn)感。另一方面,你可能不愿意使用在線服務(wù),因?yàn)槟阆氡C苣闼龅墓ぷ鳌?/span>
在接下來的這個(gè)項(xiàng)目中,我將帶您完成構(gòu)建一個(gè)語音助理的所有步驟,該助理允許您與開源LLM進(jìn)行語音交互。所有組件都將在您的計(jì)算機(jī)上以本地方式運(yùn)行。
系統(tǒng)構(gòu)架
這個(gè)項(xiàng)目的體系結(jié)構(gòu)包括三個(gè)獨(dú)立的組件:
- 一個(gè)喚醒詞檢測服務(wù)
- 一個(gè)語音助理服務(wù)
- 一個(gè)聊天服務(wù)
由三部分組成的系統(tǒng)架構(gòu)流程圖(作者本人提供的圖片)
注意,這三個(gè)組件是獨(dú)立的項(xiàng)目,每個(gè)都有自己獨(dú)立的Github存儲(chǔ)倉庫。下面,讓我們分析一下每個(gè)組件,并了解一下它們是如何相互作用的。
聊天服務(wù)
該聊天服務(wù)運(yùn)行一個(gè)名為HuggingFaceH4/zephyr-7b-alpha(https://huggingface.co/HuggingFaceH4/zephyr-7b-alpha)的開源LLM。該服務(wù)通過POST調(diào)用接收提示,通過LLM傳遞提示,并將輸出作為調(diào)用響應(yīng)返回。
你可以從鏈接https://github.com/sebastiengilbert73/chat_service處找到此服務(wù)相關(guān)代碼。
在路徑…/chat_service/server/中,我們將文件chat_server_config.xml.example重命名為chat_server/config.xml。
然后,您可以使用以下命令啟動(dòng)聊天服務(wù)器:
python .\chat_server.py
當(dāng)該服務(wù)首次運(yùn)行時(shí),需要幾分鐘才能啟動(dòng),因?yàn)榇笮臀募?huì)從HuggingFace網(wǎng)站下載并存儲(chǔ)在本地緩存目錄中。
最后,您將從終端觀察到服務(wù)正在運(yùn)行的確認(rèn)信息:
確認(rèn)聊天服務(wù)正在運(yùn)行(作者本人提供的圖片)
如果您想測試與LLM的交互,請轉(zhuǎn)到…/chat_service/chainlit_interface/路徑下,將文件app_config.xml.example重命名為app_config.xml。然后,使用如下命令啟動(dòng)Web聊天服務(wù):
.\start_interface.sh
然后,你可以從本地地址localhost:8000進(jìn)行瀏覽。一切正常的話,您應(yīng)該能夠通過文本界面與本地運(yùn)行的LLM進(jìn)行交互:
與本地運(yùn)行的LLM進(jìn)行文本交互(作者本人提供的圖片)
語音助理服務(wù)
語音助理服務(wù)是進(jìn)行語音到文本和文本到語音轉(zhuǎn)換的地方。你可以從鏈接https://github.com/sebastiengilbert73/voice_assistant處下載到這個(gè)語音助理服務(wù)完整的代碼。
切換到如下路徑:
…/voice_assistant/server/
然后,將文件voice_assistant_service_config.xml.example重命名為voice_aassistant_service-config.xml。
助理首先播放問候語,表示正在聆聽用戶說話。其中,問候語相應(yīng)的文本配置在voice_assistant_config.xml中的元素<welcome_message>下:
voice_assistant_config.xml文件關(guān)鍵內(nèi)容(作者本人提供的圖片)
文本到語音引擎是pyttsx3(https://pypi.org/project/pyttsx3/),它允許程序?qū)⑽谋巨D(zhuǎn)換為您可以通過音頻輸出設(shè)備聽到的口語音頻。根據(jù)我的經(jīng)驗(yàn),無論是英語還是法語,這個(gè)引擎的聲音都相當(dāng)自然。與其他依賴API調(diào)用的軟件包不同,它在本地運(yùn)行。
一個(gè)名為facebook/seamless-m4t-v2-lage(https://huggingface.co/facebook/seamless-m4t-v2-large)的模型負(fù)責(zé)執(zhí)行語音到文本的推理。首次運(yùn)行voice_assistant_service.py時(shí)會(huì)下載模型權(quán)重。
函數(shù)voice_assistant_service.main()中的主循環(huán)執(zhí)行以下任務(wù):
- 從麥克風(fēng)中獲取一句話。使用語音到文本模型將其轉(zhuǎn)換為文本。
- 檢查用戶是否說出了配置文件中<end_of_enversation_text>元素中定義的消息。在這種情況下,對話結(jié)束,并且程序在播放完再見消息后終止。
- 檢查句子是否是胡言亂語。語音轉(zhuǎn)文本引擎通常會(huì)輸出一個(gè)有效的英語句子,即使我什么都沒說。在偶然的情況下,這些不受歡迎的輸出往往會(huì)重復(fù)出現(xiàn)。例如,胡言亂語句子有時(shí)會(huì)以“[”或“i’m going to”開頭。我在配置文件的<gibbish_prefix_list>元素中收集了一個(gè)前綴列表,這些前綴通常與胡言亂語語句相關(guān)(該列表可能會(huì)因另一個(gè)語音到文本模型而更改)。每當(dāng)音頻輸入以列表中的一個(gè)前綴開頭時(shí),該句子就會(huì)被忽略。
- 如果句子看起來沒有胡言亂語,就會(huì)向聊天服務(wù)發(fā)送請求,然后播放回應(yīng)。
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()函數(shù)中的主循環(huán)(作者本人編寫的代碼)
喚醒詞服務(wù)
最后一個(gè)組件是持續(xù)監(jiān)聽用戶麥克風(fēng)的服務(wù)。當(dāng)用戶說出喚醒詞時(shí),系統(tǒng)呼叫啟動(dòng)語音助理服務(wù)。喚醒詞服務(wù)運(yùn)行的模型比語音助理服務(wù)模型更小。因此,讓喚醒詞服務(wù)持續(xù)運(yùn)行是有意義的,而語音助理服務(wù)只在我們需要的時(shí)候啟動(dòng)。
你可以從鏈接https://github.com/sebastiengilbert73/wakeword_service處找到喚醒詞服務(wù)代碼。
克隆完項(xiàng)目后,轉(zhuǎn)到路徑…/wakeword_service/server下,并將文件wakeword_service_gui_config.xml.example重命名為wakeword.service_gui-config.xml。
然后,將另一個(gè)文件command.bat.example重命名為command.bat。這里,您需要編輯一個(gè)文件command.bat,以便虛擬環(huán)境激活和對voice_assistant_service.py的調(diào)用與您的目錄結(jié)構(gòu)相對應(yīng)。
您可以通過以下調(diào)用來啟動(dòng)服務(wù):
python gui.py
喚醒詞檢測服務(wù)的核心是openwakeword項(xiàng)目(https://github.com/dscripka/openWakeWord)。在幾個(gè)喚醒詞模型中,我選擇了“hey jarvis”模型。我發(fā)現(xiàn)簡單地說“Jarvis?”就會(huì)觸發(fā)檢測。
每當(dāng)檢測到喚醒字時(shí),就會(huì)調(diào)用如配置文件的<command_on_wakeword>元素中所指定的一個(gè)命令文件。在我們的例子中,command.bat文件激活虛擬環(huán)境并啟動(dòng)語音助理服務(wù)。
喚醒詞檢測服務(wù)GUI的配置文件(作者本人提供的圖片)
如果您想將喚醒詞檢測服務(wù)用于其他用途的話,可以編輯一下command.bat文件,使其啟動(dòng)您想要啟動(dòng)的任何程序即可。
當(dāng)檢測到喚醒詞時(shí),喚醒詞檢測服務(wù)會(huì)發(fā)出兩聲蜂鳴聲音頻信號,指示其已被觸發(fā)。這種快速反饋告訴用戶,他們必須等待,直到文本到語音和語音到文本模型加載到計(jì)算機(jī)的GPU中,這可能需要幾秒鐘的時(shí)間。當(dāng)兩種型號都加載后,語音助理服務(wù)會(huì)播放問候語,對話就可以開始了。會(huì)話結(jié)束后,語音助理服務(wù)終止,喚醒詞檢測服務(wù)發(fā)出另一個(gè)兩聲蜂鳴聲信號。
當(dāng)上述三個(gè)組件都安裝并測試完成后,我們就可以啟動(dòng)聊天和喚醒詞檢測服務(wù)。喚醒詞檢測服務(wù)將不斷收聽麥克風(fēng)。當(dāng)檢測到喚醒詞(“Jarvis?”)時(shí),它將啟動(dòng)語音助理服務(wù)。然后,你可以大聲提問并得到口頭回答。當(dāng)檢測到會(huì)話結(jié)束語(“Thank you and goodbye”)時(shí),語音助理服務(wù)將結(jié)束。
與助理互動(dòng)的示例
以下是與語音助理交互的示例:
“Jarvis?” [嘟嘟]
[語音助手模型加載時(shí)保持幾秒鐘的靜音]
“Hello! How can I help you?”
[中文意思]“你好,我能幫你什么?”
“What are Saturn’s rings made of?”
[中文意思]“土星環(huán)是由什么組成的?”
“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.”
[中文意思]“土星環(huán)主要由冰顆粒組成,大部分由水冰組成。然而,環(huán)中也有少量的其他冰,如氨冰和巖石碎片。環(huán)的確切組成取決于與土星的距離,內(nèi)環(huán)密度更大,由更小的顆粒組成,而外環(huán)則更為分散并含有更大的冰粒?!?/span>
“Tell me the plot of the movie ‘Back to the Future’.”
[中文意思]“告訴我電影《回到未來》的情節(jié)。”
“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的故事,他意外地被一輛由他古怪的科學(xué)家朋友Doc Brown駕駛的穿越DeLorean的汽車帶回了1955年。Marty必須應(yīng)對過去的挑戰(zhàn),同時(shí)努力修復(fù)對現(xiàn)在的傷害,防止他十幾歲的母親愛上他十多歲的父親。一路上,Marty與年輕版的Doc Brown交上了朋友,并幫助他克服了一場個(gè)人悲劇。這部電影探討了命運(yùn)、家庭以及改變過去的后果等主題。”
“Thank you and goodbye”
[中文意思]“謝謝你,再見”
“Goodbye” [嘟嘟]
結(jié)論
在本文的項(xiàng)目中,我們實(shí)現(xiàn)了一個(gè)由喚醒詞檢測服務(wù)、語音助理服務(wù)和聊天服務(wù)組成的語音助理系統(tǒng)。這些組件中的每一個(gè)都是可用于其他項(xiàng)目的獨(dú)立構(gòu)建組件。
在我開發(fā)這個(gè)語音助理時(shí)遇到的許多驚喜中,最讓我印象深刻的是語音到文本轉(zhuǎn)換的質(zhì)量。如果你和我一樣,你可能也遇到過自動(dòng)語音識別系統(tǒng)無法轉(zhuǎn)錄簡單命令(如“調(diào)低音量”)的問題!其實(shí),我已經(jīng)預(yù)計(jì)到語音到文本的轉(zhuǎn)換將成為整個(gè)項(xiàng)目開發(fā)的主要障礙。在嘗試了一些不很令人滿意的模型后,我登陸到模型facebook/seamless-m4t-v2-lage(https://huggingface.co/facebook/seamless-m4t-v2-large),此模型輸出結(jié)果的質(zhì)量給我留下了深刻的印象。我甚至可以用法語說話,神經(jīng)網(wǎng)絡(luò)會(huì)自動(dòng)將其翻譯成英語。簡直太神奇了!
最后,我希望你也能嘗試一下這個(gè)有趣的項(xiàng)目,并讓我知道你會(huì)用它做什么!
譯者介紹
朱先忠,51CTO社區(qū)編輯,51CTO專家博客、講師,濰坊一所高校計(jì)算機(jī)教師,自由編程界老兵一枚。
原文標(biāo)題:Build a Locally Running Voice Assistant,作者:Sébastien Gilbert
鏈接:https://towardsdatascience.com/build-a-locally-running-voice-assistant-2f2ead904fe9