Ollama: 多模态模型

多模态模型让 AI 有了眼睛——看图说话,一目了然。

💡 提示:多模态模型(如llava、minicpm-v)比纯文本模型大2-3倍,且图像处理需要额外的视觉编码器计算,因此强烈推荐使用GPU加速。在CPU-only环境下,多模态模型的推理速度可能慢到无法实用(1-3 tok/s),8GB以上VRAM的GPU是流畅运行多模态模型的基本要求。

📋 前置知识:需要先掌握以下内容

1. 你将学到


2. 一个 SaaS 创业者的真实故事

ℹ️ 信息: 目前 Ollama 支持的多模态模型主要是 LLaVA 系列(llava、llava-llama3、minicpm-v 等)。视觉理解能力不及 GPT-4V,但对 UI 截图分析、OCR 辅助、产品描述等场景已足够实用。

💡 提示: 多模态模型推荐使用 llava:13b 而非 llava:7b——13B 版本的视觉理解能力显著提升,尤其是在需要描述细节(如 UI 元素位置、图表数据)的场景下。7B 适合简单分类,13B 适合描述和分析。

(1) 痛点:用户反馈截图看不完

Alice 的 GlobalShop 电商团队每天收到 50+ 条用户反馈,每条附带 UI 截图。手动分析截图写反馈报告太耗时,Alice 希望自动化这个过程。

(2) 解法:视觉模型自动分析截图

用 LLaVA 模型自动分析 UI 截图,生成结构化反馈报告:

BASH
ollama run llava "What UI issues do you see in this image?" /path/to/screenshot.png

3. 多模态模型架构

⚠️ 警告: 多模态模型(如 llava)比纯文本模型大 2-3 倍,且图像处理消耗更多 VRAM。8GB VRAM 的 GPU 可能只能处理低分辨率图像,高分辨率图片可能导致 OOM(内存溢出)。建议先用小图测试。

(1) 视觉语言模型(VLM)原理

100%
flowchart TD
    A[Image Input] --> B[Vision Encoder<br/>CLIP/ViT]
    B --> C[Image Embeddings]
    D[Text Input] --> E[Text Tokenizer]
    E --> F[Text Embeddings]
    C --> G[Projection Layer]
    F --> G
    G --> H[Language Model<br/>LLaMA/Mistral]
    H --> I[Text Output]
组件 作用 模型示例
Vision Encoder 提取图像特征 CLIP ViT-L/14
Projection Layer 对齐视觉与语言空间 MLP adapter
Language Model 生成文本描述 LLaMA 2 / Mistral

(2) 可用多模态模型对比

模型 参数量 大小 强项 图像类型
llava 7B 4.7 GB 通用图像描述 照片/截图/文档
llava-llama3 8B 5.5 GB 更强推理+视觉 复杂场景理解
llava:13b 13B 7.4 GB 更高精度 细节识别
minicpm-v 8B 5.2 GB OCR + 中文 文档/表格
bakllava 7B 4.7 GB 轻量快速 简单图像

▶ 示例 1: 拉取与运行 LLaVA

BASH
# Pull the multimodal model
ollama pull llava

# Basic image description (CLI with file path)
ollama run llava "Describe this image in detail" /path/to/photo.jpg

# Without image: text-only mode
ollama run llava "What is machine learning?"

输出:

TEXT 📖 仅展示
I'm a helpful AI assistant running locally on your machine...

4. CLI 图像输入方式

(1) 两种图像输入方式

⚠️ 注意:图像在送入模型前会被自动缩放到模型支持的最大分辨率(通常336×336或448×448像素)。极高分辨率的原图细节可能在此过程中丢失。如果需要模型识别图像中的小字或细节,建议先将图片裁剪到关键区域再输入,而非直接发送整张高分辨率图片。

方式 语法 适用场景
文件路径 ollama run llava "prompt" /path/to/image.jpg 本地图片,最简单
交互式 在对话中使用 .image 命令 动态输入图片

(2) 支持的图像格式

格式 扩展名 最大尺寸 说明
JPEG .jpg/.jpeg 限制内 照片首选
PNG .png 限制内 截图/含文字
WebP .webp 限制内 Web 图片
GIF .gif 仅首帧 不支持动画
⚠️ 注意: 图像会缩放到模型支持的分辨率(通常 336×336 或 448×448 像素)。极高分辨率图像细节可能丢失。

▶ 示例 2: CLI 多模态交互

BASH
# Start interactive session with image
ollama run llava

>>> .image /path/to/product-photo.jpg
>>> What product is shown and what are its key features?

# Output: The image shows a pair of premium wireless headphones...
# Key features include:
# 1. Over-ear design with memory foam cushions
# 2. Active noise cancellation
# 3. USB-C charging port visible on the left ear cup

>>> .image /path/to/chart.png
>>> Summarize the data trends shown in this chart

# Output: The chart displays quarterly revenue from 2023-2024...

输出:

TEXT 📖 仅展示
I'm a helpful AI assistant running locally on your machine...

5. REST API 多模态调用

(1) API 请求格式

和 均支持 字段,传入 Base64 编码的图像:

字段 类型 说明
images list[string] Base64 编码图像列表
每条 image string 不含 data:image/... 前缀

▶ 示例 3: REST API Base64 图像调用

BASH
# Convert image to Base64 and call API
IMAGE_BASE64=$(base64 -w 0 /path/to/photo.jpg)

curl http://localhost:11434/api/chat -d "{
  \"model\": \"llava\",
  \"messages\": [{
    \"role\": \"user\",
    \"content\": \"Describe this image\",
    \"images\": [\"$IMAGE_BASE64\"]
  }],
  \"stream\": false
}"

输出:

TEXT 📖 仅展示
{"status":"ok","data":{}}

▶ 示例 4: Python SDK 多模态调用

PYTHON
import ollama
import base64
from pathlib import Path

def analyze_image(image_path: str, prompt: str, model: str = "llava") -> str:
    """Analyze an image using a multimodal model."""
    # Read and encode image
    image_data = base64.b64encode(
        Path(image_path).read_bytes()
    ).decode("utf-8")

    response = ollama.chat(
        model=model,
        messages=[{
            "role": "user",
            "content": prompt,
            "images": [image_data]
        }],
        stream=False
    )
    return response["message"]["content"]

# Usage
result = analyze_image(
    "/path/to/screenshot.png",
    "List all UI issues you can identify in this screenshot"
)
print(result)

输出:

TEXT 📖 仅展示
# 函数定义成功

6. 实战场景

(1) 场景对比

场景 输入 模型推荐 Prompt 示例
产品描述 产品照片 llava "Describe this product for an e-commerce listing"
Bug 分析 UI 截图 llava-llama3 "What UI bugs are visible in this screenshot?"
OCR 辅助 文档扫描 minicpm-v "Extract all text from this document image"
图表解读 数据图表 llava "Summarize the trends in this data chart"
安全审查 内容图片 llava "Does this image contain any unsafe content?"

▶ 示例 5: Alice 的 UI 截图分析

PYTHON
import ollama
import base64
from pathlib import Path
import json

def analyze_ui_screenshot(image_path: str) -> dict:
    """Analyze a UI screenshot and return structured feedback."""
    image_data = base64.b64encode(
        Path(image_path).read_bytes()
    ).decode("utf-8")

    system_prompt = """You are a UI/UX expert reviewing application screenshots.
Analyze the screenshot and provide feedback in this JSON format:
{
  "issues": [{"type": "layout|color|text|accessibility", "description": "...", "severity": "high|medium|low"}],
  "summary": "Brief overall assessment"
}"""

    response = ollama.chat(
        model="llava-llama3",
        messages=[
            {"role": "system", "content": system_prompt},
            {"role": "user", "content": "Review this UI screenshot for issues",
             "images": [image_data]}
        ],
        stream=False,
        format="json",
        options={"temperature": 0.3}
    )

    try:
        return json.loads(response["message"]["content"])
    except json.JSONDecodeError:
        return {"raw": response["message"]["content"]}

# Usage
feedback = analyze_ui_screenshot("/path/to/app-screenshot.png")
print(json.dumps(feedback, indent=2))

输出:

TEXT 📖 仅展示
# 函数定义成功

7. 综合示例:多模态客服辅助系统

PYTHON
# ============================================
# Comprehensive: Multimodal customer service
# Image analysis + text chat for e-commerce
# ============================================

import ollama
import base64
from pathlib import Path
from dataclasses import dataclass
from typing import Optional

@dataclass
class MultimodalSupport:
    chat_model: str = "qwen2.5"
    vision_model: str = "llava"
    temperature: float = 0.3

    def handle_product_query(
        self, image_path: str, question: str
    ) -> str:
        """Answer product questions using image + text."""
        image_data = base64.b64encode(
            Path(image_path).read_bytes()
        ).decode("utf-8")

        response = ollama.chat(
            model=self.vision_model,
            messages=[{
                "role": "user",
                "content": f"Answer this question about the product shown: {question}",
                "images": [image_data]
            }],
            stream=False,
            options={"temperature": self.temperature}
        )
        return response["message"]["content"]

    def handle_damage_report(
        self, image_path: str, order_id: str
    ) -> str:
        """Process a damage report with photo evidence."""
        image_data = base64.b64encode(
            Path(image_path).read_bytes()
        ).decode("utf-8")

        # Step 1: Analyze damage from image
        damage_desc = ollama.chat(
            model=self.vision_model,
            messages=[{
                "role": "user",
                "content": "Describe the damage visible in this product photo. Be specific about the type and severity.",
                "images": [image_data]
            }],
            stream=False,
            options={"temperature": 0.2}
        })["message"]["content"]

        # Step 2: Generate response using chat model
        response = ollama.chat(
            model=self.chat_model,
            messages=[
                {"role": "system", "content": "You are an e-commerce customer service agent handling damage reports."},
                {"role": "user", "content": f"Order {order_id} has damage: {damage_desc}. Generate a polite response acknowledging the damage and explaining the refund/replacement process."}
            ],
            stream=False,
            options={"temperature": self.temperature}
        )
        return response["message"]["content"]

    def extract_text_from_image(
        self, image_path: str
    ) -> str:
        """OCR-like text extraction from document images."""
        image_data = base64.b64encode(
            Path(image_path).read_bytes()
        ).decode("utf-8")

        response = ollama.chat(
            model="minicpm-v",
            messages=[{
                "role": "user",
                "content": "Extract all visible text from this image. Preserve the original layout and formatting.",
                "images": [image_data]
            }],
            stream=False,
            options={"temperature": 0.1}
        )
        return response["message"]["content"]

# Usage
if __name__ == "__main__":
    service = MultimodalSupport()

    print("=== Damage Report ===")
    # print(service.handle_damage_report("damaged_item.jpg", "#12345"))

    print("=== Product Query ===")
    # print(service.handle_product_query("headphones.jpg", "Does this have noise cancellation?"))

    print("=== OCR Extraction ===")
    # print(service.extract_text_from_image("receipt.png"))

❓ 常见问题

Q 多模态模型和纯文本模型能互换吗?
A 不能。多模态模型处理图像+文本,纯文本模型只处理文本。多模态模型无图像时也可处理纯文本,但纯文本模型不能处理图像。
Q 图像分辨率会影响推理速度吗?
A 会。更高分辨率图像编码更多 token,增加推理时间。Ollama 自动缩放到模型支持的最大分辨率,无需手动调整。
Q 一张图片能包含多个问题吗?
A 可以。在 prompt 中列出多个问题,模型会逐一回答。但建议每次聚焦 1-2 个问题以获得更准确回答。
Q llava 的中文能力如何?
A llava 主要面向英文。中文图像描述建议用 minicpm-v 或 qwen2.5-vl(如果可用)。Prompt 用中文可获得中文回复。
Q 视频能处理吗?
A 当前 Ollama 多模态仅支持静态图像。视频需先提取关键帧为图片,再逐帧分析。GIF 只处理首帧。
Q Base64 编码图片太大怎么办?
A 图片先压缩到合理分辨率(如 1024px 内)。JPEG 质量设为 80 通常够用。避免发送 10MB+ 原图。

📖 小节


📝 作业

  1. 基础题(难度⭐):拉取 llava 模型,用 CLI 分析一张产品照片,描述产品特征。
  2. 进阶题(难度⭐⭐):用 Python SDK 实现图片+文本多轮对话——先分析图片内容,再基于分析结果深入提问。
  3. 挑战题(难度⭐⭐⭐):为 Alice 构建一个 UI 截图自动审查工具:输入截图,输出结构化 JSON 格式的 Bug 报告(类型、描述、严重程度),并自动分类归档。
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏