在智能体(Agent)应用和自动化评测快速发展的背景下,LLM 不再只是“回答问题的模型”,而是被要求承担越来越多的工程任务。其中一类非常有代表性但又容易被忽视的问题,就是 Harness Optimization,也就是对测试执行框架、工具链、评测编排流程的优化。很多团队在落地大模型自动化能力时会发现,任务推理本身没问题,真正拖后腿的往往是整个执行链路的设计不合理、参数配置不到位、分支逻辑不够健壮。本文将围绕 HarnessOpt-Bench 这类评测方向,系统拆解“面向 Harness 优化的 LLM 能力评估”到底在评测什么、怎样设计评测集、如何量化模型表现。
本文面向对 LLM 评测、Agent 工作流、自动化测试平台感兴趣的后端开发者和算法工程师。读完你可以掌握 Harness 优化任务的基本分类,看懂 HarnessOpt-Bench 这类基准的设计逻辑,并能自己搭建一套最小可运行的评测流程。
1. Harness 优化到底在解决什么问题
1.1 什么是 Harness
Harness 在国内技术社区常被翻译为“测试装备”“测试夹具”或“执行框架”。在不同语境下含义略有差别,但核心指向是一致的:为了让某个目标程序、模型或智能体能够稳定运行,我们需要在其外部构建一套“驱动装置”。
用一个简单的例子说明。我们想测试一个排序函数sort_data()在 100 组随机数据上的表现:
def sort_data(data): return sorted(data)如果直接写 100 次调用,代码会非常冗余,而且很难统计失败率。于是我们会封装一层TestHarness,负责数据生成、调用被测函数、收集日志、统计结果。这就是最朴素的 Harness。
class SortTestHarness: def __init__(self, func): self.func = func def run(self, cases): results = [] for data in cases: try: output = self.func(data) results.append({"input": data, "output": output, "status": "ok"}) except Exception as exc: results.append({"input": data, "output": None, "status": "error", "msg": str(exc)}) return results在真实工程中,Harness 的范围会明显扩大,可能包括:
- 测试数据准备与清洗逻辑。
- 被测系统或模型的启动、关闭、重置逻辑。
- 请求构造、超时控制、重试机制。
- 外部依赖的 Mock 与桩服务。
- 评测结果的收集、聚合与可视化。
- 多环境部署时的参数切换与资源调度。
Harness 的质量,直接决定了整个自动化流程的稳定性和可信度。只要 Harness 里有一个分支逻辑写错了,后面所有评测结果都可能是无效的。
1.2 为什么需要 Harness 优化
Harness 写出“能跑”的版本并不难,难的是写出“高效、稳定、易扩展”的版本。实际开发中,我们经常面临几种情况:
- 用例数量从 100 涨到 10000,原来的串行执行方式导致评测时间过长。
- 被测服务偶尔超时,但 Harness 没有重试机制,导致大量误报失败。
- 新增一种输入格式时,需要改动 Harness 中多处代码,扩展性差。
- 日志只记录结果,不记录中间上下文,错误发生后无法定位根因。
- 多环境部署时,配置项散落在代码中,想切换环境必须改代码重新发布。
这些问题统称为“Harness 有待优化”。过去这项工作主要依赖资深测试开发工程师人工完成,而 HarnessOpt-Bench 想做的事情,就是把这类优化任务形式化,交给大语言模型来尝试解决,并建立一个标准评估尺度。
1.3 HarnessOpt-Bench 的核心思想
从命名就可以拆解出三层含义:
- Harness:代表评测对象,也就是优化目标 Workload。
- Opt:是 Optimization 的缩写,表示这类任务的核心不是“按照需求实现新功能”,而是在已有框架上做结构性调整,让执行效率、稳定性、可维护性等指标提升。
- Bench:Benchmark,表示这是一个标准化的测试基准,用于横向比较不同 LLM 的性能。
所以在 HarnessOpt-Bench 中,LLM 的输入是一份“现有 Harness 代码 + 一段优化诉求”,输出是一份“修改后的 Harness 代码”或“优化方案文本”。评估者再通过自动化方式验证修改后的 Harness 是否达到了预期指标。
这个方向和纯代码生成任务有本质区别。代码生成通常给一个自然语言描述,要求写出完整函数;Harness 优化则是给一段未达到生产标准的代码,要求做改造,改造前后接口语义要保持一致,不能为了性能牺牲正确性。
2. HarnessOpt-Bench 评测任务的分类与设计
2.1 任务分类维度
设计评测集之前,先要明确回答一个问题:哪些任务场景最能体现 LLM 的 Harness 优化能力?
参考工程实践中的高频痛点,可以划分为五类:
| 任务类型 | 典型问题 | 优化目标 |
|---|---|---|
| 执行效率优化 | 串行执行耗时过长、重复构建数据 | 吞吐量提升、响应时间下降 |
| 稳定性优化 | 缺少重试、超时设置不合理、连接池过小 | 失败率下降、异常恢复能力增强 |
| 可扩展性优化 | 写死配置、数据类型硬编码、无插件机制 | 新增场景改动量变小 |
| 可观测性优化 | 日志缺失、指标不完整、错误上下文丢失 | 日志覆盖度提升、错误定位时间缩短 |
| 资源管理优化 | 连接未关闭、线程池未释放、内存占用过高 | 资源利用率提升、内存泄漏减少 |
这五类并不是完全独立的。实际场景中一个 Harness 往往同时存在多个问题,但评测任务最好一次聚焦一个主目标,否则难以归因,也不方便打分。
2.2 评测样本的构成
一个标准评测样本应该包含以下字段:
- Task ID:唯一标识。
- Category:任务类型。
- Harness Code:初始 Harness 完整源码。
- Dependencies:运行时需要的第三方库列表。
- Optimization Request:自然语言描述的优化需求。
- Validation Script:用于自动验证修改后 Harness 的脚本。
- Metric Definition:本次任务的量化指标如何计算。
{ "task_id": "harness-opt-001", "category": "stability", "harness_code": "class HttpHarness:\n ...", "dependencies": ["requests"], "optimization_request": "当前 Harness 在调用外部 API 时经常因超时失败,请补充合适的超时控制与重试机制,失败后输出明确日志。", "validation_script": "python validate_harness_opt_001.py", "metric_definition": "pass@1, avg_latency, failure_rate" }与纯算法题不同,Harness 优化评测更接近“软件工程能力评测”。模型不能只写出一个能跑的函数,必须保证:
- 原有接口可以被外部继续调用。
- 优化项确实生效。
- 不引入新的兼容性问题。
- 改动在可接受的复杂度范围内。
2.3 为什么这种评估有难度
对 LLM 来说,Harness 优化任务有几个天然难点。
第一,上下文工程复杂。初始 Harness 可能包含大量配置和工具函数,真正需要修改的地方只有几行。模型需要先做代码定位,再做修改,这种“定位 + 修改”的模式比“从零生成”更难。
第二,正确性验证成本高。Harness 往往依赖外部服务,评测环境很难完全复现。如果 Harness 中有网络调用或数据库操作,自动验证脚本就必须做 Mock,否则评测无法稳定执行。
第三,指标之间存在权衡。例如增加重试机制能降低失败率,但可能提高平均延迟。如果优化目标不明确,模型很可能陷入“指标打架”的困境。
这些难点决定了 HarnessOpt-Bench 不能只用一个简单的准确率指标来评价模型,后面我们会专门讲指标设计。
3. 环境准备与总体评测流程
3.1 基础运行环境
构建 HarnessOpt-Bench 评测系统时,建议先准备好如下环境:
- 操作系统:Ubuntu 20.04 / 22.04 或 macOS,使用 Windows 时注意 mock server 的端口占用问题。
- Python 版本:3.10 或更高。
- 推理框架:兼容 OpenAI API 格式的模型服务,或者本地 vLLM 部署的开源模型。
- 辅助工具:pytest、requests、pydantic、pandas。
版本不是固定的,请按你实际使用的模型和框架调整。本文演示环境以 Python 3.10 为主,重点讲解评测链路如何搭建。
3.2 评测主流程
HarnessOpt-Bench 的评测流程可以拆成七个步骤:
- 加载评测任务集。
- 将任务输入给 LLM。
- 获取模型返回的优化后 Harness 源码。
- 提取代码部分。
- 构造临时评测目录并安装依赖。
- 运行验证脚本与指标计算脚本。
- 汇总结果并生成评测报告。
设计这套流程时要注意:构建评测系统本身也是 Harness 优化,因此评测框架也需要具备可观测性和稳定性。每一次模型输出都要保留原始内容,不能只保存最终得分,否则出问题时很难回溯。
3.3 示例项目结构
这里提供一个最小可扩展的项目结构:
harnessopt_bench/ ├── config/ │ └── settings.yaml ├── data/ │ ├── tasks.json │ └── examples/ ├── runner/ │ ├── evaluator.py │ ├── model_client.py │ └── validator.py ├── scripts/ │ ├── run_benchmark.py │ └── collect_result.py ├── requirements.txt └── README.md核心模块职责如下:
model_client.py:封装对大模型服务的调用。evaluator.py:调度整个评测流程。validator.py:对模型输出做格式校验与代码执行验证。settings.yaml:配置模型端点、温度参数、超时时间等。
4. 构建 HarnessOpt-Bench 评估数据集的完整案例
4.1 定义任务元信息
首先我们定义一个数据类,来描述一个 Harness 优化任务。这里用 Pydantic 做数据校验,避免脏数据进入评测流程。
from typing import List, Optional from pydantic import BaseModel, Field class HarnessTask(BaseModel): task_id: str = Field(description="任务唯一标识") category: str = Field(description="任务类型:efficiency/stability/extensibility/observability/resource") title: str = Field(description="任务标题") initial_code: str = Field(description="初始 Harness 代码") dependencies: List[str] = Field(default_factory=list, description="运行时需要的第三方库") optimization_request: str = Field(description="优化需求") validation_hint: Optional[str] = Field(default=None, description="验证提示")在实际评测中,initial_code应该来自真实重构案例的“优化前版本”,而不是人工临时编写的玩具代码。因为真实代码中的坑往往是隐性的,例如某个配置项没有暴露给调用方、某个异常被静默吞掉等,这些隐性细节才是评测模型的难点。
4.2 构造一个稳定性优化任务
下面我们构造一个典型任务:现有 HTTP 调用 Harness 没有超时控制,服务短暂故障时请求全部失败。
# 初始代码:http_harness_v1.py import requests class HttpHarness: def __init__(self, base_url, token): self.base_url = base_url.rstrip("/") self.token = token self.headers = {"Authorization": f"Bearer {token}"} def call_api(self, path: str, payload: dict): url = f"{self.base_url}/{path.lstrip('/')}" response = requests.post(url, json=payload, headers=self.headers) return response.json()这段代码存在三个明显问题:
- 没有超时设置。如果服务端一直不响应,
requests.post会一直阻塞。 - 没有重试机制。一次网络抖动可能直接导致整条评测链路失败。
- 没有状态码检查。即使请求返回 500,代码也当作正常响应处理。
优化诉求可以描述为:
给 HttpHarness 增加超时控制、重试机制与状态码检查。超时时间设为 5 秒,最多重试 3 次,指数退避。非 2xx 状态码需要抛出异常,并记录日志。保持 call_api 方法签名不变。4.3 编写验证脚本
验证脚本是整个评测中投入成本最高的部分。它要做到三件事:
- 用模拟服务验证优化后的 Harness 行为是否满足要求。
- 量化指标是否达标。
- 原有接口是否被破坏。
# scripts/validate_http_harness.py import json import time import threading from http.server import BaseHTTPRequestHandler, HTTPServer # 一个可控的模拟服务:前两次返回 500,第三次返回 200 class MockHandler(BaseHTTPRequestHandler): counter = 0 def do_POST(self): MockHandler.counter += 1 if MockHandler.counter <= 2: self.send_response(500) self.end_headers() self.wfile.write(b'{"error": "temporary failure"}') else: self.send_response(200) self.end_headers() self.wfile.write(b'{"ok": true}') def log_message(self, *args): pass def start_server(): server = HTTPServer(("127.0.0.1", 0), MockHandler) port = server.server_address[1] thread = threading.Thread(target=server.serve_forever, daemon=True) thread.start() return server, port def validate_harness(harness_code: str, port: int): # 将模型返回的代码写入临时文件并导入 local_ns = {} exec(harness_code, local_ns) HttpHarness = local_ns["HttpHarness"] harness = HttpHarness(f"http://127.0.0.1:{port}", "test-token") start = time.time() try: result = harness.call_api("v1/classify", {"text": "hello"}) elapsed = time.time() - start # 通过重试,最终应该得到成功响应 assert result.get("ok") is True, f"unexpected result: {result}" # 整体耗时应该小于 15 秒 assert elapsed < 15, f"too slow: {elapsed}" print(json.dumps({"status": "pass", "elapsed": elapsed})) except Exception as exc: print(json.dumps({"status": "fail", "error": str(exc)})) raise if __name__ == "__main__": import sys code_path = sys.argv[1] with open(code_path, "r", encoding="utf-8") as f: code_content = f.read() server, port = start_server() try: validate_harness(code_content, port) finally: server.shutdown()这个验证脚本不会直接判断输出必须等于某个值,而是看重试逻辑是否真正被触发。Mock 服务保证了前两次响应均为 500,只有实现重试的 Harness 才能最终拿到 200。这样做的好处是:即使模型“编”出一个看似合理的实现,验证环节也能把它挡住。
4.4 评估任务集的 JSON 示例
一个评测集通常是多个任务组成的 JSON 文件:
[ { "task_id": "harness-opt-001", "category": "stability", "title": "HTTP 调用 Harness 超时与重试优化", "initial_code": "class HttpHarness:\n ...", "dependencies": ["requests"], "optimization_request": "增加超时控制、重试机制与状态码检查,保持 call_api 签名不变。", "validation_hint": "使用本地 mock server 验证重试是否生效" }, { "task_id": "harness-opt-002", "category": "efficiency", "title": "批量任务 Harness 并发度优化", "initial_code": "class BatchRunner:\n ...", "dependencies": ["concurrent.futures"], "optimization_request": "将串行执行改为线程池并发,可配置最大并发数。", "validation_hint": "构造耗时任务验证总执行时间明显下降" } ]在构建评测集时,我建议始终保留一个“验证提示”字段。它不会直接告诉模型正确做法,但可以帮助评测维护者快速理解任务意图。
5. LLM 推理调用与结果提取
5.1 模型客户端设计
评测系统需要以代码方式调用 LLM。建议实现一个轻量客户端,支持请求重试、超时管理和结果缓存。
import json import time from typing import Optional import requests class ModelClient: def __init__( self, api_base: str, api_key: str, model_name: str, temperature: float = 0.2, max_tokens: int = 4096, timeout: int = 120, ): self.api_base = api_base.rstrip("/") self.api_key = api_key self.model_name = model_name self.temperature = temperature self.max_tokens = max_tokens self.timeout = timeout def chat(self, messages: list, n: int = 1) -> list[str]: url = f"{self.api_base}/chat/completions" headers = { "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json", } payload = { "model": self.model_name, "messages": messages, "temperature": self.temperature, "max_tokens": self.max_tokens, "n": n, } for attempt in range(3): try: resp = requests.post(url, json=payload, headers=headers, timeout=self.timeout) resp.raise_for_status() data = resp.json() return [choice["message"]["content"] for choice in data["choices"]] except Exception as exc: if attempt == 2: raise RuntimeError(f"model call failed: {exc}") from exc time.sleep(2 ** attempt)注意:/chat/completions路径只是 OpenAI 兼容接口的约定,不同的模型服务可能有差异。如果你使用本地 vLLM、Ollama 或国内大模型平台,请以对应服务的 API 文档为准。
5.2 Prompt 模板设计
Harness 优化任务的 Prompt 设计直接影响输出质量。比较推荐的模板结构如下:
你是一名资深测试开发工程师。下面给出一个待优化的 Harness 代码和一份优化需求。 要求: 1. 保持已有类名、方法名和对外接口不变。 2. 只输出修改后的完整 Python 代码,不要额外解释。 3. 代码必须可以直接导入执行。 优化需求: {optimization_request} 初始代码: ```python {initial_code}这个模板强调了三件事:接口不变、全量输出代码、不输出多余解释。如果模型输出中包含解释文字,会干扰后面的代码提取与执行,因此还需要实现一个“代码块抽取器”。 ### 5.3 抽取模型输出中的代码 很多模型在输出时会把代码放在 Markdown 代码块中。即使 Prompt 要求不输出解释,防御性解析依然有必要。 ```python import re from typing import List def extract_python_code(raw_output: str) -> str: """从模型输出中提取最可能完整的 Python 代码。""" # 优先提取 markdown 代码块 pattern = re.compile(r"```(?:python|py)?\s*\n(.*?)```", re.DOTALL) blocks = pattern.findall(raw_output) if blocks: # 选择最长的一段,通常是主体代码 return max(blocks, key=len).strip() # 如果没有 markdown 块,尝试按 class/def 起始位置截取 lines = raw_output.splitlines() code_lines = [] in_code = False for line in lines: stripped = line.strip() if stripped.startswith("class ") or stripped.startswith("def "): in_code = True if in_code: code_lines.append(line) if code_lines: return "\n".join(code_lines).strip() return raw_output.strip()代码抽取是评测系统中容易被忽略但非常重要的一步。如果没有这层防护,模型偶尔输出一段说明文字就会让整个验证流程失败。
6. 完整评测执行器实现
6.1 核心评测逻辑
我们设计一个Evaluator类,用于串联整个流程。它的主要职责包括:读取任务、调用模型、保存原始输出、执行验证、记录指标。
import json import os import subprocess import sys import tempfile from pathlib import Path from typing import Dict, List from model_client import ModelClient from validator import extract_python_code class Evaluator: def __init__( self, model_client: ModelClient, work_dir: str = "eval_output", max_attempts_per_task: int = 1, ): self.model_client = model_client self.work_dir = Path(work_dir) self.max_attempts_per_task = max_attempts_per_task self.work_dir.mkdir(parents=True, exist_ok=True) def build_prompt(self, task: dict) -> list: system_msg = "你是一名资深测试开发工程师,善于优化测试执行框架。" user_msg = f"""优化需求: {task['optimization_request']} 初始代码: ```python {task['initial_code']}要求:只输出修改后的完整 Python 代码,不要额外解释。保持类名和方法签名不变。""" return [ {"role": "system", "content": system_msg}, {"role": "user", "content": user_msg}, ]
def run_task(self, task: dict) -> dict: task_result = { "task_id": task["task_id"], "status": "fail", "error": None, "model_outputs": [], "metrics": {}, } prompt = self.build_prompt(task) for attempt in range(self.max_attempts_per_task): try: raw_output = self.model_client.chat(prompt, n=1)[0] task_result["model_outputs"].append(raw_output) code = extract_python_code(raw_output) code_path = self.write_code_to_temp(task["task_id"], code) ok, metrics = self.run_validation(task, code_path) task_result["metrics"] = metrics if ok: task_result["status"] = "pass" break else: task_result["error"] = metrics.get("error", "validation failed") except Exception as exc: task_result["error"] = str(exc) return task_result### 6.2 输出代码落盘与验证 `write_code_to_temp` 负责将模型输出的代码写入到带任务 ID 的临时文件。这样做可以方便后续人工查看失败样例。 ```python def write_code_to_temp(self, task_id: str, code: str) -> Path: task_dir = self.work_dir / task_id task_dir.mkdir(exist_ok=True) code_path = task_dir / "harness.py" code_path.write_text(code, encoding="utf-8") return code_path def run_validation(self, task: dict, code_path: Path) -> tuple: validation_script = self.work_dir / "validate" / f"validate_{task['task_id']}.py" if not validation_script.exists(): # 如果没有专门验证脚本,至少做语法检查 return self.static_check(code_path) cmd = [sys.executable, str(validation_script), str(code_path)] proc = subprocess.run(cmd, capture_output=True, text=True, timeout=300) if proc.returncode == 0: try: metrics = json.loads(proc.stdout.strip().splitlines()[-1]) except json.JSONDecodeError: metrics = {"stdout": proc.stdout, "stderr": proc.stderr} return True, metrics return False, {"error": proc.stderr, "stdout": proc.stdout}这里的关键点在于:验证脚本可能依赖第三方库,安装依赖应在评测环境初始化阶段完成,不应该在任务验证时临时执行pip install,否则评测结果会受到网络环境影响。
7. 指标设计与结果解读
7.1 基础指标:任务通过率
任务通过率是最直观的指标,计算公式为:
Pass Rate = 通过验证的任务数 / 总任务数这个指标衡量的是模型能否在给定约束下完成 Harness 优化。但单看通过率有一个问题:有些任务即使未完全通过,模型输出的方案也具备很好的参考价值,而通过率会掩盖这部分信息。
7.2 分级评估分数
建议引入分级评分,而不是简单的 0/1:
| 分数 | 含义 | 示例 |
|---|---|---|
| 0 | 输出无关内容或语法错误 | 模型没有输出 Python 代码 |
| 1 | 代码可运行但未解决问题 | 增加了超时参数但未实现重试 |
| 2 | 主要问题已解决,但存在遗漏 | 实现重试但未记录日志 |
| 3 | 完全解决且质量优秀 | 重试、超时、状态码检查、日志全部到位 |
这种分级方式更适合反映模型的实际工程水平。两名模型可能通过率一样,但一个经常拿到 2 分,另一个经常拿到 3 分,显然后者更可靠。
7.3 领域细分指标
根据不同任务分类,可以设计额外的量化指标:
- 效率类任务:优化前后执行时间下降比例、并发数提升幅度。
- 稳定性类任务:失败率下降比例、重试成功次数。
- 可扩展性类任务:新增一个数据格式时的代码改动行数。
- 可观测性类任务:日志覆盖的异常分支比例。
- 资源类任务:优化前后内存峰值对比。
这些指标的意义在于避免模型走捷径。例如某模型直接给所有请求timeout=0.001,理论上“超时控制”实现了,但实际不可用,这时通过率即使通过,延迟指标也会暴露问题。
7.4 结果汇总与报告
最终评测报告可以用 JSON 形式输出,便于后续可视化:
{ "model": "demo-model-v1", "total_tasks": 50, "pass_rate": 0.68, "avg_score": 2.4, "detail": [ { "task_id": "harness-opt-001", "category": "stability", "score": 3, "latency": 5.4, "has_retry": true } ] }8. 常见问题与排查思路
在实际构建 HarnessOpt-Bench 或类似评测系统时,常见问题主要集中在以下几类。
8.1 模型输出的代码无法通过语法检查
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
SyntaxError | 模型输出中夹带解释文字,导致整体不可解析 | 加强代码抽取逻辑,只提取最长代码块 |
ImportError | 依赖列表未注入运行环境 | 评测环境统一安装依赖,并在日志中打印缺失包 |
| 方法名不一致 | 模型擅自重命名了call_api | 验证脚本中显式断言类名与方法名存在 |
这类问题说明 prompt 模板还不够强约束。可以在 prompt 末尾增加一行:“请确保HttpHarness类存在,且call_api方法签名不变。”
8.2 模型偷懒:没有真正优化
有一些模型会直接复制初始代码,或者只做无意义的注释修改。此时验证脚本必须能够区分是否真正达到优化目标。
最好的办法是让“优化前代码”在验证脚本中不能通过。例如上面的 Mock Server 例子,初始代码没有重试,必然返回 500,验证脚本会直接失败。这样一来,模型无法通过“原样返回”蒙混过关。
8.3 验证脚本本身不稳定
验证脚本如果依赖网络、端口或外部服务,就可能导致误判。建议遵循以下原则:
- 所有外部依赖尽量 Mock。
- 使用随机空闲端口。
- 每次验证前重置服务状态。
- 验证脚本设置明确的超时时间。
8.4 模型超时或返回截断
当max_tokens设置太小时,模型可能在代码输出中途被截断。解决方法是调大max_tokens,并把temperature控制在一个较低的区间,比如 0.2 或 0.3,这样可以降低输出随机性。
9. Harness 优化的工程建议
9.1 配置与代码分离
不管是让 LLM 优化 Harness,还是人工编写 Harness,都应该遵循配置与代码分离的原则。把超时时间、重试次数、并发数、日志级别等参数放到配置文件或环境变量中,避免硬编码。
import os class HttpHarness: def __init__(self, base_url: str, token: str): self.base_url = base_url.rstrip("/") self.timeout = float(os.getenv("HARNESS_TIMEOUT", "5")) self.max_retries = int(os.getenv("HARNESS_MAX_RETRIES", "3")) self.headers = {"Authorization": f"Bearer {token}"}这样做的好处是:评测环境和生产环境可以使用同一套代码,只切换环境变量即可。
9.2 日志一定要带上上下文
优化 Harness 时,最容易被忽略的是日志。很多模型只加print("error"),没有错误码、没有请求 ID、没有耗时信息。工程化做法是结构化输出日志。
import logging import time logger = logging.getLogger("harness") def call_api(self, path: str, payload: dict): url = f"{self.base_url}/{path.lstrip('/')}" start = time.time() try: response = requests.post(url, json=payload, headers=self.headers, timeout=self.timeout) elapsed_ms = (time.time() - start) * 1000 logger.info( "api call finished", extra={"url": url, "status_code": response.status_code, "elapsed_ms": elapsed_ms}, ) response.raise_for_status() return response.json() except Exception as exc: elapsed_ms = (time.time() - start) * 1000 logger.error( "api call failed", extra={"url": url, "error": str(exc), "elapsed_ms": elapsed_ms}, ) raise9.3 优化必须服务于可衡量目标
给 LLM 提出 Harness 优化需求时,不要只说“优化一下性能”,而应该给出量化目标。例如:
- 将 1000 个样本的评测时间从 30 分钟降到 5 分钟以内。
- 将 API 调用失败率从 30% 降到 5% 以下。
- 新增数据类型时,适配代码改动量不超过 20 行。
这不仅是评测设计的原则,也是我们日常使用 LLM 辅助开发时的最佳实践。目标越具体,模型输出的方案越可落地。
9.4 保护评测集安全
如果 HarnessOpt-Bench 涉及真实业务代码,要注意脱敏。不要直接把公司内部含密钥、地址、账号信息的代码放进评测集。可以用通用占位符替换敏感信息,并增加自动化检查脚本,扫描评测集中是否出现常见密钥格式。
10. 总结与学习路线
HarnessOpt-Bench 这类评测方向,本质上是在考察 LLM 的软件工程改造能力。它和写一个新函数不同,要求模型能够阅读既有代码、定位瓶颈、在保持接口兼容的前提下做结构优化。这对模型的能力边界提出了新的挑战,也给评测系统设计者带来了不少实务问题。
通过本文的拆解,你应该已经清楚:
- Harness 不是简单的“测试工具”,而是整个自动化链路的骨架。
- Harness 优化可以从效率、稳定性、可扩展性、可观测性、资源管理五个维度分类。
- 评测集设计的关键在于有明确目标、可自动验证、能区分“真优化”和“假优化”。
- 一个完整的评测执行器需要包含 Prompt 构造、代码抽取、依赖安装、验证脚本、指标统计和结果落盘。
下一步可以从最小数据集做起。先准备 10 个任务,搭好评测框架,再用市面上常见的开源模型跑一轮,看看不同模型的表现在哪个分类上差距最大。如果你想继续深入,可以考虑引入多轮交互评测:第一轮模型给出优化方案,评测系统反馈验证结果,模型根据反馈继续修改。这更接近真实开发者的工作模式。
Harness 优化的核心不是“把代码改得更花哨”,而是让整个执行链路更稳、更快、更可控。带着这个标准去评测模型,才有参考价值。如果本篇文章对你有帮助,欢迎收藏备用,也欢迎在实践中多尝试不同的任务设计,把你的评测结果分享出来。