ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

AI全栈开发工程实践:从Vibe Coding到稳定交付

AI全栈开发工程实践:从Vibe Coding到稳定交付 1. 先搞清楚2025年的AI全栈开发到底在做什么如果把时间拨回三年前全栈开发这个词的含义还相当清晰前端写页面后端写接口中间挂个数据库能一个人把整套系统从头撸到尾就可以自称全栈。但现在打开招聘网站或者技术社区你会发现AI全栈开发已经变成了另一种完全不同的物种——它要求你懂大模型API、会写Agent、能搭RAG、还得处理流式响应、管理Token成本甚至要会设计评估体系。很多人都被这个概念搞得很焦虑觉得自己好像什么都不会了。我个人的判断是AI全栈开发并没有抛弃传统全栈的根基它是在原有基础上长出了一个新层次。传统的前端、后端、数据库、部署这些能力依然值钱但顶层多了一圈模型能力整合的活儿——怎么选模型、怎么接入、怎么让模型在业务里稳定干活、怎么控制成本、怎么做评测。把这个层次想明白你就抓住了AI全栈开发的核心。这篇文章不打算写那种从零搭建一个AI应用的流水账教程而是想聊一聊我在实际项目中沉淀下来的一套打法。从Vibe Coding的快速试错到Harness与SDDSpec-Driven Development规格驱动开发这种偏工程化的协作方式再到模型接入层、Agent编排、测试观测这些具体环节的落地经验。如果你正准备做一个AI原生的全栈项目或者已经在做但总感觉哪里不对这篇文章应该能帮你把思路理顺一些。我一直强调一个观点AI全栈开发者首先是工程师其次才是会用AI的人。会写提示词、会在Cursor里让AI生成代码这只是入门。真正拉开差距的是你能不能把一个靠AI写出来的原型折腾成能抗住真实流量、能排查问题、能持续迭代的工程系统。下面我按自己项目的推进顺序把这条路上最关键的几块讲透。2. 从Vibe Coding到Harness加SDD我为什么转了方向2.1 Vibe Coding的甜蜜期与崩溃点先说一个大家可能都经历过的场景。今年上半年我接到一个内部工具的需求要做一个用自然语言查询销售数据的功能。当时时间紧我直接用Cursor开了个窗口把需求往对话框里一贴AI唰唰唰生成了几百行代码页面有了、接口也有了、连假数据都给你塞好了。那一刻的感觉确实非常爽我管这个阶段叫Vibe Coding的甜蜜期——你不需要关心实现细节只要顺着感觉往下推AI帮你把大部分脏活累活干完。但这个甜蜜期不会持续太久。项目第三周开始加真实业务逻辑的时候问题就来了。AI生成的代码里有不少它自己脑补的字段命名和数据库对不上有的函数它前后引用了两次但逻辑是冲突的更致命的是代码里没有任何测试你根本不知道改了一个文件会不会炸掉另外三个。到第五周那个项目已经变成了一堆互相缠绕的意大利面条我宁可重写也不想继续在上面改了。这就是Vibe Coding的崩溃点它适合原型验证、适合一次性脚本、适合你完全清楚自己在干什么的场景。但只要是会持续迭代、多人协作、要上生产环境的项目纯靠Vibe Coding往下堆迟早会还债。债主上门的时候利息高得吓人。2.2 Harness和SDD到底在解决什么问题后来我开始认真研究社区里那些做AI应用做得比较稳的团队是怎么协作的。发现他们提到最多的两个词一个是Harness一个是SDD。Harness这个词可以理解成给AI套上缰绳。它强调的不是让AI自由发挥而是通过规范、约束、结构化上下文让AI在你划定的轨道里干活。比如规定好项目目录结构、统一命名规范、维护一份团队的编码约定文档、把关键依赖的版本写在约束文件里这些看起来不起眼的东西实际上是保证AI生成代码不跑偏的核心手段。SDDSpec-Driven Development则更进一步它是说在让AI写代码之前先把规格写清楚。规格不是需求文档那种长篇大论而是把某个模块的输入、输出、边界条件、异常处理、接口签名都定义得很具体。我现在的习惯是如果要让AI实现一个函数我先把函数签名、参数说明、返回值约定、几个典型用例写进规格文件再让AI去填充实现。这么做的收益非常明显。第一AI不用猜需求生成结果的准确率大幅提升第二规格本身是可以测试的写完实现之后直接拿用例跑干没干对一目了然第三团队成员之间沟通有了统一语言不再出现我让AI做的和你让AI做的不是一回事这种尴尬。2.3 我自己现在的工作流如果你问我现在的开发节奏是什么样子我可以给你一个具体的参考需求阶段不用AI或者只用AI做头脑风暴辅助。我自己先把业务逻辑彻底想清楚画一张简陋的流程图标注出核心数据流转。设计阶段把流程转成SDD规格包括模块划分、接口定义、数据结构、错误码约定。这一步我会写得比较细因为它是后面所有环节的锚点。编码阶段打开Cursor或Claude Code把规格文件喂进去让AI按规格实现。遇到规格里没定义清楚的地方我不会让AI自己发挥而是停下来补规格。验证阶段把规格里的用例跑一遍再用真实数据做冒烟测试。这里强调一点AI写的代码在你真正跑起来之前都只能算候选代码。这套流程走下来Vibe Coding的爽感确实少了一点但项目的可控性提升了不止一个级别。现在我做AI全栈项目Vibe Coding和SDD不是二选一的关系——原型阶段我照样Vibe一旦确认方向要正式开发马上切到规格驱动的模式。节奏感很重要别一上来就写规格把灵感磨没了也别一路Vibe到底把项目拖进泥潭。3. 模型接入层别再把API密钥散落在业务代码里3.1 为什么业务代码不能直接调模型API很多人做AI应用的第一步就是在业务代码里直接调OpenAI或其他厂商的API然后API密钥写死在配置里。Demo阶段这么干没问题但项目一复杂这种搞法很快就会让你痛不欲生。我见过最崩溃的一个案例一个团队做了个多租户应用每个租户可以配置自己的模型供应商代码里直接new了十几个不同的客户端分别对接不同厂商。后来要统一加一个重试机制他们得在十几个文件里各改一遍要统计每个租户的Token消耗根本没法统计因为调用散落得到处都是。最后实在忍不了花了两周时间重构把模型调用全部收敛到了一个统一网关后面。这就引出我的一个核心建议在业务代码和模型厂商之间一定要隔一层。这一层可以是自己写的封装库也可以直接用现成的代理网关方案。目前我接触到的主流做法里LiteLLM Proxy算是比较省事的选择它能统一OpenAI、Anthropic、Gemini、各种国产模型厂商的调用协议对外暴露一个OpenAI兼容的接口业务代码只需要学会一种调用方式就够了。3.2 一个能用的LiteLLM Proxy配置长什么样LiteLLM Proxy的部署方式比较灵活可以用Docker跑也可以嵌到现有服务里。我这边用一个简单的Docker Compose配置来说明version: 3.8 services: litellm: image: ghcr.io/berriai/litellm:main-latest ports: - 4000:4000 volumes: - ./config.yaml:/app/config.yaml environment: - LITELLM_MASTER_KEYsk-your-master-key - OPENAI_API_KEY${OPENAI_API_KEY} - ANTHROPIC_API_KEY${ANTHROPIC_API_KEY} - DEEPSEEK_API_KEY${DEEPSEEK_API_KEY}对应的config.yaml可以按模型供应商做路由配置model_list: - model_name: gpt-4o-mini litellm_params: model: openai/gpt-4o-mini api_key: os.environ/OPENAI_API_KEY - model_name: claude-3-5-sonnet litellm_params: model: anthropic/claude-3-5-sonnet api_key: os.environ/ANTHROPIC_API_KEY - model_name: deepseek-chat litellm_params: model: deepseek/deepseek-chat api_key: os.environ/DEEPSEEK_API_KEY litellm_settings: drop_params: true set_verbose: false general_settings: master_key: sk-your-master-key这样配置完之后业务代码里就不用再关心底层到底是哪家模型了。你只需要在配置里改一下model_name指向的目标比如把gpt-4o-mini切到deepseek-chat业务代码一行都不用动成本可能就降下来了。这个灵活性在项目后期的价值非常大尤其是当你发现某个模型在特定任务上效果不好或者某家厂商涨价了换模型的成本从改全站代码变成了改一行配置。3.3 路由、限流和降级的实战注记接入层从能用到好用中间还隔着几个很实际的细节。第一个是路由策略。你可以按任务类型路由比如情感分析类任务走便宜的小模型复杂推理类任务走贵的大模型也可以按租户路由付费高的租户用更好的模型还可以按模型健康度路由某个模型接口报错率高了自动切到备胎。这些策略在LiteLLM里都能配但你要想清楚自己的业务适合哪一种不要为了用功能而用功能。第二个是限流。模型厂商都有调用频率限制如果不做客户端限流流量一上来你就等着被429轰炸。我一般会在接入层做两层限流一层是针对单一API Key的QPS控制另一层是针对单个用户或者单个租户的配额控制。这样既能保护上游模型服务也能防止某个用户把预算烧光。第三个是降级。模型接口一定会出问题不是今天就是明天。我的习惯是给关键链路配置降级方案主模型挂了切备胎模型备胎模型也挂了就返回缓存结果或者一个友好的兜底文案。这个降级逻辑一定提前写好不要等线上事故发生了再临时加。我在生产环境里见过太多次模型超时导致整个页面白屏的案例根因都是没有降级设计。4. Agent编排别让工具调用变成失控现场4.1 Agent循环的核心构成如果说模型接入层是AI应用的骨架那Agent编排就是中枢神经。今年做的好几个项目里最让我花时间的都不是模型效果本身而是Agent怎么稳定地把活儿干完。很多人对Agent的理解是给模型一个目标它自己会想方设法完成这个描述没错但到了工程实现层面就没这么浪漫了。一个标准的Agent循环通常包含四步感知接收用户输入或环境状态、思考让LLM决定下一步做什么、行动调用工具或执行代码、观察读取工具返回结果决定是否继续循环。这个循环说起来简单但工程化之后你会发现真正决定Agent好坏的不是模型聪明不聪明而是你对这个循环的每个环节做了多少约束。我常用的做法是把Agent循环的思考部分和行动部分拆成两层。思考层用大模型负责理解意图、拆解计划行动层走工具调用框架每个工具都有严格的输入输出schema校验。这样即使模型产生了幻觉在行动层也会被拦住不会把一个不存在的工具昌出来执行。4.2 Tool的设计哲学给AI的工具要像给新同事的交接文档Agent的能力边界约等于它工具集的边界。所以工具设计是整个Agent项目里性价比最高的工作。我总结了几个原则都是踩坑踩出来的。第一工具职责要单一。一个工具只做一件事不要搞什么万能工具。工具太泛模型反而不知道怎么用工具拆得细模型的选择正确率会明显提升。比如别设计一个操作数据库工具要拆成查询用户信息更新订单状态统计销售数据这种细粒度的工具。第二工具的输入描述要写得极其清楚。模型是通过描述来理解工具的描述里要写清楚参数的格式、单位、边界条件。比如一个查询天气的工具参数描述不要只写城市名要写城市中文全称如北京市不接受拼音或缩写。很多Agent跑偏的案例根因都是工具描述写得模棱两可。第三工具的返回值要带结构化信息。不要只返回一段文本让模型自己解析要返回结构化的JSON并且明确标注执行成功还是失败。失败时最好给出失败原因码让模型能据此决定是换一种方式重试还是直接向用户说明情况。第四一定要有安全护栏。Agent能调用的工具里凡是涉及写操作或者敏感数据读取的都要加权限校验和确认机制。你不能让Agent在用户一句话的引导下就把数据库表删了。这个底线必须守住。4.3 上下文窗口的管理 Agent失忆的真正原因另一个让人头大的问题是上下文管理。大模型的上下文窗口再大也是有限的Agent一旦跑上十几轮早期的重要信息很容易被挤掉表现就是Agent开始失忆——用户明明告诉过它的偏好它后面完全忘了。我把上下文管理总结成一个分层记忆的模式。第一层是短期上下文就是当前这一轮对话里模型能看到的内容通常把最近的几轮消息和当前Agent状态放进去第二层是工作记忆也就是Agent在这次任务执行过程中产生的关键中间结果用结构化摘要的方式保存下来第三层是长期记忆存用户的偏好、历史交互的提炼信息存到向量数据库或者KV存储里在需要的时候检索出来注入上下文。这个分层模式的好处是你不用把所有信息都塞进上下文窗口让模型自己找重点。而是你自己决定哪些信息必须出现在上下文里哪些信息按需检索。这么做不仅省Token更重要的是提升了Agent的稳定性——它不会被成千上万的无关历史信息干扰判断。另外说一个细节每轮Agent循环结束时让它输出一个当前状态摘要几十个字就行下一轮开头把这个摘要放回上下文。这个小技巧能极大缓解长任务的失忆问题强烈推荐你用起来。5. 应用层与前端AI只是后端的新成员5.1 业务逻辑和数据结构依然得靠人想清楚我见过不少被AI冲昏头脑的团队觉得有了大模型啥都能干业务逻辑也不用设计了直接让模型理解需求自己输出结果。结果就是模型输出飘忽不定同一个问题今天一个答案明天一个答案根本没法做产品承诺。我的看法是AI全栈开发里业务逻辑不等于模型输出。模型应该只在理解自然语言、生成文本、做语义匹配这些它有优势的环节出现其他环节——数据校验、状态流转、权限控制、金额计算——依然要用确定性代码来写。比如一个审批流系统流程的状态机必须用代码写清楚不能指望模型来判断当前状态能不能流转到下一个状态。你在做AI全栈项目的时候动工之前先用最原始的方法把核心业务逻辑梳理清楚分清楚哪些环节是模型负责的哪些是代码负责的。这个划分越清晰后面的开发越顺。5.2 前端的AI交互范式不是把文本框换成聊天框就完事了前端在AI应用里的角色也变了。以前的前端是展示数据和收集指令现在的AI前端要处理流式输出、处理中间状态、处理模型在思考这个动作。不要以为AI前端就是加一个聊天窗口。很多场景下需要的是局部AI化——一个文档编辑器里嵌入一个AI助手让它帮你改写选中的段落一个看板应用里加一个用自然语言筛选数据的输入框一个表单里加一个AI验真的提示。直接推倒整个页面重做成对话式交互往往不是最优解因为用户在有明确目标时传统表单的效率是高于自然语言的。前端接入AI时流式响应是绕不开的痛点。SSEServer-Sent Events是目前我比较推荐的方式后端把模型生成的Token流不断推给前端前端用ReadableStream逐段解析渲染。这里有一个经验不要把每个Token都直接往DOM上append那会导致页面频繁重排性能差到没法用。更好的做法是维护一个缓冲区定期比如每50毫秒把累积的文本一次性渲染到页面上顺滑度会好很多。5.3 错误处理和重试机制AI应用前端的隐蔽工程AI应用的前端错误处理比传统应用复杂得多。传统接口要么成功要么失败AI接口则多了一堆中间态连接中断、流式响应截断、模型返回了不合法格式、内容被安全策略拦截、限流超时。每一种情况都必须设计对应的用户提示和恢复策略。我现在的习惯是前端封装一层统一的AI调用客户端把SSE连接管理、超时重连、部分结果缓存、错误分类这些逻辑都收敛在一个模块里。页面组件只关心三个状态流式输出中、输出完成、输出失败。这样业务页面代码干净AI相关的复杂性被隔离在一个能被重点测试的模块里。这里要特别说一个容易踩的坑流式响应中途连接断了用户已经看到了一部分输出后端其实已经消耗了Token。如果你不做结果缓存用户刷新页面就得重新生成一次、再花一遍Token体验和成本都很糟。所以我建议后端对每次生成的完整结果做落地缓存即使前端断线了重新连接后可以直接从缓存里拿到完整结果而不是重新调用模型。6. 测试、观测与成本上生产之前必须过的三道坎6.1 评测不是感觉还行是给模型建一套考试卷AI应用的测试和传统软件测试有一个本质区别传统软件的行为是确定性的同一个输入必然得到同一个输出AI应用的输出有随机性同一个问题每次答案都可能不一样。这就导致这次跑通了不代表下次也能跑通于是评测体系变得极其重要。我做的第一件事永远是建立测试集。测试集不是随随便便找几条数据而是按业务场景组织的一个考试卷日常问题、边界问题、刁钻问题、错误输入每个类别下至少准备二十条以上。然后定期把这个考试卷喂给模型看它得多少分。版本升级之后分数有没有下降功能修改之后有没有影响其他场景的通过率——这些都是靠测试集来回答的。有过一次惨痛教训某个版本对话框配置动了一处温度参数让模型在常规问题上表现更好了但几乎不处理涉及多条件约束的用户问题我的测试集里这个类别的通过率从百分之七十多跌到了百分之三十以下是靠跑测试集发现的。如果没有这层保障这种退化了的需求逻辑可能就悄悄上线了。在评测里还要区分两种能力一种是模型本身的效果另一种是你整套系统的效果。有时候模型输出是对的但是你的检索器没找到正确的上下文导致最终答案不对。这时候要能快速定位是哪一环出了问题所以我建议在做评测的同时记录每一条请求的完整链路数据这在下一节会详细说。6.2 追踪每一次模型调用没有踪可追出了事只能抓瞎传统应用出了问题你可以查日志、查数据库、复现用户操作。AI应用出了问题你往往要面对一个对话黑盒——用户的输入是什么中间检索了什么模型完整的Prompt是什么模型返回的内容是什么这些信息缺一环排查就无从下手。所以从项目第一天起就要做全链路追踪。每条请求进来给一个traceId把这个请求涉及的所有环节——包括模型调用、工具调用、检索过程、Token消耗——都记录下来关联到同一个traceId上。现在市面上有不少可观测性工具可以做这件事比如Langfuse或者一些商业APM产品都支持LLM追踪。不要觉得这是上线前才需要做的事。我在开发阶段就启动追踪好处是开发过程中每跑一个用例都能直观看到系统给模型喂了什么样的上下文很多质量问题不用等到上线就被你发现并修正了。另外全链路数据还是评估成本的重要依据——哪个环节消耗了最多的Token一目了然。6.3 Token预算怎么算从拍脑袋到精打细算成本控制这块很多团队的处理方式都很粗暴反正模型调用便宜用呗。等月底看到账单才傻眼。AI应用的Token成本是可以精确计算和控制的关键在于你在每个环节做了多少浪费。我给你一个简单的成本优化清单第一Prompt压缩。系统提示词、历史消息、检索回来的上下文文档这些都是Token消耗大户。系统提示词尽量精简检索回来的文档要做重排序只取最相关的部分不要一股脑全塞进去。第二缓存。完全相同的请求直接命中缓存不要重复调模型。第三模型分级。简单任务用便宜小模型复杂任务才用贵的大模型这个前面讲接入层时说过。第四结果缓存。同一类问题即使输入不完全一致计算语义相似度后命中缓存也是一种可行方案。再分享一个算账的例子。我曾经做一个客服问答助手上线前估算每个会话平均消耗是1万Token按当时的模型价格算单个会话成本大概是几毛钱。但上线后实际跑下来每个会话消耗到了4万Token一查发现主要是两个问题历史消息没有做摘要每轮对话都把原始历史全部塞进去检索到的知识库文档每次都原封不动贴五篇实际上只有两篇是相关的。做了两个优化之后单会话Token消耗降到了1.5万左右成本降了一半还多。这种数据不追踪永远不知道追踪了全都是机会。7. 实用经验清单这些坑我替你踩过了最后分享几个具体的、可以立刻用起来的经验全部来自真实的项目经历。第一AI生成的代码也要做代码评审。我在前面说过要相信但验证具体到代码上就是AI生成的PR必须走和人类写的PR一样的评审流程至少要有另一个人过目。AI写的代码里有一种很典型的问题——看着正确但实际上有隐藏假设比如假设某个数组一定非空、假设某个值一定在字典里。评审单靠看很难发现但有一个简单的办法所有AI生成的代码第一版都不要直接进主干先在分支上把测试跑一遍再合。第二用规格文档约束AI不要用对话约束AI。你可以跟Cursor聊十轮让AI微调代码但下一次重新打开项目它可能完全忘了之前的约定。所以我前面提到的SDD不只是流程更是一种持久化上下文的手段——把约定写进仓库里的markdown文件让AI每次启动时自动读取。我现在每个项目根目录都会放一个AGENTS.md或者docs/spec.md里面写清楚项目结构、编码规范、常用命令、数据模型约定。这个文件是给AI看的也是给未来接手的人看的一举两得。第三模型选择不要跟风按任务实测。市面上每月都有新模型不要听别人说好用就直接切。我的习惯是每次接到新任务或者新模型发布时跑同一套测试集对比通过率和成本决策依据就是数据。有的模型聊天体验很好但代码能力一般有的模型推理很强但价格贵三倍适合你的业务场景的才是最好的。第四流式输出时要处理模型中途反悔的情况。我们在Agent工具调用场景里经常遇到一个问题模型先输出了一句话接着又决定调用工具前端已经把那句话渲染出来了就会显得很突兀。我的处理方式是前端对模型输出做分片管理已经渲染的文本标记为已确认新的工具调用事件到来时清空未确认区域、保留已确认区域。这个体验细节一开始很容易被忽略但用户感知非常明显。第五一定要维护一份AI工程的坑清单。我现在有一个文档专门记录这个项目里所有踩过的坑和对应的规避方案比如温度参数超过0.7时JSON输出容易不合法检索结果的顺序对答案质量影响极大不要在同一进程里并发调用多个模型供应商的流式接口会导致内存暴涨。这种经验性的东西靠大脑记不靠谱写下来才是你自己的知识库。每次新人和我协作我把这份坑清单发给他团队的试错成本一下就降下来了。回到最开始那句话AI全栈开发不是会写提示词就行也不是传统全栈那套东西被淘汰了。它更像是传统工程能力上面叠加了一层新能力——理解模型的边界、设计好模型与代码的协作方式、用工程手段控制不确定性和成本。把这几件事想明白、做扎实你会发现AI应用开发并没有那么玄学它只是一套需要重新适应的方法论。希望这篇文章里的经验和思路能帮你少走一段弯路把更多精力花在真正有价值的事情上。
返回列表