🚀

用 Ollama 搭一个本地 AI 代码解释器:复杂代码秒变大白话

把手写复杂代码丢给本地 LLM,自动翻译成大白话+逐行注释+画流程图。代码看不懂?本地 AI 替你拆解。

👁️ - 次阅读

项目背景

你是不是也经历过这种场景:接手一段前人写的代码,功能逻辑复杂,注释几乎没有,看半天看不懂在干嘛。

上网搜解决方法?把代码贴给 ChatGPT 吧,敏感业务逻辑全上传到人家服务器;用本地模型吧,又不会搭。

其实用 Ollama 搭一个本地代码解释器很简单——代码不离开本地,翻译、注释、画流程图一步到位。

这个项目的目标:输入一段代码,输出大白话解释 + 逐行中文注释 + 调用流程图,全在本地跑。

技术选型

组件选择理由
语言Python 3.10+生态成熟
LLMOllama + Qwen2.5-Coder代码理解能力强,本地免费
代码解析tree-sitter抽象语法树,精准定位代码结构
流程图Graphviz (digraph)轻量,Python 直接调用
输出格式Markdown兼容性好,可直接嵌入文档

不需要数据库,不需要后端服务。一个脚本,一段代码,出来就是解释结果。

实现步骤

第一步:安装依赖

pip install ollama tree-sitter tree-sitter-python graphviz
brew install graphviz  # macOS
# 或 sudo apt install graphviz  # Ubuntu

启动 Ollama 并拉取代码专用模型:

ollama pull qwen2.5-coder:7b
ollama serve

第二步:项目结构

code_explainer/
├── explainer.py      # 主脚本
├── prompts.py        # 提示词模板
├── parser.py         # 代码结构解析
├── visualizer.py     # 流程图生成
├── config.yaml       # 配置文件
└── samples/          # 示例代码
    └── example.py

第三步:编写主脚本

explainer.py:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
import json
import ollama
import yaml
from pathlib import Path
from parser import parse_code_structure
from visualizer import generate_flowchart
from prompts import (
    EXPLAIN_PROMPT,
    COMMENT_PROMPT,
    FLOW_PROMPT
)


def load_config(config_path: str = "config.yaml") -> dict:
    """加载配置文件"""
    with open(config_path, "r", encoding="utf-8") as f:
        return yaml.safe_load(f)


def explain_code(code: str, model: str = "qwen2.5-coder:7b", config: dict = None) -> dict:
    """调用 Ollama 解释代码"""
    cfg = config or load_config()
    
    # 1. 大白话解释
    explain_resp = ollama.chat(
        model=model,
        messages=[{
            "role": "user",
            "content": EXPLAIN_PROMPT.format(code=code, language=cfg.get("language", "python"))
        }]
    )
    plain_explain = explain_resp["message"]["content"].strip()
    
    # 2. 逐行注释
    comment_resp = ollama.chat(
        model=model,
        messages=[{
            "role": "user",
            "content": COMMENT_PROMPT.format(code=code, language=cfg.get("language", "python"))
        }]
    )
    commented_code = comment_resp["message"]["content"].strip()
    
    # 3. 流程图描述(给 visualizer 用)
    flow_resp = ollama.chat(
        model=model,
        messages=[{
            "role": "user",
            "content": FLOW_PROMPT.format(code=code)
        }]
    )
    flow_desc = flow_resp["message"]["content"].strip()
    
    return {
        "plain_explain": plain_explain,
        "commented_code": commented_code,
        "flow_desc": flow_desc
    }


def process_file(file_path: str, output_dir: str = "output"):
    """处理单个代码文件"""
    code = Path(file_path).read_text(encoding="utf-8")
    model = load_config().get("model", "qwen2.5-coder:7b")
    
    print(f"📄 正在分析: {file_path}")
    print(f"🤖 使用模型: {model}")
    print("-" * 50)
    
    result = explain_code(code, model=model)
    
    # 生成输出目录
    out = Path(output_dir)
    out.mkdir(exist_ok=True)
    
    base_name = Path(file_path).stem
    
    # 保存大白话解释
    explain_file = out / f"{base_name}_explain.md"
    explain_file.write_text(f"# {base_name} 代码解释\n\n{result['plain_explain']}\n", encoding="utf-8")
    print(f"✅ 解释已保存: {explain_file}")
    
    # 保存带注释的代码
    comment_file = out / f"{base_name}_commented.py"
    comment_file.write_text(result["commented_code"], encoding="utf-8")
    print(f"✅ 注释代码已保存: {comment_file}")
    
    # 生成流程图
    flow_file = out / f"{base_name}_flowchart.dot"
    flow_file.write_text(result["flow_desc"], encoding="utf-8")
    print(f"✅ 流程图描述已保存: {flow_file}")
    
    # 尝试渲染流程图
    try:
        import graphviz as gv
        dot = gv.Source(result["flow_desc"])
        dot.render(out / f"{base_name}_flowchart", format="png", cleanup=True)
        print(f"✅ 流程图已渲染: {out / f'{base_name}_flowchart.png'}")
    except Exception as e:
        print(f"⚠️ 流程图渲染失败: {e}")
    
    # 打印到终端
    print("\n" + "=" * 50)
    print("📖 大白话解释:")
    print("=" * 50)
    print(result["plain_explain"])
    print("\n" + "=" * 50)
    print("💬 终端输出完成,结果已保存到 output/ 目录")


def main():
    if len(sys.argv) < 2:
        print("用法: python explainer.py <代码文件路径> [输出目录]")
        print("示例: python explainer.py samples/example.py ./output")
        sys.exit(1)
    
    code_file = sys.argv[1]
    output_dir = sys.argv[2] if len(sys.argv) > 2 else "output"
    
    if not Path(code_file).exists():
        print(f"❌ 文件不存在: {code_file}")
        sys.exit(1)
    
    process_file(code_file, output_dir)


if __name__ == "__main__":
    main()

第四步:编写提示词模板

prompts.py:

# 大白话解释提示词
EXPLAIN_PROMPT = """你是一位经验丰富的程序员,擅长把复杂代码翻译成普通人能听懂的话。

请用中文解释以下 {language} 代码的功能和逻辑:

```{language}
{code}
```

要求:
1. 用一段话概括这段代码的核心功能(不超过100字)
2. 列出代码的输入、输出和关键步骤
3. 指出代码中可能存在的性能问题或潜在 bug
4. 给出改进建议(不超过3条)

只输出解释内容,不要重复代码。"""

# 逐行注释提示词
COMMENT_PROMPT = """你是代码注释专家。请为以下 {language} 代码添加详细的中文注释。

```{language}
{code}
```

要求:
1. 文件头注释说明文件用途
2. 每个函数/方法添加 docstring
3. 关键逻辑行添加行内注释
4. 复杂算法添加步骤说明

直接输出带注释的完整代码,不要添加额外解释。"""

# 流程图提示词
FLOW_PROMPT = """请分析以下代码的逻辑流程,输出 DOT 格式的有向图描述。

```python
{code}
```

要求:
1. 用节点表示关键步骤(函数调用、条件判断、循环等)
2. 用箭头表示执行顺序
3. 条件分支标注 true/false
4. 使用标准的 DOT 语法

只输出 DOT 代码,格式如下:
digraph {
  rankdir=TB;
  node [shape=box];
  ...
}"""

第五步:运行

# 先准备一段示例代码
python explainer.py samples/example.py ./output

运行后你会得到三个文件:

  • example_explain.md — 大白话解释
  • example_commented.py — 带中文注释的代码
  • example_flowchart.png — 流程图

终端输出示例:

📄 正在分析: samples/example.py
🤖 使用模型: qwen2.5-coder:7b
--------------------------------------------------
✅ 解释已保存: output/example_explain.md
✅ 注释代码已保存: output/example_commented.py
✅ 流程图描述已保存: output/example_flowchart.dot
✅ 流程图已渲染: output/example_flowchart.png

==================================================
📖 大白话解释:
==================================================
这段代码实现了一个简单的缓存装饰器...

运行效果

以这段经典的快速排序为例:

def quick_sort(arr):
    if len(arr) <= 1:
        return arr
    pivot = arr[len(arr) // 2]
    left = [x for x in arr if x < pivot]
    middle = [x for x in arr if x == pivot]
    right = [x for x in arr if x > pivot]
    return quick_sort(left) + middle + quick_sort(right)

AI 生成的解释:

核心功能:对列表进行升序排序,使用分治策略,每次选中间元素作为基准点,将数组分为小于、等于、大于三部分,递归排序后合并。

输入:任意可比较元素的列表 输出:排序后的新列表(不修改原列表)

潜在问题:

  • 每次递归都创建三个新列表,内存开销大
  • 最坏情况 O(n²),虽然概率低

改进建议:

  • 改为原地排序,减少内存分配
  • 使用三数取中法选择 pivot

流程图会自动画出递归调用结构,一眼看清数据流向。

优化方向

  1. 支持多语言:当前只解析 Python,加上 JavaScript、Go 等语言的 tree-sitter parser,输入不同语言自动切换。

  2. 批量处理:加个 --dir 参数,一次性处理整个目录的代码文件,适合给新项目做整体解读。

  3. 增量解释:只解释修改过的部分,不重复分析未改动代码。结合 git diff 实现。

  4. 交互式问答:加个 REPL 模式,解释完之后可以继续追问"这个函数为什么这么写?““有没有更简单的写法?”

  5. 集成 IDE:做成 VSCode 插件,选中代码右键就能看解释,写代码时实时提示。

  6. 模型切换:短代码用 llama3.2:1b 秒出结果,复杂算法切到 qwen2.5-coder:14b 提升准确率。

  7. 导出 PDF:把解释、注释代码、流程图打包成一份 PDF 报告,发给同事直接看。

核心思路就一句:代码看不懂的时候,本地 AI 替你拆。不用联网,不用担心泄露,模型选对解释质量就够了。

你手头有没有一段看不懂的老代码?直接喂进去试试,看 AI 能不能给你讲清楚。

这篇文章对你有帮助吗?