这里主要讲解一些重要概念,这是理解 AI 业务,和后续设计的基础。

1、sessionId、agentId、eventId

一个完整的逻辑流示例:

  • 场景:你在一个名为“旅行助手”的对话框(Session ID: S-123)里问:“帮我查下上海明天的天气”。
  • 动作
    1. 点击发送,后端启动一个 Agent 进程,生成 Agent ID: A-999
    2. 前端立刻建立 SSE 连接:GET /sub/A-999
    3. 微服务开始推送事件:
      • 推送 Event ID: E-1 内容:{"type": "thought", "text": "我需要调用天气插件"}
      • 推送 Event ID: E-2 内容:{"type": "tool_call", "name": "weather_api"}
      • (此时网络闪断 1 秒)
      • 前端重连,带上 Last-Event-ID: E-2
      • 推送 Event ID: E-3 内容:{"type": "answer", "text": "上海明天多云转晴"}
    4. 回答结束,Agent ID: A-999 销毁,但该回答被存入 Session ID: S-123 的历史记录中。

2、SSE

场景:

  • 你打开对话框,给 AI 发了一条消息
  • AI 回复你,对话框的字是一个一个打印机一样的出来,耗时很长

这种效果怎么实现呢?

  1. 前端轮询:性能不现实。
  2. WebSocket:太重了。
  3. SSE:

SSE 是一种在基于 HTTP 协议之上的服务器推送技术。它的工作原理非常“返璞归真”:

  1. 握手:前端发起一个普通的 HTTP 请求。
  2. 不关门:后端在 Header 中设置 Connection: keep-aliveContent-Type: text/event-stream,告诉浏览器:“这个请求还没完,别关掉,我要开始不停发数据了”。
  3. 流式传输:后端持续不断地向这个连接里写入数据块。

为什么 Agent 场景首选 SSE 而不是 WebSocket?

  • 轻量级:它就是 HTTP,不需要处理复杂的 WebSocket 握手和心跳。
  • 原生重连:浏览器会自动处理断线重连。
  • 单向性:Agent 场景主要是后端向前端单向输出状态,SSE 的设计初衷就是如此。

3、当我给 AI 发了一个问题,这期间发生了什么?

用户感知:

1、打开对话框,给 AI 发了一个问题:1+1 等于几?

2、AI 开始回答,回答像打印机效果一样,一个字一个字出现。

按时间顺序发生了什么?

阶段一:建立通信管道 (Handshake)

当用户点击“发送”按钮的那一刻,系统首先要搭建一条实时传输的“高速公路”。

  1. 客户端 (Client):向业务后端发送一个普通的 HTTP POST 请求(带着你的问题:“1+1等于几?”)。

  2. 业务后端 (App Server)

    • 接收请求,验证用户身份。
    • 在数据库创建一条新的对话记录(关联 Session ID)。
    • 生成一个新的任务实例(关联 Agent ID)。
    • 关键动作:立即返回这个 agentId 给客户端。
  3. 客户端 (Client):拿到 agentId 后,立刻发起 SSE 订阅:

    const source = new EventSource('/sse/subscribe/agent_001');

  4. SSE 微服务:接收订阅请求,保持连接挂起,并将该连接存入内存 Map 中。

阶段二:驱动 AI 思考 (Reasoning)

此时,前端页面可能正在显示“AI 正在思考…”的占位符。

  1. 业务后端 (App Server):调用 AI 模型接口(如 OpenAI/Claude)。
  2. AI 模型:开始处理,并通过 Stream 模式 返回数据块(Chunks)。
  3. 业务后端 (App Server)
    • 接收到 AI 的第一个 Chunk(例如:“1”)。
    • 将这个碎片封装成一个 Event,发给 SSE 微服务

阶段三:事件分发与渲染 (Streaming)

这是最核心的“打印机效果”来源。

  1. SSE 微服务
    • 收到业务后端发来的事件。
    • 根据 agentId 找到对应的所有前端连接。
    • 按照 SSE 格式(data: {...})将字符串写入连接。
  2. 客户端 (Client)
    • 触发 onmessage 回调。
    • 解析出 JSON 数据,提取出文本碎片。
  3. 前端 UI (React/Vue)
    • 将新收到的字符追加到当前的 state 中:content += newChar
    • 触发页面重新渲染,用户看到字符“跳”了出来。

阶段四:收尾与持久化 (Completion)

  1. AI 模型:发送一个结束标志(如 [DONE])。
  2. 业务后端 (App Server)
    • 通知 SSE 微服务 发送一个 type: "done" 的事件。
    • 将完整的回答(1+1=2)一次性写入数据库,供以后翻阅历史记录。
  3. 客户端 (Client)
    • 收到 done 事件,关闭 SSE 连接。
    • 停止“打印”状态,将该次对话标记为完成。