一份写给前端开发者的 Python 小项目实战指南
缘起:为什么我要写这份笔记?
前几天,我搭了一套 AI 代码审查服务,用 Python + Flask 写了大概 200 行代码,实现了:当 GitLab 收到 MR 时,自动调用 AI 分析代码 diff,然后把审查意见贴回 MR 评论区。
团队里几个前端同事看了都很好奇:"我不会 Python,这个能学会吗?" 我就想,干脆写一份零基础也能看懂的学习笔记,把我踩过的坑、理解的过程都记录下来。
一、这个服务到底干了什么事?
你先别管代码,我们先理清楚它想解决什么问题:
- 每次有人提 MR,都要人工 review,很慢,而且有些低级错误(比如忘记处理空值、变量命名不规范)反复出现。
- 我们希望让 AI 先帮忙扫一遍,把明显的错误挑出来,人工只需要看复杂逻辑。
所以这个服务的流程就是:
- GitLab CI 触发一个任务 →
- 调用这个 Python 服务(传过去项目名、MR 编号)→
- Python 服务从 GitLab 拉取这次 MR 的代码变更(diff)→
- 把 diff 发给大模型(比如 GPT-4)→
- 大模型按我们的规范返回审查意见 →
- 服务再把这些意见通过 GitLab API 贴到 MR 评论区。
你可以把它想象成:一个会看代码的 AI 同事,24 小时在线,随叫随到。
二、这个项目用了哪些技术?(尽量让前端看懂)
| 技术 | 作用 | 类比(前端视角) |
|---|---|---|
| Python 3 | 后端语言 | 类似 Node.js |
| Flask | Web 框架 | 类似 Express |
| OpenAI SDK | 调用大模型 | 类似调用第三方 API |
| requests | 发 HTTP 请求 | 类似 axios |
| python-dotenv | 读取 .env 配置 |
类似 dotenv 包 |
| git 命令 | 克隆规范文件仓库 | 就是 git clone |
所以即使你不会 Python,只要你会写 JavaScript,理解这些概念都不难------只是语法不同罢了。
三、手把手运行起来(Mac / Linux)
1. 安装 Python(如果没有)
Mac 用户(一般电脑自带):
bash
brew install python3
验证:
bash
python3 --version # 应该显示 3.9 以上
2. 下载代码
把上面那份 app.py 保存到一个文件夹里,比如 ~/ai-review-service/。
同时创建一个 requirements.txt,内容如下:
flask
openai
python-dotenv
requests
3. 安装依赖
bash
cd ~/ai-review-service
pip3 install -r requirements.txt
如果提示
pip3找不到,试试pip。或者用python3 -m pip install ...
4. 配置环境变量(创建 .env 文件)
在相同目录下新建 .env 文件,内容如下(把尖括号里的换成你自己的):
env
OPENAI_API_KEY=sk-xxxxxxxxxxxxxx
OPENAI_BASE_URL=https://api.openai.com/v1
OPENAI_MODEL=gpt-4o-mini
GITLAB_TOKEN=glpat-xxxxxxxxxxxx
GITLAB_URL=https://gitlab.com
REVIEW_SPEC_PATH=./specs/frontend-code-review.md
AUTO_SYNC_SPEC=true
SKILLS_REPO_URL=https://gitlab.com/your-team/skills.git
各字段含义我后面会详细解释。
5. 启动服务
bash
python3 app.py
看到类似下面的输出就成功了:
bash
🚀 AI Review 服务启动中...
📡 服务地址: http://localhost:5001
🔑 测试令牌: test-token-123
📝 审查接口: POST /api/review
四、配置文件 .env 详解(小白必看)
| 变量 | 含义 | 从哪里获取 |
|---|---|---|
OPENAI_API_KEY |
调用 OpenAI(或兼容接口)的密钥 | 在 OpenAI 官网或阿里云 DashScope 申请 |
OPENAI_BASE_URL |
API 地址 | 默认是 OpenAI 官方,如果国内用通义千问就改成阿里云地址 |
OPENAI_MODEL |
使用的模型名 | 比如 gpt-4o-mini、qwen3.7-max |
GITLAB_TOKEN |
GitLab 个人访问令牌 | GitLab → Settings → Access Tokens,勾选 api 或 read_api 权限 |
GITLAB_URL |
你的 GitLab 服务器地址 | 公司内部的 GitLab 地址,比如 https://gitlab.your-company.com |
REVIEW_SPEC_PATH |
代码审查规范文件存放路径 | 可以默认,会在启动时从 skills 仓库下载 |
AUTO_SYNC_SPEC |
是否自动同步规范 | true 或 false,建议 true |
SKILLS_REPO_URL |
存放审查规范的 Git 仓库地址 | 你自己建一个仓库,里面放 frontend-code-review/SKILL.md |
特别注意:
GITLAB_TOKEN必须有api权限,否则无法在 MR 下发评论。- 如果只是测试,可以先不配置
GITLAB_TOKEN,服务会返回"无法获取 diff"的提示,但不会报错。
五、代码逐段解析(不要求你懂 Python,但知道它在干嘛)
我会把 app.py 拆成几个核心功能,用大白话解释。
1. 导入依赖和读取配置
python
from flask import Flask, request, jsonify
import os
import subprocess
# ... 其他导入
load_dotenv() # 自动读取 .env 文件
Flask就像 Express 的app对象,用来定义路由。load_dotenv()让你能在代码里用os.getenv('OPENAI_API_KEY')拿到配置。
2. 同步审查规范文件
python
def sync_specs_from_git():
# 用 git clone 拉取一个仓库,然后把里面的 SKILL.md 复制到本地
为什么需要这个?
团队代码规范可能会更新。我们把它单独放在一个 Git 仓库里,服务启动时自动拉取最新版。这样不用改代码,只改规范文件,AI 就会按新规则审查。
对前端的类比 :就像你 npm install 一个依赖包,只不过这里 git clone 了一个文档。
3. 从 GitLab 获取 MR 的 diff
python
def get_mr_diff(project_path, mr_iid):
# 调用 GitLab API: GET /projects/:id/merge_requests/:iid/changes
# 返回一个包含代码增删内容的字符串
核心逻辑:
project_path类似group/project。mr_iid是 MR 的编号(比如!123中的 123)。- 用
requests库发 GET 请求,带上PRIVATE-TOKEN头。 - 解析返回的 JSON,提取
changes数组中的diff字段。
如果失败怎么办? 代码里做了详细的错误提示,比如 401 告诉你 token 权限不够,403 告诉你没权限访问项目。
4. 调用 AI 进行审查
python
def get_real_ai_review(mr_info, code_diff):
# 1. 加载团队规范文件内容
# 2. 拼接一个超长的 prompt(提示词)
# 3. 调用 OpenAI API
# 4. 解析返回的 JSON
这是最核心的函数。它做的事情可以理解为:给 AI 下指令。
指令内容大致是:
你是一位审查专家。下面是 MR 的代码变更,请按以下规范检查:...... 输出格式必须是 JSON,每个问题要标明文件、行号、优先级、分类。
AI 返回的 JSON 结构类似:
json
{
"score": 75,
"suggestions": [
{"type": "error", "file": "src/App.vue", "line": 12, "message": "空指针风险,建议加 ?."}
]
}
前端同学注意:这个 prompt 就是你的"需求文档",你想让 AI 怎么审查,完全可以通过修改 prompt 来控制。甚至你可以把 ESLint 规则翻译成自然语言写进去。
5. 定义 HTTP 接口(路由)
python
@app.route('/api/review', methods=['POST'])
def review_code():
# 1. 验证 Authorization 头里的 Bearer token
# 2. 解析请求 body(JSON)
# 3. 调用 get_mr_diff 拉取代码
# 4. 调用 get_real_ai_review
# 5. 返回结果
@app.route类似 Express 的app.post()。- 函数名随便起,但里面逻辑一定要清晰。
- 返回的 JSON 会通过
jsonify自动转成响应。
6. 健康检查与测试接口
python
@app.route('/health')
def health_check():
return {"status": "ok", ...}
作用:让你确认服务是否还活着,以及配置是否正确(比如检查 API Key 是否存在)。
还有一个 /test/gitlab 接口,可以手动测试 GitLab token 是否有效。
六、如何在 GitLab CI 里调用这个服务?
在你的前端项目根目录,修改 .gitlab-ci.yml,添加一个 job:
yaml
ai-review:
stage: review
tags:
- mac-runner # 如果你用本地 runner
script:
- |
curl -X POST http://localhost:5001/api/review \
-H "Authorization: Bearer test-token-123" \
-H "Content-Type: application/json" \
-d "{
\"project\": \"$CI_PROJECT_PATH\",
\"mr_iid\": $CI_MERGE_REQUEST_IID,
\"source_branch\": \"$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME\",
\"target_branch\": \"$CI_MERGE_REQUEST_TARGET_BRANCH_NAME\"
}"
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
$CI_PROJECT_PATH等变量是 GitLab CI 自带的,不用你手动填。test-token-123是服务里硬编码的测试 token,你可以改成更安全的随机字符串。
如果你不想用本地 runner ,也可以把这个服务部署到一台有公网 IP 的服务器上,然后把 http://localhost:5001 换成对应的 IP。
七、踩坑记录(我摔过的地方)
1. Token 权限不足 → 401
- 错误:
获取 MR 变更失败: 401 - 原因:GitLab Token 只给了
read_user,没给api。 - 解决:重新生成 Token,权限勾选
api(或至少read_api+write_repository)。
2. 本地服务跑在 5001,GitLab Runner 却访问不通
- 错误:
curl: (7) Failed to connect to localhost port 5001 - 原因:Runner 如果是 Docker 模式,
localhost指向容器内部,不是你的 Mac。 - 解决:要么用
host.docker.internal(Mac),要么改用 shell executor(我上面用的就是 shell)。
3. Python 依赖安装失败
- 错误:
No module named 'flask' - 原因:你可能用了系统自带的 Python 2.7,或者忘记激活虚拟环境。
- 解决:用
python3 -m pip install,或者先python3 -m venv venv创建虚拟环境。
4. AI 返回的 JSON 解析失败
- 现象:服务日志提示
JSON 解析失败,MR 里出现 raw_response。 - 原因:大模型偶尔会返回带解释文字的 JSON,或者 JSON 不完整。
- 解决:代码里已经做了"尝试提取 ```json 代码块"的逻辑,如果还失败,可以让模型 temperature 更低(比如 0.1)。
八、扩展想法(你可以自己加的功能)
- 支持更多 Git 平台:比如 GitHub、Gitee,原理一样,只是 API 地址和 Token 不同。
- 支持本地模型:用 Ollama 跑一个开源的 CodeLlama,不用花 API 钱。
- 增量审查:只审查变更的部分,而不是全量 diff,提高速度。
- 自动修复:让 AI 不仅发现问题,还生成一个修复 patch,用户点一下就能应用。
九、最后想说的话
之前作为一个前端,我一开始也觉得 Python 很陌生。但实际写下来发现,Flask 比 Express 还简单 :不需要配置中间件,不需要处理路由参数解析,甚至不需要 async/await(默认就是同步,很适合这种小工具)。
而且这种"小 AI 服务"的写法非常固定:
接收请求 → 调第三方 API → 加工数据 → 返回 JSON 。
你只要会写 JavaScript,换成 Python 只是字典和列表的语法区别。
希望这份笔记能让你有信心去改一改上面的代码,甚至自己写一个。如果你在尝试中遇到问题,欢迎在评论区留言(或者提 issue),我会把新的踩坑经历补充进来。
最后再啰嗦一句:代码不重要,解决问题的方法才重要。这个服务虽然只有 200 行,但它让团队的代码规范真正落地了,这才是最有价值的部分。