Skip to content

Working streaming Gradio chatbot outputs #1246

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 21 commits into from
Apr 30, 2025

Conversation

aymeric-roucher
Copy link
Collaborator

@aymeric-roucher aymeric-roucher commented Apr 24, 2025

This finalizes the streaming refactoring: makes step functions generators, and adds some intermediate yield to yield intermediate completions.

Also I've set all examples to stream outputs by default when the underlying Model class allows it. Progressively we should switch wherever we can to stream_ouputs because it's much more user-friendly than waiting until the end of message generation.

yield gr.ChatMessage(role="assistant", content="**Planning step**", metadata={"status": "done"})
yield gr.ChatMessage(role="assistant", content=step_log.plan, metadata={"status": "done"})
yield gr.ChatMessage(
role="assistant", content=get_step_footnote_content(step_log, "Planning step"), metadata={"status": "done"}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Using metadata field to note when a step is done, will help us in the gradio app when receiving a completion delta to differentiate between "previous message is complete: start a new one" or "append this completion delta's text to the previous pending message".

Maybe there's a simpler way thought, WDYT?

Copy link
Member

Choose a reason for hiding this comment

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

Not clear to me how to use this param. However, it seems it requires a "title" key.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Filling the "title" key makes a title show up, which wouldn't look very good in our case.
This title field does not seem mandatory in practice, since the previous implementaiton of gr.ChatMessage in smolagents comes from @yvrjsharma and does not have title fields in every message.

Copy link
Member

Choose a reason for hiding this comment

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

So it appears to be a misalignment in the doc of this param.

<a target="_blank" href="https://github.com/huggingface/smolagents"><b>huggingface/smolagents</b></a>
</div>""")
gr.HTML(
"<br><br><h4><center>Powered by <a target='_blank' href='https://github.com/huggingface/smolagents'><b>smolagents</b></a></center></h4>"
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Making the branding a bit less present, because for now it's too big. Maybe could be removed altogether.

@aymeric-roucher aymeric-roucher marked this pull request as ready for review April 25, 2025 08:11
yield gr.ChatMessage(role="assistant", content="**Planning step**", metadata={"status": "done"})
yield gr.ChatMessage(role="assistant", content=step_log.plan, metadata={"status": "done"})
yield gr.ChatMessage(
role="assistant", content=get_step_footnote_content(step_log, "Planning step"), metadata={"status": "done"}
Copy link
Member

Choose a reason for hiding this comment

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

Not clear to me how to use this param. However, it seems it requires a "title" key.

pass
def step(self, memory_step: ActionStep) -> Generator[Any]:
"""To be implemented in children classes. Should yield either None if the step is not final, or the final answer."""
yield None
Copy link
Member

Choose a reason for hiding this comment

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

I think the conversion of step to generator is a breaking change.

Copy link
Member

@albertvillanova albertvillanova left a comment

Choose a reason for hiding this comment

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

I solved the conflicts with he main branch and aligned the Generator type hint.

Also made a direct change in the PR instead of discussing it: feel free to revert.

@aymeric-roucher
Copy link
Collaborator Author

@yvrjsharma could you take a look at this comment? The way've I've modified the method pull_messages_from_step to detect pending streaming outputs it to put them gr.ChatMessages objects with "status" : "pending" in their metadata: however the metadata typed dict in gradio seems to need a title key and accept no other, is it legit to use status?

@@ -1007,10 +1035,10 @@ def initialize_system_prompt(self) -> str:
)
return system_prompt

def step(self, memory_step: ActionStep) -> None | Any:
def _step(self, memory_step: ActionStep) -> Generator[Any]:
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@albertvillanova here's how I modified the step method.

Copy link
Member

@albertvillanova albertvillanova left a comment

Choose a reason for hiding this comment

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

Thank you!

Just a comment: what about aligning the naming of the streaming versions of run and step? Currently:

  • _run_stream
  • _step

@aymeric-roucher
Copy link
Collaborator Author

@albertvillanova I went for _step_stream and _run_stream.

@aymeric-roucher aymeric-roucher merged commit d02f0cc into main Apr 30, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants