Feat: Add memory multi-select dropdown to recall and message operator forms. #4213 (#12106)

### What problem does this PR solve?

Feat: Add memory multi-select dropdown to recall and message operator
forms. #4213

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu
2025-12-23 11:54:32 +08:00
committed by GitHub
parent 712d537d66
commit 9e31631d8f
10 changed files with 95 additions and 13 deletions

View File

@ -0,0 +1,33 @@
import { useFetchAllMemoryList } from '@/hooks/use-memory-request';
import { useTranslation } from 'react-i18next';
import { RAGFlowFormItem } from './ragflow-form';
import { MultiSelect } from './ui/multi-select';
type MemoriesFormFieldProps = {
label: string;
};
export function MemoriesFormField({ label }: MemoriesFormFieldProps) {
const { t } = useTranslation();
const memoryList = useFetchAllMemoryList();
const options = memoryList.data?.map((memory) => ({
label: memory.name,
value: memory.id,
}));
return (
<RAGFlowFormItem name="memory_ids" label={label}>
{(field) => (
<MultiSelect
options={options || []}
placeholder={t('common.pleaseSelect')}
maxCount={100}
onValueChange={field.onChange}
defaultValue={field.value}
modalPopover
/>
)}
</RAGFlowFormItem>
);
}

View File

@ -0,0 +1,30 @@
import { IMemory } from '@/interfaces/database/memory';
import memoryService from '@/services/memory-service';
import { useQuery } from '@tanstack/react-query';
export const enum MemoryApiAction {
FetchMemoryList = 'fetchMemoryList',
}
export const useFetchAllMemoryList = () => {
const { data, isLoading, isError, refetch } = useQuery<IMemory[], Error>({
queryKey: [MemoryApiAction.FetchMemoryList],
queryFn: async () => {
const { data: response } = await memoryService.getMemoryList(
{
params: { page_size: 100000000, page: 1 },
data: {},
},
true,
);
return response.data.memory_list ?? [];
},
});
return {
data,
isLoading,
isError,
refetch,
};
};

View File

@ -0,0 +1,11 @@
export interface IMemory {
avatar: null;
description: null;
id: string;
memory_type: string[];
name: string;
owner_name: string;
permissions: string;
storage_type: string;
tenant_id: string;
}

View File

@ -2128,6 +2128,8 @@ Important structured information may include: names, dates, locations, events, k
immediately: 'Accepted response',
streaming: 'Final response',
},
saveToMemory: 'Save to memory',
memory: 'Memory',
},
llmTools: {
bad_calculator: {

View File

@ -1940,6 +1940,8 @@ Tokenizer 会根据所选方式将内容存储为对应的数据结构。`,
headerParameters: '请求头参数',
requestBodyParameters: '请求体参数',
},
saveToMemory: '保存到Memory',
memory: 'Memory',
},
footer: {
profile: 'All rights reserved @ React',

View File

@ -1,3 +1,4 @@
import { MemoriesFormField } from '@/components/memories-form-field';
import { BlockButton, Button } from '@/components/ui/button';
import {
Form,
@ -40,6 +41,7 @@ function MessageForm({ node }: INextOperatorForm) {
output_format: z.string().optional(),
auto_play: z.boolean().optional(),
status: z.number().optional(),
memory_ids: z.array(z.string()).optional(),
});
const form = useForm({
@ -159,6 +161,7 @@ function MessageForm({ node }: INextOperatorForm) {
</FormItem>
</>
)}
<MemoriesFormField label={t('flow.saveToMemory')}></MemoriesFormField>
</FormWrapper>
</Form>
);

View File

@ -18,13 +18,13 @@ export function useShowWebhookResponseStatus(form: UseFormReturn<any>) {
formData?.mode === AgentDialogueMode.Webhook &&
formData.execution_mode === WebhookExecutionMode.Streaming
);
}, []);
}, [getNode]);
useEffect(() => {
if (showWebhookResponseStatus && isEmpty(form.getValues('status'))) {
form.setValue('status', 200, { shouldValidate: true, shouldDirty: true });
}
}, []);
}, [form, showWebhookResponseStatus]);
return showWebhookResponseStatus;
}

View File

@ -2,6 +2,7 @@ import { Collapse } from '@/components/collapse';
import { CrossLanguageFormField } from '@/components/cross-language-form-field';
import { FormContainer } from '@/components/form-container';
import { KnowledgeBaseFormField } from '@/components/knowledge-base-item';
import { MemoriesFormField } from '@/components/memories-form-field';
import {
MetadataFilter,
MetadataFilterSchema,
@ -46,6 +47,7 @@ export const RetrievalPartialSchema = {
use_kg: z.boolean(),
toc_enhance: z.boolean(),
...MetadataFilterSchema,
memory_ids: z.array(z.string()).optional(),
};
export const FormSchema = z.object({
@ -109,12 +111,11 @@ function RetrievalForm({ node }: INextOperatorForm) {
return (
<Form {...form}>
<FormWrapper>
<FormContainer>
<RAGFlowFormItem name="query" label={t('flow.query')}>
<PromptEditor></PromptEditor>
</RAGFlowFormItem>
<KnowledgeBaseFormField showVariable></KnowledgeBaseFormField>
</FormContainer>
<RAGFlowFormItem name="query" label={t('flow.query')}>
<PromptEditor></PromptEditor>
</RAGFlowFormItem>
<KnowledgeBaseFormField showVariable></KnowledgeBaseFormField>
<MemoriesFormField label={t('flow.memory')}></MemoriesFormField>
<Collapse title={<div>{t('flow.advancedSettings')}</div>}>
<FormContainer>
<SimilaritySliderFormField

View File

@ -2,6 +2,7 @@ import { Collapse } from '@/components/collapse';
import { CrossLanguageFormField } from '@/components/cross-language-form-field';
import { FormContainer } from '@/components/form-container';
import { KnowledgeBaseFormField } from '@/components/knowledge-base-item';
import { MemoriesFormField } from '@/components/memories-form-field';
import { MetadataFilter } from '@/components/metadata-filter';
import { RerankFormFields } from '@/components/rerank';
import { SimilaritySliderFormField } from '@/components/similarity-slider';
@ -40,10 +41,9 @@ const RetrievalForm = () => {
return (
<Form {...form}>
<FormWrapper>
<FormContainer>
<DescriptionField></DescriptionField>
<KnowledgeBaseFormField showVariable></KnowledgeBaseFormField>
</FormContainer>
<DescriptionField></DescriptionField>
<KnowledgeBaseFormField showVariable></KnowledgeBaseFormField>
<MemoriesFormField label={t('flow.memory')}></MemoriesFormField>
<Collapse title={<div>{t('flow.advancedSettings')}</div>}>
<FormContainer>
<SimilaritySliderFormField

View File

@ -1,6 +1,6 @@
import api from '@/utils/api';
import request from '@/utils/next-request';
import { registerNextServer } from '@/utils/register-server';
import request from '@/utils/request';
const {
createMemory,