You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 22:53:20