一、 核心改变:API 层的 async: true 声明
在过去,你定义工具(Functions)传给大模型时,它默认为阻塞式的。
也就是说,你不给 tool result 而是直接发下一条请求,确实也是可以的。你作为客户端,完全可以把这个 tool_calls 晾在一边,不理它。模型不会死锁或崩溃,但是你的 Agent(智能体)业务逻辑大概率会“乱掉”或者被模型拒绝
从模型“大脑”(对话状态)来看:它是严重阻塞的:在旧的 API 规范中,大模型的“大脑”被硬编码成了一套严格的 ReAct 状态机 如果你不给 tool result,而是直接塞一个新问题发下一条请求,对模型来说相当于“记忆出现了严重的逻辑断层” 由于打破了它预设的逻辑闭环,旧模型经常会犯迷糊,继续复读一遍“请帮我运行工具”,或者直接返回错误。如果你想强行跳过这个工具,你必须在客户端的代码里,把模型刚才发出的 tool_calls 从对话历史中手动删掉(Pop 掉)
现在 OpenAI Astra 允许你在声明工具的 JSON Schema 中直接加入一个关键字 async: true:
1 | { |
在过去:你不给结果,模型就认为你的对话历史“残缺了”或者“格式坏了”,它的注意力机制在处理这段断层上下文时会严重失焦。在现在(Astra 异步):你告诉模型 async: true。模型在输出 tool_calls 的那一刻,它的状态机就主动进入了“后台挂起”模式。它知道这个工具去后台跑了,此时你不需要删记忆,直接发下一条新请求,模型能够非常顺畅地在上下文里跟你聊别的话题,直到几分钟后工具结果回来。
二、 运行时的状态机实现(稳定 Call ID 映射)
这是技术实现里最巧妙的部分。异步调用最怕的是“结果返回了,但模型把上下文忘光了”(这里指的是当 5 分钟后 call_1 的结果返回时,对话历史里已经塞满了这 5 分钟内产生的大量新对话、新推理逻辑。虽然你用 ID 把结果强行贴在了最新的对话末尾,但模型由于上下文太长(尤其是信息被埋在了最中间),注意力机制对 5 分钟前那个 call_1 的感知力会急剧下降,这就导致了技术上常说的 “Lost in the Middle”(迷失在中间)现象。它看到结果了,但它的注意力已经很难和 5 分钟前它发出调用时的那对“起因”产生强烈的权重关联了)
- 生成全局唯一 ID(
call_id*):当模型决定调用这个异步工具时,它会输出一个call_id: "call_abc123",然后模型*立即结束这一轮思考,转去执行其他任务(比如先回答用户的另一个小问题,或者继续生成不需要该数据的文本)。 [2, 3, 4] - 长耗时工具离线运行:你的本地客户端或服务器收到这个
call_id,开始在后台开一个独立进程(如 Python 的asyncio任务或 Celery 队列)去跑代码。 [5] - 回传结果关联:当工具在几分钟后跑完时,客户端向大模型服务器发送一个包含原有
call_id的事件: [3, 4]1
2{"role":"tool","call_id":"call_abc123",// 严格对应,大模型靠它把数据塞回正确的记忆片段中"content":"分析完成,结果为:..."
}
三、 通信层:基于 WebSocket 的全双工流式会话(Mid-turn Steering)
- 建立 WebSocket 持续长连接:客户端与大模型服务器之间保持一条“双向同时说话”的通道。
- 推理与输入交错(Interleaved):
- 模型侧:正在利用其内部的 CoT(思维链) 疯狂进行逻辑推理和输出。
- 用户侧:如果发现模型跑偏了,用户直接发送一句新的 Prompt 文本(无需等待模型停下)。
- 服务器侧实现:服务器在接收到用户新输入的瞬间,不中断当前的上下文会话,而是将新输入作为“实时动态观测(Observation)”直接插播进模型的 Attention(注意力机制)缓存中。模型会瞬间感知到新指令,并在线调整后面的推理路线(这在技术上被称为 Mid-turn Steering / 中途转向)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27【WebSocket 接收层】 【服务器核心:动态 KV Cache 管理器】 【Transformer 推理引擎】
│ │ │
│ ┌───────────────────────┐ │
│ │ [ 原始历史上下文 KV ] │ │
│ └───────────┬───────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────┐ │
│ │ [ 正在生成的 CoT KV ] │ ───(当前正基于此进行 Attention 计算)──>│
│ └───────────────────────┘ │
│ ▲ │
│ │ (突发插播!) │
用户发送: "不要用Python,改用Go" │ │
│ │ │
▼ │ │
[ 瞬间 Tokenize 并计算 KV ] ───────────────────────────┘ │
[ 新输入 Observation KV ] │
│ │
▼ │
┌───────────────────────┐ │
│ [ 融合后的新 KV 缓存 ] │ ───(下一标点/Token 立即感知新权重)──>│
└───────────────────────┘ │
│
【 效果:Mid-turn Steering (中途转向) 】 │
模型在下一发色点(Token)的注意力矩阵被突变改变, │
直接放弃原有的 Python 思路,流畅转向输出 Go 代码。 ▼