"""
语音交互式DeepSeek问答系统
通过语音输入调用DeepSeek API回答问题
"""
import json
import os
from vosk import Model, KaldiRecognizer
import pyaudio
import requests
import mysql.connector
from mysql.connector import Error
from datetime import datetime
from api.config import API_CONFIGS
from doubaotts.doubaotts import VolcanoTTS
# 初始化语音识别
model_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'model', 'vosk-model-cn-0.22', 'vosk-model-cn-0.22')
model = Model(model_path)
rec = KaldiRecognizer(model, 16000)
p = pyaudio.PyAudio()
# 本地ollama模型配置
ollama_model = "deepseek-r1:7b"
# 初始化音频输入
def init_audio():
# 列出可用音频设备
for i in range(p.get_device_count()):
print(p.get_device_info_by_index(i))
# 使用默认输入设备
stream = p.open(format=pyaudio.paInt16,
channels=1,
rate=16000,
input=True,
frames_per_buffer=8000,
input_device_index=None)
stream.start_stream()
return stream
# 调用本地ollama模型
def ask_deepseek(question):
try:
# 检查是否是数据库查询指令
if question.strip().lower().startswith("查询数据库:"):
parts = question[len("查询数据库:"):].strip().split("|")
if len(parts) == 2:
db_name = parts[0].strip()
query = parts[1].strip()
result = query_other_db(db_name, query)
if result is not None:
return f"查询结果:\n{json.dumps(result, indent=2, ensure_ascii=False)}"
else:
return "查询失败,请检查数据库名称和查询语句"
else:
return "查询格式错误,请使用'查询数据库:数据库名|SQL查询语句'格式"
# 普通问题处理
response = requests.post(
"http://localhost:11434/api/generate",
json={
"model": ollama_model,
"prompt": question,
"stream": False
}
)
if response.status_code == 200:
return response.json()['response'].split('\n')[-1] # 只返回最后一行结果
else:
return f"ollama模型错误: {response.status_code}"
except Exception as e:
return f"调用ollama模型时发生错误: {str(e)}"
# 初始化MySQL连接
def init_db():
try:
# 从配置中获取数据库连接参数
db_config = API_CONFIGS['mysql']
connection = mysql.connector.connect(
host=db_config['host'],
database=db_config['database'],
user=db_config['user'],
password=db_config['password'],
port=db_config['port'],
charset=db_config['charset'],
connection_timeout=db_config['connection_timeout']
)
if connection.is_connected():
# 创建对话记录表
cursor = connection.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS conversations (
id INT AUTO_INCREMENT PRIMARY KEY,
question TEXT NOT NULL,
answer TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""")
connection.commit()
return connection
except Error as e:
print(f"数据库连接错误: {e}")
return None
# 查询其他MySQL数据库
def query_other_db(database_name, query):
try:
# 从配置中获取基础连接参数
db_config = API_CONFIGS['mysql']
connection = mysql.connector.connect(
host=db_config['host'],
database=database_name,
user=db_config['user'],
password=db_config['password'],
port=db_config['port'],
charset=db_config['charset'],
connection_timeout=db_config['connection_timeout']
)
if connection.is_connected():
cursor = connection.cursor(dictionary=True)
cursor.execute(query)
result = cursor.fetchall()
connection.close()
return result
except Error as e:
print(f"查询数据库{database_name}错误: {e}")
return None
# 保存对话到数据库
def save_conversation(connection, question, answer):
try:
cursor = connection.cursor()
query = "INSERT INTO conversations (question, answer) VALUES (%s, %s)"
cursor.execute(query, (question, answer))
connection.commit()
except Error as e:
print(f"保存对话失败: {e}")
# 主程序
def main():
# 初始化数据库连接
db_connection = init_db()
if not db_connection:
print("警告: 无法连接到数据库,对话将不会被保存")
stream = init_audio()
print("请说出您的问题(按Ctrl+C退出)...")
try:
question = "" # 初始化question变量
while True:
try:
data = stream.read(4000, exception_on_overflow=False)
if len(data) == 0:
break
if rec.AcceptWaveform(data):
result = json.loads(rec.Result())
question = result['text']
if question.strip():
print(f"您的问题: {question}")
answer = ask_deepseek(question)
print(f"DeepSeek回答: {answer}")
# 语音播报回答
from voice_management.voice_manager import VoiceManager
voice_manager = VoiceManager()
voice_manager.create_voice(answer)
# 保存对话到数据库
if db_connection:
save_conversation(db_connection, question, answer)
question = "" # 重置question变量避免重复处理
else:
partial = json.loads(rec.PartialResult())
if 'partial' in partial:
print(f"正在识别: {partial['partial']}", end='\r')
except OSError as e:
if e.errno == -9981: # Input overflowed
continue
else:
raise
except KeyboardInterrupt:
print("\n程序结束")
finally:
try:
if stream.is_active():
stream.stop_stream()
if not stream._closed:
stream.close()
except:
pass
p.terminate()
# 关闭数据库连接
if db_connection and db_connection.is_connected():
db_connection.close()
if __name__ == "__main__":
main()能正常运行但是无法自动播放音频
最新发布