乐于分享
好东西不私藏

用 Python 做 AI 编程助手的“第二大脑”:把项目文档、代码和日志接起来

用 Python 做 AI 编程助手的“第二大脑”:把项目文档、代码和日志接起来
这两年,AI 编程助手最大的变化,不是更会补全代码了,而是大家开始发现:它不懂你的项目。

它能写一个 FastAPI 接口,能解释一段 SQL,也能帮你重构函数。但一旦问题变成:

“这个报错为什么只在线上出现?”“这个接口改了会影响哪些模块?”“这个需求当初为什么这么设计?”

普通 AI 很容易开始猜。

原因很简单:它没有项目上下文。代码仓库、设计文档、错误日志、Issue 讨论,这些信息散在不同地方。AI 如果看不到,只能凭通用经验回答。

所以,很多团队现在开始做一件事:给 AI 编程助手接一个“第二大脑”。

不一定要很重。用 Python 搭一个轻量 RAG 工作流,就能先跑起来。

一、RAG 在编程场景里到底解决什么

RAG,全称 Retrieval-Augmented Generation,简单说就是:

先从你的资料里找相关内容,再把这些内容交给大模型回答。

放到研发场景里,它要接的不是百科知识,而是项目自己的材料:

数据来源
适合回答的问题
代码仓库
函数在哪、调用链是什么、改动影响面
设计文档
为什么这么设计、边界条件是什么
错误日志
报错原因、历史相似问题
README / ADR
部署方式、架构决策、约定规范

这件事的价值不在于“让 AI 更聪明”,而是让它少胡说。

一个没有上下文的 AI,像刚入职第一天的高级工程师;一个接了项目资料的 AI,至少像看过文档、翻过日志、跑过仓库的同事。

二、最小可用架构

轻量版本不用上复杂平台,Python 就够了。

基本流程是四步:

收集资料 → 切分文本 → 向量索引 → 检索问答

可以这样选型:

模块
简单方案
文档读取
pathlib、markdown、pypdf
代码解析
tree-sitter 或直接按文件切分
向量模型
bge、text-embedding-3-small
向量库
Chroma、FAISS、SQLite + sqlite-vss
问答模型
任意支持 API 的大模型

如果只是团队内部工具,我建议先用 Chroma 或 FAISS。别一上来就搞一套复杂知识库系统,容易把时间花在工程架子上,真正的问答质量反而没人调。

三、先把资料接进来

第一步是扫描项目目录,把有价值的文件读出来。

比如只索引这些类型:

from pathlib import PathROOT = Path("./my_project")EXTS = {".py"".md"".txt"".log"".yaml"".yml"}docs = []for path in ROOT.rglob("*"):if path.suffix in EXTS and".git"notin path.parts:        text = path.read_text(encoding="utf-8", errors="ignore")        docs.append({"path": str(path),"text": text        })

这里有个小经验:不要无脑把整个仓库塞进去。

先排除这些内容:

node_modules/.venv/dist/build/.git/大体积数据文件自动生成文件

否则检索结果会很脏,模型会被无关内容带偏。

四、代码和文档的切分方式不一样

RAG 质量好不好,很大程度取决于 chunk 怎么切。

文档可以按标题切,日志可以按时间段切,代码最好按函数、类、文件结构切。偷懒一点,也可以先按固定长度切,但效果会差一些。

一个最简单的切分函数:

defsplit_text(text, size=1200, overlap=200):    chunks = []    start = 0while start < len(text):        end = start + size        chunks.append(text[start:end])        start = end - overlapreturn chunks

对代码来说,我更建议给 chunk 加上元信息:

{"path""app/services/order.py","type""code","content""...",}

因为你问“订单取消逻辑在哪里”,答案里最好能直接带文件路径。否则它说一堆解释,你还是得自己翻仓库。

五、建立向量索引

以 Chroma 为例,大概是这样:

import chromadbclient = chromadb.PersistentClient(path="./rag_db")collection = client.get_or_create_collection("project_context")for doc in docs:for i, chunk in enumerate(split_text(doc["text"])):        collection.add(            ids=[f"{doc['path']}::{i}"],            documents=[chunk],            metadatas=[{"path": doc["path"]}]        )

真实项目里,你还需要处理“增量更新”。

最简单的办法是记录文件的 hash:

文件没变:跳过文件变了:删除旧 chunk,重新索引文件删了:删除对应索引

这样每次不用全量重建,几十万行代码的仓库也能接受。

六、问答时别只把结果丢给模型

很多人做 RAG 的第一个坑是:检索出几段文本,然后直接问模型。

更稳的做法是加一个明确提示:

你是项目排障助手。只能基于给定上下文回答。如果上下文不足,直接说“不确定”,并说明还需要哪些文件或日志。回答中必须引用相关文件路径。

这样可以减少一本正经地编答案。

检索部分类似这样:

question = "订单支付成功后为什么没有发通知?"results = collection.query(    query_texts=[question],    n_results=5)context = "\n\n".join(results["documents"][0])

然后把 context + question 发给大模型。

我建议回答格式固定成三段:

可能原因依据建议排查步骤

研发场景里,漂亮的长文不重要。重要的是能不能少走弯路。

七、日志是最容易被低估的数据

很多团队只索引代码和文档,不索引日志。其实排障场景里,日志往往最有用。

尤其是这些内容:

错误堆栈请求 ID接口路径异常时间服务名环境信息

可以把日志按一次异常切成一个 chunk,而不是按固定长度切。比如用 traceback、ERROR 行、request_id 做边界。

这样你问:

“这个 ValueError 最近出现过吗?”

系统就能从历史日志里找类似报错,再结合代码给出判断。

这比单纯让 AI 看一段当前报错靠谱得多。

八、这个工具适合先做成内部命令行

别急着做 Web UI。

第一版可以就是一个 CLI:

python rag_index.py ./my_projectpython rag_ask.py "用户注册失败可能是什么原因?"

团队里用起来后,再考虑接到飞书、Slack、企业微信,或者挂到 CI 里。

比如 PR 阶段自动问:

这次改动影响了哪些接口?有没有修改到鉴权、支付、任务调度相关逻辑?相关文档是否需要更新?

这时它就不只是问答工具,而是项目上下文检查器。

九、几个实用建议

第一,先从一个仓库开始,不要一上来做全公司知识库。

第二,chunk 里一定带来源路径。没有来源的答案,很难信。

第三,提示词里要允许“不确定”。AI 在排障时最危险的不是不知道,而是不知道还硬答。

第四,定期清理索引。废弃文档、旧日志、生成代码都会污染结果。

第五,研发资料最好有基本规范。文档乱、日志乱、命名乱,RAG 只是把混乱放大了一遍。