From 265a7a283ae1a29a4827d2a973d62cad14c41dc5 Mon Sep 17 00:00:00 2001 From: balibabu <cike8899@users.noreply.github.com> Date: Mon, 8 Apr 2024 19:13:45 +0800 Subject: [PATCH] feat: add support for ollama #221 (#260) ### What problem does this PR solve? add support for ollama Issue link:#221 ### Type of change - [x] New Feature (non-breaking change which adds functionality) --- web/src/assets/svg/llm/github.svg | 10 ++ web/src/assets/svg/llm/google.svg | 13 +++ .../{icons => assets/svg/llm}/moonshot.svg | 0 web/src/assets/svg/llm/ollama.svg | 9 ++ web/src/{icons => assets/svg/llm}/openai.svg | 0 web/src/{icons => assets/svg/llm}/tongyi.svg | 0 web/src/{icons => assets/svg/llm}/wenxin.svg | 0 web/src/{icons => assets/svg/llm}/zhipu.svg | 0 web/src/components/svg-icon.tsx | 7 +- web/src/hooks/llmHooks.ts | 17 ++++ web/src/interfaces/common.ts | 8 ++ web/src/interfaces/request/llm.ts | 6 ++ web/src/locales/en.ts | 8 ++ web/src/locales/zh.ts | 8 ++ web/src/pages/user-setting/model.ts | 11 +++ .../setting-model/api-key-modal/index.tsx | 6 +- .../pages/user-setting/setting-model/hooks.ts | 30 ++++++ .../user-setting/setting-model/index.tsx | 60 ++++++++---- .../setting-model/ollama-modal/index.tsx | 96 +++++++++++++++++++ .../system-model-setting-modal/index.tsx | 6 +- web/src/services/userService.ts | 5 + web/src/utils/api.ts | 1 + 22 files changed, 275 insertions(+), 26 deletions(-) create mode 100644 web/src/assets/svg/llm/github.svg create mode 100644 web/src/assets/svg/llm/google.svg rename web/src/{icons => assets/svg/llm}/moonshot.svg (100%) create mode 100644 web/src/assets/svg/llm/ollama.svg rename web/src/{icons => assets/svg/llm}/openai.svg (100%) rename web/src/{icons => assets/svg/llm}/tongyi.svg (100%) rename web/src/{icons => assets/svg/llm}/wenxin.svg (100%) rename web/src/{icons => assets/svg/llm}/zhipu.svg (100%) create mode 100644 web/src/interfaces/request/llm.ts create mode 100644 web/src/pages/user-setting/setting-model/ollama-modal/index.tsx diff --git a/web/src/assets/svg/llm/github.svg b/web/src/assets/svg/llm/github.svg new file mode 100644 index 0000000..6f80a87 --- /dev/null +++ b/web/src/assets/svg/llm/github.svg @@ -0,0 +1,10 @@ +<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_660_5)"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M8.50662 0.453613C4.07917 0.453613 0.5 4.05917 0.5 8.51972C0.5 12.0853 2.79329 15.1035 5.9747 16.1717C6.37246 16.252 6.51816 15.9981 6.51816 15.7846C6.51816 15.5976 6.50505 14.9566 6.50505 14.2888C4.2778 14.7696 3.81399 13.3272 3.81399 13.3272C3.45606 12.3924 2.92572 12.1522 2.92572 12.1522C2.19674 11.658 2.97882 11.658 2.97882 11.658C3.78744 11.7115 4.21175 12.486 4.21175 12.486C4.92745 13.7145 6.08074 13.3674 6.54471 13.1537C6.61092 12.6328 6.82315 12.2723 7.0485 12.072C5.27211 11.885 3.40312 11.1906 3.40312 8.0923C3.40312 7.21091 3.72107 6.4898 4.22486 5.92897C4.14538 5.7287 3.86693 4.90057 4.30451 3.79219C4.30451 3.79219 4.98055 3.57848 6.50488 4.62016C7.1575 4.44359 7.83054 4.35377 8.50662 4.35302C9.18266 4.35302 9.87181 4.4466 10.5082 4.62016C12.0327 3.57848 12.7087 3.79219 12.7087 3.79219C13.1463 4.90057 12.8677 5.7287 12.7882 5.92897C13.3053 6.4898 13.6101 7.21091 13.6101 8.0923C13.6101 11.1906 11.7411 11.8716 9.95146 12.072C10.2432 12.3257 10.4949 12.8064 10.4949 13.5677C10.4949 14.6493 10.4818 15.5174 10.4818 15.7844C10.4818 15.9981 10.6277 16.252 11.0253 16.1719C14.2067 15.1033 16.5 12.0853 16.5 8.51972C16.5131 4.05917 12.9208 0.453613 8.50662 0.453613Z" fill="#24292F"/> +</g> +<defs> +<clipPath id="clip0_660_5"> +<rect width="16" height="16" fill="white" transform="translate(0.5 0.453613)"/> +</clipPath> +</defs> +</svg> diff --git a/web/src/assets/svg/llm/google.svg b/web/src/assets/svg/llm/google.svg new file mode 100644 index 0000000..f0d10ec --- /dev/null +++ b/web/src/assets/svg/llm/google.svg @@ -0,0 +1,13 @@ +<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_660_28)"> +<path d="M8 6.99902V10.0972H12.3054C12.1164 11.0936 11.549 11.9372 10.6981 12.5045L13.2945 14.5191C14.8072 13.1227 15.68 11.0718 15.68 8.63547C15.68 8.0682 15.6291 7.5227 15.5345 6.99911L8 6.99902Z" fill="#4285F4"/> +<path d="M3.51649 9.97632L2.93092 10.4246L0.858154 12.0391C2.17451 14.65 4.8725 16.4536 7.99974 16.4536C10.1597 16.4536 11.9706 15.7409 13.2942 14.5191L10.6979 12.5046C9.98516 12.9846 9.07606 13.2755 7.99974 13.2755C5.91976 13.2755 4.15254 11.8719 3.51976 9.98094L3.51649 9.97632Z" fill="#34A853"/> +<path d="M0.858119 4.86816C0.312695 5.94448 0 7.15905 0 8.45357C0 9.74809 0.312695 10.9627 0.858119 12.039C0.858119 12.0462 3.51998 9.97352 3.51998 9.97352C3.35998 9.49352 3.26541 8.98446 3.26541 8.45349C3.26541 7.92251 3.35998 7.41345 3.51998 6.93345L0.858119 4.86816Z" fill="#FBBC05"/> +<path d="M7.99991 3.63907C9.17811 3.63907 10.2254 4.04633 11.0617 4.83179L13.3526 2.54091C11.9635 1.24639 10.1599 0.453613 7.99991 0.453613C4.87266 0.453613 2.17451 2.24997 0.858154 4.86816L3.51994 6.93362C4.15263 5.04269 5.91992 3.63907 7.99991 3.63907Z" fill="#EA4335"/> +</g> +<defs> +<clipPath id="clip0_660_28"> +<rect width="16" height="16" fill="white" transform="translate(0 0.453613)"/> +</clipPath> +</defs> +</svg> diff --git a/web/src/icons/moonshot.svg b/web/src/assets/svg/llm/moonshot.svg similarity index 100% rename from web/src/icons/moonshot.svg rename to web/src/assets/svg/llm/moonshot.svg diff --git a/web/src/assets/svg/llm/ollama.svg b/web/src/assets/svg/llm/ollama.svg new file mode 100644 index 0000000..6e9fb28 --- /dev/null +++ b/web/src/assets/svg/llm/ollama.svg @@ -0,0 +1,9 @@ +<svg width="133" height="185" viewBox="0 0 133 185" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<rect width="133" height="185" fill="url(#pattern0)"/> +<defs> +<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1"> +<use xlink:href="#image0_406_1657" transform="matrix(0.00552486 0 0 0.00397193 0 -0.00840675)"/> +</pattern> +<image id="image0_406_1657" width="181" height="256" xlink:href="data:image/png;base64,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"/> +</defs> +</svg> diff --git a/web/src/icons/openai.svg b/web/src/assets/svg/llm/openai.svg similarity index 100% rename from web/src/icons/openai.svg rename to web/src/assets/svg/llm/openai.svg diff --git a/web/src/icons/tongyi.svg b/web/src/assets/svg/llm/tongyi.svg similarity index 100% rename from web/src/icons/tongyi.svg rename to web/src/assets/svg/llm/tongyi.svg diff --git a/web/src/icons/wenxin.svg b/web/src/assets/svg/llm/wenxin.svg similarity index 100% rename from web/src/icons/wenxin.svg rename to web/src/assets/svg/llm/wenxin.svg diff --git a/web/src/icons/zhipu.svg b/web/src/assets/svg/llm/zhipu.svg similarity index 100% rename from web/src/icons/zhipu.svg rename to web/src/assets/svg/llm/zhipu.svg diff --git a/web/src/components/svg-icon.tsx b/web/src/components/svg-icon.tsx index f740f2c..2171fc4 100644 --- a/web/src/components/svg-icon.tsx +++ b/web/src/components/svg-icon.tsx @@ -21,13 +21,16 @@ try { interface IProps extends IconComponentProps { name: string; width: string | number; + height?: string | number; } -const SvgIcon = ({ name, width, ...restProps }: IProps) => { +const SvgIcon = ({ name, width, height, ...restProps }: IProps) => { const ListItem = routeList.find((item) => item.name === name); return ( <Icon - component={() => <img src={ListItem?.value} alt="" width={width} />} + component={() => ( + <img src={ListItem?.value} alt="" width={width} height={height} /> + )} {...(restProps as any)} /> ); diff --git a/web/src/hooks/llmHooks.ts b/web/src/hooks/llmHooks.ts index 3e2e757..9068ebd 100644 --- a/web/src/hooks/llmHooks.ts +++ b/web/src/hooks/llmHooks.ts @@ -4,6 +4,7 @@ import { IMyLlmValue, IThirdOAIModelCollection, } from '@/interfaces/database/llm'; +import { IAddLlmRequestBody } from '@/interfaces/request/llm'; import { useCallback, useEffect, useMemo } from 'react'; import { useDispatch, useSelector } from 'umi'; @@ -206,3 +207,19 @@ export const useSaveTenantInfo = () => { return saveTenantInfo; }; + +export const useAddLlm = () => { + const dispatch = useDispatch(); + + const saveTenantInfo = useCallback( + (requestBody: IAddLlmRequestBody) => { + return dispatch<any>({ + type: 'settingModel/add_llm', + payload: requestBody, + }); + }, + [dispatch], + ); + + return saveTenantInfo; +}; diff --git a/web/src/interfaces/common.ts b/web/src/interfaces/common.ts index 518d077..76a385f 100644 --- a/web/src/interfaces/common.ts +++ b/web/src/interfaces/common.ts @@ -7,3 +7,11 @@ export interface BaseState { pagination: Pagination; searchString: string; } + +export interface IModalProps<T> { + showModal?(): void; + hideModal(): void; + visible: boolean; + loading?: boolean; + onOk?(payload?: T): Promise<void> | void; +} diff --git a/web/src/interfaces/request/llm.ts b/web/src/interfaces/request/llm.ts new file mode 100644 index 0000000..0505c0a --- /dev/null +++ b/web/src/interfaces/request/llm.ts @@ -0,0 +1,6 @@ +export interface IAddLlmRequestBody { + llm_factory: string; // Ollama + llm_name: string; + model_type: string; + api_base?: string; // chat|embedding|speech2text|image2text +} diff --git a/web/src/locales/en.ts b/web/src/locales/en.ts index 661af3c..b6d1cec 100644 --- a/web/src/locales/en.ts +++ b/web/src/locales/en.ts @@ -390,6 +390,14 @@ export default { 'The default ASR model all the newly created knowledgebase will use. Use this model to translate voices to corresponding text.', workspace: 'Workspace', upgrade: 'Upgrade', + addLlmTitle: 'Add LLM', + modelName: 'Model name', + modelNameMessage: 'Please input your model name!', + modelType: 'Model type', + modelTypeMessage: 'Please input your model type!', + addLlmBaseUrl: 'Base url', + baseUrlNameMessage: 'Please input your base url!', + vision: 'Does it support Vision?', }, message: { registered: 'Registered!', diff --git a/web/src/locales/zh.ts b/web/src/locales/zh.ts index e2165ea..a8b18fb 100644 --- a/web/src/locales/zh.ts +++ b/web/src/locales/zh.ts @@ -375,6 +375,14 @@ export default { '所有新创建的知识库都将使用默认的 ASR 模型。 使用æ¤æ¨¡åž‹å°†è¯éŸ³ç¿»è¯‘为相应的文本。', workspace: '工作空间', upgrade: 'å‡çº§', + addLlmTitle: 'æ·»åŠ LLM', + modelName: '模型å称', + modelType: '模型类型', + addLlmBaseUrl: '基础 Url', + vision: '是å¦æ”¯æŒ Vision', + modelNameMessage: '请输入模型å称ï¼', + modelTypeMessage: '请输入模型类型ï¼', + baseUrlNameMessage: '请输入基础 Urlï¼', }, message: { registered: '注册æˆåŠŸ', diff --git a/web/src/pages/user-setting/model.ts b/web/src/pages/user-setting/model.ts index fa4add7..da2ceed 100644 --- a/web/src/pages/user-setting/model.ts +++ b/web/src/pages/user-setting/model.ts @@ -151,6 +151,17 @@ const model: DvaModel<SettingModelState> = { } return retcode; }, + *add_llm({ payload = {} }, { call, put }) { + const { data } = yield call(userService.add_llm, payload); + const { retcode } = data; + if (retcode === 0) { + message.success(i18n.t('message.modified')); + + yield put({ type: 'my_llm' }); + yield put({ type: 'factories_list' }); + } + return retcode; + }, }, }; export default model; diff --git a/web/src/pages/user-setting/setting-model/api-key-modal/index.tsx b/web/src/pages/user-setting/setting-model/api-key-modal/index.tsx index 7a48507..f841cba 100644 --- a/web/src/pages/user-setting/setting-model/api-key-modal/index.tsx +++ b/web/src/pages/user-setting/setting-model/api-key-modal/index.tsx @@ -46,8 +46,10 @@ const ApiKeyModal = ({ }; useEffect(() => { - form.setFieldValue('api_key', initialValue); - }, [initialValue, form]); + if (visible) { + form.setFieldValue('api_key', initialValue); + } + }, [initialValue, form, visible]); return ( <Modal diff --git a/web/src/pages/user-setting/setting-model/hooks.ts b/web/src/pages/user-setting/setting-model/hooks.ts index f36aa02..5e9bd8c 100644 --- a/web/src/pages/user-setting/setting-model/hooks.ts +++ b/web/src/pages/user-setting/setting-model/hooks.ts @@ -2,6 +2,7 @@ import { useSetModalState } from '@/hooks/commonHooks'; import { IApiKeySavingParams, ISystemModelSettingSavingParams, + useAddLlm, useFetchLlmList, useSaveApiKey, useSaveTenantInfo, @@ -12,6 +13,7 @@ import { useFetchTenantInfo, useSelectTenantInfo, } from '@/hooks/userSettingHook'; +import { IAddLlmRequestBody } from '@/interfaces/request/llm'; import { useCallback, useEffect, useState } from 'react'; type SavingParamsState = Omit<IApiKeySavingParams, 'api_key'>; @@ -127,3 +129,31 @@ export const useSelectModelProvidersLoading = () => { return loading; }; + +export const useSubmitOllama = () => { + const loading = useOneNamespaceEffectsLoading('settingModel', ['add_llm']); + const addLlm = useAddLlm(); + const { + visible: llmAddingVisible, + hideModal: hideLlmAddingModal, + showModal: showLlmAddingModal, + } = useSetModalState(); + + const onLlmAddingOk = useCallback( + async (payload: IAddLlmRequestBody) => { + const ret = await addLlm(payload); + if (ret === 0) { + hideLlmAddingModal(); + } + }, + [hideLlmAddingModal, addLlm], + ); + + return { + llmAddingLoading: loading, + onLlmAddingOk, + llmAddingVisible, + hideLlmAddingModal, + showLlmAddingModal, + }; +}; diff --git a/web/src/pages/user-setting/setting-model/index.tsx b/web/src/pages/user-setting/setting-model/index.tsx index 03dd050..272ffb5 100644 --- a/web/src/pages/user-setting/setting-model/index.tsx +++ b/web/src/pages/user-setting/setting-model/index.tsx @@ -1,15 +1,11 @@ import { ReactComponent as MoreModelIcon } from '@/assets/svg/more-model.svg'; +import SvgIcon from '@/components/svg-icon'; import { useSetModalState, useTranslate } from '@/hooks/commonHooks'; import { LlmItem, useFetchLlmFactoryListOnMount, useFetchMyLlmListOnMount, } from '@/hooks/llmHooks'; -import { ReactComponent as MoonshotIcon } from '@/icons/moonshot.svg'; -import { ReactComponent as OpenAiIcon } from '@/icons/openai.svg'; -import { ReactComponent as TongYiIcon } from '@/icons/tongyi.svg'; -import { ReactComponent as WenXinIcon } from '@/icons/wenxin.svg'; -import { ReactComponent as ZhiPuIcon } from '@/icons/zhipu.svg'; import { SettingOutlined, UserOutlined } from '@ant-design/icons'; import { Avatar, @@ -33,24 +29,27 @@ import ApiKeyModal from './api-key-modal'; import { useSelectModelProvidersLoading, useSubmitApiKey, + useSubmitOllama, useSubmitSystemModelSetting, } from './hooks'; -import SystemModelSettingModal from './system-model-setting-modal'; - import styles from './index.less'; +import OllamaModal from './ollama-modal'; +import SystemModelSettingModal from './system-model-setting-modal'; const IconMap = { - 'Tongyi-Qianwen': TongYiIcon, - Moonshot: MoonshotIcon, - OpenAI: OpenAiIcon, - 'ZHIPU-AI': ZhiPuIcon, - 文心一言: WenXinIcon, + 'Tongyi-Qianwen': 'tongyi', + Moonshot: 'moonshot', + OpenAI: 'openai', + 'ZHIPU-AI': 'zhipu', + 文心一言: 'wenxin', + Ollama: 'ollama', }; const LlmIcon = ({ name }: { name: string }) => { - const Icon = IconMap[name as keyof typeof IconMap]; - return Icon ? ( - <Icon width={48} height={48}></Icon> + const icon = IconMap[name as keyof typeof IconMap]; + + return icon ? ( + <SvgIcon name={`llm/${icon}`} width={48} height={48}></SvgIcon> ) : ( <Avatar shape="square" size="large" icon={<UserOutlined />} /> ); @@ -90,7 +89,7 @@ const ModelCard = ({ item, clickApiKey }: IModelCardProps) => { <Col span={12} className={styles.factoryOperationWrapper}> <Space size={'middle'}> <Button onClick={handleApiKeyClick}> - API-Key + {item.name === 'Ollama' ? t('addTheModel') : 'API-Key'} <SettingOutlined /> </Button> <Button onClick={handleShowMoreClick}> @@ -142,16 +141,31 @@ const UserSettingModel = () => { showSystemSettingModal, } = useSubmitSystemModelSetting(); const { t } = useTranslate('setting'); + const { + llmAddingVisible, + hideLlmAddingModal, + showLlmAddingModal, + onLlmAddingOk, + llmAddingLoading, + } = useSubmitOllama(); const handleApiKeyClick = useCallback( (llmFactory: string) => { - showApiKeyModal({ llm_factory: llmFactory }); + if (llmFactory === 'Ollama') { + showLlmAddingModal(); + } else { + showApiKeyModal({ llm_factory: llmFactory }); + } }, - [showApiKeyModal], + [showApiKeyModal, showLlmAddingModal], ); const handleAddModel = (llmFactory: string) => () => { - handleApiKeyClick(llmFactory); + if (llmFactory === 'Ollama') { + showLlmAddingModal(); + } else { + handleApiKeyClick(llmFactory); + } }; const items: CollapseProps['items'] = [ @@ -216,7 +230,7 @@ const UserSettingModel = () => { clickButton={showSystemSettingModal} ></SettingTitle> <Divider></Divider> - <Collapse defaultActiveKey={['1']} ghost items={items} /> + <Collapse defaultActiveKey={['1', '2']} ghost items={items} /> </section> </Spin> <ApiKeyModal @@ -233,6 +247,12 @@ const UserSettingModel = () => { hideModal={hideSystemSettingModal} loading={saveSystemModelSettingLoading} ></SystemModelSettingModal> + <OllamaModal + visible={llmAddingVisible} + hideModal={hideLlmAddingModal} + onOk={onLlmAddingOk} + loading={llmAddingLoading} + ></OllamaModal> </> ); }; diff --git a/web/src/pages/user-setting/setting-model/ollama-modal/index.tsx b/web/src/pages/user-setting/setting-model/ollama-modal/index.tsx new file mode 100644 index 0000000..797de71 --- /dev/null +++ b/web/src/pages/user-setting/setting-model/ollama-modal/index.tsx @@ -0,0 +1,96 @@ +import { useTranslate } from '@/hooks/commonHooks'; +import { IModalProps } from '@/interfaces/common'; +import { IAddLlmRequestBody } from '@/interfaces/request/llm'; +import { Form, Input, Modal, Select, Switch } from 'antd'; +import omit from 'lodash/omit'; + +type FieldType = IAddLlmRequestBody & { vision: boolean }; + +const { Option } = Select; + +const OllamaModal = ({ + visible, + hideModal, + onOk, + loading, +}: IModalProps<IAddLlmRequestBody>) => { + const [form] = Form.useForm<FieldType>(); + + const { t } = useTranslate('setting'); + + const handleOk = async () => { + const values = await form.validateFields(); + const modelType = + values.model_type === 'chat' && values.vision + ? 'image2text' + : values.model_type; + + const data = { + ...omit(values, ['vision']), + model_type: modelType, + llm_factory: 'Ollama', + }; + console.info(data); + + onOk?.(data); + }; + + return ( + <Modal + title={t('addLlmTitle')} + open={visible} + onOk={handleOk} + onCancel={hideModal} + okButtonProps={{ loading }} + > + <Form + name="basic" + style={{ maxWidth: 600 }} + autoComplete="off" + layout={'vertical'} + form={form} + > + <Form.Item<FieldType> + label={t('modelType')} + name="model_type" + initialValue={'chat'} + rules={[{ required: true, message: t('modelTypeMessage') }]} + > + <Select placeholder={t('modelTypeMessage')}> + <Option value="chat">chat</Option> + <Option value="embedding">embedding</Option> + </Select> + </Form.Item> + <Form.Item<FieldType> + label={t('modelName')} + name="llm_name" + rules={[{ required: true, message: t('modelNameMessage') }]} + > + <Input placeholder={t('modelNameMessage')} /> + </Form.Item> + <Form.Item<FieldType> + label={t('addLlmBaseUrl')} + name="api_base" + rules={[{ required: true, message: t('baseUrlNameMessage') }]} + > + <Input placeholder={t('baseUrlNameMessage')} /> + </Form.Item> + <Form.Item noStyle dependencies={['model_type']}> + {({ getFieldValue }) => + getFieldValue('model_type') === 'chat' && ( + <Form.Item + label={t('vision')} + valuePropName="checked" + name={'vision'} + > + <Switch /> + </Form.Item> + ) + } + </Form.Item> + </Form> + </Modal> + ); +}; + +export default OllamaModal; diff --git a/web/src/pages/user-setting/setting-model/system-model-setting-modal/index.tsx b/web/src/pages/user-setting/setting-model/system-model-setting-modal/index.tsx index 53ee206..e3a8149 100644 --- a/web/src/pages/user-setting/setting-model/system-model-setting-modal/index.tsx +++ b/web/src/pages/user-setting/setting-model/system-model-setting-modal/index.tsx @@ -30,8 +30,10 @@ const SystemModelSettingModal = ({ }; useEffect(() => { - form.setFieldsValue(initialValues); - }, [form, initialValues]); + if (visible) { + form.setFieldsValue(initialValues); + } + }, [form, initialValues, visible]); const onFormLayoutChange = () => {}; diff --git a/web/src/services/userService.ts b/web/src/services/userService.ts index 665a7d5..9f25516 100644 --- a/web/src/services/userService.ts +++ b/web/src/services/userService.ts @@ -14,6 +14,7 @@ const { my_llm, set_api_key, set_tenant_info, + add_llm, } = api; const methods = { @@ -61,6 +62,10 @@ const methods = { url: set_api_key, method: 'post', }, + add_llm: { + url: add_llm, + method: 'post', + }, } as const; const userService = registerServer<keyof typeof methods>(methods, request); diff --git a/web/src/utils/api.ts b/web/src/utils/api.ts index e64c169..54b1b12 100644 --- a/web/src/utils/api.ts +++ b/web/src/utils/api.ts @@ -17,6 +17,7 @@ export default { llm_list: `${api_host}/llm/list`, my_llm: `${api_host}/llm/my_llms`, set_api_key: `${api_host}/llm/set_api_key`, + add_llm: `${api_host}/llm/add_llm`, //çŸ¥è¯†åº“ç®¡ç† kb_list: `${api_host}/kb/list`, -- GitLab