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