Merge branch 'feature/1.6-cx' into 'main'

feat: feature/1.6-Integrate custom model

See merge request apipark/APIPark!251
This commit is contained in:
lichunxian
2025-03-10 11:41:45 +08:00
8 changed files with 56 additions and 36 deletions
@@ -897,5 +897,6 @@
"K3d2324d0": "Deletion failed.",
"Kce2fcdbf": "No Permission",
"K24f6a5b4": "Custom (Empty Template)",
"Kea608112": "Load Preset Template"
"Kea608112": "Load Preset Template",
"Kee7de862": "Edit Provider( (0) )"
}
@@ -919,5 +919,6 @@
"K3d2324d0": "削除に失敗しました。",
"Kce2fcdbf": "権限がありません",
"K24f6a5b4": "カスタム(空のテンプレート)",
"Kea608112": "プリセットテンプレートを読み込む"
"Kea608112": "プリセットテンプレートを読み込む",
"Kee7de862": "サプライヤーを編集( (0) )"
}
@@ -850,5 +850,6 @@
"K3d2324d0": "删除失败",
"Kce2fcdbf": "暂无权限",
"K24f6a5b4": "自定义(空模板)",
"Kea608112": "载入预置模板"
"Kea608112": "载入预置模板",
"Kee7de862": "编辑供应商( (0) )"
}
@@ -919,5 +919,6 @@
"K3d2324d0": "刪除失敗。",
"Kce2fcdbf": "暫無權限",
"K24f6a5b4": "自訂(空模板)",
"Kea608112": "載入預設模板"
"Kea608112": "載入預設模板",
"Kee7de862": "編輯供應商( (0) )"
}
@@ -113,7 +113,7 @@ const AiSettingModalContent = forwardRef<AiSettingModalContentHandle, AiSettingM
if ((setModelValue && providers.length) || defaultId) {
const id = defaultId || providers[0].id
form.setFieldValue('modelMode', id)
getModelConfig(id)
getModelConfig(id, defaultId)
}
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
@@ -128,7 +128,7 @@ const AiSettingModalContent = forwardRef<AiSettingModalContentHandle, AiSettingM
* 获取模型配置
* @param id
*/
const getModelConfig = (id: string) => {
const getModelConfig = (id: string, defaultId?: string | number) => {
getLlmList(id)
fetchData<BasicResponse<{ providers: ModelDetailData[] }>>(`ai/provider/config`, {
method: 'GET',
@@ -139,7 +139,8 @@ const AiSettingModalContent = forwardRef<AiSettingModalContentHandle, AiSettingM
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
const modelEntity = {
...data.provider
...data.provider,
isNewProvider: !!defaultId
}
setLocalEntity(modelEntity)
setFormFieldsValue(modelEntity)
@@ -267,12 +268,19 @@ const AiSettingModalContent = forwardRef<AiSettingModalContentHandle, AiSettingM
* 添加模型
*/
const addModel = () => {
const providerName = form.getFieldValue('modelMode') || localEntity?.name
const providerName = localEntity?.name || form.getFieldValue('modelMode')
const showAccessConfig = localEntity?.model_config?.access_configuration_status || false
const accessConfig = localEntity?.model_config?.access_configuration_demo || ''
modal.confirm({
title: $t('添加 (0) 模型', [providerName]),
content: <AddModels ref={addModelModalRef} showAccessConfig={showAccessConfig} accessConfig={accessConfig} providerID={localEntity?.id}></AddModels>,
content: (
<AddModels
ref={addModelModalRef}
showAccessConfig={showAccessConfig}
accessConfig={accessConfig}
providerID={localEntity?.id}
></AddModels>
),
onOk: () => {
return addModelModalRef.current?.save().then((res) => {
if (res === true) {
@@ -298,7 +306,7 @@ const AiSettingModalContent = forwardRef<AiSettingModalContentHandle, AiSettingM
onOk: () => {
return addProviderModalRef.current?.save().then((res) => {
if (res) {
getModelProviderList(false, res)
getModelProviderList(false, res.id)
}
})
},
@@ -326,14 +334,16 @@ const AiSettingModalContent = forwardRef<AiSettingModalContentHandle, AiSettingM
autoComplete="off"
disabled={readOnly}
>
{modelMode === 'manual' && (
{modelMode === 'manual' && !localEntity?.isNewProvider && (
<Form.Item<ModelDetailData> label={$t('模型供应商')}>
<span className="absolute top-[-28px] right-0 text-theme cursor-pointer" onClick={addProvider}>
+ {$t('添加自定义供应商')}
</span>
<Form.Item<ModelDetailData> name="modelMode" rules={[{ required: true }]}>
<Select
showSearch
className="w-INPUT_NORMAL"
filterOption={(input, option) => (option?.searchText ?? '').includes(input.toLowerCase())}
placeholder={$t(PLACEHOLDER.select)}
loading={modelModeLoading}
options={modelProviderListRef.current?.map((x) => ({
@@ -342,7 +352,8 @@ const AiSettingModalContent = forwardRef<AiSettingModalContentHandle, AiSettingM
<div className="flex items-center gap-[10px]">
<span>{x.name}</span>
</div>
)
),
searchText: x.name.toLowerCase()
}))}
onChange={(e) => {
getModelConfig(e)
@@ -355,22 +366,25 @@ const AiSettingModalContent = forwardRef<AiSettingModalContentHandle, AiSettingM
<span className="absolute top-[-28px] right-0 text-theme cursor-pointer" onClick={addModel}>
+ {$t('添加模型')}
</span>
<Form.Item<ModelDetailData> name="defaultLlm" rules={[{ required: true }]}>
<Select
className="w-INPUT_NORMAL"
placeholder={$t(PLACEHOLDER.select)}
loading={loading}
options={llmList?.map((x) => ({
value: x.id,
label: (
<div className="flex items-center gap-[10px]">
<span>{x.name || x.id}</span>
{x?.scopes?.map((s) => <Tag key={s}>{s?.toLocaleUpperCase()}</Tag>)}
</div>
)
}))}
></Select>
</Form.Item>
<Form.Item<ModelDetailData> name="defaultLlm" rules={[{ required: true }]}>
<Select
showSearch
className="w-INPUT_NORMAL"
filterOption={(input, option) => (option?.searchText ?? '').includes(input.toLowerCase())}
placeholder={$t(PLACEHOLDER.select)}
loading={loading}
options={llmList?.map((x) => ({
value: x.id,
label: (
<div className="flex items-center gap-[10px]">
<span>{x.name || x.id}</span>
{x?.scopes?.map((s) => <Tag key={s}>{s?.toLocaleUpperCase()}</Tag>)}
</div>
),
searchText: x.name.toLowerCase()
}))}
></Select>
</Form.Item>
</Form.Item>
{source === 'guide' && (
<Form.Item label={$t('所属团队')} name="team" className="mt-[16px]" rules={[{ required: true }]}>
@@ -28,7 +28,7 @@ const OnlineModelList: React.FC = () => {
const [modalVisible, setModalVisible] = useState(false)
const [selectedProviderID, setSelectedProviderID] = useState('')
const [selectedProviderName, setSelectedProviderName] = useState('')
const [showDrawerFooterLeft, setShowDrawerFooterLeft] = useState(false)
const [currentEditDrawerData, setCurrentEditDrawerData] = useState<any>()
const handleEdit = (record: ModelListData) => {
setEntity({
@@ -117,7 +117,7 @@ const OnlineModelList: React.FC = () => {
// 更新抽屉底部
const updateEntityData = (data: any) => {
// 0 常规,1 自定义
setShowDrawerFooterLeft(!data.type)
setCurrentEditDrawerData(data)
setFooterLeft(
<a target="_blank" rel="noopener noreferrer" href={data?.getApikeyUrl} className="flex items-center gap-[8px]">
<span>{$t('从 (0) 获取 API KEY', [data?.name])}</span>
@@ -269,7 +269,7 @@ const OnlineModelList: React.FC = () => {
onAddNewBtnClick={() => setDrawerOpen(true)}
/>
<DrawerWithFooter
title={entity ? $t('编辑供应商') : $t('添加供应商')}
title={currentEditDrawerData?.isNewProvider ? $t('编辑供应商( (0) )', [currentEditDrawerData.name]) : entity ? $t('编辑供应商') : $t('添加供应商')}
open={drawerOpen}
width="30%"
onClose={() => {
@@ -284,7 +284,7 @@ const OnlineModelList: React.FC = () => {
return res
})
}
footerLeft={showDrawerFooterLeft ? footerLeft : undefined}
footerLeft={!currentEditDrawerData?.type ? footerLeft : undefined}
submitAccess=""
>
<AiSettingModalContent
@@ -3,12 +3,13 @@ import { $t } from '@common/locales'
import { BasicResponse, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const'
import { useFetch } from '@common/hooks/http'
import { forwardRef, useImperativeHandle } from 'react'
import { AISettingEntityItem } from '../types'
type modelFieldType = {
name: string
}
export type addProviderContentHandle = {
save: () => Promise<number | string>
save: () => Promise<AISettingEntityItem>
}
type addProviderContentProps = {
@@ -24,7 +25,7 @@ const AddProvider = forwardRef<addProviderContentHandle, addProviderContentProps
* 保存
* @returns
*/
const save: () => Promise<number | string> = () => {
const save: () => Promise<AISettingEntityItem> = () => {
return new Promise((resolve, reject) => {
try {
form
@@ -41,7 +42,7 @@ const AddProvider = forwardRef<addProviderContentHandle, addProviderContentProps
const { code, data, msg } = response
if (code === STATUS_CODE.SUCCESS) {
message.success($t(RESPONSE_TIPS.success) || msg)
resolve(data.id)
resolve(data.provider)
} else {
message.error(msg || $t(RESPONSE_TIPS.error))
reject(msg || $t(RESPONSE_TIPS.error))
@@ -37,6 +37,7 @@ export interface AISettingEntityItem {
name?: string
type?: number
model_config?: ModelConfigItem
isNewProvider?: boolean
}
export interface ModelDetailData extends ModelListData {
enable: boolean
@@ -63,7 +64,7 @@ export type AiProviderLlmsItems = {
logo: string
scopes: ('chat' | 'completions')[]
config: string
name?: string
name: string
}
export type AiProviderDefaultConfig = {