mirror of
https://github.com/linux-do/new-api.git
synced 2025-09-18 00:16:37 +08:00
feat: 完善模型价格页面
This commit is contained in:
parent
a3b3e6cc38
commit
ff044de42a
@ -35,27 +35,18 @@ func GetPricing(user *User, openAIModels []dto.OpenAIModels) []dto.ModelPricing
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updatePricing(openAIModels []dto.OpenAIModels) {
|
func updatePricing(openAIModels []dto.OpenAIModels) {
|
||||||
modelRatios := common.GetModelRatios()
|
//modelRatios := common.GetModelRatios()
|
||||||
enabledModels := GetEnabledModels()
|
enabledModels := GetEnabledModels()
|
||||||
allModels := make(map[string]string)
|
allModels := make(map[string]int)
|
||||||
for _, openAIModel := range openAIModels {
|
for i, model := range enabledModels {
|
||||||
if common.StringsContains(enabledModels, openAIModel.Id) {
|
allModels[model] = i
|
||||||
allModels[openAIModel.Id] = openAIModel.OwnedBy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for model, _ := range modelRatios {
|
|
||||||
if common.StringsContains(enabledModels, model) {
|
|
||||||
if _, ok := allModels[model]; !ok {
|
|
||||||
allModels[model] = "custom"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pricingMap = make([]dto.ModelPricing, 0)
|
pricingMap = make([]dto.ModelPricing, 0)
|
||||||
for model, ownerBy := range allModels {
|
for model, _ := range allModels {
|
||||||
pricing := dto.ModelPricing{
|
pricing := dto.ModelPricing{
|
||||||
Available: true,
|
Available: true,
|
||||||
ModelName: model,
|
ModelName: model,
|
||||||
OwnerBy: ownerBy,
|
|
||||||
}
|
}
|
||||||
modelPrice, findPrice := common.GetModelPrice(model, false)
|
modelPrice, findPrice := common.GetModelPrice(model, false)
|
||||||
if findPrice {
|
if findPrice {
|
||||||
|
@ -7,7 +7,8 @@ var ModelList = []string{
|
|||||||
"gpt-4", "gpt-4-0314", "gpt-4-0613", "gpt-4-1106-preview", "gpt-4-0125-preview",
|
"gpt-4", "gpt-4-0314", "gpt-4-0613", "gpt-4-1106-preview", "gpt-4-0125-preview",
|
||||||
"gpt-4-32k", "gpt-4-32k-0314", "gpt-4-32k-0613",
|
"gpt-4-32k", "gpt-4-32k-0314", "gpt-4-32k-0613",
|
||||||
"gpt-4-turbo-preview", "gpt-4-turbo", "gpt-4-turbo-2024-04-09",
|
"gpt-4-turbo-preview", "gpt-4-turbo", "gpt-4-turbo-2024-04-09",
|
||||||
"gpt-4-vision-preview", "gpt-4o",
|
"gpt-4-vision-preview",
|
||||||
|
"gpt-4o", "gpt-4o-2024-05-13",
|
||||||
"text-embedding-ada-002", "text-embedding-3-small", "text-embedding-3-large",
|
"text-embedding-ada-002", "text-embedding-3-small", "text-embedding-3-large",
|
||||||
"text-curie-001", "text-babbage-001", "text-ada-001", "text-davinci-002", "text-davinci-003",
|
"text-curie-001", "text-babbage-001", "text-ada-001", "text-davinci-002", "text-davinci-003",
|
||||||
"text-moderation-latest", "text-moderation-stable",
|
"text-moderation-latest", "text-moderation-stable",
|
||||||
|
@ -1,7 +1,16 @@
|
|||||||
import React, { useContext, useEffect, useState } from 'react';
|
import React, { useContext, useEffect, useRef, useState } from 'react';
|
||||||
import { API, copy, showError, showSuccess } from '../helpers';
|
import { API, copy, showError, showSuccess } from '../helpers';
|
||||||
|
|
||||||
import { Banner, Layout, Modal, Table, Tag, Tooltip } from '@douyinfe/semi-ui';
|
import {
|
||||||
|
Banner,
|
||||||
|
Input,
|
||||||
|
Layout,
|
||||||
|
Modal,
|
||||||
|
Space,
|
||||||
|
Table,
|
||||||
|
Tag,
|
||||||
|
Tooltip,
|
||||||
|
} from '@douyinfe/semi-ui';
|
||||||
import { stringToColor } from '../helpers/render.js';
|
import { stringToColor } from '../helpers/render.js';
|
||||||
import { UserContext } from '../context/User/index.js';
|
import { UserContext } from '../context/User/index.js';
|
||||||
import Text from '@douyinfe/semi-ui/lib/es/typography/text';
|
import Text from '@douyinfe/semi-ui/lib/es/typography/text';
|
||||||
@ -45,6 +54,27 @@ function renderAvailable(available) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ModelPricing = () => {
|
const ModelPricing = () => {
|
||||||
|
const [filteredValue, setFilteredValue] = useState([]);
|
||||||
|
const compositionRef = useRef({ isComposition: false });
|
||||||
|
|
||||||
|
const handleChange = (value) => {
|
||||||
|
if (compositionRef.current.isComposition) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const newFilteredValue = value ? [value] : [];
|
||||||
|
setFilteredValue(newFilteredValue);
|
||||||
|
};
|
||||||
|
const handleCompositionStart = () => {
|
||||||
|
compositionRef.current.isComposition = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCompositionEnd = (event) => {
|
||||||
|
compositionRef.current.isComposition = false;
|
||||||
|
const value = event.target.value;
|
||||||
|
const newFilteredValue = value ? [value] : [];
|
||||||
|
setFilteredValue(newFilteredValue);
|
||||||
|
};
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
title: '可用性',
|
title: '可用性',
|
||||||
@ -52,28 +82,28 @@ const ModelPricing = () => {
|
|||||||
render: (text, record, index) => {
|
render: (text, record, index) => {
|
||||||
return renderAvailable(text);
|
return renderAvailable(text);
|
||||||
},
|
},
|
||||||
|
sorter: (a, b) => a.available - b.available,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '提供者',
|
title: (
|
||||||
dataIndex: 'owner_by',
|
<Space>
|
||||||
render: (text, record, index) => {
|
<span>模型名称</span>
|
||||||
return (
|
<Input
|
||||||
<>
|
placeholder='模糊搜索'
|
||||||
<Tag color={stringToColor(text)} size='large'>
|
style={{ width: 200 }}
|
||||||
{text}
|
onCompositionStart={handleCompositionStart}
|
||||||
</Tag>
|
onCompositionEnd={handleCompositionEnd}
|
||||||
</>
|
onChange={handleChange}
|
||||||
);
|
showClear
|
||||||
},
|
/>
|
||||||
},
|
</Space>
|
||||||
{
|
),
|
||||||
title: '模型名称',
|
|
||||||
dataIndex: 'model_name', // 以finish_time作为dataIndex
|
dataIndex: 'model_name', // 以finish_time作为dataIndex
|
||||||
render: (text, record, index) => {
|
render: (text, record, index) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Tag
|
<Tag
|
||||||
color={stringToColor(record.owner_by)}
|
color={stringToColor(text)}
|
||||||
size='large'
|
size='large'
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
copyText(text);
|
copyText(text);
|
||||||
@ -84,6 +114,8 @@ const ModelPricing = () => {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
onFilter: (value, record) => record.model_name.includes(value),
|
||||||
|
filteredValue,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '计费类型',
|
title: '计费类型',
|
||||||
@ -91,6 +123,7 @@ const ModelPricing = () => {
|
|||||||
render: (text, record, index) => {
|
render: (text, record, index) => {
|
||||||
return renderQuotaType(parseInt(text));
|
return renderQuotaType(parseInt(text));
|
||||||
},
|
},
|
||||||
|
sorter: (a, b) => a.quota_type - b.quota_type,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '模型倍率',
|
title: '模型倍率',
|
||||||
@ -150,14 +183,17 @@ const ModelPricing = () => {
|
|||||||
return a.quota_type - b.quota_type;
|
return a.quota_type - b.quota_type;
|
||||||
});
|
});
|
||||||
|
|
||||||
// sort by owner_by, openai is max, other use localeCompare
|
// sort by model_name, start with gpt is max, other use localeCompare
|
||||||
models.sort((a, b) => {
|
models.sort((a, b) => {
|
||||||
if (a.owner_by === 'openai') {
|
if (a.model_name.startsWith('gpt') && !b.model_name.startsWith('gpt')) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if (b.owner_by === 'openai') {
|
} else if (
|
||||||
|
!a.model_name.startsWith('gpt') &&
|
||||||
|
b.model_name.startsWith('gpt')
|
||||||
|
) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return a.owner_by.localeCompare(b.owner_by);
|
return a.model_name.localeCompare(b.model_name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user