提示词工程(Prompt Engineering)从入门到实战——课程笔记
目录
一、什么是提示词工程
1.1 定义
提示词(Prompt) 是用户提供给 AI 模型的输入指令,用于引导其生成特定输出。
提示词工程(Prompt Engineering) 则是设计、优化这些指令的系统化过程,旨在提升模型输出的准确性、相关性和可用性。
简单来说:你对 AI 说什么、怎么说,直接决定了 AI 给你的回答质量。提示词工程就是研究"怎么说才能得到最好的回答"。
1.2 核心价值
| 价值维度 | 说明 |
|---|---|
| 降低幻觉(Hallucination) | 通过明确约束和上下文限定,减少 AI "胡编乱造"的概率 |
| 提升效率 | 减少反复迭代的次数,一次性获得可用结果 |
| 解锁潜能 | 引导模型完成复杂推理、创意生成、代码编写等高阶任务 |
| 保证一致性 | 在批量处理场景中,通过标准化提示词确保输出格式和质量的一致性 |
| 降低使用门槛 | 不需要微调模型,通过自然语言即可定制模型行为 |
1.3 提示词工程的发展背景
提示词工程之所以成为一门独立的"工程学科",有几个关键背景:
- 大模型能力涌现:GPT-3、ChatGPT 等模型的出现,使得同一个模型在不同提示词下可以表现出截然不同的能力。
- 从微调到提示的范式转变:早期 NLP 任务需要针对每个任务训练专门的模型;现在通过精心设计的提示词,一个通用模型就能完成多种任务。
- API 经济:调用大模型 API 已成为主流开发方式,提示词就是开发者与模型之间的"编程语言"。
二、提示词的基本结构
一个完整的 Prompt,一般包含以下六个核心组成部分:
2.1 角色(Role)
作用:定义"模型是谁",框定回答的身份和视角。
你是一名资深客服分析专家
角色设定会影响模型的语气、用词、知识范围和回答风格。后面第四章会详细展开。
2.2 任务(Task)
作用:告诉模型"要做什么",是提示词的核心指令。
请对用户工单进行分类
任务描述应尽量具体、明确、无歧义。避免模糊指令如"帮我处理一下这个",而应写成"请将以下用户反馈按照退款/物流/商品三类进行分类"。
2.3 输入(Input)
作用:提供模型需要处理的数据或上下文。
用户问题:我退款怎么还没到账
输入可以是文本、表格、代码片段、对话记录等。关键是要和任务描述清晰对应。
2.4 输出格式(Output Format)
作用:规定输出"长什么样",让结果可预期、可解析。
常见输出格式:
| 格式 | 适用场景 |
|---|---|
| JSON | 后端系统解析、API 集成 |
| Markdown | 文档生成、内容展示 |
| HTML | 前端页面渲染 |
| XML | 结构化数据交换 |
| 纯文本/大白话 | 面向普通用户的回答 |
| 列表 | 分类汇总、要点罗列 |
2.5 约束(Constraint)
作用:限制模型行为,防止输出超出预期范围。
不要编造信息,只能基于输入判断,只能输出20个字,不能输出违禁词
约束是控制模型"不做什么"的关键手段,尤其在生产环境中非常重要。
2.6 示例(Example)
作用:给模型"参考答案",帮助它理解你期望的输出形式和标准。
示例的提供与否,衍生出了 Zero-shot(不给示例)和 Few-shot(给少量示例)两种重要策略,后文会详细讲解。
2.7 完整提示词示例与代码
将以上六个部分组合,形成一个完整的提示词:
import os
from openai import OpenAI
from dotenv import load_dotenv
project_root_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
env_path = os.path.join(project_root_path, ".env")
load_dotenv(env_path)
MODEL_API_KEY = os.getenv("MODEL_API_KEY")
MODEL_BASE_URL = os.getenv("MODEL_BASE_URL")
MODEL_NAME = os.getenv("MODEL_NAME")
client = OpenAI(
api_key=MODEL_API_KEY,
base_url=MODEL_BASE_URL
)
def process_work_classify(user_input):
user_prompt = f"""
你是一名资深客服分析专家。
任务:
对用户工单进行分类。
分类标签:
- 退款问题
- 物流问题
- 商品问题
输入:
用户问题:{user_input}
输出要求:
以 JSON 格式返回:
{{
"category": ""
}}
"""
response = client.chat.completions.create(
model=MODEL_NAME,
messages=[
{"role": "user", "content": user_prompt},
],
stream=False
)
return response.choices[0].message.content
if __name__ == '__main__':
print(process_work_classify("我的商品没有收到"))
结构拆解对照:
| 结构部分 | 对应内容 |
|---|---|
| 角色 | 你是一名资深客服分析专家 |
| 任务 | 对用户工单进行分类 |
| 输入 | 用户问题:{user_input} |
| 输出格式 | 以 JSON 格式返回 |
| 约束 | 只能从给定的三个标签中选 |
| 示例 | (本例未提供,属于 Zero-shot) |
三、提示词核心技巧
3.1 角色设定(Role Prompting)
不同角色设定会让模型的输出风格完全不同:
| 角色设定 | 输出特点 |
|---|---|
| 客服 | 语气温和、礼貌,注重解决方案 |
| 数据分析师 | 理性、客观,注重数据和逻辑 |
| 教师 | 循循善诱,善于举例和类比 |
| 律师 | 严谨、条理清晰,引用条款 |
| 段子手 | 幽默、夸张,善用反转 |
使用建议:角色设定不是越花哨越好,关键是与任务匹配。一个数据分类任务不需要设定"你是一个海盗",但一个儿童教育场景设定"你是一位耐心的小学老师"就很有效。
3.2 约束控制
约束控制是提示词工程中最容易被忽视、但生产环境中最重要的环节。
常见约束类型:
1. 事实约束:不要编造信息,不确定请返回"无法判断"
2. 范围约束:只从给定内容中回答,不要引入外部知识
3. 长度约束:回答不超过100字 / 只输出一个标签
4. 格式约束:只输出JSON,不要附加说明文字
5. 安全约束:不输出违禁词、不生成有害内容
实用技巧:对于关键业务场景,约束应配合程序校验(如 json.loads() 校验、正则匹配),不能完全依赖提示词本身。模型偶尔会"忘记"约束,程序兜底是工程化必备手段。
3.3 Zero-shot(零样本)
定义:不提供任何示例,直接让模型执行任务。
适用场景:任务简单明确、模型本身已具备相关能力。
代码示例:
import os
from openai import OpenAI
from dotenv import load_dotenv
env_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), ".env")
load_dotenv(env_path)
MODEL_API_KEY = os.getenv("MODEL_API_KEY")
MODEL_BASE_URL = os.getenv("MODEL_BASE_URL")
MODEL_NAME = os.getenv("MODEL_NAME")
client = OpenAI(api_key=MODEL_API_KEY, base_url=MODEL_BASE_URL)
def llm_response(user_prompt):
response = client.chat.completions.create(
model=MODEL_NAME,
messages=[{"role": "user", "content": user_prompt}],
stream=False,
max_tokens=1024,
temperature=0.7
)
return response.choices[0].message.content
def zero_shot_sentiment(text: str) -> str:
"""Zero-shot 情感分析:仅任务说明,无样例。"""
prompt = f"""你是文本情感分析助手。
任务:判断下面这句话的情感倾向,只能从以下标签中选一个:正面、负面、中性。
待分析文本:{text}
输出要求:只输出一个标签,不要解释。"""
return llm_response(prompt)
if __name__ == "__main__":
user_text = "这家店的包装很用心,但配送比预计慢了一天。"
print(zero_shot_sentiment(user_text))
优点:提示词简洁,token 消耗少,适合简单任务。 局限:对于复杂分类边界、特殊格式要求,效果可能不稳定。
3.4 Few-shot(少样本)
定义:在提示词中提供少量示例(通常 2~5 个),让模型"模仿"示例的模式来完成任务。
适用场景:分类任务、风格控制、格式对齐、边界模糊的判断。
代码示例:
import os
from openai import OpenAI
from dotenv import load_dotenv
env_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), ".env")
load_dotenv(env_path)
MODEL_API_KEY = os.getenv("MODEL_API_KEY")
MODEL_BASE_URL = os.getenv("MODEL_BASE_URL")
MODEL_NAME = os.getenv("MODEL_NAME")
client = OpenAI(api_key=MODEL_API_KEY, base_url=MODEL_BASE_URL)
def llm_response(user_prompt):
response = client.chat.completions.create(
model=MODEL_NAME,
messages=[{"role": "user", "content": user_prompt}],
stream=False,
max_tokens=1024,
temperature=0.7
)
return response.choices[0].message.content
def few_shot_intent(user_text: str) -> str:
few_shot_prompt = f"""
你是电商客服对话的意图识别助手。
任务:
根据用户一句话判断意图,只能从以下标签中选一个:
查询物流、申请退款、咨询商品、其他
模仿下面格式(每段两行:用户:... 意图:...):
用户:我的快递到哪了?
意图:查询物流
用户:这件衣服洗一次就起球了,我要退钱。
意图:申请退款
用户:这款耳机防水吗?
意图:咨询商品
用户:今天天气不错。
意图:其他
现在只对新的一句话分类,同样输出两行「用户:」「意图:」:
用户:{user_text}
意图:
"""
return llm_response(few_shot_prompt)
if __name__ == "__main__":
user_text = "上周买的鞋子码数偏小,能换大一码吗?"
print(few_shot_intent(user_text))
Few-shot 的设计要点:
| 要点 | 说明 |
|---|---|
| 示例数量 | 通常 2~5 个即可,过多会浪费 token |
| 覆盖边界 | 示例应覆盖各类别,尤其是容易混淆的边界情况 |
| 格式一致 | 所有示例的格式必须严格一致,模型会模仿格式 |
| 多样性 | 同一类别的示例尽量用不同的表述方式 |
3.5 Chain of Thought(思维链,CoT)
定义:在提示词中要求模型"一步一步思考",先展示推理过程,再给出最终结论。
核心原理:2022 年 Google Research 团队(Jason Wei 等人)在论文 "Chain-of-Thought Prompting Elicits Reasoning in Large Language Models" 中提出,通过在提示中加入中间推理步骤,可以显著提升大模型在算术、常识推理和符号推理等任务上的表现。
适用场景:
- 数学应用题
- 逻辑推理
- 多步骤决策
- 复杂分类(需要层层判断)
代码示例:
import os
from openai import OpenAI
from dotenv import load_dotenv
env_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), ".env")
load_dotenv(env_path)
MODEL_API_KEY = os.getenv("MODEL_API_KEY")
MODEL_BASE_URL = os.getenv("MODEL_BASE_URL")
MODEL_NAME = os.getenv("MODEL_NAME")
client = OpenAI(api_key=MODEL_API_KEY, base_url=MODEL_BASE_URL)
def llm_response(user_prompt: str, max_tokens: int = 1024) -> str:
response = client.chat.completions.create(
model=MODEL_NAME,
messages=[{"role": "user", "content": user_prompt}],
stream=False,
max_tokens=max_tokens,
temperature=0.7,
)
return response.choices[0].message.content
def cot_word_problem(question: str) -> str:
"""Chain-of-Thought:要求模型先分步推理,再给出最终答案。"""
prompt = f"""你是一名擅长应用题解析的助教。
任务:
下面是一道应用题。请先「逐步写出推理过程」(可用「步骤1」「步骤2」等形式),
把每一步用到的数字和运算关系说清楚;推理结束后,最后一行单独写:
最终答案:<一个简洁结论,例如具体金额或数字>
要求:
- 推理过程与最终答案都要完整;
- 最终答案那一行必须以「最终答案:」开头。
题目:
{question}
"""
return llm_response(prompt, max_tokens=2048)
if __name__ == "__main__":
q = (
"书店促销:某书原价每本 45 元。小明买 3 本可享总价 8 折,"
"结账时还能再使用一张「满 100 减 10」的优惠券(先打折后满减)。"
"小明实际需要支付多少元?"
)
print(cot_word_problem(q))
CoT 的两种触发方式:
| 方式 | 说明 | 示例 |
|---|---|---|
| Zero-shot CoT | 不给示例,只加一句引导语 | "请一步一步思考"、"Let's think step by step" |
| Few-shot CoT | 给出示例,示例本身包含推理过程 | 示例中展示"步骤1→步骤2→结论"的完整链路 |
补充说明:Zero-shot CoT 的有效性由 Kojima 等人在 2022 年论文 "Large Language Models are Zero-Shot Reasoners" 中验证,仅需在提示末尾添加 "Let's think step by step" 就能在多个推理基准上获得显著提升。
3.6 结构化输出(JSON)
定义:要求模型按照严格的 JSON 格式输出,便于后端系统直接解析。
适用场景:API 集成、数据管道、批量处理、与下游系统对接。
代码示例:
import json
import os
from typing import Any
from dotenv import load_dotenv
from openai import OpenAI
env_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), ".env")
load_dotenv(env_path)
MODEL_API_KEY = os.getenv("MODEL_API_KEY")
MODEL_BASE_URL = os.getenv("MODEL_BASE_URL")
MODEL_NAME = os.getenv("MODEL_NAME")
client = OpenAI(api_key=MODEL_API_KEY, base_url=MODEL_BASE_URL)
def llm_json_response(user_prompt: str, max_tokens: int = 1024) -> str:
"""要求模型只输出合法 JSON 对象。"""
response = client.chat.completions.create(
model=MODEL_NAME,
messages=[{"role": "user", "content": user_prompt}],
stream=False,
max_tokens=max_tokens,
temperature=0.3,
response_format={"type": "json_object"},
)
return response.choices[0].message.content
def classify_ticket_json(user_issue: str) -> dict[str, Any]:
"""
将用户工单打成结构化 JSON,并在本地 json.loads 校验。
若网关不支持 json_object,可把 response_format 一行去掉,仅靠提示约束。
"""
prompt = f"""你是一名客服工单分析助手。请根据用户描述,输出一个 JSON 对象
(不要 markdown 代码块,不要多余说明文字)。
JSON 的键必须严格如下,类型与取值说明:
- "category": 字符串,只能是 "退款问题" | "物流问题" | "商品问题" | "其他"
- "confidence": 数字,0 到 1 之间,表示你对分类的把握
- "summary": 字符串,一句话概括用户诉求(不超过 50 字)
用户工单:
{user_issue}
"""
raw = llm_json_response(prompt)
return json.loads(raw)
if __name__ == "__main__":
issue = "上周买的鞋子码数偏小,能换大一码吗?运费谁出?"
data = classify_ticket_json(issue)
print(json.dumps(data, ensure_ascii=False, indent=2))
关键细节:
temperature建议设低(0.1~0.3),减少随机性,输出更稳定。response_format={"type": "json_object"}是 OpenAI 官方提供的 JSON 模式,部分国产模型可能不支持此参数,此时仅靠提示约束即可。- 务必在代码层做
json.loads()校验,作为兜底,因为模型偶尔会输出不合法的 JSON(如多余逗号、markdown 包裹等)。
3.7 其他常用技巧补充
除了上述核心技巧外,以下几种方法在实际项目中也经常用到:
(1)Self-Consistency(自一致性)
对同一个问题让模型多次回答(通过设置较高 temperature 或多次调用),取多数投票的结果。适用于对准确性要求高的分类和推理任务。
(2)ReAct(Reasoning + Acting)
由 Yao 等人在 2022 年提出,让模型交替进行"思考"和"行动"(如调用工具、搜索信息),是 Agent 架构的提示词基础。典型格式:
Thought: 我需要查询该订单的物流状态
Action: search_order_logistics(order_id="12345")
Observation: 订单已到达北京分拣中心
Thought: 根据物流信息,我来回答用户
Answer: 您的包裹目前已到达北京分拣中心,预计明天送达。
(3)提示词模板化
在工程实践中,提示词应模板化管理,而非硬编码在代码中。推荐做法:
- 使用 Jinja2、f-string 等模板引擎
- 将提示词模板独立为
.txt或.jinja2文件 - 变量部分通过参数注入,方便版本管理和 A/B 测试
四、角色提示词详解
4.1 三种消息角色
调用对话式接口时,请求中的 messages 每条都有 role 字段,用来区分这段话是谁说的。必须掌握三种核心角色:
(1)system(系统提示词)
- 位置:放在 messages 最前面。
- 内容:写相对稳定的设定——身份、规则、语气、输出格式等。
- 注意:具体某条工单、某句待分类的原文更适合放在
user中,不要塞进system。否则每条业务数据都要改system,难维护也浪费 token。
{
"role": "system",
"content": "你是电商客服助手。回答不超过三句话,语气礼貌;若涉及赔偿或法律问题,请建议用户联系人工客服。"
}
(2)user(用户输入)
- 内容:用户输入的内容,或程序拼出来的"任务说明 + 数据"。
- 灵活度:一轮可以有多条
user,常与assistant交替。最后一条user往往是本次要模型回答的内容。 - 说明:任务说明和示例也可以全部写在一个长
user里;若拆成多条user/assistant,在模型眼里更像"有轮次的对话",便于实现对话式 Few-shot。
(3)assistant(助手回复)
- 内容:模型上一轮已经生成的回复。下一轮请求里带上,多轮才有上下文。
- 特殊用法:也可以人工写一条
assistant当标准答案,前面配user当例题,用来教格式或定义分类边界——这正是对话式 Few-shot 的原理。
4.2 三种角色的配合方式
习惯做法:system 在最前,后面 user 与 assistant 交替。新请求里带上此前相关轮次(注意 token 上限),再追加最新的 user。
一句话概括:system 定规矩,user 给当前输入,assistant 是模型说过的话或你给的示范。
┌──────────────────────────────────────────────┐
│ messages: │
│ ┌────────────────────────────────────────┐ │
│ │ system: 你是客服助手,回答简短礼貌 │ │
│ ├────────────────────────────────────────┤ │
│ │ user: 支持7天无理由退货吗? │ │
│ ├────────────────────────────────────────┤ │
│ │ assistant: 支持。签收次日起7天内... │ │
│ ├────────────────────────────────────────┤ │
│ │ user: 那运费谁承担? ← 当前问题 │ │
│ └────────────────────────────────────────┘ │
└──────────────────────────────────────────────┘
注意事项:
- 1.在 LangChain 里常写成
SystemMessage、HumanMessage、AIMessage,含义与上面三种role完全一致。 - 2.
system并非绝对约束,重要规则可配合格式约定或程序校验。单次任务说明(如"只输出标签")有人放user顶部、有人放system,团队内部统一即可。 - 3.部分模型对
system的遵从度不同。一般来说,参数量越大的模型对system的遵从度越高。
4.3 代码实现
(1)多轮对话基础示例(OpenAI SDK)
import os
from typing import Any
from dotenv import load_dotenv
from openai import OpenAI
env_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), ".env")
load_dotenv(env_path)
MODEL_API_KEY = os.getenv("MODEL_API_KEY")
MODEL_BASE_URL = os.getenv("MODEL_BASE_URL")
MODEL_NAME = os.getenv("MODEL_NAME")
client = OpenAI(api_key=MODEL_API_KEY, base_url=MODEL_BASE_URL)
def chat(messages: list[dict[str, Any]], max_tokens: int = 1024, temperature: float = 0.7) -> str:
"""messages 为 OpenAI 格式:[{"role": "system"|"user"|"assistant", "content": "..."}, ...]"""
response = client.chat.completions.create(
model=MODEL_NAME,
messages=messages,
stream=False,
max_tokens=max_tokens,
temperature=temperature,
)
return response.choices[0].message.content
def demo_system_and_user() -> str:
"""system 定规则 + user 提问题(最常用组合)。"""
messages = [
{
"role": "system",
"content": (
"你是电商客服助手。回答不超过三句话,语气礼貌;"
"若涉及赔偿或法律问题,请建议用户联系人工客服。"
),
},
{"role": "user", "content": "我的快递显示已签收但我没收到货,怎么办?"},
]
return chat(messages)
def demo_multi_turn_with_assistant() -> str:
"""
多轮:必须把上一轮的 assistant 内容放进 messages,再接新的 user。
这里 assistant 内容模拟「上一轮模型已说过的话」。
"""
messages = [
{
"role": "system",
"content": "你是电商客服助手,回答简短。",
},
{"role": "user", "content": "你们支持 7 天无理由退货吗?"},
{
"role": "assistant",
"content": "支持。签收次日起 7 天内,商品未使用且吊牌完好可申请无理由退货。",
},
{"role": "user", "content": "那运费谁承担?"},
]
return chat(messages)
if __name__ == "__main__":
print("=== 示例 1:system + user ===")
print(demo_system_and_user())
print()
print("=== 示例 2:system + user + assistant + user(多轮追问)===")
print(demo_multi_turn_with_assistant())
(2)对话式 Few-shot(OpenAI SDK)
import os
from typing import Any
from dotenv import load_dotenv
from openai import OpenAI
env_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), ".env")
load_dotenv(env_path)
MODEL_API_KEY = os.getenv("MODEL_API_KEY")
MODEL_BASE_URL = os.getenv("MODEL_BASE_URL")
MODEL_NAME = os.getenv("MODEL_NAME")
client = OpenAI(api_key=MODEL_API_KEY, base_url=MODEL_BASE_URL)
def chat(messages: list[dict[str, Any]], max_tokens: int = 256, temperature: float = 0.3) -> str:
response = client.chat.completions.create(
model=MODEL_NAME,
messages=messages,
stream=False,
max_tokens=max_tokens,
temperature=temperature,
)
return response.choices[0].message.content
def few_shot_intent_via_messages(user_text: str) -> str:
"""
用 user/assistant 交错给出示例,最后一条 user 为真实待分类句子。
assistant 只输出意图标签。
"""
system = """你是电商客服意图识别助手。
用户会发来一句话,你只输出一个意图标签,不要解释。
标签只能是:查询物流、申请退款、咨询商品、其他。"""
shot_pairs = [
("我的快递到哪了?", "查询物流"),
("这件衣服洗一次就起球了,我要退钱。", "申请退款"),
("这款耳机防水吗?", "咨询商品"),
("今天天气不错。", "其他"),
]
messages: list[dict[str, Any]] = [{"role": "system", "content": system}]
for u, a in shot_pairs:
messages.append({"role": "user", "content": u})
messages.append({"role": "assistant", "content": a})
messages.append({"role": "user", "content": user_text})
return chat(messages)
if __name__ == "__main__":
sample = "上周买的鞋子码数偏小,能换大一码吗?"
print("待分类:", sample)
print("模型输出:", few_shot_intent_via_messages(sample))
对比两种 Few-shot 写法:将示例写在一个长
user里 vs. 用user/assistant交替。后者更贴近对话场景,模型理解起来更自然,但会多消耗一些 token。
(3)LangChain 实现多轮对话
import os
from dotenv import load_dotenv
from langchain_core.messages import AIMessage, HumanMessage, SystemMessage
from langchain_openai import ChatOpenAI
env_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), ".env")
load_dotenv(env_path)
MODEL_API_KEY = os.getenv("MODEL_API_KEY")
MODEL_BASE_URL = os.getenv("MODEL_BASE_URL")
MODEL_NAME = os.getenv("MODEL_NAME")
llm = ChatOpenAI(
api_key=MODEL_API_KEY,
base_url=MODEL_BASE_URL,
model=MODEL_NAME,
temperature=0.7,
max_tokens=1024,
)
def demo_system_and_user() -> str:
"""system 定规则 + user 提问题。"""
messages = [
SystemMessage(
content=(
"你是电商客服助手。回答不超过三句话,语气礼貌;"
"若涉及赔偿或法律问题,请建议用户联系人工客服。"
)
),
HumanMessage(content="我的快递显示已签收但我没收到货,怎么办?"),
]
return llm.invoke(messages).content
def demo_multi_turn_with_assistant() -> str:
"""多轮:含上一轮 assistant(AIMessage),再接新的 user。"""
messages = [
SystemMessage(content="你是电商客服助手,回答简短。"),
HumanMessage(content="你们支持 7 天无理由退货吗?"),
AIMessage(
content="支持。签收次日起 7 天内,商品未使用且吊牌完好可申请无理由退货。"
),
HumanMessage(content="那运费谁承担?"),
]
return llm.invoke(messages).content
if __name__ == "__main__":
print("=== 示例 1:SystemMessage + HumanMessage ===")
print(demo_system_and_user())
print()
print("=== 示例 2:System + Human + AIMessage + Human(多轮追问)===")
print(demo_multi_turn_with_assistant())
LangChain 角色映射:
SystemMessage= system,HumanMessage= user,AIMessage= assistant。
五、提示词工程的最佳实践与常见误区
最佳实践
| 实践 | 说明 |
|---|---|
| 先简后繁 | 先用最简单的提示词测试,确认基本能力后再逐步添加角色、约束、示例 |
| 迭代优化 | 提示词不是一次写好的,需要根据输出不断调整 |
| 版本管理 | 对提示词做版本控制,记录每次修改和效果变化 |
| 程序兜底 | 关键场景用代码校验输出格式,不能完全依赖提示词约束 |
| 关注 token | 提示词越长,消耗的 token 越多,成本越高,响应越慢 |
| 测试边界 | 用极端输入和边界情况测试提示词的鲁棒性 |
常见误区
| 误区 | 正确做法 |
|---|---|
| 提示词越长越好 | 精准比冗长更有效,无关信息反而会干扰模型 |
| 只测一条就上线 | 应该用多条不同输入进行批量测试 |
| 所有任务都用 CoT | 简单任务用 CoT 反而可能降低效率、增加错误 |
| 完全信任模型输出 | 生产环境必须有程序校验和异常处理 |
| system 能硬性约束一切 | system 是"软约束",模型偶尔会偏离,关键规则需配合程序校验 |
| 忽视 temperature 参数 | 任务越需要确定性,temperature 应设越低(分类任务建议 0.1~0.3) |
六、本节总结
- 提示词工程的本质是"用输入控制输出"——你不需要改模型,只需要改你对模型说的话。
- 一个好的 Prompt = 角色 + 任务 + 输入 + 输出格式 + 约束 +(可选)示例。
- Few-shot 和 CoT 是提升效果的两大关键手段——前者解决"格式和边界"问题,后者解决"推理深度"问题。
- 结构化输出(JSON)是工程化落地的必备技巧——配合
response_format和程序校验使用。 - 三种消息角色(system / user / assistant)的合理配合,是实现多轮对话和对话式 Few-shot 的基础。
- 提示词需要不断调试和演化——没有一劳永逸的"完美提示词",只有不断迭代的"更优提示词"。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)