构建视觉、语音与文本融合的AI系统

前言

多模态大模型能够同时处理文本、图像、音频等多种类型的输入,大大扩展了 AI 应用的边界。本文将介绍如何利用多模态能力构建强大的应用系统。


多模态概述

什么是多模态

┌─────────────────────────────────────────────────────────────────┐
│                      多模态输入输出                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  输入模态                   多模态模型              输出模态     │
│  ┌──────────┐                                    ┌──────────┐  │
│  │   文本   │──┐           ┌─────────┐        ┌──│   文本   │  │
│  └──────────┘  │           │         │        │  └──────────┘  │
│  ┌──────────┐  │           │  GPT-4V │        │  ┌──────────┐  │
│  │   图像   │──┼──────────>│  Gemini │────────┼──│   图像   │  │
│  └──────────┘  │           │  Claude │        │  └──────────┘  │
│  ┌──────────┐  │           │         │        │  ┌──────────┐  │
│  │   音频   │──┘           └─────────┘        └──│   音频   │  │
│  └──────────┘                                    └──────────┘  │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

主流多模态模型

模型 支持模态 特点
GPT-4V/GPT-4o 文本、图像、音频 OpenAI 旗舰
Claude 3 文本、图像 长上下文
Gemini 文本、图像、音频、视频 原生多模态
LLaVA 文本、图像 开源方案
Qwen-VL 文本、图像 国产开源

图像理解

GPT-4V 图像分析

from openai import OpenAI
import base64

client = OpenAI()

def encode_image(image_path: str) -> str:
    """将图像编码为 base64"""
    with open(image_path, "rb") as f:
        return base64.b64encode(f.read()).decode("utf-8")

def analyze_image(image_path: str, prompt: str = "描述这张图片") -> str:
    """分析图像内容"""
    
    base64_image = encode_image(image_path)
    
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {
                "role": "user",
                "content": [
                    {"type": "text", "text": prompt},
                    {
                        "type": "image_url",
                        "image_url": {
                            "url": f"data:image/jpeg;base64,{base64_image}",
                            "detail": "high"  # low, high, auto
                        }
                    }
                ]
            }
        ],
        max_tokens=1000
    )
    
    return response.choices[0].message.content

# 使用
result = analyze_image("photo.jpg", "这张图片中有什么?请详细描述。")
print(result)

进阶:多模态 RAG (Visual RAG)

传统的 RAG 只能检索文本。多模态 RAG 允许用户通过文本搜索图像,或者通过图像搜索相关的文档。

核心技术:CLIP (Contrastive Language-Image Pre-training)

CLIP 模型将图像和文本映射到同一个向量空间。这意味着“猫的图片”和“猫这个词”的向量距离非常近。

实现流程

  1. 多模态嵌入:使用 CLIP 或 OpenAI 的 text-embedding-3 (虽然它主要针对文本,但多模态模型如 GPT-4o 的内部表示是统一的) 对图像和文本进行向量化。
  2. 向量存储:将图像向量存入向量数据库(如 Milvus, Pinecone)。
  3. 跨模态检索:用户输入“红色的跑车”,系统检索出向量最接近的图片。
# 使用 Sentence-Transformers 加载 CLIP 模型进行检索
from sentence_transformers import SentenceTransformer, util
from PIL import Image

# 加载模型
model = SentenceTransformer('clip-ViT-B-32')

# 编码图像
img_emb = model.encode(Image.open('car.jpg'))

# 编码文本
text_emb = model.encode(['a red sports car', 'a blue truck', 'a cat'])

# 计算相似度
cos_scores = util.cos_sim(img_emb, text_emb)
print(f"相似度分数: {cos_scores}")

视频分析:帧采样策略

目前大多数多模态模型(如 GPT-4o)处理视频的本质是帧采样

处理步骤

  1. 采样:从视频中每秒提取 1-2 帧。
  2. 拼接/序列化:将提取的图片作为一组输入发送给模型。
  3. 上下文关联:模型结合时间戳信息理解动作的连贯性。
import cv2
import base64

def process_video(video_path: str, seconds_per_frame: int = 2):
    video = cv2.VideoCapture(video_path)
    base64_frames = []
    
    while video.isOpened():
        success, frame = video.read()
        if not success:
            break
        
        # 按频率采样
        fps = video.get(cv2.CAP_PROP_FPS)
        frame_id = int(video.get(cv2.CAP_PROP_POS_FRAMES))
        
        if frame_id % int(fps * seconds_per_frame) == 0:
            _, buffer = cv2.imencode(".jpg", frame)
            base64_frames.append(base64.b64encode(buffer).decode("utf-8"))
            
    video.release()
    return base64_frames

# 将 base64_frames 放入 GPT-4o 的 messages 列表中发送

架构深度解析:LLaVA 是如何工作的?

LLaVA (Large Language-and-Vision Assistant) 是开源多模态领域的标杆。它的架构非常优雅:

  1. Vision Encoder (视觉编码器):通常使用 CLIP-ViT-L/14。它负责将图片“看”成一堆特征向量。
  2. Projection Layer (投影层/连接器):这是一个简单的线性层或 MLP。它的作用是将视觉特征的维度“翻译”成 LLM 能理解的维度。
  3. LLM Backbone (语言模型核心):如 Llama 3Vicuna。它接收文本 Token 和经过投影的视觉特征,像处理文本一样处理视觉信息。

这种架构的启示:你不需要从头训练一个多模态模型,只需要训练中间那个微小的“投影层”,就能让现有的 LLM 获得视觉能力。


行业前沿:OCR-Free 文档解析 (ColPali)

传统的文档处理:PDF -> OCR -> 文本 -> RAG。这种方式会丢失排版、表格和公式信息。 新趋势:直接将 PDF 页面作为图像输入多模态模型。

  • ColPali:利用多模态模型直接对文档图像进行索引,检索时直接定位到图像块,精度远超纯文本 RAG。
  • Docling:IBM 开源的工具,利用多模态能力将复杂 PDF 转换为干净的 Markdown。

总结与展望

多模态不再是“附加功能”,而是 AI 应用的“标配”。

  • 视觉:从简单的描述到复杂的图表分析和文档理解。
  • 音频:实时语音翻译、情感识别。
  • 视频:长视频摘要、异常行为检测。

未来的 AI 将不再局限于对话框,而是拥有“眼睛”和“耳朵”,能够真正感知并理解物理世界。

URL 图像分析

def analyze_image_url(image_url: str, prompt: str) -> str:
    """分析 URL 图像"""
    
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {
                "role": "user",
                "content": [
                    {"type": "text", "text": prompt},
                    {
                        "type": "image_url",
                        "image_url": {"url": image_url}
                    }
                ]
            }
        ]
    )
    
    return response.choices[0].message.content

# 使用
url = "https://example.com/image.jpg"
result = analyze_image_url(url, "分析这张图片的主要内容")

多图像对比

def compare_images(image_paths: list, prompt: str) -> str:
    """对比多张图像"""
    
    content = [{"type": "text", "text": prompt}]
    
    for path in image_paths:
        base64_image = encode_image(path)
        content.append({
            "type": "image_url",
            "image_url": {
                "url": f"data:image/jpeg;base64,{base64_image}"
            }
        })
    
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": content}],
        max_tokens=1500
    )
    
    return response.choices[0].message.content

# 使用
result = compare_images(
    ["before.jpg", "after.jpg"],
    "对比这两张图片,描述它们的主要区别"
)

图像理解应用场景

文档理解与 OCR

from pydantic import BaseModel
from typing import List, Optional
import instructor

client = instructor.from_openai(OpenAI())

class Invoice(BaseModel):
    """发票信息"""
    invoice_number: str
    date: str
    vendor_name: str
    total_amount: float
    items: List[dict]
    tax: Optional[float] = None

def parse_invoice(image_path: str) -> Invoice:
    """解析发票图像"""
    
    base64_image = encode_image(image_path)
    
    return client.chat.completions.create(
        model="gpt-4o",
        response_model=Invoice,
        messages=[
            {
                "role": "user",
                "content": [
                    {"type": "text", "text": "请从这张发票图片中提取所有信息"},
                    {
                        "type": "image_url",
                        "image_url": {
                            "url": f"data:image/jpeg;base64,{base64_image}",
                            "detail": "high"
                        }
                    }
                ]
            }
        ]
    )

# 使用
invoice = parse_invoice("invoice.jpg")
print(f"发票号: {invoice.invoice_number}")
print(f"金额: {invoice.total_amount}")

图表数据提取

class ChartData(BaseModel):
    """图表数据"""
    chart_type: str  # bar, line, pie, etc.
    title: Optional[str] = None
    x_axis_label: Optional[str] = None
    y_axis_label: Optional[str] = None
    data_points: List[dict]
    insights: List[str]

def analyze_chart(image_path: str) -> ChartData:
    """分析图表并提取数据"""
    
    base64_image = encode_image(image_path)
    
    return client.chat.completions.create(
        model="gpt-4o",
        response_model=ChartData,
        messages=[
            {
                "role": "user",
                "content": [
                    {
                        "type": "text",
                        "text": """分析这张图表:
1. 识别图表类型
2. 提取所有数据点
3. 总结主要洞察"""
                    },
                    {
                        "type": "image_url",
                        "image_url": {
                            "url": f"data:image/jpeg;base64,{base64_image}",
                            "detail": "high"
                        }
                    }
                ]
            }
        ]
    )

产品识别

class Product(BaseModel):
    """产品信息"""
    name: str
    brand: Optional[str] = None
    category: str
    estimated_price_range: Optional[str] = None
    key_features: List[str]
    condition: Optional[str] = None  # new, used, damaged

def identify_product(image_path: str) -> Product:
    """识别图片中的产品"""
    
    base64_image = encode_image(image_path)
    
    response = client.chat.completions.create(
        model="gpt-4o",
        response_model=Product,
        messages=[
            {
                "role": "user",
                "content": [
                    {
                        "type": "text",
                        "text": "识别图片中的产品,提取详细信息"
                    },
                    {
                        "type": "image_url",
                        "image_url": {
                            "url": f"data:image/jpeg;base64,{base64_image}"
                        }
                    }
                ]
            }
        ]
    )
    
    return response

图像生成

DALL-E 3 图像生成

from openai import OpenAI

client = OpenAI()

def generate_image(prompt: str, size: str = "1024x1024") -> str:
    """生成图像"""
    
    response = client.images.generate(
        model="dall-e-3",
        prompt=prompt,
        size=size,  # 1024x1024, 1792x1024, 1024x1792
        quality="hd",  # standard, hd
        n=1
    )
    
    return response.data[0].url

# 使用
image_url = generate_image(
    "一只穿着宇航服的柯基犬在月球上行走,背景是地球,科幻风格,高清细节"
)
print(f"生成的图像: {image_url}")

图像变体

def create_variation(image_path: str) -> str:
    """创建图像变体"""
    
    with open(image_path, "rb") as f:
        response = client.images.create_variation(
            model="dall-e-2",
            image=f,
            n=1,
            size="1024x1024"
        )
    
    return response.data[0].url

图像编辑

def edit_image(
    image_path: str,
    mask_path: str,
    prompt: str
) -> str:
    """编辑图像(需要蒙版)"""
    
    with open(image_path, "rb") as image_file:
        with open(mask_path, "rb") as mask_file:
            response = client.images.edit(
                model="dall-e-2",
                image=image_file,
                mask=mask_file,
                prompt=prompt,
                n=1,
                size="1024x1024"
            )
    
    return response.data[0].url

语音处理

语音转文字 (Whisper)

from openai import OpenAI

client = OpenAI()

def transcribe_audio(audio_path: str, language: str = None) -> str:
    """将音频转为文字"""
    
    with open(audio_path, "rb") as audio_file:
        transcript = client.audio.transcriptions.create(
            model="whisper-1",
            file=audio_file,
            language=language,  # 可选,如 "zh", "en"
            response_format="text"
        )
    
    return transcript

# 使用
text = transcribe_audio("meeting.mp3", language="zh")
print(text)

带时间戳的转录

def transcribe_with_timestamps(audio_path: str) -> dict:
    """带时间戳的音频转录"""
    
    with open(audio_path, "rb") as audio_file:
        transcript = client.audio.transcriptions.create(
            model="whisper-1",
            file=audio_file,
            response_format="verbose_json",
            timestamp_granularities=["word", "segment"]
        )
    
    return {
        "text": transcript.text,
        "segments": [
            {
                "start": seg.start,
                "end": seg.end,
                "text": seg.text
            }
            for seg in transcript.segments
        ],
        "words": [
            {
                "word": word.word,
                "start": word.start,
                "end": word.end
            }
            for word in transcript.words
        ] if hasattr(transcript, 'words') else []
    }

# 使用
result = transcribe_with_timestamps("speech.mp3")
for segment in result["segments"]:
    print(f"[{segment['start']:.2f}s - {segment['end']:.2f}s]: {segment['text']}")

语音翻译

def translate_audio(audio_path: str) -> str:
    """将音频翻译为英文"""
    
    with open(audio_path, "rb") as audio_file:
        translation = client.audio.translations.create(
            model="whisper-1",
            file=audio_file,
            response_format="text"
        )
    
    return translation

# 将中文音频翻译为英文
english_text = translate_audio("chinese_speech.mp3")

文字转语音 (TTS)

from pathlib import Path

def text_to_speech(
    text: str,
    output_path: str,
    voice: str = "alloy"
) -> str:
    """将文字转为语音"""
    
    # 可用声音: alloy, echo, fable, onyx, nova, shimmer
    response = client.audio.speech.create(
        model="tts-1-hd",  # tts-1 或 tts-1-hd
        voice=voice,
        input=text
    )
    
    response.stream_to_file(output_path)
    return output_path

# 使用
text_to_speech(
    "欢迎使用我们的语音合成服务!这是一个测试。",
    "output.mp3",
    voice="nova"
)

流式语音生成

def stream_speech(text: str):
    """流式生成语音"""
    
    response = client.audio.speech.create(
        model="tts-1",
        voice="alloy",
        input=text
    )
    
    # 流式写入
    with open("stream_output.mp3", "wb") as f:
        for chunk in response.iter_bytes():
            f.write(chunk)

多模态 RAG

图文混合检索

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.multi_modal_llms.openai import OpenAIMultiModal
from llama_index.core.schema import ImageNode, TextNode
import base64

class MultiModalRAG:
    """多模态 RAG 系统"""
    
    def __init__(self):
        self.text_index = None
        self.image_index = None
        self.mm_llm = OpenAIMultiModal(model="gpt-4o")
    
    def load_documents(self, directory: str):
        """加载文档和图像"""
        from llama_index.readers.file import ImageReader
        
        # 加载文本文档
        text_docs = SimpleDirectoryReader(
            directory,
            required_exts=[".txt", ".md", ".pdf"]
        ).load_data()
        
        # 加载图像
        image_reader = ImageReader()
        image_docs = []
        for img_path in Path(directory).glob("*.{jpg,png,jpeg}"):
            image_docs.extend(image_reader.load_data(img_path))
        
        # 创建索引
        self.text_index = VectorStoreIndex.from_documents(text_docs)
        self.image_index = VectorStoreIndex.from_documents(image_docs)
    
    def query(self, question: str) -> str:
        """多模态查询"""
        # 检索相关文本
        text_retriever = self.text_index.as_retriever(similarity_top_k=3)
        text_nodes = text_retriever.retrieve(question)
        
        # 检索相关图像
        image_retriever = self.image_index.as_retriever(similarity_top_k=2)
        image_nodes = image_retriever.retrieve(question)
        
        # 构建多模态上下文
        context_parts = []
        
        for node in text_nodes:
            context_parts.append(f"文本: {node.text}")
        
        for node in image_nodes:
            if hasattr(node, 'image'):
                context_parts.append(f"[图像: {node.metadata.get('file_name', 'image')}]")
        
        context = "\n\n".join(context_parts)
        
        # 生成回答
        prompt = f"""基于以下上下文回答问题。

上下文:
{context}

问题: {question}

回答:"""
        
        response = self.mm_llm.complete(prompt)
        return str(response)

图像索引与检索

from openai import OpenAI
import numpy as np
from typing import List
import faiss

client = OpenAI()

class ImageSearchEngine:
    """图像搜索引擎"""
    
    def __init__(self, dimension: int = 1536):
        self.dimension = dimension
        self.index = faiss.IndexFlatIP(dimension)  # 内积相似度
        self.images = []  # 存储图像路径
        self.descriptions = []  # 存储图像描述
    
    def describe_image(self, image_path: str) -> str:
        """生成图像描述"""
        base64_image = encode_image(image_path)
        
        response = client.chat.completions.create(
            model="gpt-4o",
            messages=[
                {
                    "role": "user",
                    "content": [
                        {"type": "text", "text": "详细描述这张图片,包括主要内容、颜色、风格等"},
                        {
                            "type": "image_url",
                            "image_url": {"url": f"data:image/jpeg;base64,{base64_image}"}
                        }
                    ]
                }
            ]
        )
        
        return response.choices[0].message.content
    
    def get_embedding(self, text: str) -> List[float]:
        """获取文本嵌入"""
        response = client.embeddings.create(
            model="text-embedding-3-small",
            input=text
        )
        return response.data[0].embedding
    
    def add_image(self, image_path: str):
        """添加图像到索引"""
        # 生成描述
        description = self.describe_image(image_path)
        
        # 获取嵌入
        embedding = self.get_embedding(description)
        embedding = np.array([embedding]).astype('float32')
        
        # 添加到索引
        self.index.add(embedding)
        self.images.append(image_path)
        self.descriptions.append(description)
    
    def search(self, query: str, top_k: int = 5) -> List[dict]:
        """搜索相似图像"""
        query_embedding = self.get_embedding(query)
        query_embedding = np.array([query_embedding]).astype('float32')
        
        distances, indices = self.index.search(query_embedding, top_k)
        
        results = []
        for i, idx in enumerate(indices[0]):
            if idx != -1:
                results.append({
                    "image_path": self.images[idx],
                    "description": self.descriptions[idx],
                    "score": float(distances[0][i])
                })
        
        return results

# 使用
engine = ImageSearchEngine()
engine.add_image("photo1.jpg")
engine.add_image("photo2.jpg")

results = engine.search("一只在草地上奔跑的狗")
for r in results:
    print(f"图像: {r['image_path']}, 相似度: {r['score']:.3f}")

视频分析

视频帧提取与分析

import cv2
from typing import List
import tempfile
import os

def extract_frames(
    video_path: str,
    num_frames: int = 10
) -> List[str]:
    """从视频中提取帧"""
    
    cap = cv2.VideoCapture(video_path)
    total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    
    # 计算采样间隔
    interval = total_frames // num_frames
    
    frames = []
    frame_paths = []
    
    for i in range(num_frames):
        cap.set(cv2.CAP_PROP_POS_FRAMES, i * interval)
        ret, frame = cap.read()
        
        if ret:
            # 保存帧
            temp_path = tempfile.mktemp(suffix=".jpg")
            cv2.imwrite(temp_path, frame)
            frame_paths.append(temp_path)
    
    cap.release()
    return frame_paths

def analyze_video(video_path: str, prompt: str) -> str:
    """分析视频内容"""
    
    # 提取帧
    frame_paths = extract_frames(video_path, num_frames=8)
    
    # 构建消息
    content = [{"type": "text", "text": prompt}]
    
    for path in frame_paths:
        base64_image = encode_image(path)
        content.append({
            "type": "image_url",
            "image_url": {"url": f"data:image/jpeg;base64,{base64_image}"}
        })
    
    # 调用 GPT-4V
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": content}],
        max_tokens=2000
    )
    
    # 清理临时文件
    for path in frame_paths:
        os.remove(path)
    
    return response.choices[0].message.content

# 使用
analysis = analyze_video(
    "demo.mp4",
    "这个视频展示了什么内容?请按时间顺序描述主要事件。"
)
print(analysis)

视频摘要生成

class VideoSummarizer:
    """视频摘要生成器"""
    
    def __init__(self):
        self.client = OpenAI()
    
    def summarize(
        self,
        video_path: str,
        audio_language: str = "zh"
    ) -> dict:
        """生成视频摘要"""
        
        # 1. 提取音频转文字
        audio_path = self._extract_audio(video_path)
        transcript = self._transcribe_audio(audio_path, audio_language)
        
        # 2. 提取关键帧
        frame_paths = extract_frames(video_path, num_frames=10)
        
        # 3. 分析视觉内容
        visual_description = self._analyze_frames(frame_paths)
        
        # 4. 综合生成摘要
        summary = self._generate_summary(transcript, visual_description)
        
        # 清理
        os.remove(audio_path)
        for path in frame_paths:
            os.remove(path)
        
        return {
            "transcript": transcript,
            "visual_description": visual_description,
            "summary": summary
        }
    
    def _extract_audio(self, video_path: str) -> str:
        """从视频提取音频"""
        import moviepy.editor as mp
        
        video = mp.VideoFileClip(video_path)
        audio_path = tempfile.mktemp(suffix=".mp3")
        video.audio.write_audiofile(audio_path, logger=None)
        video.close()
        
        return audio_path
    
    def _transcribe_audio(self, audio_path: str, language: str) -> str:
        """转录音频"""
        with open(audio_path, "rb") as f:
            transcript = self.client.audio.transcriptions.create(
                model="whisper-1",
                file=f,
                language=language
            )
        return transcript.text
    
    def _analyze_frames(self, frame_paths: List[str]) -> str:
        """分析帧"""
        content = [
            {"type": "text", "text": "描述这些视频帧展示的主要视觉内容和场景变化"}
        ]
        
        for path in frame_paths:
            content.append({
                "type": "image_url",
                "image_url": {"url": f"data:image/jpeg;base64,{encode_image(path)}"}
            })
        
        response = self.client.chat.completions.create(
            model="gpt-4o",
            messages=[{"role": "user", "content": content}]
        )
        
        return response.choices[0].message.content
    
    def _generate_summary(self, transcript: str, visual: str) -> str:
        """生成综合摘要"""
        prompt = f"""基于以下视频的音频转录和视觉描述,生成一个全面的摘要。

音频转录:
{transcript}

视觉内容:
{visual}

请生成:
1. 视频主题
2. 主要内容概述
3. 关键要点(列表形式)
4. 时长估计和视频类型"""

        response = self.client.chat.completions.create(
            model="gpt-4",
            messages=[{"role": "user", "content": prompt}]
        )
        
        return response.choices[0].message.content

实战案例

智能客服系统

from openai import OpenAI
from typing import Optional
import base64

client = OpenAI()

class MultiModalCustomerService:
    """多模态智能客服"""
    
    def __init__(self, system_prompt: str = None):
        self.system_prompt = system_prompt or """你是一个专业的客服助手,可以:
1. 回答用户的文字问题
2. 分析用户上传的产品图片
3. 识别发票、收据等单据
4. 处理语音消息

请始终保持专业、友好的态度。"""
        self.conversation = []
    
    def chat(
        self,
        text: Optional[str] = None,
        image_path: Optional[str] = None,
        audio_path: Optional[str] = None
    ) -> str:
        """多模态对话"""
        
        user_content = []
        
        # 处理文字
        if text:
            user_content.append({"type": "text", "text": text})
        
        # 处理图像
        if image_path:
            base64_image = encode_image(image_path)
            user_content.append({
                "type": "image_url",
                "image_url": {"url": f"data:image/jpeg;base64,{base64_image}"}
            })
            if not text:
                user_content.insert(0, {"type": "text", "text": "请分析这张图片"})
        
        # 处理音频
        if audio_path:
            # 先转文字
            with open(audio_path, "rb") as f:
                transcript = client.audio.transcriptions.create(
                    model="whisper-1",
                    file=f
                )
            user_content.append({
                "type": "text",
                "text": f"[语音消息转文字]: {transcript.text}"
            })
        
        # 添加用户消息
        self.conversation.append({
            "role": "user",
            "content": user_content
        })
        
        # 调用 API
        messages = [
            {"role": "system", "content": self.system_prompt}
        ] + self.conversation
        
        response = client.chat.completions.create(
            model="gpt-4o",
            messages=messages,
            max_tokens=1000
        )
        
        assistant_message = response.choices[0].message.content
        
        # 保存助手回复
        self.conversation.append({
            "role": "assistant",
            "content": assistant_message
        })
        
        return assistant_message

# 使用示例
cs = MultiModalCustomerService()

# 文字咨询
response = cs.chat(text="这款产品的保修期是多久?")

# 图片咨询
response = cs.chat(
    text="这个产品有质量问题,请看图片",
    image_path="damage.jpg"
)

# 语音咨询
response = cs.chat(audio_path="question.mp3")

最佳实践

图像处理优化

# 1. 图像压缩
from PIL import Image
import io

def compress_image(image_path: str, max_size: int = 1024) -> str:
    """压缩图像以减少 token 消耗"""
    img = Image.open(image_path)
    
    # 调整尺寸
    ratio = min(max_size / img.width, max_size / img.height)
    if ratio < 1:
        new_size = (int(img.width * ratio), int(img.height * ratio))
        img = img.resize(new_size, Image.LANCZOS)
    
    # 压缩
    buffer = io.BytesIO()
    img.save(buffer, format="JPEG", quality=85)
    
    return base64.b64encode(buffer.getvalue()).decode()

# 2. 选择合适的 detail 参数
# - low: 快速,低成本,适合简单任务
# - high: 详细分析,适合 OCR、细节识别
# - auto: 自动选择

成本控制

模态 成本因素 优化建议
图像 分辨率、数量 压缩、采样
音频 时长 分段处理
视频 帧数、分辨率 关键帧提取

总结

多模态 LLM 应用极大地扩展了 AI 的能力边界:

能力 应用场景 关键技术
图像理解 OCR、商品识别 GPT-4V
图像生成 创意设计、广告 DALL-E 3
语音识别 会议记录、字幕 Whisper
语音合成 有声书、客服 TTS
视频分析 内容审核、摘要 帧提取 + 视觉模型

构建多模态应用的关键:

  1. 选择合适的模型和参数
  2. 优化输入数据格式和大小
  3. 设计高效的处理流程
  4. 控制成本和延迟

参考资源

版权声明: 如无特别声明,本文版权归 sshipanoo 所有,转载请注明本文链接。

(采用 CC BY-NC-SA 4.0 许可协议进行授权)

本文标题:《 LLM应用开发——多模态LLM应用 》

本文链接:http://localhost:3015/ai/%E5%A4%9A%E6%A8%A1%E6%80%81LLM%E5%BA%94%E7%94%A8.html

本文最后一次更新为 天前,文章中的某些内容可能已过时!