
🎁个人主页:我滴老baby 🎉欢迎大家点赞👍评论📝收藏⭐文章 🔍系列专栏:AI
文章目录:
- 自主编程智能体实战:让AI帮你写代码、调Bug、跑测试,一条龙的完整解决方案
-
- 一、编程Agent的核心能力
-
- 1.1 能力矩阵
- 二、核心实现
-
- 2.1 项目上下文理解
- 2.2 编程Agent核心
- 2.3 运行效果
- 三、高级能力
-
- 3.1 代码审查Agent
- 3.2 测试生成Agent
- 四、编程Agent能力对比
-
- 能力提升路线图
- 总结
自主编程智能体实战:让AI帮你写代码、调Bug、跑测试,一条龙的完整解决方案
Devin还在排队?自己动手打造一个编程Agent,代码生成、调试、测试全自动。
一、编程Agent的核心能力
1.1 能力矩阵
| 代码生成 | 根据需求生成代码 | LLM + Context |
| 代码理解 | 阅读和理解现有代码 | AST + LLM |
| Bug修复 | 定位和修复Bug | 错误分析 + LLM |
| 测试生成 | 自动编写测试用例 | 覆盖率分析 + LLM |
| 代码审查 | 发现代码质量问题 | 静态分析 + LLM |
| 文档生成 | 自动生成文档 | 代码分析 + LLM |

二、核心实现
2.1 项目上下文理解
# coding_agent/context.py
import os
import ast
from typing import List, Dict
from dataclasses import dataclass
@dataclass
class FileInfo:
path: str
language: str
lines: int
functions: List[str]
classes: List[str]
imports: List[str]
class ProjectContext:
"""项目上下文理解器"""
LANGUAGE_MAP = {
'.py': 'python', '.js': 'javascript', '.ts': 'typescript',
'.java': 'java', '.go': 'go', '.rs': 'rust',
'.cpp': 'cpp', '.c': 'c', '.rb': 'ruby',
}
def __init__(self, project_path: str):
self.project_path = project_path
self.files: Dict[str, FileInfo] = {}
def analyze(self) –> dict:
"""分析项目结构"""
for root, dirs, files in os.walk(self.project_path):
# 跳过隐藏目录和常见忽略目录
dirs[:] = [d for d in dirs
if not d.startswith('.')
and d not in ['node_modules', '__pycache__',
'venv', '.git', 'dist', 'build']]
for fname in files:
fpath = os.path.join(root, fname)
ext = os.path.splitext(fname)[1]
if ext in self.LANGUAGE_MAP:
info = self._analyze_file(fpath)
if info:
self.files[fpath] = info
return self._build_summary()
def _analyze_file(self, fpath: str) –> FileInfo:
"""分析单个文件"""
ext = os.path.splitext(fpath)[1]
language = self.LANGUAGE_MAP.get(ext, 'unknown')
try:
with open(fpath, 'r', encoding='utf-8') as f:
content = f.read()
except:
return None
functions = []
classes = []
imports = []
if language == 'python':
try:
tree = ast.parse(content)
for node in ast.walk(tree):
if isinstance(node, ast.FunctionDef):
functions.append(node.name)
elif isinstance(node, ast.ClassDef):
classes.append(node.name)
elif isinstance(node, (ast.Import, ast.ImportFrom)):
if isinstance(node, ast.Import):
for alias in node.names:
imports.append(alias.name)
else:
imports.append(node.module or '')
except:
pass
return FileInfo(
path=fpath,
language=language,
lines=len(content.splitlines()),
functions=functions,
classes=classes,
imports=imports
)
def _build_summary(self) –> dict:
"""构建项目摘要"""
lang_dist = {}
total_lines = 0
for info in self.files.values():
lang = info.language
lang_dist[lang] = lang_dist.get(lang, 0) + 1
total_lines += info.lines
return {
"total_files": len(self.files),
"total_lines": total_lines,
"languages": lang_dist,
"files": {
path: {
"lines": info.lines,
"functions": info.functions,
"classes": info.classes
}
for path, info in self.files.items()
}
}
def get_relevant_context(self, query: str, max_files: int = 5) –> str:
"""获取与查询相关的文件内容"""
# 简单的关键词匹配(实际可用向量检索)
relevant = []
query_words = set(query.lower().split())
for path, info in self.files.items():
score = 0
# 检查文件名匹配
fname = os.path.basename(path).lower()
score += sum(2 for w in query_words if w in fname)
# 检查函数名匹配
for func in info.functions:
score += sum(1 for w in query_words if w in func.lower())
if score > 0:
relevant.append((score, path))
relevant.sort(reverse=True)
context_parts = []
for _, path in relevant[:max_files]:
rel_path = os.path.relpath(path, self.project_path)
try:
with open(path, 'r', encoding='utf-8') as f:
content = f.read()
context_parts.append(f"// File: {rel_path}\\n{content}")
except:
pass
return "\\n\\n".join(context_parts)
2.2 编程Agent核心
# coding_agent/agent.py
import json
import subprocess
from openai import OpenAI
from coding_agent.context import ProjectContext
class CodingAgent:
"""自主编程Agent"""
SYSTEM_PROMPT = """你是一个高级编程助手。你可以:
1. 阅读和理解代码
2. 生成新代码
3. 修复Bug
4. 编写测试
5. 优化代码
工作流程:
1. 理解用户需求
2. 分析相关代码
3. 制定方案
4. 实现修改
5. 运行测试验证
6. 迭代修复直到通过
输出格式要求:
– 代码修改用 ```language … ```包裹
– 说明修改原因和影响范围"""
def __init__(self, api_key: str, project_path: str):
self.client = OpenAI(api_key=api_key)
self.context = ProjectContext(project_path)
self.conversation = []
self.max_fix_iterations = 3
def analyze_project(self):
"""分析项目"""
print("📊 正在分析项目…")
self.project_summary = self.context.analyze()
print(f" 文件数: {self.project_summary['total_files']}")
print(f" 总行数: {self.project_summary['total_lines']}")
print(f" 语言: {self.project_summary['languages']}")
def run(self, task: str) –> str:
"""执行编程任务"""
self.analyze_project()
# 构建上下文
relevant_code = self.context.get_relevant_context(task)
self.conversation = [
{"role": "system", "content": self.SYSTEM_PROMPT},
{"role": "system", "content": f"项目结构:\\n{json.dumps(
self.project_summary['languages'], indent=2)}"},
{"role": "system", "content": f"相关代码:\\n{relevant_code}"},
{"role": "user", "content": task}
]
# Step 1: 生成代码
print("\\n🔨 生成代码…")
code_result = self._generate_code()
print(code_result[:200] + "…")
# Step 2: 提取并应用代码修改
print("\\n💾 应用修改…")
modified_files = self._apply_changes(code_result)
# Step 3: 运行测试
print("\\n🧪 运行测试…")
test_result = self._run_tests()
# Step 4: 如果测试失败,迭代修复
if not test_result["success"]:
for i in range(self.max_fix_iterations):
print(f"\\n🔧 修复尝试 #{i+1}…")
fix_result = self._fix_errors(test_result["output"])
self._apply_changes(fix_result)
test_result = self._run_tests()
if test_result["success"]:
break
return code_result
def _generate_code(self) –> str:
response = self.client.chat.completions.create(
model="gpt-4o",
messages=self.conversation,
temperature=0.2
)
return response.choices[0].message.content
def _apply_changes(self, llm_output: str) –> list:
"""从LLM输出中提取代码并写入文件"""
import re
# 提取代码块
pattern = r'```(\\w+)?\\s*(?:\\/\\/\\s*File:\\s*(\\S+))?\\n(.*?)```'
matches = re.findall(pattern, llm_output, re.DOTALL)
modified = []
for lang, filepath, code in matches:
if filepath:
full_path = os.path.join(
self.context.project_path, filepath
)
os.makedirs(os.path.dirname(full_path), exist_ok=True)
with open(full_path, 'w', encoding='utf-8') as f:
f.write(code.strip())
modified.append(filepath)
print(f" ✅ 已写入: {filepath}")
return modified
def _run_tests(self) –> dict:
"""运行测试"""
try:
result = subprocess.run(
["python", "-m", "pytest", "-x", "–tb=short"],
capture_output=True, text=True, timeout=60,
cwd=self.context.project_path
)
return {
"success": result.returncode == 0,
"output": result.stdout + result.stderr
}
except subprocess.TimeoutExpired:
return {"success": False, "output": "测试超时"}
except Exception as e:
return {"success": False, "output": str(e)}
def _fix_errors(self, error_output: str) –> str:
"""根据错误信息修复代码"""
self.conversation.append({
"role": "user",
"content": f"""测试失败,以下是错误信息:
请分析错误原因并修复代码。只输出需要修改的文件。
response = self.client.chat.completions.create(
model="gpt-4o",
messages=self.conversation,
temperature=0.1
)
fix_content = response.choices[0].message.content
self.conversation.append({
"role": "assistant", "content": fix_content
})
return fix_content
2.3 运行效果
agent = CodingAgent(
api_key="your-key",
project_path="./my_project"
)
result = agent.run("""
在项目中添加一个用户管理的API模块:
1. GET /users – 获取用户列表(支持分页和搜索)
2. POST /users – 创建用户(含输入验证)
3. GET /users/<id> – 获取单个用户
4. PUT /users/<id> – 更新用户信息
5. DELETE /users/<id> – 删除用户
使用Flask框架,包含完整的错误处理和单元测试。
""")
三、高级能力
3.1 代码审查Agent
# coding_agent/reviewer.py
class CodeReviewAgent:
"""代码审查Agent"""
REVIEW_PROMPT = """请审查以下代码变更:
文件: {file_path}
变更类型: {change_type}
代码:
```{language}
{code}
请从以下维度给出审查意见:
| 代码质量 | ? | … |
| 安全性 | ? | … |
| 性能 | ? | … |
| 可维护性 | ? | … |
| 测试覆盖 | ? | … |
决策: APPROVE / REQUEST_CHANGES / REJECT 原因:
def review(self, file_path: str, code: str,
change_type: str = "addition") -> dict:
prompt = self.REVIEW_PROMPT.format(
file_path=file_path,
change_type=change_type,
language="python",
code=code
)
response = self.client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}],
temperature=0.1
)
return {
"file": file_path,
"review": response.choices[0].message.content
}
3.2 测试生成Agent
# coding_agent/test_generator.py
class TestGeneratorAgent:
"""测试生成Agent"""
GENERATE_PROMPT = """为以下函数生成完整的单元测试:
```python
{code}
要求:
生成测试代码:
def generate_tests(self, source_code: str) -> str:
prompt = self.GENERATE_PROMPT.format(code=source_code)
response = self.client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}],
temperature=0.2
)
return response.choices[0].message.content
四、编程Agent能力对比
| 本文实现 | ✅ | ✅ | ✅ | ❌ | ✅ |
| Cursor | ✅✅ | ✅✅ | ✅ | ❌ | ❌ |
| Devin | ✅✅ | ✅✅ | ✅✅ | ✅ | ❌ |
| SWE-Agent | ✅ | ✅✅ | ✅ | ❌ | ✅ |
| OpenHands | ✅✅ | ✅✅ | ✅✅ | ✅ | ✅ |
能力提升路线图
| V1 | 代码生成 + Bug修复 | LLM + AST |
| V2 | + 测试生成 + 审查 | 覆盖率分析 |
| V3 | + 项目理解 + 重构 | 全项目上下文 |
| V4 | + 多文件协调 + 部署 | Agent工作流 |
| V5 | 自主完成整个项目 | 多Agent协作 |
总结
编程Agent是AI Agent最实用的应用方向之一:
下一期预告:《AI Agent的记忆系统进阶:从向量数据库到知识图谱》

