fix: model recommendation label is not based on VRAM (#2517)

This commit is contained in:
Louis 2024-03-27 18:21:33 +07:00 committed by GitHub
parent fe730fbe42
commit 784af8cf55
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 56 additions and 11 deletions

View File

@ -10,9 +10,9 @@ import {
} from '@janhq/uikit' } from '@janhq/uikit'
import { InfoIcon } from 'lucide-react' import { InfoIcon } from 'lucide-react'
const NotEnoughRamLabel: React.FC = () => ( const NotEnoughMemoryLabel = ({ unit }: { unit: string }) => (
<Badge className="space-x-1 rounded-md" themes="danger"> <Badge className="space-x-1 rounded-md" themes="danger">
<span>Not enough RAM</span> <span>Not enough {unit}</span>
<Tooltip> <Tooltip>
<TooltipTrigger> <TooltipTrigger>
<InfoIcon size={16} /> <InfoIcon size={16} />
@ -31,4 +31,4 @@ const NotEnoughRamLabel: React.FC = () => (
</Badge> </Badge>
) )
export default React.memo(NotEnoughRamLabel) export default React.memo(NotEnoughMemoryLabel)

View File

@ -4,13 +4,19 @@ import { useAtomValue } from 'jotai'
import { useActiveModel } from '@/hooks/useActiveModel' import { useActiveModel } from '@/hooks/useActiveModel'
import NotEnoughRamLabel from './NotEnoughRamLabel' import { useSettings } from '@/hooks/useSettings'
import NotEnoughMemoryLabel from './NotEnoughMemoryLabel'
import RecommendedLabel from './RecommendedLabel' import RecommendedLabel from './RecommendedLabel'
import SlowOnYourDeviceLabel from './SlowOnYourDeviceLabel' import SlowOnYourDeviceLabel from './SlowOnYourDeviceLabel'
import { totalRamAtom, usedRamAtom } from '@/helpers/atoms/SystemBar.atom' import {
availableVramAtom,
totalRamAtom,
usedRamAtom,
} from '@/helpers/atoms/SystemBar.atom'
type Props = { type Props = {
size: number size: number
@ -20,12 +26,21 @@ const ModelLabel: React.FC<Props> = ({ size }) => {
const { activeModel } = useActiveModel() const { activeModel } = useActiveModel()
const totalRam = useAtomValue(totalRamAtom) const totalRam = useAtomValue(totalRamAtom)
const usedRam = useAtomValue(usedRamAtom) const usedRam = useAtomValue(usedRamAtom)
const availableVram = useAtomValue(availableVramAtom)
const { settings } = useSettings()
const getLabel = (size: number) => { const getLabel = (size: number) => {
const minimumRamModel = size * 1.25 const minimumRamModel = size * 1.25
const availableRam = totalRam - usedRam + (activeModel?.metadata.size ?? 0) const availableRam =
settings?.run_mode === 'gpu'
? availableVram * 1000000 // MB to bytes
: totalRam - usedRam + (activeModel?.metadata.size ?? 0)
if (minimumRamModel > totalRam) { if (minimumRamModel > totalRam) {
return <NotEnoughRamLabel /> return (
<NotEnoughMemoryLabel
unit={settings?.run_mode === 'gpu' ? 'VRAM' : 'RAM'}
/>
)
} }
if (minimumRamModel < availableRam) { if (minimumRamModel < availableRam) {
return <RecommendedLabel /> return <RecommendedLabel />

View File

@ -9,4 +9,5 @@ export const ramUtilitizedAtom = atom<number>(0)
export const gpusAtom = atom<Record<string, never>[]>([]) export const gpusAtom = atom<Record<string, never>[]>([])
export const nvidiaTotalVramAtom = atom<number>(0) export const nvidiaTotalVramAtom = atom<number>(0)
export const availableVramAtom = atom<number>(0)
export const systemMonitorCollapseAtom = atom<boolean>(false) export const systemMonitorCollapseAtom = atom<boolean>(false)

View File

@ -12,6 +12,7 @@ import {
nvidiaTotalVramAtom, nvidiaTotalVramAtom,
gpusAtom, gpusAtom,
ramUtilitizedAtom, ramUtilitizedAtom,
availableVramAtom,
} from '@/helpers/atoms/SystemBar.atom' } from '@/helpers/atoms/SystemBar.atom'
export default function useGetSystemResources() { export default function useGetSystemResources() {
@ -24,6 +25,7 @@ export default function useGetSystemResources() {
const setUsedRam = useSetAtom(usedRamAtom) const setUsedRam = useSetAtom(usedRamAtom)
const setCpuUsage = useSetAtom(cpuUsageAtom) const setCpuUsage = useSetAtom(cpuUsageAtom)
const setTotalNvidiaVram = useSetAtom(nvidiaTotalVramAtom) const setTotalNvidiaVram = useSetAtom(nvidiaTotalVramAtom)
const setAvailableVram = useSetAtom(availableVramAtom)
const setRamUtilitized = useSetAtom(ramUtilitizedAtom) const setRamUtilitized = useSetAtom(ramUtilitizedAtom)
const getSystemResources = useCallback(async () => { const getSystemResources = useCallback(async () => {
@ -64,6 +66,13 @@ export default function useGetSystemResources() {
) )
} }
setTotalNvidiaVram(totalNvidiaVram) setTotalNvidiaVram(totalNvidiaVram)
setAvailableVram(
gpus.reduce(
(total: number, gpu: { memoryFree: string }) =>
total + Number(gpu.memoryFree),
0
)
)
}, [ }, [
setUsedRam, setUsedRam,
setTotalRam, setTotalRam,
@ -71,6 +80,7 @@ export default function useGetSystemResources() {
setCpuUsage, setCpuUsage,
setGpus, setGpus,
setTotalNvidiaVram, setTotalNvidiaVram,
setAvailableVram,
]) ])
const watch = () => { const watch = () => {

View File

@ -5,13 +5,24 @@ import { atom, useAtom } from 'jotai'
export const isShowNotificationAtom = atom<boolean>(false) export const isShowNotificationAtom = atom<boolean>(false)
export type AppSettings = {
run_mode: 'cpu' | 'gpu' | undefined
notify: boolean
gpus_in_use: string[]
vulkan: boolean
gpus: string[]
}
export const useSettings = () => { export const useSettings = () => {
const [isGPUModeEnabled, setIsGPUModeEnabled] = useState(false) // New state for GPU mode const [isGPUModeEnabled, setIsGPUModeEnabled] = useState(false) // New state for GPU mode
const [showNotification, setShowNotification] = useAtom( const [showNotification, setShowNotification] = useAtom(
isShowNotificationAtom isShowNotificationAtom
) )
const [settings, setSettings] = useState<AppSettings>()
useEffect(() => { useEffect(() => {
readSettings().then((settings) => setSettings(settings as AppSettings))
setTimeout(() => validateSettings, 3000) setTimeout(() => validateSettings, 3000)
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []) }, [])
@ -79,5 +90,6 @@ export const useSettings = () => {
saveSettings, saveSettings,
setShowNotification, setShowNotification,
validateSettings, validateSettings,
settings,
} }
} }

View File

@ -24,6 +24,8 @@ import { MainViewState } from '@/constants/screens'
import { useCreateNewThread } from '@/hooks/useCreateNewThread' import { useCreateNewThread } from '@/hooks/useCreateNewThread'
import useDownloadModel from '@/hooks/useDownloadModel' import useDownloadModel from '@/hooks/useDownloadModel'
import { useSettings } from '@/hooks/useSettings'
import { toGibibytes } from '@/utils/converter' import { toGibibytes } from '@/utils/converter'
import { mainViewStateAtom } from '@/helpers/atoms/App.atom' import { mainViewStateAtom } from '@/helpers/atoms/App.atom'
@ -45,11 +47,11 @@ type Props = {
open: string open: string
} }
const getLabel = (size: number, ram: number) => { const getLabel = (size: number, ram: number, unit: string = 'RAM') => {
if (size * 1.25 >= ram) { if (size * 1.25 >= ram) {
return ( return (
<Badge className="rounded-md" themes="danger"> <Badge className="rounded-md" themes="danger">
Not enough RAM Not enough {unit}
</Badge> </Badge>
) )
} else { } else {
@ -67,13 +69,14 @@ const ExploreModelItemHeader: React.FC<Props> = ({ model, onClick, open }) => {
const downloadedModels = useAtomValue(downloadedModelsAtom) const downloadedModels = useAtomValue(downloadedModelsAtom)
const { requestCreateNewThread } = useCreateNewThread() const { requestCreateNewThread } = useCreateNewThread()
const totalRam = useAtomValue(totalRamAtom) const totalRam = useAtomValue(totalRamAtom)
const { settings } = useSettings()
const nvidiaTotalVram = useAtomValue(nvidiaTotalVramAtom) const nvidiaTotalVram = useAtomValue(nvidiaTotalVramAtom)
const setMainViewState = useSetAtom(mainViewStateAtom) const setMainViewState = useSetAtom(mainViewStateAtom)
// Default nvidia returns vram in MB, need to convert to bytes to match the unit of totalRamW // Default nvidia returns vram in MB, need to convert to bytes to match the unit of totalRamW
let ram = nvidiaTotalVram * 1024 * 1024 let ram = nvidiaTotalVram * 1024 * 1024
if (ram === 0) { if (ram === 0 || settings?.run_mode === 'cpu') {
ram = totalRam ram = totalRam
} }
const serverEnabled = useAtomValue(serverEnabledAtom) const serverEnabled = useAtomValue(serverEnabledAtom)
@ -158,7 +161,11 @@ const ExploreModelItemHeader: React.FC<Props> = ({ model, onClick, open }) => {
<span className="mr-4 font-semibold text-muted-foreground"> <span className="mr-4 font-semibold text-muted-foreground">
{toGibibytes(model.metadata.size)} {toGibibytes(model.metadata.size)}
</span> </span>
{getLabel(model.metadata.size, ram)} {getLabel(
model.metadata.size,
ram,
settings?.run_mode === 'gpu' ? 'VRAM' : 'RAM'
)}
{downloadButton} {downloadButton}
<ChevronDownIcon <ChevronDownIcon