LangChain入门和应用#6 | 豆包MarsCode AI刷题

194 阅读10分钟

提示工程-上

所以,为什么输出解析器指定的format_instructions之后,为什么能够让模型生成结构化的输出?

你只需打印最终传递给大模型的提示就好了

image.png

image.png

原来,,在LangChain框架中,输出解析器在生成提示(prompt)时,隐式地在原始提示中加入了一段特殊文本,这段文本位于 {format_instructions} 部分。LangChain自动将这段格式化指令添加到提示中,明确告知模型输出所需的结构和格式。这段指令详细地描述了我们希望得到的响应格式,通常以特定的schema(数据结构定义)来表达。

原理解析:

  • {format_instructions} 的作用:在LangChain中,{format_instructions} 实际上是一个指示模型如何格式化其输出的模板。它告诉模型必须遵循某种结构或规则来生成输出。这种结构可以是一个JSON对象,也可以是其他标准化格式的输出。此格式化指令从一个json开头,到结束,形成一个明确的格式要求。
  • Schema的含义:在这里,schema 是对输出数据结构的描述。它是一个规定了数据组织形式的模板,确保模型输出的结果符合预定的数据格式(例如,JSON格式)。这种结构化的输出能够使模型生成的结果更加规范化、可解析且符合后续处理的需求。
  • 模型响应的引导:通过这种明确的提示工程(Prompt Engineering),模型(特别是像GPT-3.5及以上版本这种具有较高智能的模型)能够根据给定的格式化指令生成符合期望的数据结构。例如,若提示中要求生成JSON格式的输出,模型将按照JSON的语法和结构来组织输出内容。

基本上,对所有主要语言模型进行的研究表明,在提示中包含例子都将产生更高质量的答案。 在针对大模型的提示工程(Prompt Engineering)方面,吴恩达老师在他的公开课程《ChatGPT Prompt Engineering for Developers》中,提出了两个核心原则:清晰而具体的指示给模型足够的思考时间。这两个原则旨在确保大语言模型能够理解并有效地处理任务,输出高质量的响应。

类似的原则也出现在OpenAI官方文档中的《GPT最佳实践》部分,其中列出了六大策略,这些策略与吴恩达的原则高度契合:

  1. 写清晰的指示:提供明确、具体的指令,避免模糊或不明确的表达,确保模型能够理解并正确执行任务。
  2. 给模型提供参考(示例) :通过提供示例或参考答案,帮助模型理解期望的输出格式或行为。
  3. 将复杂任务拆分成子任务:对于难度较大的任务,将其拆解成较小、易于处理的子任务,帮助模型逐步解决问题。
  4. 给GPT时间思考:为模型提供足够的时间进行深思熟虑,避免过于简短的反馈或急于生成结果,从而提升回答的质量。
  5. 使用外部工具:在需要时,可以结合外部工具或API,拓展模型的功能或提供额外的信息支持。
  6. 反复迭代问题:通过多次提问和调整提示,逐步优化输出,确保结果满足预期。

下面,我们进一步探讨如何做好提示工程

提示的结构

这是一个实用的提示框架ICIO 框架

🤖 Instruction (任务) :你希望 AI 去做的任务,比如翻译或者写一段文字

📋 Context (背景) :给 AI 更多的背景信息,引导模型做出更贴合需求的回复,比如你要他写的这段文字用在什么场景的、达到什么目的的

📖 Input Data (输入数据) :告诉 AI 你这次你要他处理的数据。 比如你要他翻译那么你每次要他翻译的句子就是「输入数据」

📤 Output Indicator (输出格式) :告诉 AI 他输出的时候要用什么格式、风格、类型,如果你无所谓它输出时候的格式,也可以不写

案例 - 翻译法文到英文用于商务报告

# Intruction
描述:请将以下的法文段落翻译成英文。
重要性:翻译的准确性对于我们的商务报告至关重要。
# Context
场景:这段法文将用于我们公司的年度商务报告。
目的:报告将呈现给公司的股东和潜在投资者,所以翻译需要准确且专业。
# Input Data
"La croissance économique de la France a été stable au cours des dernières années, malgré les défis mondiaux."
# Output Indicator
风格:正式和专业的商务英文风格。
注意事项:请确保翻译内容无语法错误,并保持原文的意思。

LangChain中提供String(StringPromptTemplate)和Chat(BaseChatPromptTemplate)两种基本类型的模板,并基于它们构建了不同类型的提示模板:

image.png 这些模板的导入方式如下:

# 从 LangChain 的提示模块(prompts)中导入各种提示模板类
# PromptTemplate 是基础的提示模板类,用于创建简单的模板
from langchain.prompts.prompt import PromptTemplate
​
# FewShotPromptTemplate 是一个增强版的提示模板,适用于少量示例(few-shot learning)场景
# 适合用在需要模型学习一些示例并根据这些示例进行推理的任务中
from langchain.prompts import FewShotPromptTemplate
​
# PipelinePromptTemplate 主要用于定义一个提示管道(Pipeline),
# 这种管道允许多个模板按顺序组合使用,适合复杂任务的处理
from langchain.prompts.pipeline import PipelinePromptTemplate
​
# ChatPromptTemplate 用于定义聊天模型(如 GPT)的提示模板,适合用于对话型模型的场景
# 可以为模型构建一个聊天对话的上下文模板
from langchain.prompts import ChatPromptTemplate
​
# 从 langchain.prompts 中导入几种不同类型的消息模板,分别用于不同的消息角色
# 这些模板帮助为多轮对话构建具体的消息格式,使得对话变得更加结构化和清晰# ChatMessagePromptTemplate 用于构建聊天消息的模板,适用于处理具有多轮对话的聊天模型
from langchain.prompts import ChatMessagePromptTemplate
​
# SystemMessagePromptTemplate 用于构建系统消息的模板,通常由系统发送,用于设置对话的环境或规则
from langchain.prompts import SystemMessagePromptTemplate
​
# AIMessagePromptTemplate 用于构建 AI 消息的模板,定义 AI 的回答格式
from langchain.prompts import AIMessagePromptTemplate
​
# HumanMessagePromptTemplate 用于构建人类用户消息的模板,定义用户输入的格式
from langchain.prompts import HumanMessagePromptTemplate
​

下面将分别介绍各个模板的使用

1. 使用 PromptTemplate

代码示例

pythonfrom langchain import PromptTemplate
​
template = """\
你是业务咨询顾问。
你给一个销售{product}的电商公司,起一个好的名字?
"""
prompt = PromptTemplate.from_template(template)
​
print(prompt.format(product="鲜花"))

解释

PromptTemplate 是 LangChain 提供的一个强大工具,它允许用户创建灵活且可复用的提示(prompts)。通过占位符 {},你可以将动态值传入模板中,生成特定场景下的提示信息。

  1. 模板创建

    • 在上面的示例中,template 字符串是一个简单的提示模板,其中 "{product}" 是一个占位符,它将被实际的产品名替换。这个模板要求用户作为“业务咨询顾问”,根据给定的产品(如“鲜花”),提供电商公司命名建议。
  2. 创建 PromptTemplate 对象

    • 使用 PromptTemplate.from_template(template),我们可以将一个包含占位符的模板字符串转换为一个 PromptTemplate 对象。这个对象能够接受不同的变量进行格式化。
  3. 格式化模板

    • 调用 prompt.format(product="鲜花") 时,product 变量的值(例如 "鲜花")会替换掉模板中的 {product} 占位符。最终,得到的提示会是:
    你是业务咨询顾问。
    你给一个销售鲜花的电商公司,起一个好的名字?
    
  4. 灵活性

    • LangChain 的 PromptTemplate 通过 from_template 方法自动从模板字符串中提取变量名(如 product)。这意味着你无需显式地指定哪些变量需要格式化。

手动指定 input_variables

你也可以通过构造函数手动指定变量名。例如:

pythonprompt = PromptTemplate(
    input_variables=["product", "market"], 
    template="你是业务咨询顾问。对于一个面向{market}市场的,专注于销售{product}的公司,你会推荐哪个名字?"
)
print(prompt.format(product="鲜花", market="高端"))

这将生成:

你是业务咨询顾问。对于一个面向高端市场的,专注于销售鲜花的公司,你会推荐哪个名字?

这种方式直接在 PromptTemplate 对象创建时指定了输入变量,而不依赖 from_template 方法自动提取变量。


2. 使用 ChatPromptTemplate

对于基于 OpenAI GPT 等聊天模型的对话应用,LangChain 提供了专门为这种场景设计的模板:ChatPromptTemplate。这种模板适用于多轮对话并区分不同角色(如系统消息、用户消息、助理消息)。

OpenAI 消息格式

pythonimport openai
openai.ChatCompletion.create(
  model="gpt-3.5-turbo",
  messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Who won the world series in 2020?"},
        {"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."},
        {"role": "user", "content": "Where was it played?"}
    ]
)

消息角色

  • 系统消息 (system) 用于设置对话上下文和模型行为(例如修改助手个性)。
  • 用户消息 (user) 用于表达用户的查询或需求。
  • 助手消息 (assistant) 用于表示模型的回应。

LangChain 的 ChatPromptTemplate

pythonfrom langchain.prompts import (
    ChatPromptTemplate,
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate,
)
​
# 构建模板
template = "你是一位专业顾问,负责为专注于{product}的公司起名。"
system_message_prompt = SystemMessagePromptTemplate.from_template(template)
​
human_template = "公司主打产品是{product_detail}。"
human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)
​
prompt_template = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])
​
# 格式化提示
prompt = prompt_template.format_prompt(product="鲜花装饰", product_detail="创新的鲜花设计。").to_messages()
​
# 调用模型
import os
os.environ["OPENAI_API_KEY"] = '你的OpenAI Key'
from langchain.chat_models import ChatOpenAI
​
chat = ChatOpenAI()
result = chat(prompt)
print(result)

解释

  1. 角色消息模板

    •   SystemMessagePromptTemplate
      

        HumanMessagePromptTemplate
      

      用于定义系统消息和用户消息模板。在这个示例中:

      • 系统消息设置了模型的角色和任务:“你是一位专业顾问,负责为专注于{product}的公司起名。”
      • 用户消息指定了公司主打产品的详细信息:“公司主打产品是{product_detail}。”
  2. 创建 ChatPromptTemplate

    • 使用 ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt]),将系统消息和用户消息结合起来,构建一个完整的对话提示模板。
  3. 格式化和调用模型

    • 通过 prompt_template.format_prompt,将实际的产品信息(如“鲜花装饰”和“创新的鲜花设计”)替换到模板中。然后使用 .to_messages() 方法将格式化后的提示转换为消息格式。
    • 调用 OpenAI 的聊天模型 (ChatOpenAI) 将生成的消息传递给模型,生成响应。

最终,模型会根据提示生成类似这样的公司命名建议:

1. 花语创意
2. 花韵设计
3. 花艺创新
4. 花漾装饰
...

微总结

  • PromptTemplate 允许用户创建具有动态占位符的提示模板,灵活地生成不同的提示内容,适用于非对话场景。
  • ChatPromptTemplate 专为多轮对话和不同角色的消息设计,能够清晰地定义系统、用户和助手的角色信息,适用于与聊天模型(如 GPT-3.5 和 GPT-4)进行交互。

下一节,我们将使用 FewShotPromptTemplate