ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

last30days-skill 的评估治理:为什么搜索质量评估是手动门槛而非每个 PR 的 CI 门禁

last30days-skill 的评估治理:为什么搜索质量评估是手动门槛而非每个 PR 的 CI 门禁 last30days-skill 的评估治理为什么搜索质量评估是手动门槛而非每个 PR 的 CI 门禁【免费下载链接】last30days-skillAI agent skill that researches any topic across Reddit, X, YouTube, HN, Polymarket, and the web - then synthesizes a grounded summary项目地址: https://gitcode.com/GitHub_Trending/la/last30days-skill本文基于 last30days-skill 仓库中的架构决策记录 search-quality-eval-manual-by-default-2026-05-10.md系统讲解该项目为何刻意不把evaluate_search_quality.py这个基线 vs 候选版本的搜索质量 A/B 评估器接入每个 PR 的 CI三个核心阻塞因素实时 API 依赖、成本与延迟、LLM 判分的非确定性如何共同决定了手动默认的评估策略以及配套的源码实现、操作命令与评审规范。读完本篇你将掌握在混合了实时数据源与 LLM 判定的项目中如何设计评估门禁、如何运行手动质量评估以及离线确定性评估进 CI 实时评估手动触发的分层治理模式。背景evaluate_search_quality.py是什么skills/last30days/scripts/evaluate_search_quality.py 是一个可选的本地评估脚本用于在基线版本baseline revision与候选版本candidate revision之间对一组固定的评审主题reviewer topics做检索质量对比。它产生两类指标确定性重叠指标Jaccard重叠度、retention对基线的保留率、按来源per-source的条数与重叠LLM 判分指标由 Gemini 作为裁判模型对结果做 0–3 分的相关性标注后计算Precision5、nDCG5与跨判分池的来源覆盖召回率source-coverage recall。它的定位在 docs/search-quality-eval.md 中被明确写为不是用户侧运行时的一部分默认也不需要进入 CI。也就是说这个脚本天然具备回归捕捉器的外观——见到评估器就想接入每个 PR 自动运行是大多数团队的直觉反应。而本项目的决策恰好相反刻意不把它接进每个 PR 的 CI。决策核心为什么 CI-on-every-PR 是错误默认决策文档给出了三条阻塞属性这三条共同构成了实时 API 非确定性的组合困境1. 实时 API 依赖Live API access候选版本要真正跑出结果引擎必须实际运行——意味着真实的 ScrapeCreators 调用、真实的 Reddit 抓取、真实的 YouTube 搜索。在 CI 中运行要么需要注入生产凭据在自动化流水线里长期持有生产密钥要么依赖一套 record/replay 的录制回放 fixture 集合——而外部 API 的响应结构几乎会立即漂移fixture 随之失效。这条属性可以从源码中得到印证evaluate_search_quality.py 的run_last30days()直接以子进程方式在 git worktree 中运行完整的last30days.py引擎并解析其 stdout JSON没有任何网络录制/回放层create_eval_env()同文件 L313-L327还会白名单式地透传OPENAI_API_KEY、XAI_API_KEY、SCRAPECREATORS_API_KEY、GOOGLE_API_KEY等真实凭据环境变量说明这条评估路径设计上就假定在线运行。2. 成本与延迟Cost and latency一次完整的评估会跨 N 个评审主题把流水线跑 N 次每个主题还要跑基线 候选两个版本即 2N 次完整引擎运行。乘以每个 PR包括纯文档 PR之后花费是实打实的墙钟时间也会把 CI 从约 30 秒推到好几分钟。当前默认主题池来自 fixtures/eval_topics.json包含 8 个带query_type与选题理由rationale的主题对比类、how_to、breaking_news、product、opinion、prediction、concept、factual 各型当该文件缺失时代码内还内置了 6 个兜底主题见 L31-L42。--timeout默认为 240 秒/次运行2N 次运行的累计墙钟与 API 开销对每个 PR 无条件跑一遍来说并不划算。3. 判分路径的非确定性Non-determinism in the judging pathLLM 判分指标对评审有价值但依赖当日裁判模型的行为。从源码看判分请求固定temperature: 0并要求 JSON 输出L215-L234但这只压住了采样随机性压不住模型版本漂移与同一输入不同日期的重打分差异。决策文档的判断很直白一个每 20 个 PR 就因裁判对某条结果重新打分而误挂 1 个 PR 的评估器比完全没有评估更糟——它教会贡献者重试而不是阅读结果。值得注意的是脚本对判分结果做了按裁判模型隔离的缓存judgments 缓存在output-dir/judgments/slug.json只有当缓存中记录的judge_model与本次--judge-model完全一致时才复用模型变化时宁可丢弃旧缓存重判若此时又缺少 Gemini API key则返回空判分并向 stderr 明确告警该主题的指标将全为零L283-L310。这种不静默产出错误数字的工程处理恰恰说明团队深知判分结果的模型敏感性——同一套逻辑用在 CI 自动门禁上就成了不稳定信号。确定性指标也不是真相最后一个常被忽略的点即使用户只关心确定性的重叠指标它们也只是回归守卫而非正确性度量。一个能提升 Jaccard 重叠的改动可能同时劣化综合synthesis质量一个降低重叠的改动反而可能是有意的改进。因此连确定性一侧也不安全地用于自动 fail PR。这也是为什么--mock、--quick等降成本开关L511-L523存在——它们服务于人工评估时的快速迭代而不是为 CI 门禁降档。评估器工作原理源码级拆解理解评估器的运行机制有助于理解为什么它能手动跑、不适合自动跑。双 worktree A/B 架构main()L526-L584先通过resolve_repo_dir()把--baseline/--candidate两个 git 引用解析为仓库目录标签为字面量WORKTREE时直接复用当前检出目录即候选 我手上这份代码其他引用如main、某个 tag、commit则通过git worktree add --detach tmpdir rev创建临时 detached worktreeL370-L386评估结束在finally块中统一git worktree remove --force清理。这正是决策文档中手动评估命令的底层形态LAST30DAYS_PYTHONpython3.13 \ python3 skills/last30days/scripts/evaluate_search_quality.py \ --baseline main --candidate HEAD参数默认值来自build_parser()--baseline HEAD~1、--candidate WORKTREE、--output-dir tmp/search-quality、--limit 20、--timeout 240另有--search限定来源、--quick、--mock、--judge-model、--topics-file。裁判模型的默认值取 lib/providers.py 中的常量GEMINI_FLASH_LITE gemini-3.1-flash-liteGemini key 的解析顺序为GOOGLE_API_KEY→GEMINI_API_KEY→GOOGLE_GENAI_API_KEY环境变量优先其次本地 config见 L195-L203可用GEMINI_MODEL类配置项或--judge-model覆盖。输出形态守卫与指标实现run_last30days()会对旧版本引擎探测--json-profile支持只要检出的引擎源码中出现该参数就显式传--json-profileraw并在解析结果后做形状守卫——若 payload 带schema_version却没有ranked_candidates说明引擎意外吐出了 agent 导出 profile脚本直接报错而不是给空列表打零分L359-L366。这种失败要大声的风格贯穿全脚本与决策文档CI 信号质量 覆盖率的立场一致。指标实现均为标准检索度量L136-L192jaccard(A,B) |A∩B| / |A∪B|两集皆空记 1.0retention(A,B) |A∩B| / |A|基线为空记 1.0衡量候选版本相对基线丢了多少precision_at_k统计 top-k 中判分 ≥2relevant and useful 及以上的比例判分刻度 0跑题/明显差、1弱或边缘、2相关有用、3高度相关最佳之一build_judge_prompt()L237-L270ndcg_at_k使用DCG Σ (2^grade − 1) / log2(index1)理想 DCG 由判分池baseline ∪ candidate 的并集去重后内分数降序取前 k 得到source_coverage_recall衡量判分 ≥2 的条目所覆盖的好来源集合中候选排名命中了多少。summarize_topic()L403-L437把上述指标按 baseline / candidate / stability 三段组织最终write_summary()输出output-dir/metrics.json与summary.md含| Topic | Base P5 | Cand P5 | Base nDCG5 | Cand nDCG5 | Jaccard | Retention |对比表单主题失败不中断整体而是记入failures列表写进输出退出码在存在失败时为 1L475-L584。干净的评估环境docs/search-quality-eval.md 还记录了环境隔离细节脚本 shell out 到last30days.py时强制干净的 env 认证路径——透传XAI_API_KEY、OPENAI_API_KEY、SCRAPECREATORS_API_KEY但刻意不透传浏览器 Cookie 的 X 认证使评估运行保持在无弹窗路径上同时从评估PATH中剥离node并给yt-dlp包一层--ignore-config避免旧版本引擎继承本地浏览器 Cookie 配置。这与源码中create_eval_env()只允许PATH/LANG/LC_ALL/TMPDIR与白名单凭据键L49-L61、并清空LAST30DAYS_CONFIG_DIR的做法互为印证。决策指引四条操作准则决策文档的 Guidance 部分给出四条准则其中前三条是当前规范第四条是重审条件1. 评估器保持可用只是不自动脚本对维护者和贡献者始终可运行。两种触发方式评审者请求当 PR 落在检索 / 排序 / 综合路径且风险值得时reviewer 手动请求一次评估运行贡献者自跑提交前在本地先跑获取前置信号。verify_v3.pyskills/last30days/scripts/verify_v3.py中把评估器登记为 v3 验证 bundle 的一环EVALUATOR SKILL_ROOT / scripts / evaluate_search_quality.py说明手动但常备在工具链中是真实落地的而非口头约定。2. 标准 PR CI 门禁保持确定性与契约化进入自动门禁的只能是同一输入两次运行给出同一答案的检查离线安全的pytest、插件契约检查、版本一致性契约、ruff/lint。输出质量评估quality-of-output assessment整体位于该循环之外。3. 中间地带是workflow_dispatch不是自动 PR 门禁如果维护者想要GitHub 触发但不让每个 PR 承担实时 API 成本的评估正确形态是手动派发的工作流workflow_dispatch或标签触发label-gated的工作流——而不是无条件在pull_request:上运行的工作流。核心原则一句话成本旋钮留在人手里。4. 若评估器能变为离线确定性则重审该决策阻塞项是实时 API 非确定性的组合。未来如果脚本能基于静态 fixture 计算有意义的 Jaccard / retention 指标无实时 API 调用、无 LLM 判分决策翻转它将成为默认 CI 的候选。文档明确要求跟踪这一条件、条件满足时重审。落地状态该重审条件正在被另一条路线兑现从当前仓库结构看第四条重审条件并没有让团队放弃在 CI 里做质量评估而是由另一套离线评估体系承接.github/workflows/validate.yml 的evaljob 在每个 PR 上运行uv run pytest tests/eval -x -s该离线评估套件基于录制的 HTTP fixture 回放lib/http.py处重放从不调用 LLM 或网络度量引用落地citation grounding、时效合规recency compliance、聚类一致性cluster coherence、覆盖与确定性对照 tests/eval/baseline.json 的地板值做硬基线检查详见 docs/reference/eval.md因此当前治理格局是双层离线确定性的研究质量基线进 CI每个 PR 都有分数表与硬检查而依赖实时 API 与 LLM 判分的 A/B 评估器evaluate_search_quality.py保持手动。这恰好验证了决策文档的框架CI 门禁 契约形状 确定性质量评估 人工判断触发。实操规范什么该合并、什么不该决策文档最后把指引翻译成可执行的评审规则场景处置PR 把evaluate_search_quality.py接入默认 validate.yml 工作流不合并PR 添加workflow_dispatch触发器或标签门控的运行合并Review 检索/排序类改动diff 显示可能劣化质量主动请求手动评估运行不要指望 CI 替你捕捉一次完整手动评估的可复制形态结合 docs/search-quality-eval.md 的推荐用法# 基本形式基线 origin/main vs 当前检出 uv run python skills/last30days/scripts/evaluate_search_quality.py # 指定版本与参数 uv run python skills/last30days/scripts/evaluate_search_quality.py \ --baseline main \ --candidate HEAD \ --per-source-limit 5产出位于tmp/search-quality/--output-dir可改metrics.json供程序化对比summary.md的对比表供人工评审直接阅读。判分缓存位于output-dir/judgments/切换--judge-model会自动失效旧缓存——阅读旧报告时务必确认报告所用裁判模型与缓存记录一致。两条来自用户文档的诚实提醒值得保留Jaccard与 retention 是回归守卫而非真相指标Precision5与nDCG5的上限取决于判分池质量它们帮助对比版本但不能替代更大规模的人工标注基准。小结这条架构决策的可迁移经验有三点门禁的选择标准是信号的可靠性而非覆盖的完整性——一个 5% 误挂率的自动质量门比没有门更伤害团队对 CI 的信任实时 API LLM 判分组合天然不适合无条件自动触发成本旋钮workflow_dispatch/ label-gated应留在人手里重审条件应当被显式写出并跟踪——本仓库通过另建离线 fixture 回放评估套件tests/eval部分兑现了离线确定性化路径使 CI 拿到了确定性质量基线而 A/B 实时评估器继续以手动形态服务高风险评审。对检索 / 排序 / 综合类改动正确的验证姿势是CI 的离线基线全绿 视 diff 风险手动跑一次evaluate_search_quality.py并人工阅读summary.md而不是等待某个自动门禁替你把关。【免费下载链接】last30days-skillAI agent skill that researches any topic across Reddit, X, YouTube, HN, Polymarket, and the web - then synthesizes a grounded summary项目地址: https://gitcode.com/GitHub_Trending/la/last30days-skill创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表