前言
之前讲了一些关于 RAG 的使用技巧和经验,今天我们提供两个进阶版的文本切分和检索的方法,希望对你有所帮助。以下两种方法取自 LangChain 的官方示例,感兴趣也可以直接去阅读官方文档。
一、父文档检索 Parent Document Retriever
当我们去切分文本的时候,会有两方面的考虑:
细粒度的文档块,这样在使用向量模型进行编码的时候,就能更好的表示这个文档块的语义含义,而且这个文档块所含的噪音数据会更少
粗粒度的文档块,当我们召回后需要调用大模型进行生成回答,细粒度的文档块会丢失一些上下文信息,有一定的语义损失
LangChain 中的 Parent Document Retriever 就相当于结合了不同粒度的文本块去构建检索过程,具体的实现流程如下:
首先就是使用两个文本分割器去将文本切分为父文档块和子文档块,然后建立向量存储区存储子块,建立内存存储区存储父块。之后我们需要创建 Parent Document Retriever,将上面定义好的分割器、存储器,并执行add_documents 方法将文档添加到检索器中。
在使用的时候,调用 get_relevant_documents 方法,这个时候实际上会调用向量检索返回子块的 ID,然后根据子块ID 将对应父块的内容返回给用户。
下面是示例代码
from langchain.retrievers import ParentDocumentRetriever
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.storage import InMemoryStore
from langchain.document_loaders import TextLoader
loaders = [
TextLoader('../../paul_graham_essay.txt'),
TextLoader('../../state_of_the_union.txt'),
]
docs = []
for l in loaders:
docs.extend(l.load())
# This text splitter is used to create the parent documents
parent_splitter = RecursiveCharacterTextSplitter(chunk_size=2000)
# This text splitter is used to create the child documents
# It should create documents smaller than the parent
child_splitter = RecursiveCharacterTextSplitter(chunk_size=400)
# The vectorstore to use to index the child chunks
vectorstore = Chroma(collection_name="split_parents", embedding_function=OpenAIEmbeddings())
# The storage layer for the parent documents
store = InMemoryStore()
retriever = ParentDocumentRetriever(
vectorstore=vectorstore,
docstore=store,
child_splitter=child_splitter,
parent_splitter=parent_splitter,
)
retriever.add_documents(docs)
retrieved_docs = retriever.get_relevant_documents("justice breyer")
二、多向量检索 MultiVector Retriever
父文档检索的思路是,我利用相似度召回了一个语义上相似的小块,然后返回一个能提供完整上下文信息的大块,这样可以帮助模型更好的理解上下文的语义,进行高质量的回答。
而多向量检索的思路是为同一篇文档提供不同视角的向量建模,比如:
分割文档,就是将文档切分为不同大小的块,然后分别构建向量
摘要,为每个文档创建摘要,将其与文档一起嵌入(或者替代文档);可以利用大模型进行文档总结,输出摘要内容。摘要一般包含了整篇文档的语义信息,但是会比原文要更精简。当然,使用大模型进行总结的时候,需要对大模型效果进行评估,正常来说 6B、7B 大小的模型效果不会太好。
假设性问题:为每个文档创建适合回答的假设性问题,将其与文档一起嵌入。这个是一个典型的逆向思维的例子,就是根据现在有的这篇文档,先让大模型提出几个这篇文档能够解答的问题,然后将这些问题编码成向量进行存储。这其实基于一个假设就是如果一篇文章能回答某一个问题,那么也可以回答与其相似的问题,当然,这个假设在一般情况下都是成立的,因此可以拿来使用。
import uuid
from langchain.retrievers.multi_vector import MultiVectorRetriever
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.storage import InMemoryStore
from langchain.document_loaders import TextLoader
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.document import Document
from langchain.output_parsers.openai_functions import JsonKeyOutputFunctionsParser
def func1():
# 方法1 分割文档,生成更小的组块
child_text_splitter = RecursiveCharacterTextSplitter(chunk_size=400)
sub_docs = []
for i, doc in enumerate(docs):
_id = doc_ids[i]
_sub_docs = child_text_splitter.split_documents([doc])
for _doc in _sub_docs:
_doc.metadata[id_key] = _id
sub_docs.extend(_sub_docs)
return sub_docs
def func2():
# 方法2 生成摘要
chain = (
{"doc": lambda x: x.page_content}
| ChatPromptTemplate.from_template("Summarize the following document:\n\n{doc}")
| ChatOpenAI(max_retries=0)
| StrOutputParser()
)
summaries = chain.batch(docs, {"max_concurrency": 5})
summary_docs = [Document(page_content=s,metadata={id_key: doc_ids[i]}) for i, s in enumerate(summaries)]
return summary_docs
def func3():
# 方法3 生成假设性的问题
functions = [
{
"name": "hypothetical_questions",
"description": "Generate hypothetical questions",
"parameters": {
"type": "object",
"properties": {
"questions": {
"type": "array",
"items": {
"type": "string"
},
},
},
"required": ["questions"]
}
}
]
chain = (
{"doc": lambda x: x.page_content}
# Only asking for 3 hypothetical questions, but this could be adjusted
| ChatPromptTemplate.from_template("Generate a list of 3 hypothetical questions that the below document could be used to answer:\n\n{doc}")
| ChatOpenAI(max_retries=0, model="gpt-4").bind(functions=functions, function_call={"name": "hypothetical_questions"})
| JsonKeyOutputFunctionsParser(key_name="questions")
)
hypothetical_questions = chain.batch(docs, {"max_concurrency": 5})
question_docs = []
for i, question_list in enumerate(hypothetical_questions):
question_docs.extend([Document(page_content=s,metadata={id_key: doc_ids[i]}) for s in question_list])
return question_docs
def get_docs(func_num):
if func_num==1:
return func1()
elif func_num==2:
return func2()
elif func_num==3:
return func3()
else:
return []
# 检索过程的代码
loaders = [
TextLoader('../../paul_graham_essay.txt'),
TextLoader('../../state_of_the_union.txt'),
]
docs = []
for l in loaders:
docs.extend(l.load())
text_splitter = RecursiveCharacterTextSplitter(chunk_size=10000)
docs = text_splitter.split_documents(docs)
# The vectorstore to use to index the child chunks
vectorstore = Chroma(
collection_name="full_documents",
embedding_function=OpenAIEmbeddings()
)
# The storage layer for the parent documents
store = InMemoryStore()
id_key = "doc_id"
# The retriever (empty to start)
retriever = MultiVectorRetriever(
vectorstore=vectorstore,
docstore=store,
id_key=id_key,
)
doc_ids = [str(uuid.uuid4()) for _ in docs]
# 根据不同方法类型,选择不同策略
func_num =1
candidate_docs = get_docs(func_num)
retriever.vectorstore.add_documents(candidate_docs)
retriever.docstore.mset(list(zip(doc_ids, docs)))
# search
retriever.vectorstore.similarity_search("justice breyer")[0]
那么,我们该如何学习大模型?
作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。
一、大模型全套的学习路线
学习大型人工智能模型,如GPT-3、BERT或任何其他先进的神经网络模型,需要系统的方法和持续的努力。既然要系统的学习大模型,那么学习路线是必不可少的,下面的这份路线能帮助你快速梳理知识,形成自己的体系。
L1级别:AI大模型时代的华丽登场
L2级别:AI大模型API应用开发工程
L3级别:大模型应用架构进阶实践
L4级别:大模型微调与私有化部署
一般掌握到第四个级别,市场上大多数岗位都是可以胜任,但要还不是天花板,天花板级别要求更加严格,对于算法和实战是非常苛刻的。建议普通人掌握到L4级别即可。
以上的AI大模型学习路线,不知道为什么发出来就有点糊,高清版可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费
】
二、640套AI大模型报告合集
这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。
三、大模型经典PDF籍
随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。
四、AI大模型商业化落地方案
作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量。