第五节:Vibe Coding 之前,先做一次技术选型
vibe coding 可以快速生成页面,却不会自动保证:权限真的在服务端、AI 的回答真的有依据、人工真的能接管、失败真的能追溯。
01|技术选型任务书:先规定 AI 要证明什么
技术选型不是让 AI 说“推荐 Next.js、PostgreSQL、某某模型”。
它要先回答:为了让这个产品可交付,哪些事实必须被证明?
项目范围
这是一个企业售后工单工作台。客服处理“耳机左耳无声、希望退货”这类工单时,AI 可以分类、检索知识、起草回复;人工负责编辑、确认或转人工。第一版只使用合成数据,不执行真实退款、改订单或外发消息。
任务书的六条通过标准
#oteSQDSCAhyB text { white-space: pre; }#oteSQDSCAhyB .fb0 { stroke: var(--N900-FG, 0.15); }#oteSQDSCAhyB .fb0 {stroke: rgba(31,35,41, 0.15)}#oteSQDSCAhyB .fx0 { stroke-miterlimit: 10; }#oteSQDSCAhyB .fx0 {stroke-miterlimit: 10}#oteSQDSCAhyB .fa1 { fill: rgb(187, 191, 196); }#oteSQDSCAhyB .fa1 {fill: rgb(187, 191, 196)}#oteSQDSCAhyB .fx1 { font: 400 12px MonospacedNumber, LarkHackSafariFont, LarkEmojiFont, LarkChineseQuote, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Tahoma, "PingFang SC", "Microsoft Yahei", Arial, "Hiragino Sans GB", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; }#oteSQDSCAhyB .fx1 {font-style: normal}#oteSQDSCAhyB .fx2 { text-anchor: middle; }#oteSQDSCAhyB .fx2 {text-anchor: middle}#oteSQDSCAhyB .fx3 { dominant-baseline: central; }#oteSQDSCAhyB .fx3 {dominant-baseline: central}#oteSQDSCAhyB .fx4 { stroke: none; }#oteSQDSCAhyB .fx4 {stroke: none}#oteSQDSCAhyB .fc0 { fill: var(--text-caption); }#oteSQDSCAhyB .fc0 {fill: #646a73}#oteSQDSCAhyB .fa2 { fill: var(--text-link-disabled); }#oteSQDSCAhyB .fa2 {fill: rgb(187, 191, 196)}#oteSQDSCAhyB .fa3 { fill: rgb(239, 243, 244); }#oteSQDSCAhyB .fa3 {fill: rgb(239, 243, 244)}#oteSQDSCAhyB .fx5 { font: 400 16px MonospacedNumber, LarkHackSafariFont, LarkEmojiFont, LarkChineseQuote, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Tahoma, "PingFang SC", "Microsoft Yahei", Arial, "Hiragino Sans GB", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; }#oteSQDSCAhyB .fx5 {font-style: normal}#oteSQDSCAhyB .fx6 { text-anchor: start; }#oteSQDSCAhyB .fx6 {text-anchor: start}#oteSQDSCAhyB .fx7 { dominant-baseline: alphabetic; }#oteSQDSCAhyB .fx7 {dominant-baseline: alphabetic}#oteSQDSCAhyB .fc1 { fill: rgb(15, 20, 25); }#oteSQDSCAhyB .fc1 {fill: rgb(15, 20, 25)}#oteSQDSCAhyB .fx8 { font: 400 15px MonospacedNumber, LarkHackSafariFont, LarkEmojiFont, LarkChineseQuote, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Tahoma, "PingFang SC", "Microsoft Yahei", Arial, "Hiragino Sans GB", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; }#oteSQDSCAhyB .fx8 {font-style: normal}#oteSQDSCAhyB .fx9 { font: 400 13px LarkHackSafariFont, LarkEmojiFont, "monospace", -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, "Noto Sans", Tahoma, "Nimbus Sans L", Arial, "Liberation Sans", "PingFang SC", "Hiragino Sans GB", "Noto Sans CJK SC", "Source Han Sans SC", "Source Han Sans CN", "Microsoft YaHei", "Wenquanyi Micro Hei", "WenQuanYi Zen Hei", STHeiti, SimHei, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji", system-ui; }#oteSQDSCAhyB .fx9 {font-style: normal}#oteSQDSCAhyB .fc2 { fill: rgb(193, 132, 1); }#oteSQDSCAhyB .fc2 {fill: rgb(193, 132, 1)}#oteSQDSCAhyB .fb1 { fill: var(--N900-FG, 0.15); }#oteSQDSCAhyB .fb1 {fill: rgba(31,35,41, 0.15)}#oteSQDSCAhyB .fb2 { fill: rgb(207, 217, 222); }#oteSQDSCAhyB .fb2 {fill: rgb(207, 217, 222)}#oteSQDSCAhyB .fa4 { fill: var(--bg-body); }#oteSQDSCAhyB .fa4 {fill: #fff}AB1234567要证明的能力权限并发写入AI 输出知识引用人工确认评测与审计最小验证结果客服、主管、管理员、访客访问同一资源时,服务端给出正确范围;访客不能写。流式返回分类、来源、草稿、风险与下一步,而不是一段不可评测的聊天文本。返回文档、版本、片段;停用后不再进入新检索。AI 原稿、人工终稿、修改差异、确认人和时间可查询。每次 AI 运行和固定评测都保存版本、耗时、结果和失败原因。工单带版本保存;旧版本提交返回 ,不能覆盖新内容。409

让 AI 生成任务书的起始 Prompt
把下面这段放在开始技术选型的第一轮,而不是直接问“你推荐什么技术栈”。
你正在为一个企业 AI 产品做技术选型,而不是直接写完整代码。
代码块
Markdown
你正在为一个企业 AI 产品做技术选型,而不是直接写完整代码。
先根据产品原型,列出必须被验证的能力:权限、数据写入、并发、AI 输出、知识引用、人工确认、固定评测、审计与异步任务。
对每一层只给 2~3 个候选。每个候选必须写清:
1. 它解决的产品风险;
2. 最小验证动作;
3. 通过标准与停止条件;
4. 成功或失败要保留的测试文档/截图;
5. 选择、淘汰或延后的理由。
只用合成数据。没有真实证据时只能写“待验证”,不得写“已选择”。
这段 Prompt 的作用不是让 AI 替你决定,而是强制它先把“应该如何证明”写出来。你作为产品负责人,只需要看每一个通过标准是否足以保护你的业务。
02|系统架构:把一张看不清的总图拆成三条职责线
A. 用户与业务事实
前端负责显示和交互;API 负责权限与业务规则;PostgreSQL 保存工单、会话、人工确认和审计。浏览器看到“管理员按钮”,不等于它拥有管理员权限。
B. AI 建议如何进入人工闭环

模型生成的是“建议”,不是“企业已经作出的回复”。引用必须来自本轮检索片段;命中质量、退换货、安全、补偿、个人信息或外发等场景时,服务端强制人工确认。
C. 长任务与质量验证

文档索引、批量评测这类长任务不应该堵住页面请求。它们进入 Worker,并留下状态、重试、失败原因和幂等记录。
03|边界说明:每层负责什么,不负责什么
一句话记住:改变业务事实的事情,必须经过 API、数据库和审计;模型和页面都不能绕过这一层。
04|DeepSeek 真实流式与结构化输出验证
我只使用一张合成售后工单和一条合成知识规则,要求模型以 SSE 流式返回结构化结果:
代码块
JSON
{
"classification": "质量问题分类",
"priority": "优先级",
"sources": ["知识片段 ID"],
"draft_reply": "回复草稿",
"risk_level": "风险等级",
"requires_human_confirmation": true,
"next_action": "下一步建议"
}
这个验证的正确结论不是“模型成功了”,而是:协议可以交给模型,业务可信度不能交给模型。
05|技术选型对比表 v0.1
“已选择”表示已有本项目的验证证据;“暂选”是方向明确、正式开发还需验证;“延后”不是不好,而是现在引入会增加不必要的复杂度。
06|最终选型与淘汰理由
第一版技术组合
代码块
Plain Text
Next.js + React + TypeScript
↓
独立 TypeScript API
↓
PostgreSQL
├─ 工单、会话、版本、审计
├─ 知识元数据、AI 运行、人工确认
├─ 固定评测与任务状态
└─ pgvector(知识检索候选)
↓
可替换的模型适配层 + SSE
↓
来源白名单 + 风险强制规则
↓
关键淘汰与延后
•
Go 不做首版主 API: 它能通过相同权限用例,但会为课程项目增加跨语言维护成本;高并发或 Go 工程展示是重新比较的触发条件。
•
默认 PostgreSQL FTS 不做中文主检索: 不能可靠支持中文命中与引用责任。
•
Redis 不进入第一版: PostgreSQL 任务表已验证能满足状态、重试、幂等与审计;真实瓶颈出现后再升级。
•
不绑定单一模型供应商: 模型行为、价格、可用性会变化,业务层只依赖统一适配契约。
有三项主动留到下一份技术选型任务书:Prisma/Drizzle 的公平比较、真实中文 embedding 召回、云部署环境验证。没有证据,就不写“已经选完”。
07|AI 可执行工程规范
后续让 AI 开发时,必须持续遵守这 10 条:
前端只负责呈现和交互;权限、数据写入、业务规则由服务端决定。
每个受保护接口先验证会话、账号状态、角色与资源归属。
工单写入必须携带 version;冲突返回 409,不自动覆盖。
AI 只获得后端提供的脱敏、授权上下文;不能直接访问数据库或任意工具。
模型返回的来源只能来自本轮检索片段 ID。
质量、退换货、安全、补偿、个人信息、外发等场景,服务端强制人工确认。
AI 原稿、人工终稿、确认人、确认时间、模型/提示词/知识版本和失败原因必须落库。
知识索引和固定评测进入 Worker;任务有 ID、幂等键、最大重试、取消条件和人工升级出口。
关键允许、拒绝、失败、重试、确认、转人工都写审计;不写入密钥、完整 token 或未脱敏数据。
每轮只做一个实验或验收项;改完保存测试文档或截图。没有证据,就写“待验证”。
08|交付完成度审计
这就是技术选型真正该交付的东西:不是一张“技术栈推荐表”,而是一份让 AI 可以执行、让产品负责人可以判断、让后续开发不会偏航的任务书与证据链。