RAG 进阶 半结构化数据

我在LlamaIndex和LangChain框架学习中,都有玩过RAG。最近准备开个RAG进阶系统,一起学习AI, 一起成长。欢迎点赞,留言交流。

前言

RAG是一种自然语言处理技术,它将检索(向量数据库)和生成式人工智能模型的能力,有效提高信息检索质量,我们称之为检索增强生成技术。

ChatGPT是聊天机器人,那么基于大模型的文档聊天机器人,就是RAG应用了。

Naive RAG

Naive RAG 指最基本的检索生成,包括文档分块、嵌入(Embedding)、并基于用户提出的问题进行语义相似性搜索来生成检索内容。本文我们将在Naive RAG的基础上,升华我们对RAG的认识和能力。

Naive RAG的优点是简单,缺点是性能比较差,质量也不高,本系列让我们一起来学习Advanced RAG。

Semi-Structured Data

Semi Structured Data半结构化数据的RAG是我们Advanced RAG学习的第一篇。那么什么是半结构化数据呢?这个应该是相当结构化数据来说的,我们先来理下这些概念。

  • 结构化数据

信息有预定义的结构格式。举子例子,在Mysql中,数据表的行与列分别对数据进行了预定义,这就是典型的结构化数据。它的优点是非常易于搜索与分析。

  • 非结构化数据

没有特定的格式和结构,主要由文字、图片、多媒体等构成。非结构化数据不太好统一处理,但是这些数据又是RAG需要检索的重点内容,十分具有挑战性。

  • 半结构化数据

介于结构化和非结构化之间,它由两种格式的数据混合在一起。那么我们怎么来处理呢?结构化数据我们可以用SQL等DSL语言快速解决问题,非结构化数据我们可以拆分,再embedding检索。但是如果我们的数据是结构化和非结构化混合的半结构化数据。文档的拆分就会破坏表结构, 同时表格和图片要做向量化,然后做语义查询。

PDF文档就是半结构化数据的例子。它里面包含文字、表格、图片等。等下,我们就来挑战一下怎么基于半结构化数据构建RAG。主要会用到以下几个组件:unstructured包,帮助我们自定义管道或流来处理文字、图表、图片这些元素。还有就是LangChain,我们用它来搭建整个RAG应用。向量数据库我们用的是chromadb。

Nvidia 股权变量声明

等下demo里处理的半结构化数据来自Nvida的一份股权变更声明。大家可以从下面的截图看到它的内容,比较小,方便展示结构化的图表和非结构化的文字,我们打理过后的效果。

image.png

实战

  • 安装依赖包
!pip install langchain unstructured[all-docs] pydantic lxml openai chromadb tiktoken -q -U

langchain是RAG应用开发框架、unstructured支持半结构或非结构化数据处理、pydantic可以做数据验证和解析转换、lxml做xml解析、ooenai是大模型、chromadb是向量数据库、tiktoken可以统计token数量。

  • 下载 PDF文件,命名为statement_of_changes.pdf
!wget -o statement_of_changes.pdf https://d18rn0p25nwr6d.cloudfront.net/CIK-0001045810/381953f9-934e-4cc8-b099-144910676bad.pdf

  • 安装poppler-utils和tesseract-ocr

这两个包是系统包,用于PDF文件内容的抽取以及字符的识别,安装命令会因系统不一样有所区别(mac/windows/linux)

!apt-get install poppler-utils tesseract-ocr

  • 准备LLM ,这里我们使用gpt4
import os
os.environ["OPENAI_API_KEY"] = ""

  • 编码

首先,让我们使用unstructured库提供的partition_pdf将PDF文档中的内容分成不同类型的元素。

from typing import Any
from pydantic import BaseModel
from unstructured.partition.pdf import partition_pdf

raw_pdf_elements = partition_pdf(
    filename = "statement_of_changes.pdf",
    extract_images_in_pdf=False,
    infer_table_structure=True,
    # 基于标题来划分chunk
    chunking_strategy = "by_title",
    max_characters=4000,
    new_after_n_chars=3000,
    combine_text_under_n_chars=2000,
    image_output_dir_path="."
)

我们来聊下partition_pdf函数里的几个参数的意义。extract_images_in_pdf 表示是否要抽取pdf里的图片,这里不处理,因为当前pdf里面没有图片。infer_table_structure 表示是否来抽取表格数据,这里是处理。从代码运行看,它会触发一些模型文件并加载。从下图可以看到,使用的是microsoft/table-transformer-struct-recognition模型,需要使用到GPU资源,否则就非常慢。

image.png

  • 将元素分类
category_counts = {}
for element in raw_pdf_elements:
    category = str(type(element))
    if category in category_counts:
        category_counts[category] += 1
    else:
        category_counts[category] = 1
unique_categories = set(category_counts.keys())
category_counts

通过遍历raw_pdf_elements,我们得到每个elment的类型。set 帮助我们去重,拿到了所有的类别,category_counts字典包含了每个类别的数量信息。

image.png

从上图可以看到,CompositionElement有5个,Table有4个。接下来,我们可以根据这些类型,将不同的内容放到不同的处理容器中,完成分拣操作。

class Element(BaseModel):
    type: str
    text: Any

table_elements = []
text_elements = []
for element in raw_pdf_elements:
    if "unstructured.documents.elemnts.Table" in str(type(element)):
        table_elements.append(Element(type="table", text=str(element)))
     elif "unstructured.documents.elments.CompositeElement" in str(type(element)):
     text_elements.append(Element(type="text", text=str(element)))
     print(len(table_elements))
     print(len(text_elements))

打印是4和5,我们再来打印下结构化的table。

image.png

从打印结果,可以看出所对应的表格,识别的很靠谱。table_elements[0]对应的是下图的这块,我们了解了unstructured是如何解析table的。

image.png

Chain

LangChain构建一条Chain来处理数据了。

from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema.output_parser import StrOutputParser
# 对文本和表格做摘要
prompt_text = """
You are responsible for concisely summarizing table or text chunk.
{element}
"""
prompt = ChatPromptTemplate.from_template(prompt_text)
model = ChatOpenAI(temperature=0,model="gpt-4")
summarize_chain={"element": lambda x: x} | prompt | model | StrOutputParser

# 对每个element都做, 并发是5
# 给表格做摘要, 表格也是文本
tables = [i.text for i in table_elements]
table_summarizes = summarize_chain.batch(tables, {"max_concurrency": 5})
# 给文本做摘要
texts = [i.text for i in text_elments]
text_summarizes = summarize_chain.batch(texts, {"max_concurrency": 5})

接下来,我们再使用MultiVectorRetriever构建检索链,它会将摘要信息和原始文本信息以父子关系一对一关联起来。这样即可以使用到原始文本,也可以使用到摘要信息,帮助我们提高RAG的质量。

# 生成唯一id
import uuid
# 嵌入,文本数据转向量数据
from langchain.embeddings import OpenAIEmbeddings
# Document 文档
from langchain.schema.document import Document
# 内存存储
from langchain.storage import InMemoryStore
# Chroma向量数据库
from langchain.vectorstores import Chroma
# 声明向量数据库实例
vectorstore = Chroma(collection_name="summaries", embedding_function=OpenAIEmbeddings())
store = InMemoryStore()
# 通过key 将父子文档关联起来
id_key="doc_id"
# 检索器
retriever = MultiVectorRetriever(
    vectorstore = vectorstore,
    docstore = store,
    id_key=id_key
)
# 对每个文本生成文本ID
doc_ids = [str(uuid.uuid4()) for _ in texts]
# s是摘要,metadata是原数据,里面包含id_key
summary_texts = [
    Document(page_content=s, metadata={id_key:doc_ids[i]})
    for i, s in enumerate(text_summaries)
]
# 将摘要放进向量数据库,会做Embedding
retriever.vectorstore.add_documents(summary_texts)
# 将原文放入内存存储
retriever.docstore.mset(list(doc_ids, texts))
# 表格也来做一下
table_ids = [str(uuid.uuid4()) for _ in tables]
summary_tables = [
    Document(page_content=s, metadata={id_key:table_ids[i]})
    for i, s in enumerate(table_summaries)
]
retriever.vectorstore.add_documents(summary_tables)
retriever.docstore.mset(list(zip(table_ids, tables)))

集成

from langchain.schema.runnable import RunnablePassthrough

template = """Answer the question based only on the following context, which can include text and tables:
{context}
Question: {question}
"""
prompt = ChatPromptTemplate.from_template(template)

## LLM
model = ChatOpenAI(temperature = 0, model="gpt-4")

chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt
    | model
    | StrOutputParser()
)

执行

我们基于文档中的表格数据进行提问,在某个时刻对某只股票做了交易,或变更,最后还有受益人。

image.png

chain.invoke("How many stocks were disposed?Who is the beneficial owner?")

image.png

注意,我们这里使用的是gpt4, 大家可以切换成gpt-3.5-turbo, 你会发现就不那么work了。

总结

  • MultiVectorRetriever
  • unstructured
  • chromadb 和 InMemoryStore

那么,如何系统的去学习大模型LLM?

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

作为一名热心肠的互联网老兵,我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。

但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

所有资料 ⚡️ ,朋友们如果有需要全套 《LLM大模型入门+进阶学习资源包》,扫码获取~

篇幅有限,部分资料如下:

👉LLM大模型学习指南+路线汇总👈

💥大模型入门要点,扫盲必看!
在这里插入图片描述
💥既然要系统的学习大模型,那么学习路线是必不可少的,这份路线能帮助你快速梳理知识,形成自己的体系。
在这里插入图片描述

👉大模型入门实战训练👈

💥光学理论是没用的,要学会跟着一起做,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
在这里插入图片描述

👉国内企业大模型落地应用案例👈

💥《中国大模型落地应用案例集》 收录了52个优秀的大模型落地应用案例,这些案例覆盖了金融、医疗、教育、交通、制造等众多领域,无论是对于大模型技术的研究者,还是对于希望了解大模型技术在实际业务中如何应用的业内人士,都具有很高的参考价值。 (文末领取)
在这里插入图片描述
💥《2024大模型行业应用十大典范案例集》 汇集了文化、医药、IT、钢铁、航空、企业服务等行业在大模型应用领域的典范案例。

在这里插入图片描述

👉LLM大模型学习视频👈

💥观看零基础学习书籍和视频,看书籍和视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。 (文末领取)
在这里插入图片描述

👉640份大模型行业报告👈

💥包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。
在这里插入图片描述

👉获取方式:

这份完整版的大模型 LLM 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

😝有需要的小伙伴,可以Vx扫描下方二维码免费领取🆓

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值