LangChain+Streamlit中chain.run()报错:多输出键不支持run方法
解决LangChain中RetrievalQAWithSourcesChain调用run()方法的ValueError错误
错误原因
你使用的RetrievalQAWithSourcesChain在设置return_source_documents=True后,会输出三个键:answer、sources、source_documents,但chain.run()方法仅支持链返回单个输出键的场景,因此触发ValueError。
解决方案
将chain.run()替换为chain()或chain.invoke()(LangChain v0.1及以上版本推荐用invoke),这两个方法支持多输出键的调用场景。
核心代码修改
将原代码中:
if prompt: response = chain.run(prompt, return_only_outputs=True) st.write(response)
替换为以下代码(以新版LangChain的invoke方法为例):
if user_prompt: # 传入键为"question"的字典,匹配Prompt中的{question}变量 response = chain.invoke({"question": user_prompt}) # 分别提取并展示各个输出内容 st.subheader("回答:") st.write(response["answer"]) st.subheader("来源:") st.write(response["sources"]) st.subheader("原始文档片段:") for idx, doc in enumerate(response["source_documents"]): st.write(f"### 片段{idx+1}") st.write(f"文档路径:{doc.metadata['source']}") st.write(f"内容:{doc.page_content}")
如果你的LangChain版本较低,也可以用chain()方法:
if user_prompt: response = chain({"question": user_prompt}) # 后续展示逻辑同上
完整修改后的代码
import os import streamlit as st from apikey import apikey from langchain.document_loaders import PyPDFLoader from langchain.document_loaders import DirectoryLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain.embeddings.openai import OpenAIEmbeddings from langchain.vectorstores import Chroma from langchain.chains import RetrievalQAWithSourcesChain from langchain.prompts.chat import ( ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate, ) from langchain.chat_models import ChatOpenAI os.environ['OPENAI_API_KEY'] = apikey st.title('🐔 OpenAI Testing') user_prompt = st.text_input('Put your prompt here') # 修改变量名避免与Prompt实例重名 loader = DirectoryLoader('./',glob='./*.pdf', loader_cls=PyPDFLoader) pages = loader.load_and_split() text_splitter = RecursiveCharacterTextSplitter( chunk_size = 1000, chunk_overlap = 200, length_function = len, ) docs = text_splitter.split_documents(pages) embeddings = OpenAIEmbeddings() docsearch = Chroma.from_documents(docs, embeddings) system_template = """ Use the following pieces of context to answer the users question. If you don't know the answer, just say that "I don't know", don't try to make up an answer. ---------------- {summaries}""" messages = [ SystemMessagePromptTemplate.from_template(system_template), HumanMessagePromptTemplate.from_template("{question}") ] prompt_template = ChatPromptTemplate.from_messages(messages) # 修改变量名避免冲突 chain_type_kwargs = {"prompt": prompt_template} llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0, max_tokens=256) chain = RetrievalQAWithSourcesChain.from_chain_type( llm=llm, chain_type="stuff", retriever=docsearch.as_retriever(search_kwargs={'k':2}), return_source_documents=True, chain_type_kwargs=chain_type_kwargs ) if user_prompt: response = chain.invoke({"question": user_prompt}) st.subheader("回答:") st.write(response["answer"]) st.subheader("来源:") st.write(response["sources"]) st.subheader("原始文档片段:") for idx, doc in enumerate(response["source_documents"]): st.write(f"### 片段{idx+1}") st.write(f"文档路径:{doc.metadata['source']}") st.write(f"内容:{doc.page_content}")
内容的提问来源于stack exchange,提问作者naranara
相关产品推荐
相关产品推荐

