Add support for streaming#255
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## trunk #255 +/- ##
============================================
+ Coverage 88.16% 90.20% +2.04%
- Complexity 1217 1448 +231
============================================
Files 61 69 +8
Lines 3945 4493 +548
============================================
+ Hits 3478 4053 +575
+ Misses 467 440 -27
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…t ends with newline
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
|
Will add docs once the API is reviewed and approved. |
| if (!$model instanceof StreamingTextGenerationModelInterface) { | ||
| throw new RuntimeException( | ||
| sprintf( | ||
| 'Model "%s" does not support streaming text generation.', | ||
| $model->metadata()->getId() | ||
| ) | ||
| ); | ||
| } |
There was a problem hiding this comment.
If a model doesn't implement this interface, it will fail even if the model supports text generation. It fails because streaming is gated behind this opt-in interface that no provider actually implements. We can't discover our way around it either, since streaming isn't a CapabilityEnum, so discovery can't tell which models stream and may still pick one that doesn't.
The clean solution is to remove StreamingTextGenerationModelInterface and rather add streamGenerateTextResult(array $prompt): StreamedGenerativeAiResult to TextGenerationModelInterface. Streaming is a networking primitive, not a real model capability, so every text model can stream: natively where the provider's API supports it, or by emulating it (one generateTextResult() call yielded as a single chunk) where it doesn't. Adding a method to the interface sounds like a breaking change, but if we put the emulation default in the shared base (AbstractApiBasedModel) that every provider already extends, they all inherit it and nothing breaks.
Another way is to add a new capability and wire discovery to find a model with it, but that isn't standard given streaming isn't a model-level capability, it's a networking primitive, not something a model generates. We'd also still need a method on an interface plus every provider opting in, so it's more machinery for something that isn't really model-level.
|
Created a tiny server to see streaming in action - https://gist.github.com/thelovekesh/a05a99570989672ad4b493b81a4b6dc3 |
| * @return StreamedGenerativeAiResult The streamed result. | ||
| * @throws InvalidArgumentException If the prompt or model validation fails. | ||
| * @throws RuntimeException If the model does not support streaming text generation. |
There was a problem hiding this comment.
Didn't do a real review yet, just a quick note: can you make sure the PHPDoc types use FQCN? E.g.
| * @return StreamedGenerativeAiResult The streamed result. | |
| * @throws InvalidArgumentException If the prompt or model validation fails. | |
| * @throws RuntimeException If the model does not support streaming text generation. | |
| * @return \WordPress\AiClient\Results\StreamedGenerativeAiResult The streamed result. | |
| * @throws \InvalidArgumentException If the prompt or model validation fails. | |
| * @throws \RuntimeException If the model does not support streaming text generation. |
Summary
Fixes #100
This PR introduces the core changes needed for stable streaming support in text generation.
Here is a script to test streaming with text generation. It supports streaming of reasoning, content and tool calls.
stream-text.php
Tasks
RequestandResponse.EventStreamParserInterfaceand SSE Parser.AbstractOpenAiCompatibleTextGenerationModelto use streaming in text generation.