AI 工具型应用最小项目(结构化输出)
目标:用“结构化输出 + 可编辑 + 可保存”做一个可产品化的工具。
目录
- 项目目标与范围
- 架构图(最小闭环)
- 项目结构(最小可跑)
- 输出模板(最小 Prompt)
- 前端编辑与保存(伪代码)
- 校验与重试策略(最小可用)
- 运行步骤(最少流程)
- 验收标准
- 常见坑排查清单
- 详细实现解析(结构化输出)
- 版本管理建议
- Mermaid:结构化输出流程
- 调试与排障
- 扩展方向
- UI 设计细节(最小但可用)
- 结果编辑器示例(伪代码)
- 版本对比(最小思路)
- 示例用例(可直接测试)
- 运行日志样例
- FAQ
- 详细实现解析(前端)
- 详细实现解析(后端)
- 评估指标建议
- Mermaid:版本保存流程
- 运行日志模板
- FAQ(扩展)
- 交付物清单(工具型项目)
- 示例输入与输出
- 完整可运行代码(Mock 版)
项目目标与范围
- 必须有:JSON 结构化输出、可编辑、版本保存
- 暂不需要:权限体系、协作评论、复杂模板市场
架构图(最小闭环)
项目结构(最小可跑)
tool-demo/
server/
generate.js
web/
App.jsx
ResultEditor.jsx
输出模板(最小 Prompt)
请输出 JSON:
{
"title": "...",
"items": [{ "name": "...", "priority": "P1" }]
}
JSON Schema(最小校验)
{
"type": "object",
"properties": {
"title": { "type": "string" },
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": { "type": "string" },
"priority": { "type": "string", "enum": ["P0", "P1", "P2"] }
},
"required": ["name", "priority"]
}
}
},
"required": ["title", "items"]
}
最小接口(伪代码)
接口返回格式(建议)
{ "result": { "title": "...", "items": [ { "name": "...", "priority": "P1" } ] } }
// POST /tool/generate -> 返回结构化结果
app.post("/tool/generate", async (req, res) => {
const { input } = req.body;
const result = await callLLM(input);
res.json({ result });
});
前端编辑与保存(伪代码)
const [result, setResult] = useState({});
const [history, setHistory] = useState([]);
function saveVersion() {
setHistory((h) => [...h, { time: Date.now(), data: result }]);
}
校验与重试策略(最小可用)
- 模型输出后先做 JSON 解析
- Schema 校验失败 → 把错误原因回传给模型重试 1 次
- 仍失败 → 降级为可读文本 + 手动编辑
运行步骤(最少流程)
- 生成:提交输入 → 返回 JSON
- 编辑:前端可修改字段
- 保存:保存版本并可回滚
验收标准
- JSON 可解析 + 结构稳定
- 结果可编辑并保存版本
- 超长输入会被拦截或提示
常见坑排查清单
- 输出不稳定:加 JSON schema 校验 + 自动重试
- 用户改完没保存:保存版本 + 对比差异
- 缺少回滚:至少保留 3-5 个历史版本
- 成本失控:限制输入长度 + 限制 max_tokens
详细实现解析(结构化输出)
为什么必须用 JSON
- 可直接驱动 UI
- 可存入数据库
- 可用于后续流程(比如生成任务/拆解需求)
校验失败的处理策略
- 直接重试(带失败原因)
- 追问补齐字段
- 最后降级为可读文本
版本管理建议
- 保存最近 3~5 次版本
- 标注时间与变更说明
- 支持一键回滚
Mermaid:结构化输出流程
调试与排障
- JSON 解析失败:提示模型“严格 JSON”
- 输出字段缺失:强制 required 字段
- 结果不稳定:锁定温度与Top-p
扩展方向
- 结果对比视图
- 模板市场(不同场景)
- 结果一键导出(Markdown/CSV)
UI 设计细节(最小但可用)
- 左侧输入区
- 右侧结果编辑区
- 底部版本列表
结果编辑器示例(伪代码)
function ResultEditor({ value, onChange }) {
return (
<textarea value={JSON.stringify(value, null, 2)} onChange={(e) => onChange(e.target.value)} />
);
}
版本对比(最小思路)
function diff(oldVal, newVal) {
// 伪代码:对比 JSON 字段
return Object.keys(newVal).filter((k) => oldVal[k] !== newVal[k]);
}
示例用例(可直接测试)
- 输入:"生成一份会议纪要"
- 期望:返回 JSON 且包含
title/items
运行日志样例
[generate] ok
[validate] schema pass
[save] version=3
FAQ
Q: 为什么输出经常不稳定?
A: 降低温度 + 加强 schema 校验。
Q: 版本保存太多怎么办?
A: 只保留最近 5-10 个版本。
详细实现解析(前端)
字段编辑策略
- 直接编辑 JSON
- 或映射为表单控件
表单映射示例(伪代码)
<input value={result.title} onChange={(e)=>setResult({ ...result, title: e.target.value })} />
详细实现解析(后端)
- 保证输出为 JSON
- 输出前做 schema 校验
- 失败自动重试
评估指标建议
- JSON 合格率
- 用户编辑次数
- 版本回滚率
Mermaid:版本保存流程
运行日志模板
[generate] ok
[validate] pass
[save] version=4
FAQ(扩展)
Q: 为什么不直接输出 Markdown?
A: 结构化输出更便于编辑与存储。
Q: 用户输入太长怎么办?
A: 限制输入长度 + 引导分段。
交付物清单(工具型项目)
- 一段 30 秒演示视频
- 一份示例输入/输出 JSON
- 一份指标记录(合格率)
示例输入与输出
输入:
生成一份产品需求草案
输出(JSON):
{
"title": "产品需求草案",
"items": [
{ "name": "核心功能", "priority": "P1" }
]
}
完整可运行代码(Mock 版)
源码目录:
docs/demos/tool-demo
目录结构
tool-demo/
server/
index.js
package.json
public/
index.html
server/index.js(结构化输出)
import express from "express";
import path from "path";
import { fileURLToPath } from "url";
const app = express();
app.use(express.json());
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
function buildResult(input) {
return {
title: "自动生成结果",
items: [{ name: input || "默认任务", priority: "P1" }]
};
}
app.post("/tool/generate", (req, res) => {
const { input } = req.body || {};
const result = buildResult(input);
res.json({ result });
});
app.listen(3003, () => {
console.log("Tool demo at http://localhost:3003");
});
public/index.html(最小前端)
<input id="input" placeholder="请输入需求" />
<button id="gen">生成</button>
<textarea id="result"></textarea>
运行方式
cd docs/demos/tool-demo/server
npm i
npm run dev