One-shot Chunking 与 Dedup 实验:PostHog ReviewHog 如何将沙箱化流水线阶段重构为一次 LLM Gateway 调用
2026/9/17 16:22:55 网站建设 项目流程

One-shot Chunking 与 Dedup 实验:PostHog ReviewHog 如何将沙箱化流水线阶段重构为一次 LLM Gateway 调用

【免费下载链接】posthog:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.项目地址: https://gitcode.com/GitHub_Trending/po/posthog

本文面向对 PostHog 代码评审平台 ReviewHog 的架构与实验方法感兴趣的开发者。ReviewHog 是 PostHog 仓库中的一个产品级代码评审系统,其核心是将 GitHub PR 的评审流程拆分为多个流水线阶段,其中"PR 分块(chunking)"与"问题去重(dedup)"原本以 agentic sandbox 方式运行。本文以products/review_hog/eval/experiments/2026-07-oneshot-chunking-dedup/PLAN.md为主线,结合direct_llm.pyconstants.pyactivities.pyissue_deduplicator.pyFINAL_REPORT.mdsample_oneshot_chunker.py等仓库文件,完整还原这个"one-shot(单次调用)"实验的设计、执行、测量与决策过程。你将掌握:这两个阶段为什么适合去掉沙箱、CHUNKING_ONESHOT_MAX_ADDITIONS/DEDUP_ONESHOT_MAX_FINDINGS两个门控(gate)如何工作、结构化输出如何从机制上消灭 schema 失败类,以及如何用离线采样器在极低成本下验证分块质量。


一、实验动机:两个"纯文本"阶段为何还跑在沙箱里

1.1 ReviewHog 评审流水线中的两个沙箱阶段

ReviewHog 的评审流程(见 ARCHITECTURE.md)把一次 PR 评审组织为多个阶段。其中两个阶段在很长一段时间里是流水线上仅存的"agentic sandbox":

  • PR 分块(chunking)split_pr_into_chunks用一次 LLM 调用,把变更文件按"关注点边界(concern seams)"聚合成逻辑上可评审的块(chunk),并按照评审优先级排序(见 ARCHITECTURE.md)。它的 prompt 把 PR 元数据、评论与补丁内联嵌入,不需要访问仓库。
  • 问题去重(dedup)deduplicate_issues通过一次 LLM 调用,合并位置重叠的重复发现(duplicate issues),并丢弃已被任何既有内联评论提出过的内容。它的 prompt 是纯文本,甚至显式渲染CLAUDE_CODE_CONTEXT=""(见 issue_deduplicator.py)。

而这两个阶段默认跑在 agent 默认配置opus-4-8 @ high的 agentic sandbox 上。

1.2 沙箱路径的两个成本

PLAN 明确列出两个痛点(PLAN.md):

  1. 每个 sandbox 在串行关键路径上要付约 55 秒的 provisioning 时间
  2. 存在两类失败:Modal provisioning 抖动(infra 层故障);以及 chunking 阶段约 29% 的 schema 失败类——模型返回了裸数组(bare array)而不是chunks对象。

一个关键证据是:在归档的 20 次 dedup 调用中,14 次没有使用任何工具(zero tools),说明这两类任务本质上根本不需要一个"会拿工具、能跑仓库"的 agent。

1.3 实验假设

PLAN 的实验假设(也是 POTENTIAL_EXPERIMENTS.md 中 item 7 的原始表述):

两个阶段都是纯文本任务,各自在串行关键路径上付出约 55s 的沙箱 provisioning;直接、schema 强制的 gateway 调用(相同模型/相同 prompt)在效果上等价,并且从结构上移除两类失败。

具体回答的问题是:

用 one-shot gateway 调用(Sonnet 5 @ xhigh、结构化输出保证 schema)能否在保持 chunk-plan 与 dedup 质量的同时,压缩阶段墙钟时间并消灭那两类失败?(PLAN.md)


二、实验设计:门控、模型钉扎与基准

2.1 测试 PR:冻结且可比

实验选择 PR #62096(headba725a897db35053525e5bdfac2c64a8b007fcb4,674 增 / 1 删 / 10 文件)作为基准测试对象:

  • 674 增高于 400 增的单块门控(SINGLE_CHUNK_GATE_ADDITIONS),因此两个新路径都会被实际触发(chunking 与 dedup 的 one-shot 路径都"活"着);
  • 它的质量标尺(yardstick)是旧版 ReviewHog 的 10 条发现(见../2026-07-reviewer-topology/fixtures/old_reviewhog_report.md,即 products/review_hog/eval/experiments/2026-07-reviewer-topology/fixtures/old_reviewhog_report.md)。

2.2 五个永久性 Instrument(默认开启)

实验的"仪器"全部以永久代码落地,默认开启(用户负责提交,Agent 只改文件)。PLAN 列出五个要点(PLAN.md):

  1. 门控 + 模型钉扎(constants.py):

    • CHUNKING_ONESHOT_MAX_ADDITIONS = 5000(仅统计新增行,与其它 chunking 门控口径一致);
    • DEDUP_ONESHOT_MAX_FINDINGS = 50(进入 dedup 的 issue 数,含边界);
    • ONESHOT_MODEL = "claude-sonnet-5"ONESHOT_REASONING_EFFORT = "xhigh"
    • 任何一个门控设为 0 即整体禁用该阶段的 one-shot 路径(回到沙箱)。
  2. reviewer/sandbox/direct_llm.py → run_oneshot_review(...):一次 Messages 调用,经 LLM gateway(get_async_anthropic_gateway_client(product="review_hog"))发出;adaptive thinking +output_config.effort=xhigh(这是沙箱钉扎的 API 原生表达);结构化输出(来自该阶段的 pydantic 模型)保证 JSON schema——"chunking 的 schema 失败类不可能发生";ai_stage头用于 dump/成本归因;Anthropic 错误被重抛为紧凑的ApplicationError(4xx 除 408/409/429 外均不可重试)。Bedrock 回退被刻意关闭(那条路径会剥离output_config)。

  3. 两条分支split_chunks_activity(新增行 ≤ 门控 → one-shot,否则沙箱不变)与deduplicate_issues(issue 数 ≤ 门控 → one-shot,否则沙箱不变)。两条路径 prompt 完全一致

  4. Gateway 产品注册(永久 parity 管道)review_hog被加入 gateway_client.py 的Productliteral,并在 services/llm-gateway/src/llm_gateway/products/config.py 注册为产品(任意模型、允许 API keys、不计费)。

  5. 不钉扎 chunk 数量(unpinned,刻意为之):chunk plan 本身就是要测量的输出;钉扎会完全短路 one-shot chunking 路径。

刻意的混杂变量(deliberate confound):one-shot 分支同时改变了模型(agent 默认 opus-4-8 @ high → sonnet-5 @ xhigh)与执行模式(sandbox → 直接调用)。它测试的是"期望的终态配置",而不是单变量版本。这一点在解读结果时必须始终记住。

2.3 配置矩阵与基线

label内容runs
ONESHOT-N完整 e2e 运行,one-shot chunking + dedup 生效,chunk 不钉扎2
offline samplesample_oneshot_chunker.py× 5 次对冻结快照的直接 chunker 调用(不走流水线,成本约 cents)1 batch

基线全部复用、不再重跑(PLAN.md):

  • ../2026-07-pipeline-models/C1(sonnet review+validation,dedup/chunking 沙箱跑 opus 默认,钉扎3-chunk 切分,18→11→7)——最接近今天生产配置;
  • ../2026-07-reviewer-model-sonnet5/B1/B2(sonnet review、opus-default validation、钉扎,17→11→6 / 18→14→6)。

双向注意(caveat):基线都是钉扎的,而本轮不钉扎,因此"2-chunk 还是 3-chunk 的抛硬币"重新进入漏斗。所以chunk-plan 质量与 dedup 决策是主要读数,漏斗/valid 计数是次要读数,且附有结构上的 caveat。


三、核心实现:run_oneshot_review与门控路由

3.1run_oneshot_review的完整契约

direct_llm.py 是整个机制的心脏,其完整调用参数与行为:

async def run_oneshot_review( *, team_id: int, user_id: int, prompt: str, system_prompt: str, model_to_validate: type[_ModelT], step_name: str, model: str = ONESHOT_MODEL, reasoning_effort: str = ONESHOT_REASONING_EFFORT, ) -> _ModelT:

关键实现细节:

  • 单次 Messages 调用client.messages.parse(model=..., max_tokens=64_000, system=system_prompt, messages=[...], thinking={"type": "adaptive"}, output_config={"effort": reasoning_effort}, output_format=model_to_validate, ...)output_format传入阶段的 pydantic 模型,由 SDK 在构建响应时就按该模型校验文本块——截断/非法 JSON 会在parsed_output之前直接抛pydantic.ValidationError
  • 三个内部硬上限(direct_llm.py):
    • _MAX_OUTPUT_TOKENS = 64_000(sonnet-5 的输出上限;注意 adaptive thinking 也计入输出 token 且在 xhigh 下占大头);
    • _TIMEOUT_SECONDS = 600.0(大 chunking prompt 在 xhigh 下端到端合法地需要几分钟);
    • _RETRYABLE_CLIENT_STATUSES = (408, 409, 429)
  • 错误语义APIError被重抛为紧凑ApplicationError(避免原始APIError链撑爆 Temporal 的失败序列化),4xx(除 408/409/429)标记non_retryablepydantic.ValidationError同样被压缩为可重试的ApplicationError(因为异常不带stop_reason,无法证明是确定性失败);parsed_output is None时,stop_reason == "max_tokens"标记为non_retryable——重试同一个超大 prompt 只会再次撞同一堵墙、白烧预算。
  • ai_stage属性extra_headers={"x-posthog-property-ai_stage": step_name},把一次生成归因到流水线阶段,供 dump 与成本查询使用。

3.2 门控路由:split_chunks_activity

在 activities.py 中,chunking 活动按三级逻辑路由:

# 1) 小 PR:跳过 chunking LLM 轮次,用确定性单块 planned = plan_deterministic_chunks(snapshot.pr_files) if planned is not None: # <= SINGLE_CHUNK_GATE_ADDITIONS (400) ... # 持久化后直接返回 # 2) 构建自包含 prompt(元数据+评论+补丁内联) prompt = generate_chunking_prompt(snapshot.pr_metadata, snapshot.pr_comments, snapshot.pr_files) # 3) 按 one-shot 门控路由 additions = count_reviewable_additions(snapshot.pr_files) use_oneshot = bool(CHUNKING_ONESHOT_MAX_ADDITIONS) and additions <= CHUNKING_ONESHOT_MAX_ADDITIONS async with Heartbeater(): if use_oneshot: chunks = await run_oneshot_review(..., model_to_validate=ChunksList, step_name="chunking") else: chunks = await run_sandbox_review(..., model=CHUNKING_MODEL, reasoning_effort=CHUNKING_REASONING_EFFORT)

值得注意的两点代码级事实:

  • 门控用bool(CHUNKING_ONESHOT_MAX_ADDITIONS)短路:设为 0 时 one-shot 路径整体关闭;
  • "每个文件恰好在一个 chunk 中"是由代码强制、而非信任 LLM:无论走哪条路径,reconcile_chunks(chunks, snapshot.pr_files)都会校正遗漏文件,避免下游静默漏审。

路由行为有参数化测试背书:test_split_chunks_activity_routes_llm_chunking_by_oneshot_gate断言additions == CHUNKING_ONESHOT_MAX_ADDITIONS时走 one-shot、+1时走沙箱(见 test_review_activity.py)。

3.3 门控路由:deduplicate_issues

issue_deduplicator.py 先去重一个确定性位置预过滤器_select_dedup_candidates:只有与另一条 issue、任何既有内联评论或上一轮 finding 共享文件且行区间重叠的 issue 才可能重复,因此位置孤立的问题不经过 LLM 调用直接存活;零候选时整个 LLM 轮次被跳过。随后按实际送入 LLM 的候选数(而非预过滤总数)路由:

if DEDUP_ONESHOT_MAX_FINDINGS and len(candidates) <= DEDUP_ONESHOT_MAX_FINDINGS: deduplication_result = await run_oneshot_review( ..., model_to_validate=IssueDeduplication, step_name="dedup") else: deduplication_result = await run_sandbox_review(...) # unique 总是存活;只有位置候选可能被 LLM 丢弃 duplicate_ids = {dup.id for dup in deduplication_result.duplicates} deduplicated_issues = unique + [issue for issue in candidates if issue.id not in duplicate_ids]

同等的路由测试存在于 test_issue_deduplicator.py。另外注意 DECISIONS.md 记录了一个后期测量:dedup 的输出 token 在 xhigh 下由 adaptive thinking 主导而非答案本身(schema 只含 ids,≤~700 token),最坏一例 36-finding PR 输出 28,899 token / $0.35——这是后续可以再做一次"effort=high"的尾巴优化。

3.4run_oneshot_review的单元测试

test_direct_llm.py 精确锁定了 gateway 调用的契约:

assert mock_get.call_args.kwargs["product"] == "review_hog" assert kwargs["model"] == ONESHOT_MODEL assert kwargs["output_config"] == {"effort": ONESHOT_REASONING_EFFORT} assert kwargs["output_format"] is IssueDeduplication assert kwargs["thinking"] == {"type": "adaptive"}

四、测量项与运行循环

4.1 七项测量指标

PLAN 明确了七项"测什么"(PLAN.md):

  1. 机制(mechanics):运行时间线上没有sandbox_prompt:chunking/sandbox_prompt:dedup任务;dump 的 per-model 统计里 chunking/dedup 生成以claude-sonnet-5+ai_product=review_hog+ai_stage出现(silent-fallback 防护也适用于 one-shot 调用)。
  2. Chunk-plan 质量(主要):切分数与接缝 vs 归档分布(在 2-chunk 的 backend/frontend 切分与好的 3-chunk 的 core.py / tool+toolkit / frontend 切分之间抛硬币,17 次归档采样);来自 2 次 e2e 与 5 次离线采样的全覆盖检查(每个可审文件恰好出现一次)。
  3. Dedup 决策(主要):raw→dedup 幸存集合 vs 归档行为——明显的重复坍缩仍发生、无新假合并(抽查幸存者与 raw 发现列表)。
  4. 漏斗:raw→dedup→valid vs C1/B 区间(次要,附结构 caveat)。
  5. 阶段成本/时间:chunking+dedup 阶段墙钟(C1 测得 dedup 阶段约 10 分钟含沙箱 provisioning;预期远低于 1 分钟)与 per-stage token(经ai_stage切分)。
  6. Schema 失败:构造上期望 0(对比归档中 14 次 chunking 任务的 4 次失败)。
  7. Judge vs old-10:按既定协议产出judge_results.json,报告写FINAL_REPORT.md

4.2 每轮运行循环(从../2026-07-pipeline-models/PLAN.md继承)

一次完整运行(PLAN.md):

  1. 预检(见下);
  2. 记录RUN_START_EPOCH=$(date +%s),然后执行(不带--publish):
    flox activate -- bash -c "SANDBOX_PROVIDER=MODAL_DOCKER DJANGO_SETTINGS_MODULE=posthog.settings \ python manage.py run_review --pr-url https://github.com/PostHog/posthog/pull/62096 \ --team-id 1 --user-id 1"
  3. Dump(写结果前必须先 dump):
    LABEL=ONESHOT-<n> RUN_SECONDS=<s> RUN_START_EPOCH=<epoch> \ OUT_DIR=products/review_hog/eval/experiments/2026-07-oneshot-chunking-dedup/runs \ flox activate -- bash -c "DJANGO_SETTINGS_MODULE=posthog.settings python manage.py shell -c \ \"exec(open('products/review_hog/eval/scripts/dump_result.py').read())\""
  4. no-verdict 检查(reset 之前)grep -c "no-verdict" <dump>;若有则重跑run_review(skip-resume 只重试缺失 verdict 的部分),并以相同 label 重新 dump。
  5. 模型与机制验证(强制):per-model 统计显示 review/validation 仍在 sonnet-5,且 chunking/dedup 生成不在沙箱路径上——通过ai_stage/ai_product属性(查询本地$ai_generation事件)与"不存在 chunking/dedup 沙箱任务"双确认。
  6. Run 1 dump 之后(reset 之前):运行离线 chunker 采样(sample_oneshot_chunker.py)→runs/chunker-offline-sample.md
  7. 最后flox activate -- bash -c "DJANGO_SETTINGS_MODULE=posthog.settings python manage.py reset_review_hog --yes"(dump 在 reset 之前)。

4.3 预检清单(每次运行)

PLAN 的预检清单(PLAN.md):

  • Worker 已启动并热重载当前代码(nodemon 监听products/;启动时间需晚于文件 mtime);review-pr workflow 活动期间绝不编辑 workflow 读取的常量
  • ngrok 已启动;SANDBOX_PROVIDER=MODAL_DOCKER;floxDEBUG=True;PR head 复核 ==ba725a89
  • LLM gateway 运行在 :3308 且已加载review_hog产品(uvicorn --reload 会拾取配置编辑——但 reload 会切断 live 流,所以 gateway 配置编辑只在轮次之间进行)。2026-07-03 已做过 smoke 验证:一次 one-shot dedup 调用端到端成功 →$ai_generation带 model=claude-sonnet-5、ai_product=review_hog、ai_stage 戳(593 in / 20 out);
  • 环境坑(仅 agent 驱动的 shell):PostHog Desktop harness 会把LLM_GATEWAY_URL覆盖成它自己的本地代理——手动 shell 调用要加前缀LLM_GATEWAY_URL=http://localhost:3308;从普通终端启动的 Temporal worker 拿到的是正确的 debug 默认值,不受影响;
  • 上一轮的 DB reset 已完成(dump-before-reset 纪律)。

五、离线采样器:低成本、无流水线的分块质量探针

5.1 基于 DB 快照的sample_oneshot_chunker.py

实验设计了一个"廉价去噪器"(sample_oneshot_chunker.py):在 run 的数据仍在 DB 里时(dump 之后、reset_review_hog之前),对最新 team-1 ReviewReport 的持久化pr_snapshot连发 N 次直接的 one-shot chunker 调用。每次采样是一次 gateway 调用(约 cents,无沙箱),串行执行。

运行方式:

N_SAMPLES=5 OUT_FILE=products/review_hog/eval/experiments/2026-07-oneshot-chunking-dedup/runs/chunker-offline-sample.md \ python manage.py shell -c "exec(open('products/review_hog/eval/experiments/2026-07-oneshot-chunking-dedup/sample_oneshot_chunker.py').read())"

脚本逻辑要点:加载最新的PRSnapshotArtefact;用count_reviewable_additions计算可审新增行;若additions <= SINGLE_CHUNK_GATE_ADDITIONS> CHUNKING_ONESHOT_MAX_ADDITIONS会打印 WARNING(说明生产环境在这个尺寸下根本不会走该路径);然后generate_chunking_prompt(...)渲染当前 prompt,循环run_oneshot_review(..., model_to_validate=ChunksList, step_name="chunking-offline-sample")。每个样本输出 chunk 数、每块的新增行分布,并在最后做全覆盖校验missing/extra/ 重复文件出现即标记COVERAGE VIOLATION,落盘到指定 OUT_FILE。

5.2 完全本地的sample_oneshot_chunker_fixture.py

prompt 迭代场景下,实验还提供了不需要 GitHub、不需要 DB的 fixture 变体(sample_oneshot_chunker_fixture.py):直接解析拓扑轮冻结的pr62096.diff(复用与真实 fetch 相同的测试/lockfile 过滤器和补丁解析器),渲染当前 chunking prompt,连发 N 次直接 gateway 调用。

N_SAMPLES=5 python manage.py shell -c "exec(open('products/review_hog/eval/experiments/2026-07-oneshot-chunking-dedup/sample_oneshot_chunker_fixture.py').read())"

已知与真实运行的偏差:fixture 中没有 PR body,所以PR_INTENT只带标题——对切分结构检查无影响。同样,在 agent shell 中记得加LLM_GATEWAY_URL=http://localhost:3308前缀。

这两个采样器让"chunking prompt 迭代"的成本趋近于零且完全本地——这也是后续 prompt 修正能被快速验证的关键基础设施。


六、运行结果与关键读数

6.1 漏斗、成本与时间(per run)

runchunks(draw)unitsraw→dedup→validfetch→chunk planwave-end→dedup donetotal tok (in/out)wall-clock
ONESHOT-12(unpinned)813→11→1047s/attempt*38s33.9M/230k sonnet-52374s incl.*(eff ≈ 34 min)
ONESHOT-23(unpinned)1218→14→936s54s53.1M/352k sonnet-51626s(27.1 min, clean)

* ONESHOT-1 的 chunking 首次尝试被一次中途 worker 重启丢弃(用户发起);Temporal 在 5 分钟 heartbeat 超时后重跑——属于 infra 事件,不是路径问题。

对照基线:C1(all-sonnet、钉扎、沙箱 dedup/chunking)18→11→7,43 分钟,其中 dedup 阶段约 10 分钟;B 对 17→11→6 / 18→14→6,有效约 21 分钟。漏斗对比带有 unpinned-vs-pinned 的 chunk 结构 caveat。

时间收益直接体现在机制上:combine→clean→dedup→persist 坍缩到38–54s(对比 C1 的约 10 分钟);fetch→chunk-plan 是36–70s。两个 one-shot 阶段合计约$0.29/run naive(每阶段约 50k in / 4k out)。

6.2 Old-10 覆盖率(judge,root-cause 匹配)

V= 抓到且 validator 判 valid ·i= 抓到但 validator 驳回 ·.= 漏掉

old# | O1 O2 | 1 | . . | 任何一轮都没出现(此前 0/21) 2 | V V | O1 只抓到一半;O2 把完整根因拆到两条 VALID 发现里 3 | V V | 每一轮每一次运行都抓到 4 | . . | 从未出现(此前 0/21) 5 | V . | 第三次浮出水面——此处 VALID(update_action 步骤替换未被标为危险) 6 | V . | 第三次 VALID(无界的 compact list 输出) 7 | . . | 只出现过一次(B2,被驳回) 8 | . . | 从未出现(旧 must_fix) 9 | i . | validator 用合理的既有模式反驳将其驳回 10 | . . | 从未出现(旧 must_fix)

技能内容盲区(#1/#4/#8/#10)依然存在——与每一轮一致;它们住在 review 阶段,而本次实验没有触碰该阶段。

6.3 新发现(judge 对照 diff 与仓库验证)

runnew_plausible其中 validator-VALIDnew_junk通过 validation 的 junk
O16600
O2664(全部被驳回)0

两轮独立浮现的亮点:list_actions的对象级访问控制绕过(must_fix、VALID,judge 对照filter_queryset_by_access_level先例验证——注意 sonnet-5 轮的 judge 对相关 finding 家族有分歧,此变体通过了验证)和$autocapture-only 元素过滤的静默退化。O1 的 validator 获得 judge 明确表扬:每条 VALID 事实准确、一次有理有据的驳回、并抓出某条发现的修复建议不可行。

6.4 One-shot 机制记分板

check结果
chunking one-shot ≤5k adds✓ 两轮 + live PR(每轮 1 次生成,review_hog/chunking
dedup one-shot ≤50 findings✓ 两轮(每轮 1 次生成,review_hog/dedup
dedup sandbox fallback >50✓ live PR #67419:61 raw → 沙箱 dedup,review_hog/dedup生成数为 0
schema 失败0(结构化输出)
阶段归因ai_product/ai_stage戳把运行阶段与本地 cron 噪声区分开
live publish✓ #67419 评审已发布(30 条内联评论,钉扎到 head,published_head_sha已设置)

6.5 唯一的回归信号:one-shot chunker 把小型 PR 切碎

在 #62096(497 可审新增行)上:in-pipeline draw 为 2、3;离线批 4、4、4、3、3——n=7 总分布 2,3,3,3,4,4,4,碎片最小到 16 行。而同一 PR 的沙箱归档只出现过 2 或 3(17 次运行约 50/50)。到大规模时效应消失:3217 行的 live PR 拿到了干净的 6-chunk 计划(约 536 行/块,对比 300 行目标的 naive 11 块)。每次 draw 覆盖率都完整

用户的裁决(2026-07-03):约 500 行的 PR 切 4 块明确太多——这是成本风险(units = chunks × 4,4-draw 会把 review 阶段成本翻倍 vs 2-draw),而非正确性风险(覆盖率在所有 draw 中都完整)。这命中了 chunking 半边"chunk plans degrade"的 kill criterion。

随后(2026-07-04,用户批准后)应用了prompt 修正:给prompts/chunking/prompt.jinja的 sizing 规则加了约 100 行下限 + 计数公式上限。2026-07-06 验证:sample_oneshot_chunker_fixture.py(完全本地)对 #62096 fixture 的 5/5 draw = 每轮 2 块、全覆盖、零 <100 行的碎片——未调优时 4,4,4,3,3 的切碎消失了。chunking 半边因此可以随 dedup 一起采纳。


七、评分、kill 标准与决策记录

7.1 评分流程

每个 dump 对照 old-10 由 judge 评审(与先前轮次相同的协议/prompt;raw 输出进judge_results.json;用户最终复核 judge 的调用),叠加上面六项阶段聚焦读数。

7.2 Kill 标准(item 7 改编)

  • dedup 幸存集合与归档 dedup 行为背离(假合并或漏掉明显重复),跨运行成立;
  • 或 chunk plans 相对归档切分退化(覆盖率破坏、接缝不连贯、系统性单文件切碎)。

Win ⇒ 默认开启的代码保留(用户提交);kill ⇒ 回滚 = 把两个门控设为 0(沙箱行为字节级回归)。

7.3 已锁定的决策(2026-07-03/04)

  • 不钉扎 e2e ×2 + 离线 5 采样 chunker 批——chunk-plan 质量直接判定;漏斗读数带结构 caveat;
  • 门控指标 = 仅新增行——与SINGLE_CHUNK_GATE_ADDITIONS/CHUNK_TARGET_ADDITIONS口径一致;
  • review_hog注册为 gateway 产品——永久 parity 管道;
  • 永久代码、默认开启于 5000/50——"翻开关看"风格;回滚 = 两个常量;
  • 用户提交一切,agent 只编辑文件(自 sonnet-5 轮起的常设约定);
  • 任何运行都不 publish;结果目录runs/位于本文件旁;
  • chunker-shatter 修复 = prompt 调整,先 DEFERRED("现在不做")再 APPLIED(见 6.5);
  • 2026-07-04(post-round、本分支上独立的 prod 变更):VALIDATION_MODELclaude-sonnet-5回退到claude-opus-4-8(effort 保持 XHIGH)——因用户观察到 sonnet validator 的"量宽松"倾向(constants 测试保持绿色)。与 one-shot 变更无关,记录于此只因为它共享分支;
  • JUDGING DONE 2026-07-04judge_results.json+FINAL_REPORT.md:old-coverage 4 valid(O1,含 #5 第三次浮出水面 + #6 第三次 VALID)/ 2 valid(O2),对比 B 对的 3/1;两轮 validated-junk 都是 0;dedup 决策 in-band;建议 = 现在采纳 dedup,chunking 等调优 prompt 的批量验证(或期间把门控设 0)。三次 judge-agent 尝试有两次死于 harness infra(一次中断级联、一次 gateway 502),第三次成功。

八、结论、交接与成本

8.1 最终报告结论(TL;DR)

FINAL_REPORT.md 的核心结论:

  1. 机制在门控两侧都成立:≤5k 行的 chunking 与 ≤50 findings 的 dedup 以单次 gateway 调用运行(每轮通过ai_product=review_hog+ai_stage戳验证、无 chunking/dedup 沙箱任务);live PR #67419(3217 行、61 raw findings)同时触发了 one-shot chunking 与>50 的沙箱 dedup 回退,然后正常发布。
  2. 节省的是时间与可靠性,不是 token:combine→clean→dedup→persist 坍缩到38–54s(C1 约 10 分钟);fetch→chunk-plan 36–70s;两阶段合计约$0.29/run naiveschema 失败 = 0 by construction(结构化输出)对比归档 29% 的 chunking schema 失败类。
  3. 质量保持:漏斗 13→11→10 与 18→14→9 valid(0 no-verdict),valid 数持平或高于此前每一轮;old-10 覆盖 4 valid(O1)与 2 valid(O2),对比 sonnet 轮 B 对的 3/1;两轮 validated-junk 都是 0(每条 VALID 都被 judge 验证为事实准确);dedup 削减比例与归档行为一致,无假合并或橡皮图章信号。
  4. 一个真实的回归信号:one-shot chunker 把小型 PR 切碎(4,4,4,3,3 vs 沙箱 2–3)——但覆盖率完整、大规模下消失;prompt 修正后2026-07-06 验证 5/5 draw = 2 块、全覆盖、零碎片
  5. 范围外 watch item:sonnet-5 validator 体积宽松(这里 91%/64%、live PR 86% 且 30 条内联评论),虽然 #62096 上它放行的没有 junk;用户在轮末把VALIDATION_MODEL回退到claude-opus-4-8@ xhigh。

8.2 建议

现在采纳 one-shot dedup——门控两侧路由都已验证、决策与归档行为一致、0 validated junk、阶段时间约 10 分钟 → <1 分钟、两类失败消失。也采纳 one-shot chunking——调优后的 prompt 已验证(#62096 上 5/5 draw = 2 块、无碎片);CHUNKING_ONESHOT_MAX_ADDITIONS = 0仍是线上行为出意外时的即时回滚。两条路径在分支上默认开启;采纳 = 提交它。

8.3 交接项

  • Validator 轮:sonnet validator 的体积宽松(91%/64%/86% 存活率)且 #62096 零 validated junk,是校准数据点而非 junk 泄漏——但 live PR 上 30 条内联评论是 UX 问题。轮末VALIDATION_MODEL已回退到claude-opus-4-8@ xhigh(用户)。
  • Chunker prompt 调优:已验证(5/5 干净 draw)。fixture 采样器让未来的 prompt 迭代几乎免费且完全本地——未经批量验证不要再发布 prompt 改动
  • 技能内容轮:#1/#4/#8/#10 在又一个配置下仍然全盲——结论不变。
  • Infra:两个非路径事件值得记住——activity 中途的 worker 重启会造成 5 分钟 heartbeat-timeout stall(one-shot 调用中途不可续,Temporal 会整体重试);desktop-harness 的LLM_GATEWAY_URL覆盖可能误导 agent-shell 脚本(worker 不受影响)。

8.4 本轮成本

约 87M in / 580k out(2 轮,naive 约 $350,真实成本远低——缓存读占主导)+ 约 10 次离线 chunker 调用(约 $1)+ 2 个 judge agent。one-shot 阶段本身约 $0.29/run naive


九、方法论要点与可迁移经验

这个实验对任何"把 agentic sandbox 阶段降级为一次 LLM 调用"的工程决策都有参考价值:

  1. 先看任务性质再决定架构:dedup 归档里 14/20 次调用零工具使用、chunking prompt 完全自包含——"纯文本任务"是去沙箱的判据,而不是凭直觉。可用grep/归档统计直接验证工具使用率。
  2. 用门控而不是一刀切CHUNKING_ONESHOT_MAX_ADDITIONS/DEDUP_ONESHOT_MAX_FINDINGS让小规模走快路径、大规模保留沙箱(沙箱能导航仓库、不必一次性 hold 全 PR);门控设 0 即整体回退,给了字节级一致的回滚面。两条路径共享同一 prompt,避免模型/提示词漂移。
  3. 结构化输出消灭一类失败:把 pydantic 模型作为output_format,让 SDK 在构建响应时校验,max_tokens截断也会以确定性方式标为 non-retryable——"schema 失败类"从运行时故障变成不可能事件。
  4. 混杂变量要显式声明:"模型 + 执行模式"一起变是端到端态测试(end-state-config style);解读质量读数时明确"钉扎 vs 不钉扎"的 caveat,把漏斗读数降级为次要指标。
  5. 低成本探针基础设施sample_oneshot_chunker.py(DB 快照)与sample_oneshot_chunker_fixture.py(本地 diff fixture)让 chunk-plan 质量在每次 run 之外可重复、批量、廉价地采样——prompt 调优验证(5/5 draw)正是靠它完成的。
  6. 质量信号要多维:漏斗 valid 数、old-10 覆盖率、validated-junk 数、dedup 幸存集合、chunk 切分分布各自回答不同问题;单看任何一维都可能被结构 caveat 误导。

相关仓库路径索引

  • 实验计划与结果:PLAN.md、FINAL_REPORT.md、judge_results.json
  • 运行 dump:runs/ONESHOT-1.md、runs/ONESHOT-2.md、runs/chunker-offline-sample.md
  • 采样器:sample_oneshot_chunker.py、sample_oneshot_chunker_fixture.py
  • 核心实现:direct_llm.py、constants.py、activities.py、issue_deduplicator.py
  • 测试:test_direct_llm.py、test_issue_deduplicator.py、test_review_activity.py
  • 背景:POTENTIAL_EXPERIMENTS.md、DECISIONS.md、ARCHITECTURE.md、gateway_client.py、llm-gateway products 配置

【免费下载链接】posthog:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.项目地址: https://gitcode.com/GitHub_Trending/po/posthog

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询