流式生成阶段总结API文档

本文档描述了如何使用流式生成阶段总结API调用AI生成会员的阶段训练总结,并以流式方式实时返回生成的内容。

API概述

流式生成阶段总结API提供了调用AI生成会员阶段训练总结的功能,并以流式方式实时返回生成的内容,可以用于教练或会员在阶段结束后自动生成训练效果的总结报告,并提供更好的用户体验。

接口详情

流式生成阶段总结

POST /gym/member/stream_stage_summary

调用AI生成指定阶段的总结内容,并以流式方式实时返回生成的内容。

请求参数

参数名 类型 必填 描述
stage_id Integer 阶段ID

响应格式

API返回Server-Sent Events (SSE)格式的流式数据,每个事件包含以下JSON数据:

{
    "text": "生成的文本块",  // 生成的文本块,如果为空字符串且done为true,表示生成完成
    "done": true/false     // 可选,如果为true,表示生成完成
}

错误码说明

错误码 描述
400 请求参数错误,如缺少必要参数或评估记录不足
404 未找到指定阶段
500 服务器内部错误

示例请求

POST /gym/member/stream_stage_summary
Content-Type: application/x-www-form-urlencoded

stage_id=123

使用说明

调用此API后,服务器会以流式方式实时返回AI生成的内容,客户端可以逐块显示这些内容,提供更好的用户体验。

注意:要使用此API,阶段必须至少有2条体适能评估记录,否则将返回错误。

生成完成后,客户端可以调用update_stage_summary API将完整的总结内容保存到阶段记录中。

使用示例

JavaScript示例(使用EventSource)

// 使用EventSource接收流式数据
function streamStageSummary(stageId, accessToken) {
    // 创建结果容器
    const resultContainer = document.getElementById('result-container');
    resultContainer.innerHTML = '';
    
    // 完整的总结内容
    let fullSummary = '';
    
    // 创建EventSource
    const url = `/gym/member/stream_stage_summary?stage_id=${stageId}&access_token=${accessToken}`;
    const eventSource = new EventSource(url);
    
    // 处理消息
    eventSource.onmessage = function(event) {
        try {
            const data = JSON.parse(event.data);
            
            // 检查是否完成
            if (data.done === true) {
                console.log('生成完成');
                eventSource.close();
                
                // 可以在这里调用update_stage_summary API保存总结
                saveStageSummary(stageId, fullSummary);
                return;
            }
            
            // 检查是否有错误
            if (data.error) {
                console.error('生成错误:', data.error);
                resultContainer.innerHTML += `

${data.error}

`; eventSource.close(); return; } // 显示文本块 if (data.text) { fullSummary += data.text; resultContainer.innerHTML = fullSummary; // 滚动到底部 resultContainer.scrollTop = resultContainer.scrollHeight; } } catch (e) { console.error('解析事件数据出错:', e); } }; // 处理错误 eventSource.onerror = function(error) { console.error('EventSource错误:', error); resultContainer.innerHTML += '

连接错误,请重试

'; eventSource.close(); }; } // 保存总结内容 async function saveStageSummary(stageId, summary) { try { const response = await fetch('/gym/member/update_stage_summary', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + accessToken }, body: JSON.stringify({ stage_id: stageId, summary: summary }) }); const data = await response.json(); if (data.error === 0) { console.log('阶段总结保存成功:', data.message); } else { console.error('保存失败:', data.message); } } catch (error) { console.error('保存请求出错:', error); } }

使用fetch API的替代方法

// 使用fetch API接收流式数据
async function streamStageSummaryWithFetch(stageId, accessToken) {
    // 创建结果容器
    const resultContainer = document.getElementById('result-container');
    resultContainer.innerHTML = '';
    
    // 完整的总结内容
    let fullSummary = '';
    
    try {
        // 发送请求
        const response = await fetch(`/gym/member/stream_stage_summary?stage_id=${stageId}&access_token=${accessToken}`, {
            method: 'POST'
        });
        
        // 获取reader
        const reader = response.body.getReader();
        const decoder = new TextDecoder();
        
        // 读取数据
        while (true) {
            const { value, done } = await reader.read();
            
            if (done) {
                console.log('流读取完成');
                break;
            }
            
            // 解码数据
            const chunk = decoder.decode(value, { stream: true });
            
            // 处理SSE格式的数据
            const lines = chunk.split('\n\n');
            for (const line of lines) {
                if (line.startsWith('data: ')) {
                    try {
                        const data = JSON.parse(line.substring(6));
                        
                        // 检查是否有错误
                        if (data.error) {
                            console.error('生成错误:', data.error);
                            resultContainer.innerHTML += `

${data.error}

`; return; } // 检查是否完成 if (data.done === true) { console.log('生成完成'); // 可以在这里调用update_stage_summary API保存总结 saveStageSummary(stageId, fullSummary); return; } // 显示文本块 if (data.text) { fullSummary += data.text; resultContainer.innerHTML = fullSummary; // 滚动到底部 resultContainer.scrollTop = resultContainer.scrollHeight; } } catch (e) { console.error('解析事件数据出错:', e); } } } } } catch (error) { console.error('请求出错:', error); resultContainer.innerHTML += '

连接错误,请重试

'; } }

Python示例

import requests
import json
import sseclient  # 需要安装 sseclient-py 包

def stream_stage_summary(stage_id, access_token):
    """
    流式生成阶段总结
    
    Args:
        stage_id: 阶段ID
        access_token: 访问令牌
    """
    url = f'http://your-domain.com/gym/member/stream_stage_summary?stage_id={stage_id}'
    
    headers = {
        'Accept': 'text/event-stream',
        'Authorization': f'Bearer {access_token}'
    }
    
    # 发送请求
    response = requests.post(url, headers=headers, stream=True)
    
    # 创建SSE客户端
    client = sseclient.SSEClient(response)
    
    # 完整的总结内容
    full_summary = ''
    
    # 处理事件
    try:
        for event in client.events():
            try:
                data = json.loads(event.data)
                
                # 检查是否有错误
                if 'error' in data:
                    print(f"生成错误: {data['error']}")
                    break
                
                # 检查是否完成
                if data.get('done', False):
                    print("生成完成")
                    
                    # 可以在这里调用update_stage_summary API保存总结
                    save_stage_summary(stage_id, full_summary, access_token)
                    break
                
                # 显示文本块
                if 'text' in data and data['text']:
                    full_summary += data['text']
                    print(data['text'], end='', flush=True)
                    
            except json.JSONDecodeError:
                print(f"解析事件数据出错: {event.data}")
                
    except Exception as e:
        print(f"流处理错误: {str(e)}")
    
    return full_summary

def save_stage_summary(stage_id, summary, access_token):
    """
    保存阶段总结
    
    Args:
        stage_id: 阶段ID
        summary: 总结内容
        access_token: 访问令牌
    """
    url = 'http://your-domain.com/gym/member/update_stage_summary'
    
    headers = {
        'Content-Type': 'application/json',
        'Authorization': f'Bearer {access_token}'
    }
    
    data = {
        'stage_id': stage_id,
        'summary': summary
    }
    
    response = requests.post(url, json=data, headers=headers)
    
    if response.status_code == 200:
        result = response.json()
        if result['error'] == 0:
            print(f"阶段总结保存成功: {result['message']}")
            return result
        else:
            print(f"保存失败: {result['message']}")
            raise Exception(result['message'])
    else:
        print(f"请求失败,状态码: {response.status_code}")
        raise Exception(f"请求失败,状态码: {response.status_code}")

# 调用示例
try:
    summary = stream_stage_summary(
        stage_id=123,
        access_token='your-access-token'
    )
    print(f"\n完整总结:\n{summary}")
except Exception as e:
    print(f"流式生成阶段总结失败: {str(e)}")