大模型应用开发教程06 | 高级提示词策略(Few-shot / CoT / 结构化)
·
理论部分
在第 5 篇我们已经能用 “System(角色/规则)+ User(任务/输入)” 把模型输出变得可控。但很多真实业务还会遇到两类问题:
- 同一个任务,输出仍然会漂移:格式不稳定、细节忽多忽少、偶尔跑题
- 输出难以被程序消费:我们想拿结果去写入数据库、调用工具、做后续计算,但模型给的是一段“看起来对”的自然语言
这时候就需要更“工程化”的提示词策略。最常用的三类是:Few-shot、CoT、结构化输出。
1)Few-shot(少样本提示)
Few-shot 的核心思想是:给模型看我们想要的“示例”,让示例变成隐性的规则。
它特别适合:
- 我们要模型模仿某种输出格式(例如固定字段、固定段落结构)
- 我们要模型保持口径一致(例如统一的分类标准、统一的评分维度)
示例一般放在 user 内容里或作为多条消息放入 messages,常见形式是:
- 输入:A → 输出:A’
- 输入:B → 输出:B’
- 现在输入:C → 请按同样方式输出:C’
2)CoT(Chain-of-Thought,思维链)
CoT 的核心思想是:让模型把复杂任务分解成步骤再输出结果。
它特别适合:
- 推理/规划型任务(数学、逻辑、步骤规划、长文本分析)
- 需要“过程正确”才能保证“结果正确”的任务
但要注意:
- 不是所有任务都需要 CoT,信息抽取这类任务通常更需要“结构化输出”
- 在产品场景里,你更常见的做法是:让模型在内部推理,但只输出最终结果(避免把中间过程暴露给用户)
3)结构化输出(Structured Output)
结构化输出的核心思想是:我们先定义一个输出 Schema(字段名/类型/含义),再要求模型严格按 Schema 返回。
它特别适合:
- 信息抽取(简历解析、合同关键字段提取、发票/工单解析)
- 工具调用(把模型输出当作函数参数)
- 后续要做程序处理(验证、入库、统计、检索)
结构化输出常见两种实现方式:
- 强提示约束:在 Prompt 里明确声明 JSON 结构、缺失字段填 null、禁止输出解释文字
- 协议级约束(如果模型/SDK 支持):例如
response_format={"type": "json_object"}或 JSON Schema 模式
本项目采用的是“强提示约束”的方式:适配性更强,所有兼容的模型都能用。
实践部分
本案例做什么
实现一个“简历解析助手”,输入一段乱糟糟的简历文本,让模型输出一份严格 JSON 格式的结构化结果:
- 姓名、工作年限、技能、公司、学历、电话、以及一句话总结
- 如果字段找不到,填
null - 输出只能是 JSON,不能夹带解释文字
主要代码
本篇直接使用项目脚本:src/2.2_structured_output.py
import os
import json
from dotenv import load_dotenv
from openai import OpenAI
load_dotenv()
client = OpenAI(
api_key=os.getenv("ZHIPUAI_API_KEY"),
base_url=os.getenv("ZHIPUAI_BASE_URL")
)
def extract_resume_info(resume_text):
"""
使用 LLM 提取简历信息为 JSON
"""
# 定义期望的 JSON 结构 (Schema)
# 这一步非常关键,你描述得越清楚,模型提取越准
schema_desc = """
{
"name": "姓名",
"years_of_experience": "工作年限(数字)",
"skills": ["技能列表"],
"companies": ["工作过的公司列表"],
"education": "最高学历",
"phone": "联系电话",
"summary": "一句话总结求职者的特点"
}
"""
system_prompt = f"""
你是一个专业的 HR 简历解析助手。
请分析用户的输入,提取关键信息,并以 JSON 格式输出。
输出必须严格遵守以下 JSON 结构:
{schema_desc}
注意:
1. 如果某个字段在文本中找不到,请填 null。
2. 不要输出任何 JSON 以外的解释性文字(如“好的,这是结果...”)。
3. 直接返回 JSON 字符串。
"""
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": resume_text}
]
print("🤖 正在解析简历...")
# 调用模型
# 注:如果模型支持 json_object 模式,建议开启 response_format={"type": "json_object"}
# 智谱 glm-4-flash 目前主要靠 prompt 约束,我们这里通过 prompt 强力约束
response = client.chat.completions.create(
model="glm-4-flash",
messages=messages,
temperature=0.1, # 信息提取类任务,温度要低,越严谨越好
)
content = response.choices[0].message.content
# 清洗数据:有时候模型可能会把 JSON 包裹在 ```json ... ```里,需要去掉
if "```json" in content:
content = content.replace("```json", "").replace("```", "")
return content
def main():
print("=== 📄 智能简历解析助手 (JSON版) ===")
# 模拟一段乱糟糟的简历文本
default_resume = """
你好,我叫李四。
之前在字节跳动干了3年后端,主要用 Go 和 Python。
后来去了腾讯做了一年架构师。
我的电话是 186-1234-5678。
本科毕业于浙江大学。
希望能找个不加班的工作。
"""
print(f"\n原始文本:\n{default_resume}")
print("-" * 30)
try:
json_str = extract_resume_info(default_resume)
# 尝试将字符串解析为 Python 字典,验证是否为合法 JSON
data = json.loads(json_str)
print("\n✅ 解析成功! 结构化数据如下:\n")
# 美化打印 JSON
print(json.dumps(data, indent=4, ensure_ascii=False))
# 演示一下怎么用这个数据
print("\n[后续代码调用示例]")
print(f"候选人: {data.get('name')}")
print(f"技能栈: {', '.join(data.get('skills', []))}")
except json.JSONDecodeError:
print("\n❌ 解析失败:模型返回的不是标准 JSON。")
print("模型原始返回:", json_str)
except Exception as e:
print(f"\n❌ 发生错误: {e}")
if __name__ == "__main__":
main()
运行方式
在项目根目录执行:
python3 src/2.2_structured_output.py
运行结果示例
正常情况下,我们会看到模型输出的结构化 JSON(字段值可能略有不同):
=== 📄 智能简历解析助手 (JSON版) ===
原始文本:
...
------------------------------
✅ 解析成功! 结构化数据如下:
{
"name": "李四",
"years_of_experience": 4,
"skills": [
"Go",
"Python"
],
"companies": [
"字节跳动",
"腾讯"
],
"education": "本科",
"phone": "186-1234-5678",
"summary": "..."
}
如果出现 解析失败:模型返回的不是标准 JSON,通常是模型在 JSON 前后输出了额外文字。这个脚本已经做了基础清洗(去掉 ```json 包裹),但也可以进一步加强约束:更严格地声明“只能输出 JSON”,并把温度保持在较低水平。
总结
这一篇我们掌握了三类常用的高级提示词策略:
- Few-shot:用示例让模型“照着做”
- CoT:让复杂任务更容易推理正确
- 结构化输出:让结果可验证、可解析、可直接给程序使用
更多推荐
所有评论(0)