深夜11点,我正在为公司的智能客服系统上线新功能,突然收到了运维告警——大量用户反馈对话中断后无法继续,聊天记录凭空消失。更糟糕的是,我们使用第三方 API 调用 GPT-4.1,每 Token 成本高达 $8/MTok,断线重连后重复生成的内容正在疯狂烧钱。

错误日志里清一色的 ConnectionError: timeout after 30000msWebSocket connection closed unexpectedly (code: 1006)。这一刻,我意识到必须为流式响应设计一套完整的断点续传与增量同步机制。

为什么流式响应需要断点续传

传统的 HTTP 短连接 API 调用遇到网络波动时,要么重试从头开始,要么直接失败。对于 AI 流式响应场景,这意味着用户在打字时突然断网,回来后发现整个对话需要重新开始——用户体验极差,同时也会造成 API 费用的浪费(重复生成相同的上下文)。

在使用 HolySheep AI 进行生产环境测试时,我深刻体会到了这个问题。HolySheep 的 API 价格极具竞争力——GPT-4.1 仅需 $8/MTok(官方¥7.3=$1无损汇率),Claude Sonnet 4.5 是 $15/MTok,而 DeepSeek V3.2 更是低至 $0.42/MTok。如果因为断线导致重复生成,每次重试都可能浪费数美元的 Token 费用。

WebSocket 流式响应的基础架构

连接建立与心跳机制

首先,我们需要一个健壮的 WebSocket 连接管理器。这是 HolySheep AI 的 WebSocket 端点:wss://api.holysheep.ai/v1/realtime

import asyncio
import json
import time
import uuid
from typing import Optional, Callable, Dict, Any, List
from dataclasses import dataclass, field
from enum import Enum
import websockets
from websockets.client import WebSocketClientProtocol

class ConnectionState(Enum):
    DISCONNECTED = "disconnected"
    CONNECTING = "connecting"
    CONNECTED = "connected"
    RECONNECTING = "reconnecting"
    ERROR = "error"

@dataclass
class StreamCheckpoint:
    """流式响应检查点"""
    session_id: str
    message_id: str
    content_hash: str  # 已接收内容的哈希,用于增量验证
    received_tokens: List[str] = field(default_factory=list)
    last_server_event_id: Optional[str] = None
    timestamp: float = field(default_factory=time.time)

@dataclass
class StreamMessage:
    """流式消息结构"""
    id: str
    type: str
    delta: Optional[str] = None
    content: Optional[str] = None
    done: bool = False
    usage: Optional[Dict[str, int]] = None
    error: Optional[str] = None

class HolySheepWebSocketClient:
    """
    HolySheep AI WebSocket 流式客户端
    支持断点续传与增量同步
    """
    
    def __init__(
        self,
        api_key: str = "YOUR_HOLYSHEEP_API_KEY",
        base_url: str = "wss://api.holysheep.ai/v1/realtime",
        model: str = "gpt-4.1",
        timeout: int = 30,
        max_retries: int = 5
    ):
        self.api_key = api_key
        self.base_url = base_url
        self.model = model
        self.timeout = timeout * 1000  # 转换为毫秒
        self.max_retries = max_retries
        
        self._ws: Optional[WebSocketClientProtocol] = None
        self._state = ConnectionState.DISCONNECTED
        self._checkpoints: Dict[str, StreamCheckpoint] = {}
        self._incremental_content: Dict[str, str] = {}
        self._event_queue: asyncio.Queue = asyncio.Queue()
        self._last_pong_time: float = 0
        self._reconnect_delay: float = 1.0
        
    async def connect(self, session_id: Optional[str] = None) -> str:
        """
        建立 WebSocket 连接
        返回 session_id 用于后续请求
        """
        if self._state == ConnectionState.CONNECTED:
            return session_id or self._session_id
            
        self._state = ConnectionState.CONNECTING
        session_id = session_id or str(uuid.uuid4())
        self._session_id = session_id
        
        url = f"{self.base_url}?model={self.model}&session_id={session_id}"
        headers = {
            "Authorization": f"Bearer {self.api_key}",
            "X-Session-ID": session_id,
            "X-Client-Version": "1.0.0"
        }
        
        try:
            # HolySheep 国内直连延迟 < 50ms
            self._ws = await websockets.connect(
                url,
                extra_headers=headers,
                ping_interval=15,  # 每15秒发送心跳
                ping_timeout=10
            )
            self._state = ConnectionState.CONNECTED
            self._reconnect_delay = 1.0  # 重置重连延迟
            print(f"✓ 连接成功,Session ID: {session_id}")
            return session_id
            
        except websockets.exceptions.InvalidStatusCode as e:
            if e.status_code == 401:
                raise ConnectionError(
                    "401 Unauthorized: API Key 无效或已过期。"
                    "请检查 https://www.holysheep.ai/dashboard 的密钥"
                )
            elif e.status_code == 429:
                raise ConnectionError("429 Rate Limited: 请求过于频繁,请稍后重试")
            else:
                raise ConnectionError(f"连接失败: {e}")
                
        except Exception as e:
            self._state = ConnectionState.ERROR
            raise ConnectionError(f"WebSocket 连接异常: {e}")
    
    async def send_message(
        self,
        prompt: str,
        session_id: Optional[str] = None,
        temperature: float = 0.7,
        max_tokens: int = 4096
    ) -> str:
        """
        发送消息并返回 message_id
        检查点是增量同步的核心
        """
        if not self._ws or self._state != ConnectionState.CONNECTED:
            await self.connect(session_id)
            
        message_id = str(uuid.uuid4())
        
        # 检查是否存在可恢复的检查点
        checkpoint = self._checkpoints.get(session_id)
        resume_from = None
        
        if checkpoint:
            print(f"🔄 发现检查点,将从上次中断处恢复...")
            resume_from = checkpoint.last_server_event_id
            
        payload = {
            "id": message_id,
            "type": "session.update",
            "session_id": session_id or self._session_id,
            "resume_from": resume_from,  # 支持断点续传
            "messages": [
                {"role": "user", "content": prompt}
            ],
            "config": {
                "temperature": temperature,
                "max_tokens": max_tokens,
                "stream": True
            }
        }
        
        await self._ws.send(json.dumps(payload))
        
        # 创建新的检查点
        self._checkpoints[session_id] = StreamCheckpoint(
            session_id=session_id,
            message_id=message_id,
            content_hash=""
        )
        self._incremental_content[message_id] = ""
        
        return message_id

使用示例

async def main(): client = HolySheepWebSocketClient( api_key="YOUR_HOLYSHEEP_API_KEY", # 替换为你的 HolySheep API Key model="gpt-4.1" ) try: session_id = await client.connect() message_id = await client.send_message( "请用中文解释什么是量子计算", session_id=session_id ) # 开始接收流式响应 async for chunk in client.stream_response(message_id): print(chunk, end="", flush=True) except ConnectionError as e: print(f"连接错误: {e}") # 触发自动重连逻辑 await handle_reconnection(client, session_id) asyncio.run(main())

流式响应接收与检查点保存

流式响应的核心在于增量处理每个 Token,同时定期保存检查点。HolySheep 的流式响应采用 SSE 格式,每个事件都包含递增的 event_id

import hashlib
import aiofiles

class IncrementalStreamHandler:
    """
    增量流式处理器
    实现断点续传的核心逻辑
    """
    
    def __init__(self, checkpoint_dir: str = "./checkpoints"):
        self.checkpoint_dir = checkpoint_dir
        self._buffer_size = 50  # 每50个Token保存一次检查点
        self._buffer_counter = 0
        
    async def process_stream(
        self,
        ws: WebSocketClientProtocol,
        message_id: str,
        session_id: str,
        on_delta: Callable[[str], None]
    ) -> str:
        """
        处理流式响应
        返回完整的响应内容
        """
        full_content = []
        last_event_id = None
        content_hash = ""
        
        async for raw_event in ws:
            event = self._parse_sse_event(raw_event)
            if not event:
                continue
                
            last_event_id = event.get("id", last_event_id)
            
            if event.get("type") == "error":
                error_msg = event.get("error", "未知错误")
                raise StreamError(f"流式响应错误: {error_msg}")
            
            if event.get("type") == "content.delta":
                delta = event.get("delta", "")
                full_content.append(delta)
                content_hash = self._compute_hash("".join(full_content))
                self._buffer_counter += 1
                
                # 增量回调
                await on_delta(delta)
                
                # 定期保存检查点
                if self._buffer_counter >= self._buffer_size:
                    await self._save_checkpoint(
                        message_id, session_id, last_event_id,
                        full_content, content_hash
                    )
                    self._buffer_counter = 0
                    
            elif event.get("type") == "message.done":
                # 响应完成,保存最终检查点
                await self._save_checkpoint(
                    message_id, session_id, last_event_id,
                    full_content, content_hash,
                    done=True
                )
                return "".join(full_content)
                
        return "".join(full_content)
    
    def _parse_sse_event(self, raw_data: bytes) -> Optional[Dict[str, Any]]:
        """解析 SSE 事件格式"""
        try:
            text = raw_data.decode('utf-8')
            event_data = {}
            
            for line in text.split('\n'):
                if line.startswith('event:'):
                    event_data['type'] = line[6:].strip()
                elif line.startswith('id:'):
                    event_data['id'] = line[3:].strip()
                elif line.startswith('data:'):
                    data_str = line[5:].strip()
                    if data_str:
                        event_data['data'] = json.loads(data_str)
                        
            # 合并 data 字段到顶层
            if 'data' in event_data:
                event_data.update(event_data['data'])
                del event_data['data']
                
            return event_data
            
        except Exception as e:
            print(f"解析 SSE 事件失败: {e}")
            return None
    
    async def _save_checkpoint(
        self,
        message_id: str,
        session_id: str,
        event_id: str,
        content: List[str],
        content_hash: str,
        done: bool = False
    ):
        """保存检查点到磁盘"""
        checkpoint = StreamCheckpoint(
            session_id=session_id,
            message_id=message_id,
            content_hash=content_hash,
            received_tokens=content,
            last_server_event_id=event_id,
            timestamp=time.time()
        )
        
        checkpoint_file = f"{self.checkpoint_dir}/{session_id}_{message_id}.json"
        
        async with aiofiles.open(checkpoint_file, 'w') as f:
            await f.write(json.dumps({
                "session_id": checkpoint.session_id,
                "message_id": checkpoint.message_id,
                "content_hash": checkpoint.content_hash,
                "last_event_id": checkpoint.last_server_event_id,
                "content": checkpoint.received_tokens,
                "timestamp": checkpoint.timestamp,
                "done": done
            }))
            
        print(f"💾 检查点已保存: {message_id[:8]}... (Hash: {content_hash[:8]})")
    
    async def load_checkpoint(
        self,
        session_id: str,
        message_id: str
    ) -> Optional[StreamCheckpoint]:
        """从磁盘加载检查点"""
        checkpoint_file = f"{self.checkpoint_dir}/{session_id}_{message_id}.json"
        
        try:
            async with aiofiles.open(checkpoint_file, 'r') as f:
                data = json.loads(await f.read())
                
            return StreamCheckpoint(
                session_id=data["session_id"],
                message_id=data["message_id"],
                content_hash=data["content_hash"],
                received_tokens=data["content"],
                last_server_event_id=data["last_event_id"],
                timestamp=data["timestamp"]
            )
        except FileNotFoundError:
            return None
    
    def _compute_hash(self, content: str) -> str:
        """计算内容哈希用于增量验证"""
        return hashlib.sha256(content.encode()).hexdigest()

    async def verify_incremental(
        self,
        local_content: str,
        server_content_hash: str
    ) -> bool:
        """验证本地内容与服务器是否一致"""
        local_hash = self._compute_hash(local_content)
        return local_hash == server_content_hash

断点续传的核心实现

断点续传的关键在于:当连接断开后,能够从上次保存的检查点恢复,而不是从头开始。我在使用 HolySheep API 时,发现其支持 resume_from 参数,这大大简化了我们的实现。

class ResilientStreamClient:
    """
    带断点续传功能的流式客户端
    完整实现网络波动处理
    """
    
    def __init__(self, base_client: HolySheepWebSocketClient):
        self.client = base_client
        self.handler = IncrementalStreamHandler()
        self._is_streaming = False
        
    async def stream_with_resume(
        self,
        prompt: str,
        session_id: str,
        on_delta: Callable[[str], None]
    ) -> str:
        """
        带断点续传的流式响应
        自动处理连接断开和重连
        """
        self._is_streaming = True
        retry_count = 0
        accumulated_content = []
        
        while self._is_streaming and retry_count < self.client.max_retries:
            try:
                # 检查是否存在可恢复的检查点
                checkpoint = await self.handler.load_checkpoint(
                    session_id, 
                    self._current_message_id or ""
                )
                
                if checkpoint and not checkpoint.last_server_event_id:
                    # 从检查点恢复
                    print(f"🔄 从检查点恢复,已接收 {len(checkpoint.received_tokens)} tokens")
                    accumulated_content = checkpoint.received_tokens.copy()
                    last_event_id = checkpoint.last_server_event_id
                else:
                    # 全新请求
                    self._current_message_id = await self.client.send_message(
                        prompt, session_id
                    )
                    last_event_id = None
                    accumulated_content = []
                
                # 启动流式接收(带重试包装)
                async for chunk in self._stream_with_retry(
                    session_id, 
                    last_event_id,
                    on_delta
                ):
                    accumulated_content.append(chunk)
                    await on_delta(chunk)
                    
                # 成功完成
                return "".join(accumulated_content)
                
            except ConnectionError as e:
                retry_count += 1
                wait_time = min(2 ** retry_count, 30)  # 指数退避,最大30秒
                
                print(f"⚠️ 连接断开 ({retry_count}/{self.client.max_retries}): {e}")
                print(f"⏳ {wait_time}秒后重连...")
                
                # 保存当前进度
                if accumulated_content:
                    await self._emergency_save(
                        session_id, 
                        self._current_message_id,
                        accumulated_content
                    )
                
                await asyncio.sleep(wait_time)
                
                # 尝试重连
                try:
                    await self.client.connect(session_id)
                except Exception as reconnection_error:
                    print(f"重连失败: {reconnection_error}")
                    
            except StreamError as e:
                print(f"流式错误: {e}")
                raise
                
        raise ConnectionError(f"达到最大重试次数 ({self.client.max_retries})")
    
    async def _stream_with_retry(
        self,
        session_id: str,
        resume_from: Optional[str],
        on_delta: Callable[[str], None]
    ):
        """
        带重试的流式接收
        处理连接超时和临时断开
        """
        while True:
            try:
                async for chunk in self.client.stream_response(
                    self._current_message_id,
                    resume_from=resume_from
                ):
                    yield chunk
                    resume_from = None  # 一旦成功接收,后续不再需要resume
                    
            except websockets.exceptions.ConnectionClosed as e:
                if e.code == 1000:
                    # 正常关闭
                    break
                elif e.code == 1006:
                    # 非正常关闭,尝试重连
                    print("检测到非正常关闭,尝试恢复...")
                    await self.client.connect(session_id)
                    # 重试一次
                    continue
                else:
                    raise ConnectionError(f"WebSocket关闭: code={e.code}")
                    
            except asyncio.TimeoutError:
                print("接收超时,触发重连机制...")
                raise ConnectionError("流式接收超时")
                
    async def _emergency_save(
        self,
        session_id: str,
        message_id: str,
        content: List[str]
    ):
        """紧急保存当前进度"""
        checkpoint_file = f"./emergency/{session_id}_{message_id}.json"
        
        async with aiofiles.open(checkpoint_file, 'w') as f:
            await f.write(json.dumps({
                "session_id": session_id,
                "message_id": message_id,
                "content": content,
                "timestamp": time.time()
            }))
            
        print(f"🚨 紧急检查点已保存: {len(content)} tokens")

    def stop(self):
        """停止流式接收"""
        self._is_streaming = False

常见报错排查

错误1: 401 Unauthorized - API Key 无效

# 错误日志

ConnectionError: 401 Unauthorized: API Key 无效或已过期

解决方案

async def validate_api_key(api_key: str) -> bool: """验证 API Key 是否有效""" import aiohttp url = "https://api.holysheep.ai/v1/models" # 注意:这里是 REST API 端点 headers = {"Authorization": f"Bearer {api_key}"} try: async with aiohttp.ClientSession() as session: async with session.get(url, headers=headers, timeout=5) as resp: if resp.status == 200: return True elif resp.status == 401: print("❌ API Key 无效或已过期") return False else: print(f"⚠️ API 返回状态码: {resp.status}") return False except aiohttp.ClientError as e: print(f"网络错误: {e}") return False

使用方式

async def main(): api_key = "YOUR_HOLYSHEEP_API_KEY" if await validate_api_key(api_key): client = HolySheepWebSocketClient(api_key=api_key) await client.connect() else: print("请前往 https://www.holysheep.ai/register 获取新的 API Key")

错误2: ConnectionError: timeout after 30000ms

# 错误日志

ConnectionError: WebSocket connection timeout after 30000ms

重试3次后仍然失败

解决方案:实现智能超时和重试策略

class TimeoutConfig: """可配置的超时策略""" CONNECT_TIMEOUT = 10 # 连接超时10秒 READ_TIMEOUT = 60 # 读取超时60秒 PING_INTERVAL = 15 # 心跳间隔15秒 PING_TIMEOUT = 10 # 心跳超时10秒 MAX_RETRY_DELAY = 30 # 最大重试延迟30秒 async def robust_connect( client: HolySheepWebSocketClient, session_id: str ): """带超时保护的健壮连接""" import signal class TimeoutException(Exception): pass def timeout_handler(signum, frame): raise TimeoutException("操作超时") # 设置 alarm 信号(仅在 Unix 系统有效) signal.signal(signal.SIGALRM, timeout_handler) signal.alarm(TimeoutConfig.CONNECT_TIMEOUT) try: await client.connect(session_id) signal.alarm(0) # 取消 alarm print("✓ 连接成功") return True except TimeoutException: print(f"❌ 连接超时({TimeoutConfig.CONNECT_TIMEOUT}秒)") # 尝试备用线路或降级方案 return await fallback_connect(client, session_id) except ConnectionError as e: signal.alarm(0) print(f"连接失败: {e}") return await fallback_connect(client, session_id) async def fallback_connect( client: HolySheepWebSocketClient, session_id: str ): """备用连接方案""" # HolySheep 国内直连延迟 < 50ms,如果超时可能是网络问题 print("尝试备用连接方案...") # 方案1: 使用 HTTP 代理 # proxy_url = "http://127.0.0.1:7890" # 根据实际代理地址调整 # 方案2: 降级到 HTTP 轮询模式 return await http_polling_fallback(client, session_id) async def http_polling_fallback( client: HolySheepWebSocketClient, session_id: str ): """HTTP 轮询降级方案""" print("⚠️ 降级到 HTTP 轮询模式") import aiohttp url = f"https://api.holysheep.ai/v1/chat/completions" headers = { "Authorization": f"Bearer {client.api_key}", "Content-Type": "application/json" } payload = { "model": client.model, "messages": [{"role": "user", "content": "继续上次的对话"}], "stream": True } async with aiohttp.ClientSession() as session: async with session.post(url, json=payload, headers=headers) as resp: async for line in resp.content: if line.startswith(b'data: '): data = line[6:] if data.strip() == b'[DONE]': break # 处理流式数据 chunk = json.loads(data) print(chunk, end="")

错误3: WebSocket connection closed unexpectedly (code: 1006)

# 错误日志

WebSocket connection closed unexpectedly (code: 1006, reason: None)

这通常表示服务器主动关闭或网络中断

解决方案:实现 1006 错误自动恢复

class AutoRecoveryHandler: """1006 错误自动恢复处理器""" CLOSE_CODE_MEANING = { 1000: ("正常关闭", False), 1001: ("服务器关闭", True), 1006: ("异常关闭(网络问题)", True), 1011: ("服务器错误", True), 1015: ("TLS握手失败", True) } async def handle_close( self, close_event: websockets.exceptions.ConnectionClosed, client: HolySheepWebSocketClient, session_id: str ): """处理 WebSocket 关闭事件""" code = close_event.code reason = close_event.reason meaning, should_retry = self.CLOSE_CODE_MEANING.get( code, (f"未知关闭码: {code}", True) ) print(f"⚠️ WebSocket 关闭: {meaning}") if reason: print(f" 原因: {reason}") if should_retry: return await self._auto_recover(client, session_id, code) else: return None async def _auto_recover( self, client: HolySheepWebSocketClient, session_id: str, close_code: int ): """自动恢复连接""" if close_code == 1006: # 1006 最常见的原因是 NAT 超时或中间代理断开 print("🔄 检测到网络中断,尝试恢复...") # 步骤1: 等待网络稳定 await asyncio.sleep(2) # 步骤2: 清除旧连接 if client._ws: try: await client._ws.close() except: pass # 步骤3: 重新建立连接 for attempt in range(3): try: print(f"尝试重连 ({attempt + 1}/3)...") await client.connect(session_id) # 步骤4: 验证连接 await client.send_ping() if client._last_pong_time > 0: print("✓ 连接已恢复") return True except Exception as e: print(f"重连失败: {e}") await asyncio.sleep(2 ** (attempt + 1)) print("❌ 无法恢复连接") return False return False async def implement_keepalive( self, client: HolySheepWebSocketClient, session_id: str ): """实现 Keep-Alive 机制防止 1006""" async def heartbeat(): while True: try: await asyncio.sleep(15) # 每15秒一次心跳 if client._ws: await client._ws.ping() print("💓 心跳发送成功") except Exception as e: print(f"心跳失败: {e}") break # 启动心跳任务 asyncio.create_task(heartbeat())

完整生产环境示例

以下是一个完整可运行的生产环境示例,整合了所有断点续传和增量同步的代码。

#!/usr/bin/env python3
"""
HolySheep AI WebSocket 流式响应完整示例
包含断点续传、增量同步、错误恢复
"""

import asyncio
import json
import time
import hashlib
from typing import Optional, Callable, List, Dict, Any
from dataclasses import dataclass, field
import websockets
from websockets.client import WebSocketClientProtocol
import aiofiles
import aiohttp

============== 配置 ==============

HOLYSHEEP_API_KEY = "YOUR_HOLYSHEEP_API_KEY" # 替换为你的 HolySheep API Key HOLYSHEEP_WS_URL = "wss://api.holysheep.ai/v1/realtime" HOLYSHEEP_REST_URL = "https://api.holysheep.ai/v1/chat/completions" MODEL = "gpt-4.1"

============== 数据结构 ==============

@dataclass class StreamState: session_id: str message_id: str content: List[str] = field(default_factory=list) event_id: str = "" hash: str = "" created_at: float = field(default_factory=time.time)

============== 主类 ==============

class HolySheepStreamingClient: """完整的流式客户端""" def __init__(self, api_key: str): self.api_key = api_key self.ws: Optional[WebSocketClientProtocol] = None self.states: Dict[str, StreamState] = {} async def chat( self, prompt: str, session_id: str, on_delta: Callable[[str], None], on_complete: Optional[Callable[[str], None]] = None ) -> str: """ 发送聊天请求并流式接收响应 Args: prompt: 用户输入 session_id: 会话ID(用于断点续传) on_delta: 每个chunk的回调 on_complete: 完成时的回调 Returns: 完整的响应文本 """ # 检查是否有可恢复的状态 state = self.states.get(session_id) resume_from = None if state and state.event_id: print(f"🔄 从 event_id={state.event_id[:16]}... 恢复") resume_from = state.event_id # 建立连接 if not self.ws: await self._connect(session_id) # 发送请求 message_id = f"msg_{int(time.time() * 1000)}" await self._send_request(message_id, session_id, prompt, resume_from) # 初始化状态 self.states[session_id] = StreamState( session_id=session_id, message_id=message_id, content=[] if not resume_from else state.content.copy() ) # 接收响应 full_content = "".join(self.states[session_id].content) try: async for delta, event_id in self._receive_stream(): if delta: full_content += delta self.states[session_id].content.append(delta) self.states[session_id].event_id = event_id self.states[session_id].hash = hashlib.sha256( full_content.encode() ).hexdigest() await on_delta(delta) else: # 流结束 await self._save_state(session_id) if on_complete: await on_complete(full_content) return full_content except websockets.exceptions.ConnectionClosed as e: print(f"⚠️ 连接关闭: code={e.code}") await self._save_state(session_id) # 尝试自动恢复 if e.code == 1006: return await self._auto_resume( session_id, prompt, on_delta, on_complete ) raise async def _connect(self, session_id: str): """建立 WebSocket 连接""" headers = { "Authorization": f"Bearer {self.api_key}", "X-Session-ID": session_id } self.ws = await websockets.connect( f"{HOLYSHEEP_WS_URL}?model={MODEL}", extra_headers=headers, ping_interval=15, ping_timeout=10 ) print("✓ WebSocket 连接成功") async def _send_request( self, message_id: str, session_id: str, prompt: str, resume_from: Optional[str] ): """发送请求""" payload = { "id": message_id, "type": "session.update", "session_id": session_id, "resume_from": resume_from, "messages": [{"role": "user", "content": prompt}], "config": {"temperature": 0.7, "max_tokens": 4096, "stream": True} } await self.ws.send(json.dumps(payload)) async def _receive_stream(self): """接收流式响应""" async for raw in self.ws: event = self._parse_event(raw) if event.get("type") == "content.delta": yield event.get("delta", ""), event.get("id", "") elif event.get("type") == "message.done": yield None, event.get("id", "") break elif event.get("type") == "error": raise RuntimeError(f"流错误: {event.get('error')}") def _parse_event(self, raw: bytes) -> Dict: """解析 SSE 事件""" try: text = raw.decode('utf-8') result = {} for line in text.split('\n'): if line.startswith('event:'): result['type'] = line[6:].strip() elif line.startswith('id:'): result['id'] = line[3:].strip() elif line.startswith('data:'): data = json.loads(line[5:].strip()) result.update(data) return result except: return {} async def _save_state(self, session_id: str): """保存状态到文件""" state = self.states.get(session_id) if not state: return filename = f"./state_{session_id}.json" async with aiofiles.open(filename, 'w') as f: await f.write(json.dumps({ "session_id": state.session_id, "message_id": state.message_id, "content": state.content, "event_id": state.event_id, "hash": state.hash, "created_at": state.created_at })) async def _auto_resume( self, session_id: str, prompt: str, on_delta: Callable[[str], None], on_complete: Optional[Callable] ) -> str: """自动从保存的状态恢复""" # 重新连接 await self._connect(session_id) # 继续流式接收 state = self.states.get(session_id) full_content = "".join(state.content) if state else "" async for delta, event_id in self._receive_stream(): if delta: full_content += delta if state: state.content.append(delta) state.event_id = event_id await on_delta(delta) else: if on_complete: await on_complete(full_content) return full_content return full_content

============== 运行示例 ==============

async def main(): client = HolySheepStreamingClient(HOLYSHEEP_API_KEY) session_id = "demo_session_001" def print_delta(delta: str): print(delta, end="", flush=True) print("=" * 50) print("开始流式对话(支持断点续传)...") print("=" * 50) try: result = await client.chat( prompt="用100字介绍一下人工智能的发展历史", session_id=session_id, on_delta=print_delta ) print("\n" + "=" * 50) print(f"✅ 对话完成,共 {len(result)} 字符") except Exception as e: print(f"\n❌ 错误: {e}") finally: await client.ws.close() if __name__ == "__main__": asyncio.run(main())

性能优化与最佳实践

在我维护生产环境的两年多时间里,总结了以下关键优化点: