I am trying to embed an OpenAI assistant into my Wix webpage using the npm package that is available. I created my own custom package so, I can have clean code on the Front-End
The code should
- create a new OpenAI object
- retrieve Assistant
- create thread
4.create message - retrieve message
I have made several changes and added error catching. The error that I keep recieving is a TYPE ERROR: openAI is not a constructor.
I have tried using an HTTP request and have gotten similar errors.
Front End Code
import { getSecret, getAssistantID} from "@cameronkastner/instructor-backend"
import {createThread,createOpenAI, runAssistant, getRunStatus, retrieveMessage, retrieveAssistant } from "@cameronkastner/instructor";
import * as OpenAI from 'openai';
console.log(OpenAI);
let openNewAI;
$w.onReady(async function () {
});
export async function sendText_click(event) {
try {
const threadID = await createThread($w('#inputText').value, openNewAI);
const runID = await runAssistant(threadID, openNewAI);
let runStatus;
do {
runStatus = await getRunStatus(threadID, runID, openNewAI);
await new Promise(resolve => setTimeout(resolve, 1000));
} while (runStatus === 'queued' || runStatus === 'in progress');
var cleanText = await retrieveMessage(threadID, openNewAI);
$w('#outputText').label = cleanText;
} catch (error) {
console.error("Error in sendText_click:", error);
$w('#outputText').label = "An error occurred. Please try again.";
}
}
// method to initialize OpenAI
import { Configuration, OpenAIApi } from "openai";
// Wrap your code inside an async function
async function initializeOpenAI() {
const configuration = new Configuration({
apiKey: await getSecret() // Ensure getSecret is async
});
openNewAI = new OpenAIApi(configuration);
const assistantID = await getAssistantID(); // Ensure getAssistantID is async
const newAssistant = await retrieveAssistant(openNewAI, assistantID);
// Continue with your logic using newAssistant
}
// Call the function to execute
initializeOpenAI().catch(console.error);
Custom Package
import OpenAI from 'openai';
import { getSecret } from 'backend/aModule.jsw';
import { getAssistantID } from 'backend/aModule.jsw';
let openai;
let threadId;
let runId;
/*export async function createOpenAI(apiKey) {
openai = new OpenAI({
apiKey: apiKey
});
console.log(openai);
return openai;
}*/
export async function retrieveAssistant(openai, assistantID = getAssistantID()) {
try {
// Retrieve the assistant details using the provided ID
const assistant = await openai.beta.assistants.retrieve(assistantID);
return assistant;
} catch (error) {
console.error('Error in retrieveAssistant:', error);
// Return null to indicate an error occurred
return null;
}
} // End of retrieveAssistant function
export async function createThread(inputText, openai) {
try {
// Create a new thread
const thread = await openai.beta.threads.create();
// Check if thread creation was successful and has an id
if (!thread || !thread.id) {
throw new Error("Failed to create a new thread.");
}
// Assign the created thread's ID to threadId
threadId = thread.id;
// Create a new message in the thread with the user's input
await openai.beta.threads.messages.create(threadId, {
role: "user",
content: inputText
});
return threadId;
} catch (error) {
console.error('Error in createThread:', error);
return null; // Indicate failure
}
}
export async function runAssistant(threadId, openai) {
try {
// Create a run for the assistant in the specified thread
const run = await openai.beta.threads.runs.create(threadId, { assistant_id: getAssistantID() });
// Check if the run was successfully created and has an id
if (!run || !run.id) {
throw new Error("Failed to create a new run.");
}
// Assign the created run's ID to runId
runId = run.id;
// Initialize the run status
let runStatus = run.status;
// Define a maximum number of retries to avoid an infinite loop
const maxRetries = 10;
let retries = 0;
// Continue to check the run's status until it's no longer 'queued' or 'in_progress'
while ((runStatus === "queued" || runStatus === "in_progress") && retries < maxRetries) {
// Wait for a short period before checking the status again
await new Promise(resolve => setTimeout(resolve, 1000)); // Waits for 1 second
// Retrieve the updated status of the run
const updatedRun = await openai.beta.threads.runs.retrieve(threadId, runId);
runStatus = updatedRun.status;
// Increment the retries count
retries++;
}
// If the maximum number of retries was reached, throw an error
if (retries >= maxRetries) {
throw new Error("Run status check exceeded maximum retries.");
}
return runId;
} catch (error) {
console.error('Error in runAssistant:', error);
return null; // Indicate failure
}
}
export async function getRunStatus(threadId, runId, openai) {
try {
const run = await openai.beta.threads.runs.retrieve(threadId, runId);
return run.status; // This will return the status of the run
} catch (error) {
console.error('Error in getRunStatus:', error);
return null; // Return null or a specific error message if there is an error
}
}
export async function retrieveMessage(threadId, openai) {
try {
const messages = await openai.beta.threads.messages.list(threadId);
let outputText = "";
messages.data.forEach(message => {
if (Array.isArray(message.content)) {
message.content.forEach(contentObj => {
if (contentObj.type === 'text' && contentObj.text && typeof contentObj.text.value === 'string') {
const cleanedContent = contentObj.text.value.replace(/​``​``​``【oaicite:0】``​``​``​/g, '').trim();
outputText += cleanedContent + " "; // Append instead of assign
}
});
}
});
return outputText;
} catch (error) {
console.error('Error in retrieveMessage:', error);
}
}