《易车实战学习Langchain开发》-02-模型I/O,关于Prompt、LLMs、Output Parsers不能说的秘密

大家好,我是静愚,朋友们都喜欢叫我“鲸鱼🐳”。我将带领大家开启一段Langchain技术的实战之旅。
以《易车》实际应用场景为背景的系列学习文章,旨在帮助你们更直观、更深入地理解和掌握Langchain技术。
掌握一项技术,最重要的是能够解决实际问题。脱离了业务场景的技术,就像是无根之木、无源之水。
在这里,我们一起探索如何将Langchain技术应用于实际业务,让技术落地生根,助力业务发展。

上篇内容《易车实战学习Langchain开发》-01-使用Langchain构建“易车”销售平台智能问答系统 我们使用Langchain构建了一个简单的《易车》销售智能问答系统。

从这篇文章开始,我将带领大家一起学习一下Langchain的六大核心组件,其中会穿插着一些案例。

LangChain 主要由 6 个核心组件组成:

  1. 模型输入/输出(Model I/O):模型I/O 组件负责处理模型的输入(Prompt构造)和输出(响应解析)。
  2. 提示词(Prompt):指导模型按照用户或场景的需求输出内容。
  3. 链(Chains):Chains 组件用于构建和管理处理流程,它将多个模型和服务组合成一个完整的处理链条,同时它提供了流程控制、数据传递、异常处理等功能。
  4. 记忆(Memory):Memory 组件用于存储和管理系统的状态和历史数据。
  5. 代理(Agents):Agents 组件是 Langchain 平台的智能代理,负责处理用户的请求并调用相应的模型和服务。它能够根据用户的意图和上下文动态地选择合适的模型和处理流程,并将结果返回给用户。

本节我们就来看看核心组件模型

1. Model IO

从Langchain的整体架构来看,Langchain的模型I/O(Model IO)模块是框架的核心组成部分,负责管理与大型语言模型(LLM)的交互。它包括输入、模型和输出三个主要部分,简化了模型输入数据的格式化、模型调用以及输出结果的解析过程。

Langchain Model I/O

Model I/O 的工作流程: 格式化原始输入数据,将其传递给模型以获取预测结果,并将输出解析为结构化格式,以供下游组件或应用程序使用。

Model I/O流程包含以下三个核心步骤:

  1. 格式化(Format):原始数据被清洗、标记化、编码,并根据特定任务需求构建提示模板,以转换成适合语言模型处理的格式。
  2. 预测(Predict):格式化后的数据被直接送入语言模型,模型基于其内部知识和训练数据生成文本输出。
  3. 解析(Parse):语言模型的文本输出被提取特定信息、转换成不同数据类型,并经过必要的后处理,以满足下游组件或应用程序的结构化需求。

在模型I/O的三个环节中,Langchain都为我们提供了不少的工具,使用这些工具能够帮助我们快速达成需求。下面我们用示例的方式来深挖一下这三个环节。

2. 提示词模板(Prompt)

模型I/O的输入部分涉及到构建语言模型的输入,即Prompts。

PromptTemplate提供了构建语言模型输入的方式,允许开发者通过模板化的方式来定义模型的输入,包括对语言模型的身份设定描述、回答案例以及具体的问题。这些模板可以包含变量,使得输入能够动态适应不同的场景。

简单的说,Prompt的目的就是为了:给予模型清晰明确的指示

一个最简单的例子:

from langchain import PromptTemplate
template = """/
You are a naming consultant for new companies.
What is a good name for a company that makes {product}?
"""
prompt = PromptTemplate.from_template(template)
prompt.format(product="colorful socks")

输出: “”" You are a naming consultant for new companies. What is a good name for a company that makes colorful socks? “”"

这里,我们希望为销售的每一种汽车生成一段简介文案,那么每当你的员工或者顾客想了解某种汽车时,调用该模板就会生成适合的文字。这个提示模板的生成方式如下:

# 提示模板
from langchain.prompts import PromptTemplate

# 创建模板
template = """您是一位专业的汽车销售文案撰写员。\n
对于售价为 {price} 元的 {car_name} 轿车,您能提供一个吸引人的50字简短销售口号吗?
"""
prompt = PromptTemplate.from_template(template)
# 打印LangChain提示模板的内容
print(prompt)

输出:

input_variables=[‘car_name’, ‘price’]

template=‘您是一位专业的汽车销售文案撰写员。\n\n对于售价为 {price} 元的 {car_name} ,您能提供一个吸引人的简短描述吗?\n’

因此 PromptTemplatefrom_template 方法就是将一个原始的模板字符串转化为一个更丰富、更方便操作的 PromptTemplate 对象,这个对象就是 LangChain 中的提示模板。

3. 模型(LLMs)

模型部分涉及到实际调用的语言模型。Langchain提供了与多种LLM平台兼容的接口,允许开发者根据需要选择不同的模型进行交互。这些模型可以是文本生成模型、聊天模型或文本嵌入模型,它们通过统一的接口与Langchain集成,降低了学习成本和集成难度。

angChain支持多种类型的大型语言模型(LLMs)平台,包括但不限于以下几类:

  • 国外模型:如OpenAI、Cohere、Hugging Face等提供的模型。
  • 国内模型:如通义千问、百川、ChatGLM等。
  • 其他模型:包括Anthropic、Azure、Google Cloud Platform的Vertex AI(PaLM-2)和Jina AI等。

LangChain通过其模型组件提供了与这些不同LLMs的集成,并为所有模型提供一个统一的接口,使得开发者可以根据项目需要选择相应的模型进行应用开发。

接着上面的案例,我们将调用语言模型,让模型帮我们写文案,并且返回文案的结果。

from langchain_community.chat_models import ChatBaichuan
import os

# 创建模型实例
llm = ChatBaichuan(
    baichuan_api_key=os.getenv('BAICHUAN_API_KEY'),
    model="Baichuan3-Turbo",
)
# 输入提示
input = prompt.format(car_name=["Su7"], price='20万')
# 得到模型的输出
output = llm.invoke(input)
# 打印输出内容
print(output)  

input = prompt.format(car_name=["Su7"], price='20万') 这行代码的作用是将模板实例化,此时将 {car_name} 替换为 “Su7”,{price} 替换为 ‘20万’,形成了具体的提示:“您是一位专业的鲜花店文案撰写员。对于售价为 50 元的玫瑰,您能提供一个吸引人的简短描述吗?”

content='驾驭未来,畅享豪华——“Su7”,您的专属移动城堡,仅需20万元!'

运用LangChain和提示模板的优势体现在以下几个方面:

  1. 提升代码可读性:通过使用模板,提示文本变得更加清晰易懂,尤其在面对复杂或多变量的提示场景时,这一优势尤为明显。
  2. 增强代码复用性:提示模板可以在不同的场合多次使用,从而简化代码结构,避免在每次生成提示时重复编写字符串。
  3. 方便维护:当需要对提示内容进行调整时,仅需修改模板即可,无需在代码各处查找并逐一修改提示文本。
  4. 简化变量处理:在涉及多个变量的提示中,模板能够自动完成变量插入,省去了手动拼接字符串的繁琐操作。
  5. 参数化:提示模板可根据不同的参数灵活生成相应的提示内容,这对于定制化文本生成具有极大的便利性。

4. 输出解析(Output Parsers)

输出部分负责处理模型的输出结果。OutputParsers将模型的原始输出转换为结构化数据,以便后续的处理和分析。Langchain提供了多种输出解析器,如CSV解析器、日期时间解析器、枚举解析器和JSON解析器等,这些解析器能够将非结构化文本转换为可处理的结构化数据,提高信息处理效率。

LangChain的OutputParsers是一组用于解析大型语言模型(LLMs)输出的工具,它们能够将LLMs的文本输出转换为结构化数据,以便于后续处理和分析。以下是一些常用的OutputParsers类型及其作用:

  1. SimpleJsonOutputParser:将输出解析为JSON格式,适合需要以JSON结构存储或传输数据的场景。
  2. PydanticAttrOutputFunctionsParser:将输出解析为Pydantic对象的属性,适用于需要使用Pydantic模型进行数据验证和处理的情况。
  3. PydanticOutputFunctionsParser:将输出解析为整个Pydantic对象,适用于需要完整数据模型的场景。
  4. DatetimeOutputParser:将输出解析为日期时间格式,有助于处理涉及时间信息的数据。
  5. RegexParser/RegexDictParser:使用正则表达式解析输出,适用于需要根据复杂模式匹配文本的场景。
  6. RetryOutputParser/RetryWithErrorOutputParser:包裹另一个解析器,并尝试修复解析错误,提高解析的鲁棒性。
  7. StructuredOutputParser:将输出解析为结构化输出,适用于需要从文本中提取多个字段的场景。
  8. XMLOutputParser:使用XML格式解析输出,适用于需要以XML格式表示数据的场合。

这些解析器通过提供不同的解析策略,帮助开发者将LLMs的自然语言输出转换为易于编程处理的结构化数据,从而在各种应用中实现高效的数据管理和利用

**继续上面的案例,**如果我们向一次性让模型输出多款汽车的销售宣传语,然后存入到CSV中,那么上面直接范围文本的格式将无法满足我们的需求。

目标输出结构:

{
    "description": "让你心动!50 元就可以拥有这支充满浪漫气息的玫瑰花束,让 TA 感受你的真心爱意。"
    "reason": "因为爱情是无价的,50 元对应热恋中的情侣也会觉得值得。"
}

代码逻辑:

# 导入LangChain中的提示模板
from langchain.prompts import PromptTemplate

# 创建原始提示模板
prompt_template = """您是一位专业的汽车销售文案撰写员。\n
对于售价为 {price} 元的 {car_name} 轿车,您能提供一个吸引人的50字简短销售口号吗?
{format_instructions}
"""

# 通过LangChain调用模型
from langchain_community.chat_models import ChatBaichuan

# 创建模型实例
llm = ChatBaichuan(
    baichuan_api_key=os.getenv('BAICHUAN_API_KEY'),
    model="Baichuan3-Turbo",
)

# 导入结构化输出解析器和ResponseSchema
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 = PromptTemplate.from_template(prompt_template, partial_variables={"format_instructions": format_instructions})

# 数据准备
cars = ["Su7", "深蓝SL07"]
prices = ["20万", "15万"]

# 创建一个空的DataFrame用于存储结果
import pandas as pd

df = pd.DataFrame(columns=["car", "price", "description", "reason"])  # 先声明列名

for car, price in zip(cars, prices):
    # 根据提示准备模型的输入
    input = prompt.format(car_name=car, price=price)

    # 获取模型的输出
    output = llm.invoke(input)
    print(output.content)
    # 解析模型的输出(这是一个字典结构)
    parsed_output = output_parser.parse(output.content)

    # 在解析后的输出中添加“car”和“price”
    parsed_output['car'] = car
    parsed_output['price'] = price

    # 将解析后的输出添加到DataFrame中
    df.loc[len(df)] = parsed_output

# 打印字典
print(df.to_dict(orient='records'))

# 保存DataFrame到CSV文件
df.to_csv("files/cars_with_descriptions.csv", index=False)

输出结果: ```json

{

​ “description”: “驾驭未来,畅享豪华,20万Su7轿车,您的智慧之选。”,

​ “reason”: “此口号强调了车辆的先进性、豪华感和性价比,同时使用了’驾驭未来’和’智慧之选’等词汇来吸引目标客户群体。”

}

```

```json

{

​ “description”: “深蓝SL07,您的15万元智慧之选,驾驭未来,畅享科技出行新体验!”,

​ “reason”: “突出性价比和科技感,强调15万元的价值,吸引注重科技和性价比的消费者”

}

```

[{‘car’: ‘Su7’, ‘price’: ‘20万’, ‘description’: ‘驾驭未来,畅享豪华,20万Su7轿车,您的智慧之选。’, ‘reason’: “此口号强调了车辆的先进性、豪华感和性价比,同时使用了’驾驭未来’和’智慧之选’等词汇来吸引目标客户群体。”}, {‘car’: ‘深蓝SL07’, ‘price’: ‘15万’, ‘description’: ‘深蓝SL07,您的15万元智慧之选,驾驭未来,畅享科技出行新体验!’, ‘reason’: ‘突出性价比和科技感,强调15万元的价值,吸引注重科技和性价比的消费者’}]

在这里插入图片描述

到这里,我们今天的任务也就顺利完成了。

最后

使用LangChain框架的优势主要包括以下几点:

  1. 模板管理:LangChain有助于在大型项目中高效管理众多提示模板,确保代码结构清晰和整洁。
  2. 变量提取与检查:LangChain能够自动识别并检查模板中的变量,防止遗漏,确保所有变量都被正确填充。
  3. 模型切换便捷:通过简单更改模型名称,LangChain允许用户轻松尝试不同的模型,无需重写代码。
  4. 输出解析:LangChain的提示模板支持定义输出格式,使得后续处理已格式化的输出更加便捷。

在接下来的课程中,我们将进一步探讨LangChain的提示模板,学习如何通过优质的提示工程,使模型生成更精确、更高质量的输出。

  • 33
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

静愚 AGI

你的善意终将流回自己,加油!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值