-
Notifications
You must be signed in to change notification settings - Fork 204
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(api): add messages endpoint with streaming helpers (#286)
More information here: https://docs.anthropic.com/claude/reference/messages_post
- Loading branch information
1 parent
0c55c84
commit c464b87
Showing
43 changed files
with
3,291 additions
and
198 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
configured_endpoints: 1 | ||
configured_endpoints: 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import asyncio | ||
|
||
from anthropic import AsyncAnthropic | ||
|
||
client = AsyncAnthropic() | ||
|
||
|
||
async def main() -> None: | ||
async with client.beta.messages.stream( | ||
max_tokens=1024, | ||
messages=[ | ||
{ | ||
"role": "user", | ||
"content": "Say hello there!", | ||
} | ||
], | ||
model="claude-2.1", | ||
) as stream: | ||
async for text in stream.text_stream: | ||
print(text, end="", flush=True) | ||
print() | ||
|
||
# you can still get the accumulated final message outside of | ||
# the context manager, as long as the entire stream was consumed | ||
# inside of the context manager | ||
accumulated = await stream.get_final_message() | ||
print("accumulated message: ", accumulated.model_dump_json(indent=2)) | ||
|
||
|
||
asyncio.run(main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import asyncio | ||
from typing_extensions import override | ||
|
||
from anthropic import AsyncAnthropic | ||
from anthropic.types.beta import MessageStreamEvent | ||
from anthropic.lib.streaming import AsyncMessageStream | ||
|
||
client = AsyncAnthropic() | ||
|
||
|
||
class MyStream(AsyncMessageStream): | ||
@override | ||
async def on_stream_event(self, event: MessageStreamEvent) -> None: | ||
print("on_event fired with:", event) | ||
|
||
|
||
async def main() -> None: | ||
async with client.beta.messages.stream( | ||
max_tokens=1024, | ||
messages=[ | ||
{ | ||
"role": "user", | ||
"content": "Say hello there!", | ||
} | ||
], | ||
model="claude-2.1", | ||
event_handler=MyStream, | ||
) as stream: | ||
accumulated = await stream.get_final_message() | ||
print("accumulated message: ", accumulated.model_dump_json(indent=2)) | ||
|
||
|
||
asyncio.run(main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
# Message Helpers | ||
|
||
## Streaming Responses | ||
|
||
```python | ||
async with client.beta.messages.stream( | ||
max_tokens=1024, | ||
messages=[ | ||
{ | ||
"role": "user", | ||
"content": "Say hello there!", | ||
} | ||
], | ||
model="claude-2.1", | ||
) as stream: | ||
async for text in stream.text_stream: | ||
print(text, end="", flush=True) | ||
print() | ||
``` | ||
|
||
`client.beta.messages.stream()` returns a `MessageStreamManager`, which is a context manager that yields a `MessageStream` which is iterable, emits events and accumulates messages. | ||
|
||
Alternatively, you can use `client.beta.messages.create(..., stream=True)` which returns an | ||
iteratable of the events in the stream and uses less memory (most notably, it does not accumulate a final message | ||
object for you). | ||
|
||
The stream will be cancelled when the context manager exits but you can also close it prematurely by calling `stream.close()`. | ||
|
||
See an example of streaming helpers in action in [`examples/messages_stream.py`](examples/messages_stream.py) and defining custom event handlers in [`examples/messages_stream_handler.py`](examples/messages_stream_handler.py) | ||
|
||
> [!NOTE] | ||
> The synchronous client has the same interface just without `async/await`. | ||
### Lenses | ||
|
||
#### `.text_stream` | ||
|
||
Provides an iterator over just the text deltas in the stream: | ||
|
||
```py | ||
async for text in stream.text_stream: | ||
print(text, end="", flush=True) | ||
print() | ||
``` | ||
|
||
### Events | ||
|
||
#### `await on_stream_event(event: MessageStreamEvent)` | ||
|
||
The event is fired when an event is received from the API. | ||
|
||
#### `await on_message(message: Message)` | ||
|
||
The event is fired when a full Message object has been accumulated. This corresponds to the `message_stop` SSE. | ||
|
||
#### `await on_content_block(content_block: ContentBlock)` | ||
|
||
The event is fired when a full ContentBlock object has been accumulated. This corresponds to the `content_block_stop` SSE. | ||
|
||
#### `await on_text(text: str, snapshot: str)` | ||
|
||
The event is fired when a `text` ContentBlock object is being accumulated. The first argument is the text delta and the second is the current accumulated text, for example: | ||
|
||
```py | ||
on_text('Hello', 'Hello') | ||
on_text(' there', 'Hello there') | ||
on_text('!', 'Hello there!') | ||
``` | ||
|
||
This corresponds to the `content_block_delta` SSE. | ||
|
||
#### `await on_exception(exception: Exception)` | ||
|
||
The event is fired when an exception is encountered while streaming the response. | ||
|
||
#### `await on_timeout()` | ||
|
||
The event is fired when the request times out. | ||
|
||
#### `await on_end()` | ||
|
||
The last event fired in the stream. | ||
|
||
### Methods | ||
|
||
#### `await .close()` | ||
|
||
Aborts the request. | ||
|
||
#### `await .until_done()` | ||
|
||
Blocks until the stream has been read to completion. | ||
|
||
#### `await .get_final_message()` | ||
|
||
Blocks until the stream has been read to completion and returns the accumulated `Message` object. | ||
|
||
#### `await .get_final_text()` | ||
|
||
> [!NOTE] | ||
> Currently the API will only ever return 1 content block | ||
Blocks until the stream has been read to completion and returns all `text` content blocks concatenated together. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.