fix: filter invaild lora in form

This commit is contained in:
jialin
2026-05-25 13:56:44 +08:00
committed by jialin
parent 1e334903dd
commit f0a1dad48e
4 changed files with 68 additions and 74 deletions
+14 -54
View File
@@ -5,34 +5,18 @@ import {
} from '@gpustack/core-ui'; } from '@gpustack/core-ui';
import _ from 'lodash'; import _ from 'lodash';
import { useEffect, useMemo, useState } from 'react'; import { useEffect, useMemo, useState } from 'react';
import { modelSourceMap } from '../config'; import useQueryModelLoraList, {
import useQueryModelLoraList from '../services/use-query-lora-list'; LoraOptionGroup
} from '../services/use-query-lora-list';
type LoraDataItem = {
label: string;
value: string;
lora_repo_name: string;
source: string;
};
interface LoraListItemProps { interface LoraListItemProps {
item: { value: any[]; lora_name: string }; item: { value: any[]; lora_name: string };
base: string; base: string;
defaultDataList: LoraDataItem[]; defaultDataList: LoraOptionGroup[];
selectedRepoNames: Set<string>; selectedRepoNames: Set<string>;
onChange: (partial: { value?: any[]; lora_name?: string }) => void; onChange: (partial: { value?: any[]; lora_name?: string }) => void;
} }
const sourceLabel = (source: string) => {
if (source === modelSourceMap.huggingface_value) {
return modelSourceMap.huggingface;
}
if (source === modelSourceMap.modelscope_value) {
return modelSourceMap.modelScope;
}
return source;
};
const LoraListItem: React.FC<LoraListItemProps> = ({ const LoraListItem: React.FC<LoraListItemProps> = ({
item, item,
base, base,
@@ -64,40 +48,16 @@ const LoraListItem: React.FC<LoraListItemProps> = ({
}, [base]); }, [base]);
const groupedOptions = useMemo(() => { const groupedOptions = useMemo(() => {
const groups: Record<
string,
{
label: string;
value: string;
isParent: boolean;
children: any[];
}
> = {};
const currentRepo = item.value?.[1]; const currentRepo = item.value?.[1];
return itemDataList
itemDataList.forEach((it) => { .map((group) => ({
if (!groups[it.source]) { ...group,
groups[it.source] = { children: group.children.filter(
label: sourceLabel(it.source), (child) =>
value: it.source, !selectedRepoNames.has(child.value) || child.value === currentRepo
isParent: true, )
children: [] }))
}; .filter((group) => group.children.length > 0);
}
const isSelectedByOther =
selectedRepoNames.has(it.lora_repo_name) &&
it.lora_repo_name !== currentRepo;
if (!isSelectedByOther) {
groups[it.source].children.push({
label: it.lora_repo_name,
value: it.lora_repo_name,
source: it.source,
isParent: false
});
}
});
return Object.values(groups).filter((g) => g.children.length > 0);
}, [itemDataList, selectedRepoNames, item.value]); }, [itemDataList, selectedRepoNames, item.value]);
const handleSearch = (q: string) => { const handleSearch = (q: string) => {
@@ -153,7 +113,7 @@ const LoraListItem: React.FC<LoraListItemProps> = ({
); );
} }
return ( return (
<AutoTooltip ghost maxWidth={200}> <AutoTooltip ghost maxWidth={180}>
{data.label} {data.label}
</AutoTooltip> </AutoTooltip>
); );
+8 -6
View File
@@ -60,11 +60,13 @@ const ModelLoraList = () => {
}, [itemList]); }, [itemList]);
const syncFormField = (newItemList: ItemValue[]) => { const syncFormField = (newItemList: ItemValue[]) => {
const newFormList = newItemList.map((it) => ({ const newFormList = newItemList
source: (it.value?.[0] || '') as 'huggingface' | 'model_scope', .map((it) => ({
lora_repo_name: it.value?.[1] || '', source: (it.value?.[0] || '') as 'huggingface' | 'model_scope',
lora_name: it.lora_name || '' lora_repo_name: it.value?.[1] || '',
})); lora_name: it.lora_name || ''
}))
.filter((it) => it.lora_repo_name?.trim() && it.lora_name?.trim());
form.setFieldValue('lora_list', newFormList); form.setFieldValue('lora_list', newFormList);
}; };
@@ -91,7 +93,7 @@ const ModelLoraList = () => {
}; };
return ( return (
<Form.Item<FormData> name="lora_list" trigger=""> <Form.Item<FormData> name="lora_list">
<MetadataList <MetadataList
label="LoRA Adapter" label="LoRA Adapter"
dataList={itemList} dataList={itemList}
@@ -1,6 +1,7 @@
import { useQueryData } from '@gpustack/core-ui'; import { useQueryData } from '@gpustack/core-ui';
import { useState } from 'react'; import { useState } from 'react';
import { queryModelLoraAdapter } from '../apis'; import { queryModelLoraAdapter } from '../apis';
import { modelSourceMap } from '../config';
import { ModelLoraAdapterResult } from '../config/types'; import { ModelLoraAdapterResult } from '../config/types';
type Parameters = { type Parameters = {
@@ -9,6 +10,30 @@ type Parameters = {
limit?: number; // default to 40 limit?: number; // default to 40
}; };
export type LoraOptionChild = {
label: string;
value: string;
source: string;
isParent: false;
};
export type LoraOptionGroup = {
label: string;
value: string;
isParent: true;
children: LoraOptionChild[];
};
const sourceLabel = (source: string) => {
if (source === modelSourceMap.huggingface_value) {
return modelSourceMap.huggingface;
}
if (source === modelSourceMap.modelscope_value) {
return modelSourceMap.modelScope;
}
return source;
};
export const useQueryModelLoraList = () => { export const useQueryModelLoraList = () => {
const { detailData, loading, fetchData, cancelRequest } = useQueryData< const { detailData, loading, fetchData, cancelRequest } = useQueryData<
ModelLoraAdapterResult, ModelLoraAdapterResult,
@@ -18,24 +43,29 @@ export const useQueryModelLoraList = () => {
fetchDetail: queryModelLoraAdapter fetchDetail: queryModelLoraAdapter
}); });
const [dataList, setDataList] = useState< const [dataList, setDataList] = useState<LoraOptionGroup[]>([]);
{
label: string;
value: string;
lora_repo_name: string;
source: string;
}[]
>([]);
const getData = (params: Parameters) => { const getData = (params: Parameters) => {
fetchData(params).then((result) => { fetchData(params).then((result) => {
if (result) { if (result) {
const formattedData = result.lora_list.map((item) => ({ const groups: Record<string, LoraOptionGroup> = {};
...item, result.lora_list.forEach((item) => {
label: item.lora_repo_name, if (!groups[item.source]) {
value: item.lora_repo_name groups[item.source] = {
})); label: sourceLabel(item.source),
setDataList(formattedData); value: item.source,
isParent: true,
children: []
};
}
groups[item.source].children.push({
label: item.lora_repo_name,
value: item.lora_repo_name,
source: item.source,
isParent: false
});
});
setDataList(Object.values(groups));
} }
}); });
}; };
+2
View File
@@ -124,6 +124,7 @@ export interface ModelFile {
id: number; id: number;
created_at: string; created_at: string;
updated_at: string; updated_at: string;
is_lora: boolean;
} }
export interface ModelFileFormData { export interface ModelFileFormData {
@@ -135,4 +136,5 @@ export interface ModelFileFormData {
model_scope_file_path: string; model_scope_file_path: string;
local_path: string; local_path: string;
local_dir: string; local_dir: string;
is_lora: boolean;
} }