【Agent Harness实战】认清现实吧,LLM就是个“超级赌场”,而我们需要的是一套“紧箍咒”

认清现实吧,LLM就是个"超级赌场",而我们需要的是一套"紧箍咒"

📌 摘要:LLM本质上是一个无状态的"条件概率文本生成器",它没有记忆、没有意识、不会创新,且天生存在弱指令遵守和幻觉两大致命弱点。不加约束地使用LLM就像让一个"天才但散漫的实习生"独立负责生产任务,注定会出问题。本文提出"Harness(约束框架)"的概念------通过记忆系统、系统调用门、校验Agent、知识图谱和Batch Agent等工程手段,给LLM装上"规则引擎",让它从"不可靠的赌场"变成"可信赖的生产力工具"。核心观点:别神化AI,要工程化AI。
🔍 SEO关键词:LLM本质、条件概率文本生成器、LLM幻觉、弱指令遵守、Harness约束框架、Agent工程化、LLM无状态、知识图谱、AI系统设计、LLM生产部署

之前我的系列文章一直在聊"流马怎么设计"、"用了什么技术"、"能带来什么收益"。但今天我想退一步,聊聊一个更根本的问题:

LLM到底是什么?它擅长什么?不擅长什么?为什么我们需要一套"Harness"来约束它?

这些问题的答案,决定了我们到底应该把AI当成"神"来崇拜,还是当成"工具"来调教。

一、LLM的本质:一个没有状态的"条件概率文本生成器"

如果你用过LLM的API,你会发现一个"反直觉"的事实:LLM本身没有任何记忆。 它不知道上一轮对话说了什么,不知道你是谁,甚至不知道自己在哪。

每一次你调用它,你发给它的消息长这样:

diff 复制代码
系统提示词(Agent.md、Skills、Rules、Specs、Powers...)
+ 对话历史(如果有的话)
+ 当前用户的输入

LLM拿到这一大坨文本,开始工作。它的工作原理非常"简单粗暴":

  1. 根据你给的输入条件,计算下一个词的概率分布。
  2. 从这个概率分布中,选出第一个词。
  3. 把选出的第一个词拼到输入后面,重新计算第二个词的概率分布。
  4. 再选第二个词。
  5. 递归执行,直到生成完整的回答。

这就是全部。没有思考,没有意识,没有状态。

你可能会问:"那它怎么记住对话上下文?"答案是:它不记,是你每次都把历史对话重新塞给它。 LLM本身是无状态的------每次请求都是一次全新的计算,它的"记忆"完全依赖于你每次喂进去的上下文。

这也解释了为什么你可以随时切换模型(从GPT-4换到Claude,或者换到Qwen),只要上下文一致,任务可以无缝继续。因为LLM只是一个"接收文本、返回文本"的函数,它的内部状态不影响外部任务的一致性。状态由外部系统(就是我们一直在做的Harness)维护,LLM只负责"给定输入,生成输出"。

至于温度(Temperature)、Top-K、Top-P这些参数,它们属于后处理工程 ,不影响LLM的本质。温度高,LLM选词的随机性大,输出看起来更"有创意";温度低,LLM更倾向于选概率最高的词,输出更"保守"。但无论怎么调,它都是在已有的概率分布上做文章。它不会"顿悟",不会"灵光一闪",不会创造出训练数据中从未出现过的真正新概念。

二、LLM的致命弱点:弱指令遵守 + 幻觉

因为LLM的本质是"条件概率",所以它有两个无法根治的毛病。

第一个毛病:弱指令遵守。

你告诉它"必须用JSON格式输出",它答应了。但输出的时候,可能多打了一个逗号,少加了一个引号。为什么?因为它在生成每个词的时候,只是在考虑"下一个词是什么概率最高",而不是"我有没有严格遵守某个规则"。

你把一堆规则写在System Prompt里------它都会"看",但会不会遵守?看运气。看概率。看它训练数据里类似的规则被遵守的频率。

这就是"弱指令遵守":它能理解你的指令,但它无法保证每次都不犯低级错误。 因为它不是一个"函数",不会"编译"------它只是一个"文本生成器"。

第二个毛病:幻觉。

这也是条件概率的必然结果。当LLM遇到一个它"不太确定"的问题时,它不会说"我不知道"。它会基于训练数据中见过的类似模式,"编"一个听起来合理的答案。这个答案可能格式完全正确、语气非常自信,但内容完全错误。

幻觉不是bug,是feature。 LLM的设计目标就是"生成",不是"验证"。验证需要外部世界的信息------一个它没有的"现实锚点"。

三、既然创新不行,守成也不行,那LLM不是"鸡肋"了吗?

读到这,你可能觉得:创新任务不适合LLM,因为它只会根据先验出结果。非创新任务也不适合,因为它总会犯错。那LLM不就是个鸡肋吗?

对,如果不加任何约束,它就是鸡肋。 写个周报还行,写生产代码?你敢直接部署它生成的代码不经人工审查吗?我猜你不敢。

但这不是LLM的错,这是我们用法的错。 我们把一个天生"无状态、弱约束、会幻觉"的文本生成器,当成一个"全知全能的智能体"来用。出了问题,我们骂它"不靠谱",但其实是我们自己没给它搭好台子。

这就是Harness存在的意义。Harness不是给LLM锦上添花,而是给LLM雪中送炭。

四、Harness怎么做:给"赌场"装上"规则引擎"

LLM是一个"超级赌场"------它每次生成一个词,都是在赌概率。而Harness,就是给这个赌场装上规则引擎、审计系统和质量门禁。

在我的流马(Gliding Horse)里,Harness是这样调教LLM的:

1. 用记忆系统弥补LLM的"无状态"

LLM自己没记忆,但流马有四层记忆(L0-L3)。对话历史不用全塞进上下文,而是存摘要和IRI。LLM需要细节时,沿着IRI去图数据库里查。状态由Harness维护,LLM只是一个"查询引擎"。

2. 用系统调用门弥补LLM的"弱指令遵守"

你写Prompt说"不要删文件"?LLM可能还是会删。但流马在代码层拦截:PA想写文件?白名单里没有,直接拒绝。DA想调用危险API?Ed25519签名对不上,直接拒绝。软约束在Prompt里,硬约束在代码里。Harness替LLM兜底。

3. 用CA检查Agent和阶段门禁弥补LLM的"幻觉"

LLM生成了一份PRD,说"功能模块已完整"。CA Agent会自动检查:真的完整吗?缺少参与者定义?打回重做。这个检查不是LLM的"自我反省",而是独立于LLM之外的校验Agent在把关

4. 用知识图谱弥补LLM的"没有现实锚点"

LLM说"上次我们讨论过JWT密钥长度是256位"。真的吗?流马自动查知识图谱里的历史决策节点,验证事实。如果LLM在胡编,知识图谱会"打脸"。

5. 用Batch Agent让系统"自我优化"

技能图谱用久了会乱,知识碎片会散,失败模式会堆积。流马的后台整理Agent自动做技能合并、实体解析、失败模式挖掘。**系统越用越聪明,不是因为LLM变强了,而是因为Harness在持续优化。 系统越用越聪明,不是因为LLM变强了,而是因为Harness在持续优化。

下面是流马(Gliding Horse)中Harness的整体系统架构图,直观展示各组件如何协同工作:

flowchart TB subgraph User[&#34;用户层&#34;] UI[&#34;用户界面 / API&#34;] end subgraph LLM[&#34;LLM 层&#34;] LLM_Engine[&#34;大语言模型<br/>(条件概率文本生成器)&#34;] end subgraph Harness[&#34;Harness 规则引擎层&#34;] direction TB Memory[&#34;记忆系统 L0-L3<br/>维护状态与摘要&#34;] Gate[&#34;系统调用门<br/>白名单 / Ed25519 签名&#34;] CA[&#34;CA 检查 Agent<br/>独立校验与门禁&#34;] KG[&#34;知识图谱<br/>事实锚点与验证&#34;] Batch[&#34;Batch Agent<br/>后台自我优化&#34;] end subgraph Storage[&#34;存储层&#34;] GraphDB[&#34;图数据库&#34;] FileSys[&#34;文件系统&#34;] end UI -->|&#34;用户请求&#34;| Harness Harness -->|&#34;查询/生成&#34;| LLM_Engine LLM_Engine -->|&#34;返回结果&#34;| Harness Memory -->|&#34;状态管理&#34;| GraphDB KG -->|&#34;事实验证&#34;| GraphDB Gate -->|&#34;安全拦截&#34;| FileSys CA -->|&#34;质量校验&#34;| UI Batch -->|&#34;定期整理&#34;| GraphDB style Harness fill:#4a90d9,color:#fff,stroke:#2c5f8a style LLM_Engine fill:#e67e22,color:#fff,stroke:#b85e0a style Memory fill:#27ae60,color:#fff style Gate fill:#e74c3c,color:#fff style CA fill:#8e44ad,color:#fff style KG fill:#f39c12,color:#fff style Batch fill:#1abc9c,color:#fff

架构说明:用户请求先进入Harness层,由Harness统一调度LLM、管理记忆、执行安全检查、验证事实,并定期自我优化。LLM仅作为"查询引擎"被调用,不直接接触存储或执行危险操作。

**

五、总结:别把LLM当神,把它当"天才实习生"

LLM是一个天才但散漫的实习生。它学富五车(训练数据量大),反应极快(推理速度快),但:

  • 不记事儿(无状态)
  • 不守规矩(弱指令遵守)
  • 爱胡扯(幻觉)
  • 没有创新(基于先验)
  • 不懂验证(只会生成)

如果你直接让它独立负责生产任务,它一定会闯祸。 但如果你给它配上一套完善的工程体系------记忆系统帮它记事儿,校验系统帮它把关,门禁系统帮它守住底线,知识系统帮它验证事实------它就能从一个"散漫的天才"变成"可信赖的生产力"。

这就是Harness的价值:不是让LLM变得更强,而是让LLM变得靠谱。

流马不是在做"更强的AI",而是在做"让AI可以放心用"的工程基座。

六、最后说句心里话

AI圈现在有两个极端:一派把LLM当成"通向AGI的神谕",一派把LLM当成"只会写周报的玩具"。

我的立场在中间:LLM是伟大的发明,但它只是一个"零件"。 它需要操作系统、需要文件系统、需要权限管理、需要质量保障------就像CPU很强大,但没有主板、内存、操作系统,它就是个发热的硅片。

LLM是天才,Harness是纪律。天才需要纪律,才能创造价值。

我这套系统叫 Gliding Horse(流马) ,所有代码都在 GitHub 上:github.com/doiito/glid...

*系列第15篇了。写了这么多,其实核心思想只有一个:别神化AI,工程化AI。如果你也在做Agent系统,希望这个系列能让你少踩一些坑。

七、实战:用Harness约束LLM的Python示例

前面我们聊了Harness的理念------给LLM装上"规则引擎"。下面用一个完整的Python示例,展示如何通过一个简单的Harness类来包装LLM调用,实现记忆缓存输出格式校验内容安全检查

7.1 核心Harness类

python 复制代码
import json
import re
import hashlib
from typing import Any, Callable, Optional

class Harness:
    """
    Harness 类:给 LLM 调用套上"紧箍咒"
    
    对应文章中的 Harness 理念:
    - 记忆缓存 → 避免重复调用,节省成本
    - 格式校验 → 确保 LLM 输出符合预期结构
    - 安全检查 → 过滤敏感/违规内容
    """
    
    def __init__(self, llm_func: Callable[[str], str]):
        # llm_func:实际的 LLM 调用函数(如 OpenAI API 封装)
        self.llm_func = llm_func
        # 记忆缓存:存储已处理过的 prompt 及其结果
        self._cache: dict[str, str] = {}
        # 关键词黑名单:内容安全检查用
        self._blocklist: set[str] = set()
    
    # ---------- 记忆缓存 ----------
    def _cache_key(self, prompt: str) -> str:
        """生成缓存键,对应文章"缓存机制""""
        return hashlib.sha256(prompt.encode()).hexdigest()
    
    def _check_cache(self, prompt: str) -> Optional[str]:
        """命中缓存直接返回,对应文章"减少重复调用""""
        key = self._cache_key(prompt)
        return self._cache.get(key)
    
    def _update_cache(self, prompt: str, response: str):
        """更新缓存"""
        key = self._cache_key(prompt)
        self._cache[key] = response
    
    # ---------- 格式校验 ----------
    def _validate_json(self, text: str) -> dict:
        """
        校验 LLM 输出是否为合法 JSON
        对应文章"输出格式约束"------LLM 可能输出非结构化文本
        """
        try:
            return json.loads(text)
        except json.JSONDecodeError as e:
            raise ValueError(f"输出格式校验失败:不是合法 JSON({e})")
    
    # ---------- 安全检查 ----------
    def add_blocklist(self, keywords: list[str]):
        """添加关键词黑名单,对应文章"内容安全过滤""""
        self._blocklist.update(k.lower() for k in keywords)
    
    def _safety_check(self, text: str) -> bool:
        """
        检查输出是否包含黑名单关键词
        对应文章"安全护栏"------防止 LLM 生成违规内容
        """
        lower_text = text.lower()
        for keyword in self._blocklist:
            if keyword in lower_text:
                return False  # 未通过安全检查
        return True
    
    # ---------- 主调用入口 ----------
    def invoke(self, prompt: str, require_json: bool = False) -> Any:
        """
        带 Harness 约束的 LLM 调用
        
        参数:
            prompt: 输入提示词
            require_json: 是否要求输出为 JSON 格式
        
        返回:
            校验通过后的 LLM 输出
        
        对应文章"Harness 工作流":
        1. 查缓存 → 2. 调用 LLM → 3. 格式校验 → 4. 安全检查 → 5. 更新缓存
        """
        # 步骤1:查缓存
        cached = self._check_cache(prompt)
        if cached is not None:
            print("[Harness] 命中缓存,跳过 LLM 调用")
            return cached
        
        # 步骤2:调用 LLM
        print("[Harness] 调用 LLM...")
        raw_response = self.llm_func(prompt)
        
        # 步骤3:格式校验
        if require_json:
            raw_response = self._validate_json(raw_response)
        
        # 步骤4:安全检查
        response_str = json.dumps(raw_response, ensure_ascii=False) if isinstance(raw_response, dict) else str(raw_response)
        if not self._safety_check(response_str):
            raise RuntimeError("内容安全检查未通过:输出包含敏感关键词")
        
        # 步骤5:更新缓存
        self._update_cache(prompt, response_str)
        
        return raw_response

7.2 使用示例

python 复制代码
# 模拟一个 LLM 调用函数(实际使用时替换为 OpenAI / 本地模型 API)
def mock_llm(prompt: str) -> str:
    """模拟 LLM 返回 JSON 格式的天气信息"""
    return json.dumps({
        "city": "北京",
        "temperature": 22,
        "condition": "晴",
        "advice": "适合户外活动"
    })

# 创建 Harness 实例
harness = Harness(llm_func=mock_llm)

# 添加安全关键词过滤
harness.add_blocklist(["暴力", "色情", "赌博"])

# 调用 LLM,要求 JSON 输出
try:
    result = harness.invoke(
        prompt="北京今天天气怎么样?",
        require_json=True
    )
    print(f"✅ 校验通过,结果:{result}")
    # 输出:{'city': '北京', 'temperature': 22, 'condition': '晴', 'advice': '适合户外活动'}
    
    # 第二次调用相同 prompt → 命中缓存
    result2 = harness.invoke(prompt="北京今天天气怎么样?", require_json=True)
    print(f"✅ 缓存命中,结果:{result2}")
    
except ValueError as e:
    print(f"❌ 格式校验失败:{e}")
except RuntimeError as e:
    print(f"❌ 安全检查失败:{e}")

7.3 扩展思路

这个Harness类只是一个起点,你可以根据实际需求扩展:

功能 对应文章理念 实现方式
重试机制 容错性 校验失败时自动重试 LLM,最多 N 次
Token 预算控制 成本约束 在调用前预估 token,超限则截断 prompt
输出长度限制 质量保障 校验响应字符数,超限则截断或重试
多轮对话记忆 状态管理 用列表维护对话历史,每次调用自动拼接上下文
结构化输出 Schema 格式约束 用 Pydantic 定义输出模型,校验时自动转换

核心思想:LLM 是"天才实习生",Harness 是"纪律"。没有纪律的天才只会制造混乱,有了纪律的天才才能创造价值。

相关推荐
盒马盒马1 小时前
Rust:Vec
开发语言·rust
沪漂阿龙1 小时前
RAG 是什么?为什么大模型需要外挂知识库?
人工智能·架构·langchain
Benszen1 小时前
eNSP搭建企业网毕设(详细配置命令)
架构
盒马盒马1 小时前
Rust:String
java·前端·rust
vortex52 小时前
Alpine Linux 运行架构解析:从内核到容器的精简之道
linux·运维·架构
狗哥哥2 小时前
统一下载网关技术方案
前端·架构
Java识堂2 小时前
注册中心选型
架构
王二端茶倒水2 小时前
智慧酒店 WiFi 运营:从 Portal 认证到住客体验闭环
运维·物联网·架构
淡海水2 小时前
38-Hybrid生态-LeanCLR总览
unity·架构·c#·热更新·clr·hybrid·leanclr