ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

一个人三周交付企业级AI项目:3个Agent+worktree+CI+RAG实战

2026/10/6 20:13:02 拓冰建站 浏览量
一个人三周交付企业级AI项目:3个Agent+worktree+CI+RAG实战 1. 项目缘起与整体思路拆解1.1 一个真实到有点扎心的交付背景去年年底我接了一个企业级内部工具的项目需求方是一家做供应链管理的公司要做一个“合同智能审核 知识问答”的内部系统。合同审核部分需要对接他们已有的审批流知识问答部分要能吃他们过去五年的项目文档、合同模板、法务意见书。项目预算不算高但要求很明确两个月内上线能扛住内部大概两百人的日常使用。正常来说这种项目配一个 4 人团队——一个后端、一个前端、一个算法、一个测试——干两个月是合理的。但我当时手上只有自己一个人外加三个 AI Agent 作为“虚拟队友”。最后实际交付周期是 3 周比原计划压缩了将近三分之二。这篇文章不聊虚的就把这 3 周里我怎么拆任务、怎么让 Agent 干活、怎么保证代码质量、怎么处理并发和 CI 这些事原原本本讲一遍。如果你也在琢磨“一个人怎么用 AI Agent 扛一个企业项目”或者你团队里已经在用 Agent 但总觉得“差点意思”那这篇应该能给你一些可以直接抄的作业。核心关键词我会反复提到AI Agent、worktree、CI、code review、RAG这几个东西串起来就是我这三周的主线。1.2 为什么是“3 个 Agent”而不是“1 个全能 Agent”一开始我也想过搞一个“全能型” Agent什么都能干。但实测下来单个 Agent 在长上下文里会严重退化——它写着写着后端代码突然开始给你补前端样式或者把 RAG 的检索逻辑和业务逻辑搅在一起。这不是模型能力问题是任务边界模糊导致的注意力漂移。所以我把它拆成了三个角色每个角色有明确的职责边界和输出格式Agent A后端与基础设施负责 FastAPI 接口、数据库 schema、CI 配置、部署脚本。它的输出必须是可运行的 Python 代码 配置文件。Agent BRAG 与知识库负责文档解析、切分、向量化、检索链路、重排序。它的输出是独立的 RAG 模块对外只暴露一个retrieve(query)接口。Agent C前端与联调负责管理后台页面、问答界面、审核结果展示。它的输出是 Vue 组件 API 调用层。这三个 Agent 之间不直接通信而是通过我定义的接口契约来协作。比如 Agent B 必须按照{chunks: [...], scores: [...]}的格式返回Agent C 只认这个格式。这样即使 B 内部换了 embedding 模型或者切分策略C 那边完全不用动。提示Agent 拆分的关键不是“按技术栈拆”而是“按输出物的可验证性拆”。每个 Agent 的产出必须能被独立测试否则联调时你会疯掉。1.3 三周时间线是怎么排的我把三周分成了三个阶段每个阶段有明确的“可演示成果”阶段时间目标关键动作第一周Day 1-7跑通最小闭环搭骨架、定接口、RAG 能返回结果、前端能调通第二周Day 8-14补齐企业级能力并发处理、CI 流水线、code review 自动化、权限第三周Day 15-21压测与交付压测、修 bug、文档、部署脚本、交接这个排期的核心逻辑是第一周不求好看只求能跑。很多项目死在“第一周就想把架构做完美”结果三周过去还在改 schema。我的做法是第一周允许硬编码、允许丑、允许临时方案但必须有一个端到端能演示的路径。2. 核心细节解析与实操要点2.1 Git worktree让三个 Agent 互不打架的关键这是整个项目里我觉得最值得单独拿出来讲的一个点。如果你同时让多个 Agent 改同一个仓库最常见的灾难是Agent A 在改main.pyAgent B 也在改main.py然后你 merge 的时候发现冲突多到想砸键盘。Git worktree解决的就是这个问题。它和git branch的区别在于branch 只是指向某个提交的指针你切换 branch 时工作区会变而 worktree 允许你把同一个仓库的不同分支同时检出到不同目录每个目录有独立的工作区互不影响。我当时的做法是这样的# 主仓库在 ~/project/main cd ~/project/main # 为 Agent A 创建 worktree git worktree add ../agent-a -b feat/backend # 为 Agent B 创建 worktree git worktree add ../agent-b -b feat/rag # 为 Agent C 创建 worktree git worktree add ../agent-c -b feat/frontend这样三个 Agent 分别在~/project/agent-a、~/project/agent-b、~/project/agent-c里干活各自提交到自己的分支。我作为“人类协调者”定期把三个分支 merge 回main。实测下来有几个细节特别重要每个 worktree 要有独立的虚拟环境。Python 项目里如果三个 worktree 共用一个 venv依赖冲突会让你怀疑人生。我是在每个 worktree 里单独python -m venv .venv。数据库要隔离。Agent B 跑 RAG 测试时会往数据库写向量数据如果和 Agent A 的开发库共用A 的测试数据会被污染。我用的是不同的 schema 名比如dev_backend、dev_rag。merge 频率要高。不要等一周才 merge 一次我基本是每天下班前把三个分支都 merge 到main跑一遍集成测试。冲突早发现早解决拖久了就是灾难。注意worktree 不是万能的。如果两个 Agent 必须改同一个文件的同一段逻辑worktree 也救不了你。这时候要做的是重新划分接口边界而不是硬 merge。2.2 RAG 链路的设计从“能搜到”到“搜得准”RAG 这块我踩的坑最多值得展开讲。企业知识库和通用问答最大的区别是用户问的问题往往带着内部术语和缩写通用 embedding 模型直接编码效果很差。我的 RAG 链路是这样的文档解析支持 PDF、Word、Markdown、Excel。PDF 用pdfplumberWord 用python-docxExcel 用openpyxl。这里有个坑很多企业文档是扫描件纯文本提取出来是空的。我的处理是检测到空文本就标记为“需 OCR”走单独的队列不阻塞主流程。切分策略不是简单的按字数切。我用的是“标题层级 语义边界”混合切分。先按 Markdown 标题或 Word 的 Heading 样式切大块再在大块内按句子边界切到 300-500 字。这样每个 chunk 自带上下文检索出来不会断章取义。向量化用的是本地部署的 embedding 模型不是调外部 API。原因有两个一是企业数据不能出内网二是本地模型可以针对内部术语做微调。维度是 768存到 PostgreSQL 的 pgvector 扩展里。检索先用向量检索召回 top-20再用一个轻量级的 cross-encoder 做重排序取 top-5 送给大模型。这一步对准确率提升非常明显实测从 62% 提到了 81%。生成大模型只负责“根据检索到的内容回答问题”prompt 里明确写了“如果检索内容里没有答案就说不知道”。这比让模型自由发挥靠谱得多。关于RAG 知识库能不能存图片我的答案是可以但不是直接存。我的做法是把图片单独存对象存储在 chunk 里存图片的 URL 和一段图片描述用多模态模型生成的。检索时如果命中带图片的 chunk前端会把图片一起展示出来。这样既保留了图片信息又不会让向量库变得臃肿。2.3 并发处理AI Agent 怎么扛住两百人同时用“AI Agent 怎么扛并发”是热词里出现频率很高的一个问题。我的理解是Agent 本身不是并发瓶颈瓶颈在它调用的下游服务。这个项目里并发压力主要来自三个地方RAG 检索每次问答都要查向量库两百人同时问就是两百次向量检索。大模型调用如果每次问答都实时调大模型延迟会很高而且成本扛不住。合同审核审核逻辑里有多个规则引擎每个规则都要查数据库。我的处理方案是分层削峰第一层请求队列 限流。所有问答请求先进 Redis 队列用asyncio.Semaphore控制同时处理的数量。我设的是 20 个并发 worker超出的请求排队等待前端显示“正在排队预计等待 X 秒”。第二层缓存。相同或相似的问题直接返回缓存结果。相似度判断用的是向量余弦相似度阈值设 0.95。实测下来内部问答场景里重复问题比例大概 30%缓存能省掉这部分开销。第三层异步化。合同审核这种耗时操作全部改成异步任务用户提交后返回一个 task_id前端轮询结果。这样不会阻塞主线程。第四层降级。如果大模型调用超时或失败直接返回检索到的原文片段并提示“智能回答暂时不可用以下是相关文档片段”。用户体验上比直接报错好得多。实测下来这套方案在 4 核 8G 的机器上能稳定支撑 200 人日常使用P95 延迟在 3 秒以内。3. 实操过程与核心环节实现3.1 第一周从零到能演示的端到端闭环第一周的目标很明确周五下班前能演示一个完整的问答流程。用户输入问题系统返回答案答案来自知识库。Day 1 我做的事情是搭骨架。用 FastAPI 建了三个路由/api/ask、/api/upload、/api/health。数据库用 PostgreSQL pgvector建了两张表documents存文档元信息chunks存切分后的文本和向量。Day 2-3 让 Agent B 集中搞 RAG。我给它定的接口契约是# rag/retriever.py class Retriever: def retrieve(self, query: str, top_k: int 5) - list[dict]: 返回格式 [ {chunk_id: ..., text: ..., score: 0.92, source: ...}, ... ] passAgent B 内部怎么实现我不管但对外必须暴露这个接口。这样 Agent C 写前端时可以直接 mock 这个接口不用等 B 完成。Day 4-5 让 Agent C 写前端。问答界面很简单一个输入框、一个回答区、一个“相关文档”折叠面板。我用的是 Vue 3 Element PlusAgent C 生成组件代码后我人工调了一下样式。Day 6-7 联调。这里出了个经典问题Agent B 返回的score是 numpy 的 float32FastAPI 序列化时报错。解决办法是在返回前统一转成 Python float。这种问题很典型Agent 生成的代码在单元测试里没问题一联调就暴露。实操心得第一周一定要安排至少一天做“端到端联调”不要等到第二周。联调暴露的问题往往不是逻辑问题而是类型、编码、时区这些琐碎但致命的问题。3.2 第二周CI 与 code review 自动化第二周的核心是“让代码质量可控”。三个 Agent 同时产出代码如果没有自动化检查merge 到 main 的代码质量会参差不齐。我搭的 CI 流水线是这样的GitLab CIGitHub CI 同理stages: - lint - test - build lint: stage: lint script: - ruff check . - mypy . --ignore-missing-imports test: stage: test script: - pytest tests/ --covapp --cov-reportterm coverage: /TOTAL.*\s(\d%)/ build: stage: build script: - docker build -t contract-ai:$CI_COMMIT_SHORT_SHA . only: - main关键点在于lint 和 test 必须作为 merge 的前置条件。我在 GitLab 里设置了“Pipeline must succeed”才能 merge。这样 Agent 提交的代码如果 lint 不过根本进不了 main。Code review 自动化这块我的做法是让一个独立的 Agent 做“初审”。它的 prompt 是这样的你是一个严格的代码审查者。请检查以下 diff 1. 是否有明显的逻辑错误 2. 是否有未处理的异常 3. 是否有硬编码的密钥或配置 4. 是否有性能隐患如循环内查数据库 输出格式每条问题一行格式为 [严重程度] 文件:行号 - 问题描述这个 Agent 跑在 CI 里每次 MR 自动评论。我只需要看它的评论决定是否人工介入。实测下来它能抓到大概 70% 的明显问题剩下 30% 需要我人工看。3.3 第三周压测、修 bug 与交付第三周基本就是“填坑周”。压测用的是 Locust模拟 200 个用户并发提问。第一次压测结果很难看P95 延迟 12 秒错误率 8%。排查下来主要三个问题向量检索没有索引。pgvector 默认是精确检索数据量到十万级就明显变慢。加了 IVFFlat 索引后检索时间从 800ms 降到 50ms。数据库连接池太小。默认是 5 个连接200 并发直接打满。调到 50 后正常。大模型调用没有超时。有一次外部服务卡住整个请求线程被占死。加了 10 秒超时和重试机制后解决。修完这三个问题第二次压测 P95 降到 2.8 秒错误率 0.3%。这个水平对于内部工具来说完全够用了。交付时我准备了三样东西一份部署文档含 Docker Compose 文件、一份运维手册含常见问题排查、一份交接录屏30 分钟讲清楚每个模块的职责和扩展点。这三样东西看起来简单但能极大降低后续维护成本。4. 常见问题与排查技巧实录4.1 Agent 协作中的典型翻车现场问题一Agent 之间接口不一致。Agent B 返回的字段叫sourceAgent C 以为是file_name。这种问题在联调时才会暴露。解决办法是在项目根目录放一个contracts/文件夹里面用 JSON Schema 定义所有跨模块接口。每个 Agent 在写代码前必须先读这个 schema。问题二Agent 过度设计。你让它写一个“简单的缓存”它给你搞了个多级缓存 一致性哈希。我的处理是在 prompt 里明确写“不要引入新依赖不要做当前需求之外的抽象”。这句话能省掉大量返工。问题三Agent 忘记上下文。长对话里 Agent 会忘记之前定的约定。我的做法是每个 Agent 的 system prompt 里固定包含“项目约定”部分比如“所有时间字段用 UTC”“所有 API 返回{code: 0, data: ...}”。每次新对话都带上不依赖记忆。4.2 RAG 效果不好的排查清单现象可能原因排查方法检索不到相关文档切分太碎或太大打印 chunk 内容看是否语义完整检索到但不相关embedding 模型不匹配换模型或加领域微调答案胡编prompt 没限制加“仅根据检索内容回答”答案不完整top_k 太小增大 top_k 或加重排序中文效果差模型不支持中文换多语言模型4.3 几个我踩过的坑坑一worktree 里的 .env 文件。每个 worktree 是独立目录.env不会自动同步。我一开始忘了这事Agent A 的数据库配置和 Agent B 的不一样联调时数据对不上。后来写了个脚本每次创建 worktree 自动复制.env.template并提示填写。坑二CI 缓存导致依赖不一致。GitLab CI 的 cache 有时候会缓存旧的requirements.txt导致新加的依赖装不上。解决办法是在 cache key 里加上requirements.txt的 hash。坑三Agent 生成的测试用例太“水”。它写的测试基本都是“调用函数断言不报错”没有真正的边界测试。我的做法是人工补关键路径的测试Agent 写的测试只作为补充。坑四大模型 API 的 rate limit。压测时并发一高外部 API 直接返回 429。解决办法是加本地队列 指数退避重试同时在 prompt 里控制输出长度减少 token 消耗。5. 这套打法适合谁、不适合谁5.1 适合的场景这套“3 个 Agent worktree CI RAG”的打法最适合的是中小型企业内部工具需求相对明确、用户量不大、但对数据安全有要求。比如内部知识库、合同审核、工单分类、文档摘要这类场景。另一个适合的场景是个人开发者接私活。你一个人接了一个本来需要小团队的项目用这套方法可以把交付周期压缩一半以上。前提是你对业务逻辑本身要清楚Agent 只是帮你写代码不是帮你做需求分析。5.2 不适合的场景如果你的项目是面向海量用户的 C 端产品这套打法要谨慎。C 端产品的并发量、稳定性要求、用户体验细节不是几个 Agent 能搞定的。Agent 生成的代码在“正确性”上没问题但在“极致性能”和“边界处理”上往往不够。另外需求极度不明确的项目也不适合。Agent 需要明确的接口契约才能干活如果需求本身还在反复变你大部分时间会花在改契约上不如先人工把需求理清楚。5.3 后续可以怎么扩展这套骨架搭好之后扩展方向其实很多。比如把 code review Agent 升级成“自动修复”——它发现问题后直接提一个 fix commit你只需要 review。再比如把 RAG 的检索链路做成可插拔的方便以后换 embedding 模型或加重排序策略。还有一个我觉得很有价值的方向是把 Agent 的 prompt 和接口契约版本化。每次项目复盘时看看哪些 prompt 写得好、哪些契约设计得合理沉淀成模板。下次接新项目时直接复用这些模板启动速度会快很多。我在实际使用中发现Agent 协作最大的成本不是 Agent 本身而是人类协调者定义接口和验收标准的时间。这部分工作省不掉但可以随着经验积累越来越快。踩过几次坑之后我现在定义接口契约基本半小时能搞定这在以前是不可想象的。