mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-07-29 04:08:12 +08:00
### What problem does this PR solve? feat:Unify the 'Add Model Provider' modal ### Type of change - [x] New Feature (non-breaking change which adds functionality) - [x] Refactoring
217 lines
6.1 KiB
TypeScript
217 lines
6.1 KiB
TypeScript
import { useSetModalState } from '@/hooks/common-hooks';
|
|
import {
|
|
useAddInstanceModel,
|
|
useAddProviderInstance,
|
|
useFetchAddedProviders,
|
|
useFetchProviderInstances,
|
|
useVerifyProviderConnection,
|
|
} from '@/hooks/use-llm-request';
|
|
import {
|
|
IAddProviderInstanceRequestBody,
|
|
IModelInfo,
|
|
} from '@/interfaces/request/llm';
|
|
import { useCallback, useMemo, useState } from 'react';
|
|
import { splitProviderPayload } from './payload-utils';
|
|
|
|
export type VerifyResult = {
|
|
isValid: boolean | null;
|
|
logs: string;
|
|
};
|
|
|
|
/**
|
|
* Unified Provider instance submission hook
|
|
* Internally handles both verify and save modes
|
|
*/
|
|
const useSubmitProviderInstance = () => {
|
|
const { addProviderInstance } = useAddProviderInstance();
|
|
const { addInstanceModel } = useAddInstanceModel();
|
|
|
|
return useCallback(
|
|
async (payload: IAddProviderInstanceRequestBody, isVerify = false) => {
|
|
if (isVerify) {
|
|
return addProviderInstance({ ...payload, verify: true });
|
|
}
|
|
|
|
// Multi-model flow: when model_info is provided as an array, the
|
|
// backend is expected to create the instance and all listed models
|
|
// in a single addProviderInstance call. Skip the instance/model split.
|
|
if (Array.isArray((payload as any).model_info)) {
|
|
return addProviderInstance(payload as IAddProviderInstanceRequestBody);
|
|
}
|
|
|
|
const { instancePayload, modelPayload } = splitProviderPayload(payload);
|
|
const hasModelPayload =
|
|
!!modelPayload.model_name && !!modelPayload.model_type;
|
|
|
|
const instanceRet = await addProviderInstance({
|
|
...instancePayload,
|
|
llm_factory: payload.llm_factory,
|
|
instance_name: payload.instance_name,
|
|
} as IAddProviderInstanceRequestBody);
|
|
if (instanceRet.code !== 0 || !hasModelPayload) {
|
|
return instanceRet;
|
|
}
|
|
|
|
if (!hasModelPayload) {
|
|
return { code: 0, data: null } as any;
|
|
}
|
|
|
|
return addInstanceModel({
|
|
provider_name: payload.llm_factory,
|
|
instance_name: payload.instance_name,
|
|
...modelPayload,
|
|
});
|
|
},
|
|
[addProviderInstance, addInstanceModel],
|
|
);
|
|
};
|
|
|
|
export const useFetchInstanceNameSet = (providerName: string) => {
|
|
const { data: addedProviders } = useFetchAddedProviders();
|
|
const providerExists = useMemo(
|
|
() => addedProviders.some((p) => p.name === providerName),
|
|
[addedProviders, providerName],
|
|
);
|
|
const { data: instances } = useFetchProviderInstances(
|
|
providerExists ? providerName : '',
|
|
);
|
|
const instanceNameSet = useMemo(
|
|
() => new Set(instances.map((i) => i.instance_name)),
|
|
[instances],
|
|
);
|
|
return { instanceNameSet, providerExists };
|
|
};
|
|
|
|
export const useHideWhenInstanceExists = (instanceNameSet: Set<string>) => {
|
|
return useCallback(
|
|
(formValues: any) => {
|
|
const name = ((formValues?.instance_name as string) || '').trim();
|
|
return !(name && instanceNameSet.has(name));
|
|
},
|
|
[instanceNameSet],
|
|
);
|
|
};
|
|
|
|
export const useVerifyConnection = () => {
|
|
const { verifyProviderConnection } = useVerifyProviderConnection();
|
|
|
|
return useCallback(
|
|
async (
|
|
providerName: string,
|
|
apiKey: string,
|
|
baseUrl?: string,
|
|
region?: string,
|
|
modelInfo?: IModelInfo[],
|
|
) => {
|
|
const ret = await verifyProviderConnection({
|
|
provider_name: providerName,
|
|
api_key: apiKey,
|
|
base_url: baseUrl,
|
|
region: region,
|
|
model_info: modelInfo,
|
|
});
|
|
|
|
if (ret.code === 0) {
|
|
return {
|
|
isValid: true,
|
|
logs: ret.message,
|
|
} as VerifyResult;
|
|
} else {
|
|
return {
|
|
isValid: false,
|
|
logs: ret.message,
|
|
} as VerifyResult;
|
|
}
|
|
},
|
|
[verifyProviderConnection],
|
|
);
|
|
};
|
|
|
|
// ============ Hooks for the 4 retained special modals ============
|
|
// Bedrock / MinerU / PaddleOCR / OpenDataLoader are not yet merged into ProviderModal
|
|
|
|
export const useSubmitBedrock = () => {
|
|
const [saveLoading, setSaveLoading] = useState(false);
|
|
const submitProviderInstance = useSubmitProviderInstance();
|
|
const verifyConnection = useVerifyConnection();
|
|
const {
|
|
visible: bedrockAddingVisible,
|
|
hideModal: hideBedrockAddingModal,
|
|
showModal: showBedrockAddingModal,
|
|
} = useSetModalState();
|
|
|
|
const onBedrockAddingOk = useCallback(
|
|
async (payload: IAddProviderInstanceRequestBody, isVerify = false) => {
|
|
if (!isVerify) {
|
|
setSaveLoading(true);
|
|
}
|
|
if (isVerify) {
|
|
const legacyPayload = payload as any;
|
|
const modelType = Array.isArray(legacyPayload.model_type)
|
|
? (legacyPayload.model_type as string[])
|
|
: legacyPayload.model_type
|
|
? [legacyPayload.model_type as string]
|
|
: [];
|
|
const apiKey = JSON.stringify({
|
|
auth_mode: legacyPayload.auth_mode,
|
|
bedrock_ak: legacyPayload.bedrock_ak,
|
|
bedrock_sk: legacyPayload.bedrock_sk,
|
|
aws_role_arn: legacyPayload.aws_role_arn,
|
|
});
|
|
return verifyConnection(
|
|
payload.llm_factory as string,
|
|
apiKey,
|
|
legacyPayload.bedrock_region,
|
|
undefined,
|
|
[
|
|
{
|
|
model_type: modelType,
|
|
model_name: (legacyPayload.model_name as string) ?? '',
|
|
max_tokens: (legacyPayload.max_tokens as number) ?? 0,
|
|
},
|
|
],
|
|
);
|
|
}
|
|
const ret = await submitProviderInstance(payload, false);
|
|
setSaveLoading(false);
|
|
if (ret.code === 0) {
|
|
hideBedrockAddingModal();
|
|
}
|
|
},
|
|
[
|
|
hideBedrockAddingModal,
|
|
submitProviderInstance,
|
|
setSaveLoading,
|
|
verifyConnection,
|
|
],
|
|
);
|
|
|
|
return {
|
|
bedrockAddingLoading: saveLoading,
|
|
onBedrockAddingOk,
|
|
bedrockAddingVisible,
|
|
hideBedrockAddingModal,
|
|
showBedrockAddingModal,
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Wraps the verify callback: provides a unified call with isVerify=true for the Verify button
|
|
*/
|
|
export const useVerifySettings = ({
|
|
onVerify,
|
|
}: {
|
|
onVerify: (postBody: any, isVerify?: boolean) => Promise<any>;
|
|
}) => {
|
|
const onApiKeyVerifying = useCallback(
|
|
async (postBody: any) => {
|
|
const res = await onVerify(postBody, true);
|
|
return res;
|
|
},
|
|
[onVerify],
|
|
);
|
|
return {
|
|
onApiKeyVerifying,
|
|
};
|
|
};
|