mirror of
https://github.com/khoaliber/khoj.git
synced 2026-03-02 21:19:12 +00:00
- Consistently use /content/ for data. Remove content-source from path - Remove unnecessary /data/ prefix for API endpoints under /config
153 lines
4.7 KiB
TypeScript
153 lines
4.7 KiB
TypeScript
import { useAuthenticatedData } from '@/app/common/auth';
|
|
import React, { useEffect } from 'react';
|
|
import useSWR from 'swr';
|
|
import {
|
|
AlertDialog,
|
|
AlertDialogAction,
|
|
AlertDialogCancel,
|
|
AlertDialogContent,
|
|
AlertDialogDescription,
|
|
AlertDialogFooter,
|
|
AlertDialogHeader,
|
|
AlertDialogTitle,
|
|
} from "@/components/ui/alert-dialog";
|
|
|
|
|
|
import styles from './modelPicker.module.css';
|
|
|
|
export interface Model {
|
|
id: number;
|
|
chat_model: string;
|
|
}
|
|
|
|
// Custom fetcher function to fetch options
|
|
const fetchOptionsRequest = async (url: string) => {
|
|
const response = await fetch(url, {
|
|
method: 'GET',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
});
|
|
return response.json();
|
|
};
|
|
|
|
export const useOptionsRequest = (url: string) => {
|
|
const { data, error } = useSWR<Model[]>(url, fetchOptionsRequest);
|
|
|
|
return {
|
|
data,
|
|
isLoading: !error && !data,
|
|
isError: error,
|
|
};
|
|
};
|
|
|
|
const fetchSelectedModel = async (url: string) => {
|
|
const response = await fetch(url, {
|
|
method: 'GET',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
});
|
|
return response.json();
|
|
}
|
|
|
|
export const useSelectedModel = (url: string) => {
|
|
const { data, error } = useSWR<Model>(url, fetchSelectedModel);
|
|
|
|
return {
|
|
data,
|
|
isLoading: !error && !data,
|
|
isError: error,
|
|
}
|
|
}
|
|
|
|
interface ModelPickerProps {
|
|
disabled?: boolean;
|
|
setModelUsed?: (model: Model) => void;
|
|
initialModel?: Model;
|
|
}
|
|
|
|
export const ModelPicker: React.FC<any> = (props: ModelPickerProps) => {
|
|
const { data: models } = useOptionsRequest('/api/config/chat/model/options');
|
|
const { data: selectedModel } = useSelectedModel('/api/config/chat/model');
|
|
const [openLoginDialog, setOpenLoginDialog] = React.useState(false);
|
|
|
|
let userData = useAuthenticatedData();
|
|
|
|
useEffect(() => {
|
|
if (props.setModelUsed && selectedModel) {
|
|
props.setModelUsed(selectedModel);
|
|
}
|
|
}, [selectedModel]);
|
|
|
|
if (!models) {
|
|
return <div>Loading...</div>;
|
|
}
|
|
|
|
function onSelect(model: Model) {
|
|
if (!userData) {
|
|
setOpenLoginDialog(true);
|
|
return;
|
|
}
|
|
|
|
if (props.setModelUsed) {
|
|
props.setModelUsed(model);
|
|
}
|
|
|
|
fetch('/api/config/chat/model' + '?id=' + String(model.id), { method: 'POST', body: JSON.stringify(model) })
|
|
.then((response) => {
|
|
if (!response.ok) {
|
|
throw new Error('Failed to select model');
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
console.error('Failed to select model', error);
|
|
});
|
|
}
|
|
|
|
function isSelected(model: Model) {
|
|
if (props.initialModel) {
|
|
return model.id === props.initialModel.id;
|
|
}
|
|
return selectedModel?.id === model.id;
|
|
}
|
|
|
|
return (
|
|
<div className={styles.modelPicker}>
|
|
<select className={styles.modelPicker} onChange={(e) => {
|
|
const selectedModelId = Number(e.target.value);
|
|
const selectedModel = models.find((model) => model.id === selectedModelId);
|
|
if (selectedModel) {
|
|
onSelect(selectedModel);
|
|
} else {
|
|
console.error('Selected model not found', e.target.value);
|
|
}
|
|
}} disabled={props.disabled}>
|
|
{models?.map((model) => (
|
|
<option key={model.id} value={model.id} selected={isSelected(model)}>
|
|
{model.chat_model}
|
|
</option>
|
|
))}
|
|
</select>
|
|
<AlertDialog open={openLoginDialog} onOpenChange={setOpenLoginDialog}>
|
|
<AlertDialogContent>
|
|
<AlertDialogHeader>
|
|
<AlertDialogTitle>You must be logged in to configure your model.</AlertDialogTitle>
|
|
<AlertDialogDescription>Once you create an account with Khoj, you can configure your model and use a whole suite of other features. Check out our <a href="https://docs.khoj.dev/">documentation</a> to learn more.
|
|
</AlertDialogDescription>
|
|
</AlertDialogHeader>
|
|
<AlertDialogFooter>
|
|
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
<AlertDialogAction
|
|
onClick={() => {
|
|
window.location.href = window.location.origin + '/login';
|
|
}}>
|
|
Sign in
|
|
</AlertDialogAction>
|
|
</AlertDialogFooter>
|
|
</AlertDialogContent>
|
|
</AlertDialog>
|
|
</div>
|
|
);
|
|
};
|