Below is an explanation based on the LangChain tutorial and docs for QA chains with message history.
Background
By default the retrieval‐augmented chain (including the history‐aware version) is set up to return a dictionary containing keys like input, chat_history, context, and answer. Even though the SQL message history’s add_message method stores an ID in the in‐memory message object (by side effect), that ID does not automatically “bubble up” when the chain returns its final result.
Customizing the Output
If you’d like the final chain output to incorporate the database message ID (for instance, as part of the answer or as additional metadata), you must introduce a custom transformation step. For example, you could:
- Create a custom output parser (or post-process the result) that takes the output dictionary and, using your SQLMessageHistory instance, retrieves the corresponding stored message (with its assigned ID).
- Alternatively, modify your message history object or chain to “decorate” the output by adding in the stored ID before you return the result.
Example Approach
One way to accomplish this is to wrap your chain call in a function that extracts the stored ID from the corresponding SQLMessageHistory before returning. For instance:
def invoke_with_db_id(chain, input_data, session_id):
# Invoke the chain as usual:
result = chain.invoke(input_data)
# Here, get your history (which in your case contains the SQLMessageHistory)
# and look up the latest message (e.g., the AIMessage) and its database id.
# For this example, assume get_history_message returns the SQLMessageHistory instance.
history_obj = get_history_message(session_id)
# Extract the last message:
if history_obj.messages:
last_msg = history_obj.messages[-1]
# Attach the ID to the dictionary result under a new key
result["message_id"] = last_msg.id
return result
# Usage:
input_data = {"input": "What's Task Decomposition?", "chat_history": []}
final_result = invoke_with_db_id(history_aware_rag_chain, input_data, session_id="<SESSION_ID>")
print(final_result)
In this sketch, the function invoke_with_db_id handles both invoking the chain (which returns a dictionary) and then adds the database message ID from the history instance. This extra step is required because the chain’s design (using the current LangChain components) does not automatically return the original AIMessage objects.
Conclusion
So, while it isn’t possible to automatically change the final output from a dictionary into an AIMessage with the DB id included, you can definitely implement a custom post‐processing step. This way, you’re able to take the recorded ID from the SQLMessageHistory and include it in your chain’s final output.
This approach aligns with the flexibility that LangChain provides when composing chains and handling message histories.