Models filter
This commit is contained in:
parent
ae0d232331
commit
7eb8e5b870
|
|
@ -116,6 +116,7 @@
|
|||
.formGroup {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.formGroupFill {
|
||||
|
|
@ -128,6 +129,20 @@
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
.selectMultiline {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.selectMultiline optgroup {
|
||||
padding-block: 4px;
|
||||
}
|
||||
|
||||
.selectMultiline option {
|
||||
padding-block: 4px;
|
||||
padding-inline-start: 16px;
|
||||
}
|
||||
|
||||
.input,
|
||||
.select,
|
||||
.textarea {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { useBool } from "@common/hooks/useBool";
|
|||
import { useQuery } from "@common/hooks/useAsyncState";
|
||||
import { useInputState } from "@common/hooks/useInputState";
|
||||
import { useUpdate } from "@common/hooks/useUpdate";
|
||||
import clsx from "clsx";
|
||||
import { useMemo, useRef } from "preact/hooks";
|
||||
import styles from "../../assets/settings-modal.module.css";
|
||||
import { useAppState } from "../../contexts/state";
|
||||
|
|
@ -36,6 +37,8 @@ export const ConnectionSettings = () => {
|
|||
const modelsData = useQuery(fetchModels, connectionToFetch);
|
||||
const isLoadingModels = connectionToFetch != null && modelsData == undefined;
|
||||
|
||||
const [modelFilter, setModelFilter] = useInputState("");
|
||||
|
||||
const groupedModels = useMemo(() => {
|
||||
const sorted = (modelsData ?? []).sort((a, b) => {
|
||||
const aWeight = Number(a.support_tools) * 2 + Number(a.support_thinking);
|
||||
|
|
@ -52,6 +55,25 @@ export const ConnectionSettings = () => {
|
|||
.map(([context, models]) => ({ context, models }));
|
||||
}, [modelsData]);
|
||||
|
||||
const filteredGroupedModels = useMemo(() => {
|
||||
if (!modelFilter) return groupedModels;
|
||||
const query = modelFilter.toLowerCase();
|
||||
const fuzzyMatch = (target: string) => {
|
||||
const t = target.toLowerCase();
|
||||
let qi = 0;
|
||||
for (let ti = 0; ti < t.length && qi < query.length; ti++) {
|
||||
if (t[ti] === query[qi]) qi++;
|
||||
}
|
||||
return qi === query.length;
|
||||
};
|
||||
return groupedModels
|
||||
.map(({ context, models }) => ({
|
||||
context,
|
||||
models: models.filter(m => m.id === selectedModel || fuzzyMatch(m.id)),
|
||||
}))
|
||||
.filter(({ models }) => models.length > 0);
|
||||
}, [groupedModels, modelFilter, selectedModel]);
|
||||
|
||||
const handleBlur = () => {
|
||||
if (url && apiKey) {
|
||||
dispatch({ type: "SET_CONNECTION", connection: { url, apiKey } });
|
||||
|
|
@ -115,19 +137,27 @@ export const ConnectionSettings = () => {
|
|||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class={styles.formGroup}>
|
||||
<div class={clsx(styles.formGroup, styles.formGroupFill)}>
|
||||
<label class={styles.label}>Model</label>
|
||||
{connectionToTest ? (
|
||||
isLoadingModels ? (
|
||||
<p>Loading models...</p>
|
||||
) : groupedModels.length > 0 ? (
|
||||
<>
|
||||
<input
|
||||
type="text"
|
||||
value={modelFilter}
|
||||
onInput={setModelFilter}
|
||||
placeholder="Filter models..."
|
||||
class={styles.input}
|
||||
/>
|
||||
<select
|
||||
value={selectedModel}
|
||||
onChange={handleModelChange}
|
||||
class={styles.select}
|
||||
class={clsx(styles.select, styles.selectMultiline)}
|
||||
size={8}
|
||||
>
|
||||
<option value="">Select a model</option>
|
||||
{groupedModels.map(({ context, models }) => (
|
||||
{filteredGroupedModels.map(({ context, models }) => (
|
||||
<optgroup key={context} label={`${context} context`}>
|
||||
{models.map(m => (
|
||||
<option key={m.id} value={m.id}>
|
||||
|
|
@ -137,6 +167,7 @@ export const ConnectionSettings = () => {
|
|||
</optgroup>
|
||||
))}
|
||||
</select>
|
||||
</>
|
||||
) : (
|
||||
<p>No models available</p>
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in New Issue