恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
AI实战复盘:从想法到Web应用的工程化指南
首页
资讯中心
/
AI实战复盘:从想法到Web应用的工程化指南
AI实战复盘:从想法到Web应用的工程化指南
发布时间:2026/9/4 23:39:12
最近半年我一直在用AI搭Web应用从最早拿它当“高级补全插件”到后来把它放进整个项目链路里当真正的协作者踩过不少坑也沉淀出一套还算稳定的做法。这套做法不能说多高级但至少能让一个两三个人的小团队或者单兵作战的开发者在三四天里从一个模糊想法推进到能上线试用的Web应用。这篇文章就当是阶段性的项目复盘把我在实际开发里围绕“AI Web应用”这个组合的具体操作、选型思考、代码细节和踩坑记录都摊开来聊一聊。我默认读这篇文章的人至少写过一点前端页面或者懂一点后端接口的基础知识。但即便你只是听说过大模型API、没正经集成过也不影响阅读——因为这里面的重点不在于你用了哪款模型而在于你如何用工程手段把“不稳定的AI能力”组织成一个稳定可用的Web产品。1. 思路先行先想清楚让AI干什么再动手写提示词1.1 一个常见误区把AI当成自动写代码机器很多人都问过我同一个问题让AI帮我直接生成一个完整的Web应用靠谱吗说实话如果你只是丢一句“帮我做一个企业管理后台”绝大多数AI Coding工具确实能在几分钟内吐出一个能跑的前端页面甚至附带上一个像模像样的后端。但一旦你开始往里面加真实业务规则——不同角色看不同数据、某些操作要审批、文件上传要限制大小和格式、敏感操作要留审计日志——那它生成的东西往往就开始失控了字段对不上、接口路径不统一、权限校验形同虚设。这里面的根源在于AI擅长的东西是“常见模式的复现”而高品质Web应用的核心恰恰在于“异常情况的设计”。用户登录、列表分页、表单提交这类模式AI见过太多它能给你写得很漂亮但“订单金额超过阈值时自动跳转到人工审核队列”这种逻辑它需要你先把业务规则讲清楚否则它只能猜测而猜测的结果一定不稳定。所以我对AI在Web应用开发中的定位从来不是“写代码的机器”而是“快速把模糊需求变成可讨论的骨架的人”。它负责把70分的东西直接给你你负责把它打磨到95分。1.2 明确范围AI能覆盖哪些环节哪些必须人来把关我按实际经验把整个Web应用开发拆成下面几个环节并给每个环节评估了AI介入的程度开发环节AI介入程度人工把关重点需求梳理与原型描述很高确认业务规则描述是否完整前端页面生成很高UI细节、交互状态、异常反馈后端接口与数据模型中高外键关系、索引设计、事务边界权限与安全控制低必须逐行审查不能全信模型能力集成智能对话等中流式协议、超时处理、成本控制测试与部署运维中边界case、回归验证、监控告警从这个表你可以看到一个规律越是偏“创造”和“表达”的环节AI越能释放生产力越是偏“约束”和“安全”的环节越需要人来兜底。理解了这一点后面很多工具选型和写法上的取舍就顺理成章了。1.3 我的推荐组合Prompt驱动 AI编程工具 人工Code Review在实际项目中我的工作流是三层结构第一层是“对话式设计”用一个通用的大模型聊天工具把业务需求聊细把模糊的想法转化成功能列表、数据字段和页面清单。这个阶段不需要写代码重点是把需求讲清楚。第二层是“结对编程”用支持AI编程的IDE插件例如带Agent能力的Coding工具在当前工程上下文里让它帮我补全代码、生成接口、修bug。这一层做的是把设计变成代码。第三层是人肉Code Review也是永远不能省的一层。我会把AI生成的关键代码段逐行看一遍尤其是涉及数据写入、文件处理、用户鉴权的部分。这个流程听起来可能不够“炫酷”但它是让我从不翻车的基础保障。记住AI写代码的水平可以帮你省下大量时间但它不会为你的线上事故负责负责的人只有你。2. 从零到骨架让AI帮你把想法变成能跑的项目2.1 从一句模糊需求到一份合格的需求说明我先拿我最近做的一个小项目做例子项目很简单一个团队周报助手Web应用成员可以提交本周工作记录系统用大模型自动润色成周报格式管理者可以查看团队汇总。很多人这时候就会让AI直接写代码。但我建议多花十五分钟先让AI帮你生成一份“功能实现说明”。我会在IDE的对话框里输入这样一段信息请作为资深全栈工程师帮我规划一个团队周报助手Web应用。要求如下成员端可以填写周报字段包括本周工作内容、遇到的问题、下周计划AI自动生成润色后的周报版本人可以对比后选择保存管理者可以查看所有成员周报及汇总需要登录普通成员和管理者权限分离。 请输出功能模块清单、数据表结构草案、接口清单、页面清单、技术栈选型建议。这个做法的价值在于它会先逼着AI“想清楚”再“写代码”避免它边猜边写。AI输出的数据表草案和接口清单就是你后续所有代码生成的一致性约束相当于给了AI一份“施工蓝图”。2.2 搭建工程骨架前端、后端、数据库一次到位拿到蓝图之后我会把技术栈定下来。团队周报助手这类中后台工具我的习惯是前端用Vue3 组件库Element Plus后端用Python写FastAPI数据库先用SQLite起步等确定需要更强的并发能力再切换成PostgreSQL。这样做的好处是本地调试零成本适合快速迭代。我让AI生成项目骨架的提示词大概是这样的基于以下接口文档和数据表定义生成一个FastAPI项目骨架目录结构如下 app/main.py、app/models/、app/schemas/、app/api/、app/core/。 数据库使用SQLAlchemy 2.0 SQLite先实现用户注册、登录、当前用户信息三个接口。 密码不能明文存储要使用安全哈希算法。这一步生成出来的代码通常已经具备相当的完整度因为需求很明确、边界很窄。你可能需要手动做的只是补上CORS跨域配置、统一响应结构、接口前缀这类工程性内容。2.3 让AI自动切页面的有效姿势页面生成的效率很大程度上取决于你喂给AI的上下文是否充分。如果你只说“生成一个周报填写页面”它给你的就是一个很普通的表单页。如果你能说明“第一个字段是日期范围选择器、第二个字段是文本域、底部有一个AI润色按钮点击后调用后端接口返回内容回填到预览卡片中”那么它生成的页面基本就能直接用了。我实际使用中比较顺手的做法是把要生成的页面拆成“布局描述 数据字典 按钮行为”三段描述像这样请生成周报填写页。页面布局为顶部为标题栏左侧主区域为表单卡片右侧为AI润色结果卡片。提交数据格式为{work_done: string, problems: string, next_plan: string}。表单底部两个按钮“普通提交”和“AI润色后提交”。点击AI润色按钮时先把当前表单内容发送到 /api/v1/report/polish等待返回结果显示在右侧卡片上用户点击卡片内容即可一键填入编辑器。如果你还愿意把组件库的具体版本、表格的列定义、对话框的交互状态写清楚那生成结果基本达到“微调后可用”的水准。3. 让AI别在业务逻辑上“自由发挥”3.1 用约束性框架替代开放式提问AI生成代码时最让人头疼的地方不是它不会写而是它会用“自认为合理”的方式替你决定业务规则。比如你在需求里只说了“用户可以删除周报”它可能默认任何登录用户都能删任何周报而实际上你的规则是“只能删除自己的且超过周五晚12点就不能删”。要想让AI在这些关键节点上少犯错最好的方式不是“说得更详细”而是“给它边界和框架”。比如说在生成删除接口前我一般会先提供这样的伪代码删除周报接口逻辑从token中解析当前用户id查询周报记录若不存在返回404校验该记录的owner_id是否等于当前用户id若不是返回403校验当前时间是否晚于本周周五23:59若是返回400提示“超过可删除时间”执行删除并记录审计日志。就这么一段看似啰嗦的描述会让AI生成的代码在业务正确性上提升一个档次。真实项目里的业务Bug绝大多数都不是因为代码语法写错了而是因为这种“隐含规则”没有被表达出来。3.2 数据模型设计的两个人工检查点数据模型是Web应用的底座这里如果歪了后面所有代码都要跟着将就。AI生成的建表代码通常语法正确、字段齐全但有两个检查点我会人工重点看。第一个是外键关系。AI有时会生成冗余的外键比如周报表里既有一个user_id指向用户表又有一个reviewer_id指向用户表还有一层嵌套关联。这个本意是好的但它未必会在索引层面帮你处理好外键字段没有索引会在数据量上来后变成查询瓶颈。第二个是逻辑删除与唯一约束。很多业务里删除并不是真的从数据库里抹掉而是打一个deleted标记。如果AI不知道这个约定它生成的删除接口就是硬DELETE而你的历史报表统计全部会出错。所以我在数据模型生成的提示词里一定会带上“所有业务表均使用is_deleted字段做软删除所有记录唯一性用联合唯一索引保证”这类工程约定。3.3 权限控制最快暴露AI短板的地方如果你想让AI生成一个带登录态和权限控制的全栈应用你会发现它在“普通成员只能看到自己的数据”和“管理员能看到所有人的汇总”这条边界上经常写得模棱两可。最常见的问题是它把权限校验写在了前端按钮的v-if上而后端接口没有做任何二次鉴权。这意味着任何人只要直接调接口就能绕过界面看到不该看的数据。我从第一次遇到这个问题之后就立了一个规矩任何AI生成的后端接口只要涉及查询数据列表我都会追问一句“这个接口如何校验数据归属权如果用户A传入了用户B的ID会发生什么”然后把这道问题的答案作为硬性检查项写进测试列表里。另一个有效方法是把权限模型固定下来。与其让AI自由发挥不如直接告诉它本项目使用RBAC权限模型。用户表新增role字段取值为member或admin。member只能访问自己的数据admin可以访问全部数据。请在所有接口的依赖项中加入当前用户解析函数并在访问数据时用查询参数对用户ID进行约束。这样“按用户过滤”的逻辑就会变成AI生成代码的默认规则而不是碰运气。4. 把大模型能力嵌入Web应用一个完整流式交互的实现4.1 需求拆解不只是接一个API那么简单如果你做的Web应用只是一个传统CRUD系统那前面三章已经足够覆盖大部分工作。但你既然用了“用AI打造”这个说法大概率希望产品本身带一点智能能力比如周报自动润色、智能问答、文档摘要等。这时候就涉及一个核心点怎么把大模型能力稳定地嵌入到Web应用里。很多初学者的做法是在前端直接把用户输入发给大模型API、拿到结果展示出来。这种做法演示可以但真正做产品不行——你的密钥会暴露在前端代码里而且没法做成本控制、内容过滤和审计。我的做法是在后端封装一层统一的大模型调用服务前端永远只跟自己的后端对话由后端负责调用外部模型API。这样做的好处有三个第一密钥不会暴露第二可以统一记录每次请求的耗时、token消耗和内容第三你在替换不同模型时只需要改后端一个文件前端完全无感知。4.2 后端实现大模型调用的基础模板以周报润色这个功能为例后端代码大致长这样。我用的是FastAPI框架集成了对大模型服务的调用能力。为了适配不同模型供应商我会在配置里统一使用OpenAI兼容的接口规范这样以后换模型时只需要改base_url和api_key。from fastapi import APIRouter, Depends, HTTPException from pydantic import BaseModel import httpx router APIRouter() class PolishRequest(BaseModel): content: str tone: str 专业简洁 class PolishResponse(BaseModel): polished: str # 不同供应商的配置放在环境变量中不写入代码 MODEL_BASE_URL https://your-model-endpoint/v1 MODEL_NAME your-chat-model API_KEY your-api-key router.post(/report/polish, response_modelPolishResponse) async def polish_report(req: PolishRequest): if len(req.content) 5000: raise HTTPException(status_code400, detail内容过长请控制在5000字以内) prompt f你是一名专业的研发团队周报助理。 请把以下工作内容润色为周报格式保持要点清晰、语言精炼、不要编造原文不存在的内容。 原内容 {req.content} 润色要求{req.tone} async with httpx.AsyncClient(timeout30) as client: resp await client.post( f{MODEL_BASE_URL}/chat/completions, headers{Authorization: fBearer {API_KEY}}, json{ model: MODEL_NAME, messages: [{role: user, content: prompt}], temperature: 0.3, }, ) if resp.status_code ! 200: raise HTTPException(status_code502, detail大模型服务暂时不可用) data resp.json() polished data[choices][0][message][content] # 这里可以加一层简单的输出规范检查 polished polished.strip() if not polished: raise HTTPException(status_code502, detail模型返回为空请重试) return PolishResponse(polishedpolished)这段代码里有几个容易被忽视的细节。第一个是超时设置大模型接口的响应时间波动很大短则一两秒长则几十秒。你不可能让用户在前端干等所以一定要配合流式传输或者超时提示来做交互优化我初版是直接同步等待结果用户经常以为页面卡死了。第二个是temperature参数。润色类任务我一般设到0.2-0.4之间温度太高AI会自由发挥把“修复了一个登录Bug”润色成“攻克了系统级身份认证疑难问题”信息失真非常严重。如果你做的是创意写作类任务才需要把温度调高。4.3 前端如何接收AI返回并做流式体验如果你的功能只需要“点击后等待几秒看到结果”那同步请求就够了。但真正高品质的体验应该是打字机式的流式输出用户能看到内容逐字出现心理等待时间大幅降低。前端要接流式输出最关键的是后端返回格式改成SSEServer-Sent Events服务器推送事件。我在实际项目里直接用FastAPI的StreamingResponse改造上面那个润色接口from fastapi.responses import StreamingResponse router.post(/report/polish-stream) async def polish_report_stream(req: PolishRequest): # 参数校验略... async def event_generator(): async with httpx.AsyncClient(timeout60) as client: async with client.stream( POST, f{MODEL_BASE_URL}/chat/completions, headers{Authorization: fBearer {API_KEY}}, json{ model: MODEL_NAME, messages: [{role: user, content: prompt}], stream: True, temperature: 0.3, }, ) as resp: async for line in resp.aiter_lines(): if line.startswith(data: ): data_str line[6:].strip() if data_str [DONE]: break # 这里解析JSON取出delta.content # 通过yield把每一段增量文本推给前端 yield fdata: {data_str}\n\n return StreamingResponse(event_generator(), media_typetext/event-stream)等一下我上面这段代码为了简洁省略了逐行解析的细节。实际处理中你需要对每一行以“data: ”开头的内容做JSON解析然后从choices[0].delta.content字段里取出增量文本再把它转成SSE格式推给前端。如果你直接透传原始数据前端反而很难处理。前端接到SSE响应后用浏览器原生的EventSource对象或者fetch配合ReadableStream去读取都可以。我的经验是如果你还需要在请求头里携带登录凭证那么用EventSource会比较受限建议直接在fetch调用里设置Authorization头然后通过response.body.getReader()读取流。这个流式改造是我认为“AI能力嵌入Web应用”这件事里性价比最高的体验升级。一次投入后续所有要跟模型流式对话的功能都能复用同一套后端封装和前端解析逻辑。4.4 成本与安全别让一次坏请求拖垮你的账单接大模型之后有两件事必须提前考虑。第一件是token成本。很多人只在功能演示阶段跑通即弃等到用户量起来才发现账单失控。我的应对方式是在后端统一加一层请求审计表记录每次调用模型的输入token数、输出token数和响应耗时。每天跑个定时任务统计总消耗发现异常增长能快速定位是哪个用户、哪个接口、哪类内容在消耗资源。第二件事是内容安全。虽然你是在做自己的Web应用但大模型的生成内容仍然需要做合规检查。正规的大模型服务商大多提供了内容审核接口你可以在流式输出结束后对一些敏感字段做异步检测一旦命中就走人工复核流程。这个步骤不能省因为你的应用对用户开放后内容安全就是你的责任你不能把责任推给模型服务商。另外在把模型能力做成付费功能时要设计好配额管理。比如每个用户每天最多使用AI润色20次超过就要等待或者升级套餐。这类业务规则和AI调用没直接关系但如果不提前设计等用户量上来再补就会很痛苦。5. 高品质的那一步前端体验、测试与部署5.1 前端体验的三个容易被忽略的细节AI生成的Web应用桌面端看往往有模有样但一旦涉及真实用户场景你很快会发现三个问题。第一个问题是页面状态反馈缺失。“保存中…”“已更新”“内容超长请删减后再试”这些反馈文案和状态样式AI默认是能省则省的。一个高品质应用不会让用户产生“我点了一下但不知道成没成功”的困惑。我会在功能完成后专门做一轮“反馈走查”把每个按钮可能出现的加载、成功、失败、空状态全部列出来然后让AI根据清单补齐。第二个问题是页面在手机上没法看。很多人觉得后台管理系统不需要响应式但现在是移动办公时代管理者很可能在手机上打开你发过去的链接看数据。这个问题的解法不是重新做一套移动端而是让AI给重点页面补上移动端断点样式。第三个问题是加载策略。列表接口如果一次性拉几千条数据页面上再怎么做分页也扛不住。高品质的方案是后端接口自带分页、前端首屏只加载必要字段。如果你做的是数据分析类页面后端还要考虑聚合查询和缓存。这些听起来基础但AI生成的初版代码几乎不会考虑性能因为它的训练数据里更多是“最短路径实现功能”而不是“最优路径应对压力”。5.2 让AI帮写测试但别只靠AI很多人对AI生成代码有一个误解代码能跑就等于没有bug。实际上能跑通快乐路径只代表实现了功能真正的品质差异来自于对异常路径的处理。以周报删除接口为例你至少要测试这些case测试场景预期行为周报所有者删除自己的周报删除成功非所有者删除别人的周报返回403删除不存在的周报返回404超过周五24点删除本周周报返回400不携带token调用接口返回401同时并发两次删除同一周报只有一次成功另一次返回404我的做法是把这张测试用例表直接丢给AI让它帮我生成对应的接口测试代码。AI在写“验证正常行为的测试”方面表现不错但在“构造异常输入”上会偷懒所以这张表里几个关键的反向case我会自己手写或者至少保证它们出现在AI生成的测试里。最后还要记得跑一遍端到端流程。从注册账号、登录、填写周报、AI润色、提交、再用管理者账号登录查看汇总邮件全程自己操作一遍。这一步没有人能替代你因为只有你才知道真正的用户会怎么使用你的产品。5.3 部署上线前的环境与配置管理当你的Web应用要上线时项目结构需要和本地开发区分开。我常用的做法是前端打包后的静态文件交给Nginx托管同时也负责反向代理和后端API转发后端服务用进程管理器比如systemd或supervisor守护运行数据库从SQLite切换成独立的PostgreSQL服务环境变量统一放.env文件里并由配置管理工具统一管理所有密钥不能提交进Git仓库。这里有一个新手特别容易踩的坑本地联调时前端会直接配置一个API地址比如 http://localhost:8000然后前端开发服务器通过代理转发解决跨域。但线上环境用的是同一份代码打包产物如果里面还写着localhost那上线后所有接口请求都会失败。我的解决办法是在前端构建时读取环境变量来区分开发与生产API地址让Nginx在线上把 /api 路径直接反代到后端服务。部署本身不难但对没上过线的开发者来说“从零到能访问”的第一步往往要折腾半天。我会优先选择带一键部署能力的云平台把前端静态托管数据库和API服务分别跑在独立的容器里。等用户量确实增长到需要精细化运维时再迁移到什么Kubernetes这类容器编排体系也不迟。5.4 模型服务与业务服务采用不同的部署策略如果你的应用里面集成了大模型能力有一件事值得专门拿出来说模型服务和业务服务的部署策略应该分开。业务服务用户注册、周报CRUD对稳定性要求非常高不能因为某个用户触发了一个长耗时的大模型调用就把整个服务的线程池占满导致其他用户连登录都登不上。我的做法是所有大模型相关调用强制走异步任务队列或者在API网关层做超时熔断一旦模型服务连续报错立刻把AI功能降级为“系统繁忙请稍后再试”保证核心业务不受影响。模型服务本身则会选择那些部署弹性更好的方案。如果你用的是外部API那只需要在代码里做好接口超时和失败重试。如果你是在自己的服务器上部署开源模型那这块要单独考虑GPU资源并把输入输出token长度限制在合理范围内防止单个用户的大请求打爆显存。所以一个成熟上线的AI Web应用内部实际上是“稳定的CRUD服务”和“高波动模型服务”两层叠在一起的。你可以在前端界面上把它们揉成一个产品但在后端架构和部署上一定要物理或逻辑上分隔开。6. 我实际填过的坑五个高频问题速查6.1 上下文太长导致响应变慢或报错大模型接口都有上下文长度上限一旦你的业务内容太长请求可能直接报错或者截断信息。我遇到过用户粘贴了上万字的会议纪要结果接口直接返回context length exceeded。解法是两招。第一招是在请求前做长度预检与截断按字符数估算token数超过阈值就提示用户精简第二招是把长文拆分成多段做分段处理再用一次汇总Prompt合并结果。这需要一点工程投入但对体验提升很明显。6.2 AI生成的内容偶尔“幻觉”得很离谱做AI润色功能时最怕模型一本正经地替用户编造“完成了性能优化接口响应时间下降50%”。它没有这段真实信息但润色时默认补充了工作成果。我的处理方式是在Prompt里明确规定“不得添加原文没有的数据、数字和结论”并且把系统提示词放在一个单独的、用户不可修改的位置。同时在产品交互上给用户提供一个“原文对照模式”让AI润色结果和原内容并行展示差异部分高亮。这样用户自己就能判断哪些是AI加的料哪些可以直接采用。6.3 前端页面生成后没有数据可看AI生成的列表页、详情页往往只接真实接口没有任何模拟数据。开发阶段你每次都得手动造数据非常浪费时间。我在生成页面后都会要求AI顺便产出一批种子数据脚本直接往数据库里插入几个测试账号和几十条周报记录。这个做法让页面联调的效率提升很大而且方便后面做自动化测试。6.4 接口失败时前端没有任何提示让AI生成页面代码时我默认会在每个请求后面跟一个.catch或try/catch来弹出错误消息。但很多AI生成的代码请求失败后只是静默地在控制台打一个错误页面上毫无反应。用户点击保存按钮等了五秒没反应再点一下又发了一个重复请求最后数据库里变成两倍数据。现在的习惯是所有业务请求都必须带上loading状态、成功提示和失败提示。失败时要有“重试”按钮不能让用户自己刷新页面去猜结果。这个要求我直接写进AI的生成约束里比它自由发挥后我再补救要省事得多。6.5 版本依赖问题AI默认的库版本跟你本地对不上AI编程工具在生成代码时经常默认使用最新版的依赖库。但同时它给出的调用示例往往基于它训练数据里更早的版本。最典型的就是某个HTTP客户端库的大版本升级后接口签名发生了重大变化AI却仍然按老版本写法。规避办法是在生成项目前先把项目的依赖文件手动初始化好锁住关键依赖的大版本然后再让AI基于当前文件去补全代码。或者在让AI写代码时直接指定“当前项目使用的是vX.Y.Z版本请不要改变依赖配置”。这个小动作能省掉非常多莫名其妙的环境报错。一点个人体会把AI用进Web应用开发之后我最大的体会是它的确让“从0到1”变得非常轻松以前我一个人搭一个全栈项目要两天现在大概两个小时就能跑起来但“从1到100”的功夫一点都没省——甚至更考验你对自己业务的理解深度。你越是清楚自己的产品规则、边界和底线越能指挥AI在正确方向上发挥。如果你自己对业务都模糊AI只会让你的糊涂变成一大堆难以维护的代码。最后一句话总结我的经验想靠AI打造高品质Web应用功夫在AI之外。把它当成一个随叫随到、知识面广但偶尔会得意的实习生把你想清楚的东西交给它执行它就能帮你跑得很快你要是让它替你做决定它就敢把项目带沟里去。我会继续保持“AI负责速度人负责方向”这个工作方式用它把手头那些有价值的想法一个个变成能用的产品。