anything-llm/server/utils/chats/index.js
AntonioCiolino 98d7266291
History per workspace (#126)
* Enable saving history value per workspace

* added history

* added history

* Changes re: the PR for message limits from history
2023-06-28 12:53:26 -07:00

152 lines
3.8 KiB
JavaScript

const { v4: uuidv4 } = require("uuid");
const { OpenAi } = require("../openAi");
const { WorkspaceChats } = require("../../models/workspaceChats");
const { resetMemory } = require("./commands/reset");
const moment = require("moment");
const { getVectorDbClass } = require("../helpers");
function convertToChatHistory(history = []) {
const formattedHistory = [];
history.forEach((history) => {
const { prompt, response, createdAt } = history;
const data = JSON.parse(response);
formattedHistory.push([
{
role: "user",
content: prompt,
sentAt: moment(createdAt).unix(),
},
{
role: "assistant",
content: data.text,
sources: data.sources || [],
sentAt: moment(createdAt).unix(),
},
]);
});
return formattedHistory.flat();
}
function convertToPromptHistory(history = []) {
const formattedHistory = [];
history.forEach((history) => {
const { prompt, response } = history;
const data = JSON.parse(response);
formattedHistory.push([
{ role: "user", content: prompt },
{ role: "assistant", content: data.text },
]);
});
return formattedHistory.flat();
}
const VALID_COMMANDS = {
"/reset": resetMemory,
};
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;
}
}
return null;
}
async function chatWithWorkspace(workspace, message, chatMode = "chat") {
const uuid = uuidv4();
const openai = new OpenAi();
const VectorDb = getVectorDbClass();
const command = grepCommand(message);
if (!!command && Object.keys(VALID_COMMANDS).includes(command)) {
return await VALID_COMMANDS[command](workspace, message, uuid);
}
const { safe, reasons = [] } = await openai.isSafe(message);
if (!safe) {
return {
id: uuid,
type: "abort",
textResponse: null,
sources: [],
close: true,
error: `This message was moderated and will not be allowed. Violations for ${reasons.join(
", "
)} found.`,
};
}
const hasVectorizedSpace = await VectorDb.hasNamespace(workspace.slug);
if (!hasVectorizedSpace) {
const rawHistory = await WorkspaceChats.forWorkspace(workspace.id);
const chatHistory = convertToPromptHistory(rawHistory);
const response = await openai.sendChat(chatHistory, message, workspace);
const data = { text: response, sources: [], type: "chat" };
await WorkspaceChats.new({
workspaceId: workspace.id,
prompt: message,
response: data,
});
return {
id: uuid,
type: "textResponse",
textResponse: response,
sources: [],
close: true,
error: null,
};
} else {
var messageLimit = workspace?.openAiHistory;
const rawHistory = await WorkspaceChats.forWorkspace(workspace.id, messageLimit);
const chatHistory = convertToPromptHistory(rawHistory);
const {
response,
sources,
message: error,
} = await VectorDb[chatMode]({
namespace: workspace.slug,
input: message,
workspace,
chatHistory,
});
if (!response) {
return {
id: uuid,
type: "abort",
textResponse: null,
sources: [],
close: true,
error,
};
}
const data = { text: response, sources, type: chatMode };
await WorkspaceChats.new({
workspaceId: workspace.id,
prompt: message,
response: data,
});
return {
id: uuid,
type: "textResponse",
textResponse: response,
sources,
close: true,
error,
};
}
}
module.exports = {
convertToChatHistory,
chatWithWorkspace,
};