chore: support AWS Claude/Cloudflare/Coze

This commit is contained in:
MartialBE 2024-05-26 18:07:57 +08:00
parent ec9b6d1039
commit 2e7e563d75
No known key found for this signature in database
GPG Key ID: 27C0267EC84B0A5C
3 changed files with 220 additions and 145 deletions

View File

@ -11,12 +11,18 @@ export const CHANNEL_OPTIONS = {
value: 14, value: 14,
color: 'primary' color: 'primary'
}, },
// 33: { 33: {
// key: 33, key: 33,
// text: 'AWS Claude', text: 'AWS Claude',
// value: 33, value: 33,
// color: 'primary' color: 'primary'
// }, },
37: {
key: 37,
text: 'Cloudflare',
value: 37,
color: 'success'
},
3: { 3: {
key: 3, key: 3,
text: 'Azure OpenAI', text: 'Azure OpenAI',
@ -119,12 +125,12 @@ export const CHANNEL_OPTIONS = {
value: 32, value: 32,
color: 'primary' color: 'primary'
}, },
// 34: { 34: {
// key: 34, key: 34,
// text: 'Coze', text: 'Coze',
// value: 34, value: 34,
// color: 'primary' color: 'primary'
// }, },
35: { 35: {
key: 35, key: 35,
text: 'Cohere', text: 'Cohere',

View File

@ -40,8 +40,8 @@ const validationSchema = Yup.object().shape({
is_edit: Yup.boolean(), is_edit: Yup.boolean(),
name: Yup.string().required('名称 不能为空'), name: Yup.string().required('名称 不能为空'),
type: Yup.number().required('渠道 不能为空'), type: Yup.number().required('渠道 不能为空'),
key: Yup.string().when('is_edit', { key: Yup.string().when(['is_edit', 'type'], {
is: false, is: (is_edit, type) => !is_edit && type !== 33,
then: Yup.string().required('密钥 不能为空') then: Yup.string().required('密钥 不能为空')
}), }),
other: Yup.string(), other: Yup.string(),
@ -107,6 +107,8 @@ const EditModal = ({ open, channelId, onCancel, onOk }) => {
if (localModels.length > 0 && Array.isArray(values['models']) && values['models'].length == 0) { if (localModels.length > 0 && Array.isArray(values['models']) && values['models'].length == 0) {
setFieldValue('models', initialModel(localModels)); setFieldValue('models', initialModel(localModels));
} }
setFieldValue('config', {});
}; };
const fetchGroups = async () => { const fetchGroups = async () => {
@ -160,17 +162,25 @@ const EditModal = ({ open, channelId, onCancel, onOk }) => {
if (values.type === 18 && values.other === '') { if (values.type === 18 && values.other === '') {
values.other = 'v2.1'; values.other = 'v2.1';
} }
if (values.key === '') {
if (values.config.ak !== '' && values.config.sk !== '' && values.config.region !== '') {
values.key = `${values.config.ak}|${values.config.sk}|${values.config.region}`;
}
}
let res; let res;
const modelsStr = values.models.map((model) => model.id).join(','); const modelsStr = values.models.map((model) => model.id).join(',');
const configStr = JSON.stringify(values.config);
values.group = values.groups.join(','); values.group = values.groups.join(',');
if (channelId) { if (channelId) {
res = await API.put(`/api/channel/`, { res = await API.put(`/api/channel/`, {
...values, ...values,
id: parseInt(channelId), id: parseInt(channelId),
models: modelsStr models: modelsStr,
config: configStr
}); });
} else { } else {
res = await API.post(`/api/channel/`, { ...values, models: modelsStr }); res = await API.post(`/api/channel/`, { ...values, models: modelsStr, config: configStr });
} }
const { success, message } = res.data; const { success, message } = res.data;
if (success) { if (success) {
@ -225,6 +235,10 @@ const EditModal = ({ open, channelId, onCancel, onOk }) => {
if (data.model_mapping !== '') { if (data.model_mapping !== '') {
data.model_mapping = JSON.stringify(JSON.parse(data.model_mapping), null, 2); data.model_mapping = JSON.stringify(JSON.parse(data.model_mapping), null, 2);
} }
if (data.config !== '') {
data.config = JSON.parse(data.config);
}
data.base_url = data.base_url ?? ''; data.base_url = data.base_url ?? '';
data.is_edit = true; data.is_edit = true;
initChannel(data.type); initChannel(data.type);
@ -485,55 +499,78 @@ const EditModal = ({ open, channelId, onCancel, onOk }) => {
</Button> </Button>
</ButtonGroup> </ButtonGroup>
</Container> </Container>
<FormControl fullWidth error={Boolean(touched.key && errors.key)} sx={{ ...theme.typography.otherInput }}> {inputLabel.key && (
{!batchAdd ? ( <>
<> <FormControl fullWidth error={Boolean(touched.key && errors.key)} sx={{ ...theme.typography.otherInput }}>
<InputLabel htmlFor="channel-key-label">{inputLabel.key}</InputLabel> {!batchAdd ? (
<OutlinedInput <>
id="channel-key-label" <InputLabel htmlFor="channel-key-label">{inputLabel.key}</InputLabel>
label={inputLabel.key} <OutlinedInput
type="text" id="channel-key-label"
value={values.key} label={inputLabel.key}
name="key" type="text"
onBlur={handleBlur} value={values.key}
onChange={handleChange} name="key"
inputProps={{}} onBlur={handleBlur}
aria-describedby="helper-text-channel-key-label" onChange={handleChange}
/> inputProps={{}}
</> aria-describedby="helper-text-channel-key-label"
) : ( />
<TextField </>
multiline ) : (
id="channel-key-label" <TextField
label={inputLabel.key} multiline
value={values.key} id="channel-key-label"
name="key" label={inputLabel.key}
onBlur={handleBlur} value={values.key}
onChange={handleChange} name="key"
aria-describedby="helper-text-channel-key-label" onBlur={handleBlur}
minRows={5} onChange={handleChange}
placeholder={inputPrompt.key + ',一行一个密钥'} aria-describedby="helper-text-channel-key-label"
/> minRows={5}
)} placeholder={inputPrompt.key + ',一行一个密钥'}
/>
)}
{touched.key && errors.key ? ( {touched.key && errors.key ? (
<FormHelperText error id="helper-tex-channel-key-label"> <FormHelperText error id="helper-tex-channel-key-label">
{errors.key} {errors.key}
</FormHelperText> </FormHelperText>
) : ( ) : (
<FormHelperText id="helper-tex-channel-key-label"> {inputPrompt.key} </FormHelperText> <FormHelperText id="helper-tex-channel-key-label"> {inputPrompt.key} </FormHelperText>
)} )}
</FormControl> </FormControl>
{channelId === 0 && ( {channelId === 0 && (
<Container <Container
sx={{ sx={{
textAlign: 'right' textAlign: 'right'
}} }}
> >
<Switch checked={batchAdd} onChange={(e) => setBatchAdd(e.target.checked)} /> <Switch checked={batchAdd} onChange={(e) => setBatchAdd(e.target.checked)} />
批量添加 批量添加
</Container> </Container>
)}
</>
)} )}
{inputLabel.config &&
Object.keys(inputLabel.config).map((configName) => {
return (
<FormControl key={'config.' + configName} fullWidth sx={{ ...theme.typography.otherInput }}>
<TextField
multiline
key={'config.' + configName}
name={'config.' + configName}
value={values.config?.[configName] || ''}
label={configName}
placeholder={inputPrompt.config[configName]}
onChange={handleChange}
/>
<FormHelperText id={`helper-tex-config.${configName}-label`}> {inputPrompt.config[configName]} </FormHelperText>
</FormControl>
);
})}
<FormControl fullWidth error={Boolean(touched.model_mapping && errors.model_mapping)} sx={{ ...theme.typography.otherInput }}> <FormControl fullWidth error={Boolean(touched.model_mapping && errors.model_mapping)} sx={{ ...theme.typography.otherInput }}>
{/* <InputLabel htmlFor="channel-model_mapping-label">{inputLabel.model_mapping}</InputLabel> */} {/* <InputLabel htmlFor="channel-model_mapping-label">{inputLabel.model_mapping}</InputLabel> */}
<TextField <TextField

View File

@ -1,177 +1,209 @@
const defaultConfig = { const defaultConfig = {
input: { input: {
name: "", name: '',
type: 1, type: 1,
key: "", key: '',
base_url: "", base_url: '',
other: "", other: '',
model_mapping: "", model_mapping: '',
models: [], models: [],
groups: ["default"], groups: ['default'],
config: {}
}, },
inputLabel: { inputLabel: {
name: "渠道名称", name: '渠道名称',
type: "渠道类型", type: '渠道类型',
base_url: "渠道API地址", base_url: '渠道API地址',
key: "密钥", key: '密钥',
other: "其他参数", other: '其他参数',
models: "模型", models: '模型',
model_mapping: "模型映射关系", model_mapping: '模型映射关系',
groups: "用户组", groups: '用户组',
config: null
}, },
prompt: { prompt: {
type: "请选择渠道类型", type: '请选择渠道类型',
name: "请为渠道命名", name: '请为渠道命名',
base_url: "可空请输入中转API地址例如通过cloudflare中转", base_url: '可空请输入中转API地址例如通过cloudflare中转',
key: "请输入渠道对应的鉴权密钥", key: '请输入渠道对应的鉴权密钥',
other: "", other: '',
models: "请选择该渠道所支持的模型", models: '请选择该渠道所支持的模型',
model_mapping: model_mapping:
'请输入要修改的模型映射关系格式为api请求模型ID:实际转发给渠道的模型ID使用JSON数组表示例如{"gpt-3.5": "gpt-35"}', '请输入要修改的模型映射关系格式为api请求模型ID:实际转发给渠道的模型ID使用JSON数组表示例如{"gpt-3.5": "gpt-35"}',
groups: "请选择该渠道所支持的用户组", groups: '请选择该渠道所支持的用户组',
config: null
}, },
modelGroup: "openai", modelGroup: 'openai'
}; };
const typeConfig = { const typeConfig = {
3: { 3: {
inputLabel: { inputLabel: {
base_url: "AZURE_OPENAI_ENDPOINT", base_url: 'AZURE_OPENAI_ENDPOINT',
other: "默认 API 版本", other: '默认 API 版本'
}, },
prompt: { prompt: {
base_url: "请填写AZURE_OPENAI_ENDPOINT", base_url: '请填写AZURE_OPENAI_ENDPOINT',
other: "请输入默认API版本例如2024-03-01-preview", other: '请输入默认API版本例如2024-03-01-preview'
}, }
}, },
11: { 11: {
input: { input: {
models: ["PaLM-2"], models: ['PaLM-2']
}, },
modelGroup: "google palm", modelGroup: 'google palm'
}, },
14: { 14: {
input: { input: {
models: ["claude-instant-1", "claude-2", "claude-2.0", "claude-2.1"], models: ['claude-instant-1', 'claude-2', 'claude-2.0', 'claude-2.1']
}, },
modelGroup: "anthropic", modelGroup: 'anthropic'
}, },
15: { 15: {
input: { input: {
models: ["ERNIE-Bot", "ERNIE-Bot-turbo", "ERNIE-Bot-4", "Embedding-V1"], models: ['ERNIE-Bot', 'ERNIE-Bot-turbo', 'ERNIE-Bot-4', 'Embedding-V1']
}, },
prompt: { prompt: {
key: "按照如下格式输入APIKey|SecretKey", key: '按照如下格式输入APIKey|SecretKey'
}, },
modelGroup: "baidu", modelGroup: 'baidu'
}, },
16: { 16: {
input: { input: {
models: ["glm-4", "glm-4v", "glm-3-turbo", "chatglm_turbo", "chatglm_pro", "chatglm_std", "chatglm_lite"], models: ['glm-4', 'glm-4v', 'glm-3-turbo', 'chatglm_turbo', 'chatglm_pro', 'chatglm_std', 'chatglm_lite']
}, },
modelGroup: "zhipu", modelGroup: 'zhipu'
}, },
17: { 17: {
inputLabel: { inputLabel: {
other: "插件参数", other: '插件参数'
}, },
input: { input: {
models: [ models: ['qwen-turbo', 'qwen-plus', 'qwen-max', 'qwen-max-longcontext', 'text-embedding-v1']
"qwen-turbo",
"qwen-plus",
"qwen-max",
"qwen-max-longcontext",
"text-embedding-v1",
],
}, },
prompt: { prompt: {
other: "请输入插件参数,即 X-DashScope-Plugin 请求头的取值", other: '请输入插件参数,即 X-DashScope-Plugin 请求头的取值'
}, },
modelGroup: "ali", modelGroup: 'ali'
}, },
18: { 18: {
inputLabel: { inputLabel: {
other: "版本号", other: '版本号'
}, },
input: { input: {
models: [ models: ['SparkDesk', 'SparkDesk-v1.1', 'SparkDesk-v2.1', 'SparkDesk-v3.1', 'SparkDesk-v3.5']
"SparkDesk",
'SparkDesk-v1.1',
'SparkDesk-v2.1',
'SparkDesk-v3.1',
'SparkDesk-v3.5'
],
}, },
prompt: { prompt: {
key: "按照如下格式输入APPID|APISecret|APIKey", key: '按照如下格式输入APPID|APISecret|APIKey',
other: "请输入版本号例如v3.1", other: '请输入版本号例如v3.1'
}, },
modelGroup: "xunfei", modelGroup: 'xunfei'
}, },
19: { 19: {
input: { input: {
models: [ models: ['360GPT_S2_V9', 'embedding-bert-512-v1', 'embedding_s1_v1', 'semantic_similarity_s1_v1']
"360GPT_S2_V9",
"embedding-bert-512-v1",
"embedding_s1_v1",
"semantic_similarity_s1_v1",
],
}, },
modelGroup: "360", modelGroup: '360'
}, },
22: { 22: {
prompt: { prompt: {
key: "按照如下格式输入APIKey-AppId例如fastgpt-0sp2gtvfdgyi4k30jwlgwf1i-64f335d84283f05518e9e041", key: '按照如下格式输入APIKey-AppId例如fastgpt-0sp2gtvfdgyi4k30jwlgwf1i-64f335d84283f05518e9e041'
}, }
}, },
23: { 23: {
input: { input: {
models: ["hunyuan"], models: ['hunyuan']
}, },
prompt: { prompt: {
key: "按照如下格式输入AppId|SecretId|SecretKey", key: '按照如下格式输入AppId|SecretId|SecretKey'
}, },
modelGroup: "tencent", modelGroup: 'tencent'
}, },
24: { 24: {
inputLabel: { inputLabel: {
other: "版本号", other: '版本号'
}, },
input: { input: {
models: ["gemini-pro"], models: ['gemini-pro']
}, },
prompt: { prompt: {
other: "请输入版本号例如v1", other: '请输入版本号例如v1'
}, },
modelGroup: "google gemini", modelGroup: 'google gemini'
}, },
25: { 25: {
input: { input: {
models: ['moonshot-v1-8k', 'moonshot-v1-32k', 'moonshot-v1-128k'], models: ['moonshot-v1-8k', 'moonshot-v1-32k', 'moonshot-v1-128k']
}, },
modelGroup: "moonshot", modelGroup: 'moonshot'
}, },
26: { 26: {
input: { input: {
models: ['Baichuan2-Turbo', 'Baichuan2-Turbo-192k', 'Baichuan-Text-Embedding'], models: ['Baichuan2-Turbo', 'Baichuan2-Turbo-192k', 'Baichuan-Text-Embedding']
}, },
modelGroup: "baichuan", modelGroup: 'baichuan'
}, },
27: { 27: {
input: { input: {
models: ['abab5.5s-chat', 'abab5.5-chat', 'abab6-chat'], models: ['abab5.5s-chat', 'abab5.5-chat', 'abab6-chat']
}, },
modelGroup: "minimax", modelGroup: 'minimax'
}, },
29: { 29: {
modelGroup: "groq", modelGroup: 'groq'
}, },
30: { 30: {
modelGroup: "ollama", modelGroup: 'ollama'
}, },
31: { 31: {
modelGroup: "lingyiwanwu", modelGroup: 'lingyiwanwu'
}, },
33: {
inputLabel: {
key: '',
config: {
region: 'Region',
ak: 'Access Key',
sk: 'Secret Key'
}
},
prompt: {
key: '',
config: {
region: 'regione.g. us-west-2',
ak: 'AWS IAM Access Key',
sk: 'AWS IAM Secret Key'
}
},
modelGroup: 'anthropic'
},
37: {
inputLabel: {
config: {
user_id: 'Account ID'
}
},
prompt: {
config: {
user_id: '请输入 Account ID例如d8d7c61dbc334c32d3ced580e4bf42b4'
}
},
modelGroup: 'Cloudflare'
},
34: {
inputLabel: {
config: {
user_id: 'User ID'
}
},
prompt: {
models: '对于 Coze 而言,模型名称即 Bot ID你可以添加一个前缀 `bot-`,例如:`bot-123456`',
config: {
user_id: '生成该密钥的用户 ID'
}
},
modelGroup: 'Coze'
}
}; };
export { defaultConfig, typeConfig }; export { defaultConfig, typeConfig };