拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Open SWE Review 与 Analyzer 架构解析:基于 LangGraph 的隔离式 PR 评审与仓库风格学习图谱

Open SWE Review 与 Analyzer 架构解析基于 LangGraph 的隔离式 PR 评审与仓库风格学习图谱【免费下载链接】open-sweAn Open-Source Asynchronous Coding Agent项目地址: https://gitcode.com/GitHub_Trending/op/open-sweOpen SWE 以 LangGraph 为基础将PR 代码评审与仓库评审风格学习拆分为两个彼此隔离的专用深度代理图谱revieweragent.graphs.reviewer:traced_reviewer_agent与analyzeragent.graphs.analyzer:traced_analyzer。本文以 openwiki/architecture/reviewer-and-analyzer.md 为主干结合源码逐层剖析评审图谱的权限边界、run 准备、持久化 finding 生命周期与发布语义以及分析器如何为每个仓库学习一份评审风格补充提示词并最终通过每日 cron 持续进化。读完本文你将理解 Open SWE 评审系统评审与学习分离、状态持久化、失败可重试的核心设计以及每个配置项在源码中的落点。关联阅读PR Review Workflow触发路由与 webhook 行为、Sandbox Lifecycle沙箱提供方与恢复、Tools完整工具目录。Reviewer受限的 PR 评审图谱权限边界与图谱构造Reviewer 对仓库是只读的。其系统提示词明确禁止 commit、push 以及对gh pr review/评审 API 的直接调用构造出的深度代理不携带任何编码、提交、推送或打开 PR 的工具——仓库变更永远不会成为评审代理的动作。GitHub 评审变更被集中收敛到publish_review与 finding 线程工具中保证所有写操作只有一条受控路径。在图谱工厂get_reviewer_agent(config)agent/reviewer.py中可以看到完整的构造细节配置隔离工厂先config.copy()浅拷贝外层 config 及其configurable映射再写入默认递归上限recursion_limit DEFAULT_RECURSION_LIMIT从而保留调用方的配置不被动用。该不变量由 tests/reviewer/test_factory_config_isolation.py 专门保护。空图降级若运行没有thread_id或图谱未以执行模式加载graph_loaded_for_execution为假工厂刻意返回一个空深度代理create_deep_agent(system_prompt, tools[])而不是去申请沙箱。模型解析从显式配置reviewer_model_id/reviewer_reasoning_effort、reviewer_subagent_model_id/reviewer_subagent_reasoning_effort或团队默认模型对中选取评审模型与子代理模型经过gate_fable_model模型门控再挂载带 reconnect 闭包的缓存沙箱后端。评审代理的显式工具清单agent/reviewer.py类别工具评审生命周期fetch_review_diff、add_finding、update_finding、list_findings、publish_review、resolve_finding_thread、reply_to_finding_thread只读外部辅助web_search、fetch_url、http_request图谱允许挂载一个reviewer子代理_reviewer_subagent见 agent/reviewer.py。父代理分配不相交的文件分区给子代理子代理只返回候选缺陷既没有 finding 工具也没有发布工具——校验、持久化与发布的责任始终在父代理。子代理会编译成独立图谱因此父代理的中间件不会包裹其模型调用仅附加SanitizeOpenAIResponsesMiddleware、ModelErrorMiddleware、ModelCallTimeoutMiddleware。Run 准备、GitHub 访问与上下文组装PrepareReviewerRunMiddlewareagent/reviewer.py在首次模型调用前执行确定性的准备工作认证与沙箱代理对配置了 source 仓库的运行铸造仓库作用域的 GitHub App installation token缓存为该线程的 bot tokencache_github_token_for_thread(..., is_bot_tokenTrue)并供给沙箱 GitHub 代理。沙箱与检出以allow_replacementTrue确保沙箱存在克隆或拉取仓库强制 checkout PR head并从 base 修订物化受信任的仓库技能materialize_trusted_skills。Diff 计算计算评审区间及其 unified diff含 delta-only 的重复评审区间再推导变更的(file, side, line)集合。将diff_text与diff_line_set写入 run state——这让add_finding能在创建时拒绝无效锚点而不是等 GitHub 批量拒绝。并行上下文抓取并发获取 PR 标题与正文、已有 GitHub 评审线程、已保存的仓库风格、组织准则、base SHA 上的根级与作用域级AGENTS.md/CLAUDE.md、API 标准技能以及可选的作者 trace 上下文。线程对账已有线程在渲染进提示词块之前先执行reconcile_findings_with_review_threads。引导式提示词diff 就绪后为变更文件选择作用域指令渲染出的提示词按 first-review、re-review、finding-reply 三种模式选择上下文。后台分组diff 分组以 best-effort 后台任务启动maybe_generate_and_store_diff_groups永不阻塞评审。代码中通过_BACKGROUND_TASKS强引用持有 fire-and-forget 任务防止事件循环在飞行中将其 GCagent/reviewer.py。整体流程如下上下文获取在准备阶段并发进行对账在加载已有线程上下文的同时运行。沙箱替换失败语义如果沙箱替换本身抛出SandboxUnreachableError准备阶段会在 PR 上发布一条带类型的 unreachable-sandbox 通知并使该 run 失败agent/reviewer.py而不是静默留下未评审的 PR。这个替换策略是安全的因为每次 run 都会重新派生 checkout且 finding 不属于沙箱状态。提示词与输入安全约束评审提示词要求 finding 具备具体、锚定在变更行上的失败模式并拒绝投机性评论、普通风格/命名 nit、diff 之外的既有缺陷以及同一缺陷跨文件的重复扇出。明确违反仓库约定的问题在锚定于 diff 且具备具体失败模式时仍可评审。建议suggestion仅限小而明显的修复源码中MAX_SUGGESTION_LINES 4超过 4 行的 suggestion 被丢弃。不可信输入处理是评审系统的重要安全面。PR 标题/正文、已有评审线程评论、finding 回复都是攻击者可控的 GitHub 内容。渲染器agent/reviewer.py的做法是将它们置于 XML data 块中pr_review_threads/thread/comment/body等并在系统提示词中声明块内内容是数据而非指令对登录名按 GitHub login 语法^A-Za-z0-9){0,38}(?:\[bot\])?$校验不匹配者一律显示为unknown防止自由文本通过author属性泄漏用_escape_for_data_block对包装器的闭合标签做空白容忍匹配并改写为惰性形式如/body→/body_使正文无法逃逸出包装器单条超长评论截断至 4000 字符防止单个评论撑爆上下文。作者 trace 上下文同样被显式视为不可信不得发布。持久化 finding 生命周期Finding 存储在确定性评审线程的 LangGraph metadata中而非沙箱内。reviewer_thread_id(owner, repo, pr_number)使用 UUID5见 agent/thread_ids.py基于f{owner}/{repo}/pr/{pr_number}/reviewer派生因此 webhook、dashboard 代码和 run 在多次 push 之间都能检索到同一个每 PR 一线程。set_reviewer_thread_metadata总是写入kind: revieweragent/review/findings.py该标签支持 UI 的跨线程查找与用量聚合。Findingagent/review/findings.py记录位置与 side、严重度与置信度、标题/描述/建议、diff 成员关系与 hunk、状态、首次与最后确认 SHA、发布身份review/comment/thread ID 列表、surface 状态、人类回复/对账字段、指纹与交互历史。旧版持久化形状在读取时统一规范化coerce_finding中的_normalize_publication_identity把扁平单数 ID、github_thread_resolved标志与嵌套surface记录折叠进规范字段。surface 状态是单调的规范化在遇到矛盾的遗留数据时取推进最远的状态SURFACE_STATE_ORDER。surface 状态机独立于 finding 的open/resolved/dismissed状态推进add_findingagent/tools/add_finding.py的校验逻辑校验 title、severitylow/medium/high/critical、confidencelow/medium/high、sideLEFT/RIGHT与有序行区间end_line start_linediff 上下文解析顺序注入的 run state →configurable→ 重新拉取已认证 PR diff锚定行区间不在对应 diff side 上时返回success: false与in_diff: false提示词要求模型不要重新锚定或重试文件级 finding 会被接受但不渲染为 inline commentGitHub Reviews API 要求 inline 评论必须锚定到行见render_inline_comment_payload对无end_line返回None成功写入时尽量抽取 diff hunk、裁剪超过 4 行的 suggestion并通过内容指纹去重_finding_fingerprint对 file/side/行区间/规范化描述做 SHA-256。每次常规 run 前reconcile_findings_with_review_threadsagent/review/reconcile.py按以下优先级匹配 finding 与 GitHub 线程嵌入 marker → 记录的线程 ID → 记录的评论 ID。它回填评论/线程 ID并把匹配的 finding 标记为 surfaced。只有所有匹配线程都已 resolvefinding 才变为 resolvedoutdated 但未 resolve 的线程不会解决它。bot 评论之后最新的非 bot 回复被保留为human_reply交互并标记needs_reassessment: Trueagent/review/reconcile.py给后续 re-review 一个持久的重新评估理由。发布与失败语义publish_review过滤条件未发布not surfaced、在 diff 内、状态为 open、severity 达到阈值默认medium的 finding并按REVIEW_FINDING_CAP 6封顶批量。一次调用发布一个GitHub PR Review包含固定、由宿主生成的摘要正文no issues found 或 found N potential issue(s)代理不写散文每个可渲染 finding 一条 inline comment锚定pathline区间加start_linesidesuggestion存在时追加为围栏suggestion块——启用 GitHub 的 Commit suggestion 按钮每条评论带open-swe-review-commentJSON markerfinding 身份 锚点元数据支持对账与丢失 ID 恢复。评论正文由render_inline_comment_body生成agent/review/publish.py格式为marker → severity emojicritical/high/medium/low 标题 → 详情 → 行引用 → 分隔线 反馈引导 → 可选suggestion块。严重度低于阈值或 diff 外的 finding 被收进摘要正文的details折叠块render_out_of_diff_sectionweb app 也可查看。发布成功后的工具行为记录 review/comment/thread 身份通过 GraphQLresolveReviewThread变异为已 resolved 的 finding 解决线程推进last_reviewed_sha记录用量清理 started-review 状态评论结算 GitHub review check run。re-review 时已发布的 finding不会重复发布没有任何新 inline comment 的 run 可以有意跳过重复的空评审skipped_empty_re_review同时仍解决线程并推进状态。调用方必须检查结构化结果结果含义success: truereview_id: nullskipped_empty_re_review: true合法的未发布结果无新评论可发dry_run: true评估模拟不产生真实发布数值型review_id确认产生了真实 review当 GitHub 报告无法解析的锚点422 Path could not be resolved/Line could not be resolved见post_pull_request_review的_error_kind: unresolved_anchor时工具过滤无效 finding 并以有效锚点重试一次仍失败则返回unresolvable_findings与补救提示避免盲目重试。持久化线程状态缺失则返回结构化的 do-not-retry 结果ReviewerThreadMissingError被包装为thread_missing_tool_result见 agent/review/findings.py因为线程不可能通过重试出现。Analyzer仓库评审风格学习图谱与沙箱模型Analyzer 为 reviewer学习一份仓库特定的评审风格提示词。其准备流程PrepareAnalyzerRunMiddlewareagent/analyzer.py解析仓库身份与模式、确保沙箱存在并用 dashboard 提供的 OAuth token 或 GitHub App installation token 配置 LangSmith GitHub 代理仅当SANDBOX_TYPE langsmith时。Analyzer 只有两个领域工具read_finding_outcomes与save_review_style_prompt外加 80 次模型调用上限STYLE_ANALYZER_MODEL_CALL_LIMIT 80、输入净化、工具错误、超时与响应净化中间件。与 reviewer 相同get_analyzer在没有thread_id或图谱执行被禁用时返回空代理。差异点analyzer 工厂把默认递归上限直接写进传入的 configconfig[recursion_limit] DEFAULT_RECURSION_LIMIT而非浅拷贝——需要配置隔离的调用方不能假设 reviewer 的行为在此同样适用。analyzer_mode选择一份虚拟 playbookbootstrap→ 使用bootstrap-repo-analysis技能agent/skills/bootstrap-repo-analysis/SKILL.md。冷启动流程用gh收集并扩展历史合并 PR 反馈寻找实质性的人类评论与评审者规范然后综合出初始提示词。continual→ 使用continual-learning技能agent/skills/continual-learning/SKILL.md。读取已确认与已驳回的 reviewer 结果提升反复出现的确认模式、降级反复出现的误报模式对当前提示词做精炼而非替换。基础提示词将模型导向模式 playbook并注入REVIEWER_STYLE_THEMES见 agent/review/style_guidance.py保证学习到的建议始终受限于 reviewer 的高信号、diff 锚定策略边界。playbook 而非简短的基础提示词定义操作流程。两份 playbook 被打包为虚拟文件启动器把build_skill_files()种入输入files通道get_analyzer在CompositeBackend中以StateBackend挂载/skills/路由agent/utils/analyzer_skills.py。代理以/skills/name/SKILL.md读取而后端收到的是剥离前缀的路径。CompositeBackend剥离/skills/前缀后委托给StateBackend种入的键是剥离后的路径如/bootstrap-repo-analysis/SKILL.md代理与SkillsMiddleware则以/skills/...寻址——从而避免把捆绑的过程性内容写入执行沙箱。风格存储与启动路径REVIEW_STYLES是一个类型化 storeTypedStore位于review_styles命名空间以owner/repo为键agent/review/styles.py。一条ReviewStyle记录包含字段说明statusidle / running / completed / failedcustom_prompt/analysis_summary已保存的评审风格提示词与摘要top_reviewers/prs_sampled/reviews_sampled采样评审者与样本计数analysis_thread_id/analysis_run_id分析线程与 run IDcontinual_cron_id每日持续学习 cron 的 IDerror/ 审计时间戳失败信息与审计字段Reviewer 在准备阶段以**失败软化fail-soft**方式检索custom_promptget_repo_custom_promptagent/review/styles.pystore 故障只是丢失风格补充不会让整个 PR 评审失败。可用时追加到提示词的 Repository-specific review style 章节且仅当与全局评审标准一致时才生效系统提示词中注明 Apply them when they agree with the global bar above。启动路径agent/review/style_jobs.pystart_bootstrap_analysis先用调用方 GitHub token 收集评审样本collect_review_samples把记录标记为 running再在review_style_thread_id(owner, repo)确定性线程上创建持久化 analyzer run传递样本、计数、评审者、OAuth token、bootstrap 模式与虚拟技能文件。样本收集或持久化 run 启动失败时把风格记录标记为 failed。start_continual_run用同一个确定性风格线程创建即时的、结果驱动的持久化 run。终端工具save_review_style_promptagent/tools/save_review_style.py要求非空custom_prompt与review_style_full_name持久化裁剪后的提示词、摘要、评审者与样本计数为 completed 记录。空输出把记录标记为 failed。保存后尝试cron 注册但注册失败不会撤销已保存的风格。持续学习 cron 操作保存成功后调用ensure_continual_cronagent/review/analyzer_cron.py。若风格记录已有 cron ID注册是幂等的否则创建一个指向analyzer的每日 LangGraph cron携带kind: analyzer_continual元数据与由 SHA-256 派生的稳定时间05:00–08:59 UTC 之间按仓库错峰避免惊群minute digest % 60、hour 5 (digest // 60) % 4并把返回的 cron ID 存回记录。remove_continual_cronbest-effort 删除已注册的远端 cron 并清空存储的 ID注册失败仅记 debug 日志。cron 本身是无线程的但其 configurable 显式提供确定性的review_style_thread_idbuild_continual_run_configurableagent/review/style_jobs.py——否则 analyzer 会因没有 thread_id 而创建空图run 静默空转。其输入不携带累积的消息历史而共享线程仍按仓库键定沙箱与 metadata。调度的 configurable 选择continual模式由于不提供新鲜用户 tokenanalyzer 准备阶段会获取 App installation token。同一份输入种入 playbook 所需的捆绑技能。聚焦测试评审测试套件覆盖配置隔离、diff 与工具校验含 LEFT-side 锚点、持久化 finding 行为、发布与 marker 渲染、对账、后台 diff 分组、trace 上下文、trigger/watch 行为以及 review API/chat 路径。具体而言tests/reviewer/test_factory_config_isolation.py保护 reviewer 的配置拷贝不变量tests/reviewer/test_reviewer_tools.py校验 validation 与持久化决策tests/reviewer/test_reviewer_reconcile.py覆盖 marker 回填与 terminal-thread 规则tests/reviewer/test_reviewer_publish.py覆盖渲染的 marker 与 suggestion 块tests/analyzer/test_analyzer_cron.py验证 cron 创建、幂等、移除、种入的 continual 技能文件、显式线程配置与确定性调度窗口。总结评审与学习分离的设计要点回顾整条链路Open SWE 评审体系的设计可以归纳为四点权限最小化reviewer 只读仓库写操作全部收敛到 finding 工具与publish_reviewGitHub 评审变异是唯一出口。状态外置finding 存于确定性 reviewer 线程的 LangGraph metadata跨 push、跨沙箱重建存活配合 marker 对账实现线程级恢复。失败结构化锚点不可解析、线程缺失、空 re-review 都返回结构化结果而非模糊错误从根上避免盲目重试烧 token。评审风格自进化analyzer 以 bootstrap 冷启动 continual 每日精炼将团队历史评审习惯固化为仓库级提示词再以确定性时间窗口的 cron 持续更新而这一切都受全局评审标准的约束。输出文章【免费下载链接】open-sweAn Open-Source Asynchronous Coding Agent项目地址: https://gitcode.com/GitHub_Trending/op/open-swe创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门