mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-02-07 02:55:08 +08:00
Feat: Add model verify (#13005)
### What problem does this PR solve? Feat: Add model verify ### Type of change - [x] New Feature (non-breaking change which adds functionality) --------- Co-authored-by: Liu An <asiro@qq.com>
This commit is contained in:
@ -77,7 +77,14 @@ if (process.env.NODE_ENV === 'development') {
|
||||
},
|
||||
);
|
||||
}
|
||||
const queryClient = new QueryClient();
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
refetchOnWindowFocus: false,
|
||||
retry: 2,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
type Locale = ConfigProviderProps['locale'];
|
||||
|
||||
|
||||
@ -119,17 +119,19 @@ export const ConfirmDeleteDialogNode = ({
|
||||
}) => {
|
||||
return (
|
||||
<div className="flex flex-col gap-2.5">
|
||||
<div className="flex items-center border-0.5 text-text-secondary border-border-button rounded-lg px-3 py-4">
|
||||
{avatar && (
|
||||
<RAGFlowAvatar
|
||||
className="w-8 h-8"
|
||||
avatar={avatar.avatar}
|
||||
isPerson={avatar.isPerson}
|
||||
name={avatar.name}
|
||||
/>
|
||||
)}
|
||||
{name && <div className="ml-3">{name}</div>}
|
||||
</div>
|
||||
{(avatar || name) && (
|
||||
<div className="flex items-center border-0.5 text-text-secondary border-border-button rounded-lg px-3 py-4">
|
||||
{avatar && (
|
||||
<RAGFlowAvatar
|
||||
className="w-8 h-8"
|
||||
avatar={avatar.avatar}
|
||||
isPerson={avatar.isPerson}
|
||||
name={avatar.name}
|
||||
/>
|
||||
)}
|
||||
{name && <div className="ml-3">{name}</div>}
|
||||
</div>
|
||||
)}
|
||||
{warnText && <div className="text-state-error text-xs">{warnText}</div>}
|
||||
{children}
|
||||
</div>
|
||||
|
||||
@ -271,11 +271,12 @@ export interface IApiKeySavingParams {
|
||||
llm_name?: string;
|
||||
model_type?: string;
|
||||
base_url?: string;
|
||||
verify?: boolean;
|
||||
}
|
||||
|
||||
export const useSaveApiKey = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
// const { t } = useTranslation();
|
||||
const {
|
||||
data,
|
||||
isPending: loading,
|
||||
@ -285,14 +286,14 @@ export const useSaveApiKey = () => {
|
||||
mutationFn: async (params: IApiKeySavingParams) => {
|
||||
const { data } = await userService.set_api_key(params);
|
||||
if (data.code === 0) {
|
||||
message.success(t('message.modified'));
|
||||
// message.success(t('message.modified'));
|
||||
queryClient.invalidateQueries({ queryKey: [LLMApiAction.MyLlmList] });
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [LLMApiAction.MyLlmListDetailed],
|
||||
});
|
||||
queryClient.invalidateQueries({ queryKey: [LLMApiAction.FactoryList] });
|
||||
}
|
||||
return data.code;
|
||||
return data;
|
||||
},
|
||||
});
|
||||
|
||||
@ -330,25 +331,25 @@ export const useSaveTenantInfo = () => {
|
||||
|
||||
export const useAddLlm = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
// const { t } = useTranslation();
|
||||
const {
|
||||
data,
|
||||
isPending: loading,
|
||||
mutateAsync,
|
||||
} = useMutation({
|
||||
mutationKey: [LLMApiAction.AddLlm],
|
||||
mutationFn: async (params: IAddLlmRequestBody) => {
|
||||
mutationFn: async (params: IAddLlmRequestBody & { verify?: boolean }) => {
|
||||
const { data } = await userService.add_llm(params);
|
||||
if (data.code === 0) {
|
||||
if (data.code === 0 && !params.verify) {
|
||||
queryClient.invalidateQueries({ queryKey: [LLMApiAction.MyLlmList] });
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [LLMApiAction.MyLlmListDetailed],
|
||||
});
|
||||
queryClient.invalidateQueries({ queryKey: [LLMApiAction.FactoryList] });
|
||||
queryClient.invalidateQueries({ queryKey: [LLMApiAction.LlmList] });
|
||||
message.success(t('message.modified'));
|
||||
// message.success(t('message.modified'));
|
||||
}
|
||||
return data.code;
|
||||
return data;
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@ -61,6 +61,7 @@ export default {
|
||||
tokenPlaceholder: 'e.g. eyJhbGciOiJIUzI1Ni...',
|
||||
},
|
||||
selected: 'Selected',
|
||||
seeAll: 'See all',
|
||||
},
|
||||
login: {
|
||||
loginTitle: 'Sign in to your account',
|
||||
@ -889,6 +890,9 @@ This auto-tagging feature enhances retrieval by adding another layer of domain-s
|
||||
deleteSelectedConfirm: 'Delete the selected {count} session(s)?',
|
||||
},
|
||||
setting: {
|
||||
Verify: 'Verify',
|
||||
keyValid: 'Your API key is valid.',
|
||||
keyInvalid: 'Your API key is invalid.',
|
||||
deleteModel: 'Delete model',
|
||||
bedrockCredentialsHint:
|
||||
'Tip: Leave Access Key / Secret Key blank to use AWS IAM authentication.',
|
||||
|
||||
@ -56,6 +56,7 @@ export default {
|
||||
zendeskDescription: '连接 Zendesk,同步工单、文章及其他内容。',
|
||||
promptPlaceholder: '请输入或使用 / 快速插入变量。',
|
||||
selected: '已选择',
|
||||
seeAll: '查看全部',
|
||||
},
|
||||
login: {
|
||||
loginTitle: '登录账户',
|
||||
@ -835,6 +836,9 @@ General:实体和关系提取提示来自 GitHub - microsoft/graphrag:基于
|
||||
deleteSelectedConfirm: '删除选中的 {count} 个会话?',
|
||||
},
|
||||
setting: {
|
||||
Verify: '验证',
|
||||
keyValid: '你的 API 密钥有效。',
|
||||
keyInvalid: '你的 API 密钥无效。',
|
||||
deleteModel: '删除模型',
|
||||
modelEmptyTip: '暂无可用模型,<br>请先在右侧面板添加模型。',
|
||||
sourceEmptyTip: '暂未添加任何数据源,请从下方选择一个进行连接。',
|
||||
|
||||
@ -115,7 +115,7 @@ export const ModelProviderCard: FC<IModelCardProps> = ({
|
||||
content={{
|
||||
node: (
|
||||
<ConfirmDeleteDialogNode>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex items-center gap-2 border-0.5 text-text-secondary border-border-button rounded-lg px-3 py-4">
|
||||
<LlmIcon name={item.name} />
|
||||
{item.name}
|
||||
</div>
|
||||
|
||||
@ -20,30 +20,56 @@ import { ApiKeyPostBody } from '../interface';
|
||||
import { MinerUFormValues } from './modal/mineru-modal';
|
||||
|
||||
type SavingParamsState = Omit<IApiKeySavingParams, 'api_key'>;
|
||||
|
||||
export type VerifyResult = {
|
||||
isValid: boolean | null;
|
||||
logs: string;
|
||||
};
|
||||
export const useSubmitApiKey = () => {
|
||||
const [savingParams, setSavingParams] = useState<SavingParamsState>(
|
||||
{} as SavingParamsState,
|
||||
);
|
||||
const [editMode, setEditMode] = useState(false);
|
||||
const { saveApiKey, loading } = useSaveApiKey();
|
||||
const { saveApiKey } = useSaveApiKey();
|
||||
const [saveLoading, setSaveLoading] = useState(false);
|
||||
const {
|
||||
visible: apiKeyVisible,
|
||||
hideModal: hideApiKeyModal,
|
||||
showModal: showApiKeyModal,
|
||||
} = useSetModalState();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const onApiKeySavingOk = useCallback(
|
||||
async (postBody: ApiKeyPostBody) => {
|
||||
async (postBody: ApiKeyPostBody, isVerify = false) => {
|
||||
if (!isVerify) {
|
||||
setSaveLoading(true);
|
||||
}
|
||||
const ret = await saveApiKey({
|
||||
...savingParams,
|
||||
...postBody,
|
||||
verify: isVerify,
|
||||
});
|
||||
|
||||
if (ret === 0) {
|
||||
queryClient.invalidateQueries({ queryKey: ['llmList'] });
|
||||
hideApiKeyModal();
|
||||
setEditMode(false);
|
||||
if (!isVerify) {
|
||||
setSaveLoading(false);
|
||||
if (ret.code === 0) {
|
||||
queryClient.invalidateQueries({ queryKey: ['llmList'] });
|
||||
hideApiKeyModal();
|
||||
setEditMode(false);
|
||||
}
|
||||
}
|
||||
if (isVerify) {
|
||||
let res = {} as VerifyResult;
|
||||
if (ret.data?.success) {
|
||||
res = {
|
||||
isValid: true,
|
||||
logs: ret.data?.message,
|
||||
};
|
||||
} else {
|
||||
res = {
|
||||
isValid: false,
|
||||
logs: ret.data.message,
|
||||
};
|
||||
}
|
||||
return res;
|
||||
}
|
||||
},
|
||||
[hideApiKeyModal, saveApiKey, savingParams, queryClient],
|
||||
@ -59,7 +85,7 @@ export const useSubmitApiKey = () => {
|
||||
);
|
||||
|
||||
return {
|
||||
saveApiKeyLoading: loading,
|
||||
saveApiKeyLoading: saveLoading,
|
||||
initialApiKey: '',
|
||||
llmFactory: savingParams.llm_factory,
|
||||
editMode,
|
||||
@ -119,7 +145,8 @@ export const useSubmitOllama = () => {
|
||||
const [initialValues, setInitialValues] = useState<
|
||||
Partial<IAddLlmRequestBody> & { provider_order?: string }
|
||||
>();
|
||||
const { addLlm, loading } = useAddLlm();
|
||||
const [saveLoading, setSaveLoading] = useState(false);
|
||||
const { addLlm } = useAddLlm();
|
||||
const {
|
||||
visible: llmAddingVisible,
|
||||
hideModal: hideLlmAddingModal,
|
||||
@ -127,20 +154,41 @@ export const useSubmitOllama = () => {
|
||||
} = useSetModalState();
|
||||
|
||||
const onLlmAddingOk = useCallback(
|
||||
async (payload: IAddLlmRequestBody) => {
|
||||
async (payload: IAddLlmRequestBody, isVerify = false) => {
|
||||
if (!isVerify) {
|
||||
setSaveLoading(true);
|
||||
}
|
||||
const cleanedPayload = { ...payload };
|
||||
if (!cleanedPayload.api_key || cleanedPayload.api_key.trim() === '') {
|
||||
delete cleanedPayload.api_key;
|
||||
}
|
||||
|
||||
const ret = await addLlm(cleanedPayload);
|
||||
if (ret === 0) {
|
||||
hideLlmAddingModal();
|
||||
setEditMode(false);
|
||||
setInitialValues(undefined);
|
||||
const ret = await addLlm({ ...cleanedPayload, verify: isVerify });
|
||||
if (!isVerify) {
|
||||
setSaveLoading(false);
|
||||
if (ret.code === 0) {
|
||||
hideLlmAddingModal();
|
||||
setEditMode(false);
|
||||
setInitialValues(undefined);
|
||||
}
|
||||
}
|
||||
if (isVerify) {
|
||||
let res = {} as VerifyResult;
|
||||
if (ret.data?.success) {
|
||||
res = {
|
||||
isValid: true,
|
||||
logs: ret.data?.message,
|
||||
};
|
||||
} else {
|
||||
res = {
|
||||
isValid: false,
|
||||
logs: ret.data?.message,
|
||||
};
|
||||
}
|
||||
return res;
|
||||
}
|
||||
},
|
||||
[hideLlmAddingModal, addLlm],
|
||||
[hideLlmAddingModal, addLlm, setSaveLoading],
|
||||
);
|
||||
|
||||
const handleShowLlmAddingModal = (
|
||||
@ -168,7 +216,7 @@ export const useSubmitOllama = () => {
|
||||
};
|
||||
|
||||
return {
|
||||
llmAddingLoading: loading,
|
||||
llmAddingLoading: saveLoading,
|
||||
editMode,
|
||||
initialValues,
|
||||
onLlmAddingOk,
|
||||
@ -180,7 +228,8 @@ export const useSubmitOllama = () => {
|
||||
};
|
||||
|
||||
export const useSubmitVolcEngine = () => {
|
||||
const { addLlm, loading } = useAddLlm();
|
||||
const [saveLoading, setSaveLoading] = useState(false);
|
||||
const { addLlm } = useAddLlm();
|
||||
const {
|
||||
visible: volcAddingVisible,
|
||||
hideModal: hideVolcAddingModal,
|
||||
@ -188,17 +237,38 @@ export const useSubmitVolcEngine = () => {
|
||||
} = useSetModalState();
|
||||
|
||||
const onVolcAddingOk = useCallback(
|
||||
async (payload: IAddLlmRequestBody) => {
|
||||
const ret = await addLlm(payload);
|
||||
if (ret === 0) {
|
||||
hideVolcAddingModal();
|
||||
async (payload: IAddLlmRequestBody, isVerify = false) => {
|
||||
if (!isVerify) {
|
||||
setSaveLoading(true);
|
||||
}
|
||||
const ret = await addLlm({ ...payload, verify: isVerify });
|
||||
if (!isVerify) {
|
||||
setSaveLoading(false);
|
||||
if (ret.code === 0) {
|
||||
hideVolcAddingModal();
|
||||
}
|
||||
}
|
||||
if (isVerify) {
|
||||
let res = {} as VerifyResult;
|
||||
if (ret.data?.success) {
|
||||
res = {
|
||||
isValid: true,
|
||||
logs: ret.data?.message,
|
||||
};
|
||||
} else {
|
||||
res = {
|
||||
isValid: false,
|
||||
logs: ret.data?.message,
|
||||
};
|
||||
}
|
||||
return res;
|
||||
}
|
||||
},
|
||||
[hideVolcAddingModal, addLlm],
|
||||
[hideVolcAddingModal, addLlm, setSaveLoading],
|
||||
);
|
||||
|
||||
return {
|
||||
volcAddingLoading: loading,
|
||||
volcAddingLoading: saveLoading,
|
||||
onVolcAddingOk,
|
||||
volcAddingVisible,
|
||||
hideVolcAddingModal,
|
||||
@ -207,7 +277,8 @@ export const useSubmitVolcEngine = () => {
|
||||
};
|
||||
|
||||
export const useSubmitTencentCloud = () => {
|
||||
const { addLlm, loading } = useAddLlm();
|
||||
const [saveLoading, setSaveLoading] = useState(false);
|
||||
const { addLlm } = useAddLlm();
|
||||
const {
|
||||
visible: TencentCloudAddingVisible,
|
||||
hideModal: hideTencentCloudAddingModal,
|
||||
@ -215,17 +286,38 @@ export const useSubmitTencentCloud = () => {
|
||||
} = useSetModalState();
|
||||
|
||||
const onTencentCloudAddingOk = useCallback(
|
||||
async (payload: IAddLlmRequestBody) => {
|
||||
const ret = await addLlm(payload);
|
||||
if (ret === 0) {
|
||||
hideTencentCloudAddingModal();
|
||||
async (payload: IAddLlmRequestBody, isVerify = false) => {
|
||||
if (!isVerify) {
|
||||
setSaveLoading(true);
|
||||
}
|
||||
const ret = await addLlm({ ...payload, verify: isVerify });
|
||||
if (!isVerify) {
|
||||
setSaveLoading(false);
|
||||
if (ret.code === 0) {
|
||||
hideTencentCloudAddingModal();
|
||||
}
|
||||
}
|
||||
if (isVerify) {
|
||||
let res = {} as VerifyResult;
|
||||
if (ret.data?.success) {
|
||||
res = {
|
||||
isValid: true,
|
||||
logs: ret.data?.message,
|
||||
};
|
||||
} else {
|
||||
res = {
|
||||
isValid: false,
|
||||
logs: ret.data?.message,
|
||||
};
|
||||
}
|
||||
return res;
|
||||
}
|
||||
},
|
||||
[hideTencentCloudAddingModal, addLlm],
|
||||
[hideTencentCloudAddingModal, addLlm, setSaveLoading],
|
||||
);
|
||||
|
||||
return {
|
||||
TencentCloudAddingLoading: loading,
|
||||
TencentCloudAddingLoading: saveLoading,
|
||||
onTencentCloudAddingOk,
|
||||
TencentCloudAddingVisible,
|
||||
hideTencentCloudAddingModal,
|
||||
@ -234,7 +326,8 @@ export const useSubmitTencentCloud = () => {
|
||||
};
|
||||
|
||||
export const useSubmitSpark = () => {
|
||||
const { addLlm, loading } = useAddLlm();
|
||||
const [saveLoading, setSaveLoading] = useState(false);
|
||||
const { addLlm } = useAddLlm();
|
||||
const {
|
||||
visible: SparkAddingVisible,
|
||||
hideModal: hideSparkAddingModal,
|
||||
@ -242,17 +335,38 @@ export const useSubmitSpark = () => {
|
||||
} = useSetModalState();
|
||||
|
||||
const onSparkAddingOk = useCallback(
|
||||
async (payload: IAddLlmRequestBody) => {
|
||||
const ret = await addLlm(payload);
|
||||
if (ret === 0) {
|
||||
hideSparkAddingModal();
|
||||
async (payload: IAddLlmRequestBody, isVerify = false) => {
|
||||
if (!isVerify) {
|
||||
setSaveLoading(true);
|
||||
}
|
||||
const ret = await addLlm({ ...payload, verify: isVerify });
|
||||
if (!isVerify) {
|
||||
setSaveLoading(false);
|
||||
if (ret.code === 0) {
|
||||
hideSparkAddingModal();
|
||||
}
|
||||
}
|
||||
if (isVerify) {
|
||||
let res = {} as VerifyResult;
|
||||
if (ret.data?.success) {
|
||||
res = {
|
||||
isValid: true,
|
||||
logs: ret.data?.message,
|
||||
};
|
||||
} else {
|
||||
res = {
|
||||
isValid: false,
|
||||
logs: ret.data?.message,
|
||||
};
|
||||
}
|
||||
return res;
|
||||
}
|
||||
},
|
||||
[hideSparkAddingModal, addLlm],
|
||||
[hideSparkAddingModal, addLlm, setSaveLoading],
|
||||
);
|
||||
|
||||
return {
|
||||
SparkAddingLoading: loading,
|
||||
SparkAddingLoading: saveLoading,
|
||||
onSparkAddingOk,
|
||||
SparkAddingVisible,
|
||||
hideSparkAddingModal,
|
||||
@ -261,7 +375,8 @@ export const useSubmitSpark = () => {
|
||||
};
|
||||
|
||||
export const useSubmityiyan = () => {
|
||||
const { addLlm, loading } = useAddLlm();
|
||||
const [saveLoading, setSaveLoading] = useState(false);
|
||||
const { addLlm } = useAddLlm();
|
||||
const {
|
||||
visible: yiyanAddingVisible,
|
||||
hideModal: hideyiyanAddingModal,
|
||||
@ -269,17 +384,38 @@ export const useSubmityiyan = () => {
|
||||
} = useSetModalState();
|
||||
|
||||
const onyiyanAddingOk = useCallback(
|
||||
async (payload: IAddLlmRequestBody) => {
|
||||
const ret = await addLlm(payload);
|
||||
if (ret === 0) {
|
||||
hideyiyanAddingModal();
|
||||
async (payload: IAddLlmRequestBody, isVerify = false) => {
|
||||
if (!isVerify) {
|
||||
setSaveLoading(true);
|
||||
}
|
||||
const ret = await addLlm({ ...payload, verify: isVerify });
|
||||
if (!isVerify) {
|
||||
setSaveLoading(false);
|
||||
if (ret.code === 0) {
|
||||
hideyiyanAddingModal();
|
||||
}
|
||||
}
|
||||
if (isVerify) {
|
||||
let res = {} as VerifyResult;
|
||||
if (ret.data?.success) {
|
||||
res = {
|
||||
isValid: true,
|
||||
logs: ret.data?.message,
|
||||
};
|
||||
} else {
|
||||
res = {
|
||||
isValid: false,
|
||||
logs: ret.data?.message,
|
||||
};
|
||||
}
|
||||
return res;
|
||||
}
|
||||
},
|
||||
[hideyiyanAddingModal, addLlm],
|
||||
[hideyiyanAddingModal, addLlm, setSaveLoading],
|
||||
);
|
||||
|
||||
return {
|
||||
yiyanAddingLoading: loading,
|
||||
yiyanAddingLoading: saveLoading,
|
||||
onyiyanAddingOk,
|
||||
yiyanAddingVisible,
|
||||
hideyiyanAddingModal,
|
||||
@ -288,7 +424,8 @@ export const useSubmityiyan = () => {
|
||||
};
|
||||
|
||||
export const useSubmitFishAudio = () => {
|
||||
const { addLlm, loading } = useAddLlm();
|
||||
const [saveLoading, setSaveLoading] = useState(false);
|
||||
const { addLlm } = useAddLlm();
|
||||
const {
|
||||
visible: FishAudioAddingVisible,
|
||||
hideModal: hideFishAudioAddingModal,
|
||||
@ -296,17 +433,38 @@ export const useSubmitFishAudio = () => {
|
||||
} = useSetModalState();
|
||||
|
||||
const onFishAudioAddingOk = useCallback(
|
||||
async (payload: IAddLlmRequestBody) => {
|
||||
const ret = await addLlm(payload);
|
||||
if (ret === 0) {
|
||||
hideFishAudioAddingModal();
|
||||
async (payload: IAddLlmRequestBody, isVerify = false) => {
|
||||
if (!isVerify) {
|
||||
setSaveLoading(true);
|
||||
}
|
||||
const ret = await addLlm({ ...payload, verify: isVerify });
|
||||
if (!isVerify) {
|
||||
setSaveLoading(false);
|
||||
if (ret.code === 0) {
|
||||
hideFishAudioAddingModal();
|
||||
}
|
||||
}
|
||||
if (isVerify) {
|
||||
let res = {} as VerifyResult;
|
||||
if (ret.data?.success) {
|
||||
res = {
|
||||
isValid: true,
|
||||
logs: ret.data?.message,
|
||||
};
|
||||
} else {
|
||||
res = {
|
||||
isValid: false,
|
||||
logs: ret.data?.message,
|
||||
};
|
||||
}
|
||||
return res;
|
||||
}
|
||||
},
|
||||
[hideFishAudioAddingModal, addLlm],
|
||||
[hideFishAudioAddingModal, addLlm, setSaveLoading],
|
||||
);
|
||||
|
||||
return {
|
||||
FishAudioAddingLoading: loading,
|
||||
FishAudioAddingLoading: saveLoading,
|
||||
onFishAudioAddingOk,
|
||||
FishAudioAddingVisible,
|
||||
hideFishAudioAddingModal,
|
||||
@ -315,7 +473,8 @@ export const useSubmitFishAudio = () => {
|
||||
};
|
||||
|
||||
export const useSubmitGoogle = () => {
|
||||
const { addLlm, loading } = useAddLlm();
|
||||
const [saveLoading, setSaveLoading] = useState(false);
|
||||
const { addLlm } = useAddLlm();
|
||||
const {
|
||||
visible: GoogleAddingVisible,
|
||||
hideModal: hideGoogleAddingModal,
|
||||
@ -323,17 +482,38 @@ export const useSubmitGoogle = () => {
|
||||
} = useSetModalState();
|
||||
|
||||
const onGoogleAddingOk = useCallback(
|
||||
async (payload: IAddLlmRequestBody) => {
|
||||
const ret = await addLlm(payload);
|
||||
if (ret === 0) {
|
||||
hideGoogleAddingModal();
|
||||
async (payload: IAddLlmRequestBody, isVerify = false) => {
|
||||
if (!isVerify) {
|
||||
setSaveLoading(true);
|
||||
}
|
||||
const ret = await addLlm({ ...payload, verify: isVerify });
|
||||
if (!isVerify) {
|
||||
setSaveLoading(false);
|
||||
if (ret.code === 0) {
|
||||
hideGoogleAddingModal();
|
||||
}
|
||||
}
|
||||
if (isVerify) {
|
||||
let res = {} as VerifyResult;
|
||||
if (ret.data?.success) {
|
||||
res = {
|
||||
isValid: true,
|
||||
logs: ret.data?.message,
|
||||
};
|
||||
} else {
|
||||
res = {
|
||||
isValid: false,
|
||||
logs: ret.data?.message,
|
||||
};
|
||||
}
|
||||
return res;
|
||||
}
|
||||
},
|
||||
[hideGoogleAddingModal, addLlm],
|
||||
[hideGoogleAddingModal, addLlm, setSaveLoading],
|
||||
);
|
||||
|
||||
return {
|
||||
GoogleAddingLoading: loading,
|
||||
GoogleAddingLoading: saveLoading,
|
||||
onGoogleAddingOk,
|
||||
GoogleAddingVisible,
|
||||
hideGoogleAddingModal,
|
||||
@ -342,7 +522,8 @@ export const useSubmitGoogle = () => {
|
||||
};
|
||||
|
||||
export const useSubmitBedrock = () => {
|
||||
const { addLlm, loading } = useAddLlm();
|
||||
const [saveLoading, setSaveLoading] = useState(false);
|
||||
const { addLlm } = useAddLlm();
|
||||
const {
|
||||
visible: bedrockAddingVisible,
|
||||
hideModal: hideBedrockAddingModal,
|
||||
@ -350,17 +531,38 @@ export const useSubmitBedrock = () => {
|
||||
} = useSetModalState();
|
||||
|
||||
const onBedrockAddingOk = useCallback(
|
||||
async (payload: IAddLlmRequestBody) => {
|
||||
const ret = await addLlm(payload);
|
||||
if (ret === 0) {
|
||||
hideBedrockAddingModal();
|
||||
async (payload: IAddLlmRequestBody, isVerify = false) => {
|
||||
if (!isVerify) {
|
||||
setSaveLoading(true);
|
||||
}
|
||||
const ret = await addLlm({ ...payload, verify: isVerify });
|
||||
if (!isVerify) {
|
||||
setSaveLoading(false);
|
||||
if (ret.code === 0) {
|
||||
hideBedrockAddingModal();
|
||||
}
|
||||
}
|
||||
if (isVerify) {
|
||||
let res = {} as VerifyResult;
|
||||
if (ret.data?.success) {
|
||||
res = {
|
||||
isValid: true,
|
||||
logs: ret.data?.message,
|
||||
};
|
||||
} else {
|
||||
res = {
|
||||
isValid: false,
|
||||
logs: ret.data?.message,
|
||||
};
|
||||
}
|
||||
return res;
|
||||
}
|
||||
},
|
||||
[hideBedrockAddingModal, addLlm],
|
||||
[hideBedrockAddingModal, addLlm, setSaveLoading],
|
||||
);
|
||||
|
||||
return {
|
||||
bedrockAddingLoading: loading,
|
||||
bedrockAddingLoading: saveLoading,
|
||||
onBedrockAddingOk,
|
||||
bedrockAddingVisible,
|
||||
hideBedrockAddingModal,
|
||||
@ -369,7 +571,8 @@ export const useSubmitBedrock = () => {
|
||||
};
|
||||
|
||||
export const useSubmitAzure = () => {
|
||||
const { addLlm, loading } = useAddLlm();
|
||||
const [saveLoading, setSaveLoading] = useState(false);
|
||||
const { addLlm } = useAddLlm();
|
||||
const {
|
||||
visible: AzureAddingVisible,
|
||||
hideModal: hideAzureAddingModal,
|
||||
@ -377,17 +580,38 @@ export const useSubmitAzure = () => {
|
||||
} = useSetModalState();
|
||||
|
||||
const onAzureAddingOk = useCallback(
|
||||
async (payload: IAddLlmRequestBody) => {
|
||||
const ret = await addLlm(payload);
|
||||
if (ret === 0) {
|
||||
hideAzureAddingModal();
|
||||
async (payload: IAddLlmRequestBody, isVerify = false) => {
|
||||
if (!isVerify) {
|
||||
setSaveLoading(true);
|
||||
}
|
||||
const ret = await addLlm({ ...payload, verify: isVerify });
|
||||
if (!isVerify) {
|
||||
setSaveLoading(false);
|
||||
if (ret.code === 0) {
|
||||
hideAzureAddingModal();
|
||||
}
|
||||
}
|
||||
if (isVerify) {
|
||||
let res = {} as VerifyResult;
|
||||
if (ret.data?.success) {
|
||||
res = {
|
||||
isValid: true,
|
||||
logs: ret.data?.message,
|
||||
};
|
||||
} else {
|
||||
res = {
|
||||
isValid: false,
|
||||
logs: ret.data?.message,
|
||||
};
|
||||
}
|
||||
return res;
|
||||
}
|
||||
},
|
||||
[hideAzureAddingModal, addLlm],
|
||||
[hideAzureAddingModal, addLlm, setSaveLoading],
|
||||
);
|
||||
|
||||
return {
|
||||
AzureAddingLoading: loading,
|
||||
AzureAddingLoading: saveLoading,
|
||||
onAzureAddingOk,
|
||||
AzureAddingVisible,
|
||||
hideAzureAddingModal,
|
||||
@ -436,7 +660,8 @@ export const useHandleDeleteFactory = (llmFactory: string) => {
|
||||
};
|
||||
|
||||
export const useSubmitMinerU = () => {
|
||||
const { addLlm, loading } = useAddLlm();
|
||||
const [saveLoading, setSaveLoading] = useState(false);
|
||||
const { addLlm } = useAddLlm();
|
||||
const {
|
||||
visible: mineruVisible,
|
||||
hideModal: hideMineruModal,
|
||||
@ -444,7 +669,10 @@ export const useSubmitMinerU = () => {
|
||||
} = useSetModalState();
|
||||
|
||||
const onMineruOk = useCallback(
|
||||
async (payload: MinerUFormValues) => {
|
||||
async (payload: MinerUFormValues, isVerify = false) => {
|
||||
if (!isVerify) {
|
||||
setSaveLoading(true);
|
||||
}
|
||||
const cfg: any = {
|
||||
...payload,
|
||||
mineru_delete_output:
|
||||
@ -461,12 +689,30 @@ export const useSubmitMinerU = () => {
|
||||
api_base: '',
|
||||
max_tokens: 0,
|
||||
};
|
||||
const ret = await addLlm(req);
|
||||
if (ret === 0) {
|
||||
hideMineruModal();
|
||||
const ret = await addLlm({ ...req, verify: isVerify });
|
||||
if (!isVerify) {
|
||||
setSaveLoading(false);
|
||||
if (ret.code === 0) {
|
||||
hideMineruModal();
|
||||
}
|
||||
}
|
||||
if (isVerify) {
|
||||
let res = {} as VerifyResult;
|
||||
if (ret.data?.success) {
|
||||
res = {
|
||||
isValid: true,
|
||||
logs: ret.data?.message,
|
||||
};
|
||||
} else {
|
||||
res = {
|
||||
isValid: false,
|
||||
logs: ret.data?.message,
|
||||
};
|
||||
}
|
||||
return res;
|
||||
}
|
||||
},
|
||||
[addLlm, hideMineruModal],
|
||||
[addLlm, hideMineruModal, setSaveLoading],
|
||||
);
|
||||
|
||||
return {
|
||||
@ -474,12 +720,13 @@ export const useSubmitMinerU = () => {
|
||||
hideMineruModal,
|
||||
showMineruModal,
|
||||
onMineruOk,
|
||||
mineruLoading: loading,
|
||||
mineruLoading: saveLoading,
|
||||
};
|
||||
};
|
||||
|
||||
export const useSubmitPaddleOCR = () => {
|
||||
const { addLlm, loading } = useAddLlm();
|
||||
const [saveLoading, setSaveLoading] = useState(false);
|
||||
const { addLlm } = useAddLlm();
|
||||
const {
|
||||
visible: paddleocrVisible,
|
||||
hideModal: hidePaddleOCRModal,
|
||||
@ -487,7 +734,10 @@ export const useSubmitPaddleOCR = () => {
|
||||
} = useSetModalState();
|
||||
|
||||
const onPaddleOCROk = useCallback(
|
||||
async (payload: any) => {
|
||||
async (payload: any, isVerify = false) => {
|
||||
if (!isVerify) {
|
||||
setSaveLoading(true);
|
||||
}
|
||||
const cfg: any = {
|
||||
...payload,
|
||||
};
|
||||
@ -499,14 +749,32 @@ export const useSubmitPaddleOCR = () => {
|
||||
api_base: '',
|
||||
max_tokens: 0,
|
||||
};
|
||||
const ret = await addLlm(req);
|
||||
if (ret === 0) {
|
||||
hidePaddleOCRModal();
|
||||
return true;
|
||||
const ret = await addLlm({ ...req, verify: isVerify });
|
||||
if (!isVerify) {
|
||||
setSaveLoading(false);
|
||||
if (ret.code === 0) {
|
||||
hidePaddleOCRModal();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (isVerify) {
|
||||
let res = {} as VerifyResult;
|
||||
if (ret.data?.success) {
|
||||
res = {
|
||||
isValid: true,
|
||||
logs: ret.data?.message,
|
||||
};
|
||||
} else {
|
||||
res = {
|
||||
isValid: false,
|
||||
logs: ret.data?.message,
|
||||
};
|
||||
}
|
||||
return res;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[addLlm, hidePaddleOCRModal],
|
||||
[addLlm, hidePaddleOCRModal, setSaveLoading],
|
||||
);
|
||||
|
||||
return {
|
||||
@ -514,6 +782,37 @@ export const useSubmitPaddleOCR = () => {
|
||||
hidePaddleOCRModal,
|
||||
showPaddleOCRModal,
|
||||
onPaddleOCROk,
|
||||
paddleocrLoading: loading,
|
||||
paddleocrLoading: saveLoading,
|
||||
};
|
||||
};
|
||||
|
||||
export const useVerifySettings = ({
|
||||
onVerify,
|
||||
}: {
|
||||
onVerify:
|
||||
| ((
|
||||
postBody: ApiKeyPostBody,
|
||||
isVerify?: boolean,
|
||||
) => Promise<VerifyResult | undefined>)
|
||||
| ((
|
||||
payload: IAddLlmRequestBody,
|
||||
isVerify?: boolean,
|
||||
) => Promise<VerifyResult | undefined>)
|
||||
| ((
|
||||
payload: MinerUFormValues,
|
||||
isVerify?: boolean,
|
||||
) => Promise<VerifyResult | undefined>)
|
||||
| ((payload: any, isVerify?: boolean) => Promise<boolean | VerifyResult>)
|
||||
| (() => void);
|
||||
}) => {
|
||||
const onApiKeyVerifying = useCallback(
|
||||
async (postBody: any) => {
|
||||
const res = await onVerify(postBody, true);
|
||||
return res;
|
||||
},
|
||||
[onVerify],
|
||||
);
|
||||
return {
|
||||
onApiKeyVerifying,
|
||||
};
|
||||
};
|
||||
|
||||
@ -20,6 +20,7 @@ import {
|
||||
useSubmitTencentCloud,
|
||||
useSubmitVolcEngine,
|
||||
useSubmityiyan,
|
||||
useVerifySettings,
|
||||
} from './hooks';
|
||||
import ApiKeyModal from './modal/api-key-modal';
|
||||
import AzureOpenAIModal from './modal/azure-openai-modal';
|
||||
@ -204,6 +205,76 @@ const ModelProviders = () => {
|
||||
},
|
||||
[showApiKeyModal, showLlmAddingModal, ModalMap, detailedLlmList],
|
||||
);
|
||||
|
||||
const handleOk = useMemo(() => {
|
||||
if (apiKeyVisible) {
|
||||
return onApiKeySavingOk;
|
||||
}
|
||||
if (llmAddingVisible) {
|
||||
return onLlmAddingOk;
|
||||
}
|
||||
if (volcAddingVisible) {
|
||||
return onVolcAddingOk;
|
||||
}
|
||||
if (TencentCloudAddingVisible) {
|
||||
return onTencentCloudAddingOk;
|
||||
}
|
||||
if (SparkAddingVisible) {
|
||||
return onSparkAddingOk;
|
||||
}
|
||||
if (yiyanAddingVisible) {
|
||||
return onyiyanAddingOk;
|
||||
}
|
||||
if (FishAudioAddingVisible) {
|
||||
return onFishAudioAddingOk;
|
||||
}
|
||||
if (bedrockAddingVisible) {
|
||||
return onBedrockAddingOk;
|
||||
}
|
||||
if (AzureAddingVisible) {
|
||||
return onAzureAddingOk;
|
||||
}
|
||||
if (mineruVisible) {
|
||||
return onMineruOk;
|
||||
}
|
||||
if (paddleocrVisible) {
|
||||
return onPaddleOCROk;
|
||||
}
|
||||
if (GoogleAddingVisible) {
|
||||
return onGoogleAddingOk;
|
||||
}
|
||||
return () => {};
|
||||
}, [
|
||||
GoogleAddingVisible,
|
||||
onGoogleAddingOk,
|
||||
apiKeyVisible,
|
||||
onApiKeySavingOk,
|
||||
llmAddingVisible,
|
||||
onLlmAddingOk,
|
||||
volcAddingVisible,
|
||||
onVolcAddingOk,
|
||||
TencentCloudAddingVisible,
|
||||
onTencentCloudAddingOk,
|
||||
SparkAddingVisible,
|
||||
onSparkAddingOk,
|
||||
yiyanAddingVisible,
|
||||
onyiyanAddingOk,
|
||||
FishAudioAddingVisible,
|
||||
onFishAudioAddingOk,
|
||||
bedrockAddingVisible,
|
||||
onBedrockAddingOk,
|
||||
AzureAddingVisible,
|
||||
onAzureAddingOk,
|
||||
mineruVisible,
|
||||
onMineruOk,
|
||||
paddleocrVisible,
|
||||
onPaddleOCROk,
|
||||
]);
|
||||
|
||||
const { onApiKeyVerifying } = useVerifySettings({
|
||||
onVerify: handleOk,
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="flex w-full border-[0.5px] border-border-button rounded-lg relative ">
|
||||
<Spotlight />
|
||||
@ -227,6 +298,7 @@ const ModelProviders = () => {
|
||||
initialValue={initialApiKey}
|
||||
editMode={editMode}
|
||||
onOk={onApiKeySavingOk}
|
||||
onVerify={onApiKeyVerifying}
|
||||
llmFactory={llmFactory}
|
||||
></ApiKeyModal>
|
||||
{llmAddingVisible && (
|
||||
@ -238,6 +310,7 @@ const ModelProviders = () => {
|
||||
editMode={llmEditMode}
|
||||
initialValues={llmInitialValues}
|
||||
llmFactory={selectedLlmFactory}
|
||||
onVerify={onApiKeyVerifying}
|
||||
></OllamaModal>
|
||||
)}
|
||||
<VolcEngineModal
|
||||
@ -246,6 +319,7 @@ const ModelProviders = () => {
|
||||
onOk={onVolcAddingOk}
|
||||
loading={volcAddingLoading}
|
||||
llmFactory={LLMFactory.VolcEngine}
|
||||
onVerify={onApiKeyVerifying}
|
||||
></VolcEngineModal>
|
||||
<GoogleModal
|
||||
visible={GoogleAddingVisible}
|
||||
@ -253,6 +327,7 @@ const ModelProviders = () => {
|
||||
onOk={onGoogleAddingOk}
|
||||
loading={GoogleAddingLoading}
|
||||
llmFactory={LLMFactory.GoogleCloud}
|
||||
onVerify={onApiKeyVerifying}
|
||||
></GoogleModal>
|
||||
<TencentCloudModal
|
||||
visible={TencentCloudAddingVisible}
|
||||
@ -260,6 +335,7 @@ const ModelProviders = () => {
|
||||
onOk={onTencentCloudAddingOk}
|
||||
loading={TencentCloudAddingLoading}
|
||||
llmFactory={LLMFactory.TencentCloud}
|
||||
onVerify={onApiKeyVerifying}
|
||||
></TencentCloudModal>
|
||||
<SparkModal
|
||||
visible={SparkAddingVisible}
|
||||
@ -267,6 +343,7 @@ const ModelProviders = () => {
|
||||
onOk={onSparkAddingOk}
|
||||
loading={SparkAddingLoading}
|
||||
llmFactory={LLMFactory.XunFeiSpark}
|
||||
onVerify={onApiKeyVerifying}
|
||||
></SparkModal>
|
||||
<YiyanModal
|
||||
visible={yiyanAddingVisible}
|
||||
@ -274,6 +351,7 @@ const ModelProviders = () => {
|
||||
onOk={onyiyanAddingOk}
|
||||
loading={yiyanAddingLoading}
|
||||
llmFactory={LLMFactory.BaiduYiYan}
|
||||
onVerify={onApiKeyVerifying}
|
||||
></YiyanModal>
|
||||
<FishAudioModal
|
||||
visible={FishAudioAddingVisible}
|
||||
@ -281,6 +359,7 @@ const ModelProviders = () => {
|
||||
onOk={onFishAudioAddingOk}
|
||||
loading={FishAudioAddingLoading}
|
||||
llmFactory={LLMFactory.FishAudio}
|
||||
onVerify={onApiKeyVerifying}
|
||||
></FishAudioModal>
|
||||
<BedrockModal
|
||||
visible={bedrockAddingVisible}
|
||||
@ -288,6 +367,7 @@ const ModelProviders = () => {
|
||||
onOk={onBedrockAddingOk}
|
||||
loading={bedrockAddingLoading}
|
||||
llmFactory={LLMFactory.Bedrock}
|
||||
onVerify={onApiKeyVerifying}
|
||||
></BedrockModal>
|
||||
<AzureOpenAIModal
|
||||
visible={AzureAddingVisible}
|
||||
@ -295,18 +375,21 @@ const ModelProviders = () => {
|
||||
onOk={onAzureAddingOk}
|
||||
loading={AzureAddingLoading}
|
||||
llmFactory={LLMFactory.AzureOpenAI}
|
||||
onVerify={onApiKeyVerifying}
|
||||
></AzureOpenAIModal>
|
||||
<MinerUModal
|
||||
visible={mineruVisible}
|
||||
hideModal={hideMineruModal}
|
||||
onOk={onMineruOk}
|
||||
loading={mineruLoading}
|
||||
onVerify={onApiKeyVerifying}
|
||||
></MinerUModal>
|
||||
<PaddleOCRModal
|
||||
visible={paddleocrVisible}
|
||||
hideModal={hidePaddleOCRModal}
|
||||
onOk={onPaddleOCROk}
|
||||
loading={paddleocrLoading}
|
||||
onVerify={onApiKeyVerifying}
|
||||
></PaddleOCRModal>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -15,6 +15,8 @@ import { KeyboardEventHandler, useCallback, useEffect } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { ApiKeyPostBody } from '../../../interface';
|
||||
import { LLMHeader } from '../../components/llm-header';
|
||||
import { VerifyResult } from '../../hooks';
|
||||
import VerifyButton from '../verify-button';
|
||||
|
||||
interface IProps extends Omit<IModalManagerChildrenProps, 'showModal'> {
|
||||
loading: boolean;
|
||||
@ -22,6 +24,9 @@ interface IProps extends Omit<IModalManagerChildrenProps, 'showModal'> {
|
||||
llmFactory: string;
|
||||
editMode?: boolean;
|
||||
onOk: (postBody: ApiKeyPostBody) => void;
|
||||
onVerify: (
|
||||
postBody: any,
|
||||
) => Promise<boolean | void | VerifyResult | undefined>;
|
||||
showModal?(): void;
|
||||
}
|
||||
|
||||
@ -46,6 +51,7 @@ const ApiKeyModal = ({
|
||||
initialValue,
|
||||
editMode = false,
|
||||
onOk,
|
||||
onVerify,
|
||||
}: IProps) => {
|
||||
const form = useForm<FieldType>();
|
||||
const { t } = useTranslate('setting');
|
||||
@ -181,6 +187,8 @@ const ApiKeyModal = ({
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<VerifyButton onVerify={onVerify} />
|
||||
</div>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import {
|
||||
DynamicForm,
|
||||
DynamicFormRef,
|
||||
FormFieldConfig,
|
||||
FormFieldType,
|
||||
} from '@/components/dynamic-form';
|
||||
@ -8,19 +9,29 @@ import { useCommonTranslation, useTranslate } from '@/hooks/common-hooks';
|
||||
import { useBuildModelTypeOptions } from '@/hooks/logic-hooks/use-build-options';
|
||||
import { IModalProps } from '@/interfaces/common';
|
||||
import { IAddLlmRequestBody } from '@/interfaces/request/llm';
|
||||
import { VerifyResult } from '@/pages/user-setting/setting-model/hooks';
|
||||
import { memo, useCallback, useRef } from 'react';
|
||||
import { FieldValues } from 'react-hook-form';
|
||||
import { LLMHeader } from '../../components/llm-header';
|
||||
import VerifyButton from '../../modal/verify-button';
|
||||
|
||||
const AzureOpenAIModal = ({
|
||||
visible,
|
||||
hideModal,
|
||||
onOk,
|
||||
onVerify,
|
||||
loading,
|
||||
llmFactory,
|
||||
}: IModalProps<IAddLlmRequestBody> & { llmFactory: string }) => {
|
||||
}: IModalProps<IAddLlmRequestBody> & {
|
||||
llmFactory: string;
|
||||
onVerify?: (
|
||||
postBody: any,
|
||||
) => Promise<boolean | void | VerifyResult | undefined>;
|
||||
}) => {
|
||||
const { t } = useTranslate('setting');
|
||||
const { t: tg } = useCommonTranslation();
|
||||
const { buildModelTypeOptions } = useBuildModelTypeOptions();
|
||||
const formRef = useRef<DynamicFormRef>(null);
|
||||
|
||||
const fields: FormFieldConfig[] = [
|
||||
{
|
||||
@ -114,6 +125,27 @@ const AzureOpenAIModal = ({
|
||||
await onOk?.(data);
|
||||
};
|
||||
|
||||
const verifyParamsFunc = useCallback(() => {
|
||||
const values = formRef.current?.getValues();
|
||||
const modelType =
|
||||
values.model_type === 'chat' && values.vision
|
||||
? 'image2text'
|
||||
: values.model_type;
|
||||
return {
|
||||
llm_factory: llmFactory,
|
||||
model_type: modelType,
|
||||
};
|
||||
}, [llmFactory]);
|
||||
|
||||
const handleVerify = useCallback(
|
||||
async (params: any) => {
|
||||
const verifyParams = verifyParamsFunc();
|
||||
const res = await onVerify?.({ ...params, ...verifyParams });
|
||||
return (res || { isValid: null, logs: '' }) as VerifyResult;
|
||||
},
|
||||
[verifyParamsFunc, onVerify],
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={<LLMHeader name={llmFactory} />}
|
||||
@ -127,6 +159,7 @@ const AzureOpenAIModal = ({
|
||||
onSubmit={(data) => {
|
||||
console.log(data);
|
||||
}}
|
||||
ref={formRef}
|
||||
defaultValues={
|
||||
{
|
||||
model_type: 'embedding',
|
||||
@ -137,23 +170,26 @@ const AzureOpenAIModal = ({
|
||||
}
|
||||
labelClassName="font-normal"
|
||||
>
|
||||
<div className="absolute bottom-0 right-0 left-0 flex items-center justify-end w-full gap-2 py-6 px-6">
|
||||
<DynamicForm.CancelButton
|
||||
handleCancel={() => {
|
||||
hideModal?.();
|
||||
}}
|
||||
/>
|
||||
<DynamicForm.SavingButton
|
||||
submitLoading={loading || false}
|
||||
buttonText={tg('ok')}
|
||||
submitFunc={(values: FieldValues) => {
|
||||
handleOk(values);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<>
|
||||
{onVerify && <VerifyButton onVerify={handleVerify} />}
|
||||
<div className="absolute bottom-0 right-0 left-0 flex items-center justify-end w-full gap-2 py-6 px-6">
|
||||
<DynamicForm.CancelButton
|
||||
handleCancel={() => {
|
||||
hideModal?.();
|
||||
}}
|
||||
/>
|
||||
<DynamicForm.SavingButton
|
||||
submitLoading={loading || false}
|
||||
buttonText={tg('ok')}
|
||||
submitFunc={(values: FieldValues) => {
|
||||
handleOk(values);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
</DynamicForm.Root>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default AzureOpenAIModal;
|
||||
export default memo(AzureOpenAIModal);
|
||||
|
||||
@ -9,12 +9,14 @@ import { useCommonTranslation, useTranslate } from '@/hooks/common-hooks';
|
||||
import { useBuildModelTypeOptions } from '@/hooks/logic-hooks/use-build-options';
|
||||
import { IModalProps } from '@/interfaces/common';
|
||||
import { IAddLlmRequestBody } from '@/interfaces/request/llm';
|
||||
import { VerifyResult } from '@/pages/user-setting/setting-model/hooks';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { useMemo } from 'react';
|
||||
import { memo, useCallback, useMemo } from 'react';
|
||||
import { useForm, useWatch } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
import { LLMHeader } from '../../components/llm-header';
|
||||
import { BedrockRegionList } from '../../constant';
|
||||
import VerifyButton from '../../modal/verify-button';
|
||||
|
||||
type FieldType = IAddLlmRequestBody & {
|
||||
auth_mode?: 'access_key_secret' | 'iam_role' | 'assume_role';
|
||||
@ -28,9 +30,15 @@ const BedrockModal = ({
|
||||
visible = false,
|
||||
hideModal,
|
||||
onOk,
|
||||
onVerify,
|
||||
loading,
|
||||
llmFactory,
|
||||
}: IModalProps<IAddLlmRequestBody> & { llmFactory: string }) => {
|
||||
}: IModalProps<IAddLlmRequestBody> & {
|
||||
llmFactory: string;
|
||||
onVerify?: (
|
||||
postBody: any,
|
||||
) => Promise<boolean | void | VerifyResult | undefined>;
|
||||
}) => {
|
||||
const { t } = useTranslate('setting');
|
||||
const { t: ct } = useCommonTranslation();
|
||||
const { buildModelTypeOptions } = useBuildModelTypeOptions();
|
||||
@ -130,6 +138,40 @@ const BedrockModal = ({
|
||||
onOk?.(data as unknown as IAddLlmRequestBody);
|
||||
};
|
||||
|
||||
const verifyParamsFunc = useCallback(() => {
|
||||
const values = form.getValues();
|
||||
const cleanedValues: Record<string, any> = { ...values };
|
||||
const fieldsByMode: Record<string, string[]> = {
|
||||
access_key_secret: ['bedrock_ak', 'bedrock_sk'],
|
||||
iam_role: ['aws_role_arn'],
|
||||
assume_role: [],
|
||||
};
|
||||
|
||||
cleanedValues.auth_mode = authMode;
|
||||
|
||||
Object.keys(fieldsByMode).forEach((mode) => {
|
||||
if (mode !== authMode) {
|
||||
fieldsByMode[mode].forEach((field) => {
|
||||
delete cleanedValues[field];
|
||||
});
|
||||
}
|
||||
});
|
||||
return {
|
||||
...cleanedValues,
|
||||
llm_factory: llmFactory,
|
||||
max_tokens: values.max_tokens,
|
||||
};
|
||||
}, [llmFactory, authMode, form]);
|
||||
|
||||
const handleVerify = useCallback(
|
||||
async (params: any) => {
|
||||
const verifyParams = verifyParamsFunc();
|
||||
const res = await onVerify?.({ ...params, ...verifyParams });
|
||||
return (res || { isValid: null, logs: '' }) as VerifyResult;
|
||||
},
|
||||
[verifyParamsFunc, onVerify],
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={<LLMHeader name={llmFactory} />}
|
||||
@ -262,10 +304,11 @@ const BedrockModal = ({
|
||||
/>
|
||||
)}
|
||||
</RAGFlowFormItem>
|
||||
{onVerify && <VerifyButton onVerify={handleVerify} />}
|
||||
</form>
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default BedrockModal;
|
||||
export default memo(BedrockModal);
|
||||
|
||||
@ -8,16 +8,25 @@ import { useCommonTranslation, useTranslate } from '@/hooks/common-hooks';
|
||||
import { useBuildModelTypeOptions } from '@/hooks/logic-hooks/use-build-options';
|
||||
import { IModalProps } from '@/interfaces/common';
|
||||
import { IAddLlmRequestBody } from '@/interfaces/request/llm';
|
||||
import { VerifyResult } from '@/pages/user-setting/setting-model/hooks';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { FieldValues } from 'react-hook-form';
|
||||
import { LLMHeader } from '../../components/llm-header';
|
||||
import VerifyButton from '../../modal/verify-button';
|
||||
|
||||
const FishAudioModal = ({
|
||||
visible,
|
||||
hideModal,
|
||||
onOk,
|
||||
onVerify,
|
||||
loading,
|
||||
llmFactory,
|
||||
}: IModalProps<IAddLlmRequestBody> & { llmFactory: string }) => {
|
||||
}: IModalProps<IAddLlmRequestBody> & {
|
||||
llmFactory: string;
|
||||
onVerify?: (
|
||||
postBody: any,
|
||||
) => Promise<boolean | void | VerifyResult | undefined>;
|
||||
}) => {
|
||||
const { t } = useTranslate('setting');
|
||||
const { t: tc } = useCommonTranslation();
|
||||
const { buildModelTypeOptions } = useBuildModelTypeOptions();
|
||||
@ -85,6 +94,14 @@ const FishAudioModal = ({
|
||||
await onOk?.(data as IAddLlmRequestBody);
|
||||
};
|
||||
|
||||
const handleVerify = useCallback(
|
||||
async (params: any) => {
|
||||
const res = await onVerify?.({ ...params, llm_factory: llmFactory });
|
||||
return (res || { isValid: null, logs: '' }) as VerifyResult;
|
||||
},
|
||||
[llmFactory, onVerify],
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={<LLMHeader name={llmFactory} />}
|
||||
@ -100,6 +117,9 @@ const FishAudioModal = ({
|
||||
defaultValues={{ model_type: 'tts' }}
|
||||
labelClassName="font-normal"
|
||||
>
|
||||
{onVerify && (
|
||||
<VerifyButton onVerify={handleVerify} isAbsolute={false} />
|
||||
)}
|
||||
<div className="flex items-center justify-between w-full">
|
||||
<a
|
||||
href="https://fish.audio"
|
||||
@ -123,4 +143,4 @@ const FishAudioModal = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default FishAudioModal;
|
||||
export default memo(FishAudioModal);
|
||||
|
||||
@ -8,16 +8,25 @@ import { useCommonTranslation, useTranslate } from '@/hooks/common-hooks';
|
||||
import { useBuildModelTypeOptions } from '@/hooks/logic-hooks/use-build-options';
|
||||
import { IModalProps } from '@/interfaces/common';
|
||||
import { IAddLlmRequestBody } from '@/interfaces/request/llm';
|
||||
import { VerifyResult } from '@/pages/user-setting/setting-model/hooks';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { FieldValues } from 'react-hook-form';
|
||||
import { LLMHeader } from '../../components/llm-header';
|
||||
import VerifyButton from '../../modal/verify-button';
|
||||
|
||||
const GoogleModal = ({
|
||||
visible,
|
||||
hideModal,
|
||||
onOk,
|
||||
onVerify,
|
||||
loading,
|
||||
llmFactory,
|
||||
}: IModalProps<IAddLlmRequestBody> & { llmFactory: string }) => {
|
||||
}: IModalProps<IAddLlmRequestBody> & {
|
||||
llmFactory: string;
|
||||
onVerify?: (
|
||||
postBody: any,
|
||||
) => Promise<boolean | void | VerifyResult | undefined>;
|
||||
}) => {
|
||||
const { t } = useTranslate('setting');
|
||||
const { t: tc } = useCommonTranslation();
|
||||
const { buildModelTypeOptions } = useBuildModelTypeOptions();
|
||||
@ -112,6 +121,20 @@ const GoogleModal = ({
|
||||
await onOk?.(data);
|
||||
};
|
||||
|
||||
const verifyParamsFunc = useCallback(() => {
|
||||
return {
|
||||
llm_factory: llmFactory,
|
||||
};
|
||||
}, [llmFactory]);
|
||||
|
||||
const handleVerify = useCallback(
|
||||
async (params: any) => {
|
||||
const verifyParams = verifyParamsFunc();
|
||||
const res = await onVerify?.({ ...params, ...verifyParams });
|
||||
return (res || { isValid: null, logs: '' }) as VerifyResult;
|
||||
},
|
||||
[verifyParamsFunc, onVerify],
|
||||
);
|
||||
return (
|
||||
<Modal
|
||||
title={<LLMHeader name={llmFactory} />}
|
||||
@ -132,6 +155,7 @@ const GoogleModal = ({
|
||||
}
|
||||
labelClassName="font-normal"
|
||||
>
|
||||
{onVerify && <VerifyButton onVerify={handleVerify} />}
|
||||
<div className="absolute bottom-0 right-0 left-0 flex items-center justify-end w-full gap-2 py-6 px-6">
|
||||
<DynamicForm.CancelButton
|
||||
handleCancel={() => {
|
||||
@ -151,4 +175,4 @@ const GoogleModal = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default GoogleModal;
|
||||
export default memo(GoogleModal);
|
||||
|
||||
@ -13,13 +13,16 @@ import { RAGFlowSelect } from '@/components/ui/select';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import { LLMFactory } from '@/constants/llm';
|
||||
import { IModalProps } from '@/interfaces/common';
|
||||
import { VerifyResult } from '@/pages/user-setting/setting-model/hooks';
|
||||
import { buildOptions } from '@/utils/form';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { t } from 'i18next';
|
||||
import { memo } from 'react';
|
||||
import { useForm, useWatch } from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { z } from 'zod';
|
||||
import { LLMHeader } from '../../components/llm-header';
|
||||
import VerifyButton from '../verify-button';
|
||||
|
||||
const FormSchema = z.object({
|
||||
llm_name: z.string().min(1, {
|
||||
@ -46,8 +49,13 @@ const MinerUModal = ({
|
||||
visible,
|
||||
hideModal,
|
||||
onOk,
|
||||
onVerify,
|
||||
loading,
|
||||
}: IModalProps<MinerUFormValues>) => {
|
||||
}: IModalProps<MinerUFormValues> & {
|
||||
onVerify?: (
|
||||
postBody: any,
|
||||
) => Promise<boolean | void | VerifyResult | undefined>;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const backendOptions = buildOptions([
|
||||
@ -152,16 +160,23 @@ const MinerUModal = ({
|
||||
/>
|
||||
)}
|
||||
</RAGFlowFormItem>
|
||||
{onVerify && (
|
||||
<VerifyButton
|
||||
onVerify={onVerify as (postBody: any) => Promise<VerifyResult>}
|
||||
/>
|
||||
)}
|
||||
</form>
|
||||
</Form>
|
||||
<DialogFooter>
|
||||
<ButtonLoading type="submit" form="mineru-form" loading={loading}>
|
||||
{t('common.save', 'Save')}
|
||||
</ButtonLoading>
|
||||
<div className="flex gap-2">
|
||||
<ButtonLoading type="submit" form="mineru-form" loading={loading}>
|
||||
{t('common.save', 'Save')}
|
||||
</ButtonLoading>
|
||||
</div>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default MinerUModal;
|
||||
export default memo(MinerUModal);
|
||||
|
||||
@ -8,17 +8,24 @@ import { useCommonTranslation, useTranslate } from '@/hooks/common-hooks';
|
||||
import { useBuildModelTypeOptions } from '@/hooks/logic-hooks/use-build-options';
|
||||
import { IModalProps } from '@/interfaces/common';
|
||||
import { IAddLlmRequestBody } from '@/interfaces/request/llm';
|
||||
import { VerifyResult } from '@/pages/user-setting/setting-model/hooks';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { FieldValues } from 'react-hook-form';
|
||||
import { LLMHeader } from '../../components/llm-header';
|
||||
import VerifyButton from '../../modal/verify-button';
|
||||
|
||||
const TencentCloudModal = ({
|
||||
visible,
|
||||
hideModal,
|
||||
onOk,
|
||||
onVerify,
|
||||
loading,
|
||||
llmFactory,
|
||||
}: IModalProps<Omit<IAddLlmRequestBody, 'max_tokens'>> & {
|
||||
llmFactory: string;
|
||||
onVerify?: (
|
||||
postBody: any,
|
||||
) => Promise<boolean | void | VerifyResult | undefined>;
|
||||
}) => {
|
||||
const { t } = useTranslate('setting');
|
||||
const { t: tc } = useCommonTranslation();
|
||||
@ -108,6 +115,21 @@ const TencentCloudModal = ({
|
||||
await onOk?.(data);
|
||||
};
|
||||
|
||||
const verifyParamsFunc = useCallback(() => {
|
||||
return {
|
||||
llm_factory: llmFactory,
|
||||
};
|
||||
}, [llmFactory]);
|
||||
|
||||
const handleVerify = useCallback(
|
||||
async (params: any) => {
|
||||
const verifyParams = verifyParamsFunc();
|
||||
const res = await onVerify?.({ ...params, ...verifyParams });
|
||||
return (res || { isValid: null, logs: '' }) as VerifyResult;
|
||||
},
|
||||
[verifyParamsFunc, onVerify],
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={<LLMHeader name={llmFactory} />}
|
||||
@ -127,6 +149,9 @@ const TencentCloudModal = ({
|
||||
}
|
||||
labelClassName="font-normal"
|
||||
>
|
||||
{onVerify && (
|
||||
<VerifyButton onVerify={handleVerify} isAbsolute={false} />
|
||||
)}
|
||||
<div className="absolute bottom-0 right-0 left-0 flex items-center justify-between w-full py-6 px-6">
|
||||
<a
|
||||
href="https://cloud.tencent.com/document/api/1093/37823"
|
||||
@ -156,4 +181,4 @@ const TencentCloudModal = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default TencentCloudModal;
|
||||
export default memo(TencentCloudModal);
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import {
|
||||
DynamicForm,
|
||||
DynamicFormRef,
|
||||
FormFieldConfig,
|
||||
FormFieldType,
|
||||
} from '@/components/dynamic-form';
|
||||
@ -9,9 +10,11 @@ import { useCommonTranslation, useTranslate } from '@/hooks/common-hooks';
|
||||
import { useBuildModelTypeOptions } from '@/hooks/logic-hooks/use-build-options';
|
||||
import { IModalProps } from '@/interfaces/common';
|
||||
import { IAddLlmRequestBody } from '@/interfaces/request/llm';
|
||||
import { useMemo } from 'react';
|
||||
import { VerifyResult } from '@/pages/user-setting/setting-model/hooks';
|
||||
import { memo, useCallback, useMemo, useRef } from 'react';
|
||||
import { FieldValues } from 'react-hook-form';
|
||||
import { LLMHeader } from '../../components/llm-header';
|
||||
import VerifyButton from '../../modal/verify-button';
|
||||
|
||||
const llmFactoryToUrlMap: Partial<Record<LLMFactory, string>> = {
|
||||
[LLMFactory.Ollama]:
|
||||
@ -38,6 +41,7 @@ const OllamaModal = ({
|
||||
visible,
|
||||
hideModal,
|
||||
onOk,
|
||||
onVerify,
|
||||
loading,
|
||||
llmFactory,
|
||||
editMode = false,
|
||||
@ -45,10 +49,14 @@ const OllamaModal = ({
|
||||
}: IModalProps<Partial<IAddLlmRequestBody> & { provider_order?: string }> & {
|
||||
llmFactory: string;
|
||||
editMode?: boolean;
|
||||
onVerify?: (
|
||||
postBody: any,
|
||||
) => Promise<boolean | void | VerifyResult | undefined>;
|
||||
}) => {
|
||||
const { t } = useTranslate('setting');
|
||||
const { t: tc } = useCommonTranslation();
|
||||
const { buildModelTypeOptions } = useBuildModelTypeOptions();
|
||||
const formRef = useRef<DynamicFormRef>(null);
|
||||
|
||||
const optionsMap: Partial<
|
||||
Record<LLMFactory, { label: string; value: string }[]>
|
||||
@ -233,6 +241,27 @@ const OllamaModal = ({
|
||||
await onOk?.(data);
|
||||
};
|
||||
|
||||
const verifyParamsFunc = useCallback(() => {
|
||||
const values = formRef.current?.getValues();
|
||||
const modelType =
|
||||
values.model_type === 'chat' && values.vision
|
||||
? 'image2text'
|
||||
: values.model_type;
|
||||
return {
|
||||
llm_factory: llmFactory,
|
||||
model_type: modelType,
|
||||
};
|
||||
}, [llmFactory]);
|
||||
|
||||
const handleVerify = useCallback(
|
||||
async (params: any) => {
|
||||
const verifyParams = verifyParamsFunc();
|
||||
const res = await onVerify?.({ ...params, ...verifyParams });
|
||||
return (res || { isValid: null, logs: '' }) as VerifyResult;
|
||||
},
|
||||
[verifyParamsFunc, onVerify],
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={<LLMHeader name={llmFactory} />}
|
||||
@ -245,10 +274,14 @@ const OllamaModal = ({
|
||||
<DynamicForm.Root
|
||||
key={`${visible}-${llmFactory}`}
|
||||
fields={fields}
|
||||
ref={formRef}
|
||||
onSubmit={() => {}}
|
||||
defaultValues={defaultValues}
|
||||
labelClassName="font-normal"
|
||||
>
|
||||
{onVerify && (
|
||||
<VerifyButton onVerify={handleVerify} isAbsolute={false} />
|
||||
)}
|
||||
<div className="flex items-center justify-between w-full gap-2 ">
|
||||
<a href={url} target="_blank" rel="noreferrer" className="text-sm">
|
||||
{t('ollamaLink', { name: llmFactory })}
|
||||
@ -273,4 +306,4 @@ const OllamaModal = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default OllamaModal;
|
||||
export default memo(OllamaModal);
|
||||
|
||||
@ -2,6 +2,7 @@ import { RAGFlowFormItem } from '@/components/ragflow-form';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog';
|
||||
@ -9,12 +10,15 @@ import { Form } from '@/components/ui/form';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { RAGFlowSelect, RAGFlowSelectOptionType } from '@/components/ui/select';
|
||||
import { LLMFactory } from '@/constants/llm';
|
||||
import { VerifyResult } from '@/pages/user-setting/setting-model/hooks';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { t } from 'i18next';
|
||||
import { memo } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { z } from 'zod';
|
||||
import { LLMHeader } from '../../components/llm-header';
|
||||
import VerifyButton from '../verify-button';
|
||||
|
||||
const FormSchema = z.object({
|
||||
llm_name: z.string().min(1, {
|
||||
@ -33,6 +37,9 @@ export interface IModalProps<T> {
|
||||
visible: boolean;
|
||||
hideModal: () => void;
|
||||
onOk?: (data: T) => Promise<boolean>;
|
||||
onVerify?: (
|
||||
postBody: any,
|
||||
) => Promise<boolean | void | VerifyResult | undefined>;
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
@ -44,6 +51,7 @@ const PaddleOCRModal = ({
|
||||
visible,
|
||||
hideModal,
|
||||
onOk,
|
||||
onVerify,
|
||||
loading,
|
||||
}: IModalProps<PaddleOCRFormValues>) => {
|
||||
const { t } = useTranslation();
|
||||
@ -113,22 +121,29 @@ const PaddleOCRModal = ({
|
||||
/>
|
||||
)}
|
||||
</RAGFlowFormItem>
|
||||
<div className="flex justify-end space-x-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={hideModal}
|
||||
className="btn btn-secondary"
|
||||
>
|
||||
{t('common.cancel')}
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={loading}
|
||||
className="btn btn-primary"
|
||||
>
|
||||
{t('common.add')}
|
||||
</button>
|
||||
</div>
|
||||
{onVerify && (
|
||||
<VerifyButton
|
||||
onVerify={onVerify as (postBody: any) => Promise<VerifyResult>}
|
||||
/>
|
||||
)}
|
||||
<DialogFooter>
|
||||
<div className="flex justify-end space-x-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={hideModal}
|
||||
className="btn btn-secondary"
|
||||
>
|
||||
{t('common.cancel')}
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={loading}
|
||||
className="btn btn-primary"
|
||||
>
|
||||
{t('common.add')}
|
||||
</button>
|
||||
</div>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</Form>
|
||||
</DialogContent>
|
||||
@ -136,4 +151,4 @@ const PaddleOCRModal = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default PaddleOCRModal;
|
||||
export default memo(PaddleOCRModal);
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import {
|
||||
DynamicForm,
|
||||
DynamicFormRef,
|
||||
FormFieldConfig,
|
||||
FormFieldType,
|
||||
} from '@/components/dynamic-form';
|
||||
@ -8,21 +9,30 @@ import { useCommonTranslation, useTranslate } from '@/hooks/common-hooks';
|
||||
import { useBuildModelTypeOptions } from '@/hooks/logic-hooks/use-build-options';
|
||||
import { IModalProps } from '@/interfaces/common';
|
||||
import { IAddLlmRequestBody } from '@/interfaces/request/llm';
|
||||
import { VerifyResult } from '@/pages/user-setting/setting-model/hooks';
|
||||
import omit from 'lodash/omit';
|
||||
import { memo, useCallback, useRef } from 'react';
|
||||
import { FieldValues } from 'react-hook-form';
|
||||
import { LLMHeader } from '../../components/llm-header';
|
||||
import VerifyButton from '../../modal/verify-button';
|
||||
|
||||
const SparkModal = ({
|
||||
visible,
|
||||
hideModal,
|
||||
onOk,
|
||||
onVerify,
|
||||
loading,
|
||||
llmFactory,
|
||||
}: IModalProps<IAddLlmRequestBody> & { llmFactory: string }) => {
|
||||
}: IModalProps<IAddLlmRequestBody> & {
|
||||
llmFactory: string;
|
||||
onVerify?: (
|
||||
postBody: any,
|
||||
) => Promise<boolean | void | VerifyResult | undefined>;
|
||||
}) => {
|
||||
const { t } = useTranslate('setting');
|
||||
const { t: tc } = useCommonTranslation();
|
||||
const { buildModelTypeOptions } = useBuildModelTypeOptions();
|
||||
|
||||
const formRef = useRef<DynamicFormRef>(null);
|
||||
const fields: FormFieldConfig[] = [
|
||||
{
|
||||
name: 'model_type',
|
||||
@ -128,6 +138,27 @@ const SparkModal = ({
|
||||
await onOk?.(data as IAddLlmRequestBody);
|
||||
};
|
||||
|
||||
const verifyParamsFunc = useCallback(() => {
|
||||
const values = formRef.current?.getValues();
|
||||
const modelType =
|
||||
values.model_type === 'chat' && values.vision
|
||||
? 'image2text'
|
||||
: values.model_type;
|
||||
return {
|
||||
llm_factory: llmFactory,
|
||||
model_type: modelType,
|
||||
};
|
||||
}, [llmFactory]);
|
||||
|
||||
const handleVerify = useCallback(
|
||||
async (params: any) => {
|
||||
const verifyParams = verifyParamsFunc();
|
||||
const res = await onVerify?.({ ...params, ...verifyParams });
|
||||
return (res || { isValid: null, logs: '' }) as VerifyResult;
|
||||
},
|
||||
[verifyParamsFunc, onVerify],
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={<LLMHeader name={llmFactory} />}
|
||||
@ -141,6 +172,7 @@ const SparkModal = ({
|
||||
onSubmit={(data) => {
|
||||
console.log(data);
|
||||
}}
|
||||
ref={formRef}
|
||||
defaultValues={
|
||||
{
|
||||
model_type: 'chat',
|
||||
@ -149,6 +181,7 @@ const SparkModal = ({
|
||||
}
|
||||
labelClassName="font-normal"
|
||||
>
|
||||
{onVerify && <VerifyButton onVerify={handleVerify} />}
|
||||
<div className="absolute bottom-0 right-0 left-0 flex items-center justify-end w-full gap-2 py-6 px-6">
|
||||
<DynamicForm.CancelButton
|
||||
handleCancel={() => {
|
||||
@ -168,4 +201,4 @@ const SparkModal = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default SparkModal;
|
||||
export default memo(SparkModal);
|
||||
|
||||
@ -0,0 +1,123 @@
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { useTranslate } from '@/hooks/common-hooks';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { replaceText } from '@/pages/dataset/process-log-modal';
|
||||
import { ApiKeyPostBody } from '@/pages/user-setting/interface';
|
||||
import { RefreshCcw } from 'lucide-react';
|
||||
import { memo, useCallback, useState } from 'react';
|
||||
import { useFormContext } from 'react-hook-form';
|
||||
import { VerifyResult } from '../../hooks';
|
||||
|
||||
interface IVerifyButton {
|
||||
onVerify: (params: any) => Promise<VerifyResult>;
|
||||
isAbsolute?: boolean;
|
||||
params?: any;
|
||||
}
|
||||
|
||||
const VerifyButton: React.FC<IVerifyButton> = ({
|
||||
onVerify,
|
||||
isAbsolute = true,
|
||||
params,
|
||||
}) => {
|
||||
const { t } = useTranslate('setting');
|
||||
const [isVerifying, setIsVerifying] = useState(false);
|
||||
const [verifyResult, setVerifyResult] = useState<VerifyResult | null>(null);
|
||||
const form = useFormContext();
|
||||
|
||||
const onHandleVerify = useCallback(async () => {
|
||||
const formValid = await form?.trigger();
|
||||
if (!formValid) {
|
||||
return;
|
||||
}
|
||||
// setVerifyLoading(true);
|
||||
try {
|
||||
const values = form.getValues();
|
||||
const result = await onVerify({
|
||||
...values,
|
||||
verify: true,
|
||||
...params,
|
||||
} as ApiKeyPostBody & { verify: boolean });
|
||||
setVerifyResult(result);
|
||||
} catch (error: any) {
|
||||
let logs = '';
|
||||
|
||||
if (error?.message) {
|
||||
logs = error.message;
|
||||
} else if (typeof error === 'string') {
|
||||
logs = error;
|
||||
}
|
||||
|
||||
setVerifyResult({
|
||||
isValid: false,
|
||||
logs: logs,
|
||||
});
|
||||
} finally {
|
||||
// setVerifyLoading(false);
|
||||
}
|
||||
}, [form, onVerify, params]);
|
||||
const handleVerify = async () => {
|
||||
setVerifyResult({
|
||||
isValid: null,
|
||||
logs: '',
|
||||
});
|
||||
setIsVerifying(true);
|
||||
try {
|
||||
await onHandleVerify();
|
||||
} catch (error) {
|
||||
setVerifyResult({
|
||||
isValid: false,
|
||||
logs: (error as Error).message || 'Unknown error',
|
||||
});
|
||||
} finally {
|
||||
setIsVerifying(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
!isAbsolute || (verifyResult && verifyResult.isValid === false)
|
||||
? 'flex flex-col gap-5 w-full '
|
||||
: 'absolute left-6 bottom-6 z-[100]',
|
||||
)}
|
||||
>
|
||||
<div className="flex gap-2 items-center">
|
||||
<Button
|
||||
type="button"
|
||||
onClick={handleVerify}
|
||||
disabled={isVerifying}
|
||||
variant={'ghost'}
|
||||
>
|
||||
<RefreshCcw
|
||||
size={14}
|
||||
className={cn(isVerifying ? 'animate-spin-reverse' : '', '')}
|
||||
/>
|
||||
{t('Verify')}
|
||||
</Button>
|
||||
|
||||
{verifyResult && verifyResult.isValid !== null && (
|
||||
<div
|
||||
className={`flex items-center gap-2 ${
|
||||
verifyResult.isValid ? 'text-state-success' : 'text-state-error'
|
||||
}`}
|
||||
>
|
||||
<span>
|
||||
{verifyResult.isValid ? t('keyValid') : t('keyInvalid')}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{verifyResult && verifyResult.isValid !== null && (
|
||||
<div className="space-y-2">
|
||||
{verifyResult.logs && (
|
||||
<div className="w-full whitespace-pre-line text-wrap bg-bg-card rounded-lg h-fit max-h-[250px] overflow-y-auto scrollbar-auto p-2.5">
|
||||
{replaceText(verifyResult.logs)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(VerifyButton);
|
||||
@ -1,5 +1,6 @@
|
||||
import {
|
||||
DynamicForm,
|
||||
DynamicFormRef,
|
||||
FormFieldConfig,
|
||||
FormFieldType,
|
||||
} from '@/components/dynamic-form';
|
||||
@ -8,8 +9,11 @@ import { useCommonTranslation, useTranslate } from '@/hooks/common-hooks';
|
||||
import { useBuildModelTypeOptions } from '@/hooks/logic-hooks/use-build-options';
|
||||
import { IModalProps } from '@/interfaces/common';
|
||||
import { IAddLlmRequestBody } from '@/interfaces/request/llm';
|
||||
import { VerifyResult } from '@/pages/user-setting/setting-model/hooks';
|
||||
import { memo, useCallback, useRef } from 'react';
|
||||
import { FieldValues } from 'react-hook-form';
|
||||
import { LLMHeader } from '../../components/llm-header';
|
||||
import VerifyButton from '../../modal/verify-button';
|
||||
|
||||
type VolcEngineLlmRequest = IAddLlmRequestBody & {
|
||||
endpoint_id: string;
|
||||
@ -20,13 +24,19 @@ const VolcEngineModal = ({
|
||||
visible,
|
||||
hideModal,
|
||||
onOk,
|
||||
onVerify,
|
||||
loading,
|
||||
llmFactory,
|
||||
}: IModalProps<IAddLlmRequestBody> & { llmFactory: string }) => {
|
||||
}: IModalProps<IAddLlmRequestBody> & {
|
||||
llmFactory: string;
|
||||
onVerify?: (
|
||||
postBody: any,
|
||||
) => Promise<boolean | void | VerifyResult | undefined>;
|
||||
}) => {
|
||||
const { t } = useTranslate('setting');
|
||||
const { t: tc } = useCommonTranslation();
|
||||
const { buildModelTypeOptions } = useBuildModelTypeOptions();
|
||||
|
||||
const formRef = useRef<DynamicFormRef>(null);
|
||||
const fields: FormFieldConfig[] = [
|
||||
{
|
||||
name: 'model_type',
|
||||
@ -91,6 +101,27 @@ const VolcEngineModal = ({
|
||||
await onOk?.(data);
|
||||
};
|
||||
|
||||
const verifyParamsFunc = useCallback(() => {
|
||||
const values = formRef.current?.getValues();
|
||||
const modelType =
|
||||
values.model_type === 'chat' && values.vision
|
||||
? 'image2text'
|
||||
: values.model_type;
|
||||
return {
|
||||
llm_factory: llmFactory,
|
||||
model_type: modelType,
|
||||
};
|
||||
}, [llmFactory]);
|
||||
|
||||
const handleVerify = useCallback(
|
||||
async (params: any) => {
|
||||
const verifyParams = verifyParamsFunc();
|
||||
const res = await onVerify?.({ ...params, ...verifyParams });
|
||||
return (res || { isValid: null, logs: '' }) as VerifyResult;
|
||||
},
|
||||
[verifyParamsFunc, onVerify],
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={<LLMHeader name={llmFactory} />}
|
||||
@ -104,6 +135,7 @@ const VolcEngineModal = ({
|
||||
onSubmit={(data) => {
|
||||
console.log(data);
|
||||
}}
|
||||
ref={formRef}
|
||||
defaultValues={
|
||||
{
|
||||
model_type: 'chat',
|
||||
@ -112,6 +144,9 @@ const VolcEngineModal = ({
|
||||
}
|
||||
labelClassName="font-normal"
|
||||
>
|
||||
{onVerify && (
|
||||
<VerifyButton onVerify={handleVerify} isAbsolute={false} />
|
||||
)}
|
||||
<div className="absolute bottom-0 right-0 left-0 flex items-center justify-between w-full py-6 px-6">
|
||||
<a
|
||||
href="https://www.volcengine.com/docs/82379/1302008"
|
||||
@ -140,4 +175,4 @@ const VolcEngineModal = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default VolcEngineModal;
|
||||
export default memo(VolcEngineModal);
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import {
|
||||
DynamicForm,
|
||||
DynamicFormRef,
|
||||
FormFieldConfig,
|
||||
FormFieldType,
|
||||
} from '@/components/dynamic-form';
|
||||
@ -8,61 +9,74 @@ import { useCommonTranslation, useTranslate } from '@/hooks/common-hooks';
|
||||
import { useBuildModelTypeOptions } from '@/hooks/logic-hooks/use-build-options';
|
||||
import { IModalProps } from '@/interfaces/common';
|
||||
import { IAddLlmRequestBody } from '@/interfaces/request/llm';
|
||||
import { VerifyResult } from '@/pages/user-setting/setting-model/hooks';
|
||||
import { memo, useCallback, useMemo, useRef } from 'react';
|
||||
import { FieldValues } from 'react-hook-form';
|
||||
import { LLMHeader } from '../../components/llm-header';
|
||||
import VerifyButton from '../../modal/verify-button';
|
||||
|
||||
const YiyanModal = ({
|
||||
visible,
|
||||
hideModal,
|
||||
onOk,
|
||||
onVerify,
|
||||
loading,
|
||||
llmFactory,
|
||||
}: IModalProps<IAddLlmRequestBody> & { llmFactory: string }) => {
|
||||
}: IModalProps<IAddLlmRequestBody> & {
|
||||
llmFactory: string;
|
||||
onVerify?: (
|
||||
postBody: any,
|
||||
) => Promise<boolean | void | VerifyResult | undefined>;
|
||||
}) => {
|
||||
const { t } = useTranslate('setting');
|
||||
const { t: tc } = useCommonTranslation();
|
||||
const { buildModelTypeOptions } = useBuildModelTypeOptions();
|
||||
const formRef = useRef<DynamicFormRef>(null);
|
||||
|
||||
const fields: FormFieldConfig[] = [
|
||||
{
|
||||
name: 'model_type',
|
||||
label: t('modelType'),
|
||||
type: FormFieldType.Select,
|
||||
required: true,
|
||||
options: buildModelTypeOptions(['chat', 'embedding', 'rerank']),
|
||||
defaultValue: 'chat',
|
||||
},
|
||||
{
|
||||
name: 'llm_name',
|
||||
label: t('modelName'),
|
||||
type: FormFieldType.Text,
|
||||
required: true,
|
||||
placeholder: t('yiyanModelNameMessage'),
|
||||
},
|
||||
{
|
||||
name: 'yiyan_ak',
|
||||
label: t('addyiyanAK'),
|
||||
type: FormFieldType.Text,
|
||||
required: true,
|
||||
placeholder: t('yiyanAKMessage'),
|
||||
},
|
||||
{
|
||||
name: 'yiyan_sk',
|
||||
label: t('addyiyanSK'),
|
||||
type: FormFieldType.Text,
|
||||
required: true,
|
||||
placeholder: t('yiyanSKMessage'),
|
||||
},
|
||||
{
|
||||
name: 'max_tokens',
|
||||
label: t('maxTokens'),
|
||||
type: FormFieldType.Number,
|
||||
required: true,
|
||||
placeholder: t('maxTokensTip'),
|
||||
validation: {
|
||||
min: 0,
|
||||
const fields = useMemo<FormFieldConfig[]>(
|
||||
() => [
|
||||
{
|
||||
name: 'model_type',
|
||||
label: t('modelType'),
|
||||
type: FormFieldType.Select,
|
||||
required: true,
|
||||
options: buildModelTypeOptions(['chat', 'embedding', 'rerank']),
|
||||
defaultValue: 'chat',
|
||||
},
|
||||
},
|
||||
];
|
||||
{
|
||||
name: 'llm_name',
|
||||
label: t('modelName'),
|
||||
type: FormFieldType.Text,
|
||||
required: true,
|
||||
placeholder: t('yiyanModelNameMessage'),
|
||||
},
|
||||
{
|
||||
name: 'yiyan_ak',
|
||||
label: t('addyiyanAK'),
|
||||
type: FormFieldType.Text,
|
||||
required: true,
|
||||
placeholder: t('yiyanAKMessage'),
|
||||
},
|
||||
{
|
||||
name: 'yiyan_sk',
|
||||
label: t('addyiyanSK'),
|
||||
type: FormFieldType.Text,
|
||||
required: true,
|
||||
placeholder: t('yiyanSKMessage'),
|
||||
},
|
||||
{
|
||||
name: 'max_tokens',
|
||||
label: t('maxTokens'),
|
||||
type: FormFieldType.Number,
|
||||
required: true,
|
||||
placeholder: t('maxTokensTip'),
|
||||
validation: {
|
||||
min: 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
[t, buildModelTypeOptions],
|
||||
);
|
||||
|
||||
const handleOk = async (values?: FieldValues) => {
|
||||
if (!values) return;
|
||||
@ -88,16 +102,47 @@ const YiyanModal = ({
|
||||
await onOk?.(data);
|
||||
};
|
||||
|
||||
const verifyParamsFunc = useCallback(() => {
|
||||
const values = formRef.current?.getValues();
|
||||
const modelType =
|
||||
values.model_type === 'chat' && values.vision
|
||||
? 'image2text'
|
||||
: values.model_type;
|
||||
return {
|
||||
llm_factory: llmFactory,
|
||||
llm_name: values.llm_name as string,
|
||||
model_type: modelType,
|
||||
api_key: {
|
||||
yiyan_ak: values.yiyan_ak,
|
||||
yiyan_sk: values.yiyan_sk,
|
||||
},
|
||||
max_tokens: values.max_tokens as number,
|
||||
};
|
||||
}, [llmFactory]);
|
||||
|
||||
const handleVerify = useCallback(
|
||||
async (params: any) => {
|
||||
const verifyParams = verifyParamsFunc();
|
||||
const res = await onVerify?.({ ...params, ...verifyParams });
|
||||
return (res || { isValid: null, logs: '' }) as VerifyResult;
|
||||
},
|
||||
[verifyParamsFunc, onVerify],
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={<LLMHeader name={llmFactory} />}
|
||||
open={visible || false}
|
||||
onOpenChange={(open) => !open && hideModal?.()}
|
||||
maskClosable={false}
|
||||
footer={<div className="p-4"></div>}
|
||||
// footer={<div className="p-4"></div>}
|
||||
footer={<></>}
|
||||
footerClassName="pb-10"
|
||||
>
|
||||
<DynamicForm.Root
|
||||
key={`${visible}-${llmFactory}`}
|
||||
fields={fields}
|
||||
ref={formRef}
|
||||
onSubmit={(data) => {
|
||||
console.log(data);
|
||||
}}
|
||||
@ -109,23 +154,26 @@ const YiyanModal = ({
|
||||
}
|
||||
labelClassName="font-normal"
|
||||
>
|
||||
<div className="absolute bottom-0 right-0 left-0 flex items-center justify-end w-full gap-2 py-6 px-6">
|
||||
<DynamicForm.CancelButton
|
||||
handleCancel={() => {
|
||||
hideModal?.();
|
||||
}}
|
||||
/>
|
||||
<DynamicForm.SavingButton
|
||||
submitLoading={loading || false}
|
||||
buttonText={tc('ok')}
|
||||
submitFunc={(values: FieldValues) => {
|
||||
handleOk(values);
|
||||
}}
|
||||
/>
|
||||
<div>
|
||||
{onVerify && <VerifyButton onVerify={handleVerify} />}
|
||||
<div className="absolute bottom-0 right-0 left-0 flex items-center justify-end w-full gap-2 py-6 px-6">
|
||||
<DynamicForm.CancelButton
|
||||
handleCancel={() => {
|
||||
hideModal?.();
|
||||
}}
|
||||
/>
|
||||
<DynamicForm.SavingButton
|
||||
submitLoading={loading || false}
|
||||
buttonText={tc('ok')}
|
||||
submitFunc={(values: FieldValues) => {
|
||||
handleOk(values);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</DynamicForm.Root>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default YiyanModal;
|
||||
export default memo(YiyanModal);
|
||||
|
||||
@ -211,11 +211,16 @@ module.exports = {
|
||||
'0%,70%,100%': { opacity: '1' },
|
||||
'20%,50%': { opacity: '0' },
|
||||
},
|
||||
'spin-reverse': {
|
||||
from: { transform: 'rotate(0deg)' },
|
||||
to: { transform: 'rotate(-360deg)' },
|
||||
},
|
||||
},
|
||||
animation: {
|
||||
'accordion-down': 'accordion-down 0.2s ease-out',
|
||||
'accordion-up': 'accordion-up 0.2s ease-out',
|
||||
'caret-blink': 'caret-blink 1.25s ease-out infinite',
|
||||
'spin-reverse': 'spin-reverse 1s linear infinite',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user