如何借助Langchain获取更详细的问答结果来源信息?
解决Langchain RetrievalQAWithSourcesChain返回详细来源的方案
问题根源
RetrievalQAWithSourcesChain返回的来源信息,本质由**加载文档时存入的元数据(metadata)**决定:LLM仅负责从检索到的文档元数据中提取来源字段,链本身仅做组装工作。默认URL加载器只会把完整URL存入元数据的source字段,因此最终返回的只有完整URL。
具体实现步骤
1. 自定义URL加载逻辑,提取章节标题与锚点
手动解析页面结构,提取每个章节的标题、内容及对应锚点URL,将这些信息存入文档元数据:
from langchain.schema import Document import requests from bs4 import BeautifulSoup def load_url_with_chapters(target_url): response = requests.get(target_url) soup = BeautifulSoup(response.text, 'html.parser') docs = [] # 示例:以页面h2标签为章节标题,需根据目标页面结构调整 for chapter_tag in soup.find_all('h2'): chapter_title = chapter_tag.get_text(strip=True) anchor_id = chapter_tag.get('id') # 拼接带锚点的URL source_url = f"{target_url}#{anchor_id}" if anchor_id else target_url # 提取章节内容(直到下一个h2标签) content_list = [] next_node = chapter_tag.next_sibling while next_node and next_node.name != 'h2': if hasattr(next_node, 'get_text'): content_list.append(next_node.get_text(strip=True)) next_node = next_node.next_sibling chapter_content = '\n'.join(content_list) # 创建带元数据的Document对象 docs.append(Document( page_content=chapter_content, metadata={ 'source': source_url, 'chapter_title': chapter_title } )) return docs # 加载带章节信息的文档 docs = load_url_with_chapters("你的目标URL")
如果页面是动态渲染(如JS加载内容),替换requests为SeleniumURLLoader获取页面源码即可。
2. 构建向量库时保留元数据
将自定义加载的文档存入向量库,元数据会被同步存储:
from langchain.embeddings import OpenAIEmbeddings from langchain.vectorstores import Chroma embeddings = OpenAIEmbeddings() vector_store = Chroma.from_documents(docs, embeddings)
3. 自定义链的提示词,指定来源格式
修改默认提示词,让LLM返回包含章节标题和锚点URL的详细来源:
from langchain.chains import RetrievalQAWithSourcesChain from langchain.prompts import PromptTemplate from langchain.chat_models import ChatOpenAI llm = ChatOpenAI(temperature=0, model_name='gpt-3.5-turbo') # 自定义提示模板,明确要求返回的来源格式 prompt_template = """ 使用以下上下文回答用户问题,不知道答案就直接说不知道,不要编造内容。 回答末尾必须按格式列出来源: Sources: - [章节标题](锚点URL) 上下文: {summaries} 问题: {question} """ PROMPT = PromptTemplate( template=prompt_template, input_variables=["summaries", "question"] ) # 初始化自定义提示词的链 chain = RetrievalQAWithSourcesChain.from_llm( llm=llm, retriever=vector_store.as_retriever(), prompt=PROMPT ) # 执行查询 result = chain({"question": "你的问题内容"}) print(result['answer'])
关键注意事项
- 页面结构解析逻辑需根据目标URL的实际HTML标签调整(比如部分页面用h3或特定class的div作为章节标识)
- 元数据可灵活扩展,如需添加段落位置、作者等信息,只需在加载时存入元数据,并在提示词中对应提取即可
内容的提问来源于stack exchange,提问作者GSouth
相关产品推荐
相关产品推荐

