mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 12:32:30 +08:00
Fixes: Added session variable types and modified configuration (#11269)
### What problem does this PR solve? Fixes: Added session variable types and modified configuration - Added more types of session variables - Modified the embedding model switching logic in the knowledge base configuration ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
@ -61,6 +61,12 @@ export interface FormFieldConfig {
|
||||
horizontal?: boolean;
|
||||
onChange?: (value: any) => void;
|
||||
tooltip?: React.ReactNode;
|
||||
customValidate?: (
|
||||
value: any,
|
||||
formValues: any,
|
||||
) => string | boolean | Promise<string | boolean>;
|
||||
dependencies?: string[];
|
||||
schema?: ZodSchema;
|
||||
}
|
||||
|
||||
// Component props interface
|
||||
@ -94,36 +100,40 @@ const generateSchema = (fields: FormFieldConfig[]): ZodSchema<any> => {
|
||||
let fieldSchema: ZodSchema;
|
||||
|
||||
// Create base validation schema based on field type
|
||||
switch (field.type) {
|
||||
case FormFieldType.Email:
|
||||
fieldSchema = z.string().email('Please enter a valid email address');
|
||||
break;
|
||||
case FormFieldType.Number:
|
||||
fieldSchema = z.coerce.number();
|
||||
if (field.validation?.min !== undefined) {
|
||||
fieldSchema = (fieldSchema as z.ZodNumber).min(
|
||||
field.validation.min,
|
||||
field.validation.message ||
|
||||
`Value cannot be less than ${field.validation.min}`,
|
||||
);
|
||||
}
|
||||
if (field.validation?.max !== undefined) {
|
||||
fieldSchema = (fieldSchema as z.ZodNumber).max(
|
||||
field.validation.max,
|
||||
field.validation.message ||
|
||||
`Value cannot be greater than ${field.validation.max}`,
|
||||
);
|
||||
}
|
||||
break;
|
||||
case FormFieldType.Checkbox:
|
||||
fieldSchema = z.boolean();
|
||||
break;
|
||||
case FormFieldType.Tag:
|
||||
fieldSchema = z.array(z.string());
|
||||
break;
|
||||
default:
|
||||
fieldSchema = z.string();
|
||||
break;
|
||||
if (field.schema) {
|
||||
fieldSchema = field.schema;
|
||||
} else {
|
||||
switch (field.type) {
|
||||
case FormFieldType.Email:
|
||||
fieldSchema = z.string().email('Please enter a valid email address');
|
||||
break;
|
||||
case FormFieldType.Number:
|
||||
fieldSchema = z.coerce.number();
|
||||
if (field.validation?.min !== undefined) {
|
||||
fieldSchema = (fieldSchema as z.ZodNumber).min(
|
||||
field.validation.min,
|
||||
field.validation.message ||
|
||||
`Value cannot be less than ${field.validation.min}`,
|
||||
);
|
||||
}
|
||||
if (field.validation?.max !== undefined) {
|
||||
fieldSchema = (fieldSchema as z.ZodNumber).max(
|
||||
field.validation.max,
|
||||
field.validation.message ||
|
||||
`Value cannot be greater than ${field.validation.max}`,
|
||||
);
|
||||
}
|
||||
break;
|
||||
case FormFieldType.Checkbox:
|
||||
fieldSchema = z.boolean();
|
||||
break;
|
||||
case FormFieldType.Tag:
|
||||
fieldSchema = z.array(z.string());
|
||||
break;
|
||||
default:
|
||||
fieldSchema = z.string();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle required fields
|
||||
@ -300,10 +310,90 @@ const DynamicForm = {
|
||||
|
||||
// Initialize form
|
||||
const form = useForm<T>({
|
||||
resolver: zodResolver(schema),
|
||||
resolver: async (data, context, options) => {
|
||||
const zodResult = await zodResolver(schema)(data, context, options);
|
||||
|
||||
let combinedErrors = { ...zodResult.errors };
|
||||
|
||||
const fieldErrors: Record<string, { type: string; message: string }> =
|
||||
{};
|
||||
for (const field of fields) {
|
||||
if (field.customValidate && data[field.name] !== undefined) {
|
||||
try {
|
||||
const result = await field.customValidate(
|
||||
data[field.name],
|
||||
data,
|
||||
);
|
||||
if (typeof result === 'string') {
|
||||
fieldErrors[field.name] = {
|
||||
type: 'custom',
|
||||
message: result,
|
||||
};
|
||||
} else if (result === false) {
|
||||
fieldErrors[field.name] = {
|
||||
type: 'custom',
|
||||
message:
|
||||
field.validation?.message || `${field.label} is invalid`,
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
fieldErrors[field.name] = {
|
||||
type: 'custom',
|
||||
message:
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: 'Validation failed',
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
combinedErrors = {
|
||||
...combinedErrors,
|
||||
...fieldErrors,
|
||||
} as any;
|
||||
console.log('combinedErrors', combinedErrors);
|
||||
return {
|
||||
values: Object.keys(combinedErrors).length ? {} : data,
|
||||
errors: combinedErrors,
|
||||
} as any;
|
||||
},
|
||||
defaultValues,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const dependencyMap: Record<string, string[]> = {};
|
||||
|
||||
fields.forEach((field) => {
|
||||
if (field.dependencies && field.dependencies.length > 0) {
|
||||
field.dependencies.forEach((dep) => {
|
||||
if (!dependencyMap[dep]) {
|
||||
dependencyMap[dep] = [];
|
||||
}
|
||||
dependencyMap[dep].push(field.name);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const subscriptions = Object.keys(dependencyMap).map((depField) => {
|
||||
return form.watch((values: any, { name }) => {
|
||||
if (name === depField && dependencyMap[depField]) {
|
||||
dependencyMap[depField].forEach((dependentField) => {
|
||||
form.trigger(dependentField as any);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return () => {
|
||||
subscriptions.forEach((sub) => {
|
||||
if (sub.unsubscribe) {
|
||||
sub.unsubscribe();
|
||||
}
|
||||
});
|
||||
};
|
||||
}, [fields, form]);
|
||||
|
||||
// Expose form methods via ref
|
||||
useImperativeHandle(ref, () => ({
|
||||
submit: () => form.handleSubmit(onSubmit)(),
|
||||
|
||||
@ -51,6 +51,7 @@ export interface SegmentedProps
|
||||
direction?: 'ltr' | 'rtl';
|
||||
motionName?: string;
|
||||
activeClassName?: string;
|
||||
itemClassName?: string;
|
||||
rounded?: keyof typeof segmentedVariants.round;
|
||||
sizeType?: keyof typeof segmentedVariants.size;
|
||||
buttonSize?: keyof typeof segmentedVariants.buttonSize;
|
||||
@ -62,6 +63,7 @@ export function Segmented({
|
||||
onChange,
|
||||
className,
|
||||
activeClassName,
|
||||
itemClassName,
|
||||
rounded = 'default',
|
||||
sizeType = 'default',
|
||||
buttonSize = 'default',
|
||||
@ -92,12 +94,13 @@ export function Segmented({
|
||||
<div
|
||||
key={actualValue}
|
||||
className={cn(
|
||||
'inline-flex items-center text-base font-normal cursor-pointer',
|
||||
'inline-flex items-center text-base font-normal cursor-pointer',
|
||||
segmentedVariants.round[rounded],
|
||||
segmentedVariants.buttonSize[buttonSize],
|
||||
{
|
||||
'text-text-primary bg-bg-base': selectedValue === actualValue,
|
||||
},
|
||||
itemClassName,
|
||||
activeClassName && selectedValue === actualValue
|
||||
? activeClassName
|
||||
: '',
|
||||
|
||||
@ -1009,6 +1009,7 @@ Example: general/v2/`,
|
||||
pleaseUploadAtLeastOneFile: 'Please upload at least one file',
|
||||
},
|
||||
flow: {
|
||||
formatTypeError: 'Format or type error',
|
||||
variableNameMessage:
|
||||
'Variable name can only contain letters and underscores',
|
||||
variableDescription: 'Variable Description',
|
||||
|
||||
@ -956,6 +956,7 @@ General:实体和关系提取提示来自 GitHub - microsoft/graphrag:基于
|
||||
pleaseUploadAtLeastOneFile: '请上传至少一个文件',
|
||||
},
|
||||
flow: {
|
||||
formatTypeError: '格式或类型错误',
|
||||
variableNameMessage: '名称只能包含字母和下划线',
|
||||
variableDescription: '变量的描述',
|
||||
defaultValue: '默认值',
|
||||
|
||||
@ -0,0 +1,134 @@
|
||||
import {
|
||||
DynamicForm,
|
||||
DynamicFormRef,
|
||||
FormFieldConfig,
|
||||
} from '@/components/dynamic-form';
|
||||
import { Modal } from '@/components/ui/modal/modal';
|
||||
import { t } from 'i18next';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { FieldValues } from 'react-hook-form';
|
||||
import { TypeMaps, TypesWithArray } from '../constant';
|
||||
import { useHandleForm } from '../hooks/use-form';
|
||||
import { useObjectFields } from '../hooks/use-object-fields';
|
||||
|
||||
export const AddVariableModal = (props: {
|
||||
fields?: FormFieldConfig[];
|
||||
setFields: (value: any) => void;
|
||||
visible?: boolean;
|
||||
hideModal: () => void;
|
||||
defaultValues?: FieldValues;
|
||||
setDefaultValues?: (value: FieldValues) => void;
|
||||
}) => {
|
||||
const {
|
||||
fields,
|
||||
setFields,
|
||||
visible,
|
||||
hideModal,
|
||||
defaultValues,
|
||||
setDefaultValues,
|
||||
} = props;
|
||||
|
||||
const { handleSubmit: submitForm, loading } = useHandleForm();
|
||||
|
||||
const { handleCustomValidate, handleCustomSchema, handleRender } =
|
||||
useObjectFields();
|
||||
|
||||
const formRef = useRef<DynamicFormRef>(null);
|
||||
|
||||
const handleFieldUpdate = (
|
||||
fieldName: string,
|
||||
updatedField: Partial<FormFieldConfig>,
|
||||
) => {
|
||||
setFields((prevFields: any) =>
|
||||
prevFields.map((field: any) =>
|
||||
field.name === fieldName ? { ...field, ...updatedField } : field,
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const typeField = fields?.find((item) => item.name === 'type');
|
||||
|
||||
if (typeField) {
|
||||
typeField.onChange = (value) => {
|
||||
handleFieldUpdate('value', {
|
||||
type: TypeMaps[value as keyof typeof TypeMaps],
|
||||
render: handleRender(value),
|
||||
customValidate: handleCustomValidate(value),
|
||||
schema: handleCustomSchema(value),
|
||||
});
|
||||
const values = formRef.current?.getValues();
|
||||
// setTimeout(() => {
|
||||
switch (value) {
|
||||
case TypesWithArray.Boolean:
|
||||
setDefaultValues?.({ ...values, value: false });
|
||||
break;
|
||||
case TypesWithArray.Number:
|
||||
setDefaultValues?.({ ...values, value: 0 });
|
||||
break;
|
||||
case TypesWithArray.Object:
|
||||
setDefaultValues?.({ ...values, value: {} });
|
||||
break;
|
||||
case TypesWithArray.ArrayString:
|
||||
setDefaultValues?.({ ...values, value: [''] });
|
||||
break;
|
||||
case TypesWithArray.ArrayNumber:
|
||||
setDefaultValues?.({ ...values, value: [''] });
|
||||
break;
|
||||
case TypesWithArray.ArrayBoolean:
|
||||
setDefaultValues?.({ ...values, value: [false] });
|
||||
break;
|
||||
case TypesWithArray.ArrayObject:
|
||||
setDefaultValues?.({ ...values, value: [] });
|
||||
break;
|
||||
default:
|
||||
setDefaultValues?.({ ...values, value: '' });
|
||||
break;
|
||||
}
|
||||
// }, 0);
|
||||
};
|
||||
}
|
||||
}, [fields]);
|
||||
|
||||
const handleSubmit = async (fieldValue: FieldValues) => {
|
||||
await submitForm(fieldValue);
|
||||
hideModal();
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={t('flow.add') + t('flow.conversationVariable')}
|
||||
open={visible || false}
|
||||
onCancel={hideModal}
|
||||
showfooter={false}
|
||||
>
|
||||
<DynamicForm.Root
|
||||
ref={formRef}
|
||||
fields={fields || []}
|
||||
onSubmit={(data) => {
|
||||
console.log(data);
|
||||
}}
|
||||
defaultValues={defaultValues}
|
||||
onFieldUpdate={handleFieldUpdate}
|
||||
>
|
||||
<div className="flex items-center justify-end w-full gap-2">
|
||||
<DynamicForm.CancelButton
|
||||
handleCancel={() => {
|
||||
hideModal?.();
|
||||
}}
|
||||
/>
|
||||
<DynamicForm.SavingButton
|
||||
submitLoading={loading || false}
|
||||
buttonText={t('common.ok')}
|
||||
submitFunc={(values: FieldValues) => {
|
||||
handleSubmit(values);
|
||||
// console.log(values);
|
||||
// console.log(nodes, edges);
|
||||
// handleOk(values);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</DynamicForm.Root>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
@ -13,14 +13,14 @@ export enum TypesWithArray {
|
||||
String = 'string',
|
||||
Number = 'number',
|
||||
Boolean = 'boolean',
|
||||
// Object = 'object',
|
||||
// ArrayString = 'array<string>',
|
||||
// ArrayNumber = 'array<number>',
|
||||
// ArrayBoolean = 'array<boolean>',
|
||||
// ArrayObject = 'array<object>',
|
||||
Object = 'object',
|
||||
ArrayString = 'array<string>',
|
||||
ArrayNumber = 'array<number>',
|
||||
ArrayBoolean = 'array<boolean>',
|
||||
ArrayObject = 'array<object>',
|
||||
}
|
||||
|
||||
export const GobalFormFields = [
|
||||
export const GlobalFormFields = [
|
||||
{
|
||||
label: t('flow.name'),
|
||||
name: 'name',
|
||||
@ -50,11 +50,11 @@ export const GobalFormFields = [
|
||||
label: t('flow.description'),
|
||||
name: 'description',
|
||||
placeholder: t('flow.variableDescription'),
|
||||
type: 'textarea',
|
||||
type: FormFieldType.Textarea,
|
||||
},
|
||||
] as FormFieldConfig[];
|
||||
|
||||
export const GobalVariableFormDefaultValues = {
|
||||
export const GlobalVariableFormDefaultValues = {
|
||||
name: '',
|
||||
type: TypesWithArray.String,
|
||||
value: '',
|
||||
@ -65,9 +65,9 @@ export const TypeMaps = {
|
||||
[TypesWithArray.String]: FormFieldType.Textarea,
|
||||
[TypesWithArray.Number]: FormFieldType.Number,
|
||||
[TypesWithArray.Boolean]: FormFieldType.Checkbox,
|
||||
// [TypesWithArray.Object]: FormFieldType.Textarea,
|
||||
// [TypesWithArray.ArrayString]: FormFieldType.Textarea,
|
||||
// [TypesWithArray.ArrayNumber]: FormFieldType.Textarea,
|
||||
// [TypesWithArray.ArrayBoolean]: FormFieldType.Textarea,
|
||||
// [TypesWithArray.ArrayObject]: FormFieldType.Textarea,
|
||||
[TypesWithArray.Object]: FormFieldType.Textarea,
|
||||
[TypesWithArray.ArrayString]: FormFieldType.Textarea,
|
||||
[TypesWithArray.ArrayNumber]: FormFieldType.Textarea,
|
||||
[TypesWithArray.ArrayBoolean]: FormFieldType.Textarea,
|
||||
[TypesWithArray.ArrayObject]: FormFieldType.Textarea,
|
||||
};
|
||||
41
web/src/pages/agent/gobal-variable-sheet/hooks/use-form.tsx
Normal file
41
web/src/pages/agent/gobal-variable-sheet/hooks/use-form.tsx
Normal file
@ -0,0 +1,41 @@
|
||||
import { useFetchAgent } from '@/hooks/use-agent-request';
|
||||
import { GlobalVariableType } from '@/interfaces/database/agent';
|
||||
import { useCallback } from 'react';
|
||||
import { FieldValues } from 'react-hook-form';
|
||||
import { useSaveGraph } from '../../hooks/use-save-graph';
|
||||
import { TypesWithArray } from '../constant';
|
||||
|
||||
export const useHandleForm = () => {
|
||||
const { data, refetch } = useFetchAgent();
|
||||
const { saveGraph, loading } = useSaveGraph();
|
||||
const handleObjectData = (value: any) => {
|
||||
try {
|
||||
return JSON.parse(value);
|
||||
} catch (error) {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
const handleSubmit = useCallback(async (fieldValue: FieldValues) => {
|
||||
const param = {
|
||||
...(data.dsl?.variables || {}),
|
||||
[fieldValue.name]: {
|
||||
...fieldValue,
|
||||
value:
|
||||
fieldValue.type === TypesWithArray.Object ||
|
||||
fieldValue.type === TypesWithArray.ArrayObject
|
||||
? handleObjectData(fieldValue.value)
|
||||
: fieldValue.value,
|
||||
},
|
||||
} as Record<string, GlobalVariableType>;
|
||||
|
||||
const res = await saveGraph(undefined, {
|
||||
globalVariables: param,
|
||||
});
|
||||
|
||||
if (res.code === 0) {
|
||||
refetch();
|
||||
}
|
||||
}, []);
|
||||
|
||||
return { handleSubmit, loading };
|
||||
};
|
||||
@ -0,0 +1,246 @@
|
||||
import { BlockButton, Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Segmented } from '@/components/ui/segmented';
|
||||
import { Editor } from '@monaco-editor/react';
|
||||
import { t } from 'i18next';
|
||||
import { Trash2, X } from 'lucide-react';
|
||||
import { useCallback } from 'react';
|
||||
import { FieldValues } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
import { TypesWithArray } from '../constant';
|
||||
|
||||
export const useObjectFields = () => {
|
||||
const booleanRender = useCallback(
|
||||
(field: FieldValues, className?: string) => {
|
||||
const fieldValue = field.value ? true : false;
|
||||
return (
|
||||
<Segmented
|
||||
options={
|
||||
[
|
||||
{ value: true, label: 'True' },
|
||||
{ value: false, label: 'False' },
|
||||
] as any
|
||||
}
|
||||
sizeType="sm"
|
||||
value={fieldValue}
|
||||
onChange={field.onChange}
|
||||
className={className}
|
||||
itemClassName="justify-center flex-1"
|
||||
></Segmented>
|
||||
);
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const objectRender = useCallback((field: FieldValues) => {
|
||||
const fieldValue =
|
||||
typeof field.value === 'object'
|
||||
? JSON.stringify(field.value, null, 2)
|
||||
: JSON.stringify({}, null, 2);
|
||||
console.log('object-render-field', field, fieldValue);
|
||||
return (
|
||||
<Editor
|
||||
height={200}
|
||||
defaultLanguage="json"
|
||||
theme="vs-dark"
|
||||
value={fieldValue}
|
||||
onChange={field.onChange}
|
||||
/>
|
||||
);
|
||||
}, []);
|
||||
|
||||
const objectValidate = useCallback((value: any) => {
|
||||
try {
|
||||
if (!JSON.parse(value)) {
|
||||
throw new Error(t('knowledgeDetails.formatTypeError'));
|
||||
}
|
||||
return true;
|
||||
} catch (e) {
|
||||
throw new Error(t('knowledgeDetails.formatTypeError'));
|
||||
}
|
||||
}, []);
|
||||
|
||||
const arrayStringRender = useCallback((field: FieldValues, type = 'text') => {
|
||||
const values = Array.isArray(field.value)
|
||||
? field.value
|
||||
: [type === 'number' ? 0 : ''];
|
||||
return (
|
||||
<>
|
||||
{values?.map((item: any, index: number) => (
|
||||
<div key={index} className="flex gap-1 items-center">
|
||||
<Input
|
||||
type={type}
|
||||
value={item}
|
||||
onChange={(e) => {
|
||||
const newValues = [...values];
|
||||
newValues[index] = e.target.value;
|
||||
field.onChange(newValues);
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
variant={'secondary'}
|
||||
onClick={() => {
|
||||
const newValues = [...values];
|
||||
newValues.splice(index, 1);
|
||||
field.onChange(newValues);
|
||||
}}
|
||||
>
|
||||
<Trash2 />
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
<BlockButton
|
||||
type="button"
|
||||
onClick={() => {
|
||||
field.onChange([...field.value, '']);
|
||||
}}
|
||||
>
|
||||
{t('flow.add')}
|
||||
</BlockButton>
|
||||
</>
|
||||
);
|
||||
}, []);
|
||||
|
||||
const arrayBooleanRender = useCallback(
|
||||
(field: FieldValues) => {
|
||||
// const values = field.value || [false];
|
||||
const values = Array.isArray(field.value) ? field.value : [false];
|
||||
return (
|
||||
<div className="flex items-center gap-1 flex-wrap ">
|
||||
{values?.map((item: any, index: number) => (
|
||||
<div
|
||||
key={index}
|
||||
className="flex gap-1 items-center bg-bg-card rounded-lg border-[0.5px] border-border-button"
|
||||
>
|
||||
{booleanRender(
|
||||
{
|
||||
value: item,
|
||||
onChange: (value) => {
|
||||
values[index] = !!value;
|
||||
field.onChange(values);
|
||||
},
|
||||
},
|
||||
'bg-transparent',
|
||||
)}
|
||||
<Button
|
||||
variant={'transparent'}
|
||||
className="border-none py-0 px-1"
|
||||
onClick={() => {
|
||||
const newValues = [...values];
|
||||
newValues.splice(index, 1);
|
||||
field.onChange(newValues);
|
||||
}}
|
||||
>
|
||||
<X />
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
<BlockButton
|
||||
className="w-auto"
|
||||
type="button"
|
||||
onClick={() => {
|
||||
field.onChange([...field.value, false]);
|
||||
}}
|
||||
>
|
||||
{t('flow.add')}
|
||||
</BlockButton>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
[booleanRender],
|
||||
);
|
||||
|
||||
const arrayNumberRender = useCallback(
|
||||
(field: FieldValues) => {
|
||||
return arrayStringRender(field, 'number');
|
||||
},
|
||||
[arrayStringRender],
|
||||
);
|
||||
|
||||
const arrayValidate = useCallback((value: any, type: string = 'string') => {
|
||||
if (!Array.isArray(value) || !value.every((item) => typeof item === type)) {
|
||||
throw new Error(t('flow.formatTypeError'));
|
||||
}
|
||||
return true;
|
||||
}, []);
|
||||
|
||||
const arrayStringValidate = useCallback(
|
||||
(value: any) => {
|
||||
return arrayValidate(value, 'string');
|
||||
},
|
||||
[arrayValidate],
|
||||
);
|
||||
|
||||
const arrayNumberValidate = useCallback(
|
||||
(value: any) => {
|
||||
return arrayValidate(value, 'number');
|
||||
},
|
||||
[arrayValidate],
|
||||
);
|
||||
|
||||
const arrayBooleanValidate = useCallback(
|
||||
(value: any) => {
|
||||
return arrayValidate(value, 'boolean');
|
||||
},
|
||||
[arrayValidate],
|
||||
);
|
||||
|
||||
const handleRender = (value: TypesWithArray) => {
|
||||
switch (value) {
|
||||
case TypesWithArray.Boolean:
|
||||
return booleanRender;
|
||||
case TypesWithArray.Object:
|
||||
case TypesWithArray.ArrayObject:
|
||||
return objectRender;
|
||||
case TypesWithArray.ArrayString:
|
||||
return arrayStringRender;
|
||||
case TypesWithArray.ArrayNumber:
|
||||
return arrayNumberRender;
|
||||
case TypesWithArray.ArrayBoolean:
|
||||
return arrayBooleanRender;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
const handleCustomValidate = (value: TypesWithArray) => {
|
||||
switch (value) {
|
||||
case TypesWithArray.Object:
|
||||
case TypesWithArray.ArrayObject:
|
||||
return objectValidate;
|
||||
case TypesWithArray.ArrayString:
|
||||
return arrayStringValidate;
|
||||
case TypesWithArray.ArrayNumber:
|
||||
return arrayNumberValidate;
|
||||
case TypesWithArray.ArrayBoolean:
|
||||
return arrayBooleanValidate;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
const handleCustomSchema = (value: TypesWithArray) => {
|
||||
switch (value) {
|
||||
case TypesWithArray.ArrayString:
|
||||
return z.array(z.string());
|
||||
case TypesWithArray.ArrayNumber:
|
||||
return z.array(z.number());
|
||||
case TypesWithArray.ArrayBoolean:
|
||||
return z.array(z.boolean());
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
return {
|
||||
objectRender,
|
||||
objectValidate,
|
||||
arrayStringRender,
|
||||
arrayStringValidate,
|
||||
arrayNumberRender,
|
||||
booleanRender,
|
||||
arrayBooleanRender,
|
||||
arrayNumberValidate,
|
||||
arrayBooleanValidate,
|
||||
handleRender,
|
||||
handleCustomValidate,
|
||||
handleCustomSchema,
|
||||
};
|
||||
};
|
||||
@ -1,12 +1,6 @@
|
||||
import { ConfirmDeleteDialog } from '@/components/confirm-delete-dialog';
|
||||
import {
|
||||
DynamicForm,
|
||||
DynamicFormRef,
|
||||
FormFieldConfig,
|
||||
FormFieldType,
|
||||
} from '@/components/dynamic-form';
|
||||
import { FormFieldConfig } from '@/components/dynamic-form';
|
||||
import { BlockButton, Button } from '@/components/ui/button';
|
||||
import { Modal } from '@/components/ui/modal/modal';
|
||||
import {
|
||||
Sheet,
|
||||
SheetContent,
|
||||
@ -19,117 +13,65 @@ import { GlobalVariableType } from '@/interfaces/database/agent';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { t } from 'i18next';
|
||||
import { Trash2 } from 'lucide-react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { FieldValues } from 'react-hook-form';
|
||||
import { useSaveGraph } from '../hooks/use-save-graph';
|
||||
import { AddVariableModal } from './component/add-variable-modal';
|
||||
import {
|
||||
GobalFormFields,
|
||||
GobalVariableFormDefaultValues,
|
||||
GlobalFormFields,
|
||||
GlobalVariableFormDefaultValues,
|
||||
TypeMaps,
|
||||
TypesWithArray,
|
||||
} from './contant';
|
||||
} from './constant';
|
||||
import { useObjectFields } from './hooks/use-object-fields';
|
||||
|
||||
export type IGobalParamModalProps = {
|
||||
export type IGlobalParamModalProps = {
|
||||
data: any;
|
||||
hideModal: (open: boolean) => void;
|
||||
};
|
||||
export const GobalParamSheet = (props: IGobalParamModalProps) => {
|
||||
export const GlobalParamSheet = (props: IGlobalParamModalProps) => {
|
||||
const { hideModal } = props;
|
||||
const { data, refetch } = useFetchAgent();
|
||||
const [fields, setFields] = useState<FormFieldConfig[]>(GobalFormFields);
|
||||
const { visible, showModal, hideModal: hideAddModal } = useSetModalState();
|
||||
const [fields, setFields] = useState<FormFieldConfig[]>(GlobalFormFields);
|
||||
const [defaultValues, setDefaultValues] = useState<FieldValues>(
|
||||
GobalVariableFormDefaultValues,
|
||||
GlobalVariableFormDefaultValues,
|
||||
);
|
||||
const formRef = useRef<DynamicFormRef>(null);
|
||||
const { handleCustomValidate, handleCustomSchema, handleRender } =
|
||||
useObjectFields();
|
||||
const { saveGraph } = useSaveGraph();
|
||||
|
||||
const handleFieldUpdate = (
|
||||
fieldName: string,
|
||||
updatedField: Partial<FormFieldConfig>,
|
||||
) => {
|
||||
setFields((prevFields) =>
|
||||
prevFields.map((field) =>
|
||||
field.name === fieldName ? { ...field, ...updatedField } : field,
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const typefileld = fields.find((item) => item.name === 'type');
|
||||
|
||||
if (typefileld) {
|
||||
typefileld.onChange = (value) => {
|
||||
// setWatchType(value);
|
||||
handleFieldUpdate('value', {
|
||||
type: TypeMaps[value as keyof typeof TypeMaps],
|
||||
});
|
||||
const values = formRef.current?.getValues();
|
||||
setTimeout(() => {
|
||||
switch (value) {
|
||||
case TypesWithArray.Boolean:
|
||||
setDefaultValues({ ...values, value: false });
|
||||
break;
|
||||
case TypesWithArray.Number:
|
||||
setDefaultValues({ ...values, value: 0 });
|
||||
break;
|
||||
default:
|
||||
setDefaultValues({ ...values, value: '' });
|
||||
}
|
||||
}, 0);
|
||||
};
|
||||
}
|
||||
}, [fields]);
|
||||
|
||||
const { saveGraph, loading } = useSaveGraph();
|
||||
|
||||
const handleSubmit = async (value: FieldValues) => {
|
||||
const param = {
|
||||
...(data.dsl?.variables || {}),
|
||||
[value.name]: value,
|
||||
} as Record<string, GlobalVariableType>;
|
||||
|
||||
const res = await saveGraph(undefined, {
|
||||
gobalVariables: param,
|
||||
});
|
||||
|
||||
if (res.code === 0) {
|
||||
refetch();
|
||||
}
|
||||
hideAddModal();
|
||||
};
|
||||
|
||||
const handleDeleteGobalVariable = async (key: string) => {
|
||||
const handleDeleteGlobalVariable = async (key: string) => {
|
||||
const param = {
|
||||
...(data.dsl?.variables || {}),
|
||||
} as Record<string, GlobalVariableType>;
|
||||
delete param[key];
|
||||
const res = await saveGraph(undefined, {
|
||||
gobalVariables: param,
|
||||
globalVariables: param,
|
||||
});
|
||||
console.log('delete gobal variable-->', res);
|
||||
if (res.code === 0) {
|
||||
refetch();
|
||||
}
|
||||
};
|
||||
|
||||
const handleEditGobalVariable = (item: FieldValues) => {
|
||||
fields.forEach((field) => {
|
||||
if (field.name === 'value') {
|
||||
switch (item.type) {
|
||||
// [TypesWithArray.String]: FormFieldType.Textarea,
|
||||
// [TypesWithArray.Number]: FormFieldType.Number,
|
||||
// [TypesWithArray.Boolean]: FormFieldType.Checkbox,
|
||||
case TypesWithArray.Boolean:
|
||||
field.type = FormFieldType.Checkbox;
|
||||
break;
|
||||
case TypesWithArray.Number:
|
||||
field.type = FormFieldType.Number;
|
||||
break;
|
||||
default:
|
||||
field.type = FormFieldType.Textarea;
|
||||
}
|
||||
const handleEditGlobalVariable = (item: FieldValues) => {
|
||||
const newFields = fields.map((field) => {
|
||||
let newField = field;
|
||||
newField.render = undefined;
|
||||
newField.schema = undefined;
|
||||
newField.customValidate = undefined;
|
||||
if (newField.name === 'value') {
|
||||
newField = {
|
||||
...newField,
|
||||
type: TypeMaps[item.type as keyof typeof TypeMaps],
|
||||
render: handleRender(item.type),
|
||||
customValidate: handleCustomValidate(item.type),
|
||||
schema: handleCustomSchema(item.type),
|
||||
};
|
||||
}
|
||||
return newField;
|
||||
});
|
||||
setFields(newFields);
|
||||
setDefaultValues(item);
|
||||
showModal();
|
||||
};
|
||||
@ -149,8 +91,8 @@ export const GobalParamSheet = (props: IGobalParamModalProps) => {
|
||||
<div className="px-5 pb-5">
|
||||
<BlockButton
|
||||
onClick={() => {
|
||||
setFields(GobalFormFields);
|
||||
setDefaultValues(GobalVariableFormDefaultValues);
|
||||
setFields(GlobalFormFields);
|
||||
setDefaultValues(GlobalVariableFormDefaultValues);
|
||||
showModal();
|
||||
}}
|
||||
>
|
||||
@ -167,7 +109,7 @@ export const GobalParamSheet = (props: IGobalParamModalProps) => {
|
||||
key={key}
|
||||
className="flex items-center gap-3 min-h-14 justify-between px-5 py-3 border border-border-default rounded-lg hover:bg-bg-card group"
|
||||
onClick={() => {
|
||||
handleEditGobalVariable(item);
|
||||
handleEditGlobalVariable(item);
|
||||
}}
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
@ -177,13 +119,23 @@ export const GobalParamSheet = (props: IGobalParamModalProps) => {
|
||||
{item.type}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-text-primary">{item.value}</span>
|
||||
</div>
|
||||
{![
|
||||
TypesWithArray.Object,
|
||||
TypesWithArray.ArrayObject,
|
||||
TypesWithArray.ArrayString,
|
||||
TypesWithArray.ArrayNumber,
|
||||
TypesWithArray.ArrayBoolean,
|
||||
].includes(item.type as TypesWithArray) && (
|
||||
<div>
|
||||
<span className="text-text-primary">
|
||||
{item.value}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<ConfirmDeleteDialog
|
||||
onOk={() => handleDeleteGobalVariable(key)}
|
||||
onOk={() => handleDeleteGlobalVariable(key)}
|
||||
>
|
||||
<Button
|
||||
variant={'secondary'}
|
||||
@ -201,40 +153,14 @@ export const GobalParamSheet = (props: IGobalParamModalProps) => {
|
||||
})}
|
||||
</div>
|
||||
</SheetContent>
|
||||
<Modal
|
||||
title={t('flow.add') + t('flow.conversationVariable')}
|
||||
open={visible}
|
||||
onCancel={hideAddModal}
|
||||
showfooter={false}
|
||||
>
|
||||
<DynamicForm.Root
|
||||
ref={formRef}
|
||||
fields={fields}
|
||||
onSubmit={(data) => {
|
||||
console.log(data);
|
||||
}}
|
||||
defaultValues={defaultValues}
|
||||
onFieldUpdate={handleFieldUpdate}
|
||||
>
|
||||
<div className="flex items-center justify-end w-full gap-2">
|
||||
<DynamicForm.CancelButton
|
||||
handleCancel={() => {
|
||||
hideAddModal?.();
|
||||
}}
|
||||
/>
|
||||
<DynamicForm.SavingButton
|
||||
submitLoading={loading || false}
|
||||
buttonText={t('common.ok')}
|
||||
submitFunc={(values: FieldValues) => {
|
||||
handleSubmit(values);
|
||||
// console.log(values);
|
||||
// console.log(nodes, edges);
|
||||
// handleOk(values);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</DynamicForm.Root>
|
||||
</Modal>
|
||||
<AddVariableModal
|
||||
visible={visible}
|
||||
hideModal={hideAddModal}
|
||||
fields={fields}
|
||||
setFields={setFields}
|
||||
defaultValues={defaultValues}
|
||||
setDefaultValues={setDefaultValues}
|
||||
/>
|
||||
</Sheet>
|
||||
</>
|
||||
);
|
||||
|
||||
@ -4,7 +4,7 @@ import { RAGFlowNodeType } from '@/interfaces/database/flow';
|
||||
import { useCallback } from 'react';
|
||||
import { Operator } from '../constant';
|
||||
import useGraphStore from '../store';
|
||||
import { buildDslComponentsByGraph, buildDslGobalVariables } from '../utils';
|
||||
import { buildDslComponentsByGraph, buildDslGlobalVariables } from '../utils';
|
||||
|
||||
export const useBuildDslData = () => {
|
||||
const { data } = useFetchAgent();
|
||||
@ -13,7 +13,7 @@ export const useBuildDslData = () => {
|
||||
const buildDslData = useCallback(
|
||||
(
|
||||
currentNodes?: RAGFlowNodeType[],
|
||||
otherParam?: { gobalVariables: Record<string, GlobalVariableType> },
|
||||
otherParam?: { globalVariables: Record<string, GlobalVariableType> },
|
||||
) => {
|
||||
const nodesToProcess = currentNodes ?? nodes;
|
||||
|
||||
@ -41,13 +41,13 @@ export const useBuildDslData = () => {
|
||||
data.dsl.components,
|
||||
);
|
||||
|
||||
const gobalVariables = buildDslGobalVariables(
|
||||
const globalVariables = buildDslGlobalVariables(
|
||||
data.dsl,
|
||||
otherParam?.gobalVariables,
|
||||
otherParam?.globalVariables,
|
||||
);
|
||||
return {
|
||||
...data.dsl,
|
||||
...gobalVariables,
|
||||
...globalVariables,
|
||||
graph: { nodes: filteredNodes, edges: filteredEdges },
|
||||
components: dslComponents,
|
||||
};
|
||||
|
||||
@ -21,7 +21,7 @@ export const useSaveGraph = (showMessage: boolean = true) => {
|
||||
const saveGraph = useCallback(
|
||||
async (
|
||||
currentNodes?: RAGFlowNodeType[],
|
||||
otherParam?: { gobalVariables: Record<string, GlobalVariableType> },
|
||||
otherParam?: { globalVariables: Record<string, GlobalVariableType> },
|
||||
) => {
|
||||
return setAgent({
|
||||
id,
|
||||
|
||||
@ -39,7 +39,7 @@ import { useParams } from 'umi';
|
||||
import AgentCanvas from './canvas';
|
||||
import { DropdownProvider } from './canvas/context';
|
||||
import { Operator } from './constant';
|
||||
import { GobalParamSheet } from './gobal-variable-sheet';
|
||||
import { GlobalParamSheet } from './gobal-variable-sheet';
|
||||
import { useCancelCurrentDataflow } from './hooks/use-cancel-dataflow';
|
||||
import { useHandleExportJsonFile } from './hooks/use-export-json';
|
||||
import { useFetchDataOnMount } from './hooks/use-fetch-data';
|
||||
@ -126,9 +126,9 @@ export default function Agent() {
|
||||
} = useSetModalState();
|
||||
|
||||
const {
|
||||
visible: gobalParamSheetVisible,
|
||||
showModal: showGobalParamSheet,
|
||||
hideModal: hideGobalParamSheet,
|
||||
visible: globalParamSheetVisible,
|
||||
showModal: showGlobalParamSheet,
|
||||
hideModal: hideGlobalParamSheet,
|
||||
} = useSetModalState();
|
||||
|
||||
const {
|
||||
@ -216,7 +216,7 @@ export default function Agent() {
|
||||
</ButtonLoading>
|
||||
<ButtonLoading
|
||||
variant={'secondary'}
|
||||
onClick={() => showGobalParamSheet()}
|
||||
onClick={() => showGlobalParamSheet()}
|
||||
loading={loading}
|
||||
>
|
||||
<MessageSquareCode /> {t('flow.conversationVariable')}
|
||||
@ -314,11 +314,11 @@ export default function Agent() {
|
||||
loading={pipelineRunning}
|
||||
></PipelineRunSheet>
|
||||
)}
|
||||
{gobalParamSheetVisible && (
|
||||
<GobalParamSheet
|
||||
{globalParamSheetVisible && (
|
||||
<GlobalParamSheet
|
||||
data={{}}
|
||||
hideModal={hideGobalParamSheet}
|
||||
></GobalParamSheet>
|
||||
hideModal={hideGlobalParamSheet}
|
||||
></GlobalParamSheet>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
|
||||
@ -348,30 +348,30 @@ export const buildDslComponentsByGraph = (
|
||||
return components;
|
||||
};
|
||||
|
||||
export const buildDslGobalVariables = (
|
||||
export const buildDslGlobalVariables = (
|
||||
dsl: DSL,
|
||||
gobalVariables?: Record<string, GlobalVariableType>,
|
||||
globalVariables?: Record<string, GlobalVariableType>,
|
||||
) => {
|
||||
if (!gobalVariables) {
|
||||
if (!globalVariables) {
|
||||
return { globals: dsl.globals, variables: dsl.variables || {} };
|
||||
}
|
||||
|
||||
let gobalVariablesTemp: Record<string, any> = {};
|
||||
let gobalSystem: Record<string, any> = {};
|
||||
let globalVariablesTemp: Record<string, any> = {};
|
||||
let globalSystem: Record<string, any> = {};
|
||||
Object.keys(dsl.globals)?.forEach((key) => {
|
||||
if (key.indexOf('sys') > -1) {
|
||||
gobalSystem[key] = dsl.globals[key];
|
||||
globalSystem[key] = dsl.globals[key];
|
||||
}
|
||||
});
|
||||
Object.keys(gobalVariables).forEach((key) => {
|
||||
gobalVariablesTemp['env.' + key] = gobalVariables[key].value;
|
||||
Object.keys(globalVariables).forEach((key) => {
|
||||
globalVariablesTemp['env.' + key] = globalVariables[key].value;
|
||||
});
|
||||
|
||||
const gobalVariablesResult = {
|
||||
...gobalSystem,
|
||||
...gobalVariablesTemp,
|
||||
const globalVariablesResult = {
|
||||
...globalSystem,
|
||||
...globalVariablesTemp,
|
||||
};
|
||||
return { globals: gobalVariablesResult, variables: gobalVariables };
|
||||
return { globals: globalVariablesResult, variables: globalVariables };
|
||||
};
|
||||
|
||||
export const receiveMessageError = (res: any) =>
|
||||
|
||||
@ -7,11 +7,14 @@ import {
|
||||
FormMessage,
|
||||
} from '@/components/ui/form';
|
||||
import { Radio } from '@/components/ui/radio';
|
||||
import { Spin } from '@/components/ui/spin';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import { useTranslate } from '@/hooks/common-hooks';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useFormContext } from 'react-hook-form';
|
||||
import {
|
||||
useHandleKbEmbedding,
|
||||
useHasParsedDocument,
|
||||
useSelectChunkMethodList,
|
||||
useSelectEmbeddingModelOptions,
|
||||
@ -62,11 +65,17 @@ export function ChunkMethodItem(props: IProps) {
|
||||
/>
|
||||
);
|
||||
}
|
||||
export function EmbeddingModelItem({ line = 1, isEdit = true }: IProps) {
|
||||
export function EmbeddingModelItem({ line = 1, isEdit }: IProps) {
|
||||
const { t } = useTranslate('knowledgeConfiguration');
|
||||
const form = useFormContext();
|
||||
const embeddingModelOptions = useSelectEmbeddingModelOptions();
|
||||
const { handleChange } = useHandleKbEmbedding();
|
||||
const disabled = useHasParsedDocument(isEdit);
|
||||
const oldValue = useMemo(() => {
|
||||
const embdStr = form.getValues('embd_id');
|
||||
return embdStr || '';
|
||||
}, [form]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
return (
|
||||
<>
|
||||
<FormField
|
||||
@ -93,14 +102,33 @@ export function EmbeddingModelItem({ line = 1, isEdit = true }: IProps) {
|
||||
className={cn('text-muted-foreground', { 'w-3/4': line === 1 })}
|
||||
>
|
||||
<FormControl>
|
||||
<SelectWithSearch
|
||||
onChange={field.onChange}
|
||||
value={field.value}
|
||||
options={embeddingModelOptions}
|
||||
disabled={isEdit ? disabled : false}
|
||||
placeholder={t('embeddingModelPlaceholder')}
|
||||
triggerClassName="!bg-bg-base"
|
||||
/>
|
||||
<Spin
|
||||
spinning={loading}
|
||||
className={cn(' rounded-lg after:bg-bg-base', {
|
||||
'opacity-20': loading,
|
||||
})}
|
||||
>
|
||||
<SelectWithSearch
|
||||
onChange={async (value) => {
|
||||
field.onChange(value);
|
||||
if (isEdit && disabled) {
|
||||
setLoading(true);
|
||||
const res = await handleChange({
|
||||
embed_id: value,
|
||||
callback: field.onChange,
|
||||
});
|
||||
if (res.code !== 0) {
|
||||
field.onChange(oldValue);
|
||||
}
|
||||
setLoading(false);
|
||||
}
|
||||
}}
|
||||
value={field.value}
|
||||
options={embeddingModelOptions}
|
||||
placeholder={t('embeddingModelPlaceholder')}
|
||||
triggerClassName="!bg-bg-base"
|
||||
/>
|
||||
</Spin>
|
||||
</FormControl>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -88,7 +88,7 @@ export function GeneralForm() {
|
||||
}}
|
||||
/>
|
||||
<PermissionFormField></PermissionFormField>
|
||||
<EmbeddingModelItem></EmbeddingModelItem>
|
||||
<EmbeddingModelItem isEdit={true}></EmbeddingModelItem>
|
||||
<PageRankFormField></PageRankFormField>
|
||||
|
||||
<TagItems></TagItems>
|
||||
|
||||
@ -4,10 +4,12 @@ import { useSetModalState } from '@/hooks/common-hooks';
|
||||
import { useSelectLlmOptionsByModelType } from '@/hooks/llm-hooks';
|
||||
import { useFetchKnowledgeBaseConfiguration } from '@/hooks/use-knowledge-request';
|
||||
import { useSelectParserList } from '@/hooks/user-setting-hooks';
|
||||
import kbService from '@/services/knowledge-service';
|
||||
import { useIsFetching } from '@tanstack/react-query';
|
||||
import { pick } from 'lodash';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { UseFormReturn } from 'react-hook-form';
|
||||
import { useParams, useSearchParams } from 'umi';
|
||||
import { z } from 'zod';
|
||||
import { formSchema } from './form-schema';
|
||||
|
||||
@ -98,3 +100,22 @@ export const useRenameKnowledgeTag = () => {
|
||||
showTagRenameModal: handleShowTagRenameModal,
|
||||
};
|
||||
};
|
||||
|
||||
export const useHandleKbEmbedding = () => {
|
||||
const { id } = useParams();
|
||||
const [searchParams] = useSearchParams();
|
||||
const knowledgeBaseId = searchParams.get('id') || id;
|
||||
const handleChange = useCallback(
|
||||
async ({ embed_id }: { embed_id: string }) => {
|
||||
const res = await kbService.checkEmbedding({
|
||||
kb_id: knowledgeBaseId,
|
||||
embd_id: embed_id,
|
||||
});
|
||||
return res.data;
|
||||
},
|
||||
[knowledgeBaseId],
|
||||
);
|
||||
return {
|
||||
handleChange,
|
||||
};
|
||||
};
|
||||
|
||||
@ -47,6 +47,7 @@ const {
|
||||
traceGraphRag,
|
||||
runRaptor,
|
||||
traceRaptor,
|
||||
check_embedding,
|
||||
} = api;
|
||||
|
||||
const methods = {
|
||||
@ -214,6 +215,11 @@ const methods = {
|
||||
url: api.pipelineRerun,
|
||||
method: 'post',
|
||||
},
|
||||
|
||||
checkEmbedding: {
|
||||
url: check_embedding,
|
||||
method: 'post',
|
||||
},
|
||||
};
|
||||
|
||||
const kbService = registerServer<keyof typeof methods>(methods, request);
|
||||
|
||||
@ -49,6 +49,8 @@ export default {
|
||||
llm_tools: `${api_host}/plugin/llm_tools`,
|
||||
|
||||
// knowledge base
|
||||
|
||||
check_embedding: `${api_host}/kb/check_embedding`,
|
||||
kb_list: `${api_host}/kb/list`,
|
||||
create_kb: `${api_host}/kb/create`,
|
||||
update_kb: `${api_host}/kb/update`,
|
||||
|
||||
Reference in New Issue
Block a user