04_模型I/O:输入提示、调用模型、解析输出 | 豆包MarsCode AI刷题

140 阅读7分钟

模型I/O:输入提示、调用模型、解析输出——学习笔记

本次学习主要涵盖LangChain中的模型I/O过程,包括输入提示、调用模型和解析输出的工作流程。这些步骤是LangChain框架中大语言模型应用的核心,使得开发人员能够高效地构建基于大模型的实际应用。

1. LangChain的模型I/O概述

模型I/O描述了使用模型的整体过程,分为三个主要部分:

  • 输入提示(Format):将用户输入或任务需求转化为模型可理解的提示。
  • 调用模型(Predict):通过API调用模型,获取模型的响应。
  • 解析输出(Parse):提取模型生成的文本中的关键信息,将其转化为结构化数据,以便于后续处理。

image.png

LangChain为这三个环节提供了丰富的工具和模板,简化了开发过程。开发者可以像模块化搭建功能一样,轻松地组合这些组件,构建复杂的AI应用程序。

2. 输入提示:提示模板的构建

提示模板(Prompt Template)是模型I/O中的第一步,涉及如何有效地构建提示,使得模型能够理解并按照预期返回结果。这部分也被称为“提示工程(Prompt Engineering)”。

课程中提到,构建提示模板时需要遵循以下原则:

  • 明确的指示:给模型提供清晰的任务描述,避免输出模糊或偏离主题。
  • 逐步推理:通过逐步引导模型进行推理,可以得到更严谨的答案。

例如,为不同种类的鲜花生成广告文案时,可以使用以下代码创建提示模板:

from langchain.prompts import PromptTemplate

# 创建原始模板
template = """您是一位专业的鲜花店文案撰写员。
对于售价为 {price} 元的 {flower_name},您能提供一个吸引人的简短描述吗?
"""

# 根据原始模板创建LangChain提示模板
prompt = PromptTemplate.from_template(template)

input_variables=['flower_name', 'price'] 
output_parser=None partial_variables={} 
template='/\n您是一位专业的鲜花店文案撰写员。
\n对于售价为 {price} 元的 {flower_name} ,您能提供一个吸引人的简短描述吗?\n'
template_format='f-string' 
validate_template=True

在这个模板中,{flower_name}{price} 是占位符,可以替换为具体的花名和价格,从而生成特定的提示。

我们可以修改输入提示,from_template方法将创建一个PromptTemplate对象,这个对象包括输入的变量、输出解析器(这个例子中没有指定)、模板的格式('f-string')、是否验证模板( True)。

image.png

使用提示模板的一个重要优点是其可复用性和灵活性,特别是在需要多次生成不同内容时,通过改变占位符的值就可以轻松适应多种情景,大大提高了开发效率。

3. 调用模型

LangChain支持多种语言模型,包括:

  • 大语言模型(LLM):这些模型专注于生成和理解自然语言文本,适用于文本生成、回答问题、内容总结等任务。大语言模型可以处理复杂的语言任务,具备强大的语言理解能力。例如,使用GPT-3.5模型来撰写一篇关于特定主题的文章。
  • 聊天模型(Chat Model):聊天模型专门用于多轮对话,能够在上下文中保持对话状态,适合用于智能客服、虚拟助手等需要与用户进行持续交互的应用。例如,使用ChatGPT作为虚拟助手与用户进行多轮问答,提供实时帮助。
  • 文本嵌入模型(Embedding Model):文本嵌入模型将文本转换为向量形式,以便进行相似度计算、聚类和分类等任务。这类模型广泛用于信息检索、推荐系统等场景,通过将文本表示为数值,可以有效地进行比较和匹配。例如,使用嵌入模型来对客户评论进行聚类,以便更好地分析客户的反馈。

调用模型时,可以使用前面创建的提示模板,将具体的内容传递给模型。例如,使用OpenAI的模型生成鲜花文案:

from langchain_openai import OpenAI

# 设置OpenAI API Key
import os
os.environ["OPENAI_API_KEY"] = '你的OpenAI Key'

# 创建模型实例
model = OpenAI(model_name='gpt-3.5-turbo-instruct')

# 输入提示
input = prompt.format(flower_name="玫瑰", price='50')

# 得到模型的输出
output = model.invoke(input)

# 打印输出内容
print(output)

通过这种方式,可以方便地调用模型来生成文本描述。

从调用模型的过程来看,LangChain对底层API的封装极大地简化了开发工作。对于不同的语言模型,LangChain提供了一致的调用接口,使得开发者无需深入了解每个模型的细节,即可快速集成大语言模型的能力。

4. 解析输出

模型生成的输出通常是非结构化文本,直接使用可能会不便。因此,LangChain提供了输出解析器,将模型的输出转化为结构化数据,以便后续处理。

例如,在生成鲜花文案时,我们希望输出包含两个字段:

  • description:鲜花的描述文本。
  • reason:撰写该文案的理由。

使用输出解析器可以更好地控制模型输出的格式,符合应用需求:

from langchain.output_parsers import StructuredOutputParser, ResponseSchema

# 定义我们想要接收的响应模式
response_schemas = [
    ResponseSchema(name="description", description="鲜花的描述文案"),
    ResponseSchema(name="reason", description="为什么这样写文案")
]

# 创建输出解析器
output_parser = StructuredOutputParser.from_response_schemas(response_schemas)

# 获取格式指示
format_instructions = output_parser.get_format_instructions()

# 创建包含输出解析器说明的提示模板
prompt_with_parser = PromptTemplate.from_template(
    template, partial_variables={"format_instructions": format_instructions}
)

# 得到解析后的输出
df = pd.DataFrame(columns=["flower", "price", "description", "reason"])

# 处理模型输出的示例
for flower, price in zip(["玫瑰", "百合"], ["50", "30"]):
    input = prompt_with_parser.format(flower_name=flower, price=price)
    output = model.invoke(input)
    parsed_output = output_parser.parse(output)
    parsed_output['flower'] = flower
    parsed_output['price'] = price
    df.loc[len(df)] = parsed_output

print(df)

image.png 通过这个例子,我们可以将模型生成的非结构化文本解析为结构化的Python字典,再将其存入DataFrame中,便于后续的数据处理。输出解析器不仅提高了模型输出的可操作性,还确保了数据的格式一致性,减少了后续数据清洗的工作量。

5. 总结

LangChain的优势在于为开发者提供了高效、简洁的开发工具链,减少了底层API调用的复杂度,使得基于大语言模型的应用开发更为便捷。尤其是在处理多样化提示和输出时,LangChain的提示模板和输出解析器提供了极大的灵活性。

思考题

  1. LangChain调用大语言模型的优势是什么?

    LangChain的主要优势在于其模块化设计,能够简化大语言模型的集成过程,使得开发者可以通过统一的接口调用不同模型。此外,LangChain还提供了丰富的工具来处理输入提示和输出解析,使得整个开发过程更加流畅和高效。

  2. 在上面的示例中,输出解析器如何工作?

    输出解析器通过定义响应模式(ResponseSchema)来指定需要从模型输出中提取的信息。输出解析器生成格式指示(format_instructions),这些指示会嵌入到提示模板中,从而引导模型返回结构化的输出。解析器随后根据这些指示将文本输出解析为指定的数据格式。

  3. 加入输出解析器后的提示为何能够生成结构化输出?

    加入输出解析器后的提示包含了明确的格式说明,这些格式说明告诉模型需要按照特定的结构来返回结果。因此,模型会根据这些说明尽量生成符合要求的输出,方便解析器进行进一步处理。

  4. 使用输出解析器后,是否有可能仍然得不到所期望的输出?

    是,尽管有输出解析器,模型仍可能无法完美地遵循格式要求。这取决于模型对提示的理解能力以及任务的复杂性。有时,模型可能会忽略部分指令,导致输出不完全符合预期。