技术教程 · 阅读约 8 分钟

用 50 行 Python 让 AI 帮你审完整个代码仓库(附完整可运行代码)

用 50 行 Python 让 AI 帮你审完整个代码仓库(附完整可运行代码)


很多人用 AI 审代码的方式是:复制一个文件,粘贴进对话框,等回复,再复制下一个。

这种方式有两个问题:一是累,二是 AI 看不到文件之间的依赖关系,给出的建议往往是孤立的、没有上下文的。

真正有用的代码审查,应该是让模型同时看到整个 repo 的结构,然后给出跨文件的、有依赖意识的建议。

今天就来实现这个。


思路

核心逻辑很简单:

1. 递归遍历 repo,收集所有代码文件

2. 把文件路径 + 内容拼成一个大的 context

3. 一次性发给模型,让它做整体审查

难点在于:大型 repo 的 token 量会超限。解决方案是分批 + 摘要:先让模型对每个文件生成摘要,再把摘要汇总后做整体分析。


完整代码


import os

import sys

from pathlib import Path

from openai import OpenAI



# 改一行 base_url,国内直连,无需代理

client = OpenAI(

    api_key="your_api_key_here",

    base_url="https://api2everything.xyz/v1"

)



# 要审查的文件类型

CODE_EXTENSIONS = {'.py', '.js', '.ts', '.go', '.java', '.rs', '.cpp', '.c', '.h'}



# 单文件 token 上限(粗略按字符估算,4 char ≈ 1 token)

MAX_CHARS_PER_FILE = 8000





def collect_files(repo_path: str) -> list[dict]:

    """递归收集代码文件"""

    files = []

    repo = Path(repo_path)

    

    # 跳过这些目录

    skip_dirs = {'.git', 'node_modules', '__pycache__', '.venv', 'dist', 'build'}

    

    for path in repo.rglob('*'):

        if any(part in skip_dirs for part in path.parts):

            continue

        if path.is_file() and path.suffix in CODE_EXTENSIONS:

            try:

                content = path.read_text(encoding='utf-8', errors='ignore')

                files.append({

                    'path': str(path.relative_to(repo)),

                    'content': content[:MAX_CHARS_PER_FILE],

                    'truncated': len(content) > MAX_CHARS_PER_FILE

                })

            except Exception:

                pass

    

    return files





def summarize_file(file: dict) -> str:

    """让模型对单个文件生成结构摘要"""

    truncation_note = "(内容已截断)" if file['truncated'] else ""

    

    prompt = f"""请对以下代码文件做简短分析(100字以内),包括:主要功能、潜在问题、值得关注的点。



文件路径:{file['path']} {truncation_note}



{file['content']}




    response = client.chat.completions.create(

        model="gpt-4o-mini",  # 摘要阶段用便宜的小模型

        messages=[{"role": "user", "content": prompt}],

        max_tokens=200

    )

    return response.choices[0].message.content





def review_repo(repo_path: str, model: str = "gpt-4o"):

    """主流程:审查整个 repo"""

    print(f"📂 扫描仓库:{repo_path}")

    files = collect_files(repo_path)

    

    if not files:

        print("未找到代码文件")

        return

    

    print(f"📄 找到 {len(files)} 个文件,开始生成摘要...\n")

    

    # 第一阶段:并行生成每个文件的摘要

    summaries = []

    for i, file in enumerate(files):

        print(f"  [{i+1}/{len(files)}] {file['path']}")

        summary = summarize_file(file)

        summaries.append(f"### {file['path']}\n{summary}")

    

    # 第二阶段:汇总摘要,做整体审查

    print("\n🔍 正在进行整体代码审查...\n")

    

    all_summaries = "\n\n".join(summaries)

    

    final_prompt = f"""你是一位资深工程师,正在对一个代码仓库做整体 Code Review。



以下是仓库中每个文件的摘要:



{all_summaries}



请从以下维度给出整体审查报告:

1. **架构问题**:模块划分、依赖关系是否合理

2. **安全风险**:有无明显的安全漏洞或不良实践

3. **性能隐患**:可能的性能瓶颈

4. **代码质量**:命名、注释、可维护性

5. **优先修复项**:列出最需要立即处理的 3 个问题



用中文回答,给出具体的文件路径和改进建议。"""



    response = client.chat.completions.create(

        model=model,

        messages=[{"role": "user", "content": final_prompt}],

        max_tokens=2000

    )

    

    print("=" * 60)

    print("📋 Code Review 报告")

    print("=" * 60)

    print(response.choices[0].message.content)





if __name__ == "__main__":

    repo_path = sys.argv[1] if len(sys.argv) > 1 else "."

    review_repo(repo_path)


使用方式


pip install openai



# 审查当前目录

python review.py .



# 审查指定路径

python review.py /path/to/your/project

把 your_api_key_here 换成你的 key 就能跑。


几个值得注意的细节

为什么摘要阶段用 gpt-4o-mini?

摘要是重复性、低难度任务,用小模型足够,成本大概是 gpt-4o 的 1/15。整体审查才需要强模型的推理能力。这种分层调用是控制成本的常见手段。

为什么不直接把所有文件塞进一个 prompt?

对于超过 20 个文件的 repo,直接拼接很容易超过 128k context 限制,而且模型在超长 context 中间部分的注意力会显著下降(lost in the middle 问题)。分批摘要 + 汇总的方式更稳定。

想换成 Claude 怎么办?

把 model 参数改成 claude-sonnet-4-5 就行,接口格式完全兼容,base_url 不用动。


关于 API 费用

跑一次中型项目(50 个文件左右),大概消耗:

  • 摘要阶段(gpt-4o-mini):约 $0.02
  • 整体审查(gpt-4o):约 $0.05

如果直接用 OpenAI 官方,加上国内访问需要的代理成本,实际花费会更高。

我自己用的是 无量Api,国内直连,价格比官方便宜 60% 以上,OpenAI / Claude / Gemini / DeepSeek 300+ 模型都有,注册就送 ¥1 余额,改一行 base_url 就能用,上面代码里已经写好了。


扩展方向

  • 加 --fix 参数,让模型直接输出修复后的代码
  • 接入 GitHub Actions,每次 PR 自动触发审查
  • 把报告格式改成 SARIF,直接导入 VS Code 的 Problems 面板

有跑起来遇到问题的,评论区说一下,我看到都会回。觉得有用的话点个赞,后续还会写更多 AI + 工程效率的实战内容。