这示例它实现了一个基于LangGraph的系统,用于处理文档检索和生成答案的过程。
! pip install langchain_community tiktoken langchain-openai langchainhub chromadb langchain langgraph tavily-python
CRAG
Corrective-RAG 是一篇最新的论文,介绍了一种有趣的主动 RAG 方法。
该框架根据问题对检索到的文档进行评分:
-
正确的文档 -
- 如果至少有一个文档超过了相关性的阈值,则继续生成。
- 在生成之前,它会进行知识细化。
- 这会将文档分成“知识条带”。
- 它对每个条带进行评分,并过滤掉无关的条带。
-
含糊或错误的文档 -
- 如果所有文档都低于相关性阈值或评分器不确定,则框架会寻找额外的数据源。
- 它会使用网络搜索来补充检索。
- 论文中的图表还表明,这里使用了查询重写。
论文链接:https://arxiv.org/pdf/2401.15884.pdf
让我们使用 LangGraph 从头开始实现这一点。
我们可以做一些简化:
- 作为初步尝试,让我们跳过知识细化阶段。如果需要,可以将其添加回节点中。
- 如果任何文档不相关,我们选择使用网络搜索来补充检索。
- 我们将使用 Tavily Search 进行网络搜索。
- 我们将使用查询重写来优化网络搜索查询。
设置 TAVILY_API_KEY
。
检索器
让我们索引3篇博客文章。
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import WebBaseLoader
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
urls = [
"https://lilianweng.github.io/posts/2023-06-23-agent/",
"https://lilianweng.github.io/posts/2023-03-15-prompt-engineering/",
"https://lilianweng.github.io/posts/2023-10-25-adv-attack-llm/",
]
docs = [WebBaseLoader(url).load() for url in urls]
docs_list = [item for sublist in docs for item in sublist]
text_splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(
chunk_size=250, chunk_overlap=0
)
doc_splits = text_splitter.split_documents(docs_list)
# Add to vectorDB
vectorstore = Chroma.from_documents(
documents=doc_splits,
collection_name="rag-chroma",
embedding=OpenAIEmbeddings(),
)
retriever = vectorstore.as_retriever()
状态
我们将定义一个图。
我们的状态将是 dict 。
我们可以从任何图形节点 state[‘keys’] 访问它。
from typing import Dict, TypedDict
from langchain_core.messages import BaseMessage
class GraphState(TypedDict):
"""
Represents the state of an agent in the conversation.
Attributes:
keys: A dictionary where each key is a string and the value is expected to be a list or another structure
that supports addition with `operator.add`. This could be used, for instance, to accumulate messages
or other pieces of data throughout the graph.
"""
keys: Dict[str, any]
节点和边
每个 node 将简单地修改 state 。
每个 edge 将选择接下来调用哪个 node 。
它将遵循上面显示的图表。
import json
import operator
from typing import Annotated, Sequence, TypedDict
# 导入langchain相关模块
from langchain import hub
from langchain.output_parsers import PydanticOutputParser
from langchain.output_parsers.openai_tools import PydanticToolsParser
from langchain.prompts import PromptTemplate
from langchain.schema import Document
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_community.vectorstores import Chroma
from langchain_core.messages import BaseMessage, FunctionMessage
from langchain_core.output_parsers