feat: /v1/chat/completion -> /v1/response (#2629)

* feat: /v1/chat/completion -> /v1/response
This commit is contained in:
Seefs
2026-01-11 21:38:07 +08:00
committed by GitHub
parent 2432181ca0
commit 71460cba15
20 changed files with 1134 additions and 14 deletions

View File

@@ -18,7 +18,7 @@ For commercial licensing, please contact support@quantumnous.com
*/
import React, { useEffect, useState, useRef } from 'react';
import { Button, Col, Form, Row, Spin, Banner } from '@douyinfe/semi-ui';
import { Button, Col, Form, Row, Spin, Banner, Tag } from '@douyinfe/semi-ui';
import {
compareObjects,
API,
@@ -35,9 +35,31 @@ const thinkingExample = JSON.stringify(
2,
);
const chatCompletionsToResponsesPolicyExample = JSON.stringify(
{
enabled: true,
all_channels: false,
channel_ids: [1, 2],
model_patterns: ['^gpt-4o.*$', '^gpt-5.*$'],
},
null,
2,
);
const chatCompletionsToResponsesPolicyAllChannelsExample = JSON.stringify(
{
enabled: true,
all_channels: true,
model_patterns: ['^gpt-4o.*$', '^gpt-5.*$'],
},
null,
2,
);
const defaultGlobalSettingInputs = {
'global.pass_through_request_enabled': false,
'global.thinking_model_blacklist': '[]',
'global.chat_completions_to_responses_policy': '{}',
'general_setting.ping_interval_enabled': false,
'general_setting.ping_interval_seconds': 60,
};
@@ -55,6 +77,10 @@ export default function SettingGlobalModel(props) {
const text = typeof value === 'string' ? value.trim() : '';
return text === '' ? '[]' : value;
}
if (key === 'global.chat_completions_to_responses_policy') {
const text = typeof value === 'string' ? value.trim() : '';
return text === '' ? '{}' : value;
}
return value;
};
@@ -108,6 +134,16 @@ export default function SettingGlobalModel(props) {
value = defaultGlobalSettingInputs[key];
}
}
if (key === 'global.chat_completions_to_responses_policy') {
try {
value =
value && String(value).trim() !== ''
? JSON.stringify(JSON.parse(value), null, 2)
: defaultGlobalSettingInputs[key];
} catch (error) {
value = defaultGlobalSettingInputs[key];
}
}
currentInputs[key] = value;
} else {
currentInputs[key] = defaultGlobalSettingInputs[key];
@@ -180,6 +216,129 @@ export default function SettingGlobalModel(props) {
</Col>
</Row>
<Form.Section text={t('ChatCompletions→Responses 兼容配置')}>
<Row style={{ marginTop: 10 }}>
<Col span={24}>
<Banner
type='warning'
title={
<span>
{t('ChatCompletions→Responses 兼容配置')}{' '}
<Tag color='red' size='small'>
Alpha
</Tag>
</span>
}
description={t(
'提示:该功能为测试版,未来配置结构与功能行为可能发生变更,请勿在生产环境使用。',
)}
/>
</Col>
</Row>
<Row style={{ marginTop: 10 }}>
<Col span={24}>
<div
style={{
display: 'flex',
gap: 8,
flexWrap: 'wrap',
alignItems: 'center',
}}
>
<Button
type='secondary'
size='small'
onClick={() =>
setInputs({
...inputs,
'global.chat_completions_to_responses_policy':
chatCompletionsToResponsesPolicyExample,
})
}
>
{t('填充模板(指定渠道)')}
</Button>
<Button
type='secondary'
size='small'
onClick={() =>
setInputs({
...inputs,
'global.chat_completions_to_responses_policy':
chatCompletionsToResponsesPolicyAllChannelsExample,
})
}
>
{t('填充模板(全渠道)')}
</Button>
<Button
type='secondary'
size='small'
onClick={() => {
const raw =
inputs['global.chat_completions_to_responses_policy'];
if (!raw || String(raw).trim() === '') return;
try {
const formatted = JSON.stringify(
JSON.parse(raw),
null,
2,
);
setInputs({
...inputs,
'global.chat_completions_to_responses_policy':
formatted,
});
} catch (error) {
showError(t('不是合法的 JSON 字符串'));
}
}}
>
{t('格式化 JSON')}
</Button>
</div>
</Col>
</Row>
<Row style={{ marginTop: 10 }}>
<Col span={24}>
<Form.TextArea
label={t('配置 JSON')}
field={'global.chat_completions_to_responses_policy'}
placeholder={
t('例如(指定渠道):') +
'\n' +
chatCompletionsToResponsesPolicyExample +
'\n\n' +
t('例如(全渠道):') +
'\n' +
chatCompletionsToResponsesPolicyAllChannelsExample
}
rows={8}
rules={[
{
validator: (rule, value) => {
if (!value || value.trim() === '') return true;
return verifyJSON(value);
},
message: t('不是合法的 JSON 字符串'),
},
]}
extraText={t(
'当客户端调用 /v1/chat/completions 且 model 命中 model_patterns 时,自动改走上游 /v1/responses并把响应转换回 /v1/chat/completions 结构',
)}
onChange={(value) =>
setInputs({
...inputs,
'global.chat_completions_to_responses_policy': value,
})
}
/>
</Col>
</Row>
</Form.Section>
<Form.Section text={t('连接保活设置')}>
<Row style={{ marginTop: 10 }}>
<Col span={24}>