feat: improve model catalog aggregation
This commit is contained in:
@@ -58,6 +58,7 @@ export function PlatformManagementPanel(props: {
|
||||
const text = [
|
||||
model.displayName,
|
||||
model.modelName,
|
||||
model.providerModelName,
|
||||
model.modelAlias,
|
||||
...model.modelType,
|
||||
model.provider,
|
||||
@@ -482,9 +483,9 @@ function PlatformModelTable(props: {
|
||||
meta={[
|
||||
platform ? platformDisplayName(platform) : model.platformName ?? '-',
|
||||
provider?.displayName ?? platform?.provider ?? model.provider ?? '-',
|
||||
model.modelAlias || model.baseModelId || '-',
|
||||
model.modelAlias || model.modelName || '-',
|
||||
]}
|
||||
subtitle={model.modelName}
|
||||
subtitle={model.providerModelName ? `调用模型名:${model.providerModelName}` : model.modelName}
|
||||
title={model.displayName || model.modelName}
|
||||
/>
|
||||
);
|
||||
@@ -608,10 +609,13 @@ function ModelSelection(props: {
|
||||
const next = new Set(selectedIds);
|
||||
next.delete(modelId);
|
||||
const modelDiscountFactors = { ...props.form.modelDiscountFactors };
|
||||
const modelNameMappings = { ...props.form.modelNameMappings };
|
||||
delete modelDiscountFactors[modelId];
|
||||
delete modelNameMappings[modelId];
|
||||
props.onChange({
|
||||
...props.form,
|
||||
modelDiscountFactors,
|
||||
modelNameMappings,
|
||||
selectionMode: 'partial',
|
||||
selectedModelIds: Array.from(next),
|
||||
});
|
||||
@@ -633,6 +637,16 @@ function ModelSelection(props: {
|
||||
});
|
||||
}
|
||||
|
||||
function updateModelNameMapping(modelId: string, value: string) {
|
||||
props.onChange({
|
||||
...props.form,
|
||||
modelNameMappings: {
|
||||
...props.form.modelNameMappings,
|
||||
[modelId]: value,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="platformModelSelector spanTwo">
|
||||
<div className="platformModelSelectorHeader">
|
||||
@@ -649,26 +663,44 @@ function ModelSelection(props: {
|
||||
<div className="platformModelEmpty">当前没有已选模型,点击“添加模型”从模型库选择。</div>
|
||||
) : (
|
||||
<div className="platformModelChoices">
|
||||
{selectedModels.map((model) => (
|
||||
<div className="platformModelChoice" key={model.id}>
|
||||
<div className="platformModelChoiceMain">
|
||||
<span>
|
||||
<strong>{stableModelAlias(model) || model.providerModelName}</strong>
|
||||
<small>{props.providerMap.get(model.providerKey)?.displayName ?? model.providerKey} · {model.providerModelName} · {baseModelTypeText(model)}</small>
|
||||
</span>
|
||||
{selectedModels.map((model) => {
|
||||
const modelLabel = stableModelAlias(model) || model.providerModelName;
|
||||
const providerModelName = props.form.modelNameMappings[model.id] ?? model.providerModelName;
|
||||
return (
|
||||
<div className="platformModelChoice" key={model.id}>
|
||||
<div className="platformModelChoiceMain">
|
||||
<span>
|
||||
<strong>{modelLabel}</strong>
|
||||
<small>{props.providerMap.get(model.providerKey)?.displayName ?? model.providerKey} · {model.providerModelName} · {baseModelTypeText(model)}</small>
|
||||
</span>
|
||||
</div>
|
||||
<div className="platformModelChoiceFields">
|
||||
<Label>
|
||||
调用模型名
|
||||
<Input
|
||||
aria-label={`${modelLabel} 调用模型名`}
|
||||
placeholder={model.providerModelName}
|
||||
value={providerModelName}
|
||||
onChange={(event) => updateModelNameMapping(model.id, event.target.value)}
|
||||
/>
|
||||
</Label>
|
||||
<Label>
|
||||
折扣率
|
||||
<Input
|
||||
aria-label={`${modelLabel} 折扣率`}
|
||||
inputMode="decimal"
|
||||
placeholder="继承"
|
||||
value={props.form.modelDiscountFactors[model.id] ?? ''}
|
||||
onChange={(event) => updateModelDiscount(model.id, event.target.value)}
|
||||
/>
|
||||
</Label>
|
||||
</div>
|
||||
<Button type="button" variant="ghost" size="icon" aria-label="移除模型" onClick={() => removeModel(model.id)}>
|
||||
<Trash2 size={14} />
|
||||
</Button>
|
||||
</div>
|
||||
<Input
|
||||
aria-label={`${stableModelAlias(model) || model.providerModelName} 折扣率`}
|
||||
inputMode="decimal"
|
||||
placeholder="折扣率"
|
||||
value={props.form.modelDiscountFactors[model.id] ?? ''}
|
||||
onChange={(event) => updateModelDiscount(model.id, event.target.value)}
|
||||
/>
|
||||
<Button type="button" variant="ghost" size="icon" aria-label="移除模型" onClick={() => removeModel(model.id)}>
|
||||
<Trash2 size={14} />
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
<ModelPickerDialog
|
||||
@@ -864,6 +896,7 @@ function platformToForm(
|
||||
supportUrlInput: readBoolean(config, 'supportUrlInput', true),
|
||||
selectedModelIds: platformModelBaseIds(platform, baseModels, currentModels),
|
||||
modelDiscountFactors: platformModelDiscountFactors(platform, baseModels, currentModels),
|
||||
modelNameMappings: platformModelNameMappings(platform, baseModels, currentModels),
|
||||
selectionMode: 'partial',
|
||||
};
|
||||
}
|
||||
@@ -885,10 +918,19 @@ function platformModelDiscountFactors(platform: IntegrationPlatform, baseModels:
|
||||
}, {});
|
||||
}
|
||||
|
||||
function platformModelNameMappings(platform: IntegrationPlatform, baseModels: BaseModelCatalogItem[], platformModels: PlatformModel[]) {
|
||||
return platformModels.reduce<Record<string, string>>((acc, model) => {
|
||||
const baseModel = findBaseModelForPlatformModel(platform, baseModels, model);
|
||||
if (baseModel?.id) acc[baseModel.id] = model.providerModelName || model.modelName;
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
function findBaseModelForPlatformModel(platform: IntegrationPlatform | undefined, baseModels: BaseModelCatalogItem[], model: PlatformModel) {
|
||||
return baseModels.find((item) => item.id === model.baseModelId) ??
|
||||
baseModels.find((item) => item.canonicalModelKey === model.modelAlias) ??
|
||||
baseModels.find((item) => stableModelAlias(item) === model.modelAlias) ??
|
||||
baseModels.find((item) => item.providerModelName === model.modelName && model.modelType.some((type) => baseModelTypes(item).includes(type))) ??
|
||||
baseModels.find((item) => item.providerKey === platform?.provider && item.providerModelName === model.modelName && model.modelType.some((type) => baseModelTypes(item).includes(type)));
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ export interface PlatformWizardForm {
|
||||
supportUrlInput: boolean;
|
||||
modelDiscountFactor: string;
|
||||
modelDiscountFactors: Record<string, string>;
|
||||
modelNameMappings: Record<string, string>;
|
||||
modelOverrideRetry: boolean;
|
||||
modelRetryEnabled: boolean;
|
||||
modelRetryMaxAttempts: string;
|
||||
@@ -78,6 +79,7 @@ export function createEmptyPlatformForm(provider = '', defaults?: ProviderConnec
|
||||
supportUrlInput: true,
|
||||
modelDiscountFactor: '',
|
||||
modelDiscountFactors: {},
|
||||
modelNameMappings: {},
|
||||
modelOverrideRetry: false,
|
||||
modelRetryEnabled: true,
|
||||
modelRetryMaxAttempts: '2',
|
||||
@@ -99,6 +101,7 @@ export function applyProviderDefaults(form: PlatformWizardForm, provider: string
|
||||
authType: defaults?.defaultAuthType ?? 'APIKey',
|
||||
selectedModelIds: [],
|
||||
modelDiscountFactors: {},
|
||||
modelNameMappings: {},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -148,6 +151,7 @@ export function platformModelPayloads(models: BaseModelCatalogItem[], form: Plat
|
||||
baseModelId: model.id,
|
||||
canonicalModelKey: model.canonicalModelKey,
|
||||
modelName: model.providerModelName,
|
||||
providerModelName: optionalString(form.modelNameMappings[model.id]) ?? model.providerModelName,
|
||||
modelAlias: stableModelAlias(model),
|
||||
modelType: baseModelTypes(model),
|
||||
displayName: stableModelAlias(model) || model.providerModelName,
|
||||
@@ -329,8 +333,8 @@ function limitRule(metric: string, value: string, windowSeconds = 60) {
|
||||
};
|
||||
}
|
||||
|
||||
function optionalString(value: string) {
|
||||
const trimmed = value.trim();
|
||||
function optionalString(value: string | null | undefined) {
|
||||
const trimmed = value?.trim() ?? '';
|
||||
return trimmed || undefined;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user