GLM-4v-9b实战教程:将GLM-4v-9b接入企业微信机器人,支持图片提问

想象一下这个场景:你的同事在企业微信群里发了一张密密麻麻的数据图表,问“谁能帮我分析一下这张图里的趋势?”或者发了一张产品设计草图,问“这个设计有什么可以改进的地方?”。

以前,你可能需要手动打开图片,仔细研究,再组织语言回复。现在,有了GLM-4v-9b,我们可以让一个机器人来做这件事。它不仅能看懂图片,还能用中文和你流畅对话,直接把分析结果发回群里。

GLM-4v-9b是智谱AI开源的一个多模态模型,只有90亿参数,但视觉理解能力很强,尤其是在处理高分辨率图片和中文场景时,表现甚至超过了一些知名的闭源大模型。最棒的是,它部署起来相对友好,一张高端消费级显卡就能跑起来。

今天这篇教程,我就手把手带你做一件事:把一个能看懂图片、会聊天的GLM-4v-9b模型,接入到企业微信的群聊机器人里。学完这篇教程,你将拥有一个7x24小时在线的“图片分析师”,随时为你的团队提供视觉问答支持。

1. 教程目标与准备工作

在开始敲代码之前,我们先明确一下要做什么,以及需要准备哪些东西。

1.1 我们要实现什么?

最终目标是创建一个企业微信机器人,它拥有以下能力:

  1. 被@时响应:当有人在企业微信群里@这个机器人时,它会做出反应。
  2. 接收图片和文字:机器人可以接收到用户发送的图片和附带的问题文字。
  3. 调用GLM-4v-9b分析:将用户发送的图片和问题,发送给我们部署好的GLM-4v-9b模型进行处理。
  4. 返回分析结果:将模型生成的理解和分析结果,重新发送到企业微信群里。

整个流程就像是一个自动化的问答中转站。

1.2 你需要准备什么?

为了完成这个教程,你需要准备好以下几样东西:

  • 一台有显卡的Linux服务器:这是用来部署和运行GLM-4v-9b模型的。模型需要一定的GPU内存。
    • 最低要求:显存至少24GB(例如NVIDIA RTX 4090),可以运行FP16精度的完整模型。
    • 推荐配置:如果你显存紧张,可以使用INT4量化后的模型,大约需要9GB显存,这样RTX 3090或4090都能很好地运行。
    • 系统:Ubuntu 20.04/22.04或CentOS 7+等常见的Linux发行版。
  • 一个企业微信账号和企业:你需要有权限在企业微信后台创建应用(机器人)。通常由团队管理员操作。
  • 基础的命令行操作知识:需要在Linux服务器上安装软件、运行命令。
  • 基本的Python编程知识:我们会写一个简单的Web服务来桥接企业微信和AI模型。

如果你已经准备好了服务器和企业微信,那我们就正式开始。

2. 第一步:在服务器上部署GLM-4v-9b模型

我们的机器人核心是GLM-4v-9b模型,所以第一步就是把它在服务器上跑起来,并提供一个可以被调用的接口。

这里我选择使用 vLLM 来部署,因为它推理效率高,且原生支持GLM-4v-9b,配置起来非常简单。

2.1 安装基础环境

首先,通过SSH连接到你的Linux服务器。然后,我们安装必要的工具和Python环境。

# 更新系统包
sudo apt-get update && sudo apt-get upgrade -y

# 安装Python3和pip(如果尚未安装)
sudo apt-get install -y python3 python3-pip

# 安装CUDA工具包(以Ubuntu为例,请根据你的系统和CUDA版本调整)
# 这里假设已安装好NVIDIA驱动和CUDA 11.8或12.1
# 你可以去NVIDIA官网查看具体安装命令

# 安装vLLM,它会自动处理很多依赖
pip3 install vllm

2.2 下载模型并启动推理服务

GLM-4v-9b的模型权重在Hugging Face上。我们可以直接用vLLM的命令来启动一个OpenAI兼容的API服务。

# 使用vLLM启动GLM-4v-9b模型服务
# 将 <你的模型下载路径> 替换成你希望保存模型的目录,例如 /home/user/models
# --tensor-parallel-size 2 表示使用两张GPU卡,如果你只有一张卡,就改成1,并确保显存足够(INT4量化约需9GB)
vllm serve THUDM/glm-4v-9b \
  --port 8000 \
  --api-key token-abc123 \ # 设置一个简单的API密钥,用于基础验证
  --served-model-name glm-4v-9b \
  --tensor-parallel-size 1 # 根据你的GPU数量修改

第一次运行会下载模型,可能需要较长时间。下载完成后,你会看到服务在8000端口启动成功的日志。

这个服务提供了一个和OpenAI Chat API格式兼容的接口。这意味着我们可以像调用GPT一样调用它。

2.3 测试模型服务是否正常

打开另一个终端,或者用curl命令测试一下服务是否正常。

curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer token-abc123" \
  -d '{
    "model": "glm-4v-9b",
    "messages": [
      {"role": "user", "content": "请用中文描述这张图片。", "image_url": "https://example.com/sample.jpg"}
    ],
    "max_tokens": 500
  }'

注意,上面的 image_url 需要替换成一个真实可访问的图片URL地址。如果模型服务正常,它会返回一段JSON格式的文本,其中包含模型对图片的描述。

恭喜!至此,你的“AI大脑”已经部署完毕,并准备好接收指令了。 接下来,我们要搭建一个“中转站”,用来接收企业微信的消息,然后转发给这个AI大脑,再把答案送回去。

3. 第二步:创建桥接Web服务(中转站)

企业微信机器人通过一个你提供的URL(称为“回调地址”)来发送消息和接收回复。我们需要用Python写一个简单的Web应用,作为这个回调地址。

这个应用要做三件事:

  1. 验证企业微信发来的请求(首次配置时需要)。
  2. 接收用户发送的消息(包含图片)。
  3. 把消息整理成GLM-4v-9b能理解的格式,调用上一步启动的模型API,拿到结果后再回复给企业微信。

我们使用轻量级的 Flask 框架来实现。

3.1 安装Flask并编写应用代码

在你的服务器上,创建一个新的项目目录,并安装Flask。

mkdir wechat-ai-bot && cd wechat-ai-bot
pip3 install flask requests

然后,创建一个名为 app.py 的文件,并输入以下代码。代码中有详细的注释,帮你理解每一步在做什么。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import hashlib
import json
import time
import requests
from flask import Flask, request, jsonify
import base64
import io
from PIL import Image
import os

app = Flask(__name__)

# ========== 配置区域 ==========
# 1. 你的GLM-4v-9b模型API地址和密钥
VLLM_API_URL = "http://localhost:8000/v1/chat/completions"
VLLM_API_KEY = "token-abc123"  # 与启动vLLM时设置的保持一致

# 2. 企业微信机器人配置(稍后在企业微信后台获取)
WECHAT_CORP_ID = "你的企业ID"  # 替换
WECHAT_AGENT_ID = "你的应用AgentId"  # 替换
WECHAT_SECRET = "你的应用Secret"  # 替换
WECHAT_TOKEN = "你自己设定的Token"  # 替换,用于验证,如“MyAIBotToken”
WECHAT_AES_KEY = "你自己设定的EncodingAESKey"  # 替换,43位字符串
# =============================

def download_image_from_url(url):
    """从URL下载图片并转换为base64编码(GLM-4v-9b API所需格式)"""
    try:
        response = requests.get(url, timeout=10)
        response.raise_for_status()
        image_data = response.content
        # 将二进制图片数据转换为base64字符串
        base64_str = base64.b64encode(image_data).decode('utf-8')
        # 构造符合OpenAI格式的image_url对象
        return {"url": f"data:image/jpeg;base64,{base64_str}"}
    except Exception as e:
        print(f"下载图片失败: {e}")
        return None

def call_glm4v_api(user_text, image_data_list):
    """调用GLM-4v-9b的vLLM API"""
    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {VLLM_API_KEY}"
    }

    # 构造消息内容,GLM-4v-9b支持多模态输入
    messages_content = []
    # 如果有图片,先添加图片
    for img_data in image_data_list:
        messages_content.append({
            "type": "image_url",
            "image_url": img_data
        })
    # 再添加文本问题
    if user_text:
        messages_content.append({
            "type": "text",
            "text": user_text
        })

    payload = {
        "model": "glm-4v-9b",
        "messages": [
            {
                "role": "user",
                "content": messages_content
            }
        ],
        "max_tokens": 1024
    }

    try:
        response = requests.post(VLLM_API_URL, headers=headers, json=payload, timeout=60)
        response.raise_for_status()
        result = response.json()
        # 提取模型返回的文本内容
        reply_text = result['choices'][0]['message']['content']
        return reply_text.strip()
    except Exception as e:
        print(f"调用GLM-4v API失败: {e}")
        return f"抱歉,AI模型处理时出现了错误: {str(e)}"

@app.route('/wechat', methods=['GET', 'POST'])
def wechat_callback():
    """企业微信机器人的回调地址"""
    if request.method == 'GET':
        # 企业微信首次验证回调地址
        signature = request.args.get('msg_signature', '')
        timestamp = request.args.get('timestamp', '')
        nonce = request.args.get('nonce', '')
        echostr = request.args.get('echostr', '')

        # 这里简化处理,实际生产环境需要按照企业微信文档进行消息加解密验证
        # 为了教程简单,我们假设验证通过,直接返回echostr
        # 注意:正式使用请务必实现完整的加解密逻辑!
        print(f"收到验证请求: signature={signature}")
        return echostr

    elif request.method == 'POST':
        # 接收用户发送的消息
        data = request.get_json()
        print(f"收到消息: {json.dumps(data, indent=2, ensure_ascii=False)}")

        # 提取消息类型和内容(这里处理文本和图片消息)
        msg_type = data.get('MsgType')
        from_user = data.get('FromUserName')
        # 企业微信的群聊消息中,ToUserName是你的机器人ID
        # 我们只处理@了机器人的消息,这里简单判断消息内容是否包含@机器人
        # 更精确的做法是解析消息中的@列表
        content = data.get('Content', '')

        # 判断是否是@机器人的消息(简单版:检查消息是否以@机器人开头)
        robot_user_id = data.get('ToUserName', '')
        if not (f"@{robot_user_id}" in content or msg_type == 'image'):
            # 如果不是@机器人的文本消息,也不是图片消息,则不回复
            return jsonify({})

        user_text = content.replace(f"@{robot_user_id}", "").replace(f"@{robot_user_id}\\n", "").strip()

        image_data_list = []
        # 处理图片消息
        if msg_type == 'image':
            pic_url = data.get('PicUrl')
            if pic_url:
                image_data = download_image_from_url(pic_url)
                if image_data:
                    image_data_list.append(image_data)
                else:
                    reply = "图片下载失败,请稍后重试。"
                    return jsonify({
                        "msgtype": "text",
                        "text": {
                            "content": reply
                        }
                    })
            # 如果图片消息还附带文字(企业微信中图片和文字是分开发送的,需要会话上下文关联,这里简化)
            # 实际开发中,你需要维护一个简单的上下文来关联同一用户短时间内发送的图片和文字

        # 调用GLM-4v-9b模型获取回复
        ai_reply = call_glm4v_api(user_text, image_data_list)

        # 将回复消息返回给企业微信
        return jsonify({
            "msgtype": "text",
            "text": {
                "content": ai_reply
            }
        })

if __name__ == '__main__':
    # 运行Flask应用,监听5000端口
    # host='0.0.0.0' 让服务可以被外部访问(确保服务器防火墙开放5000端口)
    app.run(host='0.0.0.0', port=5000, debug=False)

3.2 运行并测试桥接服务

保存好 app.py 后,在终端运行它:

python3 app.py

你应该能看到输出,表明Flask应用已经在 http://0.0.0.0:5000 上运行。

现在,我们可以先模拟企业微信的请求,测试一下整个链路是否通畅。打开另一个终端,使用curl命令模拟发送一个带图片URL的请求到我们的桥接服务(假设你的服务器IP是 192.168.1.100)。

curl -X POST http://192.168.1.100:5000/wechat \
  -H "Content-Type: application/json" \
  -d '{
    "ToUserName": "robot_user_id",
    "FromUserName": "test_user",
    "MsgType": "image",
    "PicUrl": "https://example.com/sample-chart.jpg",
    "Content": "@robot_user_id 请分析一下这张图表的主要趋势。"
  }'

如果一切正常,这个请求会被 app.py 接收,它会下载图片,调用本地的GLM-4v-9b模型API,并将模型返回的分析结果打印在Flask的日志里(或者包含在curl的响应中)。

到这里,我们的“中转站”也搭建好了,并且和“AI大脑”成功联调。 最后一步,就是去企业微信后台,把这个“中转站”的地址告诉企业微信,完成机器人的创建。

4. 第三步:配置企业微信机器人

这是最后一步,也是将AI能力暴露给真实用户的关键一步。

4.1 创建企业微信应用(机器人)

  1. 登录 企业微信管理后台
  2. 进入“应用管理” -> “应用” -> “创建应用”。
  3. 填写应用名称(例如“AI图片助手”)、选择可见范围(哪些部门或成员可以使用),然后创建。
  4. 创建成功后,进入应用详情页,记录下以下关键信息,并填入我们之前 app.py 的配置区域:
    • AgentId:应用ID。
    • Secret:应用密钥(需要点击“查看”获取,务必保密)。

4.2 配置接收消息(回调地址)

企业微信需要知道把消息发送到哪里,这就是我们刚刚写的Flask服务。

  1. 在应用详情页,找到“接收消息”设置,点击“配置”。
  2. 你需要提供一个公网可访问的URL。你的服务器必须有公网IP,并且防火墙开放了5000端口。
    • URL:填写 http://你的公网IP:5000/wechat (如果你有域名,并配置了反向代理到5000端口,也可以用域名)。
    • Token:填写你在 app.py 中设置的 WECHAT_TOKEN(例如“MyAIBotToken”)。
    • EncodingAESKey:点击“随机生成”或手动输入,然后填入 app.pyWECHAT_AES_KEY
  3. 点击“保存”。此时,企业微信会向你的URL发送一个GET请求进行验证。我们代码中简化处理直接返回了echostr,所以理论上会验证成功。但在生产环境,你必须实现完整的加解密逻辑,可以参考企业微信提供的Python SDK
  4. 保存成功后,在“企业微信”客户端,找到你刚刚创建的应用,把它拉到某个群聊中。现在,这个机器人就已经在群里了。

4.3 在群聊中测试

现在,激动人心的时刻到了!

  1. 在你添加了机器人的企业微信群里,尝试@它。
  2. 发送一张图片,并配上你的问题,比如“这张图里有什么?”或者“总结一下这个表格的数据”。
  3. 稍等片刻(取决于图片大小和模型推理速度),你应该就能收到机器人返回的、由GLM-4v-9b生成的详细分析结果了!

5. 总结与进阶思考

通过以上三步,我们成功地将强大的GLM-4v-9b多模态模型接入了企业微信,打造了一个能看懂图片的群聊助手。回顾一下我们的工作:

  1. 部署模型:利用vLLM高效部署GLM-4v-9b,提供了一个标准的API接口。
  2. 搭建桥梁:用Python Flask编写了一个轻量的Web服务,负责在企业微信和AI模型之间传递消息和图片。
  3. 配置上线:在企业微信后台完成机器人创建和回调配置,让服务落地到实际办公场景。

这个方案只是一个起点,你可以在此基础上做很多优化和扩展:

  • 消息加解密:为了安全,务必按照企业微信官方文档实现完整的消息加解密逻辑。
  • 上下文管理:让机器人能记住同一会话中之前的图片和对话,进行多轮交互。
  • 异步处理:对于耗时的图片分析,可以使用异步任务队列(如Celery),先回复“正在处理”,处理完成后再@用户发送结果。
  • 多模型路由:除了GLM-4v-9b,你还可以接入其他模型(如文本生成、语音合成),根据消息类型智能调用不同的模型。
  • 权限与审计:增加对使用者的权限控制,并记录所有的问答日志,用于分析和改进。

GLM-4v-9b开源且性能优异,特别适合对中文场景和高分辨率图片理解有要求的内部工具开发。希望这篇教程能帮你打开思路,将先进的AI能力快速、低成本地融入到日常工作中,真正提升团队效率。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐