这篇博客是继续Chainlit+LlamaIndex实战教学,带你从零搞定一个多模态RAG系统。啥是RAG?简单说,就是让AI不光会聊天,还能从你的文件堆里挖宝------PDF里的表格、PPT的幻灯片、图片的隐藏秘密,全都一网打尽。想想看,你的AI助手像个超级侦探,能从乱七八糟的文档中提取情报,还能生成聪明回答。这不比纯文本聊天有趣多了?接下来我们就正式开始讲解。
一、学习内容总览
先来个大地图,免得你迷路。这个系统不是科幻小说,而是实打实的Python项目。核心分成两大部分:
- 多模型RAG系统架构(核心:视觉大模型+大语言模型框架+向量数据库协同) 这里是系统的"大脑"。我们用视觉大模型处理图像和图表,用LlamaIndex框架管理文档索引,再加向量数据库存向量数据。简单说,就是让AI"看懂"你的文件,而不是瞎猜。
- 多模态RAG功能实现(覆盖模块开发:multimodal_rag.py核心逻辑、工具类、模型配置、界面集成) 这是"动手"部分。从代码到界面,全链路教你怎么实现。包括处理PDF/PPT/图片的模块、辅助工具、模型集成、环境变量配置,还有Chainlit做的前端聊天UI。学完这个,你能自己搭个AI聊天机器人,上传文件就能问答。
为什么有趣?因为传统RAG只管文本,现在我们升级到多模态------AI能"看到"图片里的猫,还能解释表格里的数据。幽默点说,以前AI是"盲人摸象",现在它戴上了VR眼镜!
二、多模型 RAG 系统架构
好了,进入正题。先聊架构,这就像建房子,得先画蓝图。我们的系统结合了视觉大模型(处理图像)、大语言模型框架(LlamaIndex主打,Langchain辅助),加上向量数据库Milvus。用户输入提示词,系统处理多模态数据(文本/图像/表格),然后生成响应。听起来复杂?别慌,我画个图给你看(其实是借来的示意图,哈哈)。
text-only RAG vs. 多模态 RAG对比图------看,多模态多了一双眼睛!
2.1 多模态 RAG 系统核心组成
- 视觉大模型:负责图像 / 图表处理,含两大场景 图表 / 绘图解析:提取数据趋势,比如从柱状图里读出销售额增长。 图片识别:处理截图、扫描件,比如识别手写笔记。 为什么需要?因为纯文本AI看不懂图片啊!这部分我们用多模态模型来"翻译"图像成文本描述。
- 大语言模型开发框架:双框架支撑 LlamaIndex:核心底座,负责文档切块、索引管理。像个高效的文件管理员。 Langchain:辅助重排数据,优化检索结果。幽默地说,它是"排序小能手",让AI回答更准不乱套。
- 核心组件层:四大关键模块 文本嵌入模型:把文本/图像描述转成向量(数字表示),方便搜索。 基础大语言模型:生成响应,比如DeepSeek或Moonshot------它们像聊天高手。 向量数据库:Milvus,存多模态向量。为什么Milvus?它快如闪电,支持海量数据。 重排数据:优化结果顺序,提升精准度。避免AI先告诉你无关紧要的事。
- 用户交互流程:提示词输入→多模态数据处理(文本 / 图像 / 表格)→生成响应 用户上传文件,系统解析、索引,然后根据查询检索相关片段生成回答。整个过程异步高效,不会让你等得花儿谢。

一个典型的多模态RAG流程图:从Medium文章到AI回答,全链路可视化。
2.2 多模态模型选型
选模型就像选手机,得看需求和预算。我们有在线和开源两种:
- 在线多模态对话模型 模型名称:通义千问 VL-Plus 官方地址:https://www.aliyun.com/product/bailian 核心优势:支持多类型图像解析,无需本地部署。基于阿里云的Qwen系列,它在多模态处理上很强,比如分析PDF里的图像或表格。适合RAG,因为它能无缝集成文档处理。价格?按调用付费,2025年估计有免费试用层(具体查官网)。幽默地说,它像云端保姆,不用你操心服务器。
- 开源免费多模态对话模型 模型名称:InternVL 官方地址:https://internvl.opengvlab.com/ 核心优势:可本地部署,无API成本,适合隐私敏感场景。InternVL擅长图像描述和图表分析,能在RAG中处理PPT幻灯片或扫描图片。2025年版本可能更优化了,支持更大上下文。缺点?部署需要点硬件,但免费就是王道!
选哪个?在线的省心,开源的灵活。根据你的场景混用吧。
三、多模态 RAG 功能实现
理论说完,滚起袖子干活!这部分是代码实战,从核心模块到工具类,一步步教你实现。所有代码基于Python,依赖LlamaIndex、PyMuPDF等库。记住,代码不是死的------多调试,多试错(我试过无数次崩溃,哈哈)。
3.1 rag/multimodal_rag.py(核心逻辑模块)
这是系统的"心脏",处理文件生成Document对象(LlamaIndex的结构化数据单位)。
3.1.1 核心功能定位
- 处理多类型文件(PDF、PPT、图片、文本),生成结构化Document。
- 支持异步执行,提升效率。想象一下,同时上传10个PDF,它不会卡住。
3.1.2 关键函数设计
-
表格提取与处理:parse_all_tables 从PDF页面找表格,转成Pandas DataFrame,保存Excel。还抓表格图像和上下文文本。避坑:加try-except,单个表格出错不崩盘。 代码snippet(简化版):
python
tables = page.find_tables(...) for tab in tables: pandas_df = tab.to_pandas() # 保存Excel,生成描述,建Document
幽默地说,这函数像个会计师,把乱表整理得井井有条。

用PyMuPDF提取PDF表格的示例------从混乱到有序!
- 图像提取与描述:parse_all_images 提取有效图像(滤掉小图),保存,调用describe_image生成描述。加元数据如来源、页码。 代码tip:用fitz.Rect获取bbox,过滤width < page.width / 20的噪音图。
- PDF 文件全处理:process_pdf_file 提取文本(跳页眉页脚)、表格、图像。分组文本块避免过长。整合成Document列表。
- PPT 文件处理:process_ppt_file 先转PDF,再转图像,提取文本/备注,生成描述。完美处理幻灯片。
- 异步数据加载:load_data 按文件类型分流,异步run_jobs处理。返回Document列表。效率翻倍!
3.1.3 控制流与流程说明
load_data收文件列表 → 判断类型 → 调用对应函数 → 异步执行 → 返回Documents。流程图:
3.2 rag/utils.py(多模态工具类)
辅助函数库,像瑞士军刀。
python
import base64
import os
import subprocess
from io import BytesIO
from pathlib import Path
import fitz
from PIL import Image
from pptx import Presentation
from .config import RagConfig
from .llms import moonshot_llm, vllm, deepseek_llm
from .ocr import ocr_file_to_text
def ocr_file_to_text_llm(file_path) -> str:
"""
提取⽂件中的⽂本
:param file_path:
:return:
"""
client = moonshot_llm()
file_object = client.files.create(file=Path(file_path), purpose="file
-extract")
file_content = client.files.content(file_id=file_object.id).json()
return file_content.get("content")
def get_b64_image_from_path(image_path):
with open(image_path, "rb") as image_file:
return base64.b64encode(image_file.read()).decode('utf-8')
def is_image(file_path):
try:
with Image.open(file_path) as img:
img.verify() # 验证⽂件是否是有效的图像
return True
except Exception as e:
print(f"Error: {e}")
return False
def process_table(file):
"""
解析表格:
1、借助ocr直接识别表格内容
2、借助多模态⼤模型识别
:param file:
:return: 表格内容及对表格的描述信息
"""
content = ocr_file_to_text_llm(file)
llm = deepseek_llm()
response = llm.complete(f"你的职责是解释表格。"
f"你是将线性化表格转换成简单中⽂⽂本供⼤型语⾔模型(L
LMs)使⽤的专家。"
f"请解释以下线性化表格: {content}")
return content, response.tex
3.2.1 核心工具函数分类
- 图像处理工具:describe_image用VLLM API描述图像;get_b64_image_from_path转Base64;is_image验证文件。
- 表格处理工具:process_table OCR+DeepSeek解释表格。
- 文本辅助工具:extract_text_around_item抓上下文;process_text_blocks分组文本。
- 格式转换工具:convert_ppt_to_pdf用LibreOffice转格式;convert_pdf_to_images转图像;extract_text_and_notes_from_ppt抓PPT内容;save_uploaded_file存文件。
3.3 rag/llms.py(多模态模型配置)
集成模型:vllm for VLLM(图像描述);moonshot_llm for OCR;deepseek_llm for 解释。更新模型字典支持大上下文。
python
from typing import Dict
from llama_index.llms.openai import OpenAI as DeepSeeK
from openai import OpenAI
from .config import RagConfig
from llama_index.llms.openai.utils import ALL_AVAILABLE_MODELS, CHAT_MODEL
S
DEEPSEEK_MODELS: Dict[str, int] = {
"deepseek-chat": 64000,
}
ALL_AVAILABLE_MODELS.update(DEEPSEEK_MODELS)
CHAT_MODELS.update(DEEPSEEK_MODELS)
def moonshot_llm(**kwargs):
llm = OpenAI(api_key=RagConfig.moonshot_api_key,
base_url="https://api.moonshot.cn/v1",
**kwargs)
return llm
def deepseek_llm(**kwargs):
llm = DeepSeeK(api_key=RagConfig.deepseek_api_key,
model="deepseek-chat",
api_base="https://api.deepseek.com/v1",
temperature=0.7,
**kwargs)
return llm
def vllm(**kwargs):
from openai import OpenAI
llm = OpenAI(api_key=RagConfig.vllm_api_key,
base_url=RagConfig.vllm_base_url,
**kwargs)
return llm
3.4 .env 环境变量(多模态配置新增)
新增VLLM_API_KEY、VLLM_BASE_URL、VLLM_MODEL_NAME。其他如Milvus URI。安全第一,别硬码密钥!
3.5 rag/config.py(多模态配置集成)
Pydantic类管理配置,单例模式。新增VLLM参数,默认从.env取。
python
import os
from pydantic import BaseModel, Field
class RAGConfig(BaseModel):
"""
RAG配置模型。
该模型使⽤Pydantic库来定义和验证配置参数。每个字段都设置了默认值和描述,
以便于理解和维护。这些配置参数对于RAG系统的运⾏⾄关重要,包括数据库连接、
模型维度、API密钥等。
"""
# Milvus URI,⽤于数据库连接
milvus_uri: str = Field(default=os.getenv("MILVUS_URI"), description=
"Milvus URI")
# 嵌⼊模型维度
embedding_model_dim: int = Field(default=512, description="Embedding m
odel dimension")
# Moonshot API密钥
moonshot_api_key: str = Field(default=os.getenv("MOONSHOT_API_KEY"), d
escription="Moonshot API key")
# DeepSeek API密钥
deepseek_api_key: str = Field(default=os.getenv("DEEPSEEK_API_KEY"), d
escription="DeepSeek API key")
# Postgres数据库连接字符串
pg_connection_string: str = Field(default=os.getenv("PG_CONNECTION_STR
ING"), description="Postgres connection string")
# OCR下载⽬录
ocr_download_dir: str = Field(default=os.getenv("OCR_DOWNLOAD_PATH"),
description="OCR download directory")
# OCR基础URL
ocr_base_url: str = Field(default=os.getenv("OCR_BASE_URL"), descripti
on="OCR base URL")
# VLLM API密钥
vllm_api_key: str = Field(default=os.getenv("VLLM_API_KEY"), descripti
on="VLLM API key")
# VLLM基础URL
vllm_base_url: str = Field(default=os.getenv("VLLM_BASE_URL"), descrip
tion="VLLM base URL")
# VLLM模型名称
vllm_model_name: str = Field(default=os.getenv("VLLM_MODEL_NAME"), des
cription="VLLM model name")
# 实例化RAGConfig对象---单例模式
RagConfig = RAGConfig()
3.6 chainlit_ui.py(多模态界面集成)
前端用Chainlit,超级简单。(因为代码太多了,可以去找我要源码,这里的话,主要是一些展示代码)
python
import random
from typing import Optional, List
# 导⼊chainlit库,⽤于构建和部署AI应⽤
import chainlit as cl
# 导⼊chainlit的数据模块,⽤于处理数据相关的操作
import chainlit.data as cl_data
# 从chainlit.element模块中导⼊ElementBased类,⽤于创建基于元素的组件
from chainlit.element import ElementBased
# 从chainlit.input_widget模块中导⼊Select和Switch类,⽤于创建选择和开关输⼊组件
from chainlit.input_widget import Select, Switch
# 从chainlit.types模块中导⼊ThreadDict类,⽤于定义线程字典类型
from chainlit.types import ThreadDict
# 导⼊dotenv库,⽤于加载环境变量
from dotenv import load_dotenv
# 从llama_index.core.base.llms.types模块中导⼊ChatMessage类,⽤于定义聊天消息
类型
from llama_index.core.base.llms.types import ChatMessage
# 从llama_index.core.chat_engine模块中导⼊SimpleChatEngine类,⽤于实现简单的聊
天引擎
from llama_index.core.chat_engine import SimpleChatEngine
# 从llama_index.core.chat_engine.types模块中导⼊ChatMode类,⽤于定义聊天模式
from llama_index.core.chat_engine.types import ChatMode
# 从llama_index.core.memory模块中导⼊ChatMemoryBuffer类,⽤于创建聊天记忆缓冲区
from llama_index.core.memory import ChatMemoryBuffer
# 导⼊⾃定义模块以⽀持特定功能
from persistent.minio_storage_client import MinioStorageClient
from persistent.postgresql_data_layer import PostgreSQLDataLayer
from rag.base_rag import RAG
from rag.config import RagConfig
from rag.multimodal_rag import MultiModalRAG
from rag.traditional_rag import TraditionalRAG
from utils.milvus import list_collections
# 加载环境变量,⽤于配置应⽤程序
load_dotenv()
# 实例化MinIO存储客户端,⽤于与MinIO对象存储服务交互
storage_client = MinioStorageClient()
# 配置Chainlit数据层以使⽤PostgreSQL和MinIO进⾏数据持久化
cl_data._data_layer = PostgreSQLDataLayer(conninfo=RagConfig.pg_connectio
n_string, storage_provider=storage_client)
async def view_pdf(elements: List[ElementBased]):
"""查看PDF⽂件"""
files = []
contents = []
for element in elements:
if element.name.endswith(".pdf"):
pdf = cl.Pdf(name=element.name, display="side", path=element.
path)
files.append(pdf)
contents.append(element.name)
if len(files) == 0:
return
await cl.Message(content=f"查看PDF⽂件:" + ",".join(contents), elemen
ts=files).send()
@cl.set_chat_profiles
async def chat_profile(current_user: cl.User):
if current_user.metadata["role"] != "admin":
return None
# 知识库信息最后存储在关系数据库中:名称,描述,图标
kb_list = list_collections()
profiles = [
cl.ChatProfile(
name="default",
markdown_description=f"⼤模型对话",
icon=f"/public/kbs/4.png",
)
]
for kb_name in kb_list:
profiles.append(
cl.ChatProfile(
name=kb_name,
markdown_description=f"{kb_name} 知识库",
icon=f"/public/kbs/{random.randint(1, 3)}.jpg",
)
)
return profiles
3.6.1 核心界面功能新增
- 多模态开关:设置面板Switch,默认开。
- 展示:图像inline显示,来源side显示。
- 其他:知识库选择、Starters提示、恢复对话、密码认证。

Chainlit文件上传界面------拖拽就好,简单!
3.6.2 关键逻辑:多模态 RAG 调用
main函数判断开关,用MultiModalRAG或TraditionalRAG创建索引。上传文件后流式响应,还显示来源。
4.1 关键参考文档链接
- 通义千问 VL-Plus:https://www.aliyun.com/product/bailian(Qwen系列多模态强,支持RAG文档处理)。
- InternVL:https://internvl.opengvlab.com/(开源图像分析神器)。
- LlamaIndex:https://docs.llamaindex.ai/。
- VLLM API:阿里云DashScope。
4.2 依赖安装命令
核心:pip install pymupdf python-pptx pillow openai libreoffice-python。 原有:pip install pymilvus llama-index-vector-stores-milvus chainlit python-dotenv llama-index-embeddings-huggingface。
结语:这个系统不光实用,还能让你在AI开发中脱颖而出。试试吧,说不定你的下一个项目就靠它了!有问题评论区见,保持好奇,继续coding。😉