Revert incomplete changes to GPT handler
This commit is contained in:
@@ -1,231 +1,94 @@
|
||||
import { DebugBuilder } from "../../modules/debugger.mjs";
|
||||
import { requestNodeJoinSystem } from "../../modules/socketServerWrappers.mjs";
|
||||
import { getSystemByName } from "../../modules/mongo-wrappers/mongoSystemsWrappers.mjs";
|
||||
import { getConfig } from "../../modules/mongo-wrappers/mongoConfigWrappers.mjs";
|
||||
import { getAvailableTokensInGuild } from "../modules/wrappers.mjs";
|
||||
const log = new DebugBuilder("server", "discordBot.modules.gptHandler");
|
||||
import dotenv from "dotenv";
|
||||
dotenv.config();
|
||||
|
||||
import { OpenAI } from "openai";
|
||||
import { EventEmitter } from "events";
|
||||
|
||||
// Initialize environment variables
|
||||
dotenv.config();
|
||||
const openai = new OpenAI(process.env.OPENAI_API_KEY);
|
||||
|
||||
const log = new DebugBuilder("server", "discordBot.modules.gptHandler");
|
||||
const assistant = await openai.beta.assistants.create({
|
||||
name: "Emmelia",
|
||||
instructions: process.env.DRB_SERVER_INITIAL_PROMPT,
|
||||
model: "gpt-4o",
|
||||
});
|
||||
|
||||
let assistant;
|
||||
let eventHandler;
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
const openai = new OpenAI(process.env.OPENAI_API_KEY);
|
||||
|
||||
assistant = await openai.beta.assistants.create({
|
||||
name: "Emmelia",
|
||||
instructions: (await getConfig("emmeliaInitialPrompt")) || "",
|
||||
model: "gpt-4o-mini",
|
||||
tools: [
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "checkUserVoiceChannel",
|
||||
description: "Check if the user is in a voice channel",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
userId: {
|
||||
type: "string",
|
||||
description: "The ID of the user",
|
||||
},
|
||||
guildId: {
|
||||
type: "string",
|
||||
description: "The ID of the guild",
|
||||
},
|
||||
},
|
||||
required: ["userId", "guildId"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "getSelectedSystem",
|
||||
description: "Retrieve the selected system details",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
systemName: {
|
||||
type: "string",
|
||||
description: "The name of the system",
|
||||
},
|
||||
},
|
||||
required: ["systemName"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "joinSelectedSystem",
|
||||
description: "Join the selected system in the user's voice channel",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
userId: {
|
||||
type: "string",
|
||||
description: "The ID of the user",
|
||||
},
|
||||
guildId: {
|
||||
type: "string",
|
||||
description: "The ID of the guild",
|
||||
},
|
||||
systemName: {
|
||||
type: "string",
|
||||
description: "The name of the system",
|
||||
},
|
||||
channelId: {
|
||||
type: "string",
|
||||
description: "The ID of the voice channel",
|
||||
},
|
||||
},
|
||||
required: ["userId", "guildId", "systemName", "channelId"],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
class EventHandler extends EventEmitter {
|
||||
constructor(client) {
|
||||
super();
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
async onEvent(event) {
|
||||
try {
|
||||
console.log(event);
|
||||
if (event.event === "thread.run.requires_action") {
|
||||
await this.handleRequiresAction(
|
||||
event.data,
|
||||
event.data.id,
|
||||
event.data.thread_id,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error handling event:", error);
|
||||
}
|
||||
}
|
||||
|
||||
async handleRequiresAction(data, runId, threadId) {
|
||||
try {
|
||||
const toolOutputs = await Promise.all(
|
||||
data.required_action.submit_tool_outputs.tool_calls.map(
|
||||
async (toolCall) => {
|
||||
switch (toolCall.function.name) {
|
||||
case "checkUserVoiceChannel":
|
||||
return await this.checkUserVoiceChannel(toolCall);
|
||||
case "getSelectedSystem":
|
||||
return await this.getSelectedSystem(toolCall);
|
||||
case "joinSelectedSystem":
|
||||
return await this.joinSelectedSystem(toolCall);
|
||||
default:
|
||||
throw new Error(
|
||||
`Unknown function: ${toolCall.function.name}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
await this.submitToolOutputs(toolOutputs, runId, threadId);
|
||||
} catch (error) {
|
||||
console.error("Error processing required action:", error);
|
||||
}
|
||||
}
|
||||
|
||||
async checkUserVoiceChannel(toolCall) {
|
||||
const { userId, guildId } = JSON.parse(toolCall.function.arguments);
|
||||
const guild = await this.client.guilds.get(guildId);
|
||||
const member = await guild.members.get(userId);
|
||||
const isInVoiceChannel = !!member.voice.channel;
|
||||
|
||||
return {
|
||||
tool_call_id: toolCall.id,
|
||||
output: JSON.stringify({
|
||||
isInVoiceChannel,
|
||||
channelId: member.voice.channelId,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
async getSelectedSystem(toolCall) {
|
||||
const { systemName } = JSON.parse(toolCall.function.arguments);
|
||||
const system = await getSystemByName(systemName);
|
||||
|
||||
return {
|
||||
tool_call_id: toolCall.id,
|
||||
output: JSON.stringify(system),
|
||||
};
|
||||
}
|
||||
|
||||
async joinSelectedSystem(toolCall) {
|
||||
const { userId, guildId, systemName, channelId } = JSON.parse(
|
||||
toolCall.function.arguments,
|
||||
);
|
||||
const system = await getSystemByName(systemName);
|
||||
const guild = await this.client.guilds.fetch(guildId);
|
||||
const discordToken = await getAvailableTokensInGuild(guildId);
|
||||
|
||||
if (discordToken) {
|
||||
const result = await requestNodeJoinSystem(
|
||||
system,
|
||||
channelId,
|
||||
discordToken,
|
||||
);
|
||||
return {
|
||||
tool_call_id: toolCall.id,
|
||||
output: JSON.stringify({ success: true, result }),
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
tool_call_id: toolCall.id,
|
||||
output: JSON.stringify({
|
||||
success: false,
|
||||
message: "No available bots.",
|
||||
}),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async submitToolOutputs(toolOutputs, runId, threadId) {
|
||||
try {
|
||||
const stream = this.client.beta.threads.runs.submitToolOutputsStream(
|
||||
threadId,
|
||||
runId,
|
||||
{ tool_outputs: toolOutputs },
|
||||
);
|
||||
for await (const event of stream) {
|
||||
this.emit("event", event);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error submitting tool outputs:", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eventHandler = new EventHandler(openai);
|
||||
eventHandler.on("event", eventHandler.onEvent.bind(eventHandler));
|
||||
} catch (error) {
|
||||
console.error("Initialization error:", error);
|
||||
class EventHandler extends EventEmitter {
|
||||
constructor(client) {
|
||||
super();
|
||||
this.client = client;
|
||||
}
|
||||
})();
|
||||
|
||||
async onEvent(event) {
|
||||
try {
|
||||
console.log(event);
|
||||
// Retrieve events that are denoted with 'requires_action'
|
||||
// since these will have our tool_calls
|
||||
if (event.event === "thread.run.requires_action") {
|
||||
await this.handleRequiresAction(
|
||||
event.data,
|
||||
event.data.id,
|
||||
event.data.thread_id,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error handling event:", error);
|
||||
}
|
||||
}
|
||||
|
||||
async handleRequiresAction(data, runId, threadId) {
|
||||
try {
|
||||
const toolOutputs =
|
||||
data.required_action.submit_tool_outputs.tool_calls.map((toolCall) => {
|
||||
// Call the function
|
||||
switch (toolCall.function.name) {
|
||||
case "getCurrentTemperature":
|
||||
return {
|
||||
tool_call_id: toolCall.id,
|
||||
output: "57",
|
||||
};
|
||||
}
|
||||
});
|
||||
// Submit all the tool outputs at the same time
|
||||
await this.submitToolOutputs(toolOutputs, runId, threadId);
|
||||
} catch (error) {
|
||||
console.error("Error processing required action:", error);
|
||||
}
|
||||
}
|
||||
|
||||
async submitToolOutputs(toolOutputs, runId, threadId) {
|
||||
try {
|
||||
// Use the submitToolOutputsStream helper
|
||||
const stream = this.client.beta.threads.runs.submitToolOutputsStream(
|
||||
threadId,
|
||||
runId,
|
||||
{ tool_outputs: toolOutputs },
|
||||
);
|
||||
for await (const event of stream) {
|
||||
this.emit("event", event);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error submitting tool outputs:", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const eventHandler = new EventHandler(openai);
|
||||
eventHandler.on("event", eventHandler.onEvent.bind(eventHandler));
|
||||
|
||||
export const gptHandler = async (additionalMessages) => {
|
||||
const thread = await openai.beta.threads.create();
|
||||
|
||||
// Add the additional messages to the conversation
|
||||
for (const msgObj of additionalMessages) {
|
||||
await openai.beta.threads.messages.create(thread.id, msgObj);
|
||||
}
|
||||
|
||||
log.DEBUG("AI Conversation:", thread);
|
||||
|
||||
// Run the thread to get a response
|
||||
try {
|
||||
const thread = await openai.beta.threads.create();
|
||||
|
||||
for (const msgObj of additionalMessages) {
|
||||
await openai.beta.threads.messages.create(thread.id, msgObj);
|
||||
}
|
||||
|
||||
const stream = await openai.beta.threads.runs.stream(
|
||||
thread.id,
|
||||
{ assistant_id: assistant.id },
|
||||
@@ -236,8 +99,9 @@ export const gptHandler = async (additionalMessages) => {
|
||||
eventHandler.emit("event", event);
|
||||
}
|
||||
|
||||
let response;
|
||||
const messages = await openai.beta.threads.messages.list(thread.id);
|
||||
const response = messages.data[0].content[0].text.value;
|
||||
response = messages.data[0].content[0].text.value;
|
||||
|
||||
log.DEBUG("AI Response:", response);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user