tagoo闪聊
44.38M · 2026-02-07
上篇搞定了 AST 解析和规则引擎,能检查出代码的问题了。但用了几天发现一个痛点:
规则只能告诉你"哪里有问题",不能告诉你"怎么改"。
比如它说"这个函数复杂度是 15,超过阈值了"。然后呢?具体怎么拆、拆成几个函数、每个函数干什么——还得自己想。
这不就是 LLM 擅长的事吗?
我的想法很简单:
AST 分析结果 + 规则检查结果 + 源代码 → 组装成 Prompt → LLM → 具体建议
关键是怎么组装 Prompt。直接把代码丢给 LLM 让它审查,效果一般。但如果告诉它:
效果就好多了。结构化信息能帮 LLM 更好地理解问题。
这个项目本身就是个学习项目,用本地 LLM 正好一举两得:
Ollama 是目前最方便的本地部署方案:
# 安装
curl -fsSL | sh
# 拉模型
ollama pull deepseek-r1
# 跑起来
ollama serve
Windows 直接下载安装包,更简单。
试了几个,说说感受:
| 模型 | 体验 |
|---|---|
| llama3.2:3b | 快,但有时候答非所问 |
| deepseek-r1 | 推理能力强,中文好,推荐 |
| qwen3 | 通用能力不错 |
| qwen3-coder | 代码场景最好,但要 24G 显存 |
显存有限就用 deepseek-r1,够用了。
这是整个功能的核心。好的 Prompt 能让 LLM 给出有价值的建议,差的 Prompt 只会得到泛泛而谈。
以代码审查为例:
你是一个专业的代码审查专家。请审查以下代码并提供改进建议。
## 代码信息
- 文件: {file_path}
- 语言: {language}
- 总行数: {total_lines}
## AST 分析结果
{ast_summary}
## 规则检查结果
{lint_results}
## 源代码
{code}
请从以下方面进行审查:
1. 代码质量: 可读性、可维护性、命名规范
2. 潜在问题: Bug 风险、边界情况、异常处理
3. 最佳实践: 是否遵循语言惯例和设计模式
4. 改进建议: 具体的优化方案
请给出具体的代码示例。
几个要点:
这个场景比较有意思,专门针对"函数太复杂怎么拆":
你是一个代码优化专家。请分析以下代码的复杂度问题。
## 复杂度较高的函数
- `process_data`: 复杂度 15 (行 10-85)
- `validate_input`: 复杂度 12 (行 90-130)
## 源代码
{code}
请分析:
1. 复杂度来源: 是什么导致了高复杂度
2. 影响评估: 这种复杂度会带来什么问题
3. 重构方案: 具体的简化步骤和代码示例
注意我把"复杂度较高的函数"单独列出来了,这样 LLM 就知道重点关注哪些函数。
把 AST、规则引擎、LLM 串起来:
┌────────────────────────────────────────────────────────┐
│ CodeAnalyzer │
│ │
│ 代码 ──▶ Parser ──▶ ParseResult │
│ │ │ │
│ │ ▼ │
│ │ RuleEngine ──▶ LintResult │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────┐ │
│ │ PromptBuilder │ │
│ │ 组装: 代码 + AST + 规则结果 │ │
│ └─────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ OllamaClient │
│ │ │
│ ▼ │
│ LLM 分析结果 │
└────────────────────────────────────────────────────────┘
核心流程:
不能把整个 AST 丢给 LLM,太长了。提取关键信息:
### 函数 (3 个)
- `process_data(items, config)` [复杂度: 15] (行 10-85)
- `validate_input(data)` [复杂度: 12] (行 90-130)
- `format_output(result)` [复杂度: 3] (行 135-150)
### 类 (1 个)
- `DataProcessor` (行 5-160)
这样 LLM 一眼就能看出哪些函数有问题。
共 4 个问题 (错误: 2, 警告: 2)
- [ERROR] 行 10: 函数 'process_data' 复杂度为 15,超过阈值 10
- [ERROR] 行 90: 函数 'validate_input' 复杂度为 12,超过阈值 10
- [WARNING] 行 10: 函数 'process_data' 参数过多 (7 > 5)
- [WARNING] 行 5: 类 'DataProcessor' 行数过多 (155 > 100)
输入一个嵌套很深的函数:
def process_data(data, config, options=None):
results = []
for item in data:
if item.get('type') == 'A':
if item.get('status') == 'active':
if config.get('mode') == 'strict':
value = item['value'] * 2
else:
value = item['value']
if options and options.get('transform'):
value = options['transform'](value)
results.append(value)
elif item.get('status') == 'pending':
results.append(0)
elif item.get('type') == 'B':
if item.get('priority', 0) > 5:
results.append(item['value'] * 3)
else:
results.append(item['value'])
return results
LLM 的分析:
然后它还给出了重构后的代码示例。这就比单纯报个"复杂度超标"有用多了。
输入一段有问题的代码:
def get_user(user_id):
query = f"SELECT * FROM users WHERE id = {user_id}"
cursor.execute(query)
return cursor.fetchone()
def run_command(cmd):
os.system(cmd)
LLM 的分析:
这种场景 LLM 的价值很大,它能识别出安全问题并给出修复方案。
封装了几个快捷方法,用起来很简单:
from a_brick_code_analyzer import CodeAnalyzer
analyzer = CodeAnalyzer(model="deepseek-r1")
# 代码审查
result = analyzer.review(code)
print(result.content)
# 安全检查
result = analyzer.check_security(code)
# 复杂度分析
result = analyzer.analyze_complexity(code)
# 性能优化
result = analyzer.optimize_performance(code)
# 生成文档
result = analyzer.generate_docs(code)
也可以分析整个文件:
result = analyzer.analyze_file("src/main.py")
有时候 LLM 会编造不存在的问题,或者给出不太靠谱的建议。所以它的输出只能作为参考,不能完全信任。
我的做法是:AST 和规则检查的结果是准确的,LLM 的建议需要人工判断。
3B、7B 的模型能力确实不如 GPT-4 或 Claude。复杂场景可能分析不到位。
但对于常见的代码问题,够用了。而且本地跑不花钱、不泄露代码,这个优势很大。
本地推理比较慢,7B 模型一次分析可能要 10-20 秒。
可以考虑:
这篇讲了怎么把 LLM 接入代码分析器:
核心思路还是那句话:AST 负责"看清楚",LLM 负责"想明白"。
AST 能精确计算复杂度、提取结构信息,这是它的强项。LLM 能理解代码意图、给出改进建议,这是它的强项。两者结合,比单独用哪个都好。
项目地址:GitHub - a-brick-code-analyzer