mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-04-18 03:17:27 +00:00
- Added new components for GroupRatioSettings and ModelRatioSettings to manage group and model ratios. - Integrated tabs in OperationSetting to switch between model and visual ratio settings. - Updated translations for new settings and improved existing ones in the English locale file. - Refactored ModelSettingsVisualEditor to support dynamic pricing and ratio configurations. This update improves the user interface for managing operational settings, enhancing usability and localization support.
178 lines
5.8 KiB
JavaScript
178 lines
5.8 KiB
JavaScript
import React, { useEffect, useState, useRef } from 'react';
|
||
import { Button, Col, Form, Popconfirm, Row, Space, Spin } from '@douyinfe/semi-ui';
|
||
import {
|
||
compareObjects,
|
||
API,
|
||
showError,
|
||
showSuccess,
|
||
showWarning,
|
||
verifyJSON,
|
||
} from '../../../helpers';
|
||
import { useTranslation } from 'react-i18next';
|
||
|
||
export default function ModelRatioSettings(props) {
|
||
const [loading, setLoading] = useState(false);
|
||
const [inputs, setInputs] = useState({
|
||
ModelPrice: '',
|
||
ModelRatio: '',
|
||
CompletionRatio: '',
|
||
});
|
||
const refForm = useRef();
|
||
const [inputsRow, setInputsRow] = useState(inputs);
|
||
const { t } = useTranslation();
|
||
|
||
async function onSubmit() {
|
||
try {
|
||
await refForm.current.validate().then(() => {
|
||
const updateArray = compareObjects(inputs, inputsRow);
|
||
if (!updateArray.length) return showWarning(t('你似乎并没有修改什么'));
|
||
|
||
const requestQueue = updateArray.map((item) => {
|
||
const value = typeof inputs[item.key] === 'boolean'
|
||
? String(inputs[item.key])
|
||
: inputs[item.key];
|
||
return API.put('/api/option/', { key: item.key, value });
|
||
});
|
||
|
||
setLoading(true);
|
||
Promise.all(requestQueue)
|
||
.then((res) => {
|
||
if (res.includes(undefined)) {
|
||
return showError(requestQueue.length > 1 ? t('部分保存失败,请重试') : t('保存失败'));
|
||
}
|
||
|
||
for (let i = 0; i < res.length; i++) {
|
||
if (!res[i].data.success) {
|
||
return showError(res[i].data.message);
|
||
}
|
||
}
|
||
|
||
showSuccess(t('保存成功'));
|
||
props.refresh();
|
||
})
|
||
.catch(error => {
|
||
console.error('Unexpected error:', error);
|
||
showError(t('保存失败,请重试'));
|
||
})
|
||
.finally(() => {
|
||
setLoading(false);
|
||
});
|
||
}).catch(() => {
|
||
showError(t('请检查输入'));
|
||
});
|
||
} catch (error) {
|
||
showError(t('请检查输入'));
|
||
console.error(error);
|
||
}
|
||
}
|
||
|
||
async function resetModelRatio() {
|
||
try {
|
||
let res = await API.post(`/api/option/rest_model_ratio`);
|
||
if (res.data.success) {
|
||
showSuccess(res.data.message);
|
||
props.refresh();
|
||
} else {
|
||
showError(res.data.message);
|
||
}
|
||
} catch (error) {
|
||
showError(error);
|
||
}
|
||
}
|
||
|
||
useEffect(() => {
|
||
const currentInputs = {};
|
||
for (let key in props.options) {
|
||
if (Object.keys(inputs).includes(key)) {
|
||
currentInputs[key] = props.options[key];
|
||
}
|
||
}
|
||
setInputs(currentInputs);
|
||
setInputsRow(structuredClone(currentInputs));
|
||
refForm.current.setValues(currentInputs);
|
||
}, [props.options]);
|
||
|
||
return (
|
||
<Spin spinning={loading}>
|
||
<Form
|
||
values={inputs}
|
||
getFormApi={(formAPI) => (refForm.current = formAPI)}
|
||
style={{ marginBottom: 15 }}
|
||
>
|
||
<Form.Section>
|
||
<Row gutter={16}>
|
||
<Col span={16}>
|
||
<Form.TextArea
|
||
label={t('模型固定价格')}
|
||
extraText={t('一次调用消耗多少刀,优先级大于模型倍率')}
|
||
placeholder={t('为一个 JSON 文本,键为模型名称,值为一次调用消耗多少刀,比如 "gpt-4-gizmo-*": 0.1,一次消耗0.1刀')}
|
||
field={'ModelPrice'}
|
||
autosize={{ minRows: 6, maxRows: 12 }}
|
||
trigger='blur'
|
||
stopValidateWithError
|
||
rules={[
|
||
{
|
||
validator: (rule, value) => verifyJSON(value),
|
||
message: '不是合法的 JSON 字符串'
|
||
}
|
||
]}
|
||
onChange={(value) => setInputs({ ...inputs, ModelPrice: value })}
|
||
/>
|
||
</Col>
|
||
</Row>
|
||
<Row gutter={16}>
|
||
<Col span={16}>
|
||
<Form.TextArea
|
||
label={t('模型倍率')}
|
||
placeholder={t('为一个 JSON 文本,键为模型名称,值为倍率')}
|
||
field={'ModelRatio'}
|
||
autosize={{ minRows: 6, maxRows: 12 }}
|
||
trigger='blur'
|
||
stopValidateWithError
|
||
rules={[
|
||
{
|
||
validator: (rule, value) => verifyJSON(value),
|
||
message: '不是合法的 JSON 字符串'
|
||
}
|
||
]}
|
||
onChange={(value) => setInputs({ ...inputs, ModelRatio: value })}
|
||
/>
|
||
</Col>
|
||
</Row>
|
||
<Row gutter={16}>
|
||
<Col span={16}>
|
||
<Form.TextArea
|
||
label={t('模型补全倍率(仅对自定义模型有效)')}
|
||
extraText={t('仅对自定义模型有效')}
|
||
placeholder={t('为一个 JSON 文本,键为模型名称,值为倍率')}
|
||
field={'CompletionRatio'}
|
||
autosize={{ minRows: 6, maxRows: 12 }}
|
||
trigger='blur'
|
||
stopValidateWithError
|
||
rules={[
|
||
{
|
||
validator: (rule, value) => verifyJSON(value),
|
||
message: '不是合法的 JSON 字符串'
|
||
}
|
||
]}
|
||
onChange={(value) => setInputs({ ...inputs, CompletionRatio: value })}
|
||
/>
|
||
</Col>
|
||
</Row>
|
||
</Form.Section>
|
||
</Form>
|
||
<Space>
|
||
<Button onClick={onSubmit}>{t('保存模型倍率设置')}</Button>
|
||
<Popconfirm
|
||
title={t('确定重置模型倍率吗?')}
|
||
content={t('此修改将不可逆')}
|
||
okType={'danger'}
|
||
position={'top'}
|
||
onConfirm={resetModelRatio}
|
||
>
|
||
<Button type={'danger'}>{t('重置模型倍率')}</Button>
|
||
</Popconfirm>
|
||
</Space>
|
||
</Spin>
|
||
);
|
||
}
|