222 lines
5.3 KiB
Markdown
222 lines
5.3 KiB
Markdown
# 流式聊天 API 文档
|
||
|
||
## 概述
|
||
该 API 提供实时流式聊天功能,支持文本对话和语音合成。API 使用 Server-Sent Events (SSE) 实现流式响应,确保实时性和高效性。
|
||
|
||
## 基础信息
|
||
- 基础URL: `http://your-domain:8080`
|
||
- 内容类型: `application/json`
|
||
- 响应类型: `text/event-stream` (流式响应)
|
||
|
||
## API 端点
|
||
|
||
### 1. 聊天接口
|
||
```
|
||
POST /chat
|
||
```
|
||
|
||
#### 请求参数
|
||
| 参数名 | 类型 | 必填 | 描述 |
|
||
|--------|------|------|------|
|
||
| query | string | 是 | 用户输入的查询文本 |
|
||
| response_mode | string | 是 | 响应模式,使用 "streaming" 启用流式响应 |
|
||
| user | string | 是 | 用户标识符 |
|
||
| conversation_id | string | 否 | 会话ID,首次对话可不传 |
|
||
|
||
#### 请求示例
|
||
```json
|
||
{
|
||
"query": "你好,请介绍一下自己",
|
||
"response_mode": "streaming",
|
||
"user": "user123",
|
||
"conversation_id": ""
|
||
}
|
||
```
|
||
|
||
#### 响应格式
|
||
响应使用 Server-Sent Events (SSE) 格式,每个事件包含以下字段:
|
||
|
||
| 字段名 | 类型 | 描述 |
|
||
|--------|------|------|
|
||
| answer | string | 机器人的文本回复 |
|
||
| isEnd | boolean | 是否为最后一条消息 |
|
||
| conversation_id | string | 会话ID |
|
||
| task_id | string | 任务ID |
|
||
| audio_data | string | 语音数据(URL或十六进制编码) |
|
||
|
||
#### 响应示例
|
||
```
|
||
data: {"answer":"你好!","isEnd":false,"conversation_id":"conv_123","task_id":"task_456","audio_data":"http://example.com/audio.mp3"}
|
||
data: {"answer":"我是AI助手","isEnd":false,"conversation_id":"conv_123","task_id":"task_456","audio_data":"http://example.com/audio2.mp3"}
|
||
data: {"answer":"","isEnd":true,"conversation_id":"conv_123","task_id":"task_456"}
|
||
```
|
||
|
||
### 2. 停止对话
|
||
```
|
||
POST /chat-messages/:task_id/stop
|
||
```
|
||
|
||
#### 路径参数
|
||
| 参数名 | 类型 | 描述 |
|
||
|--------|------|------|
|
||
| task_id | string | 要停止的任务ID |
|
||
|
||
#### 响应示例
|
||
```json
|
||
{
|
||
"status": "success",
|
||
"message": "Conversation stopped"
|
||
}
|
||
```
|
||
|
||
### 3. 删除对话
|
||
```
|
||
DELETE /conversations/:conversation_id
|
||
```
|
||
|
||
#### 路径参数
|
||
| 参数名 | 类型 | 描述 |
|
||
|--------|------|------|
|
||
| conversation_id | string | 要删除的会话ID |
|
||
|
||
#### 查询参数
|
||
| 参数名 | 类型 | 必填 | 描述 |
|
||
|--------|------|------|------|
|
||
| user | string | 是 | 用户标识符 |
|
||
|
||
#### 响应示例
|
||
```json
|
||
{
|
||
"status": "success",
|
||
"message": "Conversation deleted"
|
||
}
|
||
```
|
||
|
||
## 前端集成示例
|
||
|
||
### 1. 基本使用
|
||
```javascript
|
||
async function sendMessage(message) {
|
||
const response = await fetch('/chat', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify({
|
||
query: message,
|
||
response_mode: 'streaming',
|
||
user: 'user123',
|
||
conversation_id: currentConversationId
|
||
})
|
||
});
|
||
|
||
const reader = response.body.getReader();
|
||
const decoder = new TextDecoder();
|
||
|
||
while (true) {
|
||
const { value, done } = await reader.read();
|
||
if (done) break;
|
||
|
||
const chunk = decoder.decode(value);
|
||
const lines = chunk.split('\n');
|
||
|
||
for (const line of lines) {
|
||
if (line.startsWith('data: ')) {
|
||
const data = JSON.parse(line.slice(6));
|
||
// 处理响应数据
|
||
handleResponse(data);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2. 处理响应数据
|
||
```javascript
|
||
function handleResponse(data) {
|
||
// 更新会话ID
|
||
if (data.conversation_id) {
|
||
currentConversationId = data.conversation_id;
|
||
}
|
||
|
||
// 处理文本回复
|
||
if (data.answer) {
|
||
updateChatMessage(data.answer);
|
||
}
|
||
|
||
// 处理语音数据
|
||
if (data.audio_data) {
|
||
playAudio(data.audio_data);
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3. 播放音频
|
||
```javascript
|
||
function playAudio(audioData) {
|
||
// URL格式的音频
|
||
if (audioData.startsWith('http')) {
|
||
const audio = new Audio(audioData);
|
||
audio.play();
|
||
}
|
||
// 十六进制编码的音频
|
||
else {
|
||
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
||
const audioDataArray = new Uint8Array(
|
||
audioData.match(/.{1,2}/g).map(byte => parseInt(byte, 16))
|
||
);
|
||
|
||
audioContext.decodeAudioData(audioDataArray.buffer, (buffer) => {
|
||
const source = audioContext.createBufferSource();
|
||
source.buffer = buffer;
|
||
source.connect(audioContext.destination);
|
||
source.start(0);
|
||
});
|
||
}
|
||
}
|
||
```
|
||
|
||
## 错误处理
|
||
|
||
### 常见错误码
|
||
| 状态码 | 描述 |
|
||
|--------|------|
|
||
| 400 | 请求参数错误 |
|
||
| 401 | 未授权 |
|
||
| 500 | 服务器内部错误 |
|
||
|
||
### 错误响应格式
|
||
```json
|
||
{
|
||
"error": "错误描述信息"
|
||
}
|
||
```
|
||
|
||
## 最佳实践
|
||
|
||
1. **会话管理**
|
||
- 保存 `conversation_id` 以维持对话上下文
|
||
- 在对话结束时清理资源
|
||
|
||
2. **错误处理**
|
||
- 实现重试机制
|
||
- 优雅处理网络错误
|
||
- 提供用户友好的错误提示
|
||
|
||
3. **性能优化**
|
||
- 使用缓冲通道处理流式数据
|
||
- 及时清理不需要的音频资源
|
||
- 实现消息队列避免并发问题
|
||
|
||
4. **安全性**
|
||
- 验证用户身份
|
||
- 使用 HTTPS
|
||
- 实现请求频率限制
|
||
|
||
## 注意事项
|
||
|
||
1. 确保正确处理 SSE 连接的关闭
|
||
2. 实现适当的错误重试机制
|
||
3. 注意音频资源的及时释放
|
||
4. 考虑网络延迟和断线重连
|
||
5. 实现适当的加载状态提示 |