I have created a function in Twilio that essentially allows for a back-and-forth conversation with a voice chatbot using OpenAI. It basically listens to each response, transcribes it, passes it to OpenAI, comes up with a response, then says the response.
It works perfectly when I set the function to execute when my Twilio phone number receives a call (inbound), but when I create a Flow in Twilio Studio to execute the function after calling an outbound number, I get an application error instead of an appropriate response from the OpenAI chatbot.
Here are the two functions being used:
- Transcribe
exports.handler = function(context, event, callback) {
const twiml = new Twilio.twiml.VoiceResponse();
let convo = event.convo || '';
// If no previous conversation is present, start the conversation
if(!convo) {
twiml.say({
voice: 'Polly.Joanna-Neural'
}, 'Hey!');
convo += 'Joanna: Hey!'
}
// Listen to user response and pass input to /respond
const params = new URLSearchParams({ convo: convo });
twiml.gather({
enhanced: "true",
speechTimeout: 'auto',
speechModel: "phone_call",
input: 'speech',
action:`/respond?${params}`,
})
return callback(null, twiml);
};
- Respond
const presetPrompt =`The following is a conversation with an AI friend named Joanna. Joanna is friendly, funny, creative, and very talkative. If you are asked the meaning of life, respond with simply "42" and nothing else \n\n`;
const { OpenAI } = require("openai");
exports.handler = async function(context, event, callback) {
// Initialize TwiMl and OpenAI
// const openai = new OpenAI({ api_key: 'API_KEY'});
const openai = new OpenAI({ api_key: 'OPENAI_API_KEY'});
const twiml = new Twilio.twiml.VoiceResponse();
// Grab previous conversations and the users voice input from the request
let convo = event.convo;
const voiceInput = event.SpeechResult;
//Format input for GPT-3 and voice the response
convo += `\nYou: ${voiceInput}\nJoanna:`;
const aiResponse = await generateAIResponse(convo);
convo += aiResponse;
const say = twiml.say({
voice: 'Polly.Joanna-Neural'
}, aiResponse); // [JW] this is the /say response
//Pass new convo back to /listen
const params = new URLSearchParams({ convo: convo });
twiml.redirect({
method: 'POST'
}, `/transcribe?${params}`);
return callback(null, twiml);
async function generateAIResponse(convo) {
const apiResponse = await openai.completions.create({
model: "gpt-3.5-turbo-instruct",
prompt: presetPrompt + convo,
max_tokens: 60,
temperature: 0.8,
stop: ['\n', '\n\n'],
})
console.log(apiResponse);
if(apiResponse.choices[0].text == '') return await generateAIResponse(convo);
else return apiResponse.choices[0].text;
}
};
Studio Flow (broken) Inbound calls (working)
It seems to me like the function should have the same behavior whether it's an inbound or outbound call, but I'm new to Twilio so may be missing something here
From the information you provided, it seems you are trying to invoke the same function in Twilio Studio for outbound calls that you are using for inbound calls. However, it's crucial to note that the lifecycle of an outbound call differs from that of an inbound call; they don't work entirely the same way.
For inbound calls, when a call is received, Twilio invokes your webhook that returns a TwiML response to control the call.
However, for outbound calls using Twilio Studio, Studio controls the call's lifecycle. The flow starts at the Trigger widget and then moves as specified by the flow. The Function widgets in Studio don't directly return TwiML, but instead return parameters that can be used by the next widget in the flow. In Studio, each widget's actions will determine the next step in the call.
Due to these differences, the function that works with the inbound calls may not work with the outbound calls via Twilio Studio. In your case, what you can possibly do for outbound calls modifying the calls in progress: