mirror of
https://github.com/james-m-jordan/openai-cookbook.git
synced 2025-05-09 19:32:38 +00:00
125 lines
4.0 KiB
Plaintext
125 lines
4.0 KiB
Plaintext
|
|
For the streaming case, we create an EventHandler class to handle events in the response stream and submit all tool outputs at once with the “submit tool outputs stream” helper in the Python and Node SDKs.
|
|
|
|
<CodeSample
|
|
defaultLanguage="python"
|
|
code={{
|
|
python: `
|
|
from typing_extensions import override
|
|
from openai import AssistantEventHandler
|
|
|
|
class EventHandler(AssistantEventHandler):
|
|
@override
|
|
def on_event(self, event):
|
|
# Retrieve events that are denoted with 'requires_action'
|
|
# since these will have our tool_calls
|
|
if event.event == 'thread.run.requires_action':
|
|
run_id = event.data.id # Retrieve the run ID from the event data
|
|
self.handle_requires_action(event.data, run_id)
|
|
|
|
def handle_requires_action(self, data, run_id):
|
|
tool_outputs = []
|
|
|
|
for tool in data.required_action.submit_tool_outputs.tool_calls:
|
|
if tool.function.name == "get_current_temperature":
|
|
tool_outputs.append({"tool_call_id": tool.id, "output": "57"})
|
|
elif tool.function.name == "get_rain_probability":
|
|
tool_outputs.append({"tool_call_id": tool.id, "output": "0.06"})
|
|
|
|
# Submit all tool_outputs at the same time
|
|
self.submit_tool_outputs(tool_outputs, run_id)
|
|
|
|
def submit_tool_outputs(self, tool_outputs, run_id):
|
|
# Use the submit_tool_outputs_stream helper
|
|
with client.beta.threads.runs.submit_tool_outputs_stream(
|
|
thread_id=self.current_run.thread_id,
|
|
run_id=self.current_run.id,
|
|
tool_outputs=tool_outputs,
|
|
event_handler=EventHandler(),
|
|
) as stream:
|
|
for text in stream.text_deltas:
|
|
print(text, end="", flush=True)
|
|
print()
|
|
|
|
|
|
with client.beta.threads.runs.stream(
|
|
thread_id=thread.id,
|
|
assistant_id=assistant.id,
|
|
event_handler=EventHandler()
|
|
) as stream:
|
|
stream.until_done()
|
|
`.trim(),
|
|
"node.js": `
|
|
class EventHandler extends EventEmitter {
|
|
constructor(client) {
|
|
super();
|
|
this.client = client;
|
|
}\n
|
|
async onEvent(event) {
|
|
try {
|
|
console.log(event);
|
|
// Retrieve events that are denoted with 'requires_action'
|
|
// since these will have our tool_calls
|
|
if (event.event === "thread.run.requires_action") {
|
|
await this.handleRequiresAction(
|
|
event.data,
|
|
event.data.id,
|
|
event.data.thread_id,
|
|
);
|
|
}
|
|
} catch (error) {
|
|
console.error("Error handling event:", error);
|
|
}
|
|
}\n
|
|
async handleRequiresAction(data, runId, threadId) {
|
|
try {
|
|
const toolOutputs =
|
|
data.required_action.submit_tool_outputs.tool_calls.map((toolCall) => {
|
|
if (toolCall.function.name === "getCurrentTemperature") {
|
|
return {
|
|
tool_call_id: toolCall.id,
|
|
output: "57",
|
|
};
|
|
} else if (toolCall.function.name === "getRainProbability") {
|
|
return {
|
|
tool_call_id: toolCall.id,
|
|
output: "0.06",
|
|
};
|
|
}
|
|
});
|
|
// Submit all the tool outputs at the same time
|
|
await this.submitToolOutputs(toolOutputs, runId, threadId);
|
|
} catch (error) {
|
|
console.error("Error processing required action:", error);
|
|
}
|
|
}\n
|
|
async submitToolOutputs(toolOutputs, runId, threadId) {
|
|
try {
|
|
// Use the submitToolOutputsStream helper
|
|
const stream = this.client.beta.threads.runs.submitToolOutputsStream(
|
|
threadId,
|
|
runId,
|
|
{ tool_outputs: toolOutputs },
|
|
);
|
|
for await (const event of stream) {
|
|
this.emit("event", event);
|
|
}
|
|
} catch (error) {
|
|
console.error("Error submitting tool outputs:", error);
|
|
}
|
|
}
|
|
}\n
|
|
const eventHandler = new EventHandler(client);
|
|
eventHandler.on("event", eventHandler.onEvent.bind(eventHandler));\n
|
|
const stream = await client.beta.threads.runs.stream(
|
|
threadId,
|
|
{ assistant_id: assistantId },
|
|
eventHandler,
|
|
);\n
|
|
for await (const event of stream) {
|
|
eventHandler.emit("event", event);
|
|
}
|
|
`.trim(),
|
|
}}
|
|
/>
|