flowchart TD
U["用户 / CLI"] --> S["会话与任务管理"]
S --> P["Planner 任务规划"]
P --> E["Executor 步骤执行"]
E --> T["工具调用"]
T --> E
E --> R["Reflector 结果检查"]
R -->|"需要继续"| P
R -->|"任务完成"| F["Finalizer 生成最终回答"]
F --> U
P --> L["Llama-cpp 本地 GGUF 模型"]
E --> L
R --> L
F --> L
S <--> M["会话记忆与上下文管理"]
S <--> C["Checkpoint 任务保存与恢复"]
llama-agent
llama-agent是一个完全本地运行的工具型 Agent 系统。项目使用llama-cpp-python加载 GGUF 模型,通过 LangChain 的 ChatModel/Tool 接口接入模型与工具,并用 LangGraph 实现可 checkpoint、可 resume 的Planner–Executor–Reflector–Finalizer 工作流。系统支持单任务执行、持久化多轮会话、本地工具调用、全屏交互式 CLI、运行遥测和可重复 Benchmark。在此基础上,项目实现了两项面向长生命周期Agent 的上下文优化,当前优化属于Agent应用层上下文优化,能减少输入Token、Prompt预填充开销和逻辑KV占用。
目录
1. 项目说明
1.1 核心能力
llama-cpp-python执行模型推理,可配置 CPU、CUDA 或 Metal offload。BaseChatModel和BaseTool接入模型与工具生态。1.2 优化与创新
项目面向长周期 Agent 持续增长的上下文实现了两项优化:
详细设计参见第 2 章:R0、R1、R2 优化设计。
项目同时实现了 Benchmark 自动化框架:使用本地确定性 Fixture,在独立 Python子进程中运行每个样本,隔离模型、KV 状态、Checkpoint 和各类存储;R0、R1、R2使用相同模型、任务和评价规则,并自动生成原始数据、失败记录、报告和图表。
最终测试结果表明:
详细测试方法、用例和图表参见第 3 章:Benchmark 设计与测试结果。
1.3 系统架构
flowchart TD U["用户 / CLI"] --> S["会话与任务管理"] S --> P["Planner任务规划"] P --> E["Executor
步骤执行"] E --> T["工具调用"] T --> E E --> R["Reflector
结果检查"] R -->|"需要继续"| P R -->|"任务完成"| F["Finalizer
生成最终回答"] F --> U P --> L["Llama-cpp
本地 GGUF 模型"] E --> L R --> L F --> L S <--> M["会话记忆与上下文管理"] S <--> C["Checkpoint
任务保存与恢复"]
外层 LangGraph 负责一个任务的计划、执行、反思与最终回答;Executor 内部还有一个 ReAct 子图,用于完成“决定调用工具 → 执行真实工具 → 将工具结果重新送入模型 → 生成步骤结论”的闭环。 Checkpoint 只保存外层节点边界状态,避免内外两层同时持久化造成恢复语义混乱。
1.4 主要模块
1.5 当前工具
execute_shell_command、count_linesget_file_metadata、read_file、search_fileaggregate_log_errors、search_log、get_log_windowdescribe_sqlite_table、query_sqliteget_artifact_summary、retrieve_artifact、search_artifactShell 工具采用命令白名单和强制超时; SQLite 工具只允许读取; 文件、日志、SQLite 和 Artifact 工具均受到路径或任务所有权隔离。
2. R0、R1、R2 优化设计
三轮消融采用递进关系:
2.1 R0:无上下文优化的功能基线
R0 关闭所有
[memory]优化开关,工具原始结果和基线会话历史直接进入模型上下文。用于验证 Agent 功能是否完整,并作为 R1/R2 的对照组。完成一次任务的主要流程如下:
tool_calls,真实调用 Capability,并将ToolMessage重新送回模型。final_answer。thread_id继续执行。2.2 R1:工具输出虚拟化
问题
调用日志、文件或数据库工具可能一次返回几十数百 KiB的数据,若每轮对话都把完整结果写入 ToolMessage、LangGraph State 和后续 Prompt,会同时造成:
n_ctx。设计原理
对模型暴露一个小型逻辑视图,对于工具结果仅保留摘要和部分预览送入模型,原始数据则放在可寻址的外部存储中。模型只有在摘要和预览不足时,才按需搜索或读取原文。
工具结果大小在小于artifact_inline_max_bytes时,将原结果送入模型;当结果大于artifact_inline_max_bytes是,原文写入AtifactStore,只将摘要、头部预览、尾部预览和可用操作送入模型,模型根据需要调用工具查询原文。
当前摘要是确定性摘要,不会额外调用模型。它包含工具名、原始字节数、行数和结构化结果中的小型标量字段;
content、stdout、rows、matches等字段不会复制到摘要。预览在固定字符预算内平均保留头部和尾部,适合证据分别位于文件开头或结尾的场景。ArtifactStore 采用混合存储:
data/artifacts/artifacts.sqlite保存 Artifact 元数据;data/artifacts/content/<id>.bin保存原始内容;artifact://<opaque-id>作为不暴露文件路径的任务级句柄;owner_id防止一个任务读取另一个任务的 Artifact。模型可通过以下工具恢复必要证据:
get_artifact_summary:读取元数据和摘要;search_artifact:在完整 Artifact 中检索关键词并返回有限上下文;retrieve_artifact:按offset + length分段读取原文。这项优化不依赖特定模型或推理引擎,也不增加摘要推理调用。它的主要代价是磁盘写入、SQLite 元数据和按需检索调用,因此阈值过低会对小结果产生负优化。
2.3 R2:生命周期上下文管理
问题
R1 只处理单次产生的超大工具结果,但 Agent 在长任务和多轮对话中还会不断积累执行记录、工具摘要和历史消息。这些内容即使每条都不大,累计后仍会使 Prompt越来越长,增加输入 Token、预填充时间和 Checkpoint 体积。 如果简单删除旧记录,模型又可能忘记用户要求记住的事实、早期工具证据或任务结论。因此,R2 需要在减少上下文长度和保留有效记忆之间取得平衡。
设计原理
R2 将上下文看作需要持续整理的模块:重要内容和最近使用的内容保留在 Prompt中,较早内容压缩后归档,已经失效或与当前问题无关的内容不再重复发送给模型。
具体处理方式如下:
ContextStore,Agent 状态只保留摘要和memory://引用。conversations.sqlite,归档执行记录存储在ContextStore。缩短 Prompt 但不是删除历史。2.4 开关与主要参数
agent_config.toml默认关闭优化,确保普通 R0 测试不会被污染:也可以用环境变量临时覆盖:
3. Benchmark 设计与测试结果
3.1 实验方法
Benchmark 采用以下方法减少不可控因素:
suite.seed + repetition作为每次重复的模型随机种子。单个运行目录包含:
3.2 用例设计
r0_smoke.jsonr0_full.jsonr1_artifact_virtualization.jsonr2_context_pressure.jsonr2_lifecycle_context.jsonr0_full.json的 W1~W8:3.3 当前 R0~R2 对比结果
以下数据来自仓库中保留的三次自动消融测试。三次测试使用相同模型文件。 以下结果的实验平台为:
实验 A:通用功能与 R1 大输出优化
数据源: 包含 9 个 Case、1 次 Warmup、5 次正式重复,共 45 个正式样本/轮。
R1 相对 R0:
R1 共虚拟化 10 个大型结果,外置原文 418,490 B,减少模型内联400,155 B,工具结果压缩率为 95.62%。收益主要来自 16/64 KiB 两个 W4 Case;其中 64 KiB Case 的输入 Token/样本从 21,572 降至 3,960,平均耗时从30.93 s 降至 15.74 s。
实验 B:R2 累计执行上下文压力
本轮测试连续读取 6 个 6000 B 文件
R2 相对 R1:
实验 C:R2 长会话生命周期
数据源: 本轮测试包含 16 轮召回、32 轮召回、多阶段本地证据和 Artifact 中部证据回归,每轮共 20 个正式样本。
R0/R1 的会话基线只保留最近 8 轮,无法在 16/32 轮后看到最早的
AgentMem/7319,两类召回 Case 均为 0/5,因此R0,R1执行成功率低于R2。R2 相对 R1 的输入 Token 减少 **10.24%**,平均端到端耗时减少 **18.21%**。生命周期遥测显示会话上下文投影压缩率为 41.50%,额外召回 450 个历史轮次记录,最终选择 1,050 个轮次记录,共注入 49,130 Token。
结果结论
3.4 执行 Benchmark
运行单轮:
只执行指定 Case,
--case可以重复:也可以使用脚本:
4. 安装、配置与使用
4.1 环境要求
nvcc;4.2 CPU 安装
最简单的 CPU 安装:
CPU 配置中设置:
4.3 NVIDIA CUDA 安装
先确认驱动和编译器:
建议在全新虚拟环境中先构建 CUDA 版
llama-cpp-python,再安装项目:输出应为
True。然后配置:Apple Silicon 可将构建参数替换为:
4.4
pyproject.toml与运行配置pyproject.toml负责 Python 包元数据、依赖和命令入口。开发环境可安装:
模型与运行时参数配置在
agent_config.toml:4.5 单次任务与工具调用
普通对话:
显式要求 Agent 调用工具:
任务被中断后恢复:
4.6 持久化多轮会话
每次执行
continue会复用最近的conversation_id:也可以指定会话:
4.7 交互式终端
普通 stdin 交互:
全屏 TUI:
等待模型时界面显示动态省略号;任务完成后一次性显示回答。右侧状态区展示会话、模型配置、Token、逻辑 KV、RSS 和 GPU 显存等信息。
常用斜杠命令:
例如:
这些命令只约束本轮必须使用指定 Capability。
tui.show_thinking或--show-thinking只控制是否展示模型返回的原始思考内容;只有engine.disable_thinking = false时,支持 Thinking 的模型才通常会生成该内容。4.8 测试
运行单元测试:
只运行 R1/R2 相关测试: