mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-08-06 15:44:09 +08:00
fix(provider): support editing fetched model types before save (#17728)
### Summary As title now can edit
This commit is contained in:
@@ -140,9 +140,59 @@ export function useModelsCatalog({
|
||||
}: UseModelsCatalogArgs) {
|
||||
const { listProviderModels } = useListProviderModels();
|
||||
const [catalog, setCatalog] = useState<IProviderModelItem[]>([]);
|
||||
const [catalogOverrides, setCatalogOverrides] = useState<
|
||||
Record<string, IProviderModelItem>
|
||||
>({});
|
||||
const catalogOverridesRef = useRef(catalogOverrides);
|
||||
const [manualListLoading, setManualListLoading] = useState(false);
|
||||
const [hasFetched, setHasFetched] = useState(false);
|
||||
|
||||
const applyCatalogOverrides = useCallback((items: IProviderModelItem[]) => {
|
||||
const overrides = catalogOverridesRef.current;
|
||||
const names = new Set<string>();
|
||||
const merged = items.map((item) => {
|
||||
names.add(item.name);
|
||||
const override = overrides[item.name];
|
||||
return override ? { ...item, ...override, name: item.name } : item;
|
||||
});
|
||||
Object.entries(overrides).forEach(([name, override]) => {
|
||||
if (!names.has(name)) {
|
||||
merged.push(override);
|
||||
}
|
||||
});
|
||||
return merged;
|
||||
}, []);
|
||||
|
||||
const updateCatalogModel = useCallback(
|
||||
(name: string, item: IProviderModelItem) => {
|
||||
setCatalogOverrides((prev) => {
|
||||
const next = {
|
||||
...prev,
|
||||
[name]: { ...(prev[name] ?? {}), ...item, name },
|
||||
};
|
||||
catalogOverridesRef.current = next;
|
||||
return next;
|
||||
});
|
||||
setCatalog((prev) => {
|
||||
if (!prev.some((m) => m.name === name)) {
|
||||
return [...prev, { ...item, name }];
|
||||
}
|
||||
return prev.map((m) => (m.name === name ? { ...m, ...item, name } : m));
|
||||
});
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const clearCatalogOverride = useCallback((name: string) => {
|
||||
setCatalogOverrides((prev) => {
|
||||
if (!prev[name]) return prev;
|
||||
const next = { ...prev };
|
||||
delete next[name];
|
||||
catalogOverridesRef.current = next;
|
||||
return next;
|
||||
});
|
||||
}, []);
|
||||
|
||||
// Manual "List models" handler — hits the upstream catalog endpoint.
|
||||
// The result is merged into `catalog`; the displayed list then becomes
|
||||
// the union of catalog + instance models.
|
||||
@@ -160,7 +210,9 @@ export function useModelsCatalog({
|
||||
base_url: baseUrl,
|
||||
});
|
||||
if (ret?.code === 0) {
|
||||
setCatalog((ret.data as IProviderModelItem[]) ?? []);
|
||||
setCatalog(
|
||||
applyCatalogOverrides((ret.data as IProviderModelItem[]) ?? []),
|
||||
);
|
||||
}
|
||||
setHasFetched(true);
|
||||
} catch {
|
||||
@@ -203,6 +255,8 @@ export function useModelsCatalog({
|
||||
return {
|
||||
catalog,
|
||||
setCatalog,
|
||||
updateCatalogModel,
|
||||
clearCatalogOverride,
|
||||
manualListLoading,
|
||||
hasFetched,
|
||||
handleListModels,
|
||||
@@ -599,6 +653,7 @@ interface UseModelMutationsArgs {
|
||||
filteredModels: IProviderModelItem[];
|
||||
addedSet: Set<string>;
|
||||
setCatalog: Dispatch<SetStateAction<IProviderModelItem[]>>;
|
||||
clearCatalogOverride: (name: string) => void;
|
||||
/**
|
||||
* Local mutators for the draft instance's model list. Required when
|
||||
* `isDraftInstance` is true so per-model add / remove / batch updates
|
||||
@@ -621,6 +676,7 @@ export function useModelMutations({
|
||||
filteredModels,
|
||||
addedSet,
|
||||
setCatalog,
|
||||
clearCatalogOverride,
|
||||
addDraftModel,
|
||||
removeDraftModel,
|
||||
setDraftModelsList,
|
||||
@@ -644,6 +700,7 @@ export function useModelMutations({
|
||||
// rides along with the instance save (model_info in the add body).
|
||||
if (isDraftInstance) {
|
||||
addDraftModel?.(model);
|
||||
clearCatalogOverride(model.name);
|
||||
return;
|
||||
}
|
||||
await addInstanceModel({
|
||||
@@ -652,8 +709,12 @@ export function useModelMutations({
|
||||
model_name: model.name,
|
||||
model_type: model.model_types ?? [],
|
||||
max_tokens: model.max_tokens ?? 0,
|
||||
extra: { is_tools: hasToolFeature(model.features), ...(model.extra ?? {}) },
|
||||
extra: {
|
||||
is_tools: hasToolFeature(model.features),
|
||||
...(model.extra ?? {}),
|
||||
},
|
||||
});
|
||||
clearCatalogOverride(model.name);
|
||||
};
|
||||
|
||||
const handleRemoveModel = async (model: IProviderModelItem) => {
|
||||
@@ -683,6 +744,7 @@ export function useModelMutations({
|
||||
// dropped on save.
|
||||
if (isDraftInstance) {
|
||||
addDraftModel?.(item);
|
||||
clearCatalogOverride(item.name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -694,6 +756,7 @@ export function useModelMutations({
|
||||
max_tokens: item.max_tokens ?? 0,
|
||||
extra: { is_tools: hasToolFeature(item.features), ...(item.extra ?? {}) },
|
||||
});
|
||||
clearCatalogOverride(item.name);
|
||||
};
|
||||
|
||||
// Batch attach/detach the currently visible (filtered) models.
|
||||
@@ -718,6 +781,11 @@ export function useModelMutations({
|
||||
|
||||
if (isDraftInstance) {
|
||||
setDraftModelsList?.(nextModels);
|
||||
filteredModels.forEach((m) => {
|
||||
if (!addedSet.has(m.name)) {
|
||||
clearCatalogOverride(m.name);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -731,6 +799,11 @@ export function useModelMutations({
|
||||
region: instance?.region ?? 'default',
|
||||
model_info: buildModelInfo(nextModels),
|
||||
});
|
||||
filteredModels.forEach((m) => {
|
||||
if (!addedSet.has(m.name)) {
|
||||
clearCatalogOverride(m.name);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
@@ -750,14 +823,20 @@ export function useModelMutations({
|
||||
interface UseModelEditArgs {
|
||||
providerName: string;
|
||||
instanceName: string;
|
||||
addedSet: Set<string>;
|
||||
isDraftInstance?: boolean;
|
||||
updateCatalogModel: (name: string, item: IProviderModelItem) => void;
|
||||
clearCatalogOverride: (name: string) => void;
|
||||
updateDraftModel?: (item: IProviderModelItem) => void;
|
||||
}
|
||||
|
||||
export function useModelEdit({
|
||||
providerName,
|
||||
instanceName,
|
||||
addedSet,
|
||||
isDraftInstance,
|
||||
updateCatalogModel,
|
||||
clearCatalogOverride,
|
||||
updateDraftModel,
|
||||
}: UseModelEditArgs) {
|
||||
const queryClient = useQueryClient();
|
||||
@@ -807,10 +886,7 @@ export function useModelEdit({
|
||||
// Build the features array from `extra` booleans whose keys match
|
||||
// the standard feature (`is_tools`) or the provider-specific
|
||||
// whitelist. Only `true` values become selected switch-group entries.
|
||||
const featureKeySet = new Set<string>([
|
||||
'is_tools',
|
||||
...providerFeatureKeys,
|
||||
]);
|
||||
const featureKeySet = new Set<string>(['is_tools', ...providerFeatureKeys]);
|
||||
const features: string[] = [];
|
||||
const featureBooleans = new Set<string>();
|
||||
for (const [key, value] of Object.entries(extra)) {
|
||||
@@ -823,9 +899,7 @@ export function useModelEdit({
|
||||
}
|
||||
// Remaining extra fields (non-feature: element-format selects, etc.).
|
||||
const remainingExtra = Object.fromEntries(
|
||||
Object.entries(extra).filter(
|
||||
([k]) => !featureBooleans.has(k),
|
||||
),
|
||||
Object.entries(extra).filter(([k]) => !featureBooleans.has(k)),
|
||||
);
|
||||
return {
|
||||
name: editingModel.name,
|
||||
@@ -845,12 +919,18 @@ export function useModelEdit({
|
||||
if (!editingModel) return;
|
||||
const targetName = editingModel.name;
|
||||
|
||||
if (isDraftInstance && updateDraftModel) {
|
||||
if (isDraftInstance && updateDraftModel && addedSet.has(targetName)) {
|
||||
updateDraftModel(item);
|
||||
setEditingModel(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!addedSet.has(targetName)) {
|
||||
updateCatalogModel(targetName, item);
|
||||
setEditingModel(null);
|
||||
return;
|
||||
}
|
||||
|
||||
queryClient.setQueryData<IInstanceModel[]>(
|
||||
LlmKeys.instanceModels(providerName, instanceName),
|
||||
(prev) => {
|
||||
@@ -864,7 +944,10 @@ export function useModelEdit({
|
||||
max_tokens: item.max_tokens ?? 0,
|
||||
model_type: item.model_types ?? [],
|
||||
is_tools: hasToolFeature(item.features),
|
||||
extra: { is_tools: hasToolFeature(item.features), ...(item.extra ?? {}) },
|
||||
extra: {
|
||||
is_tools: hasToolFeature(item.features),
|
||||
...(item.extra ?? {}),
|
||||
},
|
||||
};
|
||||
return next;
|
||||
},
|
||||
@@ -878,6 +961,7 @@ export function useModelEdit({
|
||||
model_type: item.model_types ?? [],
|
||||
extra: { is_tools: hasToolFeature(item.features), ...(item.extra ?? {}) },
|
||||
});
|
||||
clearCatalogOverride(targetName);
|
||||
setEditingModel(null);
|
||||
};
|
||||
|
||||
|
||||
@@ -86,6 +86,8 @@ export function ModelsSection(props: ModelsSectionProps) {
|
||||
const {
|
||||
catalog,
|
||||
setCatalog,
|
||||
updateCatalogModel,
|
||||
clearCatalogOverride,
|
||||
manualListLoading,
|
||||
hasFetched,
|
||||
handleListModels,
|
||||
@@ -237,6 +239,7 @@ export function ModelsSection(props: ModelsSectionProps) {
|
||||
filteredModels,
|
||||
addedSet,
|
||||
setCatalog,
|
||||
clearCatalogOverride,
|
||||
addDraftModel,
|
||||
removeDraftModel,
|
||||
setDraftModelsList: setDraftModels,
|
||||
@@ -255,7 +258,10 @@ export function ModelsSection(props: ModelsSectionProps) {
|
||||
} = useModelEdit({
|
||||
providerName,
|
||||
instanceName,
|
||||
addedSet,
|
||||
isDraftInstance,
|
||||
updateCatalogModel,
|
||||
clearCatalogOverride,
|
||||
updateDraftModel,
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user