From 6e8d81c01efbeeb4e373c23a9bb0268d43c3616d Mon Sep 17 00:00:00 2001 From: Timothy Carambat <rambat1010@gmail.com> Date: Thu, 3 Aug 2023 15:59:51 -0700 Subject: [PATCH] better vector db selection UI on settings (#175) update logout button --- .../Modals/Settings/VectorDbs/index.jsx | 232 ++++++++++++++++++ .../src/components/Modals/Settings/index.jsx | 39 +-- frontend/src/components/Sidebar/index.jsx | 27 ++ frontend/src/media/vectordbs/chroma.png | Bin 0 -> 2006 bytes frontend/src/media/vectordbs/lancedb.png | Bin 0 -> 1896 bytes frontend/src/media/vectordbs/pinecone.png | Bin 0 -> 2166 bytes server/utils/helpers/updateENV.js | 4 +- 7 files changed, 274 insertions(+), 28 deletions(-) create mode 100644 frontend/src/components/Modals/Settings/VectorDbs/index.jsx create mode 100644 frontend/src/media/vectordbs/chroma.png create mode 100644 frontend/src/media/vectordbs/lancedb.png create mode 100644 frontend/src/media/vectordbs/pinecone.png diff --git a/frontend/src/components/Modals/Settings/VectorDbs/index.jsx b/frontend/src/components/Modals/Settings/VectorDbs/index.jsx new file mode 100644 index 000000000..0c4f5a386 --- /dev/null +++ b/frontend/src/components/Modals/Settings/VectorDbs/index.jsx @@ -0,0 +1,232 @@ +import React, { useState } from "react"; +import System from "../../../../models/system"; +import ChromaLogo from "../../../../media/vectordbs/chroma.png"; +import PineconeLogo from "../../../../media/vectordbs/pinecone.png"; +import LanceDbLogo from "../../../../media/vectordbs/lancedb.png"; + +const noop = () => false; +export default function VectorDBSelection({ + hideModal = noop, + user, + settings = {}, +}) { + const [hasChanges, setHasChanges] = useState(false); + const [vectorDB, setVectorDB] = useState(settings?.VectorDB || "lancedb"); + const [saving, setSaving] = useState(false); + const [error, setError] = useState(null); + const canDebug = settings.MultiUserMode + ? settings?.CanDebug && user?.role === "admin" + : settings?.CanDebug; + + function updateVectorChoice(selection) { + if (!canDebug || selection === vectorDB) return false; + setHasChanges(true); + setVectorDB(selection); + } + + const handleSubmit = async (e) => { + e.preventDefault(); + setSaving(true); + setError(null); + const data = {}; + const form = new FormData(e.target); + for (var [key, value] of form.entries()) data[key] = value; + const { error } = await System.updateSystem(data); + setError(error); + setSaving(false); + setHasChanges(!!error ? true : false); + }; + return ( + <div className="relative w-full max-w-2xl max-h-full"> + <div className="relative bg-white rounded-lg shadow dark:bg-stone-700"> + <div className="flex items-start justify-between px-6 py-4"> + <p className="text-gray-800 dark:text-stone-200 text-base "> + These are the credentials and settings for how your AnythingLLM + instance will function. Its important these keys are current and + correct. + </p> + </div> + + {!!error && ( + <div className="mb-8 bg-red-700 dark:bg-orange-800 bg-opacity-30 border border-red-800 dark:border-orange-600 p-4 rounded-lg w-[90%] flex mx-auto"> + <p className="text-red-800 dark:text-orange-300 text-sm">{error}</p> + </div> + )} + + <form onSubmit={handleSubmit} onChange={() => setHasChanges(true)}> + <div className="px-6 space-y-6 flex h-full w-full"> + <div className="w-full flex flex-col gap-y-4"> + <p className="block text-sm font-medium text-gray-800 dark:text-slate-200"> + Vector database provider + </p> + <div className="w-full flex overflow-x-scroll gap-x-4 no-scroll"> + <input hidden={true} name="VectorDB" value={vectorDB} /> + <VectorDBOption + name="Chroma" + value="chroma" + link="trychroma.com" + description="Open source vector database you can host yourself or on the cloud." + checked={vectorDB === "chroma"} + image={ChromaLogo} + onClick={updateVectorChoice} + /> + <VectorDBOption + name="Pinecone" + value="pinecone" + link="pinecone.io" + description="100% cloud-based vector database for enterprise use cases." + checked={vectorDB === "pinecone"} + image={PineconeLogo} + onClick={updateVectorChoice} + /> + <VectorDBOption + name="LanceDB" + value="lancedb" + link="lancedb.com" + description="100% local vector DB that runs on the same instance as AnythingLLM." + checked={vectorDB === "lancedb"} + image={LanceDbLogo} + onClick={updateVectorChoice} + /> + </div> + {vectorDB === "pinecone" && ( + <> + <div> + <label className="block mb-2 text-sm font-medium text-gray-800 dark:text-slate-200"> + Pinecone DB API Key + </label> + <input + type="text" + name="PineConeKey" + disabled={!canDebug} + className="bg-gray-50 border border-gray-500 text-gray-900 placeholder-gray-500 text-sm rounded-lg dark:bg-stone-700 focus:border-stone-500 block w-full p-2.5 dark:text-slate-200 dark:placeholder-stone-500 dark:border-slate-200" + placeholder="Pinecone API Key" + defaultValue={settings?.PineConeKey ? "*".repeat(20) : ""} + required={true} + autoComplete="off" + spellCheck={false} + /> + </div> + + <div> + <label className="block mb-2 text-sm font-medium text-gray-800 dark:text-slate-200"> + Pinecone Index Environment + </label> + <input + type="text" + name="PineConeEnvironment" + disabled={!canDebug} + className="bg-gray-50 border border-gray-500 text-gray-900 placeholder-gray-500 text-sm rounded-lg dark:bg-stone-700 focus:border-stone-500 block w-full p-2.5 dark:text-slate-200 dark:placeholder-stone-500 dark:border-slate-200" + placeholder="us-gcp-west-1" + defaultValue={settings?.PineConeEnvironment} + required={true} + autoComplete="off" + spellCheck={false} + /> + </div> + + <div> + <label className="block mb-2 text-sm font-medium text-gray-800 dark:text-slate-200"> + Pinecone Index Name + </label> + <input + type="text" + name="PineConeIndex" + disabled={!canDebug} + className="bg-gray-50 border border-gray-500 text-gray-900 placeholder-gray-500 text-sm rounded-lg dark:bg-stone-700 focus:border-stone-500 block w-full p-2.5 dark:text-slate-200 dark:placeholder-stone-500 dark:border-slate-200" + placeholder="my-index" + defaultValue={settings?.PineConeIndex} + required={true} + autoComplete="off" + spellCheck={false} + /> + </div> + </> + )} + + {vectorDB === "chroma" && ( + <> + <div> + <label className="block mb-2 text-sm font-medium text-gray-800 dark:text-slate-200"> + Chroma Endpoint + </label> + <input + type="url" + name="ChromaEndpoint" + disabled={!canDebug} + className="bg-gray-50 border border-gray-500 text-gray-900 placeholder-gray-500 text-sm rounded-lg dark:bg-stone-700 focus:border-stone-500 block w-full p-2.5 dark:text-slate-200 dark:placeholder-stone-500 dark:border-slate-200" + placeholder="http://localhost:8000" + defaultValue={settings?.ChromaEndpoint} + required={true} + autoComplete="off" + spellCheck={false} + /> + </div> + </> + )} + {vectorDB === "lancedb" && ( + <div className="w-full h-40 items-center justify-center flex"> + <p className="text-gray-800 dark:text-slate-400"> + There is no configuration needed for LanceDB. + </p> + </div> + )} + </div> + </div> + <div className="w-full p-4"> + <button + hidden={!hasChanges} + disabled={saving} + type="submit" + className="w-full text-gray-500 bg-white hover:bg-gray-100 focus:ring-4 focus:outline-none focus:ring-blue-300 rounded-lg border border-gray-200 text-sm font-medium px-5 py-2.5 hover:text-gray-900 focus:z-10 dark:bg-gray-700 dark:text-gray-300 dark:border-gray-500 dark:hover:text-white dark:hover:bg-gray-600 dark:focus:ring-gray-600" + > + {saving ? "Saving..." : "Save changes"} + </button> + </div> + </form> + <div className="flex items-center p-6 space-x-2 border-t border-gray-200 rounded-b dark:border-gray-600"> + <button + onClick={hideModal} + type="button" + className="text-gray-500 bg-white hover:bg-gray-100 focus:ring-4 focus:outline-none focus:ring-blue-300 rounded-lg border border-gray-200 text-sm font-medium px-5 py-2.5 hover:text-gray-900 focus:z-10 dark:bg-gray-700 dark:text-gray-300 dark:border-gray-500 dark:hover:text-white dark:hover:bg-gray-600 dark:focus:ring-gray-600" + > + Close + </button> + </div> + </div> + </div> + ); +} + +const VectorDBOption = ({ + name, + link, + description, + value, + image, + checked = false, + onClick, +}) => { + return ( + <div onClick={() => onClick(value)}> + <input + type="checkbox" + value={value} + className="peer hidden" + checked={checked} + readOnly={true} + formNoValidate={true} + /> + <label className="transition-all duration-300 inline-flex h-full w-60 cursor-pointer items-center justify-between rounded-lg border border-gray-200 bg-white p-5 text-gray-500 hover:bg-gray-50 hover:text-gray-600 peer-checked:border-blue-600 peer-checked:bg-blue-50 peer-checked:dark:bg-stone-800 peer-checked:text-gray-600 dark:border-slate-200 dark:bg-stone-800 dark:text-slate-400 dark:hover:bg-stone-700 dark:hover:text-slate-300 dark:peer-checked:text-slate-300"> + <div className="block"> + <img src={image} alt={name} className="mb-2 h-10 w-10 rounded-full" /> + <div className="w-full text-lg font-semibold">{name}</div> + <div className="flex w-full flex-col gap-y-1 text-sm"> + <p className="text-xs text-slate-400">{link}</p> + {description} + </div> + </div> + </label> + </div> + ); +}; diff --git a/frontend/src/components/Modals/Settings/index.jsx b/frontend/src/components/Modals/Settings/index.jsx index 9d02d94e8..a9ce6de2c 100644 --- a/frontend/src/components/Modals/Settings/index.jsx +++ b/frontend/src/components/Modals/Settings/index.jsx @@ -1,26 +1,27 @@ import React, { useEffect, useState } from "react"; -import { Archive, Lock, Key, X, Users, LogOut } from "react-feather"; +import { Archive, Lock, Key, X, Users, Database } from "react-feather"; import SystemKeys from "./Keys"; import ExportOrImportData from "./ExportImport"; import PasswordProtection from "./PasswordProtection"; import System from "../../../models/system"; import MultiUserMode from "./MultiUserMode"; -import { AUTH_TOKEN, AUTH_USER } from "../../../utils/constants"; -import paths from "../../../utils/paths"; import useUser from "../../../hooks/useUser"; +import VectorDBSelection from "./VectorDbs"; const TABS = { keys: SystemKeys, exportimport: ExportOrImportData, password: PasswordProtection, multiuser: MultiUserMode, + vectordb: VectorDBSelection, }; const noop = () => false; export default function SystemSettingsModal({ hideModal = noop }) { const { user } = useUser(); const [loading, setLoading] = useState(true); - const [selectedTab, setSelectedTab] = useState("keys"); + // const [selectedTab, setSelectedTab] = useState("keys"); + const [selectedTab, setSelectedTab] = useState("vectordb"); const [settings, setSettings] = useState(null); const Component = TABS[selectedTab || "keys"]; @@ -93,6 +94,13 @@ function SettingTabs({ selectedTab, changeTab, settings, user }) { icon={<Key className="h-4 w-4 flex-shrink-0" />} onClick={changeTab} /> + <SettingTab + active={selectedTab === "vectordb"} + displayName="Vector Database" + tabName="vectordb" + icon={<Database className="h-4 w-4 flex-shrink-0" />} + onClick={changeTab} + /> <SettingTab active={selectedTab === "exportimport"} displayName="Export or Import" @@ -100,7 +108,7 @@ function SettingTabs({ selectedTab, changeTab, settings, user }) { icon={<Archive className="h-4 w-4 flex-shrink-0" />} onClick={changeTab} /> - {!settings?.MultiUserMode ? ( + {!settings?.MultiUserMode && ( <> <SettingTab active={selectedTab === "multiuser"} @@ -117,8 +125,6 @@ function SettingTabs({ selectedTab, changeTab, settings, user }) { onClick={changeTab} /> </> - ) : ( - <LogoutTab user={user} /> )} </ul> ); @@ -150,25 +156,6 @@ function SettingTab({ ); } -function LogoutTab({ user }) { - if (!user) return null; - - return ( - <li className="mr-2"> - <button - onClick={() => { - window.localStorage.removeItem(AUTH_USER); - window.localStorage.removeItem(AUTH_TOKEN); - window.location.replace(paths.home()); - }} - className="flex items-center gap-x-1 p-4 border-b-2 rounded-t-lg group whitespace-nowrap border-transparent hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300" - > - <LogOut className="h-4 w-4 flex-shrink-0" /> Log out of {user.username} - </button> - </li> - ); -} - export function useSystemSettingsModal() { const [showing, setShowing] = useState(false); const showModal = () => { diff --git a/frontend/src/components/Sidebar/index.jsx b/frontend/src/components/Sidebar/index.jsx index 3b67abf39..8f453ca7b 100644 --- a/frontend/src/components/Sidebar/index.jsx +++ b/frontend/src/components/Sidebar/index.jsx @@ -4,6 +4,7 @@ import { Briefcase, Cpu, GitHub, + LogOut, Menu, Plus, Shield, @@ -21,6 +22,8 @@ import ActiveWorkspaces from "./ActiveWorkspaces"; import paths from "../../utils/paths"; import Discord from "../Icons/Discord"; import useUser from "../../hooks/useUser"; +import { userFromStorage } from "../../utils/request"; +import { AUTH_TOKEN, AUTH_USER } from "../../utils/constants"; export default function Sidebar() { const sidebarRef = useRef(null); @@ -103,6 +106,7 @@ export default function Sidebar() { Enterprise Installation </p> </a> + <LogoutButton /> </div> {/* Footer */} @@ -269,6 +273,7 @@ export function SidebarMobileHeader() { Enterprise Installation </p> </a> + <LogoutButton /> </div> {/* Footer */} @@ -325,3 +330,25 @@ function AdminHome() { </a> ); } + +function LogoutButton() { + if (!window.localStorage.getItem(AUTH_USER)) return null; + const user = userFromStorage(); + if (!user.username) return null; + + return ( + <button + onClick={() => { + window.localStorage.removeItem(AUTH_USER); + window.localStorage.removeItem(AUTH_TOKEN); + window.location.replace(paths.home()); + }} + className="flex flex-grow w-[100%] h-[36px] gap-x-2 py-[5px] px-4 border border-slate-400 dark:border-transparent rounded-lg text-slate-800 dark:text-slate-200 justify-center items-center hover:bg-slate-100 dark:bg-stone-800 dark:hover:bg-stone-900" + > + <LogOut className="h-4 w-4" /> + <p className="text-slate-800 dark:text-slate-200 text-xs leading-loose font-semibold"> + Log out of {user.username} + </p> + </button> + ); +} diff --git a/frontend/src/media/vectordbs/chroma.png b/frontend/src/media/vectordbs/chroma.png new file mode 100644 index 0000000000000000000000000000000000000000..fde25384d5592fe9d5eb441be28e0ccda5332d82 GIT binary patch literal 2006 zcmb7_`!|#e7ssEoy1ga5E2|tTr8o7CP|2l?@*)jSu7i^yDH)n>8Ya`AsKgP<nI2<^ zk<5%F_e+N4oNhFuWRBZlILU3~l3|QX&VJ{d|KRMk_S$=Y*82Xi*LSVG6Wv`2>g#mZ zAqb-G<am^bAU~jg<-b;_h_iCoQdL%l*t*yvNZEb0?`Kx2<{!d|1Usbo;})4}*nZZL z=z<`TyAUKc4nY=GD0UP<uI@vSvC{}*#YPbAD_ON3)+(L3yR(-A0LYclH3H==z<USm zmylEqF~uP22lzS)U9Ip|0Ch!B_82%xz)ys+Xc$j~Nfvy|14TV3MX)R%ngTKhY~sQ6 z2KcZbj1Mp%g_{%zItJnP&}R&PSix{0EDbr|gYu66idjga!DSB^AV6A7QbsQ<Pd9Xe z&GlJ+XgbJC$=6zkLj0YhMkN%A52F`GLt|*Q8Pq(<2*5&Ta(HnJO;CP0srdqp!~&j5 zve4B<p@c=e^<hY1&^sx-m`#1$&;bx-3%C9U%)^jt1qBD8;Q%z6LIxgc%%No;3^+Ec z)-1JvDHcrUC07H#5g_*v{DIGC0O;HccWLk`7-mWVi-o#kh^4?luRJGxWzU-c1X-=+ zbkx@CTGoU#%5Ss7kMUIE_FOFR)o;jS+M&t~8><36tRFq`{#v%~r#*LnUR<`h758Zq zb3C{&VbWx3a(T(7bCuE@UvWUP)81ZX(?1W4Fx366>0DKZg_V_cgz>m{XJe>yZ&p@x z?x|2`mzL(2?8*LX3iE`*@EJAfDc>zR$0OTCS`SK$vIQHnNv9~y&w>^7fc<G@W4>;0 z^M|!VEtl%YKE5gZdVIv%h4Iuo=lx=TQ@>9U-7Mna*J6g4S|EChO|+77K8)B131r%p z#(Uj@J=eciDJD~|6RR7CX{6%WU~{vekaH2I%=->(KkLbPlCB?I5j=YB{6xgXrY_9j zXPq0A9A)ImrZ~*QOmVCaE@fJ5=ot42eYtV7>3(usBz_7k&C?w82VY6)8_->Rqe<^0 z{PpkeaP<%EBexk2ULSt4A#6rE$h=MDG_x7d-{Mbp#WD6y4``q|mo{EhP*81U)NQ+X zZnE#4%zahNDNPd{X1TlZ^R$QWA2Drlc|)3VlW#A$KBh+GGroNK)iwFaEH!G%1p}M) zdvr3(|2;!?Fl1Pk23-+883K-Dx6x&d7ddA6$<=ZbDoLytqF=++C!1x{lSC30s?kMH z!u_Xn%Ilog5aF|d3(nsyeOPOz`dgxyZF+uCYH!KMPR@6^i&^4n0~7x~rIA4j&X1w( zk>Yq;9LDhTj67W5R(*(N-pC1)j0hjh8S|Lpk<yE(LCS4$mUyVNImkWJvvv!M)Qs7o z39rL^bTNEEKCNaW9K{JJ#yIZD_jSo>)uU_+t3Z_Q$9am0YeyY%^~TmRPIiDHuR{8z z+U&nJA9j)}AJVsKU0PZuS>Uc0eHLrk%_;nj%Py#=>+P7g&cj5E&azJ*qwf?DQQ7(O zHoh?X88I@`sHzUl<+92-^ld9B?F&09Fy+kT+3iJEuheVV;?`PE57Z<&gCuNfvF)kG z<b~tJMaDDZ+scN$>Ef2ppE`-cY!zBylaB2k<?iI&oD0soV#4LmR!H9utW7_l$;EDH zh^y32q6;aQxMh{AaAa7RKReSJJh90iT_{p9<J!4hHJBWa<K<KYOdPaF7wT1%8XwWL zi}&3YCmT(5i8}3wF61%Azx&-2CpdF4)ak@Ft6!?|C^~VfspX}I^^!O72u55KXzPkQ zwi*n%p-ygv_vTo6OnHa_FW;N+(C7}<ElABTApYHX$wErP(Q97bjyUO~sUhh*$AgY7 zgECoDr$4#p#wJ|VS$&((TRCMVpXV^~;)LvGuEvt?WmnRy*6eP>;W}ElFaTrrZOXQo zdG%m%w}abZVO`R%)<#7*o~<mjl~SQ0!fd>z=<eMKy!|{2mAlyRnT#>z{j3G^sa=LW zldUXb<nC8r<kB-eayD_(^752k120X^s%)K})qilAU-G<y+t#tA)8=%r;Eg)&IMr1$ zLDj{HXvZ0@^V)6kF}NZ#k6O6p`<kYcMa1Ljhdm-z#)$mSp|Zq1B|TY5nKw5#{fafD zKM(q*xh;-|p?U`cUgWI3po5hU8mt%*rDD97wRk(<)m)?Y-+Z%T14Ns@e<5{;7p$sL z8<RJZJ&&YLHcO|di#oGW>=i_GY4UJm<9Vmm-+M2~-2za*tfB$`UbpqT)tkAPCV0hj zb2L-d8m>JM94&m^5SO~<{$2b|{6LAk221#2Z%>HoU^*-ddejC2=iDS3l8DMconKN+ z<1St}GHDqy=Op-3IbU(&Lx-SpNm8O17ex{E^!f$!kK1E&8SZ;Wm))2t-M-O61?S$@ zLW19#>8*Y#5~6xjc;@DI!2$;ZXFYg0`&1$;TB^^Z@~B>{wWdFjW6lOu`W7x*9%9VQ zznfQ-o|yQk=i<`dqwD!Qp^m&Y`JbO-)u#<x+?KMVhw$f*S0DeScXDt&T5Nav*8c&E C(+X$+ literal 0 HcmV?d00001 diff --git a/frontend/src/media/vectordbs/lancedb.png b/frontend/src/media/vectordbs/lancedb.png new file mode 100644 index 0000000000000000000000000000000000000000..dc653484dcdc1c842d75fdd402c4470475a9d1a1 GIT binary patch literal 1896 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 literal 0 HcmV?d00001 diff --git a/frontend/src/media/vectordbs/pinecone.png b/frontend/src/media/vectordbs/pinecone.png new file mode 100644 index 0000000000000000000000000000000000000000..9f20d7f7f140387b65a82720f811a900e80cc503 GIT binary patch literal 2166 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 literal 0 HcmV?d00001 diff --git a/server/utils/helpers/updateENV.js b/server/utils/helpers/updateENV.js index 54eec1e5b..0ff95fa49 100644 --- a/server/utils/helpers/updateENV.js +++ b/server/utils/helpers/updateENV.js @@ -92,8 +92,8 @@ function validChromaURL(input = "") { function updateENV(newENVs = {}) { let error = ""; const validKeys = Object.keys(KEY_MAPPING); - const ENV_KEYS = Object.keys(newENVs).filter((key) => - validKeys.includes(key) + const ENV_KEYS = Object.keys(newENVs).filter( + (key) => validKeys.includes(key) && !newENVs[key].includes("******") // strip out answers where the value is all asterisks ); const newValues = {}; -- GitLab