点我展开:基本信息

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.\"

\"\"\"&#123;text_1&#125;\"\"\"
"""
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 = &#123;
        "请逐步分析下面回答,根据打分标准,输出 0.0~100.0 之间的一个数字。要求**必须**输出详细的分析过程(推理过程),并在推理结束后**仅**用 '[SCORE] X.X' 格式给出最终分数,**分数必须在0.0到100.0之间**。\n"
    &#125;

    BASIC_PROMPT_DISCRETE = &#123;
        "请逐步分析下面回答,根据打分标准,输出 0.0或100.0。要求**必须**输出详细的分析过程(推理过程),并在推理结束后**仅**用 '[SCORE] X.X' 格式给出最终分数,**分数必须为0.0或100.0,两者中的一个。**。\n"
    &#125;

    # ============  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"""
    识别以下评论的作者表达的情感。包含不超过五个项目。将答案格式化为以逗号分隔的单词列表。
    
    评论文本: '''&#123;lamp_review_zh&#125;'''
    """
    response = get_completion(prompt)
    print(response)
    
    #answer:满意,感激,赞扬,信任,愉快。
    
  • # 识别愤怒:极端情绪在某些场合非常重要。
    prompt = f"""
    以下评论的作者是否表达了愤怒?评论用三个反引号分隔。给出是或否的答案。
    
    评论文本: '''&#123;lamp_review_zh&#125;'''
    """
    response = get_completion(prompt)
    print(response)
    
    #answer:否
    
  • # 从客户评论中提取产品和公司名称:
    prompt = f"""
    从评论文本中识别以下项目:
    - 评论者购买的物品
    - 制造该物品的公司
    
    评论文本用三个反引号分隔。将你的响应格式化为以 “物品” 和 “品牌” 为键的 JSON 对象。
    如果信息不存在,请使用 “未知” 作为值。
    让你的回应尽可能简短。
      
    评论文本: '''&#123;lamp_review_zh&#125;'''
    """
    response = get_completion(prompt)
    print(response)
    
    #answer:
    &#123;
      "物品": "卧室灯",
      "品牌": "Lumina"
    &#125;
    
  • # 可用一个Prompt满足上述多个需求:
    prompt = f"""
    从评论文本中识别以下项目:
    - 情绪(正面或负面)
    - 审稿人是否表达了愤怒?(是或否)
    - 评论者购买的物品
    - 制造该物品的公司
    
    评论用三个反引号分隔。将您的响应格式化为 JSON 对象,以 “Sentiment”、“Anger”、“Item” 和 “Brand” 作为键。
    如果信息不存在,请使用 “未知” 作为值。
    让你的回应尽可能简短。
    将 Anger 值格式化为布尔值。
    
    评论文本: '''&#123;lamp_review_zh&#125;'''
    """
    response = get_completion(prompt)
    print(response)
    
    #answer:
    &#123;
        "Sentiment": "正面",
        "Anger": false,
        "Item": "卧室灯",
        "Brand": "Lumina"
    &#125;
    
  • # 推断主题
    story_zh = """
    在政府最近进行的一项调查中,要求公共部门的员工对他们所在部门的满意度进行评分。
    调查结果显示,NASA 是最受欢迎的部门,满意度为 95%。
    
    一位 NASA 员工 John Smith 对这一发现发表了评论,他表示:
    “我对 NASA 排名第一并不感到惊讶。这是一个与了不起的人们和令人难以置信的机会共事的好地方。我为成为这样一个创新组织的一员感到自豪。”
    
    NASA 的管理团队也对这一结果表示欢迎,主管 Tom Johnson 表示:
    “我们很高兴听到我们的员工对 NASA 的工作感到满意。
    我们拥有一支才华横溢、忠诚敬业的团队,他们为实现我们的目标不懈努力,看到他们的辛勤工作得到回报是太棒了。”
    
    调查还显示,社会保障管理局的满意度最低,只有 45%的员工表示他们对工作满意。
    政府承诺解决调查中员工提出的问题,并努力提高所有部门的工作满意度。
    """
    
    # 中文
    prompt = f"""
    确定以下给定文本中讨论的五个主题。
    
    每个主题用1-2个单词概括。
    
    输出时用逗号分割每个主题。
    
    给定文本: '''&#123;story_zh&#125;'''
    """
    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格式。
    ```&#123;text&#125;```
    """
    response = get_completion(prompt)
    display(Markdown(response))
    
    #answer:
    【优点】
    超级柔软可爱,女儿生日礼物非常受欢迎。
    成人也喜欢熊猫,我也很喜欢它。
    提前一天到货,让我有时间玩一下。
    【缺点】
    一只耳朵比另一只低,不对称。
    价格有点贵,但尺寸有点小,可能有更大的同价位选择。
    【总结】 这只熊猫玩具非常适合作为生日礼物,柔软可爱,深受孩子喜欢。虽然价格有点贵,但尺寸有点小,不对称的设计也有点让人失望。如果你想要更大的同价位选择,可能需要考虑其他选项。总的来说,这是一款不错的熊猫玩具,值得购买。 
    

文本扩展

  • # 定制客户邮件:根据客户评价和情感撰写自定义电子邮件响应。
    # 我们可以在推理那章学习到如何对一个评论判断其情感倾向
    sentiment = "negative"
    
    # 一个产品的评价
    review = f"""
    他们在11月份的季节性销售期间以约49美元的价格出售17件套装,折扣约为一半。\
    但由于某些原因(可能是价格欺诈),到了12月第二周,同样的套装价格全都涨到了70美元到89美元不等。\
    11件套装的价格也上涨了大约10美元左右。\
    虽然外观看起来还可以,但基座上锁定刀片的部分看起来不如几年前的早期版本那么好。\
    不过我打算非常温柔地使用它,例如,\
    我会先在搅拌机中将像豆子、冰、米饭等硬物研磨,然后再制成所需的份量,\
    切换到打蛋器制作更细的面粉,或者在制作冰沙时先使用交叉切割刀片,然后使用平面刀片制作更细/不粘的效果。\
    制作冰沙时,特别提示:\
    将水果和蔬菜切碎并冷冻(如果使用菠菜,则轻轻煮软菠菜,然后冷冻直到使用;\
    如果制作果酱,则使用小到中号的食品处理器),这样可以避免在制作冰沙时添加太多冰块。\
    大约一年后,电机发出奇怪的噪音,我打电话给客服,但保修已经过期了,所以我不得不再买一个。\
    总的来说,这些产品的总体质量已经下降,因此它们依靠品牌认可和消费者忠诚度来维持销售。\
    货物在两天内到达。
    """
    
    prompt = f"""
    你是一位客户服务的AI助手。
    你的任务是给一位重要客户发送邮件回复。
    根据客户通过“```”分隔的评价,生成回复以感谢客户的评价。提醒模型使用评价中的具体细节
    用简明而专业的语气写信。
    作为“AI客户代理”签署电子邮件。
    客户评论:
    ```&#123;review&#125;```
    评论情感:&#123;sentiment&#125;
    """
    response = get_completion(prompt)
    print(response)
    
    #answer:
    尊敬的客户,
    
    非常感谢您对我们产品的评价。我们非常抱歉您在购买过程中遇到了价格上涨的问题。我们一直致力于为客户提供最优惠的价格,但由于市场波动,价格可能会有所变化。我们深表歉意,如果您需要任何帮助,请随时联系我们的客户服务团队。
    
    我们非常感谢您对我们产品的详细评价和使用技巧。我们将会把您的反馈传达给我们的产品团队,以便改进我们的产品质量和性能。
    
    再次感谢您对我们的支持和反馈。如果您需要任何帮助或有任何疑问,请随时联系我们的客户服务团队。
    
    祝您一切顺利!
    
    AI客户代理
    
  • # 使用温度系数:在温度为零时,每次执行相同的提示时,您应该期望获得相同的完成。而使用温度为0.7,则每次都会获得不同的输出。在更高的温度下,助手更易分心,但也许更有创造力。
    response = get_completion(prompt, temperature=0.7)
    print(response)
    

Prompt Engineering 构建评价器

可通过自动化提示词迭代,对特定任务生成相关提示词,进行推理密集型回归的预测,离散的与连续的任务在设定上略有不同,在得到较好提示词后,可根据自一致性原则,在同一提示词下多做几次预测,对连续的剔除异常值后取平均,对离散的取众数。

强相关项目链接:x


SZUer继续加油!