3、LangChain基础:LangChain Tools & Agent

Multimode 集成

多模态数据传输

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

在这个例子中,我们将要求模型描述一幅图像。

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"
from langchain_core.messages import HumanMessage
from langchain_openai import ChatOpenAI

model = ChatOpenAI(model="gpt-4o")

API 参考:HumanMessage | ChatOpenAI

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

import base64
import httpx

image_data = base64.b64encode(httpx.get(image_url).content).decode("utf-8")
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)
这张图片展示了一个晴朗的天气。天空中有一些淡淡的云,阳光明媚,照亮了图中的草地和木板路。天空呈现出明亮的蓝色,与绿色的草地形成了鲜明的对比。整体感觉是非常清新和舒适的,适合户外活动和散步。

我们可以在“image_url”类型的内容块中直接提供图像 URL。请注意,只有部分模型提供商支持此功能。

message = HumanMessage(
    content=[
        {
   "type": "text", "text": "用中文描述这张图片中的天气"},
        {
   "type": "image_url", "image_url": {
   "url": image_url}},
    ],
)
response = model.invoke([message])
print(response.content)
图片中的天气晴朗,天空中有一些稀薄的白云,整体呈现出蓝色。阳光明媚,光线充足,草地和树木显得非常绿意盎然。这种天气非常适合户外活动,比如散步或野餐。总的来说,天气非常舒适宜人。

我们还可以传入多幅图像。

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)
这两张图片不一样。第一张是一个晴天的草地景色,有一条木板小路通向远方;第二张是一个覆盖着雪的村庄,有多栋房屋和一些红色灯笼。两张图片显示的是完全不同的场景。

工具调用

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

from typing import Literal
from langchain_core.messages import HumanMessage
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool


@tool
def weather_tool(weather: Literal["晴朗的", "多云的", "多雨的","下雪的"]) -> None:
    """Describe the weather"""
    pass


model = ChatOpenAI(model="gpt-4o")
model_with_tools = model.bind_tools([weather_tool])
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"
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=[
        {
   "type": "text", "text": "用中文描述两张图片中的天气"},
        {
   "type": "image_url", "image_url": {
   "url": image_url_1}},
        {
   "type": "image_url", "image_url": {
   "url": image_url_2}},
    ],
)
response = model_with_tools.invoke([message])
print(response.tool_calls)

API 参考:工具

[{
   'name': 'weather_tool', 'args': {
   'weather': '晴朗的'}, 'id': 'call_7vbVxf7xnHvBqpO5SkVCt5xq', 'type': 'tool_call'}, {
   'name': 'weather_tool', 'args': {
   'weather': '下雪的'}, 'id': 'call_zm5zOZgSTd8R57N23aBbIfwX', 'type': 'tool_call'}]

Ouput parsers: JSON, XML

如何解析 JSON 输出

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

请记住,大型语言模型是有泄漏的抽象!您必须使用具有足够容量的大型语言模型来生成格式良好的 JSON。

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

以下是如何将其与 Pydantic 一起使用以方便地声明预期模式的示例:

%pip install -qU langchain langchain-openai
from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import PromptTemplate
from pydantic import BaseModel, Field
from langchain_openai import ChatOpenAI
model = ChatOpenAI(temperature=0)
# 定义您期望的数据结构。
class Joke(BaseModel):
    setup: str = Field(description="设置笑话的问题")
    punchline: str = Field(description="解决笑话的答案")
# 还有一个用于提示语言模型填充数据结构的查询意图。
joke_query = "告诉我一个笑话。"
# 设置解析器 + 将指令注入提示模板。
parser = JsonOutputParser(pydantic_object=Joke)
prompt = PromptTemplate(
    template="回答用户的查询。\n{format_instructions}\n{query}\n",
    input_variables=["query"],
    partial_variables={
   "format_instructions": parser.get_format_instructions()},
)
chain = prompt | model | parser
chain.invoke({
   "query": joke_query})
{'setup': '为什么计算机不能得感冒?', 'punchline': '因为它们有很好的防火墙!'}

langchain v0.3与pydantic_v1 兼容问题,调整引用方式

#langchain v0.2 使用以下引用pydantic
from langchain_core.pydantic_v1 import BaseModel, Field
#langchain v0.3 使用以下引用pydantic
from pydantic import BaseModel, Field
sys:1: LangChainDeprecationWarning: As of langchain-core 0.3.0, LangChain uses pydantic v2 internally. The langchain_core.pydantic_v1 module was a compatibility shim for pydantic v1, and should no longer be used. Please update the code to import from Pydantic directly.

For example, replace imports like: `from langchain_core.pydantic_v1 import BaseModel`
with: `from pydantic import BaseModel`
or the v1 compatibility namespace if you are working in a code base that has not been fully upgraded to pydantic 2 yet. 	from pydantic.v1 import BaseModel

请注意,我们将解析器中的 format_instructions 直接传递到提示中。您可以并且应该尝试在提示的其他部分中添加自己的格式提示,以增强或替换默认指令:

parser.get_format_instructions()
'输出应格式化为符合以下 JSON 模式的 JSON 实例。\n\n例如,对于模式 {"properties": {"foo": {"title": "Foo", "description": "字符串列表", "type": "array", "items": {"type": "string"}}}, "required": ["foo"]},对象 {"foo": ["bar", "baz"]} 是该模式的格式良好实例。对象 {"properties": {"foo": ["bar", "baz"]}} 不是格式良好的。\n\n这是输出模式:\n```\n{"properties": {"setup": {"title": "Setup", "description": "设置笑话的问题", "type": "string"}, "punchline": {"title": "Punchline", "description": "解决笑话的答案", "type": "string"}}, "required": ["setup", "punchline"]}\n```'

流式处理

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

for s in chain.stream({
   "query": joke_query}):
    print(s)
{}
{'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': '因为它们有很好的防火墙!'}'


你也可以在没有 Pydantic 的情况下使用 JsonOutputParser。这将提示模型返回 JSON,但不提供关于模式应该是什么的具体信息。

## 没有 Pydantic
joke_query = "告诉我一个笑话。"
parser = JsonOutputParser()
prompt = PromptTemplate(
    template="回答用户的查询。\n{format_instructions}\n{query}\n",
    input_variables=["query"],
    partial_variables={
   "format_instructions"

你可能感兴趣的:(AI大模型应用开发技术路线,langchain,人工智能,AI编程)