Most samples of using LangChain's Expression Language (LCEL) look like this:
chain = setup_and_retrieval | prompt | model | output_parser
How can I access the source_documents in a RAG application when using this expression language?
This works well for me:
rag_chain = (
RunnablePassthrough.assign(source_documents=condense_question | retriever)
| RunnablePassthrough.assign(context=lambda inputs: format_docs(inputs["source_documents"]) if inputs["source_documents"] else "")
| RunnablePassthrough.assign(prompt=qa_prompt)
| RunnablePassthrough.assign(response=lambda inputs: llm(inputs["prompt"].messages))
)
It's called like this:
response_dict = rag_chain.invoke({"question": question, "chat_history": chat_history})
ai_msg = response_dict["response"]
source_documents = response_dict["source_documents"]
The way that helped me understand how to do it was this:
question and chat_history).RunnablePassthrough.assign, you can ADD stuff to that dictionary and then pass that on to the next step.RunnablePassthrough.assign always RETURNS a dictionary.This is what happens in my code example:
RunnablePassthrough.assign to add a new source_documents key to the dictionary. Its value is the result of calling the condense_question function (defined elsewhere) that builds and returns a condenser chain. Its condensed result is passed into our retriever (also defined elsewhere).RunnablePassthrough.assign to add a new context key to the dictionary. Its value is the result of calling a format_docs method (defined elsewhere) that combines the source_documents into a single context string.RunnablePassthrough.assign to add a new prompt key to the dictionary. Its value is the result of calling qa_prompt, which is defined as qa_prompt = ChatPromptTemplate.from_messages(...).RunnablePassthrough.assign one more time to add a new response key to the dictionary. Its value is the result of actually calling the llm with the messages from our prompt.response key contains the LLM's response as an AIMessage, and the source_documents key contains the source documents.I'm sure this can be done in a more concise way, but this worked for me and I can understand it :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With