Skip to content

Commit 5d1b144

Browse files
authored
custom model providers - async stream (#150)
1 parent 1e87490 commit 5d1b144

File tree

1 file changed

+18
-14
lines changed

1 file changed

+18
-14
lines changed

docs/user-guide/concepts/model-providers/custom_model_provider.md

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,12 @@ The `stream` method accepts three parameters directly:
139139

140140
```python
141141
@override
142-
def stream(
143-
self,
144-
messages: Messages,
145-
tool_specs: Optional[list[ToolSpec]] = None,
142+
async def stream(
143+
self,
144+
messages: Messages,
145+
tool_specs: Optional[list[ToolSpec]] = None,
146146
system_prompt: Optional[str] = None
147-
) -> Iterable[StreamEvent]:
147+
) -> AsyncIterable[StreamEvent]:
148148
"""Stream responses from the Custom model.
149149
150150
Args:
@@ -165,12 +165,12 @@ The `stream` method accepts three parameters directly:
165165
"system_prompt": system_prompt,
166166
**self.config, # Include model configuration
167167
}
168-
168+
169169
logger.debug("request=<%s> | invoking model", request)
170170

171171
# Invoke your model
172172
try:
173-
response = self.client(**request)
173+
response = await self.client(**request)
174174
except OverflowException as e:
175175
raise ContextWindowOverflowException() from e
176176

@@ -185,7 +185,7 @@ The `stream` method accepts three parameters directly:
185185
}
186186

187187
# Process each chunk from your model's response
188-
for chunk in response["stream"]:
188+
async for chunk in response["stream"]:
189189
# Convert your model's event format to Strands Agents StreamEvent
190190
if chunk.get("type") == "text_delta":
191191
yield {
@@ -209,9 +209,9 @@ For more complex implementations, you may want to create helper methods to organ
209209

210210
```python
211211
def _format_request(
212-
self,
213-
messages: Messages,
214-
tool_specs: Optional[list[ToolSpec]] = None,
212+
self,
213+
messages: Messages,
214+
tool_specs: Optional[list[ToolSpec]] = None,
215215
system_prompt: Optional[str] = None
216216
) -> dict[str, Any]:
217217
"""Optional helper method to format requests for your model API."""
@@ -241,6 +241,8 @@ For more complex implementations, you may want to create helper methods to organ
241241
return None
242242
```
243243

244+
> Note, `stream` must be implemented async. If your client does not support async invocation, you may consider wrapping the relevant calls in a thread so as not to block the async event loop. For an example on how to achieve this, you can check out the [BedrockModel](https://github.com/strands-agents/sdk-python/blob/main/src/strands/models/bedrock.py) provider implementation.
245+
244246
### 3. Understanding StreamEvent Types
245247

246248
Your custom model provider needs to convert model's response events to Strands Agents [StreamEvent](../../../api-reference/types.md#strands.types.streaming.StreamEvent) format. The StreamEvent type supports these event types:
@@ -327,7 +329,7 @@ To support structured output in your custom model provider, you need to implemen
327329
T = TypeVar('T', bound=BaseModel)
328330

329331
@override
330-
def structured_output(
332+
async def structured_output(
331333
self, output_model: Type[T], prompt: Messages
332334
) -> Generator[dict[str, Union[T, Any]], None, None]:
333335
"""Get structured output using tool calling."""
@@ -336,10 +338,10 @@ def structured_output(
336338
tool_spec = convert_pydantic_to_tool_spec(output_model)
337339

338340
# Use the stream method with tool specification
339-
response = self.stream(messages=prompt, tool_specs=[tool_spec])
341+
response = await self.stream(messages=prompt, tool_specs=[tool_spec])
340342

341343
# Process streaming response
342-
for event in process_stream(response, prompt):
344+
async for event in process_stream(response, prompt):
343345
yield event # Passed to callback handler configured in Agent instance
344346

345347
stop_reason, messages, _, _ = event["stop"]
@@ -366,6 +368,8 @@ def structured_output(
366368

367369
For detailed structured output usage patterns, see the [Structured Output documentation](../agents/structured-output.md).
368370

371+
> Note, similar to the `stream` method, `structured_output` must be implemented async. If your client does not support async invocation, you may consider wrapping the relevant calls in a thread so as not to block the async event loop. Again, for an example on how to achieve this, you can check out the [BedrockModel](https://github.com/strands-agents/sdk-python/blob/main/src/strands/models/bedrock.py) provider implementation.
372+
369373
### 5. Use Your Custom Model Provider
370374

371375
Once implemented, you can use your custom model provider in your applications for regular agent invocation:

0 commit comments

Comments
 (0)