Day 2、对开篇词中项目2的理解

74 阅读10分钟
# ---- Part 0 导入所需要的类
import os
import requests
from PIL import Image
from transformers import BlipProcessor, BlipForConditionalGeneration
from langchain.tools import BaseTool
from langchain_openai import ChatOpenAI
from langchain.agents import initialize_agent, AgentType

# ---- Part I 初始化图像字幕生成模型
# 指定要使用的工具模型(HuggingFace中的image-caption模型)
hf_model = "Salesforce/blip-image-captioning-large"

cache_dir = "/cloudide/workspace/cache"

# 确保缓存目录存在
os.makedirs(cache_dir, exist_ok=True)

print("正在初始化图像字幕生成模型...")

# 初始化处理器和工具模型
# 预处理器将准备图像供模型使用
processor = BlipProcessor.from_pretrained(hf_model, cache_dir=cache_dir)
# 然后我们初始化工具模型本身
model = BlipForConditionalGeneration.from_pretrained(hf_model, cache_dir=cache_dir)
print("初始化图像字幕生成模型成功")


# ---- Part II 定义图像字幕生成工具类
class ImageCapTool(BaseTool):
    name = "Image captioner"
    description = "使用该工具可以生成图片的文字描述,需要传入图片的URL."

    def _run(self, url: str):
        # 下载图像并将其转换为PIL对象
        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")


# ---- PartIII 初始化并运行LangChain智能体
# llm = OpenAI(temperature=0.2)
llm = ChatOpenAI(
    model=os.environ.get("LLM_MODEL_4K_FUNCTION_CALL"),
    temperature=0,
)
print("初始化大语言模型成功")
# 使用工具初始化智能体并运行
tools = [ImageCapTool()]
agent = initialize_agent(
    agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
    tools=tools,
    llm=llm,
    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 请为这张图创作合适的中文推广文案")

Part 0 导入所需要的类

1.Python自带的库:

import os
  • os: 这是Python的标准库之一,提供了与操作系统进行交互的功能。允许你处理文件和目录,包括创建、删除、修改等。

2.第三方库:

import requests
  • requests:用于发送HTTP请求,非常简单易用,可以处理GET、POST等请求,适合进行网络数据抓取和API调用。
  • PIL (Pillow):提供图像处理能力,允许打开、操作、保存图像文件,实现图像裁剪、缩放、旋转等功能。
  • transformers(特别是 BlipProcessor 和 BlipForConditionalGeneration):- Transformers库是由Hugging Face提供的,用于处理自然语言处理(NLP)和计算机视觉(CV)任务。BlipProcessor用于图像和文本的预处理,而BlipForConditionalGeneration是一个用于生成任务(如图像描述)的模型。
  • langchain.tools:- BaseTool是LangChain库的一部分,提供了一种灵活的方法来实现各种工具(工具链),用于构建基于语言模型的应用。
  • langchain_openai:- 提供与OpenAI的聊天模型(如GPT)的集成,ChatOpenAI是用于创建与OpenAI聊天的对话的工具。
  • langchain.agents:- initialize_agentAgentType是用于创建智能代理的工具,可以构建基于用户输入和状态自动采取行动的应用。

Part 1 初始化图像字幕生成模型

hf_model = "Salesforce/blip-image-captioning-large"
  • 指定了要使用的BLIP图像字幕生成模型的名称。后面这一串字符串,是这个模型的名字
cache_dir = "/cloudide/workspace/cache"定义缓存目录的路径
  • 代码将在这个路径下存储下载的模型文件,避免每次使用模型时都要重新下载。
os.makedirs(cache_dir, exist_ok=True)
  • 使用os.makedirs函数来创建缓存目录。如果该目录已经存在,exist_ok=True参数将防止抛出异常。这确保了后续代码在使用缓存目录时不会因为目录不存在而出错。(1、2这两句一起存在,这两个步骤的结合能够确保程序能够顺畅地运行,避免因缺少目录而导致的错误,同时提升效率和代码简洁性。特别是在模型训练和数据处理等需要频繁读取/写入文件的场景下,合理的目录管理是至关重要的。)
预处理器的作用: 将原始输入数据转换为模型能够理解和使用的格式。
processor = BlipProcessor.from_pretrained(hf_model, cache_dir=cache_dir)
  • 目的是使用BlipProcessor类从预训练模型中加载并初始化图像处理器。(将模型的名字,缓存目录传给**from_pretrained**这个方法)
model = BlipForConditionalGeneration.from_pretrained(hf_model, cache_dir=cache_dir)
  • 通过BlipForConditionalGeneration加载图像字幕生成模型本身。 类似地,使用from_pretrained方法,这将确保模型可用并准备好进行字幕生成。

Part 2 定义图像字幕生成工具类

def _run(self, url: str):
  • 定义了一个私有方法,用于执行生成图像字幕的任务。方法的参数 url 是图像的URL。
image = Image.open(requests.get(url, stream=True).raw).convert("RGB")
  • requests.get()方法是Python requests 库提供的一个方法,用于发送 HTTP GET 请求。GET 请求通常用于从服务器获取数据。此方法非常简单且易用,是获取网络资源的常用方式。

  • stream=True表示图像数据将被逐块下载,以允许在下载过程中进行处理。(在处理大型数据时这样做是必然的)

  • response.raw:返回一个原始流(urllib3 的 HTTPResponse 对象),可以直接用于读取未处理的数据。这使你能够以流的方式处理数据,而不需要将其完全下载到内存中。

  • Image.open(...).convert("RGB") 将获取的图像内容转换为PIL(Python Imaging Library)对象,并转换为RGB格式,以确保图像格式是模型所需要的。

  • Image.open 是 Python Imaging Library (PIL) 中的一个方法,用于打开和加载图像文件。接收的值是 requests.get(url, stream=True).raw,其类型为 requests.models.Response.raw 返回的类文件对象。这使得 Image.open() 能够读取网络上图像的原始字节并将其转换为 PIL 图像对象。

inputs = processor(image, return_tensors="pt")
  • inputs 是用 processor 对图像进行预处理后得到的字典。这个字典通常包含了对图像进行编码所需的各种信息,包括图像的张量表示和可能的其他输入数据。

  • 使用之前初始化的 processor 对象对图像进行预处理。

  • return_tensors="pt"表示返回的输入将以PyTorch张量的格式返回,以便模型可以直接使用。

  • tensors: 这个参数控制函数返回的结果是否为张量。如果设置为 True,返回的将是一个张量;如果设置为 False,则返回的是原始的 numpy 数组或其他格式。"tf" : 表示 TensorFlow 格式(TensorFlow Tensor)。"np" : 表示 Numpy 格式(Numpy array)。

out = model.generate(inputs, max_new_tokens=20)
  • model 是已经初始化的图像字幕生成模型(BlipForConditionalGeneration)。
  • generate() 方法是模型的一个特定方法,用于生成文本序列(即图像的描述)。
  • 使用 ** 运算符可以将字典中的键值对作为参数传递给 generate 方法。
  • max_new_tokens=20:这个参数指定模型生成的文本的最大长度。
caption = processor.decode(out[0], skip_special_tokens=True)
  • decode 方法通常定义在 BlipProcessor 类中。在你初始化 processor 变量时,通过 BlipProcessor.from_pretrained(...) 加载了处理器,这个方法会自动包含许多用于处理和解码数据的功能。

  • out[0] 是模型生成的第一个输出序列。

  • skip_special_tokens=True表示在解码时跳过特殊令牌(如用于填充或开始/结束的符号)。因为在自然语言处理(NLP)模型中,生成的文本通常会包含一些特殊的令牌(tokens),这些令牌用于指示特定的语义或控制模型行为。

  • 特殊令牌的种类:

    • 开始令牌(Start Token) : 通常用于标记生成文本的开始。例如,在训练过程中用来告诉模型“现在开始生成文本”。
    • 结束令牌(End Token) : 用于标记生成文本的结束,表明模型应停止生成。
    • 填充令牌(Padding Token) : 在批量处理时,由于输入序列长度不同,模型可能会填充一些默认的(无意义)令牌,以确保所有输入的长度一致。
    • 其他特殊令牌: 例如,用于区分不同句子或段落的符号,或是在多标签任务中指出特定类别的令牌。
def _arun(self, query: str):
raise NotImplementedError("This tool does not support async")
  • _arun 是一个特定的命名约定,用于表示这是一个为异步操作设计的函数的占位符。在很多框架里,成员函数或方法名以 run 结尾时,它们表示同步操作。而以 arun 结尾的版本则表示异步操作。
  • 这句话的意思是 ImageCapTool 类中定义的 _arun 方法通过其名称透露出它的目的,它是一个为处理异步任务而保留的空间,虽然目前并未实现实际的功能。在代码中,抛出 NotImplementedError 表示这个方法在当前状态下不能被调用,即使它打算将来实现异步处理。这意味着当前工具不支持异步处理。调用此方法将引发一个错误,提醒用户该功能尚未实现。

Part 3 初始化并运行LangChain智能体

llm = ChatOpenAI(
model=os.environ.get("LLM_MODEL_4K_FUNCTION_CALL"),
temperature=0,
  • llm变量被定义为一个大语言模型(LLM),在这里是利用LangChain库中的ChatOpenAI类来初始化。
  • os.environ:os 是 Python 的一个标准库,用于与操作系统进行交互。os.environ 是一个字典样式对象,包含了当前进程的环境变量。通过它,开发者可以访问和操作环境变量。
  • "LLM_MODEL_4K_FUNCTION_CALL" 可能是某个预训练的大语言模型的名称或路径
    • 环境变量就是在开发过程中,设置的一个个配置信息,比如:
export DB_HOST="localhost" export DB_USER="user" export DB_PASSWORD="password"**数据库连接信息**
export API_KEY="your_api_key_here" **API密钥**
  • mperature 是一个常用于生成模型(特别是语言模型)中的参数,用于控制生成文本的随机性和创造性。
    • 作用**:

      • 低温度(如0或接近0) :

        • 当温度设置为0时,模型会选择概率最高的单词作为输出,这样生成的文本较为确定和一致。这意味着生成的文本较少受到随机性的影响,结果更为可预测。
        • 输出通常较为保守,有助于确保生成的内容逻辑连贯且符合上下文。然而,这种方式可能会导致生成的内容缺乏多样性或创造性。
      • 适中温度(如0.5) :

        • 在这种情况下,模型会在选择单词时进行一些随机性引入。这会导致生成文本的结果具有一定的多样性,但仍然能够保持合理性。
      • 高温度(如1及以上) :

        • 更高的温度值会增加生成文本的随机性,模型可能会选择较少可能的单词。这可能导致生成的内容更为多样和创造性,但同时也可能导致内容缺乏连贯性,甚至是语义上的错误。
tools = [ImageCapTool()]

tools是一个包含初始化好的图像字幕生成工具的列表。

ImageCapTool():这不就是之前定义的,继承自BaseTool的图像字幕生成工具类吗

agent = initialize_agent(
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
tools=tools,
llm=llm,
verbose=True,
handle_parsing_errors=True,
)

目的是使用工具初始化智能体并运行

  • initialize_agent():用于创建一个智能体实例(agent是代理的意思)

  • agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION指示智能体采用“零-shot”(zero-shot)反应描述方式。这意味着该智能体不会进行任何预定义的样本学习,而是根据用户的请求即时生成响应。

  • tools=tools将之前定义的工具传递给智能体,使其能够访问和使用这些工具。

  • llm=llm将初始化好的大语言模型传递给智能体,以便智能体能够生成自然语言响应。

  • verbose=True表示在运行时输出详细信息,帮助调试和监控智能体的行为。

  • handle_parsing_errors=True允许智能体处理在解析输入时错误,确保运行的稳定性。

agent.invoke(input=f"图片链接如下:{img_url}\n 请为这张图创作合适的中文推广文案")
  • agent.invoke() 方法向智能体传递输入。这一输入包含了图像的URL以及生成推广文案的请求。