82 82
83```javascript83```javascript
84const assistant = await client.beta.assistants.create({84const assistant = await client.beta.assistants.create({
85model: "gpt-4o",85 model: "gpt-4o",
86instructions:86 instructions:
87"You are a weather bot. Use the provided functions to answer questions.",87 "You are a weather bot. Use the provided functions to answer questions.",
88tools: [88 tools: [
89{89 {
90type: "function",90 type: "function",
91function: {91 function: {
92name: "getCurrentTemperature",92 name: "getCurrentTemperature",
93description: "Get the current temperature for a specific location",93 description: "Get the current temperature for a specific location",
94parameters: {94 parameters: {
95type: "object",95 type: "object",
96properties: {96 properties: {
97location: {97 location: {
98type: "string",98 type: "string",
99description: "The city and state, e.g., San Francisco, CA",99 description: "The city and state, e.g., San Francisco, CA",
100},100 },
101unit: {101 unit: {
102type: "string",102 type: "string",
103enum: ["Celsius", "Fahrenheit"],103 enum: ["Celsius", "Fahrenheit"],
104description:104 description:
105"The temperature unit to use. Infer this from the user's location.",105 "The temperature unit to use. Infer this from the user's location.",
106},106 },
107},107 },
108required: ["location", "unit"],108 required: ["location", "unit"],
109},109 },
110},110 },
111},111 },
112{112 {
113type: "function",113 type: "function",
114function: {114 function: {
115name: "getRainProbability",115 name: "getRainProbability",
116description: "Get the probability of rain for a specific location",116 description: "Get the probability of rain for a specific location",
117parameters: {117 parameters: {
118type: "object",118 type: "object",
119properties: {119 properties: {
120location: {120 location: {
121type: "string",121 type: "string",
122description: "The city and state, e.g., San Francisco, CA",122 description: "The city and state, e.g., San Francisco, CA",
123},123 },
124},124 },
125required: ["location"],125 required: ["location"],
126},126 },
127},127 },
128},128 },
129],129 ],
130});130});
131```131```
132 132
148const thread = await client.beta.threads.create();148const thread = await client.beta.threads.create();
149const message = client.beta.threads.messages.create(thread.id, {149const message = client.beta.threads.messages.create(thread.id, {
150 role: "user",150 role: "user",
151 content: "What's the weather in San Francisco today and the likelihood it'll rain?",151 content:
152 "What's the weather in San Francisco today and the likelihood it'll rain?",
152});153});
153```154```
154 155
267 this.client = client;268 this.client = client;
268 }269 }
269 270
270async onEvent(event) {271 async onEvent(event) {
271try {272 try {
272console.log(event);273 console.log(event);
273// Retrieve events that are denoted with 'requires_action'274 // Retrieve events that are denoted with 'requires_action'
274// since these will have our tool_calls275 // since these will have our tool_calls
275if (event.event === "thread.run.requires_action") {276 if (event.event === "thread.run.requires_action") {
276await this.handleRequiresAction(277 await this.handleRequiresAction(
277event.data,278 event.data,
278event.data.id,279 event.data.id,
279event.data.thread_id,280 event.data.thread_id
280);281 );
281}282 }
282} catch (error) {283 } catch (error) {
283console.error("Error handling event:", error);284 console.error("Error handling event:", error);
284}285 }
285}286 }
286 287
287async handleRequiresAction(data, runId, threadId) {288 async handleRequiresAction(data, runId, threadId) {
288try {289 try {
289const toolOutputs =290 const toolOutputs =
290data.required_action.submit_tool_outputs.tool_calls.map((toolCall) => {291 data.required_action.submit_tool_outputs.tool_calls.map((toolCall) => {
291if (toolCall.function.name === "getCurrentTemperature") {292 if (toolCall.function.name === "getCurrentTemperature") {
292return {293 return {
293tool_call_id: toolCall.id,294 tool_call_id: toolCall.id,
294output: "57",295 output: "57",
295};296 };
296} else if (toolCall.function.name === "getRainProbability") {297 } else if (toolCall.function.name === "getRainProbability") {
297return {298 return {
298tool_call_id: toolCall.id,299 tool_call_id: toolCall.id,
299output: "0.06",300 output: "0.06",
300};301 };
301}302 }
302});303 });
303// Submit all the tool outputs at the same time304 // Submit all the tool outputs at the same time
304await this.submitToolOutputs(toolOutputs, runId, threadId);305 await this.submitToolOutputs(toolOutputs, runId, threadId);
305} catch (error) {306 } catch (error) {
306console.error("Error processing required action:", error);307 console.error("Error processing required action:", error);
307}308 }
308}309 }
309 310
310async submitToolOutputs(toolOutputs, runId, threadId) {311 async submitToolOutputs(toolOutputs, runId, threadId) {
311try {312 try {
312// Use the submitToolOutputsStream helper313 // Use the submitToolOutputsStream helper
313const stream = this.client.beta.threads.runs.submitToolOutputsStream(314 const stream = this.client.beta.threads.runs.submitToolOutputsStream(
314threadId,315 runId,
315runId,316 { thread_id: threadId, tool_outputs: toolOutputs }
316{ tool_outputs: toolOutputs },317 );
317);318 for await (const event of stream) {
318for await (const event of stream) {319 this.emit("event", event);
319this.emit("event", event);320 }
320}321 } catch (error) {
321} catch (error) {322 console.error("Error submitting tool outputs:", error);
322console.error("Error submitting tool outputs:", error);323 }
323}324 }
324}
325}325}
326 326
327const eventHandler = new EventHandler(client);327const eventHandler = new EventHandler(client);
328eventHandler.on("event", eventHandler.onEvent.bind(eventHandler));328eventHandler.on("event", eventHandler.onEvent.bind(eventHandler));
329 329
330const stream = await client.beta.threads.runs.stream(330const stream = await client.beta.threads.runs.stream(threadId, {
331threadId,331 assistant_id: assistantId,
332{ assistant_id: assistantId },332});
333eventHandler,
334);
335 333
336for await (const event of stream) {334for await (const event of stream) {
337eventHandler.emit("event", event);335 eventHandler.emit("event", event);
338}336}
339```337```
340 338
418 output: "0.06",416 output: "0.06",
419 };417 };
420 }418 }
421 },419 }
422 );420 );
423 421
424 // Submit all tool outputs at once after collecting them in a list422 // Submit all tool outputs at once after collecting them in a list
425 if (toolOutputs.length > 0) {423 if (toolOutputs.length > 0) {
426 run = await client.beta.threads.runs.submitToolOutputsAndPoll(424 run = await client.beta.threads.runs.submitToolOutputsAndPoll(run.id, {
427 thread.id,425 thread_id: thread.id,
428 run.id,426 tool_outputs: toolOutputs,
429 { tool_outputs: toolOutputs },427 });
430 );
431 console.log("Tool outputs submitted successfully.");428 console.log("Tool outputs submitted successfully.");
432 } else {429 } else {
433 console.log("No tool outputs to submit.");430 console.log("No tool outputs to submit.");
435 432
436 // Check status after submitting tool outputs433 // Check status after submitting tool outputs
437 return handleRunStatus(run);434 return handleRunStatus(run);
438 435 }
439}
440};436};
441 437
442const handleRunStatus = async (run) => {438const handleRunStatus = async (run) => {
443// Check if the run is completed439 // Check if the run is completed
444if (run.status === "completed") {440 if (run.status === "completed") {
445let messages = await client.beta.threads.messages.list(thread.id);441 let messages = await client.beta.threads.messages.list(thread.id);
446console.log(messages.data);442 console.log(messages.data);
447return messages.data;443 return messages.data;
448} else if (run.status === "requires_action") {444 } else if (run.status === "requires_action") {
449console.log(run.status);445 console.log(run.status);
450return await handleRequiresAction(run);446 return await handleRequiresAction(run);
451} else {447 } else {
452console.error("Run did not complete:", run);448 console.error("Run did not complete:", run);
453}449 }
454};450};
455 451
456// Create and poll run452// Create and poll run
457let run = await client.beta.threads.runs.createAndPoll(thread.id, {453let run = await client.beta.threads.runs.createAndPoll(thread.id, {
458assistant_id: assistant.id,454 assistant_id: assistant.id,
459});455});
460 456
461handleRunStatus(run);457handleRunStatus(run);
533 529
534```javascript530```javascript
535const assistant = await client.beta.assistants.create({531const assistant = await client.beta.assistants.create({
536model: "gpt-4o-2024-08-06",532 model: "gpt-4o-2024-08-06",
537instructions:533 instructions:
538"You are a weather bot. Use the provided functions to answer questions.",534 "You are a weather bot. Use the provided functions to answer questions.",
539tools: [535 tools: [
540{536 {
541type: "function",537 type: "function",
542function: {538 function: {
543name: "getCurrentTemperature",539 name: "getCurrentTemperature",
544description: "Get the current temperature for a specific location",540 description: "Get the current temperature for a specific location",
545parameters: {541 parameters: {
546type: "object",542 type: "object",
547properties: {543 properties: {
548location: {544 location: {
549type: "string",545 type: "string",
550description: "The city and state, e.g., San Francisco, CA",546 description: "The city and state, e.g., San Francisco, CA",
551},547 },
552unit: {548 unit: {
553type: "string",549 type: "string",
554enum: ["Celsius", "Fahrenheit"],550 enum: ["Celsius", "Fahrenheit"],
555description:551 description:
556"The temperature unit to use. Infer this from the user's location.",552 "The temperature unit to use. Infer this from the user's location.",
557},553 },
558},554 },
559required: ["location", "unit"],555 required: ["location", "unit"],
560// highlight-start556 // highlight-start
561additionalProperties: false557 additionalProperties: false,
562// highlight-end558 // highlight-end
563},559 },
564// highlight-start560 // highlight-start
565strict: true561 strict: true,
566// highlight-end562 // highlight-end
567},563 },
568},564 },
569{565 {
570type: "function",566 type: "function",
571function: {567 function: {
572name: "getRainProbability",568 name: "getRainProbability",
573description: "Get the probability of rain for a specific location",569 description: "Get the probability of rain for a specific location",
574parameters: {570 parameters: {
575type: "object",571 type: "object",
576properties: {572 properties: {
577location: {573 location: {
578type: "string",574 type: "string",
579description: "The city and state, e.g., San Francisco, CA",575 description: "The city and state, e.g., San Francisco, CA",
580},576 },
581},577 },
582required: ["location"],578 required: ["location"],
583// highlight-start579 // highlight-start
584additionalProperties: false580 additionalProperties: false,
585// highlight-end581 // highlight-end
586},582 },
587// highlight-start583 // highlight-start
588strict: true584 strict: true,
589// highlight-end585 // highlight-end
590},586 },
591},587 },
592],588 ],
593});589});
594```590```