mirror of
https://github.com/Mintplex-Labs/anything-llm.git
synced 2024-06-03 14:20:10 +02:00
9d41ff58e2
* add support for new openai models * QOL changes/improve logic for adding new openai embedding models * add example file inputs for Openai embedding ENV selection; * Fix if stmt conditional --------- Co-authored-by: timothycarambat <rambat1010@gmail.com>
235 lines
7.0 KiB
JavaScript
235 lines
7.0 KiB
JavaScript
import { ArrowsDownUp } from "@phosphor-icons/react";
|
|
import { useEffect, useState } from "react";
|
|
import Workspace from "../../../../models/workspace";
|
|
import System from "../../../../models/system";
|
|
import Directory from "./Directory";
|
|
import showToast from "../../../../utils/toast";
|
|
import WorkspaceDirectory from "./WorkspaceDirectory";
|
|
|
|
// OpenAI Cost per token
|
|
// ref: https://openai.com/pricing#:~:text=%C2%A0/%201K%20tokens-,Embedding%20models,-Build%20advanced%20search
|
|
|
|
const MODEL_COSTS = {
|
|
"text-embedding-ada-002": 0.0000001, // $0.0001 / 1K tokens
|
|
"text-embedding-3-small": 0.00000002, // $0.00002 / 1K tokens
|
|
"text-embedding-3-large": 0.00000013, // $0.00013 / 1K tokens
|
|
};
|
|
|
|
export default function DocumentSettings({
|
|
workspace,
|
|
fileTypes,
|
|
systemSettings,
|
|
}) {
|
|
const [highlightWorkspace, setHighlightWorkspace] = useState(false);
|
|
const [availableDocs, setAvailableDocs] = useState([]);
|
|
const [loading, setLoading] = useState(true);
|
|
const [workspaceDocs, setWorkspaceDocs] = useState([]);
|
|
const [selectedItems, setSelectedItems] = useState({});
|
|
const [hasChanges, setHasChanges] = useState(false);
|
|
const [movedItems, setMovedItems] = useState([]);
|
|
const [embeddingsCost, setEmbeddingsCost] = useState(0);
|
|
const [loadingMessage, setLoadingMessage] = useState("");
|
|
|
|
async function fetchKeys(refetchWorkspace = false) {
|
|
setLoading(true);
|
|
const localFiles = await System.localFiles();
|
|
const currentWorkspace = refetchWorkspace
|
|
? await Workspace.bySlug(workspace.slug)
|
|
: workspace;
|
|
|
|
const documentsInWorkspace =
|
|
currentWorkspace.documents.map((doc) => doc.docpath) || [];
|
|
|
|
// Documents that are not in the workspace
|
|
const availableDocs = {
|
|
...localFiles,
|
|
items: localFiles.items.map((folder) => {
|
|
if (folder.items && folder.type === "folder") {
|
|
return {
|
|
...folder,
|
|
items: folder.items.filter(
|
|
(file) =>
|
|
file.type === "file" &&
|
|
!documentsInWorkspace.includes(`${folder.name}/${file.name}`)
|
|
),
|
|
};
|
|
} else {
|
|
return folder;
|
|
}
|
|
}),
|
|
};
|
|
|
|
// Documents that are already in the workspace
|
|
const workspaceDocs = {
|
|
...localFiles,
|
|
items: localFiles.items.map((folder) => {
|
|
if (folder.items && folder.type === "folder") {
|
|
return {
|
|
...folder,
|
|
items: folder.items.filter(
|
|
(file) =>
|
|
file.type === "file" &&
|
|
documentsInWorkspace.includes(`${folder.name}/${file.name}`)
|
|
),
|
|
};
|
|
} else {
|
|
return folder;
|
|
}
|
|
}),
|
|
};
|
|
|
|
setAvailableDocs(availableDocs);
|
|
setWorkspaceDocs(workspaceDocs);
|
|
setLoading(false);
|
|
}
|
|
|
|
useEffect(() => {
|
|
fetchKeys();
|
|
}, []);
|
|
|
|
const updateWorkspace = async (e) => {
|
|
e.preventDefault();
|
|
setLoading(true);
|
|
showToast("Updating workspace...", "info", { autoClose: false });
|
|
setLoadingMessage("This may take a while for large documents");
|
|
|
|
const changesToSend = {
|
|
adds: movedItems.map((item) => `${item.folderName}/${item.name}`),
|
|
};
|
|
|
|
setSelectedItems({});
|
|
setHasChanges(false);
|
|
setHighlightWorkspace(false);
|
|
await Workspace.modifyEmbeddings(workspace.slug, changesToSend)
|
|
.then((res) => {
|
|
if (!!res.message) {
|
|
showToast(`Error: ${res.message}`, "error", { clear: true });
|
|
return;
|
|
}
|
|
showToast("Workspace updated successfully.", "success", {
|
|
clear: true,
|
|
});
|
|
})
|
|
.catch((error) => {
|
|
showToast(`Workspace update failed: ${error}`, "error", {
|
|
clear: true,
|
|
});
|
|
});
|
|
|
|
setMovedItems([]);
|
|
await fetchKeys(true);
|
|
setLoading(false);
|
|
setLoadingMessage("");
|
|
};
|
|
|
|
const moveSelectedItemsToWorkspace = () => {
|
|
setHighlightWorkspace(false);
|
|
setHasChanges(true);
|
|
|
|
const newMovedItems = [];
|
|
|
|
for (const itemId of Object.keys(selectedItems)) {
|
|
for (const folder of availableDocs.items) {
|
|
const foundItem = folder.items.find((file) => file.id === itemId);
|
|
if (foundItem) {
|
|
newMovedItems.push({ ...foundItem, folderName: folder.name });
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
let totalTokenCount = 0;
|
|
newMovedItems.forEach((item) => {
|
|
const { cached, token_count_estimate } = item;
|
|
if (!cached) {
|
|
totalTokenCount += token_count_estimate;
|
|
}
|
|
});
|
|
|
|
// Do not do cost estimation unless the embedding engine is OpenAi.
|
|
if (systemSettings?.EmbeddingEngine === "openai") {
|
|
const COST_PER_TOKEN =
|
|
MODEL_COSTS[
|
|
systemSettings?.EmbeddingModelPref || "text-embedding-ada-002"
|
|
];
|
|
|
|
const dollarAmount = (totalTokenCount / 1000) * COST_PER_TOKEN;
|
|
setEmbeddingsCost(dollarAmount);
|
|
}
|
|
|
|
setMovedItems([...movedItems, ...newMovedItems]);
|
|
|
|
let newAvailableDocs = JSON.parse(JSON.stringify(availableDocs));
|
|
let newWorkspaceDocs = JSON.parse(JSON.stringify(workspaceDocs));
|
|
|
|
for (const itemId of Object.keys(selectedItems)) {
|
|
let foundItem = null;
|
|
let foundFolderIndex = null;
|
|
|
|
newAvailableDocs.items = newAvailableDocs.items.map(
|
|
(folder, folderIndex) => {
|
|
const remainingItems = folder.items.filter((file) => {
|
|
const match = file.id === itemId;
|
|
if (match) {
|
|
foundItem = { ...file };
|
|
foundFolderIndex = folderIndex;
|
|
}
|
|
return !match;
|
|
});
|
|
|
|
return {
|
|
...folder,
|
|
items: remainingItems,
|
|
};
|
|
}
|
|
);
|
|
|
|
if (foundItem) {
|
|
newWorkspaceDocs.items[foundFolderIndex].items.push(foundItem);
|
|
}
|
|
}
|
|
|
|
setAvailableDocs(newAvailableDocs);
|
|
setWorkspaceDocs(newWorkspaceDocs);
|
|
setSelectedItems({});
|
|
};
|
|
|
|
return (
|
|
<div className="flex gap-x-6 justify-center">
|
|
<Directory
|
|
files={availableDocs}
|
|
loading={loading}
|
|
loadingMessage={loadingMessage}
|
|
setLoading={setLoading}
|
|
fileTypes={fileTypes}
|
|
workspace={workspace}
|
|
fetchKeys={fetchKeys}
|
|
selectedItems={selectedItems}
|
|
setSelectedItems={setSelectedItems}
|
|
updateWorkspace={updateWorkspace}
|
|
highlightWorkspace={highlightWorkspace}
|
|
setHighlightWorkspace={setHighlightWorkspace}
|
|
moveToWorkspace={moveSelectedItemsToWorkspace}
|
|
setLoadingMessage={setLoadingMessage}
|
|
/>
|
|
<div className="flex items-center">
|
|
<ArrowsDownUp className="text-white text-base font-bold rotate-90 w-11 h-11" />
|
|
</div>
|
|
<WorkspaceDirectory
|
|
workspace={workspace}
|
|
files={workspaceDocs}
|
|
highlightWorkspace={highlightWorkspace}
|
|
loading={loading}
|
|
loadingMessage={loadingMessage}
|
|
setLoadingMessage={setLoadingMessage}
|
|
setLoading={setLoading}
|
|
fetchKeys={fetchKeys}
|
|
hasChanges={hasChanges}
|
|
saveChanges={updateWorkspace}
|
|
embeddingCosts={embeddingsCost}
|
|
movedItems={movedItems}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|