【多模态】13-基于Gemini的半结构化图像检索系统分析

📅 2026/8/7 12:12:42
【多模态】13-基于Gemini的半结构化图像检索系统分析
1. 案例目标本案例演示如何使用Gemini Pro Vision模型从图像中提取结构化信息并结合向量数据库实现语义搜索和元数据过滤的自动检索系统。具体目标包括从收据图像中提取结构化信息公司、日期、地址、总额等将提取的结构化信息存储到向量数据库中实现基于语义搜索和元数据过滤的混合检索功能展示如何结合多模态LLM和向量检索技术构建实用的图像检索系统2. 技术栈与核心依赖本案例使用了以下技术栈和核心依赖多模态LLM: Gemini Pro Vision - 用于从图像中提取结构化信息向量数据库: Qdrant - 用于存储和检索结构化数据的向量表示嵌入模型: Gemini Embedding - 用于将文本转换为向量表示核心框架: LlamaIndex - 提供多模态处理和向量检索功能结构化输出: Pydantic - 定义和验证结构化数据模型主要依赖包:llama-index-multi-modal-llms-gemini llama-index-vector-stores-qdrant llama-index-embeddings-gemini llama-index-llms-gemini3. 环境配置本案例需要配置以下环境变量GOOGLE_API_KEY - 用于访问Gemini API的密钥注意: 需要获取Google AI Studio的API密钥并将其设置为环境变量GOOGLE_API_KEY。4. 案例实现1 准备图像数据下载SROIE v2收据图像数据集并定义函数加载图像文件路径def get_image_files(path: Path) - List[Path]: 获取指定目录下的所有图像文件 files [] for ext in [*.jpg, *.jpeg, *.png]: files.extend(path.glob(ext)) return sorted(files)2 定义结构化数据模型使用Pydantic定义收据信息的结构化模型class ReceiptInfo(BaseModel): company: Optional[str] Field(description公司名称) date: Optional[str] Field(description日期) address: Optional[str] Field(description地址) total: Optional[float] Field(description总额) currency: Optional[str] Field(description货币) phone: Optional[str] Field(description电话号码) email: Optional[str] Field(description电子邮件地址)3 实现结构化信息提取函数创建异步函数调用Gemini Pro Vision模型从图像中提取结构化信息async def pydantic_gemini( img_doc: ImageDocument, pydantic_model: Type[BaseModel] ) - BaseModel: 使用Gemini Pro Vision从图像中提取结构化信息 gemini_llm GeminiMultiModal( model_namemodels/gemini-pro-vision, temperature0.1, max_tokens1024, ) # 构建提示词 prompt f 请从这张收据图像中提取以下信息并按照指定的JSON格式返回 {pydantic_model.model_json_schema()} 请只返回JSON格式的结果不要包含其他文本。 # 调用模型 response await gemini_llm.acomplete( promptprompt, image_documents[img_doc] ) # 解析响应 try: json_str response.text.strip() # 提取JSON部分 start_idx json_str.find({) end_idx json_str.rfind(}) 1 if start_idx ! -1 and end_idx ! -1: json_str json_str[start_idx:end_idx] return pydantic_model.model_validate(json_str) except Exception as e: print(f解析响应时出错: {e}) return pydantic_model()4 处理图像文件使用SimpleDirectoryReader加载图像并并发处理图像文件生成结构化结果async def run_jobs( jobs: List[Tuple[ImageDocument, Type[BaseModel]]], semaphore: asyncio.Semaphore, ) - List[BaseModel]: 并发处理多个图像提取任务 async def process_job( job: Tuple[ImageDocument, Type[BaseModel]] ) - BaseModel: img_doc, pydantic_model job async with semaphore: return await pydantic_gemini(img_doc, pydantic_model) tasks [process_job(job) for job in jobs] return await asyncio.gather(*tasks) # 加载图像 image_documents SimpleDirectoryReader( input_dir./receipt_images, required_exts[.jpg, .jpeg, .png] ).load_data() # 创建任务列表 jobs [(img_doc, ReceiptInfo) for img_doc in image_documents] # 并发处理 semaphore asyncio.Semaphore(5) # 限制并发数 receipt_infos await run_jobs(jobs, semaphore)5 将结构化数据转换为TextNode实现函数将ReceiptInfo对象转换为TextNode设置文本内容、元数据及排除的嵌入/LLM元数据键def get_nodes_from_objs( objs: List[BaseModel], img_paths: List[str] ) - List[TextNode]: 将结构化对象转换为TextNode nodes [] for obj, img_path in zip(objs, img_paths): # 创建文本内容 text_content f 公司名称: {obj.company or 未知} 日期: {obj.date or 未知} 地址: {obj.address or 未知} 总额: {obj.total or 未知} 货币: {obj.currency or 未知} 电话: {obj.phone or 未知} 电子邮件: {obj.email or 未知} # 创建元数据 metadata { company: obj.company, date: obj.date, address: obj.address, total: obj.total, currency: obj.currency, phone: obj.phone, email: obj.email, image_path: img_path, } # 创建TextNode node TextNode( texttext_content.strip(), metadatametadata, excluded_embed_metadata_keyslist(metadata.keys()), excluded_llm_metadata_keyslist(metadata.keys()) ) nodes.append(node) return nodes6 创建向量存储索引使用QdrantVectorStore和GeminiEmbedding/LLM初始化VectorStoreIndex# 初始化向量存储 vector_store QdrantVectorStore( clientqdrant_client, collection_namereceipt_collection ) # 初始化嵌入模型和LLM embed_model GeminiEmbedding( model_namemodels/embedding-001, api_keyos.getenv(GOOGLE_API_KEY) ) llm Gemini( model_namemodels/gemini-pro, api_keyos.getenv(GOOGLE_API_KEY) ) # 创建索引 index VectorStoreIndex( nodesnodes, embed_modelembed_model, llmllm, vector_storevector_store )7 定义向量存储信息和自动检索器定义VectorStoreInfo包含收据内容信息和元数据字段的描述并初始化VectorIndexAutoRetrievervector_store_info VectorStoreInfo( content_info收据的详细信息包括公司名称、日期、地址、总额等, metadata_info[ MetadataInfo( namecompany, typestring, description公司名称 ), MetadataInfo( namedate, typestring, description收据日期 ), MetadataInfo( nameaddress, typestring, description公司地址 ), MetadataInfo( nametotal, typefloat, description收据总额 ), MetadataInfo( namecurrency, typestring, description货币类型 ), MetadataInfo( namephone, typestring, description电话号码 ), MetadataInfo( nameemail, typestring, description电子邮件地址 ) ] ) # 创建自动检索器 retriever VectorIndexAutoRetriever( indexindex, vector_store_infovector_store_info, similarity_top_k3, empty_query_top_k10 )8 实现查询和结果展示实现display_response函数用于打印节点内容和显示关联图像并执行查询示例def display_response(response: QueryBundle) - None: 显示查询结果 for node in response.nodes: print( * 50) print(文本内容:) print(node.text) print(\n元数据:) for key, value in node.metadata.items(): print(f{key}: {value}) # 显示图像 if image_path in node.metadata and os.path.exists(node.metadata[image_path]): print(\n关联图像:) display(Image(filenamenode.metadata[image_path])) print( * 50) # 执行查询 query 查找总额超过100美元的收据 response retriever.retrieve(query) display_response(response)5. 案例效果本案例实现了以下效果结构化信息提取: 成功从收据图像中提取公司名称、日期、地址、总额等结构化信息向量存储与检索: 将提取的结构化信息存储到向量数据库中实现高效的语义检索混合检索: 结合语义搜索和元数据过滤支持复杂的查询需求可视化展示: 展示检索结果的同时显示关联的原始图像6. 案例实现思路本案例的实现思路如下多模态处理: 利用Gemini Pro Vision的多模态能力从图像中提取结构化信息结构化输出: 使用Pydantic定义数据模型确保提取的信息具有一致的结构向量表示: 将结构化信息转换为向量表示便于进行语义检索元数据过滤: 保留结构化信息作为元数据支持精确的过滤查询自动检索: 使用VectorIndexAutoRetriever自动分析查询意图结合语义搜索和元数据过滤7. 扩展建议本案例可以进一步扩展和优化支持更多文档类型: 扩展到发票、合同等其他文档类型的结构化信息提取多语言支持: 支持多语言文档的结构化信息提取和检索更复杂的查询: 支持更复杂的查询条件如时间范围、金额范围等用户界面: 开发图形用户界面方便用户上传文档和执行查询增量更新: 支持增量添加新文档到向量数据库性能优化: 优化向量存储和检索的性能支持大规模文档处理8. 总结本案例展示了如何结合多模态LLM和向量检索技术构建一个实用的半结构化图像检索系统。通过使用Gemini Pro Vision从图像中提取结构化信息并将这些信息存储到向量数据库中我们实现了语义搜索和元数据过滤的混合检索功能。这种方法可以应用于各种需要从图像中提取结构化信息并进行检索的场景如文档管理、财务分析等。核心价值: 本案例的核心价值在于展示了多模态LLM与向量检索技术的结合为构建智能文档管理系统提供了实用方案。