多模态LLM执行函数调用的技巧

8 阅读4分钟

多模态LLM执行函数调用的技巧

一、这是什么?(概念解释)

多模态LLM(Multimodal LLM) 是能够理解和处理多种类型输入(文本、图片、音频、视频等)的大语言模型。

结合函数调用:让多模态LLM不仅能"看"图片,还能根据图片内容执行相应的工具操作。

核心能力:

  • 视觉理解:识别图片中的内容(人物、场景、文字等)
  • 工具调用:根据识别结果自动调用合适的工具
  • 跨模态推理:将视觉信息转化为工具调用参数

二、有什么用?(应用场景)

场景说明
图像识别 + 天气查询识别城市地标图片,自动查询该城市天气
文字识别 + 数据录入OCR 识别图片中的文字,自动填入表单
物品识别 + 电商平台识别商品图片,自动查询价格和库存
场景理解 + 智能客服识别用户上传的故障图片,调用维修工具
图表识别 + 数据分析识别图表数据,自动生成分析报告
文生图应用根据文字描述调用AI绘画工具生成图片
图片编辑 + PS工具识别图片需要修改的部分,调用PS API

三、应用一:图像识别 + 工具调用

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import base64
import json
import os
from typing import Type, Any
import requests
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from pydantic import Field, BaseModel
from langchain_core.runnables import RunnablePassthrough
from langchain_core.tools import BaseTool
from langchain_openai import ChatOpenAI
import dotenv

dotenv.load_dotenv()

# ============ 第一步:定义天气查询工具 ============

class WeatherArgsSchema(BaseModel):
    city: str = Field(description="需要查询天气预报的目标城市")

class WeatherTool(BaseTool):
    """根据传入的城市名查询天气"""
    name: str = "weather_query"
    description: str = "当你想询问天气或与天气相关的问题时的工具"
    args_schema: Type[BaseModel] = WeatherArgsSchema

    def _run(self, city: str) -> str:
        # 调用天气 API
        return f"{city}今天晴天,温度 25°C"

# ============ 第二步:创建多模态 Prompt ============

# 关键:支持图片输入的 Prompt 格式
prompt = ChatPromptTemplate.from_messages([
    ("human", [
        {"type": "text", "text": "请获取下上传图片所在城市的天气预报"},
        {"type": "image_url", "image_url": {"url": "{image_url}"}}
    ])
])

# 用于整理天气信息的 Prompt
weather_prompt = ChatPromptTemplate.from_template(
    """请整理下传递的城市的天气预报信息,并以用户友好的方式输出。

<weather>
{weather}
</weather>"""
)

# ============ 第三步:创建多模态 LLM 并绑定工具 ============

# 使用支持视觉的模型
llm = ChatOpenAI(model="gpt-4-vision-preview")
llm_with_tools = llm.bind_tools(
    tools=[WeatherTool()],
    tool_choice="weather_query"  # 强制使用天气工具
)

# ============ 第四步:构建链 ============

chain = (
    {
        "weather": (
            {"image_url": RunnablePassthrough()}
            | prompt
            | llm_with_tools
            | (lambda msg: msg.tool_calls[0]["args"])
            | WeatherTool()
        )
    }
    | weather_prompt
    | llm
    | StrOutputParser()
)

# ============ 第五步:准备图片并调用 ============

# 方式一:使用网络图片 URL
image_url = "https://example.com/guangzhou.jpg"

# 方式二:将本地图片转换为 base64
# with open("city.jpg", "rb") as f:
#     image_data = f.read()
#     image_url = f"data:image/jpeg;base64,{base64.b64encode(image_data).decode('utf-8')}"

result = chain.invoke(image_url)
print(result)
# 输出:根据图片识别,这是广州。广州今天晴天,温度 25°C

四、应用二:文生图工具调用

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import dotenv
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
import requests
from datetime import datetime

dotenv.load_dotenv()

# ============ 第一步:定义图片生成工具 ============

@tool
def generate_image(prompt: str) -> str:
    """
    使用AI绘画工具生成图片

    Args:
        prompt: 图片描述提示词

    Returns:
        生成图片保存路径
    """
    try:
        # 调用图片生成 API(以通义万相为例)
        # 实际使用时替换为真实的 API 调用
        image_url = "https://example.com/generated_image.jpg"

        # 下载图片
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        filename = f"generated_image_{timestamp}.png"

        img_response = requests.get(image_url)
        if img_response.status_code == 200:
            with open(filename, 'wb') as f:
                f.write(img_response.content)
            return f"图片生成成功!已保存到: {filename}"
        else:
            return f"图片生成失败"

    except Exception as e:
        return f"图片生成异常: {str(e)}"

# ============ 第二步:创建 LLM 并绑定工具 ============

llm = ChatOpenAI(model="gpt-4o-mini")
llm_with_tools = llm.bind_tools([generate_image])

# ============ 第三步:构建链 ============

def extract_tool_args(msg):
    """提取工具调用参数"""
    if msg.tool_calls:
        return msg.tool_calls[0]["args"]
    else:
        # 如果 LLM 没有调用工具,使用原始消息作为提示词
        return {"prompt": msg.content}

chain = llm_with_tools | extract_tool_args | generate_image

# ============ 第四步:调用 ============

result = chain.invoke("请生成一张图片:一只可爱的猫咪在花园里")
print(result)
# 输出:图片生成成功!已保存到: generated_image_20240713_123456.png

五、流程图

┌─────────────────────────────────────────────────────────────────────────┐
│              多模态 LLM 函数调用流程                                       │
└─────────────────────────────────────────────────────────────────────────┘


  ================== 应用一:图像识别 + 工具调用 ==================

  用户上传图片              视觉LLM                 工具执行
     │                       │                        │
     ▼                       ▼                        │
  广州塔.jpg ───────────────▶│ 分析图片                │
     │                       │                        │
     │                       │ 识别出:这是广州        │
     │◀──────────────────────│                        │
     │                       │                        │
     │                       ▼                        │
     │                  决定调用工具                 │
     │                  tool_calls: [                │
     │                    {name: "weather_query",    │
     │                     args: {city: "广州"}}      │
     │                  ]                             │
     │                       │                        │
     ▼                       │                        │
  提取参数                  │                        │
  city = "广州"             │                        │
     │                       │                        │
     ▼                       ▼                        ▼
  调用天气工具 ────────────────────────────────────────▶│
     │                                        查询广州天气
     │◀───────────────────────────────────────│
     │                       │                        │
     ▼                       ▼                        ▼
  返回天气结果                                    "晴天,25°C"
     │                       │                        │
     │                       ▼                        │
     │              整理最终回答                   │
     │◀──────────────────────│                        │
  "根据图片识别,这是      │                        │
   广州。广州今天晴天,    │                        │
   温度25°C。"             │                        │


  ================== 应用二:文生图工具调用 ==================

  用户输入                 LLM                    绘画工具
     │                       │                        │
     ▼                       ▼                        │
  "生成一只可爱的猫咪 ───────▶│ 分析需求                │
   在花园里的图片"           │                        │
     │                       │                        │
     │                       │ 决定调用图片生成工具    │
     │                       │ tool_calls: [          │
     │                       │   {name: "generate_image",│
     │                       │    args: {prompt: "..."}}│
     │                       │ ]                      │
     │◀──────────────────────│                        │
     │                       │                        │
     ▼                       │                        │
  提取参数                  │                        │
  prompt = "一只可爱的...    │                        │
     │                       │                        ▼
     ▼                       ▼                    调用绘画API
  调用图片生成工具 ──────────────────────────────────────▶│
     │                                        生成图片
     │◀───────────────────────────────────────│
     │                       │                        │
     ▼                       ▼                        ▼
  返回图片路径                                    保存图片
  "图片生成成功!                                  │
   已保存到: xxx.png"                              │


  ┌─────────────────────────────────────────────────────────────────────────┐
  │                         核心要点                                         │
  └─────────────────────────────────────────────────────────────────────────┘

  1. 多模态输入 - Prompt 支持 image_url 类型
  2. 视觉理解 - LLM 识别图片内容
  3. 参数提取 - 将识别结果转换为工具参数
  4. 工具执行 - 调用外部 API 完成任务