
Pyrefly Issue Ranking Pipeline用双阶段 5 轮 LLM管线自动为 GitHub Issue 排优先级【免费下载链接】pyreflyA fast type checker and language server for Python项目地址: https://gitcode.com/GitHub_Trending/py/pyrefly在类型检查器这类误报即劝退用户、漏报即损害可信度的项目中GitHub Issue 的优先级排序是一项高人力成本、且容易被主观判断带偏的工程活动。Pyrefly 仓库在 scripts/issue_ranker/AGENTS.md 中描述了一套自动化管线先从 GitHub 拉取 Issue用 pyrefly/pyright/mypy 三个检查器实测 Issue 中的代码片段、结合真实开源项目primer上的错误数据做影响面接地再经过 5 轮分工明确的 LLM 调用分类 → primer 影响 → 依赖关系 → 打分 → 终排产出可复现的优先级榜单。读完本文你能完整理解该管线的两阶段架构、各 Pass 的模型选择与成本估算、primer 分片并行机制并能直接在本地或 CI 中运行 collect / rank / v1-analysis 各模式。整体架构collect 与 rank 两大阶段该管线由 CLI 入口 驱动支持--mode collect、--mode rank、--mode full前两者合并以及--mode v1-analysis对既有 ranking.json 做事后 V1 差距分析见 入口文件文档字符串。Collect 阶段--mode collect从 GitHub API 抓取 Issue 并富化——提取代码、跑检查器、分类状态、解析 Issue 间关系产出中间 JSON。Rank 阶段--mode rank在富化数据之上运行由 pipeline.py 编排的 5 轮 LLM 管线输出 Markdown 报告与 JSON 结果。两阶段解耦的好处是昂贵的 collect要跑真实检查器、安装依赖只需要定期执行一次而排名策略prompt、权重、模型可以在 rank 阶段快速迭代。Collect 阶段的 7 个步骤main.py 的collect_issue_data按顺序执行 7 个阶段拉取 Issuegithub_issues.py通过 GitHub API 获取 open issues支持--labels标签过滤与--limit数量限制。区分类型检查类 Issue_is_typechecking_issue只有值得提取代码并实际跑检查器的 Issue 才进入后续环节。其判定逻辑是标题含 false positive / false negative → 一定是类型检查问题命中类型检查标签集typechecking、narrowing、overloads、conformance、typeshed等见_TYPECHECKING_LABELS→ 是命中跳过标签集performance、language-server、documentation、configuration、build-fails等见_SKIP_CODE_LABELS→ 否无标签时退回标题关键词启发式type、typing、narrow、protocol、dataclass等且刻意避免把 error handling 这类词误判为类型问题。提取代码块code_extractor.py三级策略——先匹配显式python /py 围栏_PYTHON_FENCE_RE再匹配看起来像 Python的裸围栏用行首def/class/import/from x import强信号避免误匹配错误输出文本最后回退到LLM 提取让 Haiku 模型基于 Issue 正文生成一个最小可复现代码片段NO_CODE表示无法用代码演示。LLM 修复残缺片段repair_snippetIssue 里的粘贴代码常常缺 import、有语法错误或不完整。修复 prompt 明确要求只修坏的部分、不重写逻辑并携带 Issue 标题与正文作为上下文。运行 pyrefly / pyright / mypyissue_checker.py dep_resolver.py这是 collect 阶段技术含量最高的一环下文单独展开。状态分类status_classifier.py基于三方检查器结果把每个 Issue 归入五类之一——false_positive/false_negative/confirmed_bug/already_fixed/feature_request。解析关系relationship_resolver.py识别重复 Issue、阻塞关系blocker、父子 Issue为 rank 阶段的依赖图 Pass 提供基础。collect 结束后写出的 JSON 结构为{issues: [...], relationships: {...}, metadata: {...}}metadata 中记录了标签过滤条件、Issue 总数、含代码的 Issue 数与类型检查 Issue 数collect_issue_data末尾。检查器执行细节先跑、再装依赖、重试一次、最后过滤issue_checker.py 的设计文档issue_checker.py 模块 docstring概括了核心策略每个代码片段写入临时目录依次执行——pyreflypyrefly check --output-format json snippetJSON 输出便于机器解析pyrightpyright --outputjson snippetmypymypy --no-error-summary snippet另外还会用python3直接执行片段尽力捕获运行时输出——当第三方依赖让静态检查不可靠时运行时行为是重要的旁证信号。所有检查器调用均带 60 秒超时超时返回CHECKER_TIMEOUT标记这与 primer 管线中的超时标记一致。依赖处理是这个流程中最微妙的部分dep_resolver.py 采用让检查器先报缺失、再据错误信息提取模块名的路线而不是预先静态扫描 import——因为检查器本身已知道哪些模块是标准库、哪些是第三方天然更准。其具体机制用一组正则从三类检查器的错误信息中提取缺失模块名pyrefly 的Could not resolve import of foo、pyright 的Import foo could not be resolved、mypy 的Cannot find implementation or library stub for module named foo等见_MISSING_MODULE_PATTERNS维护模块名 → pip 包名映射表PIL → pillow、cv2 → opencv-python、sklearn → scikit-learn等见_MODULE_TO_PACKAGE先尝试批量pip install失败则逐个安装install_missing_modulesdep_resolver.py#L102-L146安装成功后重跑全部检查器一次重试后仍然残留的 import 类错误被过滤掉片段本就不可能带全依赖而安装失败的模块记入unresolved_deps字段。unresolved_deps这个字段非常关键下游的classify_status和打分 Pass 都会检查它——当依赖装不上且检查器0 错误时系统明确知道这个 0 是不可信的检查器根本没解析到第三方类型会在 prompt 中附加DEPENDENCY WARNING要求 LLM 转而依据 Issue 描述推理严重性而不是轻信0 错误 已修复。状态分类启发式快路径 LLM 兜底status_classifier.py 先用廉价规则处理显而易见的情形没有任何检查器结果即没代码→feature_request三方检查器都没有真实错误过滤掉reveal_type这类信息性输出后→already_fixed。其余情形交给 Haiku 模型prompt 中特别强调跨检查器比较错误要语义比较而非字面比较、reveal_type是信息性输出不计入错误数、import 错误应忽略。若 LLM 返回非法状态或调用失败则回退到简单启发式_heuristic_classify只有 pyrefly 报错 → false positive只有其他检查器报错 → false negative都报错 → confirmed bug。Rank 阶段5 轮 LLM 管线的模型分工与成本估算run_pipeline 按顺序执行 5 个 Pass每个 Pass 使用不同档位的小/大模型并在日志中记录耗时与美元成本估算。成本估算表_COST_ESTIMATES大致为Haiku 单次调用约 $0.002、Sonnet 约 $0.03、Opus 大批量调用约 $0.75。5 个 Pass 分别对应 passes/ 目录下的模块Pass模块模型与调用量职责1. Categorizepasses/categorize.pyHaiku每 Issue 一次分类 Issue 类型/领域false positive、性能、IDE、规范符合性等2. Primer Impactpasses/primer_impact.py以确定性字符串匹配为主少量 Haiku 模糊兜底把 Issue 匹配到 primer 真实错误上量化影响面3. Dependenciespasses/dependencies.pyOpus仅 1 次构建依赖图阻塞链、重复簇、依赖组4. Scorepasses/score.pySonnet每 Issue 一次0–100 加权打分附分项 breakdown 与理由5. Rankpasses/rank.pyOpus按 50 个 Issue 一批结合全部前置结果做终排序与同分裁决值得注意的健壮性设计均可在 pipeline.py 中验证Pass 3 失败降级依赖图构建若抛异常则降级为空图dependency_groups/blocking_chains/duplicate_clusters全空继续后续 PassPass 5 完全失败降级回退为按 priority_score 排序 机械分层的 fallback 排名并在 summary 中标注原因Pass 结果缓存--pass-results path会落盘 Pass 1–4 的中间结果categorizations/primer_impacts/dep_graph/scores再次运行时若缓存完整则跳过 Pass 1–4、只重跑 Pass 5run_pipeline#L65-L92。CI 中这正是用来反复迭代终排 prompt 而不用重新支付前四轮成本的手段打分重试score_all对单个 Issue 打分失败会等待 2 秒重试一次再失败则记为priority_score: -1.0并附SCORING FAILED理由避免整体管线因单点失败中断。Pass 2primer 匹配——确定性模板化 具体度评估Pass 2 是把排名扎根于真实影响面的关键。primer_impact.py 的匹配流程建索引遍历 primer 数据中每个项目的 pyrefly 错误把错误消息中反引号包裹的标识符替换为_形成消息模板_templatizeprimer_impact.py#L27-L30即Argument x is not assignable to parameter y归一为Argument _is not assignable to parameter _按(error_kind, template)聚合出受影响项目集合与总错误数_build_primer_indexKind 匹配先精确匹配 Issue 错误 kind 与 primer kind再尝试归一化去连字符/下划线、小写匹配再做子串包含匹配最后才用一次 Haiku 调用做语义级模糊匹配_fuzzy_match_kind模式具体度评估匹配成功后再用一次 Haiku 调用评估该模式对本 Issue 的具体度——HIGH表示该 Issue 很可能就是这些 primer 错误的主要成因LOW表示模式过于泛化、根因众多。这个pattern_specificity随后会被传入 Pass 4 的 prompt让打分时按具体度加权 primer 计数避免匹配数很多但相关性很弱的假信号。Pass 4打分权重——误报与性能最重实现难度不计分Pass 4 的系统 prompt_SYSTEM_PROMPT是整条管线价值观的浓缩其权重表值得完整呈现权重信号说明最高 (x3)误报影响pyrefly 报错而 pyright/mypy 不报错的 Issue——这类错误直接赶走用户primer 频次高会放大该信号最高 (x3)性能内存、检查速度、LSP 响应。性能问题直接阻碍规模化采用高 (x2)团队指派优先级GitHub Projects 中的 P0/P1/P2P0 → 80 分P1 → 65P2 → 50但 prompt 明确允许 LLM 覆盖过期/错误的优先级中 (x1.5)漏报 规范符合度pyrefly 漏报而 pyright/mypy 能抓到的真实类型错误TypeVar/ParamSpec/overloads/narrowing 等规范差距。影响正确性但因用户感知不到没报错紧急度低于误报中 (x1.5)可处理性有清晰最小复现、根因已定位、范围明确 → 高分描述含糊、无法复现 → 低分。特别强调可处理性 ≠ 实现难度修起来再难也不扣分高 (x2)IDE 与易用性hover/补全/跳转/诊断等 LSP 功能IDE bug 建议 60–80 分IDE 功能 45–65 分中 (x1.5)Primer 广度多少 primer 项目命中该错误模式需结合具体度评估加权高 (x2.5)战略采用打了 pytorch / google 标签的 Issue 是最高优先的采用目标阻塞类应给 75中 (x1.5)生态采用pydantic、sqlalchemy 等框架标签低于战略目标低 (x0.5)边缘情形影响项目少、交互少、陈旧、小众场景prompt 中有两条硬约束尤其体现设计意图修复难度或复杂度永远不能降低分数——难修的 bug 和易修的 bug 一样重要只按用户影响与采用风险打分score.py#L47盲评设计LLM 不知道哪些 Issue 已被团队划入 V1 milestone纯靠信号打分从而可以用事后重叠率来盲验证管线质量score.py 模块 docstring。打分输入还会组装丰富的上下文score_issue前序 Pass 的分类与 primer 命中数、反应数/评论数/子 Issue 数、重复簇规模、该 Issue 阻塞的其他 Issue 数量、unresolved_deps警告、Python 运行时输出、前 5 条评论内容以及从 spec_fetcher.py 拉取的 typing 规范摘录按 primer kind 或 pyrefly 错误 kind 检索作为接地材料。输出为priority_score0–100 9 个分项 breakdownfalse_positive_impact、performance、team_priority、correctness、actionability、ide_usability、primer_breadth、adoption_impact、community_demand 一两句理由。Primer 管线用 137 个真实开源项目给排名接地Rank 所需的 primer 数据由独立脚本 scripts/compare_typecheckers.py 生产它克隆约 137 个开源 Python 项目对每个项目分别运行 pyrefly、pyright、mypy输出primer_errors.json供 ranker 的 primer_impact Pass 消费。其运行前提与本地用法来自脚本 docstringcompare_typecheckers.py#L1-L31需要一个安装了 pyright 与 mypy 的 Python 环境pip install pyright mypy支持两阶段模式先--clone-only --cache-dir /tmp/primer_cache克隆项目再在隔离环境内--reuse-cache跑检查器方便在不能联网/克隆的受限环境如容器内分步执行检查器输出有两种形态默认的错误计数汇总表以及--output-json的完整错误消息 JSON后者才是 ranker 需要的输入超时处理与 issue_checker 一致子进程超时被 kill 后返回stderrCHECKER_TIMEOUT的占位结果compare_typecheckers.py#L53-L69——注意这里是刻意使用的专用标记CHECKER_TIMEOUT而非普通timeout下游解析时不会与代码里的超时字样混淆。分片并行由--shard-index/--num-shards两个参数实现_apply_sharding参数必须成对出现、--num-shards为正、--shard-index必须在[0, num_shards)区间内项目列表按步长切片projects[shard_index :: num_shards]分片各分片可完全并行。各分片的 JSON 结果由 scripts/merge_primer_shards.py 合并回单文件再交给 rank 阶段的--primer-data。GitHub Actions 工作流分片矩阵 三任务串联.github/workflows/issue_ranking.yml 把上述脚本装配成可手动触发workflow_dispatch的 CI 工作流输入参数包括labels逗号分隔的标签过滤留空 所有 open issuesrun_primer是否运行 primer 对比约增加 2 小时时长check_snippets是否对 Issue 代码片段跑检查器默认开v1_analysis_run_id填了则只做 V1 分析从指定 Run 下载 ranking.json跳过 primer 与排名。工作流包含 4 个 job依赖关系为primer(×4) → primer-merge → rank另有条件触发的v1-analysis-standaloneprimermatrix.shard: [0, 1, 2, 3]四分片并行跑compare_typecheckers.py每分片timeout-minutes: 300先cargo build --release构建 pyrefly 二进制pip install pyright mypy产物上传为 artifactprimer-shard-Nissue_ranking.yml#L29-L83。primer-merge用 sparse-checkout 只拉取 merge_primer_shards.py下载 4 个分片 artifact 后合并为primer_errors.json上传为primer-results。rank串联三个子步骤——收集python -m scripts.issue_ranker --mode collect若check_snippets开启则pip install pyrefly pyright mypy并用which pyrefly定位二进制传入--pyreflyissue_ranking.yml#L192-L232。注意此处GITHUB_TOKEN优先取secrets.GH_PROJECT_TOKEN——该 token 需要read:project权限才能拉取 GitHub Projects 里的 P0/P1/P2 优先级缺失时会回退到普通 token此时优先级字段为空工作流内注释有说明排名--mode rank若 primer 数据存在则附加--primer-data并始终传--pass-results /tmp/pass_results_cache.json启用缓存V1 差距分析--mode v1-analysis --apply-labels读 ranking.json把分析结论以v1-verified/consider-adding/removing标签回写 GitHub Issue入口代码见main.py#L380-L396仅管理这三类标签不碰其他标签并追加到 Run Summary最后打印分层统计critical/high/medium/low 各多少与 Top 10 Issue并上传ranking.md、ranking.json、缓存与全部日志作为 artifactissue-ranking。v1-analysis-standalone当只填了v1_analysis_run_id时用gh run download run_id -n issue-ranking从历史 Run 拉取 ranking 产物单独重跑 V1 分析——支持排名只做一次标签策略反复迭代的低成本玩法。权限方面值得注意工作流整体permissions: {}显式清空仅 rank 与 v1 job 按需申请issues: write用于回写标签LLM 调用密钥使用secrets.PRIMER_CLASSIFIER_API_KEY注入ANTHROPIC_API_KEY。本地运行与完整参数速查AGENTS.md 给出的最小本地运行序列需要pyright/mypy 已安装、pyrefly 二进制、GITHUB_TOKEN、ANTHROPIC_API_KEY# 1. Primer需要 pyrefly 二进制没有 cargo 时用 --pyrefly 指向现成二进制 python3 scripts/compare_typecheckers.py --output /tmp/primer.json \ --pyrefly /path/to/pyrefly # 2. 收集并富化 Issue需要 GITHUB_TOKEN python3 -m scripts.issue_ranker --mode collect \ --pyrefly /path/to/pyrefly --output /tmp/issues.json # 3. 排名需要 ANTHROPIC_API_KEY python3 -m scripts.issue_ranker --mode rank \ --primer-data /tmp/primer.json --issue-data /tmp/issues.json \ --output /tmp/ranking.md --output-json /tmp/ranking.json完整 CLI 参数来源main.py 的main()参数说明--mode {collect,rank,full,v1-analysis}必需。collect 抓取富化rank 跑 LLM 管线full 两者合一v1-analysis 对既有 ranking.json 做 V1 差距报告--labels逗号分隔的 GitHub 标签过滤默认所有 open issues--limit N最多抓取 N 个 Issue调试用--pyrefly PATH用于检查代码片段的 pyrefly 二进制路径collect 阶段不提供则跳过检查器执行--primer-data PATHcompare_typecheckers.py 产出的 primer_errors.json--issue-data PATHcollect 模式产出的 issue_data.jsonrank 模式必需除非用 full--output/-oMarkdown 报告输出路径不传则打印到 stdout--output-jsonJSON 结果输出路径--pass-resultsPass 1–4 中间结果缓存路径文件有效时跳过 Pass 1–4 只重跑 Pass 5--ranking-jsonv1-analysis 模式的输入 ranking.json缺省回退取--output-json值--apply-labelsv1-analysis 模式下把标签回写到 GitHub仅管理 v1-verified / consider-adding / removing 三类--debug开启 DEBUG 级日志测试方面AGENTS.md 指出单测位于 scripts/issue_ranker/tests/含对 ranker 与 compare_typecheckers 的测试LLM 集成测试位于 scripts/issue_ranker/llm_tests/覆盖代码提取、状态分类、各 Pass、GitHub 抓取与 LLM 传输层并可用buck test pyrefly:issue_ranker_tests运行。经验结论primer 数据与团队优先级标签为何都重要AGENTS.md 最后记录了 2026 年 3 月的一组管线调优经验原文档中的关键结论可视为该团队的实测发现Primer 数据显著改变排名在 137 个真实项目上运行检查器让排名扎根于实际影响面没有 primer 数据时单个 Issue 的得分可能摆动 30–44 分分层tier分布也会大幅漂移团队优先级标签有独立价值纳入 GitHub Projects 的 P0/P1/P2 后管线排名与 V1 milestone 的重叠率提升约 16 个百分点两者叠加效果最佳——真实影响面客观、来自代码实测与团队判断主观、但反映业务约束互为补充。这一结论也解释了管线的整体设计哲学确定性计算检查器实测、字符串模板匹配、分片统计负责提供可复现、可核实的事实信号LLM 只负责其中真正需要语义理解的环节代码提取/修复、状态归类、依赖图、加权打分、终排裁决并且每一处 LLM 输出都有启发式 fallback状态分类的_heuristic_classify、Pass 3/5 的降级路径、Pass 2 的确定性匹配优先使得整条管线在 API 不可用时仍能产出可用结果。核心文件索引路径角色scripts/issue_ranker/AGENTS.md管线架构总览本文主体文档scripts/issue_ranker/main.pyCLI 入口collect 七阶段与四种 modescripts/issue_ranker/pipeline.py5 轮 LLM 管线编排、成本估算、缓存与降级scripts/issue_ranker/code_extractor.py三级代码提取 LLM 片段修复scripts/issue_ranker/issue_checker.py三检查器执行、依赖重试、错误过滤scripts/issue_ranker/dep_resolver.py从检查器错误提取缺失模块并安装scripts/issue_ranker/status_classifier.py五态分类启发式 LLM 兜底scripts/issue_ranker/relationship_resolver.py重复/阻塞/父子关系解析scripts/issue_ranker/passes/5 个 Pass 实现categorize / primer_impact / dependencies / score / rankscripts/issue_ranker/llm_transport.pyLLM API 封装Anthropic Llama带重试scripts/issue_ranker/spec_fetcher.py拉取 typing 规范摘录供打分接地scripts/issue_ranker/report_formatter.pyMarkdown / JSON 报告生成scripts/compare_typecheckers.pyprimer 对比脚本克隆、分片、双检查器scripts/merge_primer_shards.py合并 primer 分片输出.github/workflows/issue_ranking.ymlCI 工作流分片矩阵、合并、排名、V1 分析scripts/issue_ranker/tests/单元测试scripts/issue_ranker/llm_tests/LLM 集成测试【免费下载链接】pyreflyA fast type checker and language server for Python项目地址: https://gitcode.com/GitHub_Trending/py/pyrefly创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考