Skip to content

[Demo] Add an example with streaming #118

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 1 commit into from
Jul 19, 2025
Merged

Conversation

valtzu
Copy link
Contributor

@valtzu valtzu commented Jul 14, 2025

Q A
Bug fix? no
New feature? no
Docs? no
License MIT

I'm proposing to add an example which uses streaming via Turbo Streams / SSE since symfony/ux-turbo is already included, yet no demo app is using streaming.

This demo does not use a custom Stimulus controller at all, but solely relies on vendor-provided live & turbo_stream controllers, making it ideal for those afraid of JS :)

sequenceDiagram
    participant frontend
    participant backend
    participant platform

    frontend->>backend: Live action: submit with message
    activate backend
    backend-->>backend: Store the message<br>but do nothing else
    backend-->>frontend: Response with placeholder message element + <turbo-stream-source id="stream" src="/stream/assistant-reply">
    deactivate backend

    frontend->>backend: turbo_stream_controller.js starts consuming /stream/assistant-reply as SSE source
    activate backend
    backend->>platform: Make platform call with stream: true
    activate platform
    platform-->>backend: first chunk received
    Note over backend,frontend: Clear out "Thinking..." after receiving the first chunk
    backend-->>frontend: data: <turbo-stream action="update" target="placeholder"></turbo-stream>
    backend-->>frontend: data: <turbo-stream action="append" target="placeholder">{{ chunk }}</turbo-stream>
    loop until end of stream
        platform-->>backend: nth chunk received
        backend-->>frontend: data: <turbo-stream action="append" target="placeholder">{{ chunk }}</turbo-stream>
    end
    deactivate platform
    backend-->>frontend: data: <turbo-stream action="remove" target="stream"></turbo-stream>
    frontend-->>backend: turbo_stream_controller.js closes the stream since the <turbo-stream-source> was removed
    deactivate backend
Loading

A couple of observations made while doing this:

  1. Symfony\AI\Agent\Chat is not compatible at all with async/streaming flow.
  2. As I recall, Message IDs were designed/added "for the frontend". If that's still true, then it'd nice if you could pass the message id from the outside, because it could be needed in the frontend to render the placeholder message ("thinking...") which happens before we have an instance of AssistantMessage. Or alternatively, AssistantMessage would need to be non-readonly (or have withContent) so that the message object could be created earlier and appended with content later. At the end, I didn't end up needing the IDs here since they didn't solve the "duplicate messages" (one from turbo, another from live component) problem I had at some point.

@valtzu valtzu requested review from chr-hertel and Nyholm as code owners July 14, 2025 16:16
@OskarStark
Copy link
Contributor

INstead of an image, could you paste the mermaid code for the diagram to the PR header?

@OskarStark OskarStark added the Demo Issues & PRs about the demo application label Jul 14, 2025
@chr-hertel
Copy link
Contributor

This looks great - even tho I'm not sure I get it all - but will give it a try 👍 Thanks already!

Copy link
Contributor

@chr-hertel chr-hertel left a comment

Choose a reason for hiding this comment

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

Works great - thanks a lot! :)
Was thinking if we'd just use that for all examples instead of typed.js and being an extra demo - what do you think?

If extra demo, we'd need to update the top menu please as well, and the image in the readme:
image

</div>
<div class="card-body">
<h5 class="card-title">Turbo Stream Bot</h5>
<p class="card-text">Simple demonstration of text streaming capabilities.</p>
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
<p class="card-text">Simple demonstration of text streaming capabilities.</p>
<p class="card-text">Simple demonstration of text streaming capabilities based on Turbo and SSE.</p>

<div class="col-md-4">
<div class="card stream bg-body shadow-sm">
<div class="card-img-top py-2">
{{ ux_icon('tabler:activity', { height: '150px', width: '150px' }) }}
Copy link
Contributor

Choose a reason for hiding this comment

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

let's use the same icon on both pages:

Suggested change
{{ ux_icon('tabler:activity', { height: '150px', width: '150px' }) }}
{{ ux_icon('mdi:car-turbocharger', { height: '150px', width: '150px' }) }}

@valtzu
Copy link
Contributor Author

valtzu commented Jul 19, 2025

Was thinking if we'd just use that for all examples instead of typed.js and being an extra demo - what do you think?

I did consider that, but not sure if it's a good idea since the LLM calls don't show up in the profiler when using streaming. Maybe you know if there's something to do about that?

@chr-hertel
Copy link
Contributor

LLM calls don't show up in the profiler when using streaming

oh, wasn't aware, but true, i think having that profiler insights is important for the demo - let's keep it as a separate one - good call 👍

@valtzu
Copy link
Contributor Author

valtzu commented Jul 19, 2025

Did the suggested changes

Created an issue for the profiler bug and I have an idea for the fix too, if it'll work, then maybe we could use streaming for all demos instead of this separate one

Copy link
Contributor

@chr-hertel chr-hertel left a comment

Choose a reason for hiding this comment

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

Great work again, thanks!

@chr-hertel chr-hertel merged commit 24797e3 into symfony:main Jul 19, 2025
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Demo Issues & PRs about the demo application
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants