FastAPI__002__通过chatTTS把大模型响应数据从文本转语言并输出(简易版)
根据您提供的代码和描述,我将为您整理一份清晰的实现步骤。这份整理严格遵循您的要求,仅对内容进行排版,不进行任何内容上的改动、补充或解释。
实现步骤
有两个文件(①main.py ②speak.py)
①main.py
导入:
import traceback
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import httpx
from speak import *
import threading
import uvicorn
说明:
这个文件的代码实现在:
FastAPI__001__使用fastapi通过ollma调用本地大模型进行POST测试中已经讲过。改动:
增加
speak.py内部函数的调用,将接收到的文本传入speak内进行文本转语音,具体如下:#使用result接收到响应数据,并将响应数据转成字典之后,添加以下代码
reply_text = result.get("response", "")
# 尝试调用 speak
print(f"准备调用 speak: {reply_text}")
# threading.Thread,用于创建一个子线程,不阻塞 HTTP 响应返回给客户端
threading.Thread(target=speak, args=(reply_text,)).start()
②speak.py
导入:
import torch
import ChatTTS
import sounddevice as sd
实现:
#实例化ChatTTS对象,
chat = ChatTTS.Chat()
#尝试调用gpu
#创建函数,接收文本
#设置发音种子
#使用infer方法生成输出
#使用sounddevice.play播放音频
sounddevice.play(audio, samplerate=24000)
#添加sounddevice.wait阻塞进程,避免函数立即返回,导致语音没有播放完毕
sd.wait()
完整代码:
main.py
1 import traceback 2 from fastapi import FastAPI, HTTPException 3 from pydantic import BaseModel 4 import httpx 5 from speak import * 6 import threading 7 import uvicorn 8 9 app = FastAPI(title="本地大模型 API") 10 11 12 class ChatRequest(BaseModel): 13 message: str 14 model: str = "qwen:0.5b" 15 stream: bool = False 16 17 18 ##路径为 /chat/,即客户端需向 http://your-server:8000/chat/ 发送 POST 请求 19 @app.post("/chat/") 20 async def chat(request: ChatRequest): 21 try: 22 async with httpx.AsyncClient(timeout=120.0) as client: 23 response = await client.post( 24 "http://localhost:11434/api/generate", 25 json={ 26 "prompt": request.message, 27 "model": request.model, 28 "stream": False 29 } 30 ) 31 32 if response.status_code != 200: 33 raise HTTPException(status_code=500, detail="Model inference failed") 34 35 result = response.json() 36 reply_text = result.get("response", "") 37 38 # 尝试调用 speak 39 print(f"准备调用 speak: {reply_text}") 40 41 # threading.Thread,用于创建一个子线程 42 #target后接的是要运行的函数,不可以传"speak()",带括号会让函数立即执行并把返回值给target 43 #args接收的值会传递给target,且值必须是一个元组 44 #这是一个链式调用,start()表示启动线程 45 threading.Thread(target=speak, args=(reply_text,)).start() 46 47 return { 48 "reply": result.get("response", ""), 49 "model": request.model, 50 "done": result.get("done", True) 51 } 52 except Exception as e: 53 # 打印完整错误堆栈 54 #返回当前异常的完整堆栈信息(字符串格式) 55 error_detail = traceback.format_exc() 56 print(f"完整错误信息:\n{error_detail}") 57 #raise 表示主动抛出一个错误信息 58 #status_code=500,表示服务器内部错误 59 #detail是返回给客户端的信息 60 raise HTTPException(status_code=500, detail=f"Error: {str(e)}") 61 62 63 64 if __name__ == "__main__": 65 uvicorn.run( 66 "main:app", 67 host="127.0.0.1", 68 port=8000, 69 reload=True # 开发时可开启自动重载 70 )
speak.py
1 import torch 2 import ChatTTS 3 import sounddevice as sd 4 5 6 print("正在加载 ChatTTS 模型...") 7 8 #开启GPU 9 device = "cuda" if torch.cuda.is_available() else "cpu" 10 print(f"当前设备: {device}") 11 12 chat = ChatTTS.Chat() 13 #选择把模型放到GPU上运行 14 chat.load(compile=False, device=device) 15 16 17 print("ChatTTS 加载完成 ✅") 18 19 20 21 def speak(text: str): # : str 表示期望接收的是一个字符串 22 try: 23 if not text.strip(): #意思是如果文本连空白字符都没有,就退出函数 24 print("空文本,跳过 TTS") 25 return 26 27 #固定发音的种子为666,每次都使用同一个声音 28 torch.manual_seed(666) 29 #infer方法是根据输出生成输出 30 wavs = chat.infer( 31 [text], 32 #表示在生成过程中使用解码器 33 use_decoder=True 34 ) 35 36 audio = wavs[0] 37 #采样率必须是 24kHz(ChatTTS 输出固定为此采样率) 38 sd.play(audio, samplerate=24000) 39 sd.wait() 40 41 print("[TTS] 播放完成") 42 43 except Exception as e: 44 print(f"[TTS ERROR] {e}")

浙公网安备 33010602011771号