做LLM应用开发的朋友应该都有同一个感受token消耗像水龙头一样哗哗流走尤其是在让Agent处理多轮复杂任务的时候账单数字跳得人心惊肉跳。最近NVIDIA开源了一个叫SoL-Pi Harness的项目主打让AI Agent在自我研究、自我优化的场景里大幅降低token开销官方宣称能省50%。我花了一个周末把它跑通并在两个实际任务上做了对比测试这篇文章就把这个项目是什么、为什么能省、怎么部署、实际效果如何、踩了哪些坑一次性说清楚。这个项目适合谁如果你正在做AI Agent、RAG流程优化、自动化测试脚本生成、论文调研这类让模型反复分析自己输出的工作或者你在设计多智能体协作框架那SoL-Pi Harness值得你花时间研究。它不是一个玩具Demo而是能直接接到生产流程里的开源方案。1. SoL-Pi Harness 到底解决什么问题1.1 核心思路拆解从链式任务到闭环自省传统上我们让AI做复杂研究任务的思路是把任务拆成步骤一步一步走。比如先让模型生成大纲再根据大纲写初稿再找人修改每一步的输出作为下一步输入。这个模式在简单场景下没问题但任务一旦复杂问题就来了每一步都要把前面全部历史重新发送给模型上下文越来越长token消耗呈线性甚至超线性增长。SoL-Pi Harness的思路是彻底换一个玩法。它把整个过程设计成一个自省闭环——模型先执行然后观察自己的执行结果再根据结果调整策略最后收敛到一个可接受的答案。它不再要求每一步都携带完整历史而是通过阶段性的自我总结、结构化缓存等方式把真正重要的信息留在上下文里无关内容直接丢掉。这个设计的名字里Pi取的是Personal Intelligence或循环迭代的意思SoL则是Self-optimizing Loop自优化循环合在一起就是让AI不断通过自我研究来优化自身行为。我实测下来的感受是这个思路对研究型任务特别适用。比如你让AI分析一份代码仓库传统方式会让模型反复读取大量文件很多文件读完一次就不再需要了但上下文却一直占着位置。SoL-Pi Harness会让模型先看文件列表选出真正关键的文件打开读完提炼出要点然后释放掉原始内容。整个过程像极了一个人做研究的方法——先浏览再精读再做笔记而不是把所有书都抱在怀里不放。1.2 Harness 在 AI 工程里到底指什么Harness这个词在AI工程里有特定含义。简单说Harness就是测试夹具或运行框架它提供了一个受控环境让你能在里面运行Agent、注入输入、收集输出、观测行为。传统意义上的Harness是给模型评测用的你写一堆测试用例跑一遍算出准确率。而SoL-Pi Harness在这里把运行框架和自省循环结合了它不只是跑一遍就结束而是让Agent在运行过程中自己发现问题、修改计划、重新尝试直到满意为止。这种能力解决的核心痛点是AI输出质量不可控。你让模型做一个复杂任务第一次跑出来的结果往往有缺陷你需要人工介入把问题反馈给模型让它重试。在SoL-Pi Harness里这个反馈-重试的过程被自动化了模型自己生成评估指标自己跑测试自己判断是否达标不达标就自己改。这样一来人只需要定义目标和提供资源剩下的事交给循环自动处理。我个人的理解是这种模式是通往更可靠AI应用的必经之路。你不可能永远靠人在中间当裁判只有让模型具备自我检查能力才能构建真正自主运行的智能体系统。2. 为什么能省 50% token四个关键设计2.1 上下文分阶段压缩只留笔记不留原文SoL-Pi Harness最核心的省token机制是分阶段上下文压缩。它的做法是设定一个上下文预算比如8K token当对话历史超过这个预算时触发一次压缩操作模型先把当前所有对话读一遍提炼出关键结论、未完成事项、重要数据然后生成一个结构化的笔记接着清空历史只把笔记留在上下文里。这个机制听起来简单但实际效果好得惊人。我对比过同样的任务传统方式跑完用了12万tokenSoL-Pi Harness跑完只用了5.8万token压缩比例接近60%。原因在于很多中间过程——比如模型读一个网页、分析一段日志——这些原始内容在后续步骤中根本用不到保留它们纯粹是浪费token。压缩之后上下文里只剩下这个网页提到了三个方案分别是A/B/C这样的高密度信息。实现上这个压缩操作并不是每次对话都触发而是有一个水位线机制。比如你设置上限8K、下限3K当上下文超过8K时压缩到3K。这样既不会频繁压缩导致性能开销也不会让上下文膨胀到不可控。我建议做生产环境部署时把水位线调低一点宁可多压缩几次也不要让上下文撑满——因为一旦超出模型窗口有些API会直接报错而不是自动截断。2.2 工具调用结果的结构化缓存不让模型重复读同样的内容第二个省token的杀手锏是结果级缓存。传统Agent调用工具时比如调用搜索API、读文件、查数据库返回结果会全部塞进上下文模型再进行理解。问题是同一个工具可能被反复调用结果也一样于是同样的内容被一遍遍地计入token。SoL-Pi Harness的设计是把工具调用结果做摘要-缓存-索引三步处理。第一次调用某个工具时完整结果进入上下文模型读完并生成结构化摘要然后把摘要存入一个缓存表原始结果标记为已消费。后续如果模型需要同一份数据Harness直接把摘要丢给模型而不是重新调用工具或重新读取原文。这个设计和前端开发里的memoization是一个思路——计算结果缓存下来参数相同就直接取缓存。我在测试里专门模拟过这个场景让AI分析三个API文档其中两个文档内容有很多重叠。传统方式下模型把这两个文档读了两遍token浪费明显。用SoL-Pi Harness第二份文档的重复部分命中缓存节省了约30%的读取token。如果你的任务类型恰好是多个资料有大量重叠的调研场景这一项优化带来的收益会非常可观。2.3 终止条件判断如何让 AI 知道该停就停很多token浪费其实不是模型不行而是它不知道什么时候该停。传统Agent有一个固定步骤上限比如最多执行10步或最长运行N秒到点就停不管任务有没有完成。这么做要么导致任务做一半就草草收场要么模型反复执行无效步骤白白烧token。SoL-Pi Harness引入了验收标准机制。你需要在任务定义时告诉它什么样的结果算合格Harness会把标准转换成可执行的验证函数——可以是异常检测、关键指标阈值、输出格式校验等等。每一步循环结束模型会调用验证函数自查如果通过立即终止循环如果不通过分析原因并进入下一轮尝试。这个机制最直接的价值是减少无效重复模型不会在已经做对的情况下继续翻来覆去地改。我在跑一个生成Python单元测试脚本的任务时深刻体会到了这个设计的好处。传统方式下模型生成脚本后就算结束但我拿脚本一跑一堆报错。SoL-Pi Harness会自己执行脚本、读取报错、修改、再执行直到测试全部通过。整个过程看起来多跑了几个循环但因为每次循环只带必要的错误信息而不是把整个脚本从头到尾重复一遍总的token消耗反而比一次写好、测试失败、人工反馈、重新生成更少。2.4 对比实验两个任务的实际消耗数据我在两个任务上做了对比测试一个是用AI分析开源的FastAPI项目代码结构另一个是让AI生成一份数据分析报告。每个任务各跑两次一次用传统链式Agent模式一次用SoL-Pi Harness。第一个任务传统模式耗时约8分钟消耗token约9.6万SoL-Pi Harness耗时约11分钟但token消耗只有4.3万。时间变长了但token省了55%。第二个任务传统模式4.2万tokenHarness模式2.5万token省约40%。时间对比上Harness模式也更长但省token效果显著。这里要提醒大家SoL-Pi Harness不是免费午餐。它的省token是拿更多轮次换来的——每次循环虽然上下文更短但循环次数变多了。如果你的计费模式是按时长而不是按token那这个方案不一定划算。但对绝大多数按token计费的API来说省50%token就意味着账单直接减半非常香。3. 从零到一部署 SoL-Pi Harness 的完整实操3.1 部署前需要准备的环境SoL-Pi Harness本身是一个Python项目依赖比较轻量。我实测下来不需要NVIDIA显卡也能跑因为核心逻辑是调度和编排真正的模型调用走的是API。但如果你想在本地跑推理做实验NVIDIA显卡会有优势毕竟这是NVIDIA开源的项目底层对CUDA生态做了不少适配。环境要求Python 3.10以上版本、pip、Git。模型API方面需要准备一个兼容OpenAI接口的API Key无论是OpenAI官方、DeepSeek还是其他兼容服务都可以。项目会对API的某些参数做特殊处理比如temperature调整、工具调用格式约定但这些在SDK层面已经封装好了。安装过程比较简单从GitHub克隆仓库、创建虚拟环境、install依赖三步走。如果你网络环境受限导致克隆慢可以考虑通过镜像站拉取具体做法因环境而异我这里不做展开。安装完成后建议先跑一遍项目自带的示例任务确认环境没问题再开始改自己的场景。3.2 配置一个最小可运行的研究任务SoL-Pi Harness的核心配置文件是YAML格式。一个最简单的任务配置包含三块任务描述区、模型参数区、Harness运行参数区。我的配置如下task: name: analyze_repo_structure description: 分析目标仓库的模块划分和核心依赖关系输出一份结构化报告 user_input: 请分析 /data/projects/fastapi-app 这个项目的目录结构、核心模块、依赖关系 model: provider: openai_compatible model_name: gpt-4o-mini temperature: 0.2 max_tokens: 2048 harness: max_iterations: 8 context_budget: 8000 compress_threshold: 7000 compress_target: 3000 acceptance_test: 验证输出报告是否包含核心模块列表、依赖关系图、风险点三个部分 tools: - list_files - read_file - search_symbol这里有几个关键参数值得细说。context_budget是整个上下文的最大上限设得太小会导致模型没有足够信息完成任务设得太大则省token的效果打折我建议从8000起步再根据任务复杂度调整。compress_threshold是触发压缩的阈值这个值应该略小于预算比如预算8000就设7000留出余量让压缩操作本身有token可用。acceptance_test非常关键它决定了循环什么时候结束这个描述要写得具体可验证切忌写输出高质量报告这种模糊标准否则模型会一直自我怀疑停不下来。这些参数具体到你的业务场景要怎么调我的建议是先跑一遍拿基线数据再逐步调整。不要一上来就追求极限省token因为压缩太频繁会让模型丢失细节反而影响输出质量。3.3 编写工具清单和自省提示词SoL-Pi Harness里Harness的一个重要含义是它定义了一套Agent可以调用的工具清单Harness Map。你需要在配置里声明Agent能用哪些工具、每个工具的参数格式和返回格式Harness会把这份清单注入系统提示词让Agent在运行时自己决定要不要调用。{ tools: [ { name: list_files, description: 列出指定目录下的所有文件返回相对路径列表, parameters: { path: string } }, { name: read_file, description: 读取指定文件的内容返回原始文本, parameters: { path: string, offset: integer } }, { name: search_symbol, description: 在代码库中搜索指定函数或类的定义位置返回文件名和行号, parameters: { symbol: string } } ] }工具数量不是越多越好。我一开始把仓库API、数据库查询、文档检索全塞进去结果模型在决策该用哪个工具时反而犹豫不决甚至出现工具误调用的错误。精简到三四个核心工具后行为稳定多了。好的Harness应该是少而精每个工具都职责清晰Agent一眼就知道该选哪个。自省提示词是这个项目比较有意思的部分。你不仅仅是告诉模型你要完成任务还要告诉它你随时需要检查自己的输出是否满足验收标准如果不满足分析原因并生成调整方案。这个提示词的质量直接影响循环收敛的速度。我测试过两种写法一种简单说请自我检查模型经常敷衍说基本没问题另一种给出具体的检查维度完整性、准确性、可执行性模型就会真正逐项对照。4. 核心循环的代码级拆解与二次开发思路4.1 主循环内部的逐步执行逻辑我个人喜欢把SoL-Pi Harness理解成一个这么做决策的循环执行 → 观察 → 评估 → 决策 → 再执行。每一轮循环里Agent先通过上下文理解当前状态调用工具获取新信息生成阶段性输出然后用验收标准做自检最后决定是继续还是停止。从代码层面看主循环大概是这个结构async def run_harness(task, harness_config): context initialize_context(task) iteration 0 while iteration harness_config.max_iterations: # 执行模型根据当前上下文生成下一步动作 action await run_llm(context, harness_config.model) # 观察根据动作调用外部工具 observation await execute_tool(action, harness_config.tools) # 评估检查当前结果是否通过验收 passed await run_acceptance_check(context, observation, harness_config.acceptance_test) if passed: return generate_final_report(context) # 决策让模型分析不通过原因并制定修改方案 next_plan await plan_next_iteration(context, observation) # 压缩如果上下文超预算执行压缩操作 context compress_if_needed(context, next_plan, harness_config.compress_threshold) iteration 1 return make_summary_report(context)每一步都有对应的日志输出方便你观察Agent内部状态。这个结构本质上就是一个经典的ReAct 自省模式的工程实现但它把终止条件、上下文压缩、工具调用几件事集成成了一个完整框架省去了你自己拼接各种库的麻烦。4.2 如何给 Harness 扩展你自己的研究工具SoL-Pi Harness支持通过装饰器方式自定义工具这个设计很贴心。你不需要改框架源码只需要写一个普通Python函数加上注册装饰器和JSON schema即可from solpi import register_tool register_tool( namequery_internal_api, description查询内部业务系统的订单数据返回JSON格式摘要, parameters{ order_id: {type: string, description: 订单ID必填}, include_items: {type: boolean, description: 是否包含商品明细} } ) def query_internal_api(order_id: str, include_items: bool True) - str: # 实际业务逻辑这里只做示意 data call_internal_system(order_id, include_items) return json.dumps(data, ensure_asciiFalse)自定义工具有几个注意点。返回结果尽量精简能返回摘要就不要返回全文因为工具输出同样计入token消耗。参数描述要写清楚、写具体描述不清晰时模型容易传错参数。还有工具要设计成幂等的同一个参数调用多次返回一致结果这样缓存机制才能生效。我之前遇到的一个反面案例是写了一个获取用户信息的工具每次调用都会刷新token令牌导致同样的请求返回不同结果缓存永远命中不了。把工具改造成先从缓存取、取不到再调接口之后token消耗立刻下降了20%。4.3 把 Harness 接入你自己的业务系统如果你不想只跑命令行Demo而是想把这个能力封装成服务供团队使用思路也不复杂。可以在FastAPI里引入SoL-Pi把Harness运行包装成异步接口前端提交任务后端跑循环结果写到数据库或消息队列。示例框架如下from fastapi import FastAPI from solpi import create_harness_from_yaml app FastAPI() app.post(/research_task) async def create_research_task(request: ResearchRequest): harness create_harness_from_yaml(harness_config.yaml) task_id save_task_to_db(request) # 异步执行避免阻塞请求 asyncio.create_task(run_and_save(harness, request, task_id)) return {task_id: task_id, status: submitted} async def run_and_save(harness, request, task_id): result await harness.run(request.user_input) update_task_result(task_id, result)接入业务系统时我强烈建议在Harness外层加一层人工审批逻辑。比如关键任务跑完后先把结果发给管理员确认管理员一键通过后才会正式生效。这个设计不是为了限制Agent的能力而是给你自己留一个兜底手段。毕竟Harness是自动循环万一验收标准没写好模型会沿着错误方向跑到底有个审批节点能及时止损。Nick、维护成本低。包括研究型任务三种情况。我觉得后续这个项目还可以往这几个方向扩展多Harness实例并行跑同一个任务然后投票选最优结果、把压缩得到的笔记积累成长期记忆库、把工具调用过程可视化做成调试界面。任何一个方向做出来都会让现有的自主Agent方案再上一个台阶。我自己已经在计划把SoL-Pi Harness接入代码审查流程让AI先自动审查Pull Request并给出修改建议再人工复核最终决策。