Embedding OpenAI assistant into a webpage

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

  1. create a new OpenAI object
  2. retrieve Assistant
  3. create thread
    4.create message
  4. 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(/&#8203;``&#8203;``&#8203;``【oaicite:0】``&#8203;``&#8203;``&#8203;/g, '').trim();
                        outputText += cleanedContent + " "; // Append instead of assign
                    }
                });
            }
        });
        return outputText;
    } catch (error) {
        console.error('Error in retrieveMessage:', error);
    }
}


Without testing, your code looks pretty good. That error means that you were trying to initialize the object using an incorrect imported value from either their package, or your own package.

A few things you could check:

  • Check the version. Wix’s latest openai package is verrsion 3.3.0, but the latest on npm is 4.20.1 as of this writing. That means a major version change happened in between, which would have most likely been in line with the announcement of the assistants. The way it’s initialized looks like it has also changed, based on the new docs here -openai - npm.
    This may be a breaking change, so I’d double check the code there
  • It looks like you may have commented out the function throwing the error. It would be good to console.log the value of openAI right before it runs

I’ve personally avoided the openai package and done all my requests directly through the REST API, because it was much easier to implement earlier in the year when I was testing it for https://ettu.app