-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fine tuning order flow (cloud-based) (#1923)
* WIP fine-tuning order flow * flow patches and typo * Refine steps add fine tuning CTA on chat page add fine tuning banner and validation endpoints add finetuning banner on relevant pages with perms check * Add prod firebase url
- Loading branch information
1 parent
d0713e1
commit f8e54b2
Showing
24 changed files
with
2,172 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,7 @@ | |
"comkey", | ||
"cooldown", | ||
"cooldowns", | ||
"datafile", | ||
"Deduplicator", | ||
"Dockerized", | ||
"docpath", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -68,4 +68,4 @@ | |
"tailwindcss": "^3.3.1", | ||
"vite": "^4.3.0" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
import { API_BASE } from "@/utils/constants"; | ||
import { baseHeaders, safeJsonParse } from "@/utils/request"; | ||
|
||
const FineTuning = { | ||
cacheKeys: { | ||
dismissed_cta: "anythingllm_dismissed_fine_tune_notif", | ||
eligibility: "anythingllm_can_fine_tune", | ||
}, | ||
|
||
/** | ||
* Get the information for the Fine-tuning product to display in various frontends | ||
* @returns {Promise<{ | ||
* productDetails: { | ||
* name: string, | ||
* description: string, | ||
* icon: string, | ||
* active: boolean, | ||
* }, | ||
* pricing: { | ||
* usd: number, | ||
* }, | ||
* availableBaseModels: string[] | ||
* }>} | ||
*/ | ||
info: async function () { | ||
return await fetch(`${API_BASE}/experimental/fine-tuning/info`, { | ||
method: "GET", | ||
headers: baseHeaders(), | ||
}) | ||
.then((res) => { | ||
if (!res.ok) throw new Error("Could not get model info."); | ||
return res.json(); | ||
}) | ||
.then((res) => res) | ||
.catch((e) => { | ||
console.error(e); | ||
return null; | ||
}); | ||
}, | ||
datasetStat: async function ({ slugs = [], feedback = null }) { | ||
return await fetch(`${API_BASE}/experimental/fine-tuning/dataset`, { | ||
method: "POST", | ||
headers: baseHeaders(), | ||
body: JSON.stringify({ slugs, feedback }), | ||
}) | ||
.then((res) => { | ||
if (!res.ok) throw new Error("Could not get dataset info."); | ||
return res.json(); | ||
}) | ||
.then((res) => res) | ||
.catch((e) => { | ||
console.error(e); | ||
return { count: null }; | ||
}); | ||
}, | ||
/** | ||
* Generates Fine-Tuning order. | ||
* @param {{email:string, baseModel:string, modelName: string, trainingData: {slugs:string[], feedback:boolean|null}}} param0 | ||
* @returns {Promise<{checkoutUrl:string, jobId:string}|null>} | ||
*/ | ||
createOrder: async function ({ email, baseModel, modelName, trainingData }) { | ||
return await fetch(`${API_BASE}/experimental/fine-tuning/order`, { | ||
method: "POST", | ||
headers: baseHeaders(), | ||
body: JSON.stringify({ | ||
email, | ||
baseModel, | ||
modelName, | ||
trainingData, | ||
}), | ||
}) | ||
.then((res) => { | ||
if (!res.ok) throw new Error("Could not order fine-tune."); | ||
return res.json(); | ||
}) | ||
.then((res) => res) | ||
.catch((e) => { | ||
console.error(e); | ||
return null; | ||
}); | ||
}, | ||
|
||
/** | ||
* Determine if a user should see the CTA alert. In general this alert | ||
* Can only render if the user is empty (single user) or is an admin role. | ||
* @returns {boolean} | ||
*/ | ||
canAlert: function (user = null) { | ||
if (!!user && user.role !== "admin") return false; | ||
return !window?.localStorage?.getItem(this.cacheKeys.dismissed_cta); | ||
}, | ||
checkEligibility: async function () { | ||
const cache = window.localStorage.getItem(this.cacheKeys.eligibility); | ||
if (!!cache) { | ||
const { data, lastFetched } = safeJsonParse(cache, { | ||
data: null, | ||
lastFetched: 0, | ||
}); | ||
if (!!data && Date.now() - lastFetched < 1.8e7) | ||
// 5 hours | ||
return data.eligible; | ||
} | ||
|
||
return await fetch(`${API_BASE}/experimental/fine-tuning/check-eligible`, { | ||
method: "GET", | ||
headers: baseHeaders(), | ||
}) | ||
.then((res) => { | ||
if (!res.ok) throw new Error("Could not check if eligible."); | ||
return res.json(); | ||
}) | ||
.then((res) => { | ||
window.localStorage.setItem( | ||
this.cacheKeys.eligibility, | ||
JSON.stringify({ | ||
data: { eligible: res.eligible }, | ||
lastFetched: Date.now(), | ||
}) | ||
); | ||
return res.eligible; | ||
}) | ||
.catch((e) => { | ||
console.error(e); | ||
return false; | ||
}); | ||
}, | ||
}; | ||
|
||
export default FineTuning; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { useEffect, useState } from "react"; | ||
import useUser from "@/hooks/useUser"; | ||
import FineTuning from "@/models/experimental/fineTuning"; | ||
import { createPortal } from "react-dom"; | ||
import { Sparkle } from "@phosphor-icons/react"; | ||
import { Link, useLocation } from "react-router-dom"; | ||
import paths from "@/utils/paths"; | ||
|
||
export function FineTuningAlert() { | ||
const { user } = useUser(); | ||
const location = useLocation(); | ||
const [className, setClassName] = useState("top-banner"); | ||
const [isEligible, setIsEligible] = useState(false); | ||
|
||
function dismissAlert() { | ||
setClassName("rm-top-banner"); | ||
window?.localStorage?.setItem(FineTuning.cacheKeys.dismissed_cta, "1"); | ||
setTimeout(() => { | ||
setIsEligible(false); | ||
}, 550); | ||
} | ||
|
||
useEffect(() => { | ||
if (!FineTuning.canAlert(user)) return; | ||
if ( | ||
location.pathname === paths.orderFineTune() || | ||
location.pathname === paths.settings.chats() | ||
) | ||
return; | ||
FineTuning.checkEligibility() | ||
.then((eligible) => setIsEligible(eligible)) | ||
.catch(() => null); | ||
}, [user]); | ||
|
||
if (!isEligible) return null; | ||
return createPortal( | ||
<div | ||
className={`fixed ${className} left-0 right-0 h-14 bg-orange-400 flex items-center justify-end px-4 z-[9999]`} | ||
> | ||
<Link | ||
onClick={dismissAlert} | ||
to={paths.orderFineTune()} | ||
className="grow w-full h-full ml-4 py-1" | ||
> | ||
<div className="flex flex-col items-center w-full"> | ||
<div className="flex w-full justify-center items-center gap-x-2"> | ||
<Sparkle size={20} className="text-white" /> | ||
<p className="text-white font-medium text-lg"> | ||
You have enough data for a fine-tune! | ||
</p> | ||
</div> | ||
<p className="text-xs text-white">click to learn more →</p> | ||
</div> | ||
</Link> | ||
<div className="flex items-center gap-x-2 shrink-0"> | ||
<button | ||
onClick={dismissAlert} | ||
className="border-none text-white font-medium text-sm px-[10px] py-[6px] rounded-md bg-white/5 hover:bg-white/10" | ||
> | ||
Dismiss | ||
</button> | ||
</div> | ||
</div>, | ||
document.getElementById("root") | ||
); | ||
} |
Oops, something went wrong.