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. 实现适当的加载状态提示  |