保姆级教程:用GLM-4v-9B快速搭建智能图片问答机器人

保姆级教程:用GLM-4v-9B快速搭建智能图片问答机器人 保姆级教程用GLM-4v-9B快速搭建智能图片问答机器人1. 前言为什么选择GLM-4v-9B想象一下这样的场景你有一堆产品图片想快速知道每张图片里有什么或者你拿到一张复杂的图表需要AI帮你分析数据趋势又或者你想让AI看懂一张照片然后回答各种关于图片内容的问题。这就是我们今天要做的——用GLM-4v-9B搭建一个智能图片问答机器人。这个模型有个很厉害的特点它不仅能看懂图片还能用中文跟你聊天告诉你图片里有什么。GLM-4v-9B是智谱AI在2024年开源的一个多模态模型有90亿参数。听起来参数很多其实它很“轻量”一张RTX 4090显卡就能跑起来。更厉害的是它能处理1120×1120的高清图片连图表里的小字都能看清楚。你可能听说过GPT-4V、Claude 3这些国外的多模态模型但GLM-4v-9B在多项评测中表现比它们还要好。而且它是开源的你可以自己部署不用担心API调用限制和费用问题。2. 环境准备5分钟搞定所有依赖2.1 基础环境搭建首先我们需要一个干净的环境。我推荐用conda来管理这样不会跟你电脑上其他项目冲突。# 创建新的Python环境 conda create -n glm4v-demo python3.10 conda activate glm4v-demo # 安装核心依赖 pip install torch torchvision torchaudio pip install transformers gradio pillow如果你有NVIDIA显卡建议安装对应CUDA版本的PyTorch。上面的命令会自动安装适合你系统的版本。2.2 模型下载与准备GLM-4v-9B模型可以从Hugging Face下载。如果你在国内下载速度可能比较慢这里有几个小技巧使用镜像源在终端设置环境变量export HF_ENDPOINThttps://hf-mirror.com提前下载如果网络不好可以先下载到本地# 使用huggingface-cli工具 pip install huggingface-hub huggingface-cli download THUDM/glm-4v-9b --local-dir ./glm-4v-9b模型大小约18GBFP16精度如果显存不够可以用INT4量化版本只要9GB。3. 快速上手第一个图片问答程序3.1 最简单的代码实现我们先写一个最简单的版本让你快速看到效果。创建一个文件叫simple_demo.pyimport torch from transformers import AutoModel, AutoTokenizer from PIL import Image import gradio as gr # 加载模型和分词器 model_path THUDM/glm-4v-9b tokenizer AutoTokenizer.from_pretrained(model_path, trust_remote_codeTrue) model AutoModel.from_pretrained( model_path, trust_remote_codeTrue, torch_dtypetorch.bfloat16, device_mapauto ).eval() def ask_about_image(image, question): 回答关于图片的问题 # 准备对话消息 messages [ {role: user, content: question, image: image} ] # 将消息转换为模型输入格式 inputs tokenizer.apply_chat_template( messages, add_generation_promptTrue, tokenizeTrue, return_tensorspt, return_dictTrue ).to(model.device) # 生成回答 with torch.no_grad(): outputs model.generate(**inputs, max_new_tokens512) response tokenizer.decode(outputs[0], skip_special_tokensTrue) return response # 创建Gradio界面 demo gr.Interface( fnask_about_image, inputs[ gr.Image(typepil, label上传图片), gr.Textbox(label你的问题, value请描述这张图片) ], outputsgr.Textbox(labelAI回答), titleGLM-4v-9B图片问答机器人, description上传图片然后问AI关于图片的任何问题 ) # 启动服务 demo.launch(server_name0.0.0.0, server_port7860)保存后运行python simple_demo.py打开浏览器访问http://localhost:7860你就能看到一个简单的图片问答界面了。3.2 试试效果上传一张图片比如一张风景照问图片里有什么一张商品图问这是什么产品价格大概多少一张图表问这张图展示了什么趋势你会看到模型不仅能识别物体还能理解场景、分析内容。比如你上传一张有猫的图片问这只猫在做什么它可能会回答一只猫正在沙发上睡觉。4. 进阶功能打造更强大的问答系统4.1 支持多轮对话刚才的版本只能问一次答一次。实际使用中我们可能需要连续问多个问题。比如先问图片里有什么接着问那个红色的物体是什么。我们来升级一下支持多轮对话import torch from transformers import AutoModel, AutoTokenizer from PIL import Image import gradio as gr class ImageChatBot: def __init__(self, model_pathTHUDM/glm-4v-9b): 初始化聊天机器人 self.tokenizer AutoTokenizer.from_pretrained( model_path, trust_remote_codeTrue ) self.model AutoModel.from_pretrained( model_path, trust_remote_codeTrue, torch_dtypetorch.bfloat16, device_mapauto ).eval() self.conversation_history [] def reset_conversation(self): 重置对话历史 self.conversation_history [] def chat(self, image, user_input): 处理用户输入并生成回复 # 如果是第一轮对话重置历史 if not self.conversation_history: self.conversation_history [ {role: user, content: user_input, image: image} ] else: # 添加用户的新消息 self.conversation_history.append( {role: user, content: user_input} ) # 准备模型输入 inputs self.tokenizer.apply_chat_template( self.conversation_history, add_generation_promptTrue, tokenizeTrue, return_tensorspt, return_dictTrue ).to(self.model.device) # 生成回复 with torch.no_grad(): outputs self.model.generate( **inputs, max_new_tokens512, temperature0.7, top_p0.9 ) response self.tokenizer.decode( outputs[0], skip_special_tokensTrue ) # 提取AI的回复去掉用户的问题 ai_response response.split(user_input)[-1].strip() # 添加到对话历史 self.conversation_history.append( {role: assistant, content: ai_response} ) return ai_response # 创建聊天机器人实例 bot ImageChatBot() def chat_interface(image, message, history): Gradio聊天界面处理函数 if image is None: return 请先上传一张图片, history # 获取AI回复 response bot.chat(image, message) # 更新聊天历史用于Gradio显示 history.append((message, response)) return , history # 创建更复杂的Gradio界面 with gr.Blocks() as demo: gr.Markdown(# ️ GLM-4v-9B智能图片聊天机器人) with gr.Row(): with gr.Column(scale1): image_input gr.Image(typepil, label上传图片) clear_btn gr.Button(清空对话) with gr.Column(scale2): chatbot gr.Chatbot(height400) msg gr.Textbox(label输入你的问题) send_btn gr.Button(发送) # 清空对话按钮的功能 def clear_chat(): bot.reset_conversation() return [] # 设置事件处理 msg.submit( chat_interface, [image_input, msg, chatbot], [msg, chatbot] ) send_btn.click( chat_interface, [image_input, msg, chatbot], [msg, chatbot] ) clear_btn.click(clear_chat, outputschatbot) demo.launch(server_name0.0.0.0, server_port7860)这个版本支持连续对话可以基于同一张图片问多个问题对话历史AI会记住之前的对话内容清空功能随时开始新的对话4.2 添加实用功能让我们再加几个实用功能让这个机器人更好用import torch from transformers import AutoModel, AutoTokenizer from PIL import Image import gradio as gr import os class EnhancedImageChatBot(ImageChatBot): def __init__(self, model_pathTHUDM/glm-4v-9b): super().__init__(model_path) self.supported_tasks { 描述图片: 请详细描述这张图片的内容, 识别物体: 图片中有哪些物体, 分析场景: 这是什么场景人们在做什么, 读取文字: 图片中有文字吗如果有请告诉我内容, 情感分析: 这张图片传达了什么情感, 创意描述: 用诗意的语言描述这张图片 } def process_image_url(self, url): 处理网络图片URL import requests from io import BytesIO try: response requests.get(url, timeout10) image Image.open(BytesIO(response.content)).convert(RGB) return image except Exception as e: return f无法加载图片{str(e)} def batch_process(self, image_folder, questions_file): 批量处理图片和问题 results [] # 读取问题 with open(questions_file, r, encodingutf-8) as f: questions [line.strip() for line in f if line.strip()] # 处理每张图片 for image_file in os.listdir(image_folder): if image_file.lower().endswith((.png, .jpg, .jpeg, .bmp)): image_path os.path.join(image_folder, image_file) image Image.open(image_path).convert(RGB) for question in questions: answer self.chat(image, question) results.append({ image: image_file, question: question, answer: answer }) self.reset_conversation() # 每张图片重新开始 return results # 创建增强版机器人 enhanced_bot EnhancedImageChatBot() def create_advanced_interface(): 创建功能更丰富的界面 with gr.Blocks(themegr.themes.Soft()) as demo: gr.Markdown( # GLM-4v-9B增强版图片问答系统 *支持图片URL、批量处理、预设问题模板* ) with gr.Tabs(): # 标签页1基础聊天 with gr.TabItem( 智能聊天): with gr.Row(): with gr.Column(scale1): image_source gr.Radio( [上传图片, 图片URL], label图片来源, value上传图片 ) image_upload gr.Image(typepil, label上传图片, visibleTrue) image_url gr.Textbox(label图片URL, visibleFalse) # 快速问题模板 gr.Markdown(### 快速提问) for task, prompt in enhanced_bot.supported_tasks.items(): gr.Button(task).click( lambda pprompt: p, outputsmsg ) with gr.Column(scale2): chatbot gr.Chatbot(height400, bubble_full_widthFalse) with gr.Row(): msg gr.Textbox( label输入问题, placeholder问AI关于图片的任何问题..., scale4 ) send_btn gr.Button(发送, variantprimary, scale1) with gr.Row(): clear_btn gr.Button(清空对话) export_btn gr.Button(导出对话) # 标签页2批量处理 with gr.TabItem( 批量处理): with gr.Row(): image_folder gr.Textbox(label图片文件夹路径) questions_file gr.Textbox(label问题文件路径每行一个问题) process_btn gr.Button(开始批量处理, variantprimary) results_display gr.JSON(label处理结果) def process_batch(folder, qfile): if not os.path.exists(folder) or not os.path.exists(qfile): return {error: 路径不存在} return enhanced_bot.batch_process(folder, qfile) process_btn.click( process_batch, [image_folder, questions_file], results_display ) # 标签页3设置 with gr.TabItem(⚙️ 设置): temperature gr.Slider(0.1, 1.0, value0.7, label温度创造性) max_tokens gr.Slider(100, 1000, value512, step50, label最大生成长度) gr.Markdown( **参数说明** - **温度**值越高回答越有创意值越低回答越确定 - **最大长度**控制AI回答的长度 ) # 动态显示/隐藏图片上传和URL输入 def toggle_input(source): if source 上传图片: return gr.update(visibleTrue), gr.update(visibleFalse) else: return gr.update(visibleFalse), gr.update(visibleTrue) image_source.change( toggle_input, inputsimage_source, outputs[image_upload, image_url] ) # 聊天功能 def chat_with_image(message, history, image_upload, image_url, image_source): # 获取图片 if image_source 上传图片: image image_upload else: image enhanced_bot.process_image_url(image_url) if isinstance(image, str): # 出错情况 return image, history if image is None: return 请先提供图片, history # 获取回复 response enhanced_bot.chat(image, message) history.append((message, response)) return , history # 连接事件 msg.submit( chat_with_image, [msg, chatbot, image_upload, image_url, image_source], [msg, chatbot] ) send_btn.click( chat_with_image, [msg, chatbot, image_upload, image_url, image_source], [msg, chatbot] ) # 清空对话 def clear_chat(): enhanced_bot.reset_conversation() return [] clear_btn.click(clear_chat, outputschatbot) return demo # 启动应用 demo create_advanced_interface() demo.launch( server_name0.0.0.0, server_port7860, shareFalse # 设置为True可以生成公开链接 )这个增强版包含了多种图片输入方式支持上传和URL快速提问模板一键问常见问题批量处理功能一次处理多张图片参数调节可以调整回答的创造性和长度美观的界面分标签页布局更清晰5. 实际应用场景5.1 电商商品分析假设你开网店每天要处理很多商品图片。这个机器人可以帮你def analyze_product_image(image, product_type): 分析商品图片 questions [ f这是什么{product_type}请详细描述, 图片中的商品有什么特点, 适合什么人群使用, 估计市场价格大概多少, 写一段吸引人的商品描述文案 ] results [] for question in questions: answer bot.chat(image, question) results.append({ question: question, answer: answer }) bot.reset_conversation() return results5.2 教育辅助工具老师可以用它来批改作业或者辅助教学def educational_assistant(image, subject): 教育辅助功能 if subject 数学: questions [ 图片中的数学题是什么, 解题步骤是什么, 答案是多少, 有没有其他解法 ] elif subject 语文: questions [ 图片中的文字内容是什么, 这段文字表达了什么中心思想, 有哪些修辞手法, 请总结段落大意 ] else: questions [请分析这张图片与学习相关的内容] return [bot.chat(image, q) for q in questions]5.3 内容创作助手自媒体创作者可以用它来获取灵感def content_creation_helper(image, platform): 内容创作助手 prompts { 小红书: 为这张图片写一段小红书风格的文案要吸引人, 微博: 写一条适合微博的短文案带话题标签, 公众号: 写一篇公众号文章的开头段落, 抖音: 写一个抖音视频的脚本大纲 } prompt prompts.get(platform, 为这张图片写一段吸引人的文案) return bot.chat(image, prompt)6. 性能优化技巧6.1 减少显存占用如果你的显卡显存不够可以试试这些方法# 方法1使用量化版本 model AutoModel.from_pretrained( THUDM/glm-4v-9b-int4, # INT4量化版本 trust_remote_codeTrue, device_mapauto ) # 方法2使用CPU卸载部分在GPU部分在CPU model AutoModel.from_pretrained( THUDM/glm-4v-9b, trust_remote_codeTrue, torch_dtypetorch.float16, device_mapauto, offload_folderoffload # 临时文件目录 ) # 方法3使用梯度检查点训练时有用 model.gradient_checkpointing_enable()6.2 提高推理速度# 启用CUDA图优化需要PyTorch 2.0 torch.backends.cuda.enable_mem_efficient_sdp(False) torch.backends.cuda.enable_flash_sdp(True) # 使用半精度推理 model.half() # 转换为FP16 # 批处理同时处理多张图片 def batch_process_images(images, questions): 批量处理多张图片 all_messages [] for img, q in zip(images, questions): all_messages.append({ role: user, content: q, image: img }) # 一次性处理所有消息 inputs tokenizer.apply_chat_template( all_messages, add_generation_promptTrue, tokenizeTrue, return_tensorspt, paddingTrue, # 自动填充 return_dictTrue ).to(model.device) with torch.no_grad(): outputs model.generate(**inputs, max_new_tokens256) responses [] for i in range(len(images)): response tokenizer.decode(outputs[i], skip_special_tokensTrue) responses.append(response) return responses6.3 缓存优化对于重复的问题可以添加缓存from functools import lru_cache import hashlib class CachedImageChatBot(ImageChatBot): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.cache {} def get_image_hash(self, image): 计算图片的哈希值 import numpy as np img_array np.array(image) return hashlib.md5(img_array.tobytes()).hexdigest() lru_cache(maxsize100) def cached_chat(self, image_hash, question): 带缓存的聊天 # 这里实际调用父类的chat方法 # 为了简化我们假设有一个方法能通过hash找到图片 return super().chat(self.get_image_by_hash(image_hash), question)7. 常见问题解决7.1 模型加载失败问题CUDA out of memory或RuntimeError: Unable to load model解决# 检查GPU内存 nvidia-smi # 如果显存不足尝试 # 1. 使用量化版本 # 2. 减少batch size # 3. 使用CPU推理速度慢 model AutoModel.from_pretrained( THUDM/glm-4v-9b, trust_remote_codeTrue, device_mapcpu # 使用CPU )7.2 图片尺寸问题问题模型要求特定尺寸的图片解决def preprocess_image(image, target_size1120): 预处理图片到模型需要的尺寸 from PIL import Image # 调整尺寸保持比例 width, height image.size scale target_size / max(width, height) new_width int(width * scale) new_height int(height * scale) resized image.resize((new_width, new_height), Image.Resampling.LANCZOS) # 创建正方形画布 canvas Image.new(RGB, (target_size, target_size), (255, 255, 255)) # 将图片放在中间 x_offset (target_size - new_width) // 2 y_offset (target_size - new_height) // 2 canvas.paste(resized, (x_offset, y_offset)) return canvas7.3 回答质量不高问题AI回答太简短或不准确解决def improve_response_quality(image, question): 通过提示工程提高回答质量 # 方法1添加系统提示 system_prompt 你是一个专业的图片分析助手。 请详细描述图片内容注意细节。 如果图片中有文字请准确识别。 如果是不清楚的内容请诚实说明。 messages [ {role: system, content: system_prompt}, {role: user, content: question, image: image} ] # 方法2调整生成参数 generation_config { max_new_tokens: 1000, # 生成更长的回答 temperature: 0.3, # 降低随机性 top_p: 0.9, # 核采样 repetition_penalty: 1.1, # 减少重复 do_sample: True } # 方法3多轮追问如果第一轮回答不够好 follow_up_questions [ 能再详细一点吗, 图片中还有哪些细节, 这些信息有什么实际意义 ] return enhanced_response8. 部署到生产环境8.1 使用Docker容器化创建DockerfileFROM pytorch/pytorch:2.0.1-cuda11.7-cudnn8-runtime WORKDIR /app # 安装依赖 COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # 复制代码 COPY . . # 下载模型或从volume挂载 RUN python -c from transformers import AutoModel; AutoModel.from_pretrained(THUDM/glm-4v-9b, trust_remote_codeTrue) # 暴露端口 EXPOSE 7860 # 启动服务 CMD [python, app.py]8.2 使用API服务创建FastAPI后端from fastapi import FastAPI, UploadFile, File from pydantic import BaseModel import uvicorn from PIL import Image import io app FastAPI(titleGLM-4v-9B图片问答API) class QuestionRequest(BaseModel): question: str image_url: str None app.post(/api/ask) async def ask_about_image( question: str, image: UploadFile File(...) ): 图片问答API接口 # 读取图片 image_data await image.read() img Image.open(io.BytesIO(image_data)).convert(RGB) # 调用模型 answer bot.chat(img, question) return { success: True, question: question, answer: answer, image_size: img.size } app.get(/health) async def health_check(): 健康检查 return {status: healthy} if __name__ __main__: uvicorn.run(app, host0.0.0.0, port8000)8.3 添加监控和日志import logging from datetime import datetime class MonitoredChatBot(ImageChatBot): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.setup_logging() def setup_logging(self): 设置日志 logging.basicConfig( levellogging.INFO, format%(asctime)s - %(name)s - %(levelname)s - %(message)s, handlers[ logging.FileHandler(fchatbot_{datetime.now().strftime(%Y%m%d)}.log), logging.StreamHandler() ] ) self.logger logging.getLogger(__name__) def chat(self, image, question): 带监控的聊天 start_time datetime.now() try: response super().chat(image, question) end_time datetime.now() # 记录日志 self.logger.info( fQuestion: {question[:50]}... | fResponse time: {(end_time - start_time).total_seconds():.2f}s | fResponse length: {len(response)} ) return response except Exception as e: self.logger.error(fError processing question: {question} | Error: {str(e)}) return 抱歉处理时出现错误9. 总结通过这个教程你应该已经掌握了快速部署5分钟就能跑起来一个图片问答机器人功能扩展从简单问答到多轮对话、批量处理性能优化如何让模型跑得更快、更省内存问题解决常见错误的处理方法生产部署如何做成真正的服务GLM-4v-9B的强大之处在于它的易用性和中文支持。你不需要复杂的配置不需要昂贵的硬件一张消费级显卡就能获得接近GPT-4V的效果。实际使用中你可以根据需求调整电商场景重点优化商品识别和描述教育场景加强文字识别和解析能力内容创作调整参数让回答更有创意最重要的是开始动手尝试。上传一张图片问几个问题看看AI怎么回答。遇到问题就回头看看对应的解决方案。多试几次你就能掌握这个强大的工具了。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。