anything-llm/server/utils/chats/index.js

143 lines
3.5 KiB
JavaScript
Raw Normal View History

2023-06-08 06:31:35 +02:00
const { v4: uuidv4 } = require("uuid");
const { OpenAi } = require("../openAi");
const { WorkspaceChats } = require("../../models/workspaceChats");
2023-06-04 04:28:07 +02:00
const { resetMemory } = require("./commands/reset");
2023-06-08 06:31:35 +02:00
const moment = require("moment");
const { getVectorDbClass } = require("../helpers");
2023-06-04 04:28:07 +02:00
function convertToChatHistory(history = []) {
2023-06-08 06:31:35 +02:00
const formattedHistory = [];
2023-06-04 04:28:07 +02:00
history.forEach((history) => {
2023-06-08 06:31:35 +02:00
const { prompt, response, createdAt } = history;
2023-06-04 04:28:07 +02:00
const data = JSON.parse(response);
formattedHistory.push([
{
2023-06-08 06:31:35 +02:00
role: "user",
2023-06-04 04:28:07 +02:00
content: prompt,
sentAt: moment(createdAt).unix(),
},
{
2023-06-08 06:31:35 +02:00
role: "assistant",
2023-06-04 04:28:07 +02:00
content: data.text,
sources: data.sources || [],
sentAt: moment(createdAt).unix(),
},
2023-06-08 06:31:35 +02:00
]);
});
2023-06-04 04:28:07 +02:00
2023-06-08 06:31:35 +02:00
return formattedHistory.flat();
2023-06-04 04:28:07 +02:00
}
function convertToPromptHistory(history = []) {
2023-06-08 06:31:35 +02:00
const formattedHistory = [];
2023-06-04 04:28:07 +02:00
history.forEach((history) => {
2023-06-08 06:31:35 +02:00
const { prompt, response } = history;
2023-06-04 04:28:07 +02:00
const data = JSON.parse(response);
formattedHistory.push([
2023-06-08 06:31:35 +02:00
{ role: "user", content: prompt },
{ role: "assistant", content: data.text },
]);
});
return formattedHistory.flat();
2023-06-04 04:28:07 +02:00
}
const VALID_COMMANDS = {
2023-06-08 06:31:35 +02:00
"/reset": resetMemory,
};
2023-06-04 04:28:07 +02:00
function grepCommand(message) {
const availableCommands = Object.keys(VALID_COMMANDS);
for (let i = 0; i < availableCommands.length; i++) {
const cmd = availableCommands[i];
const re = new RegExp(`^(${cmd})`, "i");
if (re.test(message)) {
return cmd;
}
}
2023-06-08 06:31:35 +02:00
return null;
2023-06-04 04:28:07 +02:00
}
2023-06-08 06:31:35 +02:00
async function chatWithWorkspace(workspace, message, chatMode = "query") {
2023-06-04 04:28:07 +02:00
const uuid = uuidv4();
const openai = new OpenAi();
2023-06-08 06:31:35 +02:00
const VectorDb = getVectorDbClass();
const command = grepCommand(message);
2023-06-04 04:28:07 +02:00
if (!!command && Object.keys(VALID_COMMANDS).includes(command)) {
return await VALID_COMMANDS[command](workspace, message, uuid);
}
2023-06-08 06:31:35 +02:00
const { safe, reasons = [] } = await openai.isSafe(message);
2023-06-04 04:28:07 +02:00
if (!safe) {
return {
id: uuid,
2023-06-08 06:31:35 +02:00
type: "abort",
2023-06-04 04:28:07 +02:00
textResponse: null,
sources: [],
close: true,
2023-06-08 06:31:35 +02:00
error: `This message was moderated and will not be allowed. Violations for ${reasons.join(
", "
)} found.`,
2023-06-04 04:28:07 +02:00
};
}
2023-06-08 06:31:35 +02:00
const hasVectorizedSpace = await VectorDb.hasNamespace(workspace.slug);
2023-06-04 04:28:07 +02:00
if (!hasVectorizedSpace) {
2023-06-08 06:31:35 +02:00
const rawHistory = await WorkspaceChats.forWorkspace(workspace.id);
2023-06-04 04:28:07 +02:00
const chatHistory = convertToPromptHistory(rawHistory);
const response = await openai.sendChat(chatHistory, message);
2023-06-08 06:31:35 +02:00
const data = { text: response, sources: [], type: "chat" };
2023-06-04 04:28:07 +02:00
2023-06-08 06:31:35 +02:00
await WorkspaceChats.new({
workspaceId: workspace.id,
prompt: message,
response: data,
});
2023-06-04 04:28:07 +02:00
return {
id: uuid,
2023-06-08 06:31:35 +02:00
type: "textResponse",
2023-06-04 04:28:07 +02:00
textResponse: response,
sources: [],
close: true,
error: null,
};
} else {
2023-06-08 06:31:35 +02:00
const {
response,
sources,
message: error,
} = await VectorDb[chatMode]({ namespace: workspace.slug, input: message });
2023-06-04 04:28:07 +02:00
if (!response) {
return {
id: uuid,
2023-06-08 06:31:35 +02:00
type: "abort",
2023-06-04 04:28:07 +02:00
textResponse: null,
sources: [],
close: true,
error,
};
}
2023-06-08 06:31:35 +02:00
const data = { text: response, sources, type: chatMode };
await WorkspaceChats.new({
workspaceId: workspace.id,
prompt: message,
response: data,
});
2023-06-04 04:28:07 +02:00
return {
id: uuid,
2023-06-08 06:31:35 +02:00
type: "textResponse",
2023-06-04 04:28:07 +02:00
textResponse: response,
sources,
close: true,
error,
};
}
}
module.exports = {
convertToChatHistory,
2023-06-08 06:31:35 +02:00
chatWithWorkspace,
};