feat(admin):渠道模型能力页面添加字段使用说明
This commit is contained in:
1 parent
49b05b66ad
commit
f13b583c35
6 files changed
+18
-87
No files matched your search
@@ -57,7 +57,6 @@ type IAdminV1 interface {
|
||||
ChannelKeyCreate(ctx context.Context, req *v1.ChannelKeyCreateReq) (res *v1.ChannelKeyCreateRes, err error)
|
||||
ChannelKeyDelete(ctx context.Context, req *v1.ChannelKeyDeleteReq) (res *v1.ChannelKeyDeleteRes, err error)
|
||||
ChannelAbilityBatch(ctx context.Context, req *v1.ChannelAbilityBatchReq) (res *v1.ChannelAbilityBatchRes, err error)
|
||||
ChannelCostRatioImport(ctx context.Context, req *v1.ChannelCostRatioImportReq) (res *v1.ChannelCostRatioImportRes, err error)
|
||||
ProviderDefaultURL(ctx context.Context, req *v1.ProviderDefaultURLReq) (res *v1.ProviderDefaultURLRes, err error)
|
||||
ChannelKeyList(ctx context.Context, req *v1.ChannelKeyListReq) (res *v1.ChannelKeyListRes, err error)
|
||||
ChannelAbilitiesGet(ctx context.Context, req *v1.ChannelAbilitiesGetReq) (res *v1.ChannelAbilitiesGetRes, err error)
|
||||
|
||||
@@ -169,25 +169,6 @@ type AbilityItem struct {
|
||||
CostRatio float64 `json:"cost_ratio" d:"1" v:"between:0,100" dc:"成本比例:上游实际价/平台基准价,1.0=等价(参与调度 costFactor)"`
|
||||
}
|
||||
|
||||
// ChannelCostRatioImportReq 批量导入渠道模型成本比例(CSV 由前端解析为条目)
|
||||
type ChannelCostRatioImportReq struct {
|
||||
g.Meta `path:"/channels/cost-ratio-import" method:"post" mime:"json" tags:"管理后台-渠道" summary:"批量导入成本比例"`
|
||||
Items []CostRatioImportItem `json:"items" v:"required#请提供导入条目" dc:"导入条目列表"`
|
||||
}
|
||||
|
||||
// CostRatioImportItem 成本比例导入条目
|
||||
type CostRatioImportItem struct {
|
||||
ChannelID int64 `json:"channel_id" v:"required|min:1" dc:"渠道ID"`
|
||||
ModelName string `json:"model_name" v:"required" dc:"平台标准模型名"`
|
||||
CostRatio float64 `json:"cost_ratio" v:"required|between:0.0001,100" dc:"成本比例"`
|
||||
}
|
||||
|
||||
// ChannelCostRatioImportRes 批量导入成本比例响应
|
||||
type ChannelCostRatioImportRes struct {
|
||||
Updated int `json:"updated" dc:"成功更新条数"`
|
||||
Skipped []string `json:"skipped" dc:"未匹配到能力记录的条目(渠道ID:模型名)"`
|
||||
}
|
||||
|
||||
// ProviderDefaultURLReq 获取供应商默认 URL
|
||||
type ProviderDefaultURLReq struct {
|
||||
g.Meta `path:"/channels/provider-default-urls" method:"get" mime:"json" tags:"管理后台-渠道" summary:"供应商默认地址"`
|
||||
|
||||
@@ -49,6 +49,3 @@ func (c *ControllerV1) ChannelExport(ctx context.Context, req *v1.ChannelExportR
|
||||
func (c *ControllerV1) ChannelClone(ctx context.Context, req *v1.ChannelCloneReq) (res *v1.ChannelCloneRes, err error) {
|
||||
return service.Admin().CloneChannel(ctx, req)
|
||||
}
|
||||
func (c *ControllerV1) ChannelCostRatioImport(ctx context.Context, req *v1.ChannelCostRatioImportReq) (res *v1.ChannelCostRatioImportRes, err error) {
|
||||
return service.Admin().ImportChannelCostRatios(ctx, req)
|
||||
}
|
||||
@@ -636,30 +636,6 @@ func (s *sAdmin) GetChannelAbilities(ctx context.Context, req *v1.ChannelAbiliti
|
||||
return &v1.ChannelAbilitiesGetRes{List: list}, nil
|
||||
}
|
||||
|
||||
// ImportChannelCostRatios 批量导入渠道模型成本比例(CSV 由前端解析为条目提交)。
|
||||
// 只更新已存在的能力记录,未匹配的条目返回在 skipped 中;成功后触发目录失效。
|
||||
func (s *sAdmin) ImportChannelCostRatios(ctx context.Context, req *v1.ChannelCostRatioImportReq) (*v1.ChannelCostRatioImportRes, error) {
|
||||
res := &v1.ChannelCostRatioImportRes{Skipped: make([]string, 0)}
|
||||
for _, item := range req.Items {
|
||||
affected, err := dao.ChnAbilities.Ctx(ctx).
|
||||
Where("channel_id", item.ChannelID).
|
||||
Where("model_name", item.ModelName).
|
||||
Data(do.ChnAbilities{CostRatio: item.CostRatio}).
|
||||
UpdateAndGetAffected()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if affected == 0 {
|
||||
res.Skipped = append(res.Skipped, fmt.Sprintf("%d:%s", item.ChannelID, item.ModelName))
|
||||
continue
|
||||
}
|
||||
res.Updated++
|
||||
}
|
||||
// 成本比例参与调度 costFactor,变更后跨实例目录失效
|
||||
dispatchadapter.PublishInvalidate(ctx)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// GetProviderDefaultURLs 获取供应商默认 API 地址
|
||||
func (s *sAdmin) GetProviderDefaultURLs(ctx context.Context, _ *v1.ProviderDefaultURLReq) (*v1.ProviderDefaultURLRes, error) {
|
||||
return &v1.ProviderDefaultURLRes{URLs: defaultProviderURLs}, nil
|
||||
|
||||
@@ -115,9 +115,6 @@ type (
|
||||
GetChannelKeys(ctx context.Context, req *v1.ChannelKeyListReq) (*v1.ChannelKeyListRes, error)
|
||||
// GetChannelAbilities 获取渠道模型能力列表
|
||||
GetChannelAbilities(ctx context.Context, req *v1.ChannelAbilitiesGetReq) (*v1.ChannelAbilitiesGetRes, error)
|
||||
// ImportChannelCostRatios 批量导入渠道模型成本比例(CSV 由前端解析为条目提交)。
|
||||
// 只更新已存在的能力记录,未匹配的条目返回在 skipped 中;成功后触发目录失效。
|
||||
ImportChannelCostRatios(ctx context.Context, req *v1.ChannelCostRatioImportReq) (*v1.ChannelCostRatioImportRes, error)
|
||||
// GetProviderDefaultURLs 获取供应商默认 API 地址
|
||||
GetProviderDefaultURLs(ctx context.Context, _ *v1.ProviderDefaultURLReq) (*v1.ProviderDefaultURLRes, error)
|
||||
// GetChannelHealthTrend 获取渠道健康趋势数据
|
||||
|
||||
@@ -228,36 +228,6 @@ function handleUpstreamModelChange(record: any, value: string) {
|
||||
scheduleAbilitySave('上游模型名已更新')
|
||||
}
|
||||
|
||||
// CSV 批量导入成本比例:每行 "model_name,cost_ratio"(首行可为表头)
|
||||
const csvInputRef = ref<HTMLInputElement>()
|
||||
const csvImporting = ref(false)
|
||||
function triggerCsvImport() { csvInputRef.value?.click() }
|
||||
async function handleCsvFile(e: Event) {
|
||||
const input = e.target as HTMLInputElement
|
||||
const file = input.files?.[0]
|
||||
input.value = ''
|
||||
if (!file) return
|
||||
const text = await file.text()
|
||||
const items: { channel_id: number; model_name: string; cost_ratio: number }[] = []
|
||||
for (const rawLine of text.split(/\r?\n/)) {
|
||||
const line = rawLine.trim()
|
||||
if (!line) continue
|
||||
const [model, ratioStr] = line.split(',').map(s => s?.trim())
|
||||
const ratio = Number(ratioStr)
|
||||
if (!model || !Number.isFinite(ratio) || ratio <= 0) continue // 跳过表头与非法行
|
||||
items.push({ channel_id: Number(channelId), model_name: model, cost_ratio: ratio })
|
||||
}
|
||||
if (!items.length) { Message.warning('未解析到有效条目,格式:model_name,cost_ratio'); return }
|
||||
csvImporting.value = true
|
||||
try {
|
||||
const res: any = await request.post('/admin/channels/cost-ratio-import', { items })
|
||||
const data = res.data?.data || res.data
|
||||
const skipped = data?.skipped?.length ? `,未匹配 ${data.skipped.length} 条` : ''
|
||||
Message.success(`已更新 ${data?.updated ?? 0} 条${skipped}`)
|
||||
fetchAbilities()
|
||||
} catch { /* error handled by interceptor */ } finally { csvImporting.value = false }
|
||||
}
|
||||
|
||||
async function handleDeleteAbility(id: number) {
|
||||
const newList = abilitiesData.value.filter(a => a.id !== id)
|
||||
try {
|
||||
@@ -593,15 +563,14 @@ function formatHeaders(headers: Record<string, string>): string {
|
||||
<!-- Tab 2: Model Abilities -->
|
||||
<ATabPane key="abilities" title="模型能力">
|
||||
<ACard :bordered="false">
|
||||
<template #title>
|
||||
<div class="flex items-center justify-between">
|
||||
<span>模型能力配置</span>
|
||||
<AButton type="primary" @click="openAddAbilityModal">添加能力</AButton>
|
||||
</div>
|
||||
</template>
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<span style="color: var(--color-text-3)">已配置 {{ abilitiesData.length }} 个模型能力</span>
|
||||
<ASpace>
|
||||
<ATooltip content="CSV 每行:model_name,cost_ratio(如 gpt-4o,0.8)">
|
||||
<AButton type="outline" :loading="csvImporting" @click="triggerCsvImport">导入成本比例</AButton>
|
||||
</ATooltip>
|
||||
<AButton type="primary" @click="openAddAbilityModal">添加能力</AButton>
|
||||
</ASpace>
|
||||
<input ref="csvInputRef" type="file" accept=".csv,text/csv" style="display:none" @change="handleCsvFile" />
|
||||
</div>
|
||||
<ATable
|
||||
:columns="abilityColumns"
|
||||
@@ -612,6 +581,18 @@ function formatHeaders(headers: Record<string, string>): string {
|
||||
:pagination="false"
|
||||
row-key="id"
|
||||
/>
|
||||
<!-- 字段功能说明(面向运营者) -->
|
||||
<div class="mt-3 text-xs" style="color: var(--color-text-3); line-height: 1.7;">
|
||||
<div class="mb-1"><strong>字段说明</strong></div>
|
||||
<div class="flex flex-wrap gap-x-6 gap-y-1">
|
||||
<div>
|
||||
<span style="font-weight: 500;">上游模型名:</span>该渠道转发请求时实际调用的上游模型名称。仅当上游名称与平台标准模型名不同时填写(如平台名 gpt-4、上游名 gpt-4-0314);留空表示与平台模型名相同。
|
||||
</div>
|
||||
<div>
|
||||
<span style="font-weight: 500;">成本比例:</span>该渠道相对基准价的成本系数,1.0 为标准。小于 1(如 0.8)表示更便宜,多渠道择优时更优先调度;大于 1(如 1.5)表示更贵,优先级降低。仅用于渠道调度,不影响对用户的计费。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ACard>
|
||||
</ATabPane>
|
||||
|
||||
|
||||
Reference in new issue
Block a user