LangChain大模型应用开发:多模态输入与自定义输出

news/2025/2/21 10:05:25

介绍

大家好,博主又来给大家分享知识了。今天给大家分享的内容是使用LangChain进行大模型应用开发中的多模态输入与自定义输出。

LangChain中的多模态数据输入是指将多种不同形式的数据作为输入提供给基于语言模型的应用程序或系统,以丰富交互内容和提升模型处理能力,让应用能够处理和理解更广泛的信息类型,从而更好地满足用户多样化的需求。

LangChain自定义输出指的是开发者依据具体应用场景和业务需求,对基于LangChain构建的大模型应用输出结果的形式、内容、风格等进行个性化定制的能力。在一些需要数据规整呈现的场景下,我们可以让LangChain输出特定格式的结构化数据,比如JSONXML、YAML等。

好了,我们直接进入正题。

多模态数据输入

这里我们演示如何将多模态输入直接传递给模型。我们目前期望所有输入都以与OpenAI期望的格式相同的格式传递。对于支持多模态输入的其他模型提供者,我们在类中添加了逻辑以转换为预期格式。

在这个演示中,我们让大模型帮助我们描述下面这张图片。

获取Base64编码的图片信息

其中,最常支持的传入图片的方式是将其作为字节字符串传入。这种方式适用于大多数模型集成。

完整代码

python"># 从langchain_core.messages模块导入HumanMessage类,用于创建人类发送的消息
from langchain_core.messages import HumanMessage
# 从langchain_openai模块导入ChatOpenAI类,用于调用OpenAI的聊天模型
from langchain_openai import ChatOpenAI
# 导入base64模块,用于对图片数据进行Base64编码
import base64
# 导入httpx库,用于发送HTTP请求获取图片
import httpx

# 初始化一个ChatOpenAI实例,使用gpt-4o模型
model = ChatOpenAI(model="gpt-4o")

# 定义图片的URL地址
image_url = "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"

# 通过httpx库发送请求获取图片内容,并使用base64对其进行编码,最后解码为字符串
image_data = base64.b64encode(httpx.get(image_url).content).decode("utf-8")

# 创建一个HumanMessage实例,包含文本请求和Base64编码的图片信息
message = HumanMessage(
    content=[
        {"type": "text", "text": "用中文描述这张图片中的天气"},
        {
            "type": "image_url",
            "image_url": {"url": f"data:image/jpeg;base64,{image_data}"},
        },
    ],
)

# 调用模型处理消息并获取响应
response = model.invoke([message])

# 打印模型对图片天气描述的响应内容
print(response.content)

运行结果

python">这张图片中的天气晴朗,碧蓝的天空中点缀着几朵薄薄的白云。太阳光线充足,明媚的阳光洒在绿色的草地和木质步道上,显得格外清新和温暖。整体感觉空气清新,风和日丽,是一个非常舒适宜人的天气。

进程已结束,退出代码为 0

获取URL原始图片信息

我们可以在“image_url”类型的内容模块中直接提供图像URL。但是,前提是:我们使用的模型供应商必须支持此功能

完整代码

python"># 从langchain_core.messages模块导入HumanMessage类,用于创建人类发送的消息
from langchain_core.messages import HumanMessage
# 从langchain_openai模块导入ChatOpenAI类,用于调用OpenAI的聊天模型
from langchain_openai import ChatOpenAI

# 初始化一个ChatOpenAI实例,使用gpt-4o模型
model = ChatOpenAI(model="gpt-4o")

# 定义图片的URL地址
image_url = "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"

# 通过httpx库发送请求获取图片内容,并使用base64对其进行编码,最后解码为字符串
image_data = base64.b64encode(httpx.get(image_url).content).decode("utf-8")

# 创建一个HumanMessage实例,包含文本请求和原始图片URL信息
message = HumanMessage(
    content=[
        {"type": "text", "text": "用中文描述这张图片中的天气"},
        {"type": "image_url", "image_url": {"url": image_url}},
    ],
)

# 调用模型处理消息并获取响应
response = model.invoke([message])

# 打印模型对图片天气描述的响应内容
print(response.content)

运行结果

python">这张图片中的天气非常晴朗。天空中有一些轻薄的白云,主要以蓝色为主,显得天特别的高远。阳光明媚,照在绿色的草地上,使整个景象显得非常明亮和清新。整体感觉温暖且令人愉悦,适合外出活动。

进程已结束,退出代码为 0

对比多张图片信息

我们还可以传入多张图片并可以让大模型帮我们进行对比。

完整代码

python"># 从langchain_core.messages模块导入HumanMessage类,用于创建人类发送的消息
from langchain_core.messages import HumanMessage
# 从langchain_openai模块导入ChatOpenAI类,用于调用 OpenAI 的聊天模型
from langchain_openai import ChatOpenAI

# 初始化一个ChatOpenAI实例,使用gpt-4o模型
model = ChatOpenAI(model="gpt-4o")

# 定义图片的URL地址
image_url = "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"

# 创建一个HumanMessage实例,询问两张相同图片是否一样,并附带两张图片的URL
message = HumanMessage(
    content=[
        {"type": "text", "text": "这两张图片是一样的吗?"},
        {"type": "image_url", "image_url": {"url": image_url}},
        {"type": "image_url", "image_url": {"url": image_url}},
    ],
)

# 调用模型处理消息并获取响应
response = model.invoke([message])

# 打印模型对两张图片是否相同的响应内容
print(response.content)

运行结果

python">是的,这两张图片是一样的。它们显示了同一个风景场景,都是在一片绿色的草地上,有一条木板路延伸至远处,天空中有少许云彩。从图像内容、颜色和细节上看,它们是完全相同的。

进程已结束,退出代码为 0

工具调用

一些多模态模型也支持工具调用功能。要使用此类模型调用工具,只需以通常的方式将工具绑定到它们,然后使用所需类型的内容块(例如,包含图像数据)调用模型。

我们自定义一个名为weather_tool的工具函数,接收一个表示天气状况的参数,参数类型只能是指定的几种天气情况。然后我们利用LangChain库,结合OpenAIgpt-4o模型,实现对两张图片中天气状况的分析描述功能。

完整代码

python"># 导入Literal类型,用于定义一个只能取特定值的类型
from typing import Literal
# 导入HumanMessage类,用于创建人类发送的消息对象
from langchain_core.messages import HumanMessage
# 导入ChatOpenAI类,用于与OpenAI的聊天模型进行交互
from langchain_openai import ChatOpenAI
# 导入tool装饰器,用于将函数转换为工具
from langchain_core.tools import tool


# 使用tool装饰器将weather_tool函数转换为一个工具
@tool
# 定义一个名为weather_tool的工具函数,接收一个表示天气状况的参数,参数类型只能是指定的几种天气情况
def weather_tool(weather: Literal["晴朗的", "多云的", "多雨的", "下雪的"]) -> None:
    """Describe the weather"""  # 函数的文档字符串,用于描述函数的功能是描述天气
    pass  # 函数体为空,暂时不做具体操作


# 初始化一个ChatOpenAI对象,使用gpt-4o模型
model = ChatOpenAI(model="gpt-4o")

# 将模型与工具绑定,使得模型在运行时可以调用weather_tool工具
model_with_tools = model.bind_tools([weather_tool])

# 定义第一张图片的URL
image_url_1 = "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"

# 定义第二张图片的URL
image_url_2 = "https://upload.wikimedia.org/wikipedia/commons/thumb/9/92/Morning_in_China_Snow_Town.jpg/1280px-Morning_in_China_Snow_Town.jpg"

# 创建一个人类消息对象
message = HumanMessage(
    content=[  # 消息内容是一个列表,包含文本和图片URL信息
        {"type": "text", "text": "用中文描述两张图片中的天气"},  # 文本内容,指示模型要完成的任务
        {"type": "image_url", "image_url": {"url": image_url_1}},  # 第一张图片的URL信息
        {"type": "image_url", "image_url": {"url": image_url_2}},  # 第二张图片的URL信息
    ],
)

# 调用绑定了工具的模型,传入人类消息,得到模型的响应
response = model_with_tools.invoke([message])

# 打印模型响应中调用工具的相关信息
print(response.tool_calls)

运行结果

python">[{'name': 'weather_tool', 'args': {'weather': '晴朗的'}, 'id': 'call_cgXu6gngXss6RpgcLamxqB8R', 'type': 'tool_call'}, {'name': 'weather_tool', 'args': {'weather': '下雪的'}, 'id': 'call_aU3xRKwucotSpu2FinamfnHq', 'type': 'tool_call'}]

进程已结束,退出代码为 0

从上面的运行结果我们可以看到,当大模型响应完成后我们再去调用自定义工具,输出结果会按照我们自定义工具的参数格式及类型返回。

自定义格式输出

LangChain中,自定义格式输出是指按照特定需求对模型生成的结果进行格式化处理,以满足实际应用的多样化需求。这一功能非常实用,因为语言模型的输出往往是通用的文本形式,而实际使用中可能需要将其转换为特定的数据结构、字符串格式或其他应用程序易于处理的形式。

解析JSON格式输出

虽然一些模型提供商支持内置的方法返回结构化输出,但并非所有都支持。我们可以使用输出解析器来帮助用户通过提示指定任意的JSON模式,查询符合该模式的模型输出,最后将该模式解析为 JSON

请记住,大模型不是完美无缺的,存在着数据、准确性、可靠性等方面的风险和不确定性,在使用时需要谨慎,我们必须使用具有足够容量的大语言模型,具备更强的语言理解和生成能力,以及更好的逻辑和结构化输出能力。

JsonOutputParser是一个内置选项,用于提示并解析JSON输出。虽然它在功能上类似于 PydanticOutputParser,但它还支持流式返回部分JSON对象。

下面,我们将演示如何将其与Pydantic一起使用以方便地声明预期模式。

完整代码

python"># 从langchain_core库中导入JsonOutputParser类,用于将模型输出解析为JSON格式
from langchain_core.output_parsers import JsonOutputParser
# 从langchain_core库中导入PromptTemplate类,用于创建提示模板
from langchain_core.prompts import PromptTemplate
# 从pydantic库中导入BaseModel和Field类,用于定义数据模型和字段描述
from pydantic import BaseModel, Field
# 从langchain_openai库中导入ChatOpenAI类,用于调用OpenAI的聊天模型
from langchain_openai import ChatOpenAI

# 初始化ChatOpenAI模型实例,使用gpt-3.5-turbo模型,设置temperature=0不考虑随机性
chat_model = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)


# 定义一个名为Joke的类,继承自BaseModel,用于表示笑话的数据结构
class Joke(BaseModel):
    # 定义setup字段,类型为字符串,描述为设置笑话的问题
    setup: str = Field(description="设置笑话的问题")
    # 定义punchline字段,类型为字符串,描述为解决笑话的答案
    punchline: str = Field(description="解决笑话的答案")


# 定义一个字符串变量,作为向语言模型请求笑话的查询语句
joke_query = "请给我讲个编程的笑话。"

# 创建JsonOutputParser实例,指定pydantic对象为Joke类,用于解析符合Joke结构的JSON输出
json_output_parser = JsonOutputParser(pydantic_object=Joke)

# 创建PromptTemplate实例,定义提示模板的格式
prompt = PromptTemplate(
    # 模板字符串,包含回答查询、格式指令和用户查询三部分
    template="回答用户的查询。\n{format_instructions}\n{query}\n",
    # 指定输入变量为 query
    input_variables=["query"],
    # 部分变量,将解析器的格式指令插入到模板中
    partial_variables={"format_instructions": json_output_parser.get_format_instructions()},
)

# 使用管道操作符将提示模板、模型和解析器连接成一个处理链
chain = prompt | chat_model | json_output_parser

# 调用处理链,传入查询语句,得到处理结果
result = chain.invoke({"query": joke_query})

# 打印最终处理得到的结果
print(result)

运行结果

python">{'setup': '为什么计算机工程师喜欢使用黑色背景的代码编辑器?', 'punchline': '因为黑色背景让BUG无处藏。'}

进程已结束,退出代码为 0

在上述代码PromptTemplate中的partial_variables属性,我们添加format_instructions变量,然后通过get_format_instructions()方法赋值,这个方法会生成一段指导语言模型按照特定JSON格式输出的指令文本。

我们也可以将format_instructions设置为自定义的值。

自定义提示格式代码演示

python">custom_instructions = '请用中文来回答。输出应格式化为符合以下JSON模式的JSON实例。例如,对于模式{"properties": {"foo": {"title": "Foo", "description": "字符串列表", "type": "array", "items": {"type": "string"}}}, "required": ["foo"]},对象 {"foo": ["bar", "baz"]}是该模式的格式良好实例。对象{"properties": {"foo": ["bar", "baz"]}}不是格式良好的。'

prompt = PromptTemplate(
    # 模板字符串,包含回答查询、格式指令和用户查询三部分
    template="回答用户的查询。\n{format_instructions}\n{query}\n",
    # 指定输入变量为 query
    input_variables=["query"],
    # 部分变量,将解析器的格式指令插入到模板中
    partial_variables={"format_instructions": custom_instructions},
)

请大家自行去测试并查看与之前有什么不同😊。

流式处理

如上所述,JsonOutputParserPydanticOutputParser之间的一个关键区别是JsonOutputParser输出解析器支持流式处理部分块。我们演示一下:

流出输出完整代码

python"># 从langchain_core库中导入JsonOutputParser类,用于将模型输出解析为JSON格式
from langchain_core.output_parsers import JsonOutputParser
# 从 langchain_core库中导入PromptTemplate类,用于创建提示模板
from langchain_core.prompts import PromptTemplate
# 从 pydantic库中导入BaseModel和Field类,用于定义数据模型和字段描述
from pydantic import BaseModel, Field
# 从 langchain_openai库中导入ChatOpenAI类,用于调用OpenAI的聊天模型
from langchain_openai import ChatOpenAI

# 初始化ChatOpenAI模型实例,使用gpt-3.5-turbo模型,设置temperature=0不考虑随机性
chat_model = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)


# 定义一个名为Joke的类,继承自BaseModel,用于表示笑话的数据结构
class Joke(BaseModel):
    # 定义setup字段,类型为字符串,描述为设置笑话的问题
    setup: str = Field(description="设置笑话的问题")
    # 定义punchline字段,类型为字符串,描述为解决笑话的答案
    punchline: str = Field(description="解决笑话的答案")


# 定义一个字符串变量,作为向语言模型请求笑话的查询语句
joke_query = "请给我讲个编程的笑话。"

# 创建JsonOutputParser实例,指定pydantic对象为Joke类,用于解析符合 Joke 结构的 JSON 输出
json_output_parser = JsonOutputParser(pydantic_object=Joke)

# 创建 PromptTemplate 实例,定义提示模板的格式
prompt = PromptTemplate(
    # 模板字符串,包含回答查询、格式指令和用户查询三部分
    template="回答用户的查询。\n{format_instructions}\n{query}\n",
    # 指定输入变量为 query
    input_variables=["query"],
    # 部分变量,将解析器的格式指令插入到模板中
    partial_variables={"format_instructions": json_output_parser.get_format_instructions()},
)

# 使用管道操作符将提示模板、模型和解析器连接成一个处理链
chain = prompt | chat_model | json_output_parser

# 每次从生成器中获取的元素chain_stream是语言模型逐步生成的部分结果
for chain_stream in chain.stream({"query": joke_query}):
    # 打印每次从生成器中获取的部分结果,方便查看模型逐步生成输出的过程
    print(chain_stream)

流式输出运行结果

python">{}
{'setup': ''}
{'setup': '为'}
{'setup': '为什'}
{'setup': '为什么'}
{'setup': '为什么程序'}
{'setup': '为什么程序员'}
{'setup': '为什么程序员喜'}
{'setup': '为什么程序员喜欢'}
{'setup': '为什么程序员喜欢冷'}
{'setup': '为什么程序员喜欢冷笑'}
{'setup': '为什么程序员喜欢冷笑话'}
{'setup': '为什么程序员喜欢冷笑话?'}
{'setup': '为什么程序员喜欢冷笑话?', 'punchline': ''}
{'setup': '为什么程序员喜欢冷笑话?', 'punchline': '因'}
{'setup': '为什么程序员喜欢冷笑话?', 'punchline': '因为'}
{'setup': '为什么程序员喜欢冷笑话?', 'punchline': '因为只'}
{'setup': '为什么程序员喜欢冷笑话?', 'punchline': '因为只有'}
{'setup': '为什么程序员喜欢冷笑话?', 'punchline': '因为只有他'}
{'setup': '为什么程序员喜欢冷笑话?', 'punchline': '因为只有他们'}
{'setup': '为什么程序员喜欢冷笑话?', 'punchline': '因为只有他们的'}
{'setup': '为什么程序员喜欢冷笑话?', 'punchline': '因为只有他们的电'}
{'setup': '为什么程序员喜欢冷笑话?', 'punchline': '因为只有他们的电脑'}
{'setup': '为什么程序员喜欢冷笑话?', 'punchline': '因为只有他们的电脑听'}
{'setup': '为什么程序员喜欢冷笑话?', 'punchline': '因为只有他们的电脑听得'}
{'setup': '为什么程序员喜欢冷笑话?', 'punchline': '因为只有他们的电脑听得懂'}
{'setup': '为什么程序员喜欢冷笑话?', 'punchline': '因为只有他们的电脑听得懂!'}

进程已结束,退出代码为 0

我们也可以在没有Pydantic的情况下使用JsonOutputParser。此时,它会提示模型返回JSON格式的内容,但不会提供基于Pydantic定义的那种精确、详细的模式信息。不过,我们仍可通过在提示中手动说明等方式,为模型提供一些关于输出模式的大致要求。

不使用Pydantic完整代码

python"># 从langchain_core库中导入JsonOutputParser类,用于将模型输出解析为JSON格式
from langchain_core.output_parsers import JsonOutputParser
# 从langchain_core库中导入PromptTemplate类,用于创建提示模板
from langchain_core.prompts import PromptTemplate
# 从langchain_openai库中导入ChatOpenAI类,用于调用OpenAI的聊天模型
from langchain_openai import ChatOpenAI

# 初始化ChatOpenAI模型实例,使用gpt-3.5-turbo模型,设置temperature=0不考虑随机性
chat_model = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)

# 定义一个字符串变量,作为向语言模型请求笑话的查询语句
joke_query = "请给我讲个编程的笑话,并用中文来回答"

# 创建JsonOutputParser实例,用于解析JSON输出
json_output_parser = JsonOutputParser()

# 创建 PromptTemplate 实例,定义提示模板的格式
prompt = PromptTemplate(
    # 模板字符串,包含回答查询、格式指令和用户查询三部分
    template="回答用户的查询。\n{format_instructions}\n{query}\n",
    # 指定输入变量为 query
    input_variables=["query"],
    # 部分变量,将解析器的格式指令插入到模板中
    partial_variables={"format_instructions": json_output_parser.get_format_instructions()},
)

# 使用管道操作符将提示模板、模型和解析器连接成一个处理链
chain = prompt | chat_model | json_output_parser

# 调用处理链,传入查询语句,得到处理结果
result = chain.invoke({"query": joke_query})

# 打印最终处理得到的结果
print(result)

 不使用Pydantic运行结果

python">{'response': '为什么程序员总喜欢晒代码?因为他们觉得自己的代码是最美的!'}

进程已结束,退出代码为 0

解析XML格式输出

下面我们将演示如何使用XMLOutputParser来提示模型生成XML输出,然后将该输出解析为可用的格式。

标准解析完整代码

python"># 从langchain_core库中导入XMLOutputParser类,用于将模型输出解析为XML格式
from langchain_core.output_parsers import XMLOutputParser
# 从langchain_core库中导入PromptTemplate类,用于创建提示模板
from langchain_core.prompts import PromptTemplate
# 从langchain_openai库中导入ChatOpenAI类,用于调用OpenAI的聊天模型
from langchain_openai import ChatOpenAI

# 初始化ChatOpenAI模型实例,使用gpt-4o模型,设置temperature=0不考虑随机性
chat_model = ChatOpenAI(model_name="gpt-4o", temperature=0)

# 定义一个字符串变量,作为向语言模型发送需求
actor_query = "请帮我生成Jackie Chan主演的电影作品列表,按照最新的时间降序。请用中文来回答。"

# 创建XMLOutputParser实例,用于解析XML输出
xml_output_parser = XMLOutputParser()

# 我们将在下面的提示中添加这些指令
custom_instructions = """
        输出应格式化为XML文件。
        1. 输出应符合以下标签。
        2. 如果没有给出标签,请自行创建。
        3. 记住始终要打开和关闭所有标签。
        例如,对于标签 ["foo", "bar", "baz"]:
        1. String "<foo>
          <bar>
             <baz></baz>
          </bar>
        </foo>” 是符合模式的格式良好的实例。
        2. String "<foo>
           <bar>
           </foo>” 是格式错误的实例。
        3. String "<foo>
           <tag>
           </tag>
        </foo>” 是格式错误的实例。
"""

# 创建PromptTemplate实例,定义提示模板的格式
prompt = PromptTemplate(
    # 模板字符串,包含回答查询、格式指令和用户查询三部分
    template="回答用户的查询。\n{format_instructions}\n{query}\n",
    # 指定输入变量为 query
    input_variables=["query"],
    # 部分变量,将解析器的格式指令插入到模板中
    partial_variables={"format_instructions": custom_instructions},
)

# 使用管道操作符将提示模板、模型和解析器连接成一个处理链
chain = prompt | chat_model

# 调用处理链,传入查询语句,得到处理结果
result = chain.invoke({"query": actor_query})

# 打印最终处理得到的结果
print(result.content)

标准解析运行结果

python">```xml
<filmography>
    <actor>
        <name>成龙</name>
        <movies>
            <movie>
                <title>急速追杀</title>
                <release_year>2023</release_year>
                <description>成龙与约翰·塞纳联袂出演的一部动作喜剧电影。</description>
            </movie>
            <movie>
                <title>龙马精神</title>
                <release_year>2023</release_year>
                <description>成龙饰演一名老马术表演演员,电影以马术为主题融合了温情与幽默。</description>
            </movie>
            <movie>
                <title>机器之血</title>
                <release_year>2017</release_year>
                <description>成龙主演的动作科幻电影,讲述一场围绕尖端技术展开的较量。</description>
            </movie>
            <movie>
                <title>英伦对决</title>
                <release_year>2017</release_year>
                <description>成龙饰演一位悲痛欲绝的父亲,为追查女儿遇害的真相而孤军奋战。</description>
            </movie>
            <movie>
                <title>绝地逃亡</title>
                <release_year>2016</release_year>
                <description>成龙与约翰尼·诺克斯维尔合作的一部动作喜剧电影。</description>
            </movie>
            <movie>
                <title>天将雄师</title>
                <release_year>2015</release_year>
                <description>讲述了汉朝时期西域的一位将军保护丝绸之路的故事。</description>
            </movie>
            <movie>
                <title>十二生肖</title>
                <release_year>2012</release_year>
                <description>成龙主演并执导的冒险动作电影,围绕失落的中国国家文物而展开。</description>
            </movie>
            <movie>
                <title>功夫梦</title>
                <release_year>2010</release_year>
                <description>成龙与贾登·史密斯合作的翻拍版本电影,传递了传统武术精神。</description>
            </movie>
        </movies>
    </actor>
</filmography>
```

进程已结束,退出代码为 0

我们还可以添加一些标签以根据我们的需求定制输出。我们可以在提示的其他部分中尝试添加自己的格式提示,以增强或替换默认指令。

按标签解析完整代码

python"># 从langchain_core库中导入XMLOutputParser类,用于将模型输出解析为XML格式
from langchain_core.output_parsers import XMLOutputParser
# 从langchain_core库中导入PromptTemplate类,用于创建提示模板
from langchain_core.prompts import PromptTemplate
# 从langchain_openai库中导入ChatOpenAI类,用于调用OpenAI的聊天模型
from langchain_openai import ChatOpenAI

# 初始化ChatOpenAI模型实例,使用gpt-4o模型,设置temperature=0不考虑随机性
chat_model = ChatOpenAI(model_name="gpt-4o", temperature=0)

# 定义一个字符串变量,作为向语言模型发送需求
actor_query = "请帮我生成Jackie Chan主演的电影作品列表,按照最新的时间降序。请用中文来回答。"

# 创建XMLOutputParser实例,用于解析XML输出
xml_output_parser = XMLOutputParser()

# 我们将在下面的提示中添加这些指令
custom_instructions = """
        输出应格式化为XML文件。
        1. 输出应符合以下标签。
        2. 如果没有给出标签,请自行创建。
        3. 记住始终要打开和关闭所有标签。
        例如,对于标签 ["foo", "bar", "baz"]:
        1. String "<foo>
          <bar>
             <baz></baz>
          </bar>
        </foo>” 是符合模式的格式良好的实例。
        2. String "<foo>
           <bar>
           </foo>” 是格式错误的实例。
        3. String "<foo>
           <tag>
           </tag>
        </foo>” 是格式错误的实例。

        以下是输出标签:
        '''
        ['movies', 'actor', 'film', 'name', 'genre']
"""

# 创建PromptTemplate实例,定义提示模板的格式
prompt = PromptTemplate(
    # 模板字符串,包含回答查询、格式指令和用户查询三部分
    template="回答用户的查询。\n{format_instructions}\n{query}\n",
    # 指定输入变量为 query
    input_variables=["query"],
    # 部分变量,将解析器的格式指令插入到模板中
    partial_variables={"format_instructions": custom_instructions},
)

# 使用管道操作符将提示模板、模型和解析器连接成一个处理链
chain = prompt | chat_model

# 调用处理链,传入查询语句,得到处理结果
result = chain.invoke({"query": actor_query})

# 打印最终处理得到的结果
print(result.content)

按标签解析运行结果

python">```xml
<movies>
    <actor>
        <name>成龙</name>
    </actor>
    <film>
        <name>急先锋</name>
        <genre>动作</genre>
        <year>2020</year>
    </film>
    <film>
        <name>龙牌之谜</name>
        <genre>奇幻, 冒险</genre>
        <year>2019</year>
    </film>
    <film>
        <name>机器之血</name>
        <genre>动作, 科幻</genre>
        <year>2018</year>
    </film>
    <film>
        <name>功夫瑜伽</name>
        <genre>动作, 冒险, 喜剧</genre>
        <year>2017</year>
    </film>
    <film>
        <name>铁道飞虎</name>
        <genre>动作, 冒险, 喜剧</genre>
        <year>2016</year>
    </film>
    <film>
        <name>绝地逃亡</name>
        <genre>动作, 喜剧</genre>
        <year>2016</year>
    </film>
    <film>
        <name>天将雄师</name>
        <genre>动作, 历史, 战争</genre>
        <year>2015</year>
    </film>
    <film>
        <name>警察故事2013</name>
        <genre>动作, 犯罪, 剧情</genre>
        <year>2013</year>
    </film>
    <film>
        <name>十二生肖</name>
        <genre>动作, 冒险, 喜剧</genre>
        <year>2012</year>
    </film>
</movies>
```

进程已结束,退出代码为 0

同样的,该解析器支持流式处理部分块。 

流式输出完整代码

python"># 从langchain_core库中导入XMLOutputParser类,用于将模型输出解析为XML格式
from langchain_core.output_parsers import XMLOutputParser
# 从langchain_core库中导入PromptTemplate类,用于创建提示模板
from langchain_core.prompts import PromptTemplate
# 从langchain_openai库中导入ChatOpenAI类,用于调用OpenAI的聊天模型
from langchain_openai import ChatOpenAI

# 初始化ChatOpenAI模型实例,使用gpt-4o模型,设置temperature=0不考虑随机性
chat_model = ChatOpenAI(model_name="gpt-4o", temperature=0)

# 定义一个字符串变量,作为向语言模型发送需求
actor_query = "请帮我生成Jackie Chan主演的电影作品列表,按照最新的时间降序。请用中文来回答。"

# 创建XMLOutputParser实例,并按标签解析XML输出
xml_output_parser = XMLOutputParser(tags=['movies', 'actor', 'film', 'name', 'genre'])

# 创建PromptTemplate实例,定义提示模板的格式
prompt = PromptTemplate(
    # 模板字符串,包含回答查询、格式指令和用户查询三部分
    template="回答用户的查询。\n{format_instructions}\n{query}\n",
    # 指定输入变量为 query
    input_variables=["query"],
    # 部分变量,将解析器的格式指令插入到模板中
    partial_variables={"format_instructions": xml_output_parser.get_format_instructions()},
)

# 使用管道操作符将提示模板、模型和解析器连接成一个处理链
chain = prompt | chat_model

# 每次从生成器中获取的元素chain_stream是语言模型逐步生成的部分结果
for chain_stream in chain.stream({"query": actor_query}):
    # 打印每次从生成器中获取的部分结果,方便查看模型逐步生成输出的过程
    print(chain_stream)

流式输出运行结果

python">content='' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='```' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='xml' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='<' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='movies' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='   ' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' <' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='actor' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='       ' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' <' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='name' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='成' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='龙' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='</' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='name' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='       ' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' <' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='film' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='           ' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' <' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='name' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='急' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='先锋' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='</' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='name' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='           ' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' <' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='genre' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='动作' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=',' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' 冒' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='险' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='</' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='genre' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='       ' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' </' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='film' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='       ' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' <' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='film' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='           ' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' <' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='name' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='龙' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='牌' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='之' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='谜' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='</' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='name' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='           ' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' <' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='genre' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='奇' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='幻' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=',' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' 历' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='史' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='</' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='genre' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='       ' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' </' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='film' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='       ' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' <' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='film' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='           ' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' <' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='name' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='机器' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='之' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='血' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='</' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='name' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='           ' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' <' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='genre' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='科' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='幻' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=',' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' 动' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='作' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='</' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='genre' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='       ' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' </' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='film' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='       ' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' <' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='film' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='           ' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' <' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='name' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='功' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='夫' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='瑜' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='伽' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='</' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='name' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='           ' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' <' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='genre' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='动作' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=',' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' 喜' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='剧' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='</' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='genre' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='       ' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' </' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='film' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='       ' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' <' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='film' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='           ' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' <' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='name' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='铁' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='道' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='飞' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='虎' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='</' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='name' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='           ' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' <' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='genre' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='喜' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='剧' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=',' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' 动' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='作' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='</' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='genre' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='       ' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' </' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='film' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='   ' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content=' </' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='actor' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='</' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='movies' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='>\n' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='```' additional_kwargs={} response_metadata={} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'
content='' additional_kwargs={} response_metadata={'finish_reason': 'stop', 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_b705f0c291'} id='run-d0a803c9-f3bd-4af8-92d3-030addf44842'

进程已结束,退出代码为 0

解析YAML格式输出

来自不同提供商的大型语言模型(LLMs)通常根据它们训练的具体数据具有不同的优势。这也意味着有些模型在生成JSON以外的格式输出方面可能更 “优秀” 和可靠。

这个输出解析器允许用户指定任意模式,并查询符合该模式的LLMs输出,使用YAML格式化他们的响应。

我们使用PydanticYamlOutputParser来声明我们的数据模型,并为模型提供更多关于应生成何种类型YAML的上下文信息。

标准解析完整代码

python"># 从langchain导入YamlOutputParser类,用于将输出解析为YAML格式
from langchain.output_parsers import YamlOutputParser
# 从langchain_core导入PromptTemplate类,用于创建提示模板
from langchain_core.prompts import PromptTemplate
# 从pydantic库中导入BaseModel和Field类,用于定义数据模型和字段描述
from pydantic import BaseModel, Field
# 从langchain_openai导入ChatOpenAI类,用于调用OpenAI的聊天模型
from langchain_openai import ChatOpenAI


# 定义一个名为Joke的数据模型类,继承自BaseModel
class Joke(BaseModel):
    # 定义setup属性,为字符串类型,用于存储笑话的问题,并添加描述信息
    setup: str = Field(description="设置笑话的问题")
    # 定义punchline属性,为字符串类型,用于存储笑话的答案,并添加描述信息
    punchline: str = Field(description="解答笑话的答案")


# 初始化ChatOpenAI模型。
chat_model = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)

# 创建一个查询,旨在提示语言模型填充数据结构。
joke_query = "请给我将一个关于编程的笑话。用中文来回答。"

# 初始化YamlOutputParser解析器,指定要解析成的Pydantic对象为Joke类
yaml_output_parser = YamlOutputParser(pydantic_object=Joke)

# 创建一个提示模板,包含回答查询的要求、格式指令和具体查询内容
prompt = PromptTemplate(
    # 模板内容,包含回答要求、格式指令和查询变量
    template="回答用户的查询。\n{format_instructions}\n{query}\n",
    # 定义模板中的输入变量为 query
    input_variables=["query"],
    # 部分变量,将解析器的格式指令注入到模板中
    partial_variables={"format_instructions": yaml_output_parser.get_format_instructions()},
)

# 创建一个链式处理流程,先通过提示模板处理输入,再传入模型进行处理
chain = prompt | chat_model

# 打印解析器的格式指令,方便查看
print(yaml_output_parser.get_format_instructions())

# 调用链式处理流程,传入查询内容,获取模型的响应
response = chain.invoke({"query": joke_query})

# 打印模型响应的内容
print(response.content)

标准解析运行结果

python">The output should be formatted as a YAML instance that conforms to the given JSON schema below.

# Examples
## Schema
```
{"title": "Players", "description": "A list of players", "type": "array", "items": {"$ref": "#/definitions/Player"}, "definitions": {"Player": {"title": "Player", "type": "object", "properties": {"name": {"title": "Name", "description": "Player name", "type": "string"}, "avg": {"title": "Avg", "description": "Batting average", "type": "number"}}, "required": ["name", "avg"]}}}
```
## Well formatted instance
```
- name: John Doe
  avg: 0.3
- name: Jane Maxfield
  avg: 1.4
```

## Schema
```
{"properties": {"habit": { "description": "A common daily habit", "type": "string" }, "sustainable_alternative": { "description": "An environmentally friendly alternative to the habit", "type": "string"}}, "required": ["habit", "sustainable_alternative"]}
```
## Well formatted instance
```
habit: Using disposable water bottles for daily hydration.
sustainable_alternative: Switch to a reusable water bottle to reduce plastic waste and decrease your environmental footprint.
``` 

Please follow the standard YAML formatting conventions with an indent of 2 spaces and make sure that the data types adhere strictly to the following JSON schema: 
```
{"properties": {"setup": {"description": "\u8bbe\u7f6e\u7b11\u8bdd\u7684\u95ee\u9898", "title": "Setup", "type": "string"}, "punchline": {"description": "\u89e3\u7b54\u7b11\u8bdd\u7684\u7b54\u6848", "title": "Punchline", "type": "string"}}, "required": ["setup", "punchline"]}
```

Make sure to always enclose the YAML output in triple backticks (```). Please do not add anything other than valid YAML output!
```
setup: 为什么程序员总是悲伤?
punchline: 因为他们总是在处理 BUG。
```
setup='为什么程序员总是悲伤?' punchline='因为他们总是在处理 BUG。'

进程已结束,退出代码为 0

同样的,该解析器支持流式处理部分块。

流式输出完整代码

python"># 从langchain导入YamlOutputParser类,用于将输出解析为YAML格式
from langchain.output_parsers import YamlOutputParser
# 从langchain_core导入PromptTemplate类,用于创建提示模板
from langchain_core.prompts import PromptTemplate
# 从pydantic库中导入BaseModel和Field类,用于定义数据模型和字段描述
from pydantic import BaseModel, Field
# 从langchain_openai导入ChatOpenAI类,用于调用OpenAI的聊天模型
from langchain_openai import ChatOpenAI


# 定义一个名为Joke的数据模型类,继承自BaseModel
class Joke(BaseModel):
    # 定义setup属性,为字符串类型,用于存储笑话的问题,并添加描述信息
    setup: str = Field(description="设置笑话的问题")
    # 定义punchline属性,为字符串类型,用于存储笑话的答案,并添加描述信息
    punchline: str = Field(description="解答笑话的答案")


# 初始化ChatOpenAI模型。
chat_model = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)

# 创建一个查询,旨在提示语言模型填充数据结构。
joke_query = "请给我将一个关于编程的笑话。用中文来回答。"

# 初始化YamlOutputParser解析器,指定要解析成的Pydantic对象为Joke类
yaml_output_parser = YamlOutputParser(pydantic_object=Joke)

# 创建一个提示模板,包含回答查询的要求、格式指令和具体查询内容
prompt = PromptTemplate(
    # 模板内容,包含回答要求、格式指令和查询变量
    template="回答用户的查询。\n{format_instructions}\n{query}\n",
    # 定义模板中的输入变量为 query
    input_variables=["query"],
    # 部分变量,将解析器的格式指令注入到模板中
    partial_variables={"format_instructions": yaml_output_parser.get_format_instructions()},
)

# 创建一个链式处理流程,先通过提示模板处理输入,再传入模型进行处理
chain = prompt | chat_model

# 每次从生成器中获取的元素chain_stream是语言模型逐步生成的部分结果
for chain_stream in chain.stream({"query": joke_query}):
    # 打印每次从生成器中获取的部分结果,方便查看模型逐步生成输出的过程
    print(chain_stream)

流式输出运行结果

python">content='' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='``' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='`\n' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='setup' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content=':' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content=' ' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='为' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='什' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='么' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='程序' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='员' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='总' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='是' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='选择' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='快' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='餐' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='作' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='为' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='午' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='餐' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='?\n' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='p' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='unch' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='line' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content=':' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content=' 因' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='为' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='他' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='们' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='喜' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='欢' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='用' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='字' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='节' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='填' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='饱' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='自' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='己' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='!' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='\n' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='```' additional_kwargs={} response_metadata={} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'
content='' additional_kwargs={} response_metadata={'finish_reason': 'stop', 'model_name': 'gpt-3.5-turbo', 'system_fingerprint': 'fp_0165350fbb'} id='run-743ce710-3522-416e-acec-c98ffd30c7c5'

进程已结束,退出代码为 0

结束

好了,以上就是本次分享的全部内容了。希望大家能掌握与理解今天分享的内容。今天分享的内容代码部分比较多,请大家多在自己的电脑上多去测试与调试,我相信大家肯定会有所收获的!

LangChain作为一个强大的语言模型驱动的应用程序的开源框架,在数据输入和输出方面具备独特优势。

首先,它将文本、图像、音频等多种不同形式的数据,作为输入提供给基于语言模型的应用程序或系统。这种方式极大地丰富了交互内容,提升了模型处理能力,使应用能够处理和理解更广泛的信息类型,从而更好地满足用户多样化的需求。比如在智能客服场景中,用户既可以输入文字咨询,也能发送图片、语音等,模型可综合这些信息做出更准确全面的回复。

并且,开发者能依据具体应用场景和业务需求,对基于LangChain构建的大模型应用输出结果进行个性化定制。涵盖输出结果的形式、内容、风格等多个方面。在需要数据规整呈现的场景下,可让LangChain输出特定格式的结构化数据,如JSONXMLYAML等。比如在数据分析场景中,要求模型以JSON格式输出分析结果,便于后续的数据处理和系统集成;在报告生成场景中,可定制输出风格,使其更符合正式报告的要求。

那么本次分享就到这了。最后,博主还是那句话:请大家多去大胆的尝试和使用,成功总是在不断的失败中试验出来的,敢于尝试就已经成功了一半。如果大家对博主分享的内容感兴趣或有帮助,请点赞和关注。大家的点赞和关注是博主持续分享的动力🤭,博主也希望让更多的人学习到新的知识。


http://www.niftyadmin.cn/n/5860662.html

相关文章

Qt常用控件之标签QLabel

标签QLabel QLabel 标签用来显示文本和图片&#xff0c;在 Qt 中使用频率很高。 1. Label属性 属性说明textQLabel 中的文本。textFormat文本的格式。其中 Qt::PlainText 为纯文本&#xff1b;Qt::RichText 为富文本&#xff08;支持 html 格式&#xff09;&#xff1b; Qt:…

sass中@import升级@use的使用区别与案例

在 Sass 中&#xff0c;import 和 use 都用于模块化代码&#xff0c;但二者有显著区别。以下是主要差异和具体案例说明&#xff1a; 核心区别对比 特性 import (旧版) use (新版) 作用域 全局作用域&#xff08;变量/混合易冲突&#xff09; 局部作用域&#xff08;需通过…

敏捷开发07:敏捷项目可视化管理-ScrumBoard(Scrum板)使用介绍

ScrumBoard(Scrum板)介绍 ScrumBoard&#xff08;Scrum板&#xff09;是敏捷项目管理中使用的可视化工具&#xff0c;用于跟踪和监控冲刺阶段的任务进度。 主要通过可视化的看板来管理工作&#xff0c;它可视化了敏捷开发中的工作流程、任务状态、团队角色。 Scrum 团队在各…

基于Spark和Hive的酒店数据分析与推荐系统

技术介绍前端&#xff1a;html&#xff0c;css&#xff0c;js&#xff0c;Echats 后端&#xff1a;Django 数据库&#xff1a;MySQL, Hive 推荐算法&#xff1a;基于用户的协同过滤&#xff08;UserCF&#xff09; 爬虫&#xff1a;Selenium大数据框架&#xff1a;Spark#数据分…

微信小程序实现拉卡拉支付

功能需求&#xff1a;拉卡拉支付&#xff08;通过跳转拉卡拉平台进行支付&#xff09;&#xff0c;他人支付&#xff08;通过链接进行平台跳转支付&#xff09; 1.支付操作 //支付 const onCanStartPay async (obj) > {uni.showLoading({mask: true})// 支付接口获取需要传…

阿里云子账号管理ECS权限配置全指南

阿里云子账号管理ECS权限配置全指南 ——主账号授权三步走&#xff0c;附精细化权限管控方案 一、基础版&#xff1a;授予子账号ECS全量管理权限 Step1&#xff1a;主账号登录RAM控制台 进入阿里云控制台 → 顶部导航栏点击头像 → 选择访问控制(RAM)4。左侧菜单选择用户 → …

layui 远程搜索下拉选择组件(多选)

模板使用&#xff08;lay-module/searchSelect&#xff09;&#xff0c;依赖于 jquery、layui.dist 中的 dropdown 模块实现&#xff08;所以data 格式请参照 layui文档&#xff09; <link rel"stylesheet" href"layui-v2.5.6/dist/css/layui.css" /&g…

机器学习实战(9):神经网络基础——从感知机到多层感知机

机器学习中的神经网络部分是大模型LLM训练的基础之基础&#xff0c;熟练掌握这一部分的知识和基础技能对后续理解大模型原理至关重要&#xff01; 第9集&#xff1a;神经网络基础——从感知机到多层感知机 在机器学习中&#xff0c;神经网络&#xff08;Neural Networks&#…