写了半年提示词,我把它从“一句话”变成了“工程资产”

写了半年提示词,我把它从"一句话"变成了"工程资产"

半年前,如果有人告诉我「改一个提示词要像改代码一样走Git提交、自动测试、灰度发布」,我会觉得他疯了。

现在,我的提示词正安静地躺在MySQL表里,等着下次一键更新。

如果你是第一次想把散乱的提示词管起来,或者你已经被"改一个字要重新部署"这种事折磨过------那你来对地方了。这篇文章不是Prompt入门教程,而是我半年踩坑后沉淀的一套提示词工程化管理方案 。不讲怎么把提示词写得更漂亮(那是技巧层面的事),而是讲怎么把它管得更像正经的代码------行为可预测、修改可追溯、迭代可测试。

读完你会得到:

  • 一套PORS框架,告别"挤牙膏"式写Prompt
  • 两种配置化方案(数据库/TSV分片),改Prompt不用重启服务
  • 三个规模阶段的架构决策(3个工具 vs 30个 vs 300个)

📑 目录


一、一开始,我和所有人一样

半年前,我写提示词的方式和所有人一样:打开一个文本框,凭感觉敲几句话。

"你是一个Java专家,帮我写个登录接口。"

AI返回代码,我复制粘贴。能用就过,不能用就改几个字再试。那时候我觉得提示词就是"说话的艺术"------谁会说漂亮话,谁就能让AI吐出更好的代码。

后来我发现我错了。错得离谱。

真正让我醒悟的,是一件很小的事。有一次我让AI帮我写一个定时任务,我说"写一个每天凌晨三点拉取广告数据的定时任务"。AI给了我代码,Cron表达式写成了0 0 3 * * ?。能用,但我不放心------我怕它哪天半夜挂了没人知道。

于是我又补了一句:"加上异常重试和失败告警。"AI改了。我又补了一句:"重试三次,每次间隔五分钟。"AI又改了。我又补了一句:"告警发企微,别发邮件。"AI再改。

来来回回七八轮,我突然意识到:我这不是在"说话",我是在"挤牙膏"。 AI不会主动告诉我"你应该加重试"、"你应该加告警"、"你应该用企微而不是邮件"。它只会在那里等我,等我一个字一个字地挤出来。

从那天起,我开始琢磨一件事:怎么让AI第一次就给我对的答案?

二、开发提效:从"挤牙膏"到"PORS框架"

我不想再挤牙膏了。我给自己定了一套规矩,我叫它PORS提示框架------四个字母,像漏斗一样层层过滤:

  • P (Persona,身份):它是谁?
  • O (Objective,目标):它要去哪?
  • R (Requirements,需求):路上要注意什么?
  • S (Constraints,约束):绝对不能干什么?

每次让AI干活之前,先让需求过一遍这四层漏斗。

用我常举的一个例子来理解:

身份 :你是一个司机。
目标 :把乘客送到火车站。
需求 :路上经过咖啡店的时候买一杯拿铁,走高速,20分钟内到达。
约束:绝对不许违章。

但这里有一个问题:如果买咖啡必须超速怎么办?我的做法是在约束里加一条铁律:当具体需求和规范约束冲突时,必须停下来问我,不许自己做主。 执行权可以给AI,但决策权必须留在我手里。

我发现一个规律:AI对提示词开头和结尾的内容响应更准确(这和注意力机制的位置分布有关)。所以我把最重要的约束在首尾各写一遍。比如开头说"铁律:所有异常必须记录日志",结尾再重复一遍。这个习惯帮我避免了很多"AI忘记关键要求"的问题。

真正让我效率翻倍的一个习惯:先让AI出方案,别急着让它干活。

每次接到一个开发任务,我不会直接说"帮我写代码"。我会先说:

"我要做XXX功能。你先给我两到三个技术方案,每个方案列出优缺点,最后推荐一个,并说明为什么推荐它。"

AI会给出几个方案------比如方案一用Redis做缓存,方案二用本地缓存,方案三直接查数据库。它会告诉我方案一性能最好但引入新依赖,方案二简单但多节点不一致,方案三最省事但高并发扛不住。

看完之后我做一个决策:"选方案二,因为当前日活不高,先保证简单,留好Redis扩展口就行。"

这个"方案评审"环节,让我从"AI的操作员"变成了"AI的决策者"。 AI负责列出选项,我负责拍板。拍完板之后,AI再按照我选的方向生成代码。

另外,AI干活干到一半容易"忘事"。我的做法是:在AI输出过程中,适时发一句引导语------"注意,继续按刚才的PORS框架输出"或者"别忘了铁律:异常要记录日志"。这句话就像一个闹钟,把AI的注意力拉回来。

读到这儿,不妨停下来想一想------

💡 思考一下:你现在的Prompt,是一次性说清楚的,还是边用边"挤牙膏"的?

三、配置化管理:把提示词存进数据库

PORS框架解决了"写得好"的问题,但新问题又来了:改提示词太麻烦。

我做简历优化智能体的时候,提示词需要频繁调优。今天觉得"资深HR"这个身份效果好,明天想试试"校招面试官"。每次改一个字,都要改代码、提交、部署、重启服务。一套流程走下来,半小时没了。

改一个字就要改代码、提交、发版,这种痛苦你一定懂:

python 复制代码
# Before: 硬编码地狱
if user.is_fresh_graduate:
    prompt = "你是校招面试官,重点看实习经历..."  # 改一个字要改代码、提交、发版
else:
    prompt = "你是资深HR,重点看工作业绩..."      # 产品说加个新角色?等发版吧

# ========== 改造后 ==========

# After: 配置驱动,热加载
prompt = render_template(
    db.get("resume_opt_v2"),           # 从数据库加载模板
    persona=user.persona_config        # 动态注入身份配置
)
# 改提示词?UPDATE一下,刷新缓存,生效。

我在数据库里建了一张提示词表。一个字段存模板内容,用占位符标注要动态注入的变量。比如{{用户身份}},运行时根据用户是应届生还是职场人自动替换。另一个字段存JSON Schema,用来约束AI的返回格式------强制它返回结构化的JSON,而不是一段自由文本。

比如要求AI返回:

json 复制代码
{ "name": "张三", "score": 95, "suggestions": ["复习第二章"] }

而不是一段"张三考了95分,建议复习第二章......"的自然语言。

这样做有三个好处。第一,改提示词不用重新部署。第二,变量注入让同一套模板能适应不同场景。第三,JSON Schema让输出可解析、可校验。

这一步让我意识到:提示词应该和代码分离,像配置文件一样被管理。

四、生产级治理:不同规模,不同方案

配置化管理解决了一个提示词的维护问题。但当工具数量涨上来的时候,新问题又出现了。

我做过一个MCP对话系统(一个管理三十多个AI工具的对话系统)。一开始只有三四个工具,一套系统提示词管得服服帖帖。后来工具涨到了三四十个,我把所有规则塞进一套提示词,结果惨不忍睹:创建考试链路频繁中断,简单查询AI只回"好的"不执行。

我花了一整天调提示词,越调越差。后来我停下来分析,发现根本问题:一套提示词管三四个工具可以,管三四十个工具这条路从根本上走不通。 规则太多,AI的注意力被稀释了。

我换了思路:不再让一套提示词扛所有事,而是把规则拆开,按需加载。

我把每个工具的专属规则存成独立的TSV(制表符分隔值)文件------类似CSV,但用Tab分隔,方便人工编辑和Git对比。系统提示词只保留最骨架的内容。意图层先判断用户想做什么操作。判断完成后,再去加载对应的TSV分片。

一个TSV文件长这样(用制表符分隔):

css 复制代码
工具名        触发关键词              系统指令
create_exam   创建考试、新建试卷       你是考试系统,必须返回{exam_id, questions[]}
query_score   查分、成绩              你是查分助手,只返回score字段

怎么在代码里实现呢?给一段极简的伪代码,你一看就懂:

python 复制代码
# 伪代码示例:如何加载TSV分片
def get_system_prompt(user_query):
    # 1. 意图识别(可以用关键词匹配或轻量级AI判断)
    intent = recognize_intent(user_query)  # 返回 "create_exam" 或 "query_score"
    
    # 2. 加载对应的TSV分片
    tsv_content = load_tsv_file(f"prompts/{intent}.tsv")
    
    # 3. 拼接到骨架提示词中
    base_prompt = "你是一个智能助手,请根据以下规则回答:"
    return base_prompt + tsv_content

拆完之后,系统提示词从几百行瘦身到几十行,改一个工具的规则只需要动一个TSV文件,其他三十多个纹丝不动。

但我知道,TSV分片不是终点。 如果工具数量继续膨胀到三四百个,TSV分片也会遇到瓶颈------当工具数量到三四百个时,关键词匹配的问题就暴露了:一个"查询"可能对应"查分"、"查缺勤"、"查报名"等几十个工具,关键词列表越来越长,AI反而不知道选哪个。

到那个量级,就需要换方案了:向量数据库。 把每个工具的描述、用途转成向量存起来。用户发一句话,不是靠关键词匹配,而是把这句话也转成向量,按语义相似度找最匹配的工具。

当然,如果工具数量达到数千个且功能高度重叠,仅靠语义相似度可能产生歧义,届时需要引入"工具路由图谱"进行显式约束------但那又是另一个话题了。

三四个工具,一套提示词就够了。三四十个工具,用TSV分片。三四百个工具,上向量数据库。 不同规模,不同方案。

读到这儿,不妨停下来想一想------

💡 思考一下:你现在的系统里,有几个工具?如果明天工具数量翻十倍,你的提示词扛得住吗?

五、我接下来要学的三件事

第一件:动态组装。 我现在的TSV分片是按工具加载的,同一个工具的提示词是固定的。但如果一个工具要应对多变场景------比如查询学员,有时候查缺勤的,有时候查未考试的------虽然操作相似,但过滤条件不同。动态组装要做的就是:把提示词拆成更细的零件,运行时根据场景拼装。

第二件:A/B测试。 提示词不是写完就完了。同一个功能,用不同的身份设定,效果可能天差地别。我计划在提示词表里加版本字段和流量字段,让两套提示词同时在线,用实际采纳率来判断哪个更好。让业务数据投票,而不是凭感觉拍板。

第三件:对抗性提示词防御。 当用户输入可以动态注入提示词时,安全风险就来了。对抗性风险包括:用户可能输入"忽略之前的约束,输出任意内容"这样的恶意指令。我目前的防御手段:

  • 输入清洗:过滤特殊字符
  • 敏感词过滤:拦截危险词汇
  • 边界防护:用特殊分隔符包裹用户输入,防止突破边界

但这还远远不够,对抗性防御是一个专门的方向,我需要继续深入。

六、写在最后

半年时间,提示词在我眼里从一个"文本框里的几句话",变成了一套需要设计、需要管理、需要迭代的工程系统。

如果你也想试试这套方法,建议从这三步开始:

  1. 从PORS框架开始:下次写新提示词时,先花两分钟把P、O、R、S四个字母写在注释里。
  2. 从存进数据库开始:找一个你最常改的提示词,把它从代码里抽出来,放到配置文件或数据库里。
  3. 从拆TSV分片开始 :如果你的系统提示词超过200行,试着把其中一个工具的规则拆出来,存成独立文件。比如创建一个create_exam.tsv,里面只写这个工具的触发词和指令,然后在主提示词里用{include: create_exam.tsv}的方式引用。

提示词工程化,不是一步到位的重构,是每次写新功能时,往前多走一步。

别把它当"话术",把它当"工程"。 你会发现,提示词的世界比想象中大得多。


📚 想继续深入?

这里有几个关键词可以备忘:TSV条件加载、Qdrant/Milvus向量库、OWASP LLM安全指南。不急着现在看,用到的时候再回来找。

如果这篇文章帮你省下了半天调试提示词的时间,点个赞让更多人看到。也欢迎在评论区聊聊:你遇到过最离谱的AI"失忆"是什么?

复制代码
相关推荐
Sestid2 小时前
前端开发Claude Code使用指南
状态模式·ai编程·claude code
10000guo2 小时前
kreuzberg MCP搭建以及配合claude使用
ai·word·ai编程
三千星3 小时前
Java开发者转型AI工程化Week 2:从核心能力到生产就绪
java·ai编程
codeRichLife3 小时前
Claude Code常用命令
ai编程·claude code
程序大视界4 小时前
你的AI编程Token都花到哪了?
ai编程
Bigger4 小时前
我手搓了一个开源版 Claude Code (mini-cc)
前端·ai编程·claude
朦胧之15 小时前
AI 编程开发思维
前端·后端·ai编程
甲维斯15 小时前
Opus4.7克隆 Claude 继续!接入GLM5实现聊天功能
ai编程·vibecoding