import React, { useEffect, useState } from 'react'; import { Button, Form, Header, Input, Message, Segment, Card, } from 'semantic-ui-react'; import { useNavigate, useParams } from 'react-router-dom'; import { API, copy, getChannelModels, showError, showInfo, showSuccess, verifyJSON, } from '../../helpers'; import { CHANNEL_OPTIONS } from '../../constants'; const MODEL_MAPPING_EXAMPLE = { 'gpt-3.5-turbo-0301': 'gpt-3.5-turbo', 'gpt-4-0314': 'gpt-4', 'gpt-4-32k-0314': 'gpt-4-32k', }; function type2secretPrompt(type) { // inputs.type === 15 ? '按照如下格式输入:APIKey|SecretKey' : (inputs.type === 18 ? '按照如下格式输入:APPID|APISecret|APIKey' : '请输入渠道对应的鉴权密钥') switch (type) { case 15: return '按照如下格式输入:APIKey|SecretKey'; case 18: return '按照如下格式输入:APPID|APISecret|APIKey'; case 22: return '按照如下格式输入:APIKey-AppId,例如:fastgpt-0sp2gtvfdgyi4k30jwlgwf1i-64f335d84283f05518e9e041'; case 23: return '按照如下格式输入:AppId|SecretId|SecretKey'; default: return '请输入渠道对应的鉴权密钥'; } } const EditChannel = () => { const params = useParams(); const navigate = useNavigate(); const channelId = params.id; const isEdit = channelId !== undefined; const [loading, setLoading] = useState(isEdit); const handleCancel = () => { navigate('/channel'); }; const originInputs = { name: '', type: 1, key: '', base_url: '', other: '', model_mapping: '', system_prompt: '', models: [], groups: ['default'], }; const [batch, setBatch] = useState(false); const [inputs, setInputs] = useState(originInputs); const [originModelOptions, setOriginModelOptions] = useState([]); const [modelOptions, setModelOptions] = useState([]); const [groupOptions, setGroupOptions] = useState([]); const [basicModels, setBasicModels] = useState([]); const [fullModels, setFullModels] = useState([]); const [customModel, setCustomModel] = useState(''); const [config, setConfig] = useState({ region: '', sk: '', ak: '', user_id: '', vertex_ai_project_id: '', vertex_ai_adc: '', }); const handleInputChange = (e, { name, value }) => { setInputs((inputs) => ({ ...inputs, [name]: value })); if (name === 'type') { let localModels = getChannelModels(value); if (inputs.models.length === 0) { setInputs((inputs) => ({ ...inputs, models: localModels })); } setBasicModels(localModels); } }; const handleConfigChange = (e, { name, value }) => { setConfig((inputs) => ({ ...inputs, [name]: value })); }; const loadChannel = async () => { let res = await API.get(`/api/channel/${channelId}`); const { success, message, data } = res.data; if (success) { if (data.models === '') { data.models = []; } else { data.models = data.models.split(','); } if (data.group === '') { data.groups = []; } else { data.groups = data.group.split(','); } if (data.model_mapping !== '') { data.model_mapping = JSON.stringify( JSON.parse(data.model_mapping), null, 2 ); } setInputs(data); if (data.config !== '') { setConfig(JSON.parse(data.config)); } setBasicModels(getChannelModels(data.type)); } else { showError(message); } setLoading(false); }; const fetchModels = async () => { try { let res = await API.get(`/api/channel/models`); let localModelOptions = res.data.data.map((model) => ({ key: model.id, text: model.id, value: model.id, })); setOriginModelOptions(localModelOptions); setFullModels(res.data.data.map((model) => model.id)); } catch (error) { showError(error.message); } }; const fetchGroups = async () => { try { let res = await API.get(`/api/group/`); setGroupOptions( res.data.data.map((group) => ({ key: group, text: group, value: group, })) ); } catch (error) { showError(error.message); } }; useEffect(() => { let localModelOptions = [...originModelOptions]; inputs.models.forEach((model) => { if (!localModelOptions.find((option) => option.key === model)) { localModelOptions.push({ key: model, text: model, value: model, }); } }); setModelOptions(localModelOptions); }, [originModelOptions, inputs.models]); useEffect(() => { if (isEdit) { loadChannel().then(); } else { let localModels = getChannelModels(inputs.type); setBasicModels(localModels); } fetchModels().then(); fetchGroups().then(); }, []); const submit = async () => { if (inputs.key === '') { if (config.ak !== '' && config.sk !== '' && config.region !== '') { inputs.key = `${config.ak}|${config.sk}|${config.region}`; } else if ( config.region !== '' && config.vertex_ai_project_id !== '' && config.vertex_ai_adc !== '' ) { inputs.key = `${config.region}|${config.vertex_ai_project_id}|${config.vertex_ai_adc}`; } } if (!isEdit && (inputs.name === '' || inputs.key === '')) { showInfo('请填写渠道名称和渠道密钥!'); return; } if (inputs.type !== 43 && inputs.models.length === 0) { showInfo('请至少选择一个模型!'); return; } if (inputs.model_mapping !== '' && !verifyJSON(inputs.model_mapping)) { showInfo('模型映射必须是合法的 JSON 格式!'); return; } let localInputs = { ...inputs }; if (localInputs.base_url && localInputs.base_url.endsWith('/')) { localInputs.base_url = localInputs.base_url.slice( 0, localInputs.base_url.length - 1 ); } if (localInputs.type === 3 && localInputs.other === '') { localInputs.other = '2024-03-01-preview'; } let res; localInputs.models = localInputs.models.join(','); localInputs.group = localInputs.groups.join(','); localInputs.config = JSON.stringify(config); if (isEdit) { res = await API.put(`/api/channel/`, { ...localInputs, id: parseInt(channelId), }); } else { res = await API.post(`/api/channel/`, localInputs); } const { success, message } = res.data; if (success) { if (isEdit) { showSuccess('渠道更新成功!'); } else { showSuccess('渠道创建成功!'); setInputs(originInputs); } } else { showError(message); } }; const addCustomModel = () => { if (customModel.trim() === '') return; if (inputs.models.includes(customModel)) return; let localModels = [...inputs.models]; localModels.push(customModel); let localModelOptions = []; localModelOptions.push({ key: customModel, text: customModel, value: customModel, }); setModelOptions((modelOptions) => { return [...modelOptions, ...localModelOptions]; }); setCustomModel(''); handleInputChange(null, { name: 'models', value: localModels }); }; return (