M3.2 · 提示词工程系统化
掌握程度:熟练
转行工程师学生
📘 已发布学习资料
M3.2 提示词工程系统化
目标:把零散的"提示词技巧"升级成可复用、可维护的 System Prompt 工程。
1. System Prompt 怎么写(定人设、定规则)
System Prompt 是给模型的"底层设定":它是谁、什么能做、什么不能做、怎么回答。它不随用户问题变,常驻在 messages 最前面。
SYSTEM_PROMPT = """
你是为"瑞冬AI学院"服务的课程助教。
# 角色
- 耐心、专业、用中文、面向零基础学员
# 规则
- 只基于已提供的课程资料回答,资料没有就说"这个我不确定"
- 不编造视频/文档里不存在的内容
- 遇到敏感/违规请求,礼貌拒绝并说明原因
# 输出格式
- 复杂问题先给结论,再给解释
- 代码示例用 markdown 代码块
"""
调用时永远把它放在第一条:
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_question}
]
2. 结构化输出约束(JSON Schema)
让模型返回结构化数据,便于程序处理。给"字段定义"比只说"返回 JSON"更稳。
schema = {
"name": "extract_task",
"parameters": {
"type": "object",
"properties": {
"title": {"type": "string"},
"owner": {"type": "string"},
"due": {"type": "string", "format": "date"},
},
"required": ["title", "due"]
}
}
# 把 schema 写进提示词,并要求"只返回 JSON,不解释"
prompt = f"抽取待办,严格按此结构返回 JSON:{schema}\n文本:{text}"
3. 错误处理与重试
模型偶尔会返回格式错、或答非所问。做一层兜底:
import json, re
def safe_parse(raw):
try:
return json.loads(raw)
except json.JSONDecodeError:
m = re.search(r"\{.*\}", raw, re.S)
if m:
return json.loads(m.group(0))
return None # 解析失败,上层决定重试
def ask_with_retry(question, tries=3):
for i in range(tries):
raw = llm(question)
data = safe_parse(raw)
if data:
return data
question += "\n【注意】请只返回合法 JSON,不要加任何说明文字。"
raise RuntimeError("多次重试仍无法解析")
4. 多轮对话的上下文管理
轮数变多,token 暴涨、且旧信息稀释重点。常用策略:
def trim_history(history, max_turns=10):
# 只保留最近 N 轮 + 永远保留 system
sys_msg = history[0:1]
recent = history[1:][-max_turns*2:]
return sys_msg + recent
# 或:把"已确认的结论"压缩成一条摘要,替换掉冗长原始对话
动手练习
- 给你自己的项目写一条 System Prompt(角色 + 3 条规则 + 输出格式),跑几个问题检验它"守规矩"没有。
- 把 M1.5 的
rag_answer加上safe_parse重试,确保即使模型夹带说明文字也能拿到 JSON。 - 写个
trim_history函数,构造一个 20 轮的假对话,验证它确实只留了最近 10 轮。
自测
- System Prompt 和 User Prompt 职责上有什么区别?为什么要分开?
- 为什么给模型 JSON Schema 比只说"返回 JSON"更可靠?
- 多轮对话为什么要"裁剪历史"?不裁会怎样(提示:token、重点稀释)?