Possible to call OpenAI synchronously from nodejs/AWS lambda?

Any help appreciated - I’m having trouble getting to grips with why the code below fails. I have a rules engine in which the steps must be executed in sequence because each rule may assess the results of previous rules, so these have to be available.

Thanks,

David

const { Configuration, OpenAIApi } = require("openai");

exports.handler = async function(event, context, callback) {

    var output;

	try {
		output = mycaller(event.prompt);
		console.log('output: ' + output);
	}
	catch (e){
		output = e.message;
	}

	let response = {
		statusCode: 200,
		headers: { "Content-type" : "application/json" },
		body: JSON.stringify(output)
	};

	return response;
};

function mycaller(prompt)
{
	getResponse(prompt).then(res => res.data.choices[0].text);
}

async function getResponse(prompt)
{
    console.log("getResponse('" + prompt + "')");
    
	const configuration = new Configuration({
		apiKey: "my-api-key-here",
	});
	const openai = new OpenAIApi(configuration);

	return await openai.createCompletion({
			model: "text-davinci-003",
			prompt: prompt,
			temperature: 0.7,
			max_tokens: 500,
			top_p: 1,
			frequency_penalty: 0,
			presence_penalty: 0,
		});
}

You are not returning any value from the “mycaller” function. Also, since you’re already in an “async” function you can just await the call and get the response, without using “then”.

For example:

Change the handler function:

...
output = await mycaller(event.prompt);
...

And change mycaller

async function mycaller(prompt) {
   const response = await getResponse(prompt);
   return res.data.choices[0].text;
}

Thanks so much for your reply. I think I didn’t explain my situation properly though.
I understand that I can call an async version of mycaller() and how this works. My issue is that my mycaller() function in this stripped-down example represents thousands of lines of synchronous code in my “real” application, so what I’m trying to do is add one asynchronous call to chatGPT to these.

To explain a little further, I have a rules engine where each rule may require values that result from earlier rule evaluations. The logical way to code this is to evaluate them in sequence, synchronously. Theoretically it would be possible to code asynchronously with each callback re-building the tree of values but this would be really weird and a nightmare to debug.

I’ve put a “better” example below but it’s quite possible that what I need is simply not possible to do in node/javascript :slightly_smiling_face:

const { Configuration, OpenAIApi } = require("openai");

exports.handler = async function(event, context, callback) {

    var output;

	try {
		output = await makeSentence(event.prompt);
		console.log('output: ' + output);
	}
	catch (e){
		output = e.message;
	}

	let response = {
		statusCode: 200,
		headers: { "Content-type" : "application/json" },
		body: JSON.stringify(output)
	};

	return response;
};

async function makeSentence(prompt)
{
	const rule1 = getOpening();
	const rule2 = await getMiddle(prompt);
	const rule3 = getClosing(rule1 + ' ' + rule2);
	
	return rule3;
}

function getOpening()
{
	const greeting = [ 'Hello', 'Hi', 'Greetings'];
	const random = Math.floor(Math.random() * greeting.length);
	
	return '<sentence>' + greeting[random];
}

async function getMiddle(prompt)
{
    console.log("getMiddle('" + prompt + "')");
    
	const configuration = new Configuration({
		apiKey: "my-api-key-here",
	});
	const openai = new OpenAIApi(configuration);

	await openai.createCompletion({
			model: "text-davinci-003",
			prompt: prompt,
			temperature: 0.7,
			max_tokens: 500,
			top_p: 1,
			frequency_penalty: 0,
			presence_penalty: 0,
	}).then(res => {
        var text = res.data.choices[0].text;
        console.log('got response: ' + text);
        return text;
    }).catch(error => {
        console.log('Error: ' + error.message);
        return error.message;
    });
}

function getClosing(resp)
{
	return resp + '</sentence>';
}

I am not sure if I totally I understand. Based on your example I see a simple mistake. Your getMiddle function does not have a return statement. You are combining await with .then. I would use one OR the other. For example I would change getMiddle to:

const res = await openai.createCompletion({
			model: "text-davinci-003",
			prompt: prompt,
			temperature: 0.7,
			max_tokens: 500,
			top_p: 1,
			frequency_penalty: 0,
			presence_penalty: 0,
	});
return res.data.choices[0].text;

You also don’t need to recreate an instance of the OpenAIApi client inside the rules (such as in getMiddle) you can use one instance in the whole script and reuse.

I’m fairly confident that what you’re trying to do is possible with JavaScript, you just have to structure your code correctly. Always make sure to return a value from each rule function.