Skip to content

feat: Extend AnswerBuilder for Agent #9406

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
May 22, 2025
Merged

feat: Extend AnswerBuilder for Agent #9406

merged 10 commits into from
May 22, 2025

Conversation

vblagoje
Copy link
Member

Why:

Enhances the AnswerBuilder component to preserve conversation history when processing Agent outputs.

What:

  • Updates AnswerBuilder to store entire conversation history in metadata
  • Adds "all_messages" field to GeneratedAnswer metadata containing all messages
  • Preserves backward compatibility with existing pipelines
  • Updates tests to verify the new functionality

How can it be used:

Connect Agent and AnswerBuilder in a pipeline to maintain conversation context:

from haystack import Pipeline
from haystack.components.builders import AnswerBuilder
from haystack.components.agents import Agent
from haystack.components.generators.chat import OpenAIChatGenerator

# Create components
agent = Agent(chat_generator=OpenAIChatGenerator())
answer_builder = AnswerBuilder()

# Create pipeline
pipeline = Pipeline()
pipeline.add_component("agent", agent)
pipeline.add_component("answer_builder", answer_builder)

# Connect components
pipeline.connect("agent.messages", "answer_builder.replies")

# Run the pipeline
result = pipeline.run(data={"agent": {"messages": [user_message]}})

# Conversation history is preserved in the answer metadata
conversation_history = result["answer_builder"]["answers"][0].meta["all_messages"]

How did you test it:

  • Unit tests verify that conversation history is properly stored in metadata
  • Added helper function to test metadata while ignoring the new field
  • Tests ensure backward compatibility with existing code

@vblagoje vblagoje added the ignore-for-release-notes PRs with this flag won't be included in the release notes. label May 18, 2025
@coveralls
Copy link
Collaborator

coveralls commented May 18, 2025

Pull Request Test Coverage Report for Build 15186489091

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • 81 unchanged lines in 7 files lost coverage.
  • Overall coverage decreased (-0.03%) to 90.423%

Files with Coverage Reduction New Missed Lines %
components/builders/answer_builder.py 1 98.53%
components/rankers/init.py 2 50.0%
components/embedders/openai_text_embedder.py 6 89.09%
components/agents/agent.py 9 91.07%
components/rankers/transformers_similarity.py 9 91.67%
components/embedders/openai_document_embedder.py 22 62.61%
components/tools/tool_invoker.py 32 83.51%
Totals Coverage Status
Change from base Build 15136007493: -0.03%
Covered Lines: 11104
Relevant Lines: 12280

💛 - Coveralls

@vblagoje vblagoje marked this pull request as ready for review May 19, 2025 08:25
@vblagoje vblagoje requested review from a team as code owners May 19, 2025 08:25
@vblagoje vblagoje requested review from dfokina and anakin87 and removed request for a team May 19, 2025 08:25
@vblagoje vblagoje removed the ignore-for-release-notes PRs with this flag won't be included in the release notes. label May 19, 2025
@vblagoje vblagoje requested a review from tstadel May 19, 2025 08:25
@vblagoje
Copy link
Member Author

@tstadel would you please have a look - is this what you had in mind?

@tstadel
Copy link
Member

tstadel commented May 19, 2025

@vblagoje having all messages in meta is already a big win. Do I get this right, that if I just want to get the last message as answer (and have the others in this message's meta), I still have to put an OutputAdapter after AnswerBuilder?
If so would it be possible to add a flag that makes the AnswerBuilder return only the last message?

@vblagoje
Copy link
Member Author

vblagoje commented May 19, 2025

@vblagoje having all messages in meta is already a big win. Do I get this right, that if I just want to get the last message as answer (and have the others in this message's meta), I still have to put an OutputAdapter after AnswerBuilder? If so would it be possible to add a flag that makes the AnswerBuilder return only the last message?

No, no @tstadel we added dedicated last_message output in Agent, see this

@vblagoje
Copy link
Member Author

vblagoje commented May 19, 2025

So in that sense this PR was all about adding all_messages in meta - and slight accommodation of not checking that each messages has text and raising ValueError in that case. That constraint or prerequisite seems a bit drastic in this day and age of tool calling and multimodality so I removed it. I'm hoping that this slight change won't cause any issues to existing usage of AnswerBuilder - and that's what I would ask you to please think about. 🙏 man

@tstadel
Copy link
Member

tstadel commented May 19, 2025

@vblagoje I think that slight change is fine. But how would I get exactly one Answer (using the last message) having the all_messages meta field when using Agent and AnswerBuilder.
Agent just returns the last message as Message object, right?. So I can't use it in this scenario, no?

@vblagoje
Copy link
Member Author

vblagoje commented May 20, 2025

Yeah, I thought I could achieve what you wanted via this minimal change:

  • connect Agent's [last_message] to AB replies and don't bother about tool calls and message history - extracted_reply will get the text of the last message, parse it for reference if somehow documents are provided etc
  • connect Agent's [messages] to AB replies and then extracted_reply will get the text of the last message as it iterates through all messages and you'll also have all_message in metadata in addition

I did it this way cause I think it does what you wanted and doesn't cause, hopefully, too many issues to existing pipelines.

Update: As last_message in Agent will stay of ChatMessage type - we should figure out how to do the same with connecting [messages] only @tstadel.

It seems still ok. Please follow this line of reasoning. In current PR, If we connect Agent's messages output to AB, AB will take the last message from [messages] and assign it to extracted_reply, all_message still being added to the meta as planned. So we seem to be good in that case as well. LMK if I'm overlooking something.

@github-actions github-actions bot added the type:documentation Improvements on the docs label May 20, 2025
@vblagoje
Copy link
Member Author

@tstadel have a look now 🙏

Copy link
Member

@tstadel tstadel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! Thx a lot 🙏

@anakin87
Copy link
Member

@vblagoje do you need a review from me as well?
Please LMK. I don't want to block this work...

@vblagoje
Copy link
Member Author

@anakin87 please do a please focus on 6dd96fd as this unit tests demonstrates nicely what @tstadel asked for.

Another thing that I'd love to ask you is if we perhaps need last_message_only as run parameter. @tstadel didn't ask for it and I wasn't sure if we should add it or not. I was leaning to not because we already have one too many params in run. LMK what you think.

Copy link
Member

@anakin87 anakin87 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left some minor comments.

About last_message_only as run parameter: let's avoid it for the moment, if you agree.

vblagoje and others added 4 commits May 22, 2025 14:13
Co-authored-by: Stefano Fiorucci <stefanofiorucci@gmail.com>
Co-authored-by: Stefano Fiorucci <stefanofiorucci@gmail.com>
Copy link
Member

@anakin87 anakin87 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@vblagoje vblagoje merged commit 167229f into main May 22, 2025
20 checks passed
@vblagoje vblagoje deleted the extend_answer_builder branch May 22, 2025 12:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic:tests type:documentation Improvements on the docs
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Extend AnswerBuilder to convert only last message for agentic pipelines
4 participants