中断与取消(AbortSignal)
AbortSignal 是一个轻量级的中断机制,用于在运行中的 Agent 回合里停止流式输出、取消正在执行的工具调用,并尽快收敛到安全的终止状态。
适用场景包括:
用户主动打断长回复
UI/服务端超时控制
上下文切换(先停掉旧回合,再启动新回合)
核心概念
AbortSignal:一个可在多个协程之间共享的中断信号。_abort_signal:调用参数名(推荐用常量ABORT_SIGNAL_PARAM避免硬编码)。abort(reason):触发中断,并可附带原因说明。
提示:
_abort_signal只用于运行时控制,不会进入 prompt,也不会传给模型或工具。
基本用法
llm_chat 示例
import asyncio
from SimpleLLMFunc import llm_chat
from SimpleLLMFunc.hooks import AbortSignal, ABORT_SIGNAL_PARAM
@llm_chat(llm_interface=llm, stream=True, enable_event=True)
async def chat(message: str, history=None):
"""你的系统提示"""
pass
abort_signal = AbortSignal()
async def run():
async def abort_later():
await asyncio.sleep(1.5)
abort_signal.abort("user_interrupt")
asyncio.create_task(abort_later())
async for output in chat(
"请详细解释 transformer",
history=[],
**{ABORT_SIGNAL_PARAM: abort_signal},
):
# 正常处理事件流
...
asyncio.run(run())
llm_function 示例
import asyncio
from SimpleLLMFunc import llm_function
from SimpleLLMFunc.hooks import AbortSignal, ABORT_SIGNAL_PARAM
@llm_function(llm_interface=llm, enable_event=True)
async def analyze(text: str) -> str:
"""分析文本"""
pass
abort_signal = AbortSignal()
async def run():
async def abort_later():
await asyncio.sleep(1.0)
abort_signal.abort("timeout")
asyncio.create_task(abort_later())
async for output in analyze(
"一段很长的文本",
**{ABORT_SIGNAL_PARAM: abort_signal},
):
...
asyncio.run(run())
运行行为
流式输出:中断后不再接收新的 chunk。
工具调用:正在执行的工具调用会被取消;在事件流中可能看到
ToolCallErrorEvent,其error_type为CancelledError。事件流收尾:当
enable_event=True时,ReactEndEvent.extra会包含:aborted: trueabort_reason: <reason>(如果传入了 reason)
非事件流模式:生成器会提前结束,不会额外产出
ReactEndEvent。
注意:AbortSignal 是协作式中断。如果工具本身不可取消或处于阻塞状态,实际停止时间可能滞后。
TUI 的内置中断
在 @tui 场景下,当 Agent 仍在回复时再次发送消息,会自动触发中断:
当前回合被中止,新的用户消息进入队列
新消息会自动加上中断提示语(
"我要打断你的回复。")以引导模型及时收束
如果你需要更细的控制(比如自定义中断提示语),可以绕过内置流程,手动创建并传入 AbortSignal。