I am trying to create a GPT chatbot for restaurants that can ask customers for their contact info and time of reservation. After the AI chatbot is sure the customer has provided it with all of these details, I want to run what I believe is called an "action". I basically want to use another API to send an email to the person saying we will contact you shortly. In the meantime, however, I just want to do a console.log that says "confirmed" just so I know the AI understands it got all the details and can therefore proceed to the next step (just an intermediary step). However, I'm struggling with how I can move from my current code where it just has a chat with the user based on a specific assistant to actually executing actions. Here is my code (running on Node in the backend that just receives responses from a frontend and sends them back):
const express = require('express');
const { OpenAI } = require('openai');
const cors = require('cors');
require('dotenv').config();
const app = express();
app.use(cors());
app.use(express.json());
const openai = new OpenAI(process.env.OPENAI_API_KEY);
app.post('/get-response', async (req, res) => {
const userMessage = req.body.message;
let threadId = req.body.threadId; // Receive threadId from the client
const assistantId = 'MYASSISTANTID'; // Replace with your actual assistant ID
// If no threadId or it's a new session, create a new thread
if (!threadId) {
const thread = await openai.beta.threads.create();
threadId = thread.id;
}
await openai.beta.threads.messages.create(threadId, {
role: "user",
content: userMessage,
});
// Use runs to wait for the assistant response and then retrieve it
const run = await openai.beta.threads.runs.create(threadId, {
assistant_id: assistantId,
});
let runStatus = await openai.beta.threads.runs.retrieve(
threadId,
run.id
);
// Polling mechanism to see if runStatus is completed
// This should be made more robust.
while (runStatus.status !== "completed") {
await new Promise((resolve) => setTimeout(resolve, 2000));
runStatus = await openai.beta.threads.runs.retrieve(threadId, run.id);
}
// //CHECKING FOR TABLE RESERVATION:
// // If the model output includes a function call
// if (runStatus.status === 'requires_action') {
// // You might receive an array of actions, iterate over it
// for (const action of runStatus.required_action.submit_tool_outputs.tool_calls) {
// const functionName = action.function.name;
// const arguments = JSON.parse(action.function.arguments);
// // Check if the function name matches 'table_reservation'
// if (functionName === 'table_reservation') {
// handleTableReservation(arguments);
// // Respond back to the model that the action has been handled
// await openai.beta.threads.runs.submit_tool_outputs(threadId, run.id, {
// tool_outputs: [{
// tool_call_id: action.id,
// output: { success: true } // You can include more details if needed
// }]
// });
// }
// }
// }
// Get the last assistant message from the messages array
const messages = await openai.beta.threads.messages.list(threadId);
// Find the last message for the current run
const lastMessageForRun = messages.data
.filter(
(message) => message.run_id === run.id && message.role === "assistant"
)
.pop();
// If an assistant message is found, console.log() it
assistantMessage = ""
if (lastMessageForRun) {
assistantMessage = lastMessageForRun.content[0].text.value
console.log(`${assistantMessage} \n`);
}
res.json({ message: assistantMessage, threadId: threadId });
});
const PORT = 3001;
app.listen(PORT, () => console.log(`Server listening on port ${PORT}`));
If you look at my code above, you'll realize that I tried doing what I am asking about and then ended up commenting it out because it did not work.
For further context, I was trying to understand how actions and tools work as maybe this is the way I might be able to achieve what I am trying to do. And I came up with the following code that I think might be useful (the problem is I don't know how to combine the 2 pieces of code and the code below doesn't use an assistant which I eventually want to end up using):
require('dotenv').config(); // This should be at the top of your file
const { OpenAI } = require('openai');
const openai = new OpenAI(process.env.OPENAI_API_KEY);
// Example dummy function hard coded to return the same weather
// In production, this could be your backend API or an external API
function getCurrentWeather(location) {
if (location.toLowerCase().includes("tokyo")) {
return JSON.stringify({ location: "Tokyo", temperature: "10", unit: "celsius" });
} else if (location.toLowerCase().includes("san francisco")) {
return JSON.stringify({ location: "San Francisco", temperature: "72", unit: "fahrenheit" });
} else if (location.toLowerCase().includes("paris")) {
return JSON.stringify({ location: "Paris", temperature: "22", unit: "fahrenheit" });
} else {
return JSON.stringify({ location, temperature: "unknown" });
}
}
function get_table_reservations(bookingTime, numGuests) {
if (bookingTime.toLowerCase().includes("4:30")) {
return JSON.stringify({ availability: "Not available"});
}
else if (!bookingTime) {
return JSON.stringify({ availability: "Please include a booking time"});
}
else {
return JSON.stringify({ availability: "Available", forGuests: numGuests});
}
}
async function runConversation() {
// Step 1: send the conversation and available functions to the model
const messages = [
{ role: "user", content: "I want a table reservation for 3 people." },
];
const tools = [
{
type: "function",
function: {
name: "get_current_weather",
description: "Get the current weather in a given location",
parameters: {
type: "object",
properties: {
location: {
type: "string",
description: "The city and state, e.g. San Francisco, CA",
},
unit: { type: "string", enum: ["celsius", "fahrenheit"] },
},
required: ["location"],
},
},
},
{
type: "function",
function: {
name: "get_table_reservations",
description: "Tell the user if a table is available for the number of guests and time they request",
parameters: {
type: "object",
properties: {
numGuests: {
type: "integer",
description: "The number of guests",
},
bookingTime: { type: "string", description: "The time requested for a reservation, eg. 8:30 PM" },
},
required: ["numGuests", "bookingTime"],
},
},
},
];
const response = await openai.chat.completions.create({
model: "gpt-3.5-turbo-1106",
messages: messages,
tools: tools,
tool_choice: "auto", // auto is default, but we'll be explicit
});
const responseMessage = response.choices[0].message;
// Step 2: check if the model wanted to call a function
const toolCalls = responseMessage.tool_calls;
if (responseMessage.tool_calls) {
// Step 3: call the function
// Note: the JSON response may not always be valid; be sure to handle errors
const availableFunctions = {
get_current_weather: getCurrentWeather,
get_table_reservations: get_table_reservations
}; // only one function in this example, but you can have multiple
messages.push(responseMessage); // extend conversation with assistant's reply
for (const toolCall of toolCalls) {
const functionName = toolCall.function.name;
const functionToCall = availableFunctions[functionName];
const functionArgs = JSON.parse(toolCall.function.arguments);
console.log('Arguments:', toolCall.function.arguments, 'name:', functionName); // Add this line to debug
const functionResponse = functionToCall(
functionArgs.bookingTime,
functionArgs.numGuests
);
messages.push({
tool_call_id: toolCall.id,
role: "tool",
name: functionName,
content: functionResponse,
}); // extend conversation with function response
}
const secondResponse = await openai.chat.completions.create({
model: "gpt-3.5-turbo-1106",
messages: messages,
}); // get a new response from the model where it can see the function response
return secondResponse.choices;
}
}
runConversation().then(console.log).catch(console.error);
Alternatively, maybe there's a much easier way to do this through the platform.openai website itself on the assistants page. Maybe I need to change/ add something to the area in the screenshot below, perhaps a function. As a separate question, one of the examples of adding a function in the assistants API was "get_weather" but I'm not sure how this works and how the get_weather function will even run or where it needs to be defined (also shown in the second screenshot below).
Further, it would be a big help if someone could advise me how I can start using an email API to start sending emails once I have this step figured out (this part of my question is less important though)
Lastly (I know I'm asking a lot of questions), out of curiosity does anyone know if I can implement the same thing I am doing with GPT assistants with Gemini instead?


Use the Assistant API. Declare a Function Call tool and describe each parameter of the function and the function too. If you give an accurate meaning for the function ChatGPT will return you the information necessary to call your function that will send the email. For node or Python you can find tons of libraries on Git and not only. Then start learning how to use the assistant API here: Assistant API