点我展开:基本信息
Prompt Engineering 是高效运用 llm 的技术,也是 agent 的核心基础,整体难度较低但具有非常重要地位。本文从基本编写方法入手,到前沿技术与重点应用进行记录,使得prompt engineering尽可能完善。
提示词基本编写原则
编写具体指令
原则一:编写清晰、具体的指令
编写清晰的指令不意味着简短的指令,因为在许多情况下,更长的提示实际上更清晰且提供了更多上下文,这实际上可能导致更详细更相关的输出。
- 策略一:使用分隔符清晰地表示输入的不同部分,分隔符可以是:```,””,<>,
,<\tag>等,以此避免输入里面可能包含其他指令,会覆盖掉原始的指令。 - 策略二:要求一个结构化的输出,可以是 Json、HTML 等格式,便于输出解析。
- 策略三:要求模型检查是否满足条件,如果任务做出的假设不一定满足,我们可以告诉模型先检查这些假设,如果不满足,指示并停止执行。还可以考虑一些潜在的边缘情况以及模型应该如何处理它们。
- 策略四:提供少量的示例,让它以某种语气风格进行回答。
# 例如:
text_1 = f"""
Making a cup of tea is easy! First, you need to get some \
water boiling. While that's happening, \
grab a cup and put a tea bag in it. Once the water is \
hot enough, just pour it over the tea bag. \
Let it sit for a bit so the tea can steep. After a \
few minutes, take out the tea bag. If you \
like, you can add some sugar or milk to taste. \
And that's it! You've got yourself a delicious \
cup of tea to enjoy.
"""
prompt = f"""
You will be provided with text delimited by triple quotes.
If it contains a sequence of instructions, \
re-write those instructions in the following format:
Step 1 - ...
Step 2 - …
…
Step N - …
If the text does not contain a sequence of instructions, \
then simply write \"No steps provided.\"
\"\"\"{text_1}\"\"\"
"""
response = get_completion(prompt)
print("Completion for Text 1:")
print(response)
zero-shot: 零样本学习,效率更高,节俭,对于有一定主观性任务效果不太好;
few-shot: 少样本学习,需要更多的token,对于主观性任务效果较好,可以通过示例学到倾向性,但是对示例的质量非常敏感。
原则二:给模型时间去思考
如果模型匆忙地得出了错误的结论,您应该尝试重新构思查询,请求模型在提供最终答案之前进行一系列相关的推理。
- 策略一:指定完成任务所需的步骤。列出步骤一、二、三,也可要求使用的格式。
- 策略二:指导模型在下结论之前找出一个自己的解法,例如对于数学问题,先让模型自己进行计算,之后再来与正确答案对比。
虚假知识:模型偶尔会生成一些看似真实实则编造的知识,例如对于某个品牌的产品,该品牌根本没有对应产品,模型却在看似合理的分点进行分析。
说明:示例使用 \ 来使文本适应屏幕大小以提高阅读体验,GPT 并不受 \ 的影响,但在调用其他大模型时,需额外考虑 \ 是否会影响模型性能
迭代优化
人工提示词迭代
以一个产品说明书->营销手册进行prompt迭代说明。
核心诉求:根据```标记的技术说明书中提供的信息,编写一个产品描述。
| 迭代版本 | 问题 | 解决方案 |
|---|---|---|
| 001 | 生成的回答太长且繁琐 | 限制输出长度 |
| 002 | 文本关注在错误的细节上 | 对其进行细节层面的限制、方向上的引导 |
| 003 | 需要一个表格形式的描述 | 添加上输出形式限制 |
注:上述迭代过程均需遵守前面的提示原则,核心是个人在对任务理解的基础上进行特定方向的修改,对于某些问题可以将该部分进行自动化迭代。
自动化提示词迭代
MENTAT提示词自动化迭代
文章链接:推理密集型回归
主要说明:针对于推理密集型回归问题,该文章提出了一种名为MENTAT的方法,可实现prompt的自动化迭代,生成优于人工调试出的提示词,核心想法是:分别建立一个错误分析助手、一个prompt迭代助手以及一份结构化的历史记录,在每轮迭代中,llm选择出当前损失最大的样本,将上述样本、历史记录以及当前提示词输入给错误分析助手,让其生成一份错误分析报告,之后将这份错误分析报告,历史记录,及当前prompt输入给prompt迭代助手,prompt迭代助手会根据历史记录及错误分析报告进行相应的改进。多轮迭代,生成较优的prompt。
相关项目链接:github由于涉及到私密数据集,该仓库为private,仅为个人记录,若需要可在blog主页任一平台联系我。
# 核心代码
class ErrorSampleDrivenPromptWordUpdate:
"""
Phase one:批量反思提升自动化,在每轮迭代中,使用当前提示词跑一轮训练集,收集性能最差的样本,提交给LLM写一份失败分析报告,再通过三个关键输入:当前指令、
失败分析报告、格式化的先前优化尝试的历史,输入给LLM进行指令调优。反复迭代,找到最小的NMSE,即为最优的提示词。
"""
# ============ 1. 任务初始提示 ============
BASIC_PROMPT_CONTINUOUS = {
"请逐步分析下面回答,根据打分标准,输出 0.0~100.0 之间的一个数字。要求**必须**输出详细的分析过程(推理过程),并在推理结束后**仅**用 '[SCORE] X.X' 格式给出最终分数,**分数必须在0.0到100.0之间**。\n"
}
BASIC_PROMPT_DISCRETE = {
"请逐步分析下面回答,根据打分标准,输出 0.0或100.0。要求**必须**输出详细的分析过程(推理过程),并在推理结束后**仅**用 '[SCORE] X.X' 格式给出最终分数,**分数必须为0.0或100.0,两者中的一个。**。\n"
}
# ============ 2. 评分系统提示 ============
RATING_SYS = (
"你是一位医疗诊断专家,请综合当前提示词,按要求进行评分。要求**必须**输出详细的分析过程(推理过程),并在推理结束后**仅**用 '[SCORE] X.X' 格式给出最终分数。\n"
"【格式警告】:如果输出结果中缺少推理过程或未包含 '[SCORE]' 标签,你的预测将被视为无效,并可能导致惩罚。请**严格**遵守格式要求,这是你唯一需要输出的内容。\n"
)
# ============ 3. 错误分报告系统提示 ============
ERROR_REPORT_SYS_A = (
"你是一位提示词诊断专家。\n"
"我会给你:1.当前指令;2.历史修改记录;3.绝对误差最大的**一批**案例信息(包含其回答、打分标准、预测值、真实值以及预测过程)。\n"
"分析给出的信息,**特别注意**分析最大误差案例中真实值得分的思路,指出当前提示词的主要缺陷和共同偏差。"
"并给出最关键的1~2条修改方向,不要输出新指令,只输出分析报告。"
)
ERROR_REPORT_SYS_B = (
"你是一位提示词诊断专家。\n"
"我会给你:1.当前指令;2.历史修改记录;3.绝对误差最大的**一批**案例信息(包含其回答、打分标准、预测值、真实值以及预测过程)。\n"
"分析给出的信息,**特别注意**分析最大误差案例中真实值得分的思路,指出当前提示词的主要缺陷和共同偏差。"
"并给出最关键的1~2条修改方向,不要输出新指令,只输出分析报告。"
"注意通过分析最大误差案例中真实值得分的思路,关注评分的严格性,后续调整方向可选择“宽松思路“或”严格思路“,或在两者之间适当选取平衡点。"
)
# ============ 4. 迭代系统提示 ============
REFINE_SYS = (
"你是一位提示词工程师。"
"我会给你:1.当前提示词、2.错误分析报告、3.历史修改记录"
"分析给出的信息,写出一份改进后的中文提示词,要求改正当前提示词的问题。"
"改进时要求考虑历史修改记录、错误分析报告以及当前提示词中的信息,使改进的提示词更加合理。"
"可适当增加示例以引导推理过程,示例必须有推理过程,**特别注意**示例不超过5条,若超过视为严重违反规则,示例数量要尽可能少且有代表性。"
"提示词可以按照分点的方式编写,只输出新提示词文本,不要任何解释。"
"注意:核心是写出通用推理的思路。"
)
推理密集型回归:通过一系列推理最终给出一个分数,例如通过参考答案对试卷进行打分,比较两篇作文的好坏,这里分为【原则+论述】,自动迭代的是打分要点(即打分标准)与打分思路,若任务已经存在打分要点(原则)后,模型可朝着特定方向去迭代打分思路,例如在一些主观考试题中,无法严格按照标准进行打分,打分会有一定的倾向性,该方法可以让模型学到这种倾向性。后续如何引到agent上面。
基本应用
文本概括
单一文本概括Prompt实验:例如在电商背景下,需要对海量商品评论进行概述,洞悉客户偏好。(也可应用于提取文本关键信息的场景)
- 限制输出文本长度。
- 关键角度侧重:针对不同的业务,对文本的侧重会有所不同。商品评论文本,物流会更关心运输时效,商家更加关心价格与商品质量,平台更关心整体服务体验。可以通过增加Prompt提示,来体现对于某个特定角度的侧重。例如,请对三个反引号之间的评论文本进行概括,最多30个词汇,并且聚焦在产品价格和质量上。
- 关键信息提取:区别于文本概括的角度侧重,需要将不想得到的信息进行过滤,在Prompt中进行特殊限制。例如,请从以下三个反引号之间的评论文本中提取产品运输相关的信息,最多30个词汇。
推断
对于许多文本分析类的任务,例如提取标签、提取实体、理解文本情感,可编写一个Prompt即可产生结果,不需要进行大量的工作。下列有一个较为典型的例子:
# 中文样例 lamp_review_zh = """ 我需要一盏漂亮的卧室灯,这款灯具有额外的储物功能,价格也不算太高。\ 我很快就收到了它。在运输过程中,我们的灯绳断了,但是公司很乐意寄送了一个新的。\ 几天后就收到了。这款灯很容易组装。我发现少了一个零件,于是联系了他们的客服,他们很快就给我寄来了缺失的零件!\ 在我看来,Lumina 是一家非常关心顾客和产品的优秀公司! """# 情感提取 prompt = f""" 以下用三个反引号分隔的产品评论的情感是什么? 评论文本: '''{lamp_review_zh}''' """ response = get_completion(prompt) print(response) #answer:积极的情感。# 识别情感类型 prompt = f""" 识别以下评论的作者表达的情感。包含不超过五个项目。将答案格式化为以逗号分隔的单词列表。 评论文本: '''{lamp_review_zh}''' """ response = get_completion(prompt) print(response) #answer:满意,感激,赞扬,信任,愉快。# 识别愤怒:极端情绪在某些场合非常重要。 prompt = f""" 以下评论的作者是否表达了愤怒?评论用三个反引号分隔。给出是或否的答案。 评论文本: '''{lamp_review_zh}''' """ response = get_completion(prompt) print(response) #answer:否# 从客户评论中提取产品和公司名称: prompt = f""" 从评论文本中识别以下项目: - 评论者购买的物品 - 制造该物品的公司 评论文本用三个反引号分隔。将你的响应格式化为以 “物品” 和 “品牌” 为键的 JSON 对象。 如果信息不存在,请使用 “未知” 作为值。 让你的回应尽可能简短。 评论文本: '''{lamp_review_zh}''' """ response = get_completion(prompt) print(response) #answer: { "物品": "卧室灯", "品牌": "Lumina" }# 可用一个Prompt满足上述多个需求: prompt = f""" 从评论文本中识别以下项目: - 情绪(正面或负面) - 审稿人是否表达了愤怒?(是或否) - 评论者购买的物品 - 制造该物品的公司 评论用三个反引号分隔。将您的响应格式化为 JSON 对象,以 “Sentiment”、“Anger”、“Item” 和 “Brand” 作为键。 如果信息不存在,请使用 “未知” 作为值。 让你的回应尽可能简短。 将 Anger 值格式化为布尔值。 评论文本: '''{lamp_review_zh}''' """ response = get_completion(prompt) print(response) #answer: { "Sentiment": "正面", "Anger": false, "Item": "卧室灯", "Brand": "Lumina" }# 推断主题 story_zh = """ 在政府最近进行的一项调查中,要求公共部门的员工对他们所在部门的满意度进行评分。 调查结果显示,NASA 是最受欢迎的部门,满意度为 95%。 一位 NASA 员工 John Smith 对这一发现发表了评论,他表示: “我对 NASA 排名第一并不感到惊讶。这是一个与了不起的人们和令人难以置信的机会共事的好地方。我为成为这样一个创新组织的一员感到自豪。” NASA 的管理团队也对这一结果表示欢迎,主管 Tom Johnson 表示: “我们很高兴听到我们的员工对 NASA 的工作感到满意。 我们拥有一支才华横溢、忠诚敬业的团队,他们为实现我们的目标不懈努力,看到他们的辛勤工作得到回报是太棒了。” 调查还显示,社会保障管理局的满意度最低,只有 45%的员工表示他们对工作满意。 政府承诺解决调查中员工提出的问题,并努力提高所有部门的工作满意度。 """ # 中文 prompt = f""" 确定以下给定文本中讨论的五个主题。 每个主题用1-2个单词概括。 输出时用逗号分割每个主题。 给定文本: '''{story_zh}''' """ response = get_completion(prompt) print(response) #answer: 调查结果, NASA, 社会保障管理局, 员工满意度, 政府承诺
文本转换
文本转换的常见功能有:文本翻译、拼写纠正、风格调整、格式转换。下列是一个综合样例:
text = f""" Got this for my daughter for her birthday cuz she keeps taking \ mine from my room. Yes, adults also like pandas too. She takes \ it everywhere with her, and it's super soft and cute. One of the \ ears is a bit lower than the other, and I don't think that was \ designed to be asymmetrical. It's a bit small for what I paid for it \ though. I think there might be other options that are bigger for \ the same price. It arrived a day earlier than expected, so I got \ to play with it myself before I gave it to my daughter. """prompt = f""" 针对以下三个反引号之间的英文评论文本, 首先进行拼写及语法纠错, 然后将其转化成中文, 再将其转化成优质淘宝评论的风格,从各种角度出发,分别说明产品的优点与缺点,并进行总结。 润色一下描述,使评论更具有吸引力。 输出结果格式为: 【优点】xxx 【缺点】xxx 【总结】xxx 注意,只需填写xxx部分,并分段输出。 将结果输出成Markdown格式。 ```{text}``` """ response = get_completion(prompt) display(Markdown(response)) #answer: 【优点】 超级柔软可爱,女儿生日礼物非常受欢迎。 成人也喜欢熊猫,我也很喜欢它。 提前一天到货,让我有时间玩一下。 【缺点】 一只耳朵比另一只低,不对称。 价格有点贵,但尺寸有点小,可能有更大的同价位选择。 【总结】 这只熊猫玩具非常适合作为生日礼物,柔软可爱,深受孩子喜欢。虽然价格有点贵,但尺寸有点小,不对称的设计也有点让人失望。如果你想要更大的同价位选择,可能需要考虑其他选项。总的来说,这是一款不错的熊猫玩具,值得购买。
文本扩展
# 定制客户邮件:根据客户评价和情感撰写自定义电子邮件响应。 # 我们可以在推理那章学习到如何对一个评论判断其情感倾向 sentiment = "negative" # 一个产品的评价 review = f""" 他们在11月份的季节性销售期间以约49美元的价格出售17件套装,折扣约为一半。\ 但由于某些原因(可能是价格欺诈),到了12月第二周,同样的套装价格全都涨到了70美元到89美元不等。\ 11件套装的价格也上涨了大约10美元左右。\ 虽然外观看起来还可以,但基座上锁定刀片的部分看起来不如几年前的早期版本那么好。\ 不过我打算非常温柔地使用它,例如,\ 我会先在搅拌机中将像豆子、冰、米饭等硬物研磨,然后再制成所需的份量,\ 切换到打蛋器制作更细的面粉,或者在制作冰沙时先使用交叉切割刀片,然后使用平面刀片制作更细/不粘的效果。\ 制作冰沙时,特别提示:\ 将水果和蔬菜切碎并冷冻(如果使用菠菜,则轻轻煮软菠菜,然后冷冻直到使用;\ 如果制作果酱,则使用小到中号的食品处理器),这样可以避免在制作冰沙时添加太多冰块。\ 大约一年后,电机发出奇怪的噪音,我打电话给客服,但保修已经过期了,所以我不得不再买一个。\ 总的来说,这些产品的总体质量已经下降,因此它们依靠品牌认可和消费者忠诚度来维持销售。\ 货物在两天内到达。 """ prompt = f""" 你是一位客户服务的AI助手。 你的任务是给一位重要客户发送邮件回复。 根据客户通过“```”分隔的评价,生成回复以感谢客户的评价。提醒模型使用评价中的具体细节 用简明而专业的语气写信。 作为“AI客户代理”签署电子邮件。 客户评论: ```{review}``` 评论情感:{sentiment} """ response = get_completion(prompt) print(response) #answer: 尊敬的客户, 非常感谢您对我们产品的评价。我们非常抱歉您在购买过程中遇到了价格上涨的问题。我们一直致力于为客户提供最优惠的价格,但由于市场波动,价格可能会有所变化。我们深表歉意,如果您需要任何帮助,请随时联系我们的客户服务团队。 我们非常感谢您对我们产品的详细评价和使用技巧。我们将会把您的反馈传达给我们的产品团队,以便改进我们的产品质量和性能。 再次感谢您对我们的支持和反馈。如果您需要任何帮助或有任何疑问,请随时联系我们的客户服务团队。 祝您一切顺利! AI客户代理# 使用温度系数:在温度为零时,每次执行相同的提示时,您应该期望获得相同的完成。而使用温度为0.7,则每次都会获得不同的输出。在更高的温度下,助手更易分心,但也许更有创造力。 response = get_completion(prompt, temperature=0.7) print(response)
Prompt Engineering 构建评价器
可通过自动化提示词迭代,对特定任务生成相关提示词,进行推理密集型回归的预测,离散的与连续的任务在设定上略有不同,在得到较好提示词后,可根据自一致性原则,在同一提示词下多做几次预测,对连续的剔除异常值后取平均,对离散的取众数。
强相关项目链接:x

