02_PictureDescription.py
应用要求:利用AI为已经制作好的海报生成1-2句解释。
part 0 导入所需要的类
import os
os库用于与操作系统进行交互。
import requests
requests库用于发送HTTP请求。
from PIL import Image
PIL,即(Python Imaging Library),用于处理图像数据。这里从PIL库中导入了Image类。
from transformers import BlipProcessor, BlipForConditionalGeneration
Hugging Face的transformers库,用于自然语言处理和计算机视觉任务。这里从transformers 库中导入BlipProcessor和BlipForConditionalGeneration类,这些类通常用于处理文本生成任务。
from langchain.tools import BaseTool
from langchain_openai import ChatOpenAI
from langchain.agents import initialize_agent, AgentType
langchain就是我们学习的用于构建基于语言模型的应用程序的框架。
BaseTool类是LangChain中定义工具的基类,用于构建智能代理的工具集。
ChatOpenAI类是LangChain中用于与OpenAI的Chat模型进行交互的类。这个类允许我们通过API与OpenAI的聊天模型进行通信,执行自然语言生成任务。
initialize_agent是一个函数,同时导入了AgentType枚举,这些都是用于初始化和配置智能代理。
Part 1 初始化图形字幕生成模型
hf_model = "Salesforce/blip-image-captioning-large"
指定我们要使用的工具模型hf_model为Salesforce/blip-image-captioning-large,Salesforce/blip-image-captioning-largeHugging Face上的一个图像字幕生成模型。
print("正在初始化图像字幕生成模型...")
processor = BlipProcessor.from_pretrained(hf_model)
model = BlipForConditionalGeneration.from_pretrained(hf_model)
print("初始化图像字幕生成模型成功")
这部分代码用于初始化处理器和工具模型。
使用BlipProcessor类的from_pretrained方法,从指定的Hugging Face模型(hf_model)中加载预处理器。加载成功的预处理器就是processor。预处理器的作用是将图像转换为模型可以理解的格式。
使用BlipForConditionalGeneration类的from_pretrained方法,从指定的Hugging Face模型(hf_model)中加载图像字幕生成模型。加载出的图像字幕生成模型存储在变量model中,这个模型将用于根据输入的图像生成文字描述。
Part 2 定义图像字幕生成工具类
class ImageCapTool(BaseTool):
name = "Image captioner"
description = "使用该工具可以生成图片的文字描述,需要传入图片的URL."
def _run(self, url: str):
image = Image.open(requests.get(url, stream=True).raw).convert("RGB")
inputs = processor(image, return_tensors="pt")
out = model.generate(**inputs, max_new_tokens=20)
caption = processor.decode(out[0], skip_special_tokens=True)
return caption
def _arun(self, query: str):
raise NotImplementedError("This tool does not support async")
这段代码定义了一个名为 ImageCapTool 的类,它继承自 BaseTool 类,用于生成图像的文字描述。这个类有两个方法:_run 和 _arun。
name = "Image captioner"
description = "使用该工具可以生成图片的文字描述,需要传入图片的URL."
这个类的 name 属性被设置为 "Image captioner",这个属性通常用于指定类的名称。
description属性被设置为"使用该工具可以生成图片的文字描述,需要传入图片的URL.",这个属性用于提供类的详细描述,它可以包含关于类的功能、用途、使用方法、注意事项等信息。在本段代码中description属性提供了 ImageCapTool 类的功能和使用方法。
_run方法
def _run(self, url: str):
self:这是一个指向类实例的引用,在 Python 中,类的方法通常需要一个self参数,它指向调用这个方法的实例。在这个方法中,self用于访问类的其他属性和方法。url: str:这是方法的参数,它是一个字符串类型的参数,用于指定需要生成描述的图片的 URL 地址。这个参数是必需的,调用这个方法时必须提供一个有效的图片 URL。
下载图像并将其转换为PIL对象
image = Image.open(requests.get(url, stream=True).raw).convert("RGB")
- 使用
requests.get函数从给定的URL获取图像数据。stream=True参数确保只下载图像的头部信息,而不是整个图像,这样可以在下载完成前开始处理图像。 - 通过调用
raw属性获取图像的原始数据。 - 使用
Image.open函数打开图像数据,并将其转换为PIL图像对象。 - 最后,使用
convert("RGB")方法将图像转换为RGB模式,确保图像具有红、绿、蓝三个颜色通道。
这段代码的作用是下载图像并转换图像格式,并将其存储在变量'image'中。
预处理图像
inputs = processor(image, return_tensors="pt")
这段代码的作用是对图像进行预处理。使用之前初始化的 processor 对图像进行预处理,准备输入到模型中。这里的 return_tensors="pt" 参数表示返回 PyTorch 张量。
生成字幕
out = model.generate(**inputs, max_new_tokens=20)
使用之前初始化的 model 生成图像的字幕。**inputs 表示将 inputs 字典中的所有键值对作为参数传递给 generate 方法。max_new_tokens=20 限制了生成的字幕的最大token数为20。
获取字幕
caption = processor.decode(out[0], skip_special_tokens=True)
使用 processor 的 decode 方法将模型生成的输出转换为可读的文本字幕。out[0] 表示取生成结果的第一个输出(通常是最有可能的输出)。skip_special_tokens=True 表示在解码过程中跳过特殊标记,只返回实际的文本内容。
_arun方法
def _arun(self, query: str):
raise NotImplementedError("This tool does not support async")
这个方法的主要功能是处理异步请求,但由于该工具不支持异步操作,所以方法中抛出了一个 NotImplementedError 异常,表示该工具不支持异步。
_arun 方法接受一个 query 参数,这个参数是一个字符串,代表异步请求的查询内容。由于 ImageCapTool 类不支持异步操作,所以在这个方法中直接抛出了一个异常,提示该工具不支持异步。如果需要使用异步操作,可以考虑使用其他支持异步的工具或者库来实现。
异步操作是一种编程模型,它允许程序在等待某些操作完成时(例如网络请求、文件读写等)继续执行其他任务,而不是阻塞在那里等待操作完成。异步操作可以提高程序的并发性和响应性,因为程序可以在等待耗时操作完成的同时处理其他任务。
Part 3 初始化并运行LangChain智能体
初始化模型
llm = ChatOpenAI(
model=os.environ.get("LLM_MODEL_4K_FUNCTION_CALL"),
temperature=0,)
print("初始化大语言模型成功")
ChatOpenAI是OpenAI提供的一个类,用于与他们的聊天模型进行交互。- 通过环境变量
LLM_MODEL_4K_FUNCTION_CALL来获取要使用的模型名称。这样,模型名称可以在运行时通过设置环境变量来指定,而不需要修改代码。 temperature参数控制生成文本的随机性。值为0表示生成的文本将是确定性的,即每次运行都会得到相同的输出。
这样我们就得到了一个初始化后的OpenAI的聊天模型,这个模型将来可以在LangChain框架中用来执行自然语言处理任务。
初始化工具
tools = [ImageCapTool()]
用之前定义的ImageCapTool类创建了工具实例,并将其放入一个列表中,将该列表存储在变量tools中。
利用模型和工具初始化智能体
agent = initialize_agent(
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
tools=tools,
llm=llm,
verbose=True,
handle_parsing_errors=True,
)
使用 initialize_agent 函数创建了一个智能体。
- 智能体的类型是
AgentType.ZERO_SHOT_REACT_DESCRIPTION,意味着它可以根据给定的任务描述和可用的工具来生成解决方案。 tools参数是之前创建的工具列表,在本次任务中我们使用自定义的ImageCapTool根据图像的URL生成图像的描述。llm参数是一个语言模型实例,这里使用我们之前已经初始化好的ChatOpenAI模型。verbose=True表示在运行过程中会输出详细的信息。handle_parsing_errors=True表示智能体将尝试处理解析错误。
运行智能体
img_url = "https://lf3-static.bytednsdoc.com/obj/eden-cn/lkpkbvsj/ljhwZthlaukjlkulzlp/eec79e20058499.563190744f903.jpg"
# agent.run(input=f"{img_url}\n请创作合适的中文推广文案")
agent.invoke(input=f"图片链接如下:{img_url}\n 请为这张图创作合适的中文推广文案")
初始化后的智能体可以通过调用其 run 或 invoke 方法来执行任务。
run和invoke方法的区别:
- 调用方式:
run方法通常用于直接执行智能体,传入一个字符串作为输入。invoke方法则更加灵活,可以传入一个字典作为输入,其中可以包含多个参数。- 返回值:
run方法返回一个字符串,即智能体执行后的输出。invoke方法返回一个字典,其中包含智能体执行后的输出,以及其他可能的信息,如运行状态、错误信息等。- 错误处理:
run方法在执行过程中如果遇到错误,会抛出异常。invoke方法可以通过设置handle_parsing_errors=True来处理解析错误,避免程序崩溃。