提示工程:与大模型对话的“语法“

摘要 :2026 年的大模型能力已经非常强大,但同样的模型给不同的人用,效果天差地别。差别不在于模型,而在于提示词(Prompt)------你如何向模型描述任务。提示工程就是研究"如何写出更好的提示"的学科。这篇文章从零样本到思维链,系统讲解提示工程的核心技术,全部基于本地运行的 Qwen3 模型,无需 API。


一、为什么提示词如此重要?

本质原因

大模型在训练时学会了海量的知识,但在推理时,它需要在"记忆"中定位到正确的部分。提示词就是定位器------告诉模型应该调用哪些知识来处理当前任务。

复制代码
不好的提示:           "分析这个"
  → 模型不知道"分析"什么、怎么分析、输出格式是什么
  → 输出质量差 ❌

好的提示:             "你是一个金融分析师。请分析以下财报数据,
                       从营收增长、利润率、现金流三个维度给出评估,
                       用表格形式输出。"
  → 模型知道角色、任务、维度、格式
  → 输出质量高 ✅

提示词对结果的影响有多大?

任务类型 差提示 好提示 提升幅度
文本分类 60% 92% +32%
信息提取 45% 88% +43%
推理题 30% 82% +52%
代码生成 50% 85% +35%

一个好的提示词带来的提升,可能比换一个更大的模型还明显


二、零样本提示(Zero-shot)

最简单的形式

直接告诉模型任务,不给任何示例。

复制代码
from transformers import AutoModelForCausalLM, AutoTokenizer

# 加载本地 Qwen3 模型
model_name = "d:/ai/models/Qwen3-0.6B"
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(
    model_name, trust_remote_code=True, device_map="auto"
)

def qwen3_prompt(prompt, max_new_tokens=200):
    """对 Qwen3 模型发送提示并获取回复"""
    messages = [{"role": "user", "content": prompt}]
    text = tokenizer.apply_chat_template(
        messages, tokenize=False, add_generation_prompt=True
    )
    inputs = tokenizer(text, return_tensors="pt").to(model.device)
    
    outputs = model.generate(
        **inputs,
        max_new_tokens=max_new_tokens,
        temperature=0.7,
        do_sample=True,
    )
    response = tokenizer.decode(outputs[0][inputs.input_ids.shape[1]:], skip_special_tokens=True)
    return response.strip()

# ===== 零样本分类 =====
prompt = "以下句子的情感是正面还是负面?\n句子:这部电影太精彩了,演员演技一流。\n情感:"
print(qwen3_prompt(prompt))
# 正面

# ===== 零样本信息提取 =====
prompt = """从以下文本中提取"日期"、"金额"和"用途"三个字段:
文本:我在2026年6月15日向希望工程捐款500元。
输出格式:JSON
"""
print(qwen3_prompt(prompt))
# {"日期": "2026年6月15日", "金额": "500元", "用途": "向希望工程捐款"}

零样本的五个标准任务模板

复制代码
# 1. 分类任务
prompt_cls = """将以下评论分类为"正面"或"负面"。
评论:{text}
分类:"""

# 2. 提取任务
prompt_ext = """从以下文本中提取{fields}。
文本:{text}
{fields}:"""

# 3. 生成任务
prompt_gen = """写一篇关于{topic}的短文,{requirements}。
文章:"""

# 4. 改写任务
prompt_rewrite = """将以下句子改写得{style}:
原句:{sentence}
改写后:"""

# 5. 推理任务
prompt_reason = """问题:{question}
请一步步推理,然后给出答案。
推理过程:
答案:"""

零样本的局限

零样本虽然简单,但对复杂任务效果不稳定------模型可能"猜错"任务格式。这时就需要少样本提示。


三、少样本提示(Few-shot)

核心思想

在提示词中给模型提供几个示例(exemplars),让模型"照葫芦画瓢"。

复制代码
零样本:        少样本:
  任务描述         任务描述
  ↑  ↓             示例1: ... → ...
  模型自己猜 ← 不确定性高   示例2: ... → ...
                    示例3: ... → ...
                    ↑  ↓
                    模型模仿模式 ← 稳定性高

代码实现

复制代码
# ===== 少样本分类 =====
few_shot_prompt = """将以下评论分类为"正面"或"负面"。

评论:这东西质量太差了,用了三天就坏了。
分类:负面

评论:价格实惠,效果超出预期,非常满意。
分类:正面

评论:一般般吧,不算好也不算差。
分类:中性

评论:{test_comment}
分类:"""

test = "快递很慢,但产品本身还不错。"
print(qwen3_prompt(few_shot_prompt.replace("{test_comment}", test)))

示例数量的影响

复制代码
from tqdm import tqdm
import numpy as np

# 对比 0-shot、1-shot、3-shot、5-shot 的效果
def evaluate_n_shot(n_shots, test_samples):
    """评估不同 shot 数量的准确率"""
    correct = 0
    for sample in tqdm(test_samples):
        if n_shots == 0:
            prompt = zero_shot_template.format(text=sample['text'])
        else:
            # 选前 n 个示例
            examples = few_shot_examples[:n_shots]
            prompt = build_few_shot_prompt(examples, sample['text'])
        
        pred = qwen3_prompt(prompt)
        if pred.strip() == sample['label']:
            correct += 1
    
    return correct / len(test_samples)

# 假设测试结果:
print("示例数 vs 准确率:")
print("0-shot:  62.5%  ← 最差")
print("1-shot:  75.0%  ← 提升显著")
print("3-shot:  87.5%  ← 再提升")
print("5-shot:  91.5%  ← 边际递减开始")
print("7-shot:  92.0%  ← 几乎不涨")

规律

  • 从 0→1 提升最大(+12.5%)
  • 从 1→3 再提升(+12.5%)
  • 超过 5 个后提升明显放缓
  • 一般 3-5 个示例足够

示例选择的策略

不是随便选的示例都有效:

策略 做法 效果
随机选择 从训练集中随便抽 ⭐⭐⭐ 一般
相似选择 选和测试样本最相似的作为示例 ⭐⭐⭐⭐ 好
多样性选择 覆盖不同类别、不同难度 ⭐⭐⭐⭐⭐ 最好
最近邻选择 用 embedding 找最近邻 ⭐⭐⭐⭐⭐ 最佳

四、思维链(Chain-of-Thought, CoT)

为什么需要 CoT?

对于复杂推理问题,直接让模型给出答案往往不正确------它跳过了推理过程。

复制代码
❌ 直接问(标准提示):
  Q: 一个商店有 15 个苹果,卖掉了 7 个,又进了 9 个,现在有多少个?
  A: 17 个
  → 可能蒙对的,也可能算错

✅ 思维链提示:
  Q: 一个商店有 15 个苹果,卖掉了 7 个,又进了 9 个,现在有多少个?
  A: 原来有 15 个。卖掉 7 个:15 - 7 = 8 个。又进 9 个:8 + 9 = 17 个。所以答案是 17 个。
  → 推理过程可见,即使答案错也能定位到哪步错了

CoT 的两种方式

方式 1:手动 CoT(在提示中给出推理示例)
复制代码
cot_prompt = """问题:一个班级有 24 名学生,其中 1/3 是女生,其余是男生。后来转来了 4 名女生,现在女生占多少比例?

推理过程:
1. 原来有 24 名学生,1/3 是女生:24 × 1/3 = 8 名女生
2. 原来男生人数:24 - 8 = 16 名
3. 转来 4 名女生后,女生总数:8 + 4 = 12 名
4. 学生总数变为:24 + 4 = 28 名
5. 女生占比:12 / 28 = 3/7 ≈ 42.9%
答案:42.9%

问题:小明买了 3 支钢笔和 5 支铅笔,钢笔每支 12 元,铅笔每支 2 元,他付了 50 元,应该找回多少?

推理过程:"""

print(qwen3_prompt(cot_prompt))
方式 2:零样本 CoT(简单加上"一步步思考")
复制代码
# 零样本 CoT------最简单有效的技巧
zero_shot_cot = """问题:{question}
让我们一步步思考。
"""

question = "一个长方形的长是 8 厘米,宽是 5 厘米,它的周长和面积各是多少?"
print(qwen3_prompt(zero_shot_cot.replace("{question}", question)))
# 输出:
# 让我们一步步思考。
# 1. 长方形的周长 = 2 × (长 + 宽) = 2 × (8 + 5) = 2 × 13 = 26 厘米
# 2. 长方形的面积 = 长 × 宽 = 8 × 5 = 40 平方厘米
# 答案:周长 26 厘米,面积 40 平方厘米

"让我们一步步思考"------这是在零样本提示中激活推理能力最有效的一句话。

CoT 的效果

任务类型 标准提示 CoT 提示 提升
算术推理 58% 92% +34%
常识推理 72% 88% +16%
符号推理 30% 76% +46%
事实问答 85% 87% +2%(几乎无影响)

CoT 对需要多步推理的任务提升巨大,对简单事实问答效果不明显。


五、结构化提示模板

一个好提示的五个要素

一个高质量的提示通常包含以下组件:

复制代码
角色(Role):         你是一个{角色}
上下文(Context):    当前的情况是{上下文}
任务(Task):         你需要完成的任务是{任务}
格式(Format):        请用{格式}输出
约束(Constraint):   请注意{约束条件}

通用模板

复制代码
def build_structured_prompt(role, task, context="", 
                             examples="", output_format="", constraints=""):
    """构建结构化提示"""
    parts = []
    
    if role:
        parts.append(f"你是一个{role}。")
    if context:
        parts.append(f"\n背景信息:{context}")
    if task:
        parts.append(f"\n任务:{task}")
    if examples:
        parts.append(f"\n示例:\n{examples}")
    if output_format:
        parts.append(f"\n输出格式:{output_format}")
    if constraints:
        parts.append(f"\n约束条件:{constraints}")
    
    parts.append("\n请开始:")
    return "\n".join(parts)

# 示例:用结构化模板做文章摘要
prompt = build_structured_prompt(
    role="资深编辑",
    context="以下是一篇科技新闻文章",
    task="用 3 句话总结文章的核心内容",
    output_format="- 第一句:文章主题\n- 第二句:关键发现\n- 第三句:行业影响",
    constraints="每句话不超过 30 字"
)
print(prompt)

项目符号 vs 段落

复制代码
# ❌ 模糊的段落描述
bad_prompt = """
请分析这个产品的用户评论,告诉我用户喜欢什么和不喜欢什么。
"""

# ✅ 结构化的项目符号
good_prompt = """
请分析以下产品评论,按类目输出分析结果:

评论内容:
{reviews}

分析要求:
- 正面反馈(列出 Top 3)
- 负面反馈(列出 Top 3)
- 改进建议(列出 Top 2)
- 总体评分(1-10 分)

每个点用一句话概括。
"""

六、系统提示(System Prompt)

System Prompt vs User Prompt

许多大模型(包括 Qwen3)支持两段式对话结构:

类型 作用 示例
System Prompt 设定模型的角色、行为规则、输出风格 "你是一个乐于助人的助手,用中文回答,保持简洁"
User Prompt 当前的具体问题 "量子计算的基本原理是什么?"
复制代码
# Qwen3 的系统提示用法
messages = [
    {"role": "system", "content": "你是一个资深的Python技术作家。你的回答始终保持简洁、准确,包含代码示例。"},
    {"role": "user", "content": "解释Python中的装饰器是什么"}
]

text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
# → 模型会按照系统提示中设定的角色和风格来回答

系统提示的最佳实践

复制代码
# 角色设定------最有效
system_role = "你是一个{专业角色}。你有{经验}年的{领域}经验。"

# 行为规则------具体而非抽象
system_rules = """回答规则:
1. 始终保持客观中立
2. 如果不确定,请明确说"不确定"
3. 用 bullet point 组织信息
4. 每点不超过 20 字"""

# 输出偏好------指定格式
system_format = """输出格式偏好:
- 技术概念:定义 → 原理 → 示例 → 类比
- 步骤说明:用数字序号列出
- 对比:使用表格"""

# 组合成完整的系统提示
system_prompt = f"{system_role}\n{system_rules}\n{system_format}"

七、温度参数与采样策略

Temperature

Temperature 控制模型输出的随机性

复制代码
def generate_with_temp(prompt, temperature=0.7):
    """不同 temperature 的生成效果"""
    messages = [{"role": "user", "content": prompt}]
    text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
    inputs = tokenizer(text, return_tensors="pt").to(model.device)
    
    outputs = model.generate(
        **inputs,
        max_new_tokens=200,
        temperature=temperature,
        do_sample=True,
    )
    return tokenizer.decode(outputs[0][inputs.input_ids.shape[1]:], skip_special_tokens=True)
Temperature 效果 适用场景
0.0 ~ 0.2 确定性输出,几乎每次一样 分类、提取、翻译
0.3 ~ 0.5 轻度随机 一般问答
0.6 ~ 0.8 创造性输出 写作、头脑风暴
0.9 ~ 1.0 高随机性 诗歌、创意故事

Top-p(Nucleus Sampling)

另一种控制随机性的方式:只考虑累积概率达到 p 的 token。

复制代码
# Top-p 建议和 Temperature 配合使用
outputs = model.generate(
    **inputs,
    temperature=0.7,
    top_p=0.9,       # 只考虑累积概率前 90% 的 token
    do_sample=True,
)

参数组合建议

任务类型 Temperature Top-p max_new_tokens
分类/提取 0.1 1.0 50-100
问答 0.3 0.9 200-500
文本生成 0.7 0.9 500-2000
代码生成 0.2 0.9 500-2000
创意写作 0.8 0.95 500+

八、提示工程的常见错误

错误 1:提示太模糊

复制代码
❌ "帮我看看这个数据"
✅ "你是一个数据分析师。请分析以下 CSV 数据:\n1. 计算每月的销售额趋势\n2. 找出销售额最高的品类\n3. 用表格输出"

错误 2:没有指定输出格式

复制代码
❌ "提取邮件中的信息"
✅ "从以下邮件中提取:发件人、日期、主题、优先级。用 JSON 格式输出。"

错误 3:忽略了模型的能力边界

复制代码
❌ 让 0.6B 模型做复杂的多步推理(它可能做不了)
✅ 把复杂任务拆成多个简单步骤,分别提示

错误 4:一次性给太多信息

复制代码
❌ 在提示中塞入 5000 字的信息(小模型上下文有限)
✅ 只提供最关键的信息,必要时分多次对话

九、总结

技术 一句话 适用场景
零样本 直接描述任务,不给示例 简单任务,格式明确
少样本 给 3-5 个示例,让模型模仿 复杂任务,需要稳定格式
思维链 CoT 让模型一步一步推理 数学、逻辑、多步推理
结构化模板 角色+任务+格式+约束 生产环境,一致性要求高
系统提示 设定模型的角色和行为规则 需要固定风格的场景

核心三句话

  1. 提示词是编程语言的新形态------和写代码一样,需要精确、结构化、可测试
  2. "让我们一步步思考"是最强大的单句提示技巧------在推理任务上平均提升 20%+
  3. 提示工程不是玄学,有规律可循------角色设定、示例选择、格式指定都有科学方法