A I实战课程笔记00 应用2: 海报文案生成器

159 阅读8分钟

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 库中导入BlipProcessorBlipForConditionalGeneration类,这些类通常用于处理文本生成任务。

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_modelSalesforce/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")
  1. 使用requests.get函数从给定的URL获取图像数据。stream=True参数确保只下载图像的头部信息,而不是整个图像,这样可以在下载完成前开始处理图像。
  2. 通过调用raw属性获取图像的原始数据。
  3. 使用Image.open函数打开图像数据,并将其转换为PIL图像对象。
  4. 最后,使用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 方法的区别:

  1. 调用方式
    • run方法通常用于直接执行智能体,传入一个字符串作为输入。
    • invoke方法则更加灵活,可以传入一个字典作为输入,其中可以包含多个参数。
  2. 返回值
    • run方法返回一个字符串,即智能体执行后的输出。
    • invoke方法返回一个字典,其中包含智能体执行后的输出,以及其他可能的信息,如运行状态、错误信息等。
  3. 错误处理
    • run方法在执行过程中如果遇到错误,会抛出异常。
    • invoke方法可以通过设置handle_parsing_errors=True来处理解析错误,避免程序崩溃。