基于讯飞开放平台的全栈智能聊天机器人,支持文字对话、语音输入和语音输出。
- 💬 文字对话:接入讯飞星火大模型 v3.5,支持多轮上下文记忆
- 🎤 语音输入:浏览器麦克风采集 → 后端 STT 转写 → 自动发送
- 🔊 语音输出:机器人回复通过 TTS 合成为语音,在浏览器中播放
- 🔌 连接状态:WebSocket 断线自动重连,状态栏实时提示
- 📱 响应式设计:支持桌面端和移动端浏览器
pj/
├── server/ # FastAPI 后端
│ ├── main.py # 入口:创建应用 + CORS + 路由注册
│ ├── routers/
│ │ ├── chat_ws.py # WS /ws/chat — LLM 流式多轮对话
│ │ ├── stt_api.py # POST /api/stt — 语音识别(STT)
│ │ └── tts_ws.py # WS /ws/tts — 流式语音合成(TTS)
│ ├── services/
│ │ ├── spark_service.py # 讯飞星火 LLM v3.5 封装
│ │ ├── iat_service.py # 讯飞语音听写(IAT)封装
│ │ └── tts_service.py # 讯飞语音合成(TTS)封装
│ └── tests/ # 后端 pytest 测试
├── client/ # React 前端
│ └── src/
│ ├── components/
│ │ ├── chat/ # ChatHeader, ChatInput, MessageBubble, MessageList
│ │ ├── audio/ # AudioPlayButton(TTS 播放控制)
│ │ ├── voice/ # VoiceInput(麦克风录音按钮)
│ │ └── layout/ # Sidebar, MainPanel, ConnectionBanner
│ ├── stores/ # Zustand 状态管理(chat, audio, connection)
│ ├── hooks/ # useAudioPlayer, useMediaRecorder
│ ├── services/ # api.ts(REST 请求), wsClient.ts(WebSocket 连接)
│ └── __tests__/ # Vitest 前端测试
└── docs/ # 设计文档 + 开发文档
| 依赖 | 版本 |
|---|---|
| Python | 3.10+ |
| Node.js | 18+ |
| npm | 9+ |
在 讯飞开放平台 注册并创建应用,获取:
APP_IDAPI_KEYAPI_SECRET
在项目根目录创建 .env 文件(已在 .gitignore 中,不会提交到 Git):
APP_ID=你的APP_ID
API_KEY=你的API_KEY
API_SECRET=你的API_SECRET# Python 依赖
pip install fastapi uvicorn python-multipart python-dotenv \
spark-ai-python xfyunsdkspeech PyAudio \
websockets websocket-client
# 启动后端(支持热重载)
uvicorn server.main:app --reload --host 0.0.0.0 --port 8000验证:访问 http://localhost:8000/api/health,应返回 {"status":"ok"}。
cd client
npm install
npm run dev访问 http://localhost:5173
| 功能 | 协议 | 端点 | 说明 |
|---|---|---|---|
| LLM 对话 | WebSocket | /ws/chat |
流式多轮对话,逐 token 推送 |
| 语音合成 | WebSocket | /ws/tts |
流式 TTS,逐块推送 PCM 音频 |
| 语音识别 | REST | POST /api/stt |
上传 PCM 音频,返回识别文本 |
| 健康检查 | REST | GET /api/health |
返回 {"status":"ok"} |
输入(客户端 → 服务端,JSON):
{
"type": "message",
"content": "你好,请介绍一下自己",
"history": [
{"role": "user", "content": "你好"},
{"role": "assistant", "content": "你好!有什么可以帮助你的?"}
]
}| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
type |
string | 是 | "message" 发送消息 / "cancel" 取消生成 |
content |
string | type=message 时必填 | 用户消息,最长 2000 字符 |
history |
object[] | 否 | 对话历史,每条含 role 和 content |
输出(服务端 → 客户端,JSON):
{"type": "token", "content": "我"} // 流式 token,逐字推送
{"type": "done"} // 生成完成
{"type": "error", "message": "..."} // 错误(消息为通用文案)输入:
Content-Type: application/octet-stream
Body: PCM 16kHz 16bit 单声道 little-endian 原始音频字节
- 最大 10 MB(约 5 分钟音频)
- 音频来源:浏览器
MediaRecorder→ 前端转 PCM
输出:
{"text": "识别出的文本"}- 识别失败或无语音时返回
{"text": ""}
输入(客户端 → 服务端,JSON):
{"type": "synthesize", "text": "要合成的文本"}输出(服务端 → 客户端):
<binary frame> // PCM 16kHz 16bit 单声道音频块(多次推送)
{"type": "done"} // 合成完成
{"type": "error", "message": "TTS 合成失败"}
所有音频接口统一使用以下格式:
| 参数 | 值 |
|---|---|
| 编码 | PCM 16bit 有符号整数 |
| 采样率 | 16000 Hz |
| 声道数 | 1(单声道) |
| 字节序 | little-endian |
# ===== 后端 =====
uvicorn server.main:app --reload --host 0.0.0.0 --port 8000 # 启动(热重载)
python -m pytest server/tests/ -v # 运行所有测试
python -m pytest server/tests/test_chat_ws.py -v # 运行单个测试
# ===== 前端 =====
cd client
npm run dev # 启动开发服务器
npm test # 运行测试(Vitest)
npx tsc --noEmit # TypeScript 类型检查
npm run build # 生产构建
npm run lint # Lint 检查(oxlint)| 层 | 技术 | 版本 |
|---|---|---|
| 前端框架 | React + TypeScript | 19 / 6 |
| 构建工具 | Vite | 8 |
| 状态管理 | Zustand | 5 |
| 样式 | Tailwind CSS | 4 |
| 测试 | Vitest + Testing Library | — |
| 后端框架 | FastAPI | — |
| LLM | 讯飞星火 Spark v3.5 | spark-ai-python |
| 语音识别 | 讯飞 IAT | xfyunsdkspeech |
| 语音合成 | 讯飞 TTS | xfyunsdkspeech |