【机器学习】GLM-4V:图片识别多模态大模型(MLLs)初探

简介: 【机器学习】GLM-4V:图片识别多模态大模型(MLLs)初探

一、引言

之前在我的第5篇热榜第一🏆文章【机器学习】Qwen-VL:基于FastAPI私有化部署你的第一个AI多模态大模型中对Qwen-VL如何基于FastAPI封装私有化接口进行了讲述,评论区有人问到如何基于GLM-4V进行私有化接口部署。那今天我们就基于FastAPI,讲述如何封装GLM-4V私有化接口。

OpenAI兼容的API接口(OpenAI-API-compatible):是个很重要的接口规范,由大模型王者OpenAI制定,简单来说就是接口名、传参方式、参数格式统一仿照OpenAI的接口方式,这样可以降低使用接口的学习与改造,做到多厂商、多模型兼容。

  • DIFY平台:自定义的接口要求复合OpenAI兼容API规范才能使用
  • vLLM、OllamaXinference等开源推理框架:接口均参照OpenAI兼容API规范

本文基于FastAPI简单实现了一个遵照OpenAI兼容接口的Qwen-VL服务端和客户端接口,用于交流学习,如有问题与建议欢迎大家留言指正!

二、GLM-4V 介绍

2.1 GLM-4V 概述

GLM-4是清华智谱AI的第4代产品,重点强调的是ALL Tools工具调用能力,并于2024年6月5日开源了GLM-4-9B版本,包括GLM-4-9B、GLM-4-9B-Chat、GLM-4-9B-Chat-1M以及对应支持1120x1120像素的多模态模型GLM-4V-9B。今天重点对GLM-4V-9B进行介绍,并给出基于FastAPI私有化部署方式。

2.2 GLM-4V 原理

该模型采用了与CogVLM2相似的架构设计,能够处理高达1120 x 1120分辨率的输入,并通过降采样技术有效减少了token的开销。为了减小部署与计算开销,GLM-4V-9B没有引入额外的视觉专家模块,采用了直接混合文本和图片数据的方式进行训练,在保持文本性能的同时提升多模态能力,模型架构如图:

2.3 GLM-4V 模型结构

通过之前的文章中讲述的使用transformers查看model结构的方法,查看模型结构如下,包含以下几个部分

  • GLMTransformer:其中包含40个GLMBlock,每个里面包含self_attention、post_attention_layernorm以及mlp模块
  • EVA2CLIPModel:包含patch_embedding和transformer模块,transformer模块包含63个TransformerLayer,每个TransformerLayer中包含input_layernorm、attention、mlp以及post_attention_layernorm模块
  • GLU(Gated Linear Unit)机制:这是一种激活函数,它通过一个门控机制来控制信息流,GLU通常由两部分组成:一个线性变换和一个门控线性变换,用于增加模型的表达能力。
ChatGLMForConditionalGeneration(
  (transformer): ChatGLMModel(
    (embedding): Embedding(
      (word_embeddings): Embedding(151552, 4096)
    )
    (rotary_pos_emb): RotaryEmbedding()
    (encoder): GLMTransformer(
      (layers): ModuleList(
        (0-39): 40 x GLMBlock(
          (input_layernorm): RMSNorm()
          (self_attention): SelfAttention(
            (query_key_value): Linear(in_features=4096, out_features=4608, bias=True)
            (core_attention): CoreAttention(
              (attention_dropout): Dropout(p=0.0, inplace=False)
            )
            (dense): Linear(in_features=4096, out_features=4096, bias=False)
          )
          (post_attention_layernorm): RMSNorm()
          (mlp): MLP(
            (dense_h_to_4h): Linear(in_features=4096, out_features=27392, bias=False)
            (dense_4h_to_h): Linear(in_features=13696, out_features=4096, bias=False)
          )
        )
      )
      (final_layernorm): RMSNorm()
    )
    (output_layer): Linear(in_features=4096, out_features=151552, bias=False)
    (vision): EVA2CLIPModel(
      (patch_embedding): PatchEmbedding(
        (proj): Conv2d(3, 1792, kernel_size=(14, 14), stride=(14, 14))
        (position_embedding): Embedding(6401, 1792)
      )
      (transformer): Transformer(
        (layers): ModuleList(
          (0-62): 63 x TransformerLayer(
            (input_layernorm): LayerNorm((1792,), eps=1e-06, elementwise_affine=True)
            (attention): Attention(
              (query_key_value): Linear(in_features=1792, out_features=5376, bias=True)
              (dense): Linear(in_features=1792, out_features=1792, bias=True)
              (output_dropout): Dropout(p=0.0, inplace=False)
            )
            (mlp): MLP(
              (activation_fn): GELUActivation()
              (fc1): Linear(in_features=1792, out_features=15360, bias=True)
              (fc2): Linear(in_features=15360, out_features=1792, bias=True)
            )
            (post_attention_layernorm): LayerNorm((1792,), eps=1e-06, elementwise_affine=True)
          )
        )
      )
      (linear_proj): GLU(
        (linear_proj): Linear(in_features=4096, out_features=4096, bias=False)
        (norm1): LayerNorm((4096,), eps=1e-05, elementwise_affine=True)
        (act1): GELU(approximate='none')
        (dense_h_to_4h): Linear(in_features=4096, out_features=13696, bias=False)
        (gate_proj): Linear(in_features=4096, out_features=13696, bias=False)
        (dense_4h_to_h): Linear(in_features=13696, out_features=4096, bias=False)
      )
      (conv): Conv2d(1792, 4096, kernel_size=(2, 2), stride=(2, 2))
    )
  )
)

三、FastAPI封装GLM-4V大模型服务接口

3.1 FastAPI 极简入门

搭建1个FastAPI服务依赖fastapi、pydantic、uvicorn三个库:

3.1.1 FastAPI

FastAPI是一个现代、快速(高性能)的Web框架,用于构建API,用Python编写。它基于标准的Python类型提示,提供自动的交互式文档和数据验证。

代码示例:

# 导入FastAPI模块
from fastapi import FastAPI
 
# 创建一个FastAPI实例
app = FastAPI()
 
# 定义一个路径操作函数
@app.get("/")
async def root():
    # 返回一个JSON响应
    return {"message": "Hello World"}
 
# 运行应用
if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

这段代码创建了一个简单的FastAPI应用,当访问根路径/时,会返回一个包含"Hello World"的消息。可以使用uvicorn运行这个应用,它是一个ASGI服务器,FastAPI是基于ASGI构建的

3.1.2 uvicorn

uvicorn是一个ASGI(Asynchronous Server Gateway Interface)服务器,用于运行现代的异步Python Web应用,如FastAPI。以下是如何使用uvicorn运行一个FastAPI应用的步骤:

假设你有一个名为main.py的文件,其中包含你的FastAPI应用:

from fastapi import FastAPI
 
app = FastAPI()
 
@app.get("/")
async def root():
    return {"message": "Hello World"}

可以使用以下命令运行你的应用:

uvicorn main:app --reload

这里的main是你的Python文件名(不包括.py扩展名),app是你的FastAPI实例的变量名。--reload标志告诉uvicorn在代码更改时自动重新加载应用,这对于开发非常有用。

3.1.3 pydantic

Pydantic是一个Python库,用于数据验证和设置管理。它被广泛用于FastAPI中,用于定义请求和响应模型,以进行数据验证和解析。

from pydantic import BaseModel
 
class Item(BaseModel):
    name: str
    description: str = None
    price: float
    tax: float = None
    tags: list = []
 
items = {
    "foo": {"name": "Foo", "price": 50.2},
    "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
    "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}
 
item = Item(**items["foo"])
print(item)
# 输出: Item(name='Foo', description=None, price=50.2, tax=None, tags=[])

3.2  GLM-4V-API服务端

3.2.1 代码示例

from fastapi import FastAPI
from pydantic import BaseModel
import uvicorn
import requests
from io import BytesIO
from modelscope import snapshot_download
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
from PIL import Image
 
 
model_dir = snapshot_download('ZhipuAI/glm-4v-9b')
#model_dir = snapshot_download('qwen/Qwen-VL-Chat')
device = "auto" 
tokenizer = AutoTokenizer.from_pretrained(model_dir,trust_remote_code=True)
glm4_vl = AutoModelForCausalLM.from_pretrained(model_dir, device_map=device, trust_remote_code=True,torch_dtype=torch.float16).eval()
 
# 创建FastAPI应用实例
app = FastAPI()
 
# 定义请求体模型,与OpenAI API兼容
class ChatCompletionRequest(BaseModel):
    model: str
    messages: list
    max_tokens: int = 50
    temperature: float = 1.0
 
# 文本生成函数
def generate_text(model: str, messages: list, max_tokens: int, temperature: float):
    
    query = messages[0]["content"][0]["text"]
    image_url =  messages[0]["content"][1]["image_url"]["url"]
    image_get_response = requests.get(image_url)
    image = None
    if image_get_response.status_code == 200:
        # 将二进制数据转换为Image对象
        image = Image.open(BytesIO(image_get_response.content)).convert("RGB")
        # 现在你可以使用image对象进行进一步的处理
    else:
        print("Failed to download image")
    print(query,image_url,image)
    
    response, history = glm4_vl.chat(tokenizer,image=image, query=query, history=None,temperature=temperature,max_length=max_tokens)
    return response
 
# 定义路由和处理函数,与OpenAI API兼容
@app.post("/v1/chat/completions")
async def create_chat_completion(request: ChatCompletionRequest):
    # 调用自定义的文本生成函数
    response = generate_text(request.model, request.messages, request.max_tokens, request.temperature)
    return {"choices": [{"message": {"content": response}}],"model": request.model}
 
# 启动FastAPI应用
if __name__ == "__main__":
    
    uvicorn.run(app, host="0.0.0.0", port=8888)

3.2.2 代码详解

  1. 环境:在代码之前建立conda环境、pip代码中依赖的库,这个地方不讲啦,可以看之前的文章
  2. 下载必要的库:如上一节讲到的fastapi、pydantic、uvicorn等用于搭建api服务的库,以及modelscope、transformers、torch,以及图片处理的库io、PIL等
  3. 下载模型:基于modelscope的snapshot_download下载模型文件,专为网络不稳定的开发者服务
  4. 实例化分词器和模型:模型基于transformers的AutoTokenizer、AutoModelForCausalLM建立分词器和模型glm4_vl
  5. 实例化FastAPI:通过app=FastAPI()创建fastapi实例
  6. 定义请求体模型:继承pydantic的BaseModel,参数需要兼容OpenAI API
  7. 从主函数开始看:通过uvicorn.run启动Fastapi实例app,配置host和port
  8. 定义app的路由:路由指向v1/chat/completions
  9. 定义app的处理函数:处理函数调用generate_text函数,传入request接收的兼容OpenAI的请求体模型。
  10. generate_text文本和图像生成:提取query、image_url,基于requests.get获得图片二进制数据,并使用Image和BytesIO将二进制数据转换为Image对象,将Image图片和query文本传入glm4_vl.chat(),基于图片和文本生成response返回
  11. API返回格式:拼接choices、message、content等构造兼容OpenAI API的返回

3.2.3 代码使用

使用CUDA_VISIBLE_DEVICES=2 python run_api_glm4vl.py启动,指定卡2运行api服务。  

 

显存占用28.35G(模型尺寸13B,根据我们之前提过很多次的经验,推理模型显存占用=模型尺寸*2=13*2=26G,差不多。Qwen-VL模型占用18.74G,整整多了10G显存)

3.3  GLM-4V-API客户端

3.3.1 代码示例

import requests
import json
 
# 定义请求的URL
url = "http://0.0.0.0:8888/v1/chat/completions"
 
# 定义请求体
data = {
        "model": "glm-4v",
        "messages":[{"role":"user","content":[{"type":"text","text":"这是什么?"},{"type":"image_url","image_url":{"url":"https://img1.baidu.com/it/u=1369931113,3388870256&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1703696400&t=f3028c7a1dca43a080aeb8239f09cc2f"}}]}],
        "max_tokens": 1024,
        "temperature": 0.5
}
# 将字典转换为JSON格式
headers = {'Content-Type': 'application/json'}
data_json = json.dumps(data)
# 发送POST请求
response = requests.post(url, data=data_json, headers=headers)
 
# 检查响应状态码
if response.status_code == 200:
    # 如果响应成功,打印响应内容
    print(response.json())
else:
    # 如果响应失败,打印错误信息
    print(f"Error: {response.status_code}, {response.text}")

3.3.2 代码要点

requests:采用requests库进行请求,requests是一个在Python中用于发送HTTP请求的库。它允许你发送各种类型的HTTP请求,如GET、POST、PUT、DELETE等,以及处理响应。requests库的一个主要优点是它的易用性和简洁的API。

请求体data定义:完全模仿OpenAI API请求结构,服务端也根据此结构规范处理。

headers请求头:接口请求格式为JSON,采用json.dumps可以将字典型的data转换为json字符串,用于请求时采用json格式传输。更多json用法可以参考之前的文章

3.3.2 代码使用

将以上客户端代码放入post_api.py中,采用python post_api.py调用服务端接口。

比如传入的图片为:

 

glm-4v输出为   “这是一张展示海滨风景的图片。图中可以看到一片宁静的海洋,海面上有几块岩石露出水面。天空呈现出深浅不一的蓝色,其中散布着一些白云。在远处,可以看到陆地和大海的交界线,以及一些小岛或陆地突起。整个场景给人一种宁静、宽广的感觉。”

qwen-vl输出为   “这是海面,可以看到远处的海平线和海岸线。天空中飘着美丽的云彩。”

看起来glm-4v的效果要好一些,主要原因:

  • 发布日期:glm-4v发布于2024年6月6日,隔着将近一年,qwen-vl发布于2023年8月22日
  • 分辨率:glm-4v是1120*1120,qwen-vl是448*448
  • 模型尺寸:glm-4v是13B,qwen-vl是9.6B

卷吧!期待Qwen2-VL的诞生!

四、总结

本文首先在引言中强调了一下OpenAI兼容API的重要性,希望引起读者重视,其次介绍了GLM-4V的原理与模型结构,最后简要讲了下FastAPI以及搭配组件,并基于FastAPI封装了OpenAI兼容API的GLM-4V大模型服务端接口,并给出了客户端实现。本文内容在工作中非常实用,希望大家能有所收获并与我交流。期待您的关注+三连!

目录
相关文章
|
21天前
|
机器学习/深度学习 数据采集 自然语言处理
【机器学习】大模型驱动下的医疗诊断应用
摘要: 随着科技的不断发展,机器学习在医疗领域的应用日益广泛。特别是在大模型的驱动下,机器学习为医疗诊断带来了革命性的变化。本文详细探讨了机器学习在医疗诊断中的应用,包括疾病预测、图像识别、基因分析等方面,并结合实际案例进行分析。同时,还展示了部分相关的代码示例,以更好地理解其工作原理。
27 3
【机器学习】大模型驱动下的医疗诊断应用
|
21天前
|
机器学习/深度学习 算法 PyTorch
【机器学习】大模型环境下的应用:计算机视觉的探索与实践
【机器学习】大模型环境下的应用:计算机视觉的探索与实践
44 1
|
2月前
|
存储 人工智能 并行计算
Pai-Megatron-Patch:围绕Megatron-Core打造大模型训练加速生态
Pai-Megatron-Patch(https://github.com/alibaba/Pai-Megatron-Patch)是阿里云人工智能平台PAI研发的围绕Nvidia MegatronLM的大模型开发配套工具,旨在帮助开发者快速上手大模型,完成大模型(LLM)相关的高效分布式训练,有监督指令微调,下游任务评估等大模型开发链路。最近一年来,我们持续打磨Pai-Megatron-Patch的性能和扩展功能,围绕Megatron-Core(以下简称MCore)进一步打造大模型训练加速技术生态,推出更多的的训练加速、显存优化特性。
|
24天前
|
机器学习/深度学习 自然语言处理 前端开发
前端大模型入门:Transformer.js 和 Xenova-引领浏览器端的机器学习变革
除了调用API接口使用Transformer技术,你是否想过在浏览器中运行大模型?Xenova团队推出的Transformer.js,基于JavaScript,让开发者能在浏览器中本地加载和执行预训练模型,无需依赖服务器。该库利用WebAssembly和WebGPU技术,大幅提升性能,尤其适合隐私保护、离线应用和低延迟交互场景。无论是NLP任务还是实时文本生成,Transformer.js都提供了强大支持,成为构建浏览器AI应用的核心工具。
224 0
|
3月前
|
机器学习/深度学习 数据采集 物联网
【机器学习】Google开源大模型Gemma2:原理、微调训练及推理部署实战
【机器学习】Google开源大模型Gemma2:原理、微调训练及推理部署实战
109 0
|
3月前
|
机器学习/深度学习 编解码 API
【机器学习】FFmpeg+Whisper:二阶段法视频理解(video-to-text)大模型实战
【机器学习】FFmpeg+Whisper:二阶段法视频理解(video-to-text)大模型实战
46 0
|
3月前
|
机器学习/深度学习 人机交互 API
【机器学习】Whisper:开源语音转文本(speech-to-text)大模型实战
【机器学习】Whisper:开源语音转文本(speech-to-text)大模型实战
167 0
|
3月前
|
机器学习/深度学习 人工智能 自然语言处理
【机器学习】ChatTTS:开源文本转语音(text-to-speech)大模型天花板
【机器学习】ChatTTS:开源文本转语音(text-to-speech)大模型天花板
126 0
|
3月前
|
机器学习/深度学习 人工智能 编解码
【机器学习】阿里Qwen-VL:基于FastAPI私有化部署你的第一个AI多模态大模型
【机器学习】阿里Qwen-VL:基于FastAPI私有化部署你的第一个AI多模态大模型
469 0
|
20天前
|
机器学习/深度学习 人工智能 自然语言处理
【MM2024】阿里云 PAI 团队图像编辑算法论文入选 MM2024
阿里云人工智能平台 PAI 团队发表的图像编辑算法论文在 MM2024 上正式亮相发表。ACM MM(ACM国际多媒体会议)是国际多媒体领域的顶级会议,旨在为研究人员、工程师和行业专家提供一个交流平台,以展示在多媒体领域的最新研究成果、技术进展和应用案例。其主题涵盖了图像处理、视频分析、音频处理、社交媒体和多媒体系统等广泛领域。此次入选标志着阿里云人工智能平台 PAI 在图像编辑算法方面的研究获得了学术界的充分认可。
【MM2024】阿里云 PAI 团队图像编辑算法论文入选 MM2024