diff --git a/frontend/packages/core/src/pages/guide/AIModelGuide.tsx b/frontend/packages/core/src/pages/guide/AIModelGuide.tsx index 7e88505f..8563a318 100644 --- a/frontend/packages/core/src/pages/guide/AIModelGuide.tsx +++ b/frontend/packages/core/src/pages/guide/AIModelGuide.tsx @@ -4,220 +4,43 @@ import localAIPic from '@common/assets/localAI.svg' import { useGlobalContext } from '@common/contexts/GlobalStateContext' import { $t } from '@common/locales' import { Icon } from '@iconify/react/dist/iconify.js' -import { App, Upload, UploadProps, Form, message, Select } from 'antd' +import { App } from 'antd' import { Card } from 'antd' -import { useRef, useState } from 'react' +import { useRef } from 'react' import { useNavigate } from 'react-router-dom' -import WithPermission from '@common/components/aoplatform/WithPermission' -import { BasicResponse, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const' -import { useFetch } from '@common/hooks/http' -import { LocalModelItem, MemberItem, SimpleTeamItem } from '@common/const/type' + import AiSettingModalContent, { AiSettingModalContentHandle } from '../aiSetting/AiSettingModal' import { checkAccess } from '@common/utils/permission' -const { Dragger } = Upload +import LocalAiDeploy, { LocalAiDeployHandle } from './LocalAiDeploy' +import useDeployLocalModel from './deployModelUtil' +import RestAIDeploy, { RestAIDeployHandle } from './RestAIDeploy' + export const AIModelGuide = () => { const { modal } = App.useApp() - const [, forceUpdate] = useState(null) - const [form] = Form.useForm() const entityData = useRef(null) - const { fetchData } = useFetch() const navigateTo = useNavigate() - const { checkPermission, accessData } = useGlobalContext() + const { accessData } = useGlobalContext() const modalRef = useRef() + const localAiDeployRef = useRef() + const restAiDeployRef = useRef() + const { deployLocalModel } = useDeployLocalModel() - /** - * 获取 team 选项列表 - * @returns - */ - const getTeamOptionList = async (): any[] => { - const response = await fetchData>( - !checkPermission('system.workspace.team.view_all') ? 'simple/teams/mine' : 'simple/teams', - { method: 'GET', eoTransformKeys: [] } - ) - const { code, data, msg } = response - if (code === STATUS_CODE.SUCCESS) { - const teamOptionList = data.teams?.map((x: MemberItem) => { - return { ...x, label: x.name, value: x.id } - }) - if (form.getFieldValue('team') === undefined && data.teams?.length) { - form.setFieldValue('team', data.teams[0].id) - } - return teamOptionList - } else { - message.error(msg || $t(RESPONSE_TIPS.error)) - return [] - } - } - - /** - * 部署 rest 服务 - * @param file - * @returns - */ - const deployRestServer = async (file: File) => { - return new Promise((resolve, reject) => { - const formData = new FormData() - formData.append('file', file) - formData.append('type', file.type) - formData.append('team', form.getFieldValue('team')) - fetchData>('quick/service/rest', { - method: 'POST', - body: formData - }).then((response) => { - const { code, msg } = response - if (code === STATUS_CODE.SUCCESS) { - message.success(msg || $t(RESPONSE_TIPS.success)) - resolve(true) - } else { - message.error(msg || $t(RESPONSE_TIPS.error)) - reject(false) - } - }) - }) - } - - const deployPopularModel = async (id: string, modalInstance: any) => { - await deployLocalModel({ - modelID: id, - team: form.getFieldValue('team') - }) - modalInstance.destroy() - navigateTo(`/service/list`) - } - - /** - * 部署本地模型 - * @param value - * @returns - */ - const deployLocalModel = (value: { modelID: string; team?: number }) => { - return new Promise((resolve, reject) => { - fetchData>('model/local/deploy/start', { - method: 'POST', - eoBody: { - model: value.modelID, - team: value?.team - } - }) - .then((response) => { - const { code, msg } = response - if (code === STATUS_CODE.SUCCESS) { - message.success(msg || $t(RESPONSE_TIPS.success)) - resolve(true) - } else { - message.error(msg || $t(RESPONSE_TIPS.error)) - reject(false) - } - }) - .catch((errorInfo) => reject(errorInfo)) - }) - } - - /** - * 获取本地模型列表 - * @returns 本地模型列表 - */ - const getLocalModelList = async (): any[] => { - const response = await fetchData>( - 'http://uat.apikit.com:11204/mockApi/aoplatform/api/v1/model/local/can_deploy', - // 'model/local/can_deploy' - { method: 'GET', custom: true, eoTransformKeys: ['is_popular'] } - ) - // TODO_数据模拟 - if (response.ok) { - const datas = await response.json() - const { code, data, msg } = datas - if (code === STATUS_CODE.SUCCESS) { - const modelList = data.models?.map((x: LocalModelItem) => { - return { ...x, label: x.name, value: x.id } - }) - return modelList - } else { - message.error(msg || $t(RESPONSE_TIPS.error)) - return [] - } - } else { - console.error('HTTP error', response.status) - } - // const { code, data, msg } = response - // if (code === STATUS_CODE.SUCCESS) { - // const modelList = data.models?.map((x: LocalModelItem) => { - // return { ...x, label: x.name, value: x.id } - // }) - // console.log('modelList===', modelList); - - // return modelList - // } else { - // message.error(msg || $t(RESPONSE_TIPS.error)) - // return [] - // } + const dumpServerPage = () => { + navigateTo('/service/list') } /** * rest 服务卡片点击事件 */ const restCardClick = async () => { - form.resetFields() - const teamList = await getTeamOptionList() - const props: UploadProps = { - name: 'file', - multiple: false, - maxCount: 1, - beforeUpload: (file) => { - form.setFieldsValue({ key: file }) - forceUpdate({}) - return false - } - } - modal.confirm({ title: $t('添加 Rest 服务'), - content: ( - -
- - -

- -

-

{$t('选择 OpenAPI 文件 (.json / .yaml)')}

-
-
- - - -
-
- ), + content: , onOk: () => { - return new Promise((resolve, reject) => { - form - .validateFields() - .then(async (value) => { - await deployRestServer(value.key.file) - resolve(true) - navigateTo(`/service/list`) - }) - .catch((errorInfo) => reject(errorInfo)) + return restAiDeployRef.current?.deployRestAIServer().then((res) => { + if (res === true) { + dumpServerPage() + } }) }, width: 600, @@ -251,7 +74,7 @@ export const AIModelGuide = () => { onOk: () => { return modalRef.current?.deployAIServer().then((res) => { if (res === true) { - navigateTo(`/service/list`) + dumpServerPage() } }) }, @@ -286,80 +109,17 @@ export const AIModelGuide = () => { * 本地部署 AI 并生成 API */ const localModelCardClick = async () => { - form.resetFields() - const teamList = await getTeamOptionList() - const modelList = await getLocalModelList() const modalInstance = modal.confirm({ title: $t('部署 AI 模型'), - content: ( - -
- - -
- - {$t('热点模型')} -
-
- {modelList.length && - modelList - .filter((item) => item.is_popular) - .map((item) => ( - { - deployPopularModel(item.id, modalInstance) - }} - > - {item.name} - - ))} -
-
- - - -
-
- ), + content: { + modalInstance.destroy() + dumpServerPage() + }}>, onOk: () => { - return new Promise((resolve, reject) => { - form - .validateFields() - .then(async (value) => { - await deployLocalModel(value) - resolve(true) - navigateTo(`/service/list`) - }) - .catch((errorInfo) => reject(errorInfo)) + return localAiDeployRef.current?.deployLocalAIServer().then((res) => { + if (res === true) { + dumpServerPage() + } }) }, width: 600, diff --git a/frontend/packages/core/src/pages/guide/LocalAiDeploy.tsx b/frontend/packages/core/src/pages/guide/LocalAiDeploy.tsx new file mode 100644 index 00000000..639254ad --- /dev/null +++ b/frontend/packages/core/src/pages/guide/LocalAiDeploy.tsx @@ -0,0 +1,145 @@ +import { Icon } from '@iconify/react/dist/iconify.js' +import WithPermission from '@common/components/aoplatform/WithPermission' +import { BasicResponse, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const' +import { Form, message, Select } from 'antd' +import { $t } from '@common/locales' +import { LocalModelItem, SimpleTeamItem } from '@common/const/type' +import { useFetch } from '@common/hooks/http' +import { forwardRef, useEffect, useImperativeHandle, useState } from 'react' +import useDeployLocalModel from './deployModelUtil' +export type LocalAiDeployHandle = { + deployLocalAIServer: () => Promise +} +const LocalAiDeploy = forwardRef((props: any, ref: any) => { + const { onClose } = props + const [form] = Form.useForm() + const { fetchData } = useFetch() + const [modelList, setModelList] = useState([]) + const [teamList, setTeamList] = useState([]) + const { deployLocalModel, getTeamOptionList } = useDeployLocalModel() + + /** + * 获取本地模型列表 + * @returns 本地模型列表 + */ + const getLocalModelList = async () => { + const response = await fetchData>( + 'model/local/can_deploy', + { method: 'GET', eoTransformKeys: ['is_popular'] } + ) + const { code, data, msg } = response + if (code === STATUS_CODE.SUCCESS) { + const modelList = data.models?.map((x: LocalModelItem) => { + return { ...x, label: x.name, value: x.id } + }) + setModelList(modelList) + } else { + message.error(msg || $t(RESPONSE_TIPS.error)) + return [] + } + } + + /** + * 部署热门模型 + * @param id 模型ID + * @returns + */ + const deployPopularModel = async (id: string) => { + await deployLocalModel({ + modelID: id, + team: form.getFieldValue('team') + }) + onClose?.() + } + + const getTeamList = async () => { + const teamOptionList = await getTeamOptionList() + setTeamList(teamOptionList) + if (form.getFieldValue('team') === undefined && teamOptionList.length) { + form.setFieldValue('team', teamOptionList[0].value) + } + } + useEffect(() => { + getLocalModelList() + getTeamList() + }, []) + + /** + * 部署本地AI + * @returns + */ + const deployLocalAIServer = () => { + return new Promise((resolve, reject) => { + form + .validateFields() + .then(async (value) => { + await deployLocalModel(value) + resolve(true) + }) + .catch((errorInfo) => reject(errorInfo)) + }) + } + + useImperativeHandle(ref, () => ({ + deployLocalAIServer + })) + return ( + +
+ + +
+ + {$t('热点模型')} +
+
+ {modelList.length ? + modelList + .filter((item) => item.is_popular) + .map((item) => ( + { + deployPopularModel(item.id) + }} + > + {item.name} + + )) : null} +
+
+ + + +
+
+ ) +}) + +export default LocalAiDeploy diff --git a/frontend/packages/core/src/pages/guide/RestAIDeploy.tsx b/frontend/packages/core/src/pages/guide/RestAIDeploy.tsx new file mode 100644 index 00000000..01ac1c0c --- /dev/null +++ b/frontend/packages/core/src/pages/guide/RestAIDeploy.tsx @@ -0,0 +1,125 @@ +import { Icon } from '@iconify/react/dist/iconify.js' +import WithPermission from '@common/components/aoplatform/WithPermission' +import { BasicResponse, PLACEHOLDER, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const' +import { Upload, UploadProps, Form, message, Select } from 'antd' +import { $t } from '@common/locales' +import { SimpleTeamItem } from '@common/const/type' +import { useFetch } from '@common/hooks/http' +import { forwardRef, useEffect, useImperativeHandle, useState } from 'react' +import useDeployLocalModel from './deployModelUtil' + +const { Dragger } = Upload +export type RestAIDeployHandle = { + deployRestAIServer: () => Promise +} +const RestAIDeploy = forwardRef((props: any, ref: any) => { + const [form] = Form.useForm() + const { fetchData } = useFetch() + const [teamList, setTeamList] = useState([]) + const { getTeamOptionList } = useDeployLocalModel() + + const uploadProps: UploadProps = { + name: 'file', + multiple: false, + maxCount: 1, + beforeUpload: (file) => { + form.setFieldsValue({ key: file }) + return false + } + } + const getTeamList = async () => { + const teamOptionList = await getTeamOptionList() + setTeamList(teamOptionList) + if (form.getFieldValue('team') === undefined && teamOptionList.length) { + form.setFieldValue('team', teamOptionList[0].value) + } + } + useEffect(() => { + getTeamList() + }, []) + + /** + * 部署 rest 服务 + * @param file + * @returns + */ + const deployRestServer = async (file: File) => { + return new Promise((resolve, reject) => { + const formData = new FormData() + formData.append('file', file) + formData.append('type', file.type) + formData.append('team', form.getFieldValue('team')) + fetchData>('quick/service/rest', { + method: 'POST', + body: formData + }).then((response) => { + const { code, msg } = response + if (code === STATUS_CODE.SUCCESS) { + message.success(msg || $t(RESPONSE_TIPS.success)) + resolve(true) + } else { + message.error(msg || $t(RESPONSE_TIPS.error)) + reject(false) + } + }) + }) + } + + /** + * 部署本地AI + * @returns + */ + const deployRestAIServer = () => { + return new Promise((resolve, reject) => { + form + .validateFields() + .then(async (value) => { + await deployRestServer(value.key.file) + resolve(true) + }) + .catch((errorInfo) => reject(errorInfo)) + }) + } + + useImperativeHandle(ref, () => ({ + deployRestAIServer + })) + return ( + +
+ + +

+ +

+

{$t('选择 OpenAPI 文件 (.json / .yaml)')}

+
+
+ + + +
+
+ ) +}) + +export default RestAIDeploy diff --git a/frontend/packages/core/src/pages/guide/deployModelUtil.ts b/frontend/packages/core/src/pages/guide/deployModelUtil.ts new file mode 100644 index 00000000..f442a7ad --- /dev/null +++ b/frontend/packages/core/src/pages/guide/deployModelUtil.ts @@ -0,0 +1,57 @@ +// deployModelUtil.ts +import { useFetch } from '@common/hooks/http' +import { message } from 'antd' +import { STATUS_CODE, RESPONSE_TIPS, BasicResponse } from '@common/const/const' +import { $t } from '@common/locales' +import { MemberItem, SimpleTeamItem } from '@common/const/type' +import { useGlobalContext } from '@common/contexts/GlobalStateContext' + +const useDeployLocalModel = () => { + const { fetchData } = useFetch() + const { checkPermission } = useGlobalContext() + const deployLocalModel = (value: { modelID: string; team?: number }) => { + return new Promise((resolve, reject) => { + fetchData>('model/local/deploy/start', { + method: 'POST', + eoBody: { + model: value.modelID, + team: value?.team + } + }) + .then((response) => { + const { code, msg } = response + if (code === STATUS_CODE.SUCCESS) { + message.success(msg || $t(RESPONSE_TIPS.success)) + resolve(true) + } else { + message.error(msg || $t(RESPONSE_TIPS.error)) + reject(false) + } + }) + .catch((errorInfo) => reject(errorInfo)) + }) + } + /** + * 获取 team 选项列表 + * @returns + */ + const getTeamOptionList = async (): any[] => { + const response = await fetchData>( + !checkPermission('system.workspace.team.view_all') ? 'simple/teams/mine' : 'simple/teams', + { method: 'GET', eoTransformKeys: [] } + ) + const { code, data, msg } = response + if (code === STATUS_CODE.SUCCESS) { + const teamOptionList = data.teams?.map((x: MemberItem) => { + return { ...x, label: x.name, value: x.id } + }) + return teamOptionList + } else { + message.error(msg || $t(RESPONSE_TIPS.error)) + return [] + } + } + return { deployLocalModel, getTeamOptionList } +} + +export default useDeployLocalModel