回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页

【行空板M10扩展板】基于行空板M10的本地大模型vosk对话构建小学学科知识答疑库 简单

头像 linkdfrobot 2025.06.30 27 0

项目简介
  本项目基于行空板M10及其扩展板,结合本地开源大模型Vosk的语音识别与对话能力,构建一个面向小学学科的本地化知识答疑库系统。通过语音交互,学生可以快速获取语文、数学、英语等学科的知识解答,系统支持离线运行,保障隐私安全,同时降低对网络环境的依赖。项目整合了硬件控制、语音处理、自然语言理解等技术,为教育场景提供轻量级、低成本的智能辅助工具。
项目目标
  功能实现

    完成行空板与蓝牙音箱的无线连接,实现语音输入与输出的低延迟交互。

    部署Vosk本地语音识别模型,支持中英文语音转文本。

    构建小学学科知识库(如数学公式、古诗词解析、英语单词等),结合本地大模型生成精准答案。

    设计交互逻辑,实现“提问-识别-检索-语音回答”的完整闭环。

  教育价值

    为小学生提供即时、准确的学科答疑服务,弥补传统教育资源的时空限制。

    探索离线AI技术在教育硬件中的应用潜力,推动普惠型智能教育工具发展。
所需硬件

硬件名称数量用途说明
行空板M101块主控设备,运行语音收集与反馈
配套扩展板1套提供接口扩展,连接外设
蓝牙音箱1个语音输出(需支持A2DP协议)
笔记本电脑1台开发调试、知识库数据预处理,可做服务器



预期成果
  可演示系统

  用户通过蓝牙音箱提问(如“圆的面积公式是什么?”),行空板实时识别并返回语音答案。

  知识库覆盖小学主要学科高频问题,回答准确率≥85%。


实施步骤

  ●行空板与蓝牙音箱互联

  ●通过thonny控制行空板编写客户端程序并进行调试

  ●笔记本安装ollama,编写服务端程序并进行调试

  行空板与蓝牙音箱互联

  通过行空板jupyter服务新建终端执行 bluetoothctl 命令,进入交互模式后依次输入:

  power on # 开启蓝牙
  agent on # 启用配对代理
  scan on # 扫描设备(记录音箱MAC地址)
  pair [MAC] # 配对
  connect [MAC] # 连接
  trust [MAC] # 设为信任设备
  若以前连过多次则可以通过命令bluetoothctl paired-devices查看已连接过的蓝牙设备,然后直接使用命令connect [MAC]进行连接。
  若对行空板连接蓝牙细节不太清楚可以看
  行空板与蓝牙连接问题解决记录

  行空板连接蓝牙音箱的补充说明
  ●通过thonny控制行空板编写客户端程序并进行调试

代码
import json
import pyttsx3
import requests
import sounddevice as sd
import numpy as np
import wave
import io

ServerIP = '192.168.1.139'  #服务端IP地址       根据实际情况可以有变动
ServerPort = '5000'               #服务端使用端口  根据实际情况可以有变动
url = 'http://' + ServerIP + ':' + ServerPort

def record_audio(duration, samplerate=16000, channels=1):
    # 记录音频
    print(f"Recording for {duration} seconds...")
    audio = sd.rec(int(samplerate * duration), samplerate=samplerate, channels=channels, dtype='float32')
    sd.wait()  # 等待录音完成
    print("Recording complete.")
    return audio

def save_wave_file(filename, data, samplerate):
    # 保存音频为WAV文件
    with wave.open(filename, 'wb') as wav_file:
        wav_file.setnchannels(1)
        wav_file.setsampwidth(2)
        wav_file.setframerate(samplerate)
        wav_file.writeframes((data * 32767).astype(np.int16).tobytes())


def send_audio(audio_data, samplerate):
    # 将音频数据转换为WAV格式并发送到服务器
    audio_bytes = io.BytesIO()
    with wave.open(audio_bytes, 'wb') as wav_file:
        wav_file.setnchannels(1)
        wav_file.setsampwidth(2)
        wav_file.setframerate(samplerate)
        wav_file.writeframes((audio_data * 32767).astype(np.int16).tobytes())

    audio_bytes.seek(0)
    files = {'file': ('audio.wav', audio_bytes, 'audio/wav')}

    # 发送请求并打印响应
    response = requests.post(url+'/upload', files=files)
    print("Status Code:", response.status_code)
    print("Response Content:", response.content)

    # 尝试解析 JSON 响应
    try:
        result = response.json()
    except json.JSONDecodeError:
        result = "JSON decode error"

    return result

def inferMeaning(message):
    data = {'message': message}
    response = requests.post(url + '/chat', json=data)
    #print("inferMeaning:",response)
    res_con_text = response.content.decode('utf-8')
    #print("response.content:",res_con_text)
    con_pos_s = res_con_text.find("content=")
    con_pos_e = res_con_text.find("', thinking=")
    #print("con_pos_s:",con_pos_s)
    #print("con_pos_e:",con_pos_e)
    res_con_text = res_con_text[con_pos_s+len("content="):con_pos_e]
    return res_con_text

if __name__ == '__main__':
    while True:
        try:
            duration = 5  # 录音持续时间(秒)
            audio_data = record_audio(duration)
            result = send_audio(audio_data, 16000)
            #print("__name__ Recognition Result:", result)
            message_to_send = result['result'].replace('\n','').replace(' ','')
            message = json.loads(message_to_send)['text']
            #print("__name__ :",message)
            #message = input("Please enter your message: ")
            response = inferMeaning(message)
            #print("response:",response)
            if response is not None:
                #print('Assistant response:', response)
                engine = pyttsx3.init()
                engine.say(response)
                engine.runAndWait()
            else:
                print("服务端响应无效,请检查服务端是否正常工作。")
        except:
            pass

  笔记本安装ollama,编写服务端程序并进行调试

  服务端需要有较大的存储空间用来存放大模型数据,Vosk是由Alphabet的AI研究部门开发的一个开源语音识别库,它支持多种语言,包括中文、英文等,并能在多种平台上运行,如Raspberry Pi、Android、iOS等。Vosk的优势在于其高效的识别速度和良好的识别准确率,使得实时语音识别成为可能。
  相关网址如下:
  vosk官方网址
  vosk github

  ollama官方网址
  服务端需要安装的包:
  ollama、flask、vosk

代码
import ollama
from flask import Flask, request, jsonify
import vosk
import json

model_path = "vosk-model-cn-0.22"
model = vosk.Model(model_path)

app = Flask(__name__)


def getresponse(content=None):
    if content is None:
        return 'Please enter your message'


    res = ollama.chat(model="qwen2.5:0.5b", stream=False, messages=[{"role": "user", "content": content}], options={"temperature": 0})
    return res

@app.route('/chat', methods=['POST'])
def receive_message():
    data = request.json
    message = data.get('message')
    print(f"Received message: {message}")
    response = getresponse(message)
    #print("type(response):",type(response),response)
    #print("True or False:",hasattr(response, 'to_dict'))
    print("str(response):",str(response))
    return str(response)
    

@app.route('/upload', methods=['POST'])
def upload_file():
    if 'file' not in request.files:
        return jsonify({'error': 'No file part'}), 400
    file = request.files['file']
    if file.filename == '':
        return jsonify({'error': 'No selected file'}), 400
    if file:
        # 使用 vosk 处理音频文件
        rec = vosk.KaldiRecognizer(model, 16000)
        data = file.read()
        if rec.AcceptWaveform(data):
            result = rec.Result()
            return jsonify({'result': result}), 200
        else:
            return jsonify({'error': 'Recognition failed'}), 500
    return jsonify({'error': 'File upload failed'}), 500

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)  # 监听所有网络接口

  项目感想
  技术挑战:本地大模型在行空板上的性能优化(如内存占用、响应速度)是核心难点,需通过模型剪裁和量化解决。需要后期予以细节调试实现

  教育意义:离线AI工具能有效保护学生隐私,避免数据云端传输风险,符合教育信息化安全趋势。

  扩展性:未来可加入多模态交互(如屏幕显示图解),或对接学校教材数据库深化内容覆盖。

评论

user-avatar