写点粗浅的harness相关内容(1)

哇,刚上来一看,上篇文章都是三年前写的了。。。

反正近期也没什么事,记录总结一下近期学到的东西

1. harness是什么?

其实也没什么高谈阔论,我们直接从主旨说起吧:

harness 是什么?

我第一次琢磨的时候想的很简单:

LLM为核心,通过代码或者提前写好的提示词、校验规则,实现一个具有特定功能的系统。

这个理解对吗?只能说方向上没什么问题但说不上准确。实际上harness应该是"以LLM为核心决策组件,通过代码、提示词、工具、状态管理以及各种运行规则,把模型组织成一个能够持续完成任务的系统。"

很多人第一次接触harness,都会把它理解成提示词工程(正是在下= =)。

实际上提示词只是其中的一部分,思考是模型的事情,harness本身不负责思考。

harness真正负责的是:LLM的思考能够变成实际行动。


2. 关于use tool(重点)

那,那我问你,这个行动怎么实现的?

如果模型想查个天气,它总不能真的执行代码吧?

那当然是不行的,毕竟我们用的LLM就一生成模型,它能做的事情只有一件:唠嗑,根据上下文生成内容。它不会执行函数,也不知道什么是调用。真正执行工具的一直都是harness

那问题又来了,harness又是怎么知道模型想调用哪个工具的?

其实也就是在请求模型的时候,我们会把所有允许它用的工具一起发过去。

举个例子:

json 复制代码
{
  "name": "search_weather",
  "description": "查天气",
  "parameters": {
    "type": "object",
    "properties": {
      "city": {
        "type": "string",
        "description": "城市名"
      }
    },
    "required": ["city"]
  }
}

这串JSON通常被叫做 Tool Schema

可以理解成:我现在手头有的,模型可以用的工具。 模型看到这些Tool Schema之后,如果认为当前任务需要用到某个工具,则会返回一个结构化的数据,比如:

json 复制代码
{
  "tool_call": {
    "name": "search_weather",
    "arguments": "{\"city\":\"A市\"}"
  }
}

解析后就是:

json 复制代码
{
  "city": "A市"
}

这个数据很关键。它就是在告诉系统:"我觉得应该调用search_weather"。

那么问题又来了。

模型怎么知道返回这样的数据呢?我需要提前约束吗?其实是不用的,现在主流的大模型 API 基本都原生支。所以也不需要自己在提示词里先写一堆要求,比如 "返回什么什么格式的JSON"

而是通过 API 把 tools 一起传给模型。

模型如果决定调用工具,API 返回的就是专门的 tool_call/function_call 字段,就像上面写的那个一样。


3. harness具体怎么工作的?

收到这个格式的响应消息之后,harness才会开始工作。

它会先检查:

  • 这个工具在我们的tool schema中是否存在?
  • 参数是否合法?
  • 当前用户权限够不够?(如果有权限的设计)
  • 这个操作是不是危险操作?
  • 需要用户二次确认吗?

全部通过以后,才会跑去执行你的search_weather()

然而,得到执行结果之后,这个流程并不一定就结束了。


假设用户说:

帮我查看当前目录有哪些py格式的文件。

第一轮,模型不知道目录里有什么。于是它觉得该调用file_list方法。

scss 复制代码
file_list(".")

harness执行之后,得到:

css 复制代码
main.py
agent.py
README.md
test.py

显然任务到这里时还没有结束。

所以harness会把这次执行返回的结果也结果追加上下文中,于是下一轮发送给模型的内容,就变成了:

css 复制代码
User:
帮我查看当前目录有哪些py格式的文件。

Assistant:
调用了 list_files。

Tool:
main.py
agent.py
README.md
test.py

模型再次收到请求的时候,并不是接着上一轮继续思考,而是重新阅读整个上下文,那么看到这里它就知道当前目录里都有点什么文件。接下来它可以继续调用新的工具(比如find_py),也可以直接给出最终答案。

这也是agent最核心的运行循环:

  1. 模型根据当前上下文判断是不是需要工具。
  2. 如果需要工具,就返回tool call格式的数据。
  3. harness收到tool call的数据,做校验并执行工具。
  4. 将执行结果重新拼进上下文。
  5. 再给上下文整个丢给模型。
  6. 重复以上过程,直到模型认为任务已经完成,此时将结果作为最终输出。
markdown 复制代码
模型做决策
    ↓
harness调用工具
    ↓
工具返回结果
    ↓
harness更新上下文
    ↓
模型基于新的上下文重新做决策

因为模型实际每次请求时它都会重新读取当前提供给它的上下文,然后重新开始推理。所以整个过程中,真正持续存在的其实不是模型,而是harness持续更新的上下文。

它不一定就是保存聊天记录,还可以包括:

  • 工具调用历史
  • 当前任务状态
  • 中间变量
  • 记忆
  • 计划(如果有的话)
  • 已经生成的文件
  • 运行日志
  • ...

这些共同组成了agent当前的运行状态。但很多时候并不会把所有运行状态全部塞给模型。

因为因为上下文窗口是有限的,聊天来来回回十次百次千次,兴许上下文就爆了。

所以harness往往还需要一个上下文构建器,负责从你对话中积攒的大量上下文中挑出这一轮真正有价值的信息,再交给模型。

也就是说tool calling只是harness的基础。

真正决定一个agent好不好用的,往往是:

  • 状态怎么维护;
  • 上下文怎么提炼、语言怎么组织;
  • 哪些信息该给模型;
  • 哪些信息应该被丢掉(此处应有:"正在压缩上下文...")。

4. 简单总结

反正就一句话:模型负责思考,harness让模型思考转化为实际行动。

那么这篇文章内容就这些,当然了,本意还是为了归纳总结,自己能强化记忆已经不算白写,如果能帮到对harness有兴趣的人,那更是赚到了口牙

相关推荐
为你学会写情书2 小时前
LangChain.js RAG 实战:爬取掘金文章,让 LLM 告别幻觉
agent
带刺的坐椅2 小时前
SolonCode v2026.7.13 发布:多工作区协同、推理水平可控、子代理任务分组、工程体验再进化
llm·agent·codex·solon-ai·claudecode·opencode
AI程序员3 小时前
会写代码的 AI 很多,能算 Coding Agent 的没几个
人工智能·agent
zxfeng~5 小时前
伴眸-居家养老AI 眼镜智能体 技术方案
人工智能·agent·ai编程·智能眼镜
李燚5 小时前
Eino devops 调试系统源码:GraphCompileCallback 怎么工作(第50篇-E36)
数据库·golang·agent·devops·graphql·aiagent·eino
uncle_ll5 小时前
LangChain 实战指南:回调系统、自定义组件与有状态对话全落地
langchain·llm·embedding·agent·大模型开发·rag
mCell6 小时前
别给烂代码写注释——重写它
agent·代码规范·源码阅读
发光发热吧6 小时前
模型负责聪明,工程负责让聪明可靠
agent
CoovallyAIHub6 小时前
Claude Code 被曝安全后门:Coco 给出了 AI 协作的另一种答案
agent