简化物业数据管理:使用 Indexify 进行高级数据提取与检索
原文:
towardsdatascience.com/streamline-property-data-management-advanced-data-extraction-retrieval-with-indexify-3b037054ffc2
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/6805c2fece89c143c0d1977b3507d6d3.png
由 Tierra Mallorca 在 Unsplash 上拍摄的照片
TLDR:
传统的数据提取方法往往无法从非结构化内容中挖掘出更深层次的见解,尤其是在房地产领域。
本文探讨了使用 Indexify,一个用于实时、多模态数据提取的开源框架,以更好地分析物业文档。
你将学习如何设置 Indexify,包括服务器设置、提取图创建、文档摄入和数据查询,以及如何创建自定义提取器。
实施 Indexify 可以增强物业文档分析,从而获得更准确的见解、更好的决策和简化的管理。
目录
· 简介 · Indexify 概述 ∘ 提取器 ∘ 协调器 · 教程的先决条件 · 为高级文档分析设置 Indexify ∘ 安装和配置 Indexify ∘ 准备文档集合 · 使用 Indexify 摄入和处理文档 ∘ 设置提取图 ∘ 自定义提取器 ∘ 上传文档 · 使用 Indexify 提出复杂问题 ∘ 语义搜索与查询构建 ∘ 检索和分析结果 · 大规模存储和查询数据 ∘ 与 LangChain 扩展 ∘ 在数据库中存储查询结果 · 总结 · 参考文献和额外资源
简介
传统的数据提取方法往往无法解锁隐藏在非结构化内容中的更深、更复杂的见解。大多数方法仅捕捉到表面信息,而未能揭示更深层次的见解。随着企业的成长和文档集合的扩大,对高级工具的需求变得至关重要,这些工具可以解析、分析和理解这浩瀚的信息海洋。这种深度对于驱动明智的决策、识别趋势和保持竞争优势至关重要。
房地产领域正适合进行由人工智能驱动的转型。通过整合先进的 AI 解决方案,组织可以增强文档分析,解析物业记录,并简化管理流程。更好的数据提取策略可以提升房地产数据分析,提供更准确和可操作的物业文档洞察,从而实现高效的维护、销售以及更多。
在本文中,我将探讨使用 Indexify 进行数据提取和检索,Indexify 是一个由Tensorlake提供的开源框架。我还会展示这个可扩展系统在处理和分析与房产相关的文件方面的能力。
Indexify 概述
Indexify是一个开源的摄取和提取引擎,旨在为实时 LLM 应用提供动力。它能够以极低的延迟从非结构化源实时提取数据。它还支持可应用于各种用例的多模态提取工作流程,包括从文档中提取实体和嵌入、音频转录、摘要以及从图像或视频中检测对象。
它还支持高效的数据索引、存储和检索,使其成为可扩展实时 RAG 系统的强力候选者。
任何工作流程都可以通过 4 个基本步骤轻松实现:
启动 Indexify 服务器和提取器。
创建提取图。
以您需要的格式(视频、图像、音频、PDF 等)摄取数据。
检索提取的数据。
提取器
提取器模块是 Indexify 的核心功能。提取器可以从任何模态的非结构化数据中提取并返回结构化信息。例如,从 PDF 中获取特定信息并以 JSON 格式,将数据转换为嵌入,并在视频中识别面部或对象。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/ee138082ddd03a359d546b1d77f86724.png
图片由作者提供
提取器通常接收非结构化数据作为输入,并输出一系列内容对象和特征。非结构化数据的原始字节存储在 blob 存储中,提取的特征存储在向量存储和结构化存储中以便检索。任何用于处理非结构化数据的模型或算法都可以通过扩展提取器 SDK 中提供的抽象类来实现为提取器。
协调员
这些是 Indexify 中使用的高性能任务调度器。当数据开始被摄取时,它们将任务分配给提取器,帮助实现卓越的速度和性能。
要获取有关 Indexify 的更深入信息,请查看他们的文档。
教程的先决条件
对于这个教程,请确保您有 Python 3.11 或更高版本以获得最佳性能。其他安装说明将在稍后提供。
我将使用Groq作为 LLM 引擎。要开始,请访问这个页面并创建一个 API 密钥。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/afddbe6843eafc9e0d0354e2478a1be4.png
图片由作者提供
此外,还需要安装库。
pip install groq对于数据,我准备了一些房地产手册作为 PDF 文件。请随意使用您自己的与物业管理相关的文档集合。
为高级文档分析设置 Indexify
安装和配置 Indexify
在 Linux 系统上设置 Indexify 很容易。对于开发,你需要运行 3 个终端窗口。
终端 1:用于下载和运行 Indexify 服务器。
终端 2:用于运行 Indexify 提取器,这些提取器处理结构化提取、分块和嵌入。
终端 3:用于运行 Python 脚本来加载和查询 Indexify 服务器中的数据。
你可以使用以下命令启动和运行 Indexify 服务器。请记住检查命令在哪个终端上运行。
TERMINAL1curl https://getindexify.ai|sh./indexify server-d服务器将在localhost:8900上运行。
接下来,创建一个 Python 环境,并安装所有必要的库和提取器。我将在本教程中详细讨论所需的特定提取器。
TERMINAL2pip3 install indexify-extractor-sdk indexify wikipedia indexify-extractor download tensorlake/paddleocr_extractor indexify-extractor download tensorlake/minilm-l6 indexify-extractor download tensorlake/chunk-extractor.
下载后,使用以下命令运行提取器服务器:
TERMINAL2indexify-extractor join-server系统现在已准备好开发。我将在整个教程过程中保持两个终端运行。
准备文档集合
第一步是组织你的文档集合。在这个工作流程中,我将使用 PDF 文档。对于多个文档,你可以按照以下结构组织目录:将所有文档作为 PDF 文件添加到data目录。对于其他数据类型,你必须使用其他提取器或定义自定义提取器,我将在本博客的后续部分讨论。
└── data ├── doc1 ├── doc2 ├── doc3 ├── doc4 ├── venv ├── indexifyfile├── ingest_document.py ├── query_doc.py └── setup_extraction_graph.py使用 Indexify 消费和处理文档
设置提取图
Indexify 可以通过其核心功能提取器处理和存储任何模态的数据。这些提取器被设计用来从大量非结构化数据中提取内容。通过将不同的提取器链接在一起,你可以创建一个管道,简化整个数据提取和存储过程。这个过程通过创建提取图来管理。
对于本教程,我将构建以下提取图:
paddle_ocr:用于从房地产宣传册中识别和提取文本。chunk_extract:将数据分割成块以供 RAG 使用。minilm-l6: 将数据转换为嵌入表示。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/23c5c895100ca39f9561d206caf2ae31.png
图片由作者提供
配置 Indexify 客户端,并使用以下 YAML 格式定义流程。
# setup_extraction_graph.pyfromindexifyimportExtractionGraph,IndexifyClient client=IndexifyClient()extraction_graph_spec=""" name: 'propertyQA' extraction_policies: - extractor: 'tensorlake/paddleocr_extractor' name: 'textextract' - extractor: 'tensorlake/chunk-extractor' name: 'chunker' input_params: chunk_size: 1000 overlap: 100 content_source: 'textextract' - extractor: 'tensorlake/minilm-l6' name: 'pdfembedding' content_source: 'chunker' """extraction_graph=ExtractionGraph.from_yaml(extraction_graph_spec)client.create_extraction_graph(extraction_graph)运行命令以创建提取图。
TERMINAL3python3./setup_extraction_graph.py自定义提取器
为了捕获超出基本字段之外复杂的数据点,我可以创建自定义提取器并将它们添加到我们的提取图中。你可以使用以下模板定义它们。
frompydanticimportBaseModelfromtypingimportListfromindexify_extractor_sdkimportExtractor,Content,Featurefromindexify_extractor_sdk.base_extractorimportContentimportjsonclassInputParams(BaseModel):a:int=0b:str=""classMyExtractor(Extractor):name="your-docker-hub-username/MyExtractor"description="Description of the extractor goes here."# Any python dependencies included in the extractor must be listed here.python_dependencies=["torch","transformers"]# Any system dependencies that the python code here depends on needs to be listed here. We use Ubuntu base images, so any ubuntu package can be installed here.system_dependencies=[]input_mime_types=["text/plain"]def__init__(self):super().__init__()defextract(self,content:Content,params:InputParams)->List[Content]:return[Content.from_text(text="Hello World",feature=Feature.embedding(values=[1,2,3])),Content.from_text(text="Pipe Baz",feature=Feature.embedding(values=[1,2,3])),Content.from_text(text="Hello World",feature=Feature.metadata(value=json.dumps({"key":"value"})),),]defsample_input(self)->Content:Content.from_text(text="Hello World")if__name__=="__main__":MyExtractor().extract_sample_input()InputParams类使用 Pydantic 定义了可以用来配置提取器行为的参数。
MyExtractor是实现提取器的主要类。它指定了可以处理的名字、描述、依赖项和输入类型。任何被 Indexify 消费但与这些 MIME 类型不匹配的内容将不会被发送到这个提取器。
extract方法是其核心功能。它处理输入内容,并返回一个包含如元数据等特征的转换内容对象列表。sample_input方法提供了一个用于测试的示例输入。
例如,这是一个自定义提取器,它以 JSON 格式返回属性详情。
# custom_extractor.pyfrompydanticimportBaseModelfromtypingimportListfromindexify_extractor_sdkimportExtractor,Content,Featurefromindexify_extractor_sdk.base_extractorimportContentimportjsonimportreclassInputParams(BaseModel):price_regex:str=r"$(d{1,3}(,d{3})*(.d+)?)"sqft_regex:str=r"(d+)s*sqs*ft"location_regex:str=r"locateds+ins+([^.]+)"classPropertyExtractor(Extractor):name="your-docker-hub-username/PropertyExtractor"description="Extracts property price, square footage, and location from text."python_dependencies=["re"]system_dependencies=[]input_mime_types=["text/plain"]def__init__(self):super().__init__()defextract(self,content:Content,params:InputParams)->List[Content]:text=content.text()price_match=re.search(params.price_regex,text)sqft_match=re.search(params.sqft_regex,text)location_match=re.search(params.location_regex,text)property_info={"property_price":price_match.group(1)ifprice_matchelse"","property_square_feet":sqft_match.group(1)ifsqft_matchelse"","property_location":location_match.group(1).strip()iflocation_matchelse""}return[Content.from_text(text=json.dumps(property_info),feature=Feature.metadata(value=json.dumps(property_info)))]defsample_input(self)->Content:returnContent.from_text(text="Priced at $500,000 with 2,000 sq ft of living space, located in San Francisco.")if__name__=="__main__":PropertyExtractor().extract_sample_input()您可以将提取器打包到容器中以用于生产,或者使用以下命令在本地安装提取器,并在提取图中使用它。
indexify-extractor install-local custom_extractor:PropertyExtractor上传文档
当提取图设置好时,数据目录中的每个文档都应该通过管道,并以嵌入的形式存储在向量存储中。Indexify 内置了一个向量存储,您可以使用它来存储、查询和检索数据。
# ingest_document.pyimportosimportrequestsfromindexifyimportIndexifyClient# Initialize IndexifyClientclient=IndexifyClient()folder_path="data"forfilenameinos.listdir(folder_path):iffilename.endswith(".pdf"):# Construct the full file pathfile_path=os.path.join(folder_path,filename)# Upload the PDF to Indexifyclient.upload_file("propertyQA",file_path)print(f"Uploaded:{filename}")您可以使用 Indexify UI 在localhost:8900/ui查看向量存储和索引。
https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/7087bda534161d371f6b1ef69aace058.png
作者图片
您也可以使用客户端访问索引:
fromindexifyimportIndexifyClient client=IndexifyClient()content_ids=[content.idforcontentinclient.list_content("propertyQA")]extract=client.get_extracted_content(content_ids[1],"propertyQA","textextract")embedding=client.get_extracted_content(content_ids[1],"propertyQA","pdfembedding")在 Indexify 中,摄取的数据也存储在 SQL 表中,允许您使用内置 API 和 SQL 查询查询数据。
result=client.sql_query("select * from propertyQA;")输出:
SqlQueryResult(result=[{'content_id':'d6e584685d74a21d','type':'text'},{'content_id':'e32fd65fc2bbebf3','type':'text'}])使用 Indexify 提出复杂问题
语义搜索与查询构建
Indexify 的高级提取引擎赋予用户构建和执行超出基本数据提取的复杂查询的能力。Indexify 可以解释您文档的上下文和语义,从而允许提出更复杂的问题。
Indexify 从创建的索引中检索相关上下文,并返回一个内容对象。该对象的信息可用于构建复杂的提示,这些提示可以传递给 LLM 以生成适当的响应。让我们看看这是如何工作的。
results=client.search_index(name=index,query=question,top_k=3)context=""forresultinresults:context=context+f"content id:{result['content_id']}n npassage:{result['text']}n"在这里,Indexify 通过索引执行简单的语义搜索,并返回最相关的段落以及如内容 ID 等元数据,让您了解结果上下文和重要性。text参数中的数据可用于构建上下文。
获取和分析结果
语义搜索和复杂查询允许您深入挖掘您的文档集合,提取出那些并非一目了然的见解。
复杂问题的示例:
“根据历史数据,哪些属性维护问题风险最高?”
“地震损坏的风险有哪些,采取了哪些缓解措施?”
LLM 可以帮助以描述性和准确性的方式回答此类查询。从上一步检索到的上下文可以用来构建复杂的提示。
"You are a real estate expert and you have to help me manage my property. Answer the question, based on the context. Answer "Informationnotfound" if there is no context. Do not hallucinate. nquestion: {question} ncontext: {context}"构建的提示随后用于查询 LLM。对于教程,我使用了 Groq 的gemma-7b模型。以下是工作流程的完整代码。
#query_doc.pyfromindexifyimportIndexifyClientfromgroqimportGroq client=IndexifyClient()groq_client=Groq(api_key="API_KEY",)defget_context(question:str,index:str,top_k=3):results=client.search_index(name=index,query=question,top_k=3)context=""forresultinresults:context=context+f"content id:{result['content_id']}n npassage:{result['text']}n"returncontextdefcreate_prompt(question,context):returnf"You are a real estate expert and you have to help me manage my property. Answer the question, based on the context. Answer "Informationnotfound" if there is no context. Do not hallucinate. nquestion: {question} ncontext: {context}"defgenerate_response(prompt):chat_completion=groq_client.chat.completions.create(messages=[{"role":"user","content":prompt,}],model="gemma-7b-it",)returnchat_completion.choices[0].message.content question="What are the risks of earthquake damage and what mitigation measures are taken?"context=get_context(question,"propertyQA.pdfembedding.embedding")prompt=create_prompt(question,context)response=generate_response(prompt)print(response)运行此文件以获取响应。
TERMINAL3python3./query_doc.py**Risks of Earthquake Damage:**The provided text doesnotinclude information regarding the specific risks of earthquake damage,so this information cannot be extractedfromthe given context.**Mitigation Measures:**The provided text mentions that the structureisearthquake resistanceasper IS Standards.Specific mitigation measures mentioned include:-Metal/Fibre strip reinforcement onalljoints to avoid cracks.-Sharp edges avoided on fabrications to provide safety especiallyforchildren.一旦检索了数据,您就可以分析它,以识别规模化的物业管理中的趋势、异常和可操作的见解。可视化工具对于映射趋势和传达发现至关重要。例如,在房地产数据分析中,您可能会发现某些物业的维修成本较高,这表明需要主动维护。
规模化存储和查询数据
使用 LangChain 进行扩展
优化您的系统以实现高效的索引和检索,以管理大规模的属性数据和房地产分析。这涉及到配置向量存储以高效地管理大量嵌入。在生产环境中,Indexify 可以水平扩展到多个服务器实例和协调器,以并行化实时数据提取和存储。您还可以在提取图中微调chunk_size和overlap等参数,以在粒度和性能之间取得平衡。
extractor:'tensorlake/chunk-extractor'name:'chunker'input_params:chunk_size:1000overlap:100content_source:'textextract'Indexify 与流行的 LangChain 框架很好地集成,这是一个用于构建 AI 应用程序的高度可扩展框架。要开始,请安装库。
TERMINAL3pip install indexify-langchain langchain-groq我正在使用 LangChain 的基于 Indexify 的检索器。我将传递我准备好的索引和top_k参数。
fromindexifyimportIndexifyClient client=IndexifyClient()fromindexify_langchainimportIndexifyRetriever params={"name":"propertyQA.pdfembedding.embedding","top_k":2}retriever=IndexifyRetriever(client=client,params=params)这里是完整的代码:
# langchain_query_doc.pyimportrequestsimportdotenv# Setup retrieverfromindexifyimportIndexifyClientfromindexify_langchainimportIndexifyRetriever client=IndexifyClient()params={"name":"propertyQA.pdfembedding.embedding","top_k":2}retriever=IndexifyRetriever(client=client,params=params)fromlangchain_groqimportChatGroq llm=ChatGroq(model="gemma-7b-it",temperature=0,max_tokens=None,timeout=None,max_retries=2,api_key="API_KEY",)# Setup Chat Prompt Templatefromlangchain.promptsimportChatPromptTemplate template=""" You are a real estate expert and you have to help me manage my property. Answer the question, based on the context. Answer "Information not found" if there is no context. Do not hallucinate. nquestion: {question} ncontext: {context} """prompt=ChatPromptTemplate.from_template(template)fromlangchain.schema.runnableimportRunnablePassthroughfromlangchain.schema.output_parserimportStrOutputParser rag_chain=({"context":retriever,"question":RunnablePassthrough()}|prompt|llm|StrOutputParser())# Queryquery="What are the risks of earthquake damage and what mitigation measures are taken?"print(rag_chain.invoke(query))这使用IndexifyRetriever根据查询检索最相关的段落。然后,使用ChatPromptTemplate创建一个针对上下文的提示。该提示传递给 LLM,其中模型处理信息并生成响应。
在数据库中存储查询结果
一旦执行了查询并检索了结果,将此数据存储在结构化数据库中,确保您可以引用它并进行进一步的分析。
首先,为了在数据库中存储查询结果,设置一个关系型数据库并定义一个可以容纳 Indexify 返回的复杂数据结构的模式。
下面是一个如何在 PostgreSQL 数据库中存储查询结果的示例:
importpsycopg2# Connect to your PostgreSQL databaseconn=psycopg2.connect(dbname="indexify_results",user="your_username",password="your_password",host="localhost",port="5432")cursor=conn.cursor()# Create a table to store query resultscursor.execute(""" CREATE TABLE IF NOT EXISTS query_results ( id SERIAL PRIMARY KEY, query TEXT, content_id VARCHAR(255), passage TEXT ); """)conn.commit()# Example function to store resultsdefstore_results(question:str,results:list):forresultinresults:cursor.execute(""" INSERT INTO query_results (query, content_id, passage) VALUES (%s, %s, %s); """,(question,result['content_id'],result['text']))conn.commit()# Retrieve and store query resultsquestion="Which properties are likely to require renovation next year?"results=client.search_index(name="propertyQA.pdfembedding.embedding",query=question,top_k=5)store_results(question,results)# Close the database connectioncursor.close()conn.close()在定义数据库模式时,请考虑数据的关系和复杂性。该模式应容纳内容 ID 和段落文本以及元数据,如时间戳、文档来源以及任何相关的标签或类别。
这里是一个您可以考虑的示例模式。
CREATE TABLE query_results(idSERIAL PRIMARY KEY,query TEXT,content_id VARCHAR(255),passage TEXT,timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,document_source VARCHAR(255),tags TEXT[]);https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/4b017e35e113ead44ea7005fbfab1241.png
作者图片
总结
我们通过房地产行业的例子,介绍了 Indexify 如何为需要更深入实时分析的应用程序提供高效的数据提取和检索。我们详细说明了 Indexify 的工作原理,包括如何构建用于数据检索的知识库。此外,我们还探讨了如何为更大的数据集和更高的吞吐量扩展系统。最后,我们讨论了将结果存储在结构化数据库中以供未来参考和深入分析的方法。完整的代码可以在 GitHub 链接这里找到。
作为下一步,您可以探索并构建利用自定义模型和 LLM(大型语言模型)的各种用例的定制提取器。同时,查看 Indexify 如何与其他数据库和向量存储一起使用。
参考文献 & 补充资源
[1] Indexify 文档 (2023)。文档
[2] Tensorlake Github 仓库(2023)。代码库Codebase
[3] Tensorlake Discord 频道(2023)。Discord
图片
如果没有特别说明,所有图像均由作者创建。
