使用LangChain |运算符组合ChatOpenAI与ChatPromptTemplate时抛出ValueError,但LLMChain可正常运行的问题排查
这个问题的核心原因其实非常直观——你完全搞反了链组件的执行顺序!
为什么LLMChain能工作,而|运算符的链会报错?
LLMChain是LangChain的高阶封装,它内部已经帮你处理了「输入→Prompt模板→LLM→解析器」的执行逻辑,你只需要把各个组件传进去,它会自动按正确顺序流转数据。
但|运算符是基于LangChain的Runnable体系,它是严格按照从左到右的顺序执行,每个组件的输出必须能匹配下一个组件的输入类型。你的代码里写了:
conversation_chain = llm | chat_prompt | output_parser
这就意味着你先把用户输入的字典({"input_user_message": ..., "history_messages": ...})直接传给了ChatOpenAI实例,但ChatOpenAI根本不能直接处理字典类型的输入——它需要的是PromptValue、字符串或者BaseMessages列表,这就是你看到ValueError: Invalid input type <class 'dict'>的直接原因。
正确的链顺序应该是什么样的?
正确的流转逻辑是:
- 把包含变量的字典传给
ChatPromptTemplate,它会把变量渲染成符合Chat模型要求的消息格式(ChatPromptValue) - 把渲染好的消息传给
ChatOpenAI,得到模型返回的BaseMessage - 把
BaseMessage传给StrOutputParser,转成字符串输出
所以正确的链写法应该是:
conversation_chain = chat_prompt | llm | output_parser
修正后的完整代码片段
把你原代码里的conversation_chain行替换成上面的写法即可,其他部分(比如消息修剪、会话历史)都不需要改动,完整的函数修正后如下:
def chatbot(input_user_message): # creating a prompt template chat_prompt = ChatPromptTemplate.from_messages( [ ("system", "You are a helpful AI assistant."), MessagesPlaceholder(variable_name="history_messages"), ("human", "{input_user_message}"), ] ) # initializing OpenAI Chat model llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0.7) trimmer = trim_messages( max_tokens=100, strategy="last", token_counter=llm, include_system=True, start_on="human", ) def get_session_history(session_id): if session_id not in st.session_state.store: st.session_state.store[session_id] = ChatMessageHistory() else: st.session_state.store[session_id].messages = trimmer.invoke(st.session_state.store[session_id].messages) return st.session_state.store[session_id] # Initializing the output parser output_parser = StrOutputParser() # 👇 修正后的链顺序 conversation_chain = chat_prompt | llm | output_parser model_with_memory = RunnableWithMessageHistory( conversation_chain, get_session_history, input_messages_key="input_user_message", history_messages_key="history_messages", ) session_id = "1234" response = model_with_memory.invoke( {"input_user_message": input_user_message}, {"configurable": {"session_id": session_id}}, ) print(response) return response
(小细节:原LLMChain返回的是包含text字段的字典,而Runnable链用StrOutputParser后会直接返回字符串,所以最后不需要再取response["text"]了)
额外的注意点
在使用LangChain的Runnable体系(|运算符)时,一定要注意每个组件的输入输出类型匹配:
ChatPromptTemplate:输入是包含变量的字典,输出是ChatPromptValue(可被ChatLLM直接处理)ChatOpenAI:输入是PromptValue、BaseMessages列表或字符串,输出是BaseMessageStrOutputParser:输入是BaseMessage,输出是字符串
只要保证每个环节的输出能被下一个环节接受,链就能正常运行啦。
备注:内容来源于stack exchange,提问作者taher

