终端 TUI(Textual)
SimpleLLMFunc 提供了开箱即用的 TUI 装饰器,基于 textual + event stream 构建。
你可以把它直接叠加在 @llm_chat 上,让 Agent 具备完整的终端输入循环、流式渲染和工具调用可视化。
提示:
@tui依赖事件流,务必在@llm_chat中设置enable_event=True,并推荐开启stream=True以获得流式渲染体验。
安装依赖
textual 已作为框架依赖。
如果你在已有环境中升级,请重新安装依赖:
poetry install
快速开始
from SimpleLLMFunc import llm_chat, tui
@tui()
@llm_chat(
llm_interface=llm,
toolkit=[...],
stream=True,
enable_event=True,
)
async def agent(message: str, history=None):
"""Your agent prompt."""
if __name__ == "__main__":
agent() # 启动 TUI + input loop
@tui 会自动识别输入参数:
history/chat_history作为历史参数其余第一个参数作为用户输入
UI 能力
用户消息与模型消息交替渲染
模型流式输出实时刷新,并支持 Markdown 渲染
流式输出期间消息区自动跟随到底部,优先展示最新内容
推理增量(reasoning delta)以灰色文本展示(当模型提供该字段时)
每次模型调用结束后,在消息下方展示耗时与 token 用量
工具调用开始时展示结构化参数(可读格式,不是裸 JSON 字符串)
工具执行期间消费
CustomEvent并实时更新工具输出当工具(如 PyRepl)触发
input()时,输入框自动切换为工具输入模式并优先回填该请求工具结束后展示结果与调用统计(耗时/状态)
fork 任务自动拆分为独立列,基于
origin.fork_id路由到对应分栏聊天消息区支持超出视口滚动,消息项会随内容自适应高度
中断当前回复
当 Agent 仍在生成回复时再次发送消息,TUI 会触发中断并开启新回合:
当前回合会被终止(停止流式输出、取消工具调用)
新消息会自动加上中断提示语:
"我要打断你的回复。"
这用于快速打断长回复或纠正方向。如需更细粒度控制,可手动传入 AbortSignal(详见 中断与取消)。
交互与退出
发送消息:输入后按 Enter
当存在待处理的工具输入请求时,Enter 会优先把输入提交给该请求
强制发送新一轮聊天:
/chat <message>(可在有待处理工具输入时绕过优先路由)复制完整转录:
/copy或Ctrl+Y退出命令:
/exit、/quit、/q快捷键退出:
Ctrl+Q(同时保留Ctrl+C)
自定义 Tool 事件 Hook
@tui 支持通过 custom_event_hook 注入自定义事件解析逻辑:
from SimpleLLMFunc.hooks.events import CustomEvent
from SimpleLLMFunc.utils.tui import ToolEventRenderUpdate, ToolRenderSnapshot
def my_hook(
event: CustomEvent,
snapshot: ToolRenderSnapshot,
) -> ToolEventRenderUpdate | None:
if event.event_name != "batch_progress" or not isinstance(event.data, dict):
return None
return ToolEventRenderUpdate(
append_output=f"progress={event.data['percent']}%\n"
)
@tui(custom_event_hook=[my_hook])
@llm_chat(..., enable_event=True, stream=True)
async def agent(message: str, history=None):
...
框架也内置了部分常见工具事件的默认解析(例如 PyRepl 的 kernel_stdout/kernel_stderr/kernel_input_request)。
运行示例
参考示例:examples/tui_chat_example.py