TypeError when chaining Runnables in LangChain: Expected a Runnable, callable or dict
Asked Answered
R

8

11

I'm working with LangChain to create a retrieval-based QA system. However, when I attempt to chain Runnables, I encounter a TypeError that I'm unable to resolve. The error occurs when I try to use the | (pipe) operator to chain a RunnablePassthrough with a custom prompt and a ChatOpenAI instance.

Here is the error message I'm receiving:

TypeError: Expected a Runnable, callable or dict. Instead got an unsupported type: <class 'str'>

I've pinpointed the error to this part of the code:

rag_chain = ( {"context": context, "question": RunnablePassthrough()} | rag_custom_prompt | llm )

I expect the RunnablePassthrough() to pass the context and question to the next step in the chain, but it seems to fail during the coercion to a Runnable.

The following is pretty much my entire code:

## Convert the pdf into txt
def pdf_to_txt(inst_manuals):

    txt = ""
    for manual in inst_manuals:
        reader = PdfReader(inst_manuals)
        for page in reader.pages:
            txt += page.extract_text()

    return txt

## Convert txt into chunks 
def chunkify_txt(txt):

    txt_splitter = CharacterTextSplitter(
        separator= "\n",
        chunk_size= 1000,
        chunk_overlap= 200,
        length_function= len
    )

    chunks = txt_splitter.split_text(txt)

    return chunks

## Obtain the vector store
def get_vector(chunks):
    embeddings = OpenAIEmbeddings()

    vectorstore = FAISS.from_texts(texts= chunks, embedding = embeddings)

    return vectorstore

## Retrieve useful info similar to user query
def retrieve(vectorstore, question):
    logging.basicConfig()
    logging.getLogger("langchain.retrievers.multi_query").setLevel(logging.INFO)

    retriever_from_llm = MultiQueryRetriever.from_llm(
        retriever=vectorstore.as_retriever(), llm=ChatOpenAI(temperature=0)
    )
    unique_docs = retriever_from_llm.get_relevant_documents(query=question)
    
    print(f"Number of unique documents retrieved: {len(unique_docs)}")
    
    return unique_docs
    

## Generate response for user query

def gen_resp(retriever, question):
    llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)
    template = """... [custom prompt template] ..."""
    rag_custom_prompt = PromptTemplate.from_template(template)

    context = "\n".join(doc.page_content for doc in retriever)

    rag_chain = (
        {"context": context, "question": RunnablePassthrough()} | rag_custom_prompt | llm
    )

    answer = rag_chain.invoke(question)

    return answer

Has anyone encountered this before? Any suggestions on how to properly chain these Runnables or what I might be doing wrong?

I have attempted the following:

Using different retrievers (details of which could be provided upon request). I've checked the LangChain documentation for proper usage of Runnables and chaining operations. I've tried interchanging the context and question keys in the rag_chain dictionary to see if the order was the issue.

Ritch answered 9/11, 2023 at 10:29 Comment(0)
N
9

The issue is context is of type str. Pass in a lambda function instead:

  rag_chain = (
    {"context": lambda x: context, "question": RunnablePassthrough()} | rag_custom_prompt | llm
)

This is what fixed it for me

Nimwegen answered 10/1 at 14:40 Comment(2)
I do not understand how!!! but this actually fixed my issue as well. thanksReceipt
Works - recommended approach for langchain from what I can tell.Intyre
D
0

Use llm from langchain.llms library for your chain instead

from langchain.llms import OpenAI

llm = OpenAI(model_name="gpt-3.5-turbo")
Dollar answered 29/11, 2023 at 4:29 Comment(0)
C
0

I was getting a similar error message:

TypeError: Expected a Runnable, callable or dict.Instead got an unsupported type: <class 'langchain_core.runnables.passthrough.RunnablePassthrough'>

It was resolved when I upgraded to langchain==0.0.351. My OpenAI version is 0.28.1.

Crystallize answered 28/12, 2023 at 0:34 Comment(0)
A
0

I resolved this issue by upgrading my Langchain version.

pip install -U langchain

I hope this helps!

Accusal answered 4/1 at 10:54 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Waki
T
0

Have the same issue. Answers suggest Chroma.from_documents().What if you want to load from a disk such as db = Chroma(persist_directory="./chroma_db", embedding_function=embedding_function).

Name: openai
Version: 1.6.1
Summary: The official Python library for the openai API



Name: langchain
Version: 0.0.354
Summary: Building applications with LLMs through composability
Thompson answered 4/1 at 15:42 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Waki
A
0

I've ran into this issue, and interestingly, changing the import for Runnable from

from langchain_core.runnables import RunnablePassthrough

to

from langchain.schema.runnable import RunnablePassthrough

fixed the issue. There seem to be some discrepencies between the two.

Attend answered 5/2 at 14:20 Comment(0)
R
-1

If you're working with langchain and trying to implement RAG (Retrieval-Augmented Generation), here's how I solved an issue with creating a retriever within the get_vector function.

The key is to initialize a retriever that uses the FAISS vector store from the provided documents. Here’s the function that correctly sets up the retriever:

from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS
from langchain.llms import ChatOpenAI
from langchain.prompts import PromptTemplate, 
RunnablePassthrough

def get_vector(chunks):
  embeddings = OpenAIEmbeddings()
  vectorstore = 
  FAISS.from_documents(documents=chunks, embedding=embeddings)
  retriever = vectorstore.as_retriever()
return retriever

Next, when generating a response, you don't need to retrieve the documents explicitly. Instead, pass the retriever to the gen_resp function. The RAG logic within this function will handle the similarity search against your documents:

def gen_resp(retriever, question):
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)
template = """
Use the following pieces of context to answer the question at the end.
If you don't know the answer, just say that you do not have the relevant information needed to provide a verified answer, don't try to make up an answer.
When providing an answer, aim for clarity and precision. Position yourself as a knowledgeable authority on the topic, but also be mindful to explain the information in a manner that is accessible and comprehensible to those without a technical background.
Always say "Do you have any more questions pertaining to this instrument?" at the end of the answer.
{context}
Question: {question}
Helpful Answer:"""

rag_custom_prompt = PromptTemplate.from_template(template)

# Set up the RAG chain
rag_chain = (
    {"context": retriever, "question": RunnablePassthrough()} | 
    rag_custom_prompt | 
    llm
)

# Invoke the RAG chain with the question
answer = rag_chain.invoke(question)

return answer

This approach uses the power of the langchain RAG to find the most relevant context and generate a response based on that context. I hope this helps others who are learning and experimenting with langchain RAG functionality.

Ritch answered 10/11, 2023 at 3:50 Comment(0)
H
-1

I'm pretty sure invoke() expects a dictionary as it's only parameter. Thus if you try

rag_chain.invoke(
    {"question": "Why does LangChain sometimes seem to do things the opposite of what you would expect?"}
)

or in your case:

rag_chain.invoke({"question": question})

it should work. HTH

Homeopathist answered 6/12, 2023 at 17:22 Comment(2)
The error message is not from the invoke method, it is occurring when defining rag_chain.Crystallize
"it seems to fail during the coercion to a Runnable" I'm not really sure what is meant by that but it seems unlikely that variable assignment would cause a type error.Homeopathist

© 2022 - 2024 — McMap. All rights reserved.