LCEL-LangChain RAG顺序链连接报错:expected string or buffer
问题:LCEL构建RAG顺序链时触发
expected string or buffer错误 - 使用LCEL-LangChain-Python构建RAG顺序链,单独运行各链功能正常,但连接成整体链后触发
expected string or buffer错误 - 已确认所有相关变量为str类型,问题仍未解决
原始代码
from source.main.create_db import vectordb from langchain.llms import OpenAI from langchain import prompts from langchain.prompts import PromptTemplate from langchain_core.prompts import ChatPromptTemplate from langchain_openai import ChatOpenAI from langchain import memory from dotenv import load_dotenv import os as os from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate from langchain_core.runnables import RunnableParallel, RunnablePassthrough from langchain_anthropic import ChatAnthropic from langchain_core.documents import Document load_dotenv() key = os.getenv('OPENAI_API_KEY') llm = OpenAI() retriever = vectordb.as_retriever() template = ''' ou are an assistant specialized in Brazilian public exams, mainly focused on tests in the field of law, and must answer the questions below {question} ''' prompt= ChatPromptTemplate.from_template(template) output_parser = StrOutputParser() model = llm chain1 = prompt | model | output_parser template2 = ''' Correct and enhance the {answer} using your new information from the {context} and provide more references and support for the newly crafted response." ''' prompt2 = ChatPromptTemplate.from_template(template2) setup_and_retrieval = RunnableParallel( {'context':retriever , "answer":RunnablePassthrough()} ) chain2 = ({'answer': chain1} | setup_and_retrieval | prompt2 | model | StrOutputParser() ) a = chain2.invoke('tell me one law') print(a)
报错信息
a = chain2.invoke('tell me one law') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/erickrochaleaodasilva/projeto_de_lei/maquina/lib/python3.11/site-packages/langchain_core/runnables/base.py", line 2499, in invoke input = step.invoke( ^^^^^^^^^^^^ File "/Users/erickrochaleaodasilva/projeto_de_lei/maquina/lib/python3.11/site-packages/langchain_core/runnables/base.py", line 3144, in invoke output = {key: future.result() for key, future in zip(steps, futures)} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/erickrochaleaodasilva/projeto_de_lei/maquina/lib/python3.11/site-packages/langchain_core/runnables/base.py", line 3144, in <dictcomp> output = {key: future.result() for key, future in zip(steps, futures)} ^^^^^^^^^^^^^^^ File "/opt/anaconda3/lib/python3.11/concurrent/futures/_base.py", line 449, in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ File "/opt/anaconda3/lib/python3.11/concurrent/futures/_base.py", line 401, in __get_result raise self._exception File "/opt/anaconda3/lib/python3.11/concurrent/futures/thread.py", line 58, in run result = self.fn(*self.args, **self.kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/erickrochaleaodasilva/projeto_de_lei/maquina/lib/python3.11/site-packages/langchain_core/retrievers.py", line 141, in invoke return self.get_relevant_documents( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/erickrochaleaodasilva/projeto_de_lei/maquina/lib/python3.11/site-packages/langchain_core/retrievers.py", line 245, in get_relevant_documents raise e File "/Users/erickrochaleaodasilva/projeto_de_lei/maquina/lib/python3.11/site-packages/langchain_core/retrievers.py", line 238, in get_relevant_documents result = self._get_relevant_documents( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/erickrochaleaodasilva/projeto_de_lei/maquina/lib/python3.11/site-packages/langchain_core/vectorstores.py", line 696, in _get_relevant_documents docs = self.vectorstore.similarity_search(query, **self.search_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/erickrochaleaodasilva/projeto_de_lei/maquina/lib/python3.11/site-packages/langchain_community/vectorstores/chroma.py", line 348, in similarity_search docs_and_scores = self.similarity_search_with_score( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/erickrochaleaodasilva/projeto_de_lei/maquina/lib/python3.11/site-packages/langchain_community/vectorstores/chroma.py", line 437, in similarity_search_with_score query_embedding = self._embedding_function.embed_query(query) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/erickrochaleaodasilva/projeto_de_lei/maquina/lib/python3.11/site-packages/langchain_openai/embeddings/base.py", line 546, in embed_query return self.embed_documents([text])[0] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/erickrochaleaodasilva/projeto_de_lei/maquina/lib/python3.11/site-packages/langchain_openai/embeddings/base.py", line 517, in embed_documents return self._get_len_safe_embeddings(texts, engine=engine) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/erickrochaleaodasilva/projeto_de_lei/maquina/lib/python3.11/site-packages/langchain_openai/embeddings/base.py", line 310, in _get_len_safe_embeddings token = encoding.encode( ^^^^^^^^^^^^^^^^ File "/Users/erickrochaleaodasilva/projeto_de_lei/maquina/lib/python3.11/site-packages/tiktoken/core.py", line 116, in encode if match := _special_token_regex(disallowed_special).search(text): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TypeError: expected string or buffer
原因分析
从错误栈可以定位到:检索器(retriever)接收的输入不是字符串。你的setup_and_retrieval是RunnableParallel,其中context绑定了retriever,而RunnableParallel会把整个输入字典传给每个分支。当chain2以{'answer': chain1}作为输入时,retriever拿到的不是原始查询字符串,而是这个字典,导致嵌入函数无法处理非字符串输入,触发tiktoken的编码错误。
解决方案
修改后代码
from source.main.create_db import vectordb from langchain.llms import OpenAI from langchain_core.prompts import ChatPromptTemplate from dotenv import load_dotenv import os from langchain_core.output_parsers import StrOutputParser from langchain_core.runnables import RunnableParallel, RunnablePassthrough load_dotenv() key = os.getenv('OPENAI_API_KEY') llm = OpenAI() retriever = vectordb.as_retriever() # 生成初始回答的chain1 template = ''' You are an assistant specialized in Brazilian public exams, mainly focused on tests in the field of law, and must answer the questions below {question} ''' prompt = ChatPromptTemplate.from_template(template) chain1 = prompt | llm | StrOutputParser() # 用上下文优化回答的chain2 template2 = ''' Correct and enhance the {answer} using information from the {context} and provide more references and support for the newly crafted response. ''' prompt2 = ChatPromptTemplate.from_template(template2) # 关键修正:让retriever接收原始question,同时传递chain1的answer setup_and_retrieval = RunnableParallel( context=lambda x: retriever.invoke(x['question']), answer=chain1 ) # 调整chain2结构:传入包含question的字典,确保各分支拿到正确输入 chain2 = setup_and_retrieval | prompt2 | llm | StrOutputParser() # 调用测试 a = chain2.invoke({'question': 'tell me one law'}) print(a)
核心修改点
- 让retriever明确接收原始
question字符串,而非整个输入字典 - 调整chain2的输入格式,传入包含
question的字典,确保chain1和retriever都能拿到对应参数 - 移除未使用的导入,简化代码结构
- 修正第一个模板的拼写错误(
ou→You)
内容的提问来源于stack exchange,提问作者Erick Rocha
相关产品推荐
相关产品推荐

