基于pypdf和chromadb构建向量库

前面在langgraph构建智能RAG中加载文档和分块入库使用的均是langchain自带的组件,本文使用纯粹的python库实现同样的功能。本文将使用pypdf和chromadb库。

1.安装库

#pip install pypdf

#pip install chromadb

2.加载pdf文档

使用pypdf加载文件代码如下:

from pypdf import PdfReader

使用《beijing_annual_report_2024》作为示例文件

reader = PdfReader ("../data/beijing_annual_report_2024.pdf")

从该文件中提取文本,并删除前后空格。加载后一页为一项

pdf_texts=p.extract_text().strip() for p in reader.pages

剔除空页,因为检索系统不能接受空页

pdf_texts=text for text in pdf_texts if text

输出加载后内容:

打印文档第一页作为输出示例

print(pdf_texts0)

输出内容如下:

各位代表:

现在,......支持雄安新区"三校一院"交钥匙项目开学开诊,公共服务共建共享不断深化。

3.对文本分块

仍使用递归文本分块器对文本分块,具体代码如下:

from langchain_text_splitters import RecursiveCharacterTextSplitter

character_splitter = RecursiveCharacterTextSplitter(

#separators="\\n\\n", "\\n", ". ", " ", "",英文文档的分割符示例

separators="\\n\\n", "\\n", "。", ",", "、", ";", "",

chunk_size=1000,

chunk_overlap=100

)

#把所有文本拼接后再分割

character_split_texts = character_splitter.split_text('\n\n'.join(pdf_texts))

查看分段效果:

['各位......健全重大国',

'升,......中关村科技园挂牌运营',

'......北京向天津、河']

4.创建向量库

chromadb与mongodb类似,使用集合表示一个表,具体代码如下:

import chromadb

from chromadb.utils.embedding_functions import SentenceTransformerEmbeddingFunction

embedding_function = SentenceTransformerEmbeddingFunction(model_name='../models/text2vec-base-chinese')

chroma_client = chromadb.PersistentClient(path="../data/chroma")

chroma_collection = chroma_client.get_or_create_collection("beijing_annual_report_2024", embedding_function=embedding_function)

使用持久化存储,刚创建时为空。

5.分块数据入库

把第3步处理后的所有分块向量化并插入向量库以备检索,具体代码如下:

ids = str(i) for i in range(len(character_split_texts))

chroma_collection.add(ids=ids, documents=character_split_texts)

6.相似性检索

使用集合的query方法进行检索,返回2个匹配的分块,具体代码如下:

query = "促进就业的举措有哪些?"

查询Chorma来获取结果,请求5个结果

results = chroma_collection.query(query_texts=query, n_results=2)

查看检索结果:

results

输出如下:

{'ids': \['8', '36'],

'embeddings': None,

'documents': [['四是加大民生服务保障力度,......深入推进',

'促进 12 万城镇就业困难人员实现就业、......。']],

'uris': None,

'included': 'metadatas', 'documents', 'distances',

'data': None,

'metadatas': \[None, None],

'distances': \[0.4134409427642822, 0.41738224029541016]}

7.工具封装

把第6步的检索功能封装到工具中,工具返回整合后的内容和原始内容供智能体调用,具体代码如下:

from langchain.tools import tool

@tool(response_format="content_and_artifact")#返回原始内容和整合后内容

def retrieve_context(query: str):

"""Retrieve information to help answer a query."""

retrieved_docs = chroma_collection.query(query_texts=query, n_results=2)

serialized = "\n\n".join(

(f"Source: {metadata}\nContent: {content}")

for metadata, content in zip(retrieved_docs'metadatas'0, retrieved_docs'documents'0)

)

#serialized是整合后内容,retrieved_docs为原始内容,原始内容包含元数据

return serialized, retrieved_docs

测试一下工具调用结果:

retrieve_context.invoke("促进就业的举措有哪些?")

输出如下:

#以下格式是输入到大模型中提供上线文的标准格式

'Source: None\nContent: 四是加大民生服务保障力度,......市深入推进\n\nSource: None\nContent: 少于 26 万人......体育赛事。'

8.分析

基于pypdf加载文件后元数据内容不够丰富,仅有公共的元数据,并且没有文件路径,每页没有元数据。

查看元数据:

reader.metadata

输出如下,输出中没有文件名

{'/Author': 'sky',

'/Comments': '',

'/Company': '',

'/CreationDate': "D:20240208203412+12'34'",

'/Creator': 'WPS 文字',

'/Keywords': '',

'/ModDate': "D:20240208203412+12'34'",

'/Producer': '',

'/SourceModified': "D:20240208203412+12'34'",

'/Subject': '',

'/Title': '',

'/Trapped': '/False'}

查看某页内容:

reader.pages3

输出如下:

{'/Contents': {'/Filter': '/FlateDecode'},

'/MediaBox': 0, 0, 595.3, 841.9,

'/Parent': {'/Count': 13,

'/Kids': [IndirectObject(6, 0, 140335219092880),

IndirectObject(19, 0, 140335219092880),

IndirectObject(21, 0, 140335219092880),

IndirectObject(23, 0, 140335219092880),

IndirectObject(25, 0, 140335219092880),

IndirectObject(27, 0, 140335219092880),

IndirectObject(29, 0, 140335219092880),

IndirectObject(31, 0, 140335219092880),

IndirectObject(33, 0, 140335219092880),

IndirectObject(35, 0, 140335219092880),

IndirectObject(37, 0, 140335219092880),

IndirectObject(39, 0, 140335219092880),

IndirectObject(41, 0, 140335219092880)],

'/Type': '/Pages'},

'/Resources': {'/ExtGState': {'/GS13': {'/AIS': False,

'/BM': '/Normal',

'/CA': 1,

'/Type': '/ExtGState',

'/ca': 1}},

'/Font': {'/FT14': {'/BaseFont': '/ZLXSHE+Calibri',

'/DescendantFonts': IndirectObject(16, 0, 140335219092880),

'/Encoding': '/Identity-H',

'/Subtype': '/Type0',

'/ToUnicode': {'/Filter': '/FlateDecode'},

'/Type': '/Font'},

'/FT8': {'/BaseFont': '/LNUHNF+SimSun',

'/DescendantFonts': IndirectObject(10, 0, 140335219092880),

'/Encoding': '/Identity-H',

'/Subtype': '/Type0',

'/ToUnicode': {'/Filter': '/FlateDecode'},

'/Type': '/Font'}}},

'/Type': '/Page'}

基于此提供的上下文内容不够丰富,如果不能满足要求,则不能使用pypdf,仍需使用langchain社区中的文件加载器。

相关推荐
不吃青椒!4 小时前
LangGraph 流式事件处理:从实战到体系
ai·langchain·状态模式
染指11105 小时前
24.RAG进阶(Advanced RAG)-摘要索引
langchain·rag
IManiy6 小时前
知识点之LangGraph 中的四个核心概念:State、Node、Edge 和Checkpoint
langchain
雮尘7 小时前
LangGraph 与 LangSmith 入门教程(JS/TS 版)
前端·人工智能·langchain
_张一凡7 小时前
通往RAG之路(五):主流向量数据库全景解析与选型指南
pinecone·milvus·向量数据库·chroma·qdrant·rag系统搭建
veminhe8 小时前
解决了使用langchain调用聊天模型报的错
langchain
颜酱9 小时前
LangChain上手 Agent:让大模型自己调用工具解决问题
langchain
Niuguangshuo13 小时前
LangChain 学习之旅(二):用 LCEL 与解析器构建标准流水线
学习·langchain·unix
古怪今人14 小时前
Langchain PromptTemplate纯文本模板、ChatPromptTemplate对话消息模板和MessagesPlaceholder消息占位符
langchain
是上好佳佳佳呀14 小时前
【LangChain|Day02】LangChain Prompt 提示词工程笔记
笔记·langchain·prompt