Skip to content

Commit

Permalink
docs: assistant improvements (#1249)
Browse files Browse the repository at this point in the history
  • Loading branch information
stainless-bot committed Mar 19, 2024
1 parent 3eeb9b3 commit e7a3176
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 16 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,24 @@ we recommend using [python-dotenv](https://pypi.org/project/python-dotenv/)
to add `OPENAI_API_KEY="My API Key"` to your `.env` file
so that your API Key is not stored in source control.

### Streaming Helpers

The SDK also includes helpers to process streams and handle the incoming events.

```python
with client.beta.threads.runs.create_and_stream(
thread_id=thread.id,
assistant_id=assistant.id,
instructions="Please address the user as Jane Doe. The user has a premium account.",
) as stream:
for event in stream:
# Print the text from text delta events
if event.type == "thread.message.delta" and event.data.delta.content:
print(event.data.delta.content[0].text)
```

More information on streaming helpers can be found in the dedicated documentation: [helpers.md](helpers.md)

## Async usage

Simply import `AsyncOpenAI` instead of `OpenAI` and use `await` with each API call:
Expand Down
86 changes: 70 additions & 16 deletions helpers.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,28 @@ You can subscribe to events by creating an event handler class and overloading t

```python
from typing_extensions import override
from openai import AssistantEventHandler
from openai import AssistantEventHandler, OpenAI
from openai.types.beta.threads import Text, TextDelta
from openai.types.beta.threads.runs import ToolCall, ToolCallDelta

client = openai.OpenAI()

# First, we create a EventHandler class to define
# how we want to handle the events in the response stream.

class EventHandler(AssistantEventHandler):
@override
def on_text_created(self, text) -> None:
def on_text_created(self, text: Text) -> None:
print(f"\nassistant > ", end="", flush=True)

@override
def on_text_delta(self, delta, snapshot):
def on_text_delta(self, delta: TextDelta, snapshot: Text):
print(delta.value, end="", flush=True)

def on_tool_call_created(self, tool_call):
def on_tool_call_created(self, tool_call: ToolCall):
print(f"\nassistant > {tool_call.type}\n", flush=True)

def on_tool_call_delta(self, delta, snapshot):
def on_tool_call_delta(self, delta: ToolCallDelta, snapshot: ToolCall):
if delta.type == 'code_interpreter':
if delta.code_interpreter.input:
print(delta.code_interpreter.input, end="", flush=True)
Expand All @@ -47,14 +51,64 @@ class EventHandler(AssistantEventHandler):
# and stream the response.

with client.beta.threads.runs.create_and_stream(
thread_id=thread.id,
assistant_id=assistant.id,
instructions="Please address the user as Jane Doe. The user has a premium account.",
thread_id="thread_id",
assistant_id="assistant_id",
event_handler=EventHandler(),
) as stream:
stream.until_done()
```

#### An example of iterating over events

You can also iterate over all the streamed events.

```python
with client.beta.threads.runs.create_and_stream(
thread_id=thread.id,
assistant_id=assistant.id
) as stream:
for event in stream:
# Print the text from text delta events
if event.type == "thread.message.delta" and event.data.delta.content:
print(event.data.delta.content[0].text)
```

#### An example of iterating over text

You can also iterate over just the text deltas received

```python
with client.beta.threads.runs.create_and_stream(
thread_id=thread.id,
assistant_id=assistant.id
) as stream:
for text in stream.text_deltas:
print(text)
```

### Creating Streams

There are three helper methods for creating streams:

```python
client.beta.threads.runs.create_and_stream()
```

This method can be used to start and stream the response to an existing run with an associated thread
that is already populated with messages.

```python
client.beta.threads.create_and_run_stream()
```

This method can be used to add a message to a thread, start a run and then stream the response.

```python
client.beta.threads.runs.submit_tool_outputs_stream()
```

This method can be used to submit a tool output to a run waiting on the output and start a stream.

### Assistant Events

The assistant API provides events you can subscribe to for the following events.
Expand Down Expand Up @@ -139,22 +193,22 @@ This event is triggered if an exception occurs during streaming.
The assistant streaming object also provides a few methods for convenience:

```python
def current_event()
def current_run()
def current_message_snapshot()
def current_run_step_snapshot()
def current_event() -> AssistantStreamEvent | None
def current_run() -> Run | None
def current_message_snapshot() -> Message | None
def current_run_step_snapshot() -> RunStep | None
```

These methods are provided to allow you to access additional context from within event handlers. In many cases
the handlers should include all the information you need for processing, but if additional context is required it
can be accessed.

Note: There is not always a relevant context in certain situations (these will be undefined in those cases).
Note: There is not always a relevant context in certain situations (these will be `None` in those cases).

```python
def get_final_run(self)
def get_final_run_steps(self)
def get_final_messages(self)
def get_final_run(self) -> Run
def get_final_run_steps(self) -> List[RunStep]
def get_final_messages(self) -> List[Message]
```

These methods are provided for convenience to collect information at the end of a stream. Calling these events
Expand Down

0 comments on commit e7a3176

Please sign in to comment.