告别「帮我写个 Prompt」:我用 LangGraph + Vue3 搭了一个本地提示词生成器 PromptOps
填五个字段,自动选框架、追问澄清、流式出稿——把零散需求变成可直接丢进 Cursor / ChatGPT 的结构化提示词。
前言:为什么做这个?
写提示词这件事,我踩过太多坑:
- 脑子里有想法,落笔就是「你是一个专业的 XXX,请帮我……」
- 知道 APE、CRISPE、LangGPT 这些框架,但每次都要手动套
- 需求写太简略,模型输出跑偏;写太细,又变成「写提示词的提示词」
于是做了 PromptOps——一个本地运行的 AI 提示词生成工具:
- 前端填结构化表单(场景、任务、语气、复杂度……)
- 后端用 LangGraph 跑一条生成流水线:完整性检查 → 任务分析 → 框架匹配 → 组装 → 流式生成
- 信息不够时主动追问澄清,够了就直接出 中文 Markdown 成稿
- 内置 17 种提示词框架(APE、BROKE、CRISPE、LangGPT……),自动匹配场景
全程本地双进程,模型走 OpenAI 兼容 API(百炼 / OpenAI / DeepSeek 都行),密钥不进前端。
先看效果
| 生成页 |
|---|
| 示例库 |
|---|
典型流程:
- 填写「使用场景 + 具体任务 + 附加描述 + 语气风格 + 复杂度」
- 点击生成,右侧实时流式输出
- 若任务太模糊(比如「帮我弄一下」),会弹出澄清面板
- 成稿一键复制,直接粘贴到 Cursor Rules、Agent System Prompt 里
技术栈一览
| 层 | 选型 | 理由 |
|---|---|---|
| 前端 | Vue 3 + TS + Vite + Pinia + Element Plus | 表单 + SSE 流式,生态成熟 |
| 后端 | FastAPI + LangGraph + Pydantic | 类型安全、图编排清晰 |
| 模型 | 任意 OpenAI 兼容 HTTP API | 不绑供应商,换模型只改配置 |
| 包管理 | uv(后端)/ npm(前端) | 后端依赖锁定快 |
核心设计:LangGraph 六步流水线
整个生成过程不是「一个 Prompt 调一次 LLM」,而是一条有分支的状态图:
graph TD
START --> check_completeness{完整性检查}
check_completeness -->|信息不足| prepare_clarification[生成澄清问题]
check_completeness -->|无法处理| mark_blocked[标记阻塞]
check_completeness -->|通过| analyze_task{任务分析}
analyze_task -->|有关键歧义| prepare_clarification
analyze_task -->|清晰| select_framework[选择提示词框架]
select_framework --> assemble_prompt_plan[组装渲染计划]
assemble_prompt_plan --> generate[流式生成成稿]
generate --> mark_ready[完成]
prepare_clarification --> END
mark_blocked --> END
mark_ready --> END
对应代码里的拓扑(精简版):
graph.add_edge(START, "check_completeness")
graph.add_conditional_edges("check_completeness", after_completeness, {
"clarify": "prepare_clarification",
"route": "analyze_task",
"blocked": "mark_blocked",
})
graph.add_conditional_edges("analyze_task", after_analysis, {
"clarify": "prepare_clarification",
"select": "select_framework",
})
graph.add_edge("select_framework", "assemble_prompt_plan")
graph.add_edge("assemble_prompt_plan", "generate")
graph.add_edge("generate", "mark_ready")
三个我觉得值得单独说的点
1. 完整性检查:不是「字数不够就追问」
早期版本容易犯一个错:任务描述短就强制澄清。但「写周报」三个字其实完全可以生成带占位变量的提示词。
现在的规则是:
missing_task→ 阻塞- 命中「帮我弄一下」「随便写点」等语义模糊表述 → 澄清
- 其余短任务 → 直接 READY
# 长度不再单独决定澄清:例如"写周报"可直接生成带变量的提示词
_VAGUE_TASKS = frozenset({
"帮我弄一下", "弄一下", "写一下", "随便写点", ...
})
2. 框架自动匹配:17 套模板注册表
框架不是硬编码在 Prompt 里,而是 JSON 注册表 + 选择信号:
- APE:行动 / 目的 / 期望,适合任务明确、重视交付物
- BROKE:背景 / 角色 / 目标 / 关键结果,适合 OKR 风格
- LangGPT:结构化角色 + 工作流,适合复杂 Agent
- CRISPE、COAST、TRACE…… 共 17 种
LLM 根据 selection_signals / avoid_signals 做框架决策,再由 FrameworkRenderPlanBuilder 把元素填进渲染计划,最后统一流式生成。
扩展新框架 = 改 JSON,不用动核心编排。
3. SSE 事件流:前端只关心 5 种公开事件
后端 GenerationService 把 LangGraph 的 astream 映射成 SSE:
| 事件 | 含义 |
|---|---|
task.status | 阶段切换(检查中 / 路由中 / 生成中) |
clarification.required | 需要用户补充信息 |
generation.delta | 增量文本 |
task.completed | 生成完成 |
task.failed | 失败 |
前端 useGenerationStream 用 AbortController 管理订阅生命周期,切页自动 abort,避免幽灵请求。
项目结构(给想 Fork 的同学)
后端
app/
agents/ # LangGraph 图、节点、条件边
frameworks/ # 框架注册表 + 渲染计划
services/ # 生成、澄清、完整性、模型配置
api/v1/ # REST + SSE 入口
core/llm/ # OpenAI 兼容客户端工厂
前端
src/
pages/ # / 生成 /examples 示例
components/ # 表单、澄清面板、进度条、编辑器
composables/ # SSE 流式逻辑
api/ # HTTP + stream 封装
5 分钟跑起来
1. 后端(Python 3.12 + uv)
cd backend
cp .env.example .env
# 可选:预填模型配置
# AI_API_KEY=xxx
# AI_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
# AI_MODEL=qwen-plus
uv sync
uv run uvicorn app.main:create_app --factory --reload --host 127.0.0.1 --port 8000
Swagger:http://127.0.0.1:8000/docs
2. 前端(Node 20+)
cd frontend
cp .env.example .env
npm install
npm run dev
打开 http://127.0.0.1:5173 ,顶栏「配置模型」填入 API Key 即可开跑。
密钥只进后端进程,不会写进任何
VITE_*变量。
一个真实用例
输入
- 场景:写作
- 任务:生成一份新品发布文案
- 附加描述:突出自动归类能力
- 语气:自然、简洁
- 复杂度:standard
背后发生了什么
- 完整性检查 → READY(任务明确)
- 任务分析 → 识别为「营销文案 + 功能卖点」
- 框架匹配 → 可能选 CRISPE 或 APE(视分析结果)
- 组装渲染计划 → 流式输出结构化中文 Markdown 提示词
输出(示意)
## 角色
你是一位擅长 B2B SaaS 新品发布的资深文案策划……
## 任务
为具备「自动归类」能力的新品撰写发布文案……
## 约束
- 语气自然、简洁
- 突出自动归类带来的效率提升
……
复制 → 粘贴到 ChatGPT / Cursor → 直接开写。
踩坑记录
| 问题 | 解法 |
|---|---|
| CORS 报错 | 后端 ALLOWED_ORIGINS 必须包含 http://127.0.0.1:5173 |
| 重启后模型配置丢失 | 当前设计是进程内内存配置,重启回退 .env;生产可接持久化 |
| LangGraph 状态泄漏密钥 | GenerationGraphState 明确禁止密钥字段进入 State |
| 澄清轮次死循环 | 前端递增 clarification_round,后端据此调整策略 |
总结
PromptOps 解决的不是「让 AI 帮你写一句话」,而是:
把提示词编写从手工 craft 变成可复用的流水线。
LangGraph 负责编排与分支,框架注册表负责知识沉淀,SSE 负责体验——三者拆开,各自演进。
如果你也在频繁给 Agent / Copilot 写 System Prompt,不妨试试本地跑一套,至少不用再从空白文档开始憋第一句「你是一个……」了。
相关链接
- 项目仓库:github.com/lylylyp/pro…
- 后端 API 文档:启动后访问
/docs - LangGraph 官方文档:langchain-ai.github.io/langgraph/
标签: #Vue3 #FastAPI #LangGraph #PromptEngineering #AI应用 #开源项目
专栏: AI 应用开发 / 全栈实践
如果这篇对你有帮助,欢迎 点赞 + 收藏,有问题评论区见 👋