91视频免费?看_蜜芽MY188精品TV在线观看_国产免费无遮挡在线观看视频_深夜国产_亚洲精品欧洲精品_欧美黑人粗暴多交

  • 回復
  • 收藏
  • 點贊
  • 分享
  • 發新帖

【 DigiKey DIY原創大賽】在嵌入式終端上基于本地大模型實現的離線語音聊天機器人(1)

引言

今年上半年,我曾在基于RK3566的嵌入式開發板上本地部署并運行大模型,當時僅能在終端界面使用文字進行交互,而我的進一步目標是實現本地的大模型語音交互。但限于我手里的開發板內存不足,無法加載本地的語音識別模型,同時經費有限,只能暫時擱置。下半年,遇到電源網和得捷舉辦DIY活動,提供600元的經費報銷,使得該項目得以繼續。

本文將介紹在嵌入式終端上,基于本地大模型實現的多語言離線語音聊天機器人。其中,語音識別、大模型推理、文字轉語音(TTS)都是在嵌入式終端基于本地模型實現的,無需接入互聯網環境。

特點

-基于嵌入式終端實現

-無需聯網,完全離線運行

-多語言支持(中、英)

-代碼開源,模型易部署及更換

硬件環境

-Raspberry Pi 5(quad-core Arm Cortex A76 processor @ 2.4GHz, 8GB RAM)

-WM8960 音頻模塊

-2寸LCD主屏+ 0.96寸OLED雙副屏

軟件及模型

-Python: 3.11.2

-推理框架:llama-cpp-python

-語音識別:SenseVoice大模型

-推理模型:千問大模型

-文本轉語音:Piper TTS

整體框架

(按要求使用Scheme-it繪制)

環境準備

安裝llama推理框架

直接用pip安裝:

pip install llama-cpp-python

安裝SenseVoice依賴

在SenseVoice的Github倉庫,提供了requirements.txt。如果是直接使用我提供的源碼,無需拉取SenseVoice倉庫,requirements.txt存放于\models\SenseVoiceSmall目錄。使用pip安裝必要的依賴:

pip install -r requirements.txt

安裝Piper TTS

Piper TTS是我目前找到的較優離線TTS,語音接近人聲,加載速度快,完全離線運行。它無需特別安裝,只需要下載編譯好的二進制可執行文件,即可使用,我提供的源碼已經直接包含,存放于\piper目錄。

特別說明:上述安裝截圖中pip安裝含有--break-system-packages選項,這是我的系統Python結構的原因,在其它系統Python環境下,可能是不需要的。

安裝音頻及顯示驅動

本文使用的音頻及顯示模塊,均來自微雪電子,可直接參考對應模塊的教程,進行驅動安裝即可,如有問題,可聯系其技術支持。

-WM8960音頻模塊驅動安裝

-LCD+OLED三聯屏顯示驅動安裝

獲取本項目源碼

-獲取項目源碼:

   本項目完整源碼,通過gitee開源,可通過git拉取

-放置模型文件:

   受限于git倉庫對單個文件的大小的限制,兩個較大的模型文件單獨提供網盤下載

注:源碼網址見文末

代碼說明

線程結構

本項目代碼主要由多個線程組成,包含按鍵線程、錄音線程、語音識別線程、模型推理線程、文字轉語音線程、顯示線程等,各線程通過事件進行觸發并流轉運作。

主要線程代碼

Key線程

Device.pin_factory = LGPIOFactory()
# key init
key2 = Button(17)
def key2_pressed():
    start_record_event.set()
    stop_tts_event.set()
    show_record_event.set()
def key2_released():
    stop_record_event.set()
    model_doing_event.set()
    stop_tts_event.clear()
    show_record_event.clear()
# Bind key press event
key2.when_pressed = key2_pressed
key2.when_released = key2_released

該線程主要監聽按鍵的按下和釋放事件,以觸發語音錄制及識別等相關動作。

錄音線程

def recording_thread():
    while True:
        start_record_event.wait()
        start_record_event.clear()
        device = "default"
        wavfile = wave.open(f"{current_dir}/record.wav", "wb")
        mic = alsaaudio.PCM(
            alsaaudio.PCM_CAPTURE,
            alsaaudio.PCM_NONBLOCK,
            channels=1,
            rate=44100,
            format=alsaaudio.PCM_FORMAT_S16_LE,
            periodsize=160,
            device=device,
        )
        wavfile.setnchannels(1)
        wavfile.setsampwidth(2)  # PCM_FORMAT_S16_LE
        wavfile.setframerate(44100)
        print("Start speaking...")
        time_start = datetime.now()
        while True:
            if stop_record_event.is_set():
                stop_record_event.clear()
                time_stop = datetime.now()
                print("Stop speaking...")
                wavfile.close()
                if time_stop.timestamp() - time_start.timestamp() >= 1:
                    trig_sensevoice_event.set()
                else:
                    print("The speaking time is too short")
                    model_doing_event.clear()
                break
                # Read data from device
            l, data = mic.read()
            if l:
                wavfile.writeframes(data)
                time.sleep(0.001)

錄音線程,在KEY按下后被觸發執行循環錄制,KEY釋放后退出錄制。此處還做了簡單的錄音時長的判斷,因為當錄音時長過短時,后續的語音識別可能會報錯。

語音識別線程

def sensevoice_thread():
    from model import SenseVoiceSmall
    from funasr.utils.postprocess_utils import rich_transcription_postprocess

    model_dir = f"{current_dir}/models/SenseVoiceSmall"
    m, kwargs = SenseVoiceSmall.from_pretrained(model=model_dir, device="cuda:0")
    m.eval()
    senvc_load_done.set()
    print("Load sensevoice model done")

    while True:
        trig_sensevoice_event.wait()
        trig_sensevoice_event.clear()
        res = m.inference(
            data_in=f"{current_dir}/record.wav",
            language="auto",  # "zh", "en", "yue", "ja", "ko", "nospeech"
            use_itn=False,
            ban_emo_unk=False,
            **kwargs,
        )

        text = rich_transcription_postprocess(res[0][0]["text"])
        ask_text_q.put(text)
        trig_llama_event.set()

在錄音線程正常執行完成后,觸發執行語音識別線程。SenseVoice語音識別使用較為簡單,可自動識別多種語言,生成的文本直接放置到消息隊列中,供下一步模型推理使用。模塊的初始import是較費時間的,為了不影響程序的整體加載時間,所以關于SenseVoice模塊的import處理也放置在了線程中,而不是統一放在文件的開頭

------無奈的結束分割線(受論壇帖子字數限制,后續見下一帖子)-----

http://www.laiyangyintong.cn/bbs/2778145.html

全部回復(0)
正序查看
倒序查看
現在還沒有回復呢,說說你的想法
主站蜘蛛池模板: 寿光市| 尼勒克县| 澜沧| 大悟县| 海宁市| 灯塔市| 长葛市| 滕州市| 乐东| 都兰县| 东兴市| 安远县| 江川县| 梁河县| 汨罗市| 伊宁市| 砀山县| 化隆| 宁陕县| 吴川市| 连城县| 桐庐县| 利津县| 永靖县| 广安市| 涪陵区| 库车县| 灌南县| 林芝县| 武城县| 达拉特旗| 定结县| 莆田市| 石景山区| 津市市| 岚皋县| 齐齐哈尔市| 亚东县| 卢氏县| 乌审旗| 阳新县|