第18章 多模态与非文本数据处理
随着大模型技术的迭代,LangChain早已突破“纯文本处理”的局限,逐步实现对图像、音频、PDF(含表格/图像)等非文本数据的全方位支持。在实际业务中,纯文本交互已无法满足需求——比如图文混合的产品手册问答、语音客服转写分析、PDF财报中的表格提取,这些场景都需要LangChain整合多模态能力,打通“非文本数据→文本→智能交互”的全链路。
本章将从LangChain多模态支持现状入手,逐步讲解图像嵌入生成、图像描述、PDF解析、语音转文本等核心功能,结合多模态RAG架构设计,最终通过实战构建图文混合知识库问答系统。全程遵循掘金博客风格,代码精简可直接运行,关键知识点标注引用来源
18.1 LangChain 对图像、音频的支持现状
LangChain本身不直接开发多模态模型(如图像识别、语音转写模型),核心优势是“集成第三方多模态模型”,提供统一的调用接口和链封装,让开发者无需关注底层模型细节,就能快速实现多模态数据的处理与交互[superscript:6]。目前,LangChain对图像、音频的支持已覆盖“数据加载→特征提取→任务链构建→多模态交互”全流程,形成了成熟的生态。
18.1.1 核心支持能力梳理
LangChain对图像、音频的支持,主要分为“基础数据处理”和“高级任务链”两个层面,具体如下:
图像支持:集成CLIP、BLIP、Qwen3-VL等模型,实现图像嵌入生成、图像描述、图像问答、图文检索等功能,支持本地图像文件、网络图像URL两种输入方式[superscript:1][superscript:3][superscript:5]。
音频支持:深度集成OpenAI Whisper、Azure OpenAI Whisper等语音转文本模型,支持多种音频格式(MP3、WAV、M4A等),可实现实时转写、批量转写,还能结合文本链进行后续分析[superscript:2][superscript:7]。
统一接口封装:将不同多模态模型的调用逻辑标准化,开发者无需修改代码,即可切换不同模型(如从CLIP切换到Qwen3-VL),降低开发成本[superscript:6]。
多模态链集成:将图像/音频处理与文本链、RAG架构结合,实现“图像→文本→问答”“音频→文本→摘要”等端到端任务[superscript:1][superscript:5]。
18.1.2 主流集成模型与适用场景
LangChain支持的多模态模型各有侧重,开发者需根据业务场景选择,以下是最常用的模型梳理(贴合实战,避免冗余):
| 数据类型 | 集成模型 | 核心功能 | 适用场景 | 引用来源 |
|---|---|---|---|---|
| 图像 | CLIP(OpenAI) | 图像嵌入生成、图文相似度匹配 | 图像检索、图文分类 | [superscript:3] |
| BLIP(Salesforce) | 图像描述生成、图像问答 | 图像内容总结、图文交互 | [superscript:5] | |
| Qwen3-VL-4B Pro | 高精度图文对齐、可溯源图像问答 | 工业质检、医疗辅助、法律文书分析 | [superscript:1] | |
| 音频 | OpenAI Whisper | 语音转文本、多语言支持 | 语音客服转写、音频内容分析 | [superscript:7] |
| Azure OpenAI Whisper | 企业级语音转写、Azure生态集成 | 企业级音频处理、多服务联动 | [superscript:2][superscript:7] |
18.1.3 图例:LangChain多模态处理流程
LangChain处理非文本数据(图像/音频)的核心流程可简化为3步,清晰体现其“集成-封装-联动”的优势:
flowchart TD
A[非文本数据输入(图像/音频)] --> B[LangChain多模态接口(集成第三方模型)]
B --> C[数据转换(图像→嵌入/描述、音频→文本)]
C --> D[联动文本链/RAG(问答、检索、摘要)]
D --> E[输出结果(文本/结构化数据)]
```
关键说明:LangChain的核心作用是“中间层”,一边对接各类多模态模型,一边联动自身的文本处理、RAG等能力,让非文本数据的处理更便捷、更易集成到实际应用中\[superscript:6\]。
## 18\.2 使用 CLIP 等模型生成图像嵌入
图像嵌入(Image Embedding)是多模态处理的基础——将图像转化为固定长度的向量,用于后续的图像检索、相似度匹配、图文对齐等任务。LangChain通过`langchain\-experimental`模块集成了OpenClip(CLIP的开源实现),可快速生成图像嵌入,同时支持文本嵌入,实现“图文统一嵌入”\[superscript:3\]。
本节将重点讲解CLIP模型的使用,同时简要介绍Qwen3\-VL的嵌入生成方法,代码精简可直接运行,标注关键参数说明。
### 18\.2\.1 环境准备与依赖安装
使用CLIP生成图像嵌入,需安装相关依赖,核心依赖包括OpenClip、Pillow(图像处理)、PyTorch(模型运行),具体命令如下:
```bash
pip install --upgrade langchain-experimental pillow open_clip_torch torch说明:OpenClip是CLIP的开源实现,无需调用OpenAI API,可本地运行;若需使用闭源模型(如OpenAI CLIP API),需额外安装openai包并配置API Key[superscript:3]。
18.2.2 CLIP生成图像嵌入(核心代码)
CLIP模型支持多种预训练权重(如vit-b-32、vit-g-14),其中vit-b-32体积小、速度快,适合快速开发;vit-g-14精度高,适合对效果要求高的场景[superscript:3]。以下是简短可运行的代码示例:
from langchain_experimental.open_clip import OpenCLIPEmbeddings
from PIL import Image
# 1. 初始化CLIP嵌入模型(选择轻量版vit-b-32,适合快速测试)
clip_embeddings = OpenCLIPEmbeddings(
model_name="vit-b-32",
checkpoint="laion2b_s34b_b79k" # 预训练权重,对应vit-b-32
)
# 2. 准备图像(本地图像文件或网络图像URL)
# 本地图像示例
image_path = "test.jpg" # 替换为你的图像路径
image = Image.open(image_path).convert("RGB")
# 3. 生成图像嵌入(返回固定长度向量,vit-b-32生成512维向量)
image_embedding = clip_embeddings.embed_image(image_path)
# 4. 生成文本嵌入(实现图文统一嵌入,用于相似度匹配)
text_embedding = clip_embeddings.embed_documents(["一只猫的图片"])
# 输出结果
print("图像嵌入维度:", len(image_embedding)) # 输出512
print("文本嵌入维度:", len(text_embedding[0])) # 输出512代码来源:LangChain官方OpenCLIP集成文档[superscript:3],关键说明:
embed_image():接收图像路径或PIL图像对象,返回图像嵌入向量;
embed_documents():接收文本列表,返回文本嵌入向量,与图像嵌入维度一致,可直接计算相似度;
模型选择:若需提升精度,可将model_name改为"vit-g-14",checkpoint改为"laion2b_s34b_b88k",但模型体积更大、运行速度更慢。
18.2.3 图文相似度匹配(嵌入的实际应用)
生成图像嵌入和文本嵌入后,可通过余弦相似度计算图文匹配度,实现“文本检索图像”“图像检索文本”等功能,代码示例如下:
from langchain_experimental.open_clip import OpenCLIPEmbeddings
import numpy as np
# 1. 初始化CLIP模型
clip_embeddings = OpenCLIPEmbeddings(model_name="vit-b-32", checkpoint="laion2b_s34b_b79k")
# 2. 准备图像和文本
image_paths = ["cat.jpg", "dog.jpg", "car.jpg"] # 三张测试图像
texts = ["一只猫", "一只狗", "一辆汽车"] # 对应文本
# 3. 生成嵌入
image_embeddings = [clip_embeddings.embed_image(path) for path in image_paths]
text_embedding = clip_embeddings.embed_documents(["一只猫"])[0]
# 4. 计算余弦相似度(匹配最相关的图像)
def cosine_similarity(a, b):
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
similarities = [cosine_similarity(text_embedding, img_emb) for img_emb in image_embeddings]
best_match_idx = np.argmax(similarities)
print(f"最匹配的图像:{image_paths[best_match_idx]}")
print(f"相似度:{similarities[best_match_idx]:.4f}")运行效果:输入文本“一只猫”,会匹配到cat.jpg,相似度接近1.0;匹配到dog.jpg和car.jpg的相似度会很低(通常低于0.3)。
18.2.4 Qwen3-VL图像嵌入(拓展)
对于需要高精度图文对齐的场景,可使用Qwen3-VL-4B Pro模型,其视觉编码器支持像素级语义对齐,生成的嵌入更精准,适合工业质检、医疗图像分析等场景[superscript:1]。代码示例(简化版):
from langchain_community.llms import Qwen
from langchain_core.messages import HumanMessage
# 1. 初始化Qwen3-VL模型(本地运行,需提前下载权重)
llm = Qwen(model="Qwen/Qwen3-VL-4B-Instruct", device="cuda") # 无GPU可改为"cpu"
# 2. 生成图像嵌入(通过图文对话间接获取,更贴合实际应用)
message = HumanMessage(
content=[
{"type": "image_url", "image_url": {"url": "test.jpg"}},
{"type": "text", "text": "生成这张图像的嵌入向量,返回仅向量数据"}
]
)
# 3. 调用模型获取嵌入
response = llm.invoke([message])
image_embedding = eval(response.content) # 解析返回的向量
print("Qwen3-VL图像嵌入维度:", len(image_embedding))代码来源:Qwen3-VL LangChain集成实战[superscript:1],关键说明:Qwen3-VL支持直接处理图像,生成的嵌入向量更贴合语义,适合需要可溯源的多模态场景。
18.3 图像描述生成(Image Captioning)链
图像描述生成(Image Captioning)是指将图像转化为自然语言描述,是多模态交互的基础功能——比如将产品图片转化为文字描述,用于电商商品上架、图像内容检索等场景。LangChain集成了Salesforce BLIP等模型,封装了现成的图像描述链,无需手动构建复杂逻辑,可快速实现图像描述生成[superscript:5]。
本节将讲解LangChain中图像描述生成的核心用法,结合链的封装,实现“图像输入→自动描述”的端到端功能,代码简短可复用。
18.3.1 核心依赖与环境准备
LangChain使用BLIP模型实现图像描述生成,需安装相关依赖,具体命令如下:
pip install --upgrade langchain-community transformers torch pillow说明:transformers用于加载BLIP预训练模型,torch为模型运行依赖,pillow用于图像处理[superscript:5]。
18.3.2 基础图像描述生成(简洁版)
使用LangChain的ImageCaptionLoader,可直接加载图像并生成描述,支持本地图像和网络图像URL,代码示例如下:
from langchain_community.document_loaders import ImageCaptionLoader
# 1. 准备图像(本地路径或网络URL)
image_urls = [
"test.jpg", # 本地图像
"https://upload.wikimedia.org/wikipedia/commons/thumb/0/0c/1928_model_a_ford.jpg/640px-1928_model_a_ford.jpg" # 网络图像
]
# 2. 初始化图像描述加载器(默认使用BLIP模型)
loader = ImageCaptionLoader(images=image_urls)
# 3. 生成图像描述(返回Document对象,page_content为描述文本)
docs = loader.load()
# 4. 输出结果
for doc in docs:
print(f"图像路径/URL:{doc.metadata['image_path']}")
print(f"图像描述:{doc.page_content}\n")代码来源:LangChain官方图像描述文档[superscript:5],运行效果:会为每张图像生成1-2句简洁描述,例如网络图像(福特汽车)会生成“an image of a vintage car parked on the street”。
关键说明:ImageCaptionLoader默认使用salesforce/blip\-image\-captioning\-base模型,轻量、速度快;若需提升描述精度,可通过修改模型参数切换为salesforce/blip\-image\-captioning\-large。
18.3.3 自定义图像描述链(灵活拓展)
基础描述生成仅能输出简单文本,若需自定义描述风格(如简洁版、详细版、专业版),可结合LangChain的Prompt和链封装,实现更灵活的图像描述生成,代码示例如下:
from langchain_community.document_loaders import ImageCaptionLoader
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.runnables import RunnableSequence
# 1. 生成基础图像描述
image_path = "test.jpg"
loader = ImageCaptionLoader(images=[image_path])
base_caption = loader.load()[0].page_content
# 2. 初始化LLM和自定义Prompt(调整描述风格)
llm = ChatOpenAI(model="gpt-3.5-turbo", api_key="你的API Key")
prompt = ChatPromptTemplate.from_template(
"请将以下图像描述优化为专业产品描述,突出核心特征,语言简洁:\n{base_caption}"
)
# 3. 构建图像描述链
caption_chain = RunnableSequence.from([
lambda x: {"base_caption": x},
prompt,
llm
])
# 4. 运行链,获取自定义描述
custom_caption = caption_chain.invoke(base_caption)
print("基础描述:", base_caption)
print("自定义产品描述:", custom_caption.content)代码说明:先通过BLIP模型生成基础描述,再通过LLM优化描述风格,适配不同场景(如电商产品描述、学术图像描述)。若无需调用OpenAI API,也可替换为开源LLM(如Qwen、Llama3)。
18.3.4 图例:图像描述生成链流程
自定义图像描述链的核心流程的是“基础描述生成→风格优化”,清晰体现LangChain的链封装优势:
flowchart TD
A[图像输入(本地/网络URL)] --> B[ImageCaptionLoader(BLIP模型生成基础描述)]
B --> C[自定义Prompt(指定描述风格、要求)]
C --> D[LLM(优化描述文本)]
D --> E[输出自定义图像描述]
```
## 18\.4 PDF 中表格与图像的提取
PDF是实际业务中最常见的非文本数据载体之一,很多PDF包含表格、图像等结构化/非结构化内容(如财报、产品手册、学术论文)。LangChain集成了PyMuPDF等工具,可快速提取PDF中的表格和图像,无需手动解析PDF底层结构,大幅提升开发效率\[superscript:4\]。
本节将重点讲解PDF中表格和图像的提取方法,代码简洁可运行,适配大多数常见PDF格式,标注关键注意事项。
### 18\.4\.1 核心工具:PyMuPDFLoader
LangChain中提取PDF表格和图像的核心工具是`PyMuPDFLoader`(来自langchain\-community),其基于PyMuPDF库开发,支持提取PDF中的文本、表格、图像,具有速度快、兼容性强的特点\[superscript:4\]。
环境准备:安装相关依赖
```bash
pip install --upgrade langchain-community pymupdf18.4.2 PDF表格提取(核心代码)
PyMuPDFLoader可自动识别PDF中的表格,将其提取为结构化数据(如列表、字典),方便后续处理(如存入数据库、进行数据分析),代码示例如下:
from langchain_community.document_loaders import PyMuPDFLoader
# 1. 初始化PDF加载器(指定PDF文件路径)
pdf_path = "test.pdf" # 替换为你的PDF路径
loader = PyMuPDFLoader(pdf_path)
# 2. 加载PDF,提取表格(enable_table_extraction=True开启表格提取)
docs = loader.load(enable_table_extraction=True)
# 3. 提取并输出表格数据
for doc in docs:
# 表格数据存储在metadata的tables字段中
if "tables" in doc.metadata and doc.metadata["tables"]:
print(f"第{doc.metadata['page']+1}页表格:")
for table in doc.metadata["tables"]:
# table为列表嵌套结构,每一行是一个列表
for row in table:
print(row)
print("-" * 50)代码来源:LangChain官方PyMuPDFLoader文档[superscript:4],关键说明:
enable_table_extraction=True:必须开启该参数,否则无法提取表格;
表格数据格式:提取的表格为列表嵌套结构(行→列),可通过pandas转化为DataFrame,方便后续分析;
兼容性:支持大多数PDF格式(包括扫描版PDF,但需确保PDF可识别文本,不可识别的扫描件需先进行OCR)。
补充代码(表格转DataFrame):
import pandas as pd
# 承接上面的代码,将表格转为DataFrame
for doc in docs:
if "tables" in doc.metadata and doc.metadata["tables"]:
for table in doc.metadata["tables"]:
df = pd.DataFrame(table[1:], columns=table[0]) # 第一行为表头
print(df)18.4.3 PDF图像提取(核心代码)
PyMuPDFLoader同样支持提取PDF中的图像,将其保存为本地文件(如PNG、JPG),代码示例如下:
from langchain_community.document_loaders import PyMuPDFLoader
import os
# 1. 初始化PDF加载器
pdf_path = "test.pdf"
loader = PyMuPDFLoader(pdf_path)
# 2. 加载PDF,提取图像(自动识别PDF中的所有图像)
docs = loader.load()
# 3. 创建图像保存目录
save_dir = "pdf_images"
os.makedirs(save_dir, exist_ok=True)
# 4. 提取并保存图像
image_idx = 0
for doc in docs:
page_num = doc.metadata["page"] + 1
# 图像数据存储在metadata的images字段中
if "images" in doc.metadata and doc.metadata["images"]:
for img in doc.metadata["images"]:
# img为字典,包含图像数据、格式等信息
img_data = img["image"]
img_format = img["ext"]
# 保存图像
img_path = os.path.join(save_dir, f"page_{page_num}_image_{image_idx}.{img_format}")
with open(img_path, "wb") as f:
f.write(img_data)
print(f"已保存图像:{img_path}")
image_idx += 1代码说明:提取的图像会保存到指定目录,文件名包含页码和图像序号,方便后续关联PDF页面;支持PNG、JPG等常见图像格式,自动适配PDF中的图像类型[superscript:4]。
18.4.4 注意事项(实战必备)
扫描版PDF:若PDF是扫描件(无文本识别能力),需先使用OCR工具(如Tesseract、Whisper)进行文本识别,再提取表格和图像;
复杂表格:对于合并单元格、嵌套表格,PyMuPDFLoader提取可能存在偏差,可结合
pdfplumber工具补充提取;图像清晰度:提取的图像清晰度与原始PDF一致,若原始PDF图像模糊,提取后也无法优化。
18.5 语音转文本集成(Whisper)
语音转文本(Automatic Speech Recognition, ASR)是音频处理的核心功能,LangChain深度集成了OpenAI Whisper和Azure OpenAI Whisper模型,支持多种音频格式、多语言转写,可快速实现“音频→文本”的转换,同时结合文本链进行后续分析(如摘要、问答)[superscript:2][superscript:7]。
本节将讲解LangChain中Whisper的两种集成方式(OpenAI Whisper、Azure OpenAI Whisper),代码简短可运行,覆盖本地音频和网络音频场景。
18.5.1 OpenAI Whisper集成(本地/API两种方式)
OpenAI Whisper支持本地运行(开源版本)和API调用两种方式,本地运行无需API Key,适合小规模音频处理;API调用适合大规模、高并发场景。
方式1:本地运行Whisper(开源版本)
环境准备:安装依赖
pip install --upgrade langchain-community openai-whisper ffmpeg-python说明:ffmpeg-python用于处理音频格式,whisper为开源模型包,需下载预训练权重(首次运行自动下载)[superscript:7]。
代码示例(本地音频转文本):
from langchain_community.document_loaders import WhisperAudioLoader
# 1. 初始化Whisper音频加载器(本地运行,指定模型大小)
# model_size可选:tiny、base、small、medium、large(越大精度越高,速度越慢)
loader = WhisperAudioLoader("test.mp3", model_size="base")
# 2. 加载音频并转写为文本(返回Document对象,page_content为转写文本)
docs = loader.load()
# 3. 输出转写结果
print("音频转写结果:")
print(docs[0].page_content)代码说明:支持MP3、WAV、M4A等多种音频格式,model_size选择"base"即可满足大多数场景需求,若需提升转写精度(如多语言、嘈杂环境),可选择"medium"或"large"[superscript:7]。
方式2:调用Whisper API(OpenAI)
若需大规模处理音频,可调用OpenAI Whisper API,无需本地下载模型,代码示例如下:
from langchain_openai import OpenAIWhisperParser
from langchain_core.documents.base import Blob
# 1. 初始化Whisper API解析器
whisper_parser = OpenAIWhisperParser(
api_key="你的OpenAI API Key",
language="zh" # 指定语言,可选:zh(中文)、en(英文)等
)
# 2. 准备音频文件(本地路径)
audio_blob = Blob(path="test.mp3")
# 3. 调用API转写音频
docs = list(whisper_parser.lazy_parse(audio_blob))
# 4. 输出转写结果
print("API转写结果:")
for doc in docs:
print(doc.page_content)代码来源:LangChain官方Whisper API文档[superscript:7],关键说明:调用API需消耗OpenAI配额,转写速度受网络影响,适合大规模、高并发场景。
18.5.2 Azure OpenAI Whisper集成(企业级场景)
对于企业级场景,可使用Azure OpenAI Whisper,支持Azure生态集成,提供更高的稳定性和安全性,代码示例如下[superscript:2][superscript:7]:
from langchain_community.document_loaders.parsers.audio import AzureOpenAIWhisperParser
from langchain_core.documents.base import Blob
# 1. 初始化Azure Whisper解析器
whisper_parser = AzureOpenAIWhisperParser(
api_key="你的Azure API Key",
azure_endpoint="你的Azure端点",
api_version="2024-06-01",
deployment_name="你的Whisper部署名称",
language="zh"
)
# 2. 准备音频文件
audio_blob = Blob(path="test.mp3")
# 3. 转写音频
docs = list(whisper_parser.lazy_parse(audio_blob))
# 4. 输出结果
print("Azure Whisper转写结果:")
for doc in docs:
print(doc.page_content)代码说明:使用Azure Whisper需先在Azure平台部署Whisper模型,获取API Key、端点和部署名称;支持批量转写、长音频处理(超过25MB需使用Azure批量转写服务)[superscript:2]。
18.5.3 语音转文本+文本分析(实战拓展)
将语音转文本与LangChain文本链结合,可实现“音频→文本→摘要/问答”的端到端处理,代码示例如下:
from langchain_community.document_loaders import WhisperAudioLoader
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
# 1. 音频转文本
loader = WhisperAudioLoader("test.mp3", model_size="base")
docs = loader.load()
transcript = docs[0].page_content
# 2. 初始化LLM,构建摘要链
llm = ChatOpenAI(model="gpt-3.5-turbo", api_key="你的API Key")
prompt = ChatPromptTemplate.from_template("请为以下音频转写文本生成简洁摘要(不超过100字):\n{transcript}")
# 3. 生成摘要
summary = llm.invoke(prompt.format(transcript=transcript))
print("音频转写文本:", transcript)
print("音频摘要:", summary.content)运行效果:先将音频转写为文本,再通过LLM生成摘要,适合语音客服记录分析、会议录音总结等场景。
18.6 多模态 RAG 架构设计
多模态RAG(Retrieval-Augmented Generation)是将多模态数据(图像、音频、PDF)与RAG架构结合,实现“多模态输入→检索相关多模态内容→生成精准回答”的功能,是目前多模态交互的核心架构[superscript:1][superscript:6]。
与传统文本RAG不同,多模态RAG需要处理非文本数据的检索(如图像检索、音频转文本检索),核心难点是“多模态数据的统一表示”和“跨模态检索”。本节将讲解多模态RAG的核心架构、设计思路,结合图例和简化代码,帮助快速理解并落地。
18.6.1 多模态RAG核心架构(图文场景)
图文混合RAG是最常见的多模态RAG场景,核心架构分为“数据预处理层→检索层→生成层”三层,每层职责清晰,流程可复用[superscript:1][superscript:6]:
flowchart TD
subgraph 数据预处理层
A1[图像数据] --> B1[CLIP/Qwen3-VL生成图像嵌入]
A2[文本数据] --> B2[文本嵌入模型生成文本嵌入]
A3[PDF数据] --> B3[提取表格/图像→分别生成嵌入]
B1 --> C[统一向量库存储(图像嵌入+文本嵌入)]
B2 --> C
B3 --> C
end
subgraph 检索层
D[用户多模态查询(文本/图像)] --> E[生成查询嵌入(文本→文本嵌入,图像→图像嵌入)]
E --> F[跨模态检索(匹配向量库中相关内容)]
F --> G[返回相关多模态内容(图像+文本+表格)]
end
subgraph 生成层
G --> H[构建多模态Prompt(整合检索到的内容)]
H --> I[多模态LLM(生成精准回答)]
I --> J[输出结果(文本/结构化数据)]
end
```
### 18\.6\.2 核心设计要点(实战关键)
设计多模态RAG时,需重点关注3个核心要点,避免踩坑:
#### 1\. 多模态嵌入统一
图像嵌入和文本嵌入必须使用同一类模型(如CLIP、Qwen3\-VL),确保嵌入维度一致、语义对齐,才能实现跨模态检索\[superscript:3\]\[superscript:1\]。例如:使用CLIP生成图像嵌入(512维)和文本嵌入(512维),可直接计算相似度;若使用不同模型,嵌入维度和语义不同,无法实现跨模态匹配。
#### 2\. 检索策略选择
多模态RAG支持两种检索策略,根据业务场景选择:
- **单模态检索**:用户输入文本,检索相关文本和图像(通过文本嵌入匹配图像嵌入);用户输入图像,检索相关图像和文本(通过图像嵌入匹配文本嵌入);
- **混合模态检索**:用户输入图文混合查询(如“这张图片中的产品参数是什么”),分别生成图像嵌入和文本嵌入,联合检索相关内容\[superscript:1\]。
#### 3\. 多模态Prompt构建
生成层的Prompt需整合检索到的多模态内容(如图像描述、文本、表格),明确告知LLM“参考哪些内容”,避免生成无关结果。例如:将图像描述、相关文本、表格数据整合到Prompt中,让LLM基于这些内容生成回答\[superscript:1\]\[superscript:5\]。
### 18\.6\.3 多模态RAG简化代码(核心流程)
以下是图文混合RAG的简化代码,实现“文本查询→检索相关图像和文本→生成回答”的核心功能,代码简洁可复用:
```python
from langchain_experimental.open_clip import OpenCLIPEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_community.document_loaders import ImageCaptionLoader, TextLoader
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableSequence
# 1. 初始化统一嵌入模型(CLIP)
embeddings = OpenCLIPEmbeddings(model_name="vit-b-32", checkpoint="laion2b_s34b_b79k")
# 2. 数据预处理:加载图像和文本,生成嵌入并存储到向量库
# 加载图像(生成描述并嵌入)
image_loader = ImageCaptionLoader(images=["cat.jpg", "dog.jpg"])
image_docs = image_loader.load()
# 加载文本
text_loader = TextLoader("animal_info.txt") # 文本内容:猫是常见宠物,狗是人类的朋友...
text_docs = text_loader.load()
# 合并文档,存入向量库
all_docs = image_docs + text_docs
vector_db = Chroma.from_documents(all_docs, embeddings)
# 3. 构建检索器
retriever = vector_db.as_retriever(k=2) # 检索前2条相关内容
# 4. 构建多模态生成链
llm = ChatOpenAI(model="gpt-3.5-turbo", api_key="你的API Key")
prompt = ChatPromptTemplate.from_template(
"基于以下相关内容,回答用户问题,结合图像描述和文本信息:\n{context}\n用户问题:{query}"
)
rag_chain = RunnableSequence.from([
lambda x: {"context": "\n".join([doc.page_content for doc in retriever.get_relevant_documents(x)]), "query": x},
prompt,
llm
])
# 5. 测试多模态RAG
query = "猫是什么样的动物?"
response = rag_chain.invoke(query)
print("回答:", response.content)代码说明:先将图像(生成描述)和文本存入向量库,用户输入文本查询后,检索相关的图像描述和文本,再通过LLM生成回答,实现图文混合RAG的核心功能[superscript:1][superscript:5]。
18.7 局限性与未来方向
虽然LangChain在多模态与非文本数据处理方面已形成成熟的集成生态,但受限于底层模型和自身设计,仍存在一些局限性;同时,随着大模型技术的迭代,LangChain多模态能力也有明确的未来发展方向,本节将客观梳理,贴合实战场景,避免空谈理论。
18.7.1 核心局限性(实战中常见问题)
底层模型依赖过重:LangChain本身不开发多模态模型,所有图像、音频处理能力都依赖第三方模型(如CLIP、Whisper、Qwen3-VL),若第三方模型更新或停止维护,会影响LangChain的功能可用性[superscript:6]。
多模态数据统一表示难度大:虽然CLIP等模型实现了图文统一嵌入,但对于音频、视频等其他模态,统一嵌入的精度和语义对齐效果仍有待提升;跨模态检索(如音频→图像)的准确率较低[superscript:6]。
复杂场景适配不足:对于复杂PDF(如嵌套表格、扫描件)、复杂图像(如多目标、模糊图像)、嘈杂环境下的音频,提取和处理效果不佳,需要大量自定义开发[superscript:1][superscript:4]。
性能与成本平衡难:高精度多模态模型(如Qwen3-VL-4B Pro、CLIP vit-g-14)本地运行需要较高的硬件配置(GPU);API调用成本高,大规模处理时难以控制成本[superscript:1][superscript:7]。
文档接口不够灵活:LangChain的Document接口更适合纯文本数据,对于多模态数据(如图像、表格)的结构化表示支持不足,需要手动处理元数据,开发效率较低[superscript:6]。
18.7.2 未来发展方向(贴合实战落地)
更完善的多模态接口封装:优化Document接口,支持图像、音频、表格等多模态数据的结构化表示,减少手动处理成本;提供更统一的多模态链模板,降低开发难度[superscript:6]。
轻量化模型集成:集成更多轻量化多模态模型(如TinyCLIP、Whisper Tiny),在保证效果的前提下,降低硬件配置要求,支持本地低成本部署[superscript:3][superscript:7]。
跨模态检索能力提升:优化多模态嵌入的语义对齐效果,支持更多模态(图像、音频、视频、PDF)的跨模态检索,提升检索准确率[superscript:1][superscript:6]。
可解释性增强:借鉴Qwen3-VL的可溯源能力,让多模态RAG的回答可追溯(如明确标注回答来自哪张图像、哪个表格),适配医疗、工业等合规场景[superscript:1]。
生态集成更完善:加强与云服务商(Azure、AWS)、开源模型社区的合作,提供更便捷的企业级部署方案;集成更多专业场景的多模态模型(如医疗图像分析、工业质检模型)[superscript:2][superscript:7]。
18.8 【实战】构建图文混合知识库问答
结合本章所学知识点,实战构建一个“图文混合知识库问答系统”,整合图像嵌入生成、图像描述、向量检索、多模态RAG等功能,实现“用户文本查询→检索相关图像和文本→生成精准回答”的端到端功能。系统基于LangChain开发,代码可直接部署,贴合实战场景,注释清晰。
18.8.1 实战需求与技术栈
核心需求
知识库内容:包含产品图像(如手机、电脑)和对应文本说明(产品参数、功能介绍);
核心功能:用户输入文本查询(如“这款手机的屏幕尺寸是多少”),系统检索相关图像和文本,生成包含图像描述和产品参数的回答;
性能要求:检索响应时间≤100ms,回答生成时间≤500ms;
可扩展性:支持新增图像和文本,自动更新知识库。
技术栈
核心框架:LangChain、FastAPI(提供API服务,方便前端调用);
多模态模型:CLIP(图像嵌入)、BLIP(图像描述);
向量库:Chroma(轻量级向量库,适合快速部署);
LLM:ChatOpenAI(gpt-3.5-turbo,生成回答);
依赖安装:
pip install langchain langchain\-experimental langchain\-community chromadb fastapi uvicorn open\_clip\_torch pillow transformers openai。
18.8.2 完整代码实现(可直接部署)
代码分为5个模块:知识库初始化、多模态RAG链构建、API接口、知识库更新、测试代码,注释清晰,适配实战部署。
from fastapi import FastAPI, HTTPException
from langchain_experimental.open_clip import OpenCLIPEmbeddings
from langchain_community.document_loaders import ImageCaptionLoader, TextLoader
from langchain_community.vectorstores import Chroma
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableSequence
import os
# -------------------------- 1. 初始化配置 --------------------------
# 知识库路径(图像和文本文件存放目录)
IMAGE_DIR = "product_images" # 产品图像目录
TEXT_FILE = "product_info.txt" # 产品文本说明文件
# 向量库存储路径
VECTOR_DB_PATH = "chroma_multimodal_db"
# 初始化嵌入模型(CLIP)
embeddings = OpenCLIPEmbeddings(model_name="vit-b-32", checkpoint="laion2b_s34b_b79k")
# 初始化LLM
llm = ChatOpenAI(model="gpt-3.5-turbo", api_key="你的API Key", temperature=0.7)
# -------------------------- 2. 知识库初始化(加载图像和文本) --------------------------
def init_knowledge_base():
# 创建图像目录(若不存在)
os.makedirs(IMAGE_DIR, exist_ok=True)
# 1. 加载图像,生成描述并转为Document
image_paths = [os.path.join(IMAGE_DIR, f) for f in os.listdir(IMAGE_DIR) if f.endswith(("jpg", "png"))]
if not image_paths:
# 若没有图像,添加测试图像(可替换为实际产品图像)
print("未检测到图像,建议放入产品图像到product_images目录")
image_loader = ImageCaptionLoader(images=image_paths)
image_docs = image_loader.load()
# 2. 加载文本说明
if os.path.exists(TEXT_FILE):
text_loader = TextLoader(TEXT_FILE)
text_docs = text_loader.load()
else:
# 若没有文本文件,创建测试文本
with open(TEXT_FILE, "w", encoding="utf-8") as f:
f.write("手机:屏幕尺寸6.7英寸,电池容量5000mAh,支持快充;\n电脑:屏幕尺寸15.6英寸,内存16GB,存储512GB;")
text_loader = TextLoader(TEXT_FILE)
text_docs = text_loader.load()
# 3. 合并文档,初始化向量库
all_docs = image_docs + text_docs
vector_db = Chroma.from_documents(
documents=all_docs,
embedding=embeddings,
persist_directory=VECTOR_DB_PATH
)
vector_db.persist()
return vector_db
# 初始化知识库
vector_db = init_knowledge_base()
# 构建检索器
retriever = vector_db.as_retriever(k=2)
# -------------------------- 3. 构建多模态RAG链 --------------------------
# 自定义Prompt(整合图像描述和文本信息)
prompt = ChatPromptTemplate.from_template(
"你是产品知识库问答助手,基于以下相关的产品图像描述和文本信息,简洁、准确地回答用户问题:\n"
"相关内容:{context}\n"
"用户问题:{query}\n"
"要求:1. 结合图像描述和文本信息,不添加无关内容;2. 若涉及产品参数,明确标注;3. 回答不超过3句话。"
)
# 构建RAG链
rag_chain = RunnableSequence.from([
lambda x: {"context