Optimize model provider selection with category grouping (#1770)

* Initial plan

* Add provider category field to requesters and implement grouped dropdown

Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com>

* Fix TypeScript type and prettier formatting issues

Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com>

* Rename provider categories: aggregator→maas, self_deployed→self-hosted

Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com>

* Move provider_category from metadata to spec section

Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com>

* perf: adjust category

* perf: adjust data structure

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com>
Co-authored-by: Junyan Qin <rockchinq@gmail.com>
This commit is contained in:
Copilot
2025-11-11 12:49:43 +08:00
committed by GitHub
parent 8cd50fbdb4
commit 1f877e2b8e
31 changed files with 522 additions and 415 deletions

View File

@@ -1,4 +1,5 @@
export interface IChooseRequesterEntity {
label: string;
value: string;
provider_category?: string;
}

View File

@@ -34,6 +34,7 @@ import {
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
@@ -186,6 +187,7 @@ export default function EmbeddingForm({
return {
label: extractI18nObject(item.label),
value: item.name,
provider_category: item.spec.provider_category || 'manufacturer',
};
}),
);
@@ -425,11 +427,44 @@ export default function EmbeddingForm({
</SelectTrigger>
<SelectContent>
<SelectGroup>
{requesterNameList.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
<SelectLabel>
{t('models.modelManufacturer')}
</SelectLabel>
{requesterNameList
.filter(
(item) =>
item.provider_category === 'manufacturer',
)
.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
</SelectGroup>
<SelectGroup>
<SelectLabel>
{t('models.aggregationPlatform')}
</SelectLabel>
{requesterNameList
.filter((item) => item.provider_category === 'maas')
.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
</SelectGroup>
<SelectGroup>
<SelectLabel>{t('models.selfDeployed')}</SelectLabel>
{requesterNameList
.filter(
(item) =>
item.provider_category === 'self-hosted',
)
.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>

View File

@@ -34,6 +34,7 @@ import {
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
@@ -203,6 +204,7 @@ export default function LLMForm({
return {
label: extractI18nObject(item.label),
value: item.name,
provider_category: item.spec.provider_category || 'manufacturer',
};
}),
);
@@ -440,11 +442,44 @@ export default function LLMForm({
</SelectTrigger>
<SelectContent>
<SelectGroup>
{requesterNameList.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
<SelectLabel>
{t('models.modelManufacturer')}
</SelectLabel>
{requesterNameList
.filter(
(item) =>
item.provider_category === 'manufacturer',
)
.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
</SelectGroup>
<SelectGroup>
<SelectLabel>
{t('models.aggregationPlatform')}
</SelectLabel>
{requesterNameList
.filter((item) => item.provider_category === 'maas')
.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
</SelectGroup>
<SelectGroup>
<SelectLabel>{t('models.selfDeployed')}</SelectLabel>
{requesterNameList
.filter(
(item) =>
item.provider_category === 'self-hosted',
)
.map((item) => (
<SelectItem key={item.value} value={item.value}>
{item.label}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>

View File

@@ -29,6 +29,7 @@ export interface Requester {
icon?: string;
spec: {
config: IDynamicFormItemSchema[];
provider_category: string;
};
}

View File

@@ -141,6 +141,9 @@ const enUS = {
selectModelProvider: 'Select Model Provider',
modelProviderDescription:
'Please fill in the model name provided by the supplier',
modelManufacturer: 'Model Manufacturer',
aggregationPlatform: 'Aggregation Platform',
selfDeployed: 'Self-deployed',
selectModel: 'Select Model',
testSuccess: 'Test successful',
testError: 'Test failed, please check your model configuration',

View File

@@ -144,6 +144,9 @@ const jaJP = {
'リクエストボディに追加されるパラメータmax_tokens、temperature、top_p など)',
selectModelProvider: 'モデルプロバイダーを選択',
modelProviderDescription: 'プロバイダーが提供するモデル名をご入力ください',
modelManufacturer: 'モデルメーカー',
aggregationPlatform: 'アグリゲーションプラットフォーム',
selfDeployed: 'セルフデプロイ',
selectModel: 'モデルを選択してください',
testSuccess: 'テストに成功しました',
testError: 'テストに失敗しました。モデル設定を確認してください',

View File

@@ -138,6 +138,9 @@ const zhHans = {
boolean: '布尔值',
selectModelProvider: '选择模型供应商',
modelProviderDescription: '请填写供应商向您提供的模型名称',
modelManufacturer: '模型厂商',
aggregationPlatform: '中转平台',
selfDeployed: '自部署',
selectModel: '请选择模型',
testSuccess: '测试成功',
testError: '测试失败,请检查模型配置',

View File

@@ -138,6 +138,9 @@ const zhHant = {
boolean: '布林值',
selectModelProvider: '選擇模型供應商',
modelProviderDescription: '請填寫供應商向您提供的模型名稱',
modelManufacturer: '模型廠商',
aggregationPlatform: '中轉平台',
selfDeployed: '自部署',
selectModel: '請選擇模型',
testSuccess: '測試成功',
testError: '測試失敗,請檢查模型設定',