Feature: Memory interface integration testing (#11833)

### What problem does this PR solve?

Feature: Memory interface integration testing

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
chanx
2025-12-09 14:52:58 +08:00
committed by GitHub
parent c51e6b2a58
commit 28bc87c5e2
32 changed files with 1168 additions and 501 deletions

View File

@ -3,7 +3,7 @@ import { useModelOptions } from '@/components/llm-setting-items/llm-form-field';
import { HomeIcon } from '@/components/svg-icon';
import { Modal } from '@/components/ui/modal/modal';
import { t } from 'i18next';
import { useCallback, useEffect, useState } from 'react';
import { memo, useCallback, useMemo, useState } from 'react';
import { createMemoryFields } from './constants';
import { IMemory } from './interface';
@ -13,11 +13,10 @@ type IProps = {
onSubmit?: (data: any) => void;
initialMemory: IMemory;
loading?: boolean;
isCreate?: boolean;
};
export const AddOrEditModal = (props: IProps) => {
const { open, onClose, onSubmit, initialMemory } = props;
// const [fields, setFields] = useState<FormFieldConfig[]>(createMemoryFields);
// const formRef = useRef<DynamicFormRef>(null);
export const AddOrEditModal = memo((props: IProps) => {
const { open, onClose, onSubmit, initialMemory, isCreate } = props;
const [formInstance, setFormInstance] = useState<DynamicFormRef | null>(null);
const formCallbackRef = useCallback((node: DynamicFormRef | null) => {
@ -28,15 +27,25 @@ export const AddOrEditModal = (props: IProps) => {
}, []);
const { modelOptions } = useModelOptions();
useEffect(() => {
if (initialMemory && initialMemory.id) {
formInstance?.onFieldUpdate('memory_type', { hidden: true });
formInstance?.onFieldUpdate('embedding', { hidden: true });
formInstance?.onFieldUpdate('llm', { hidden: true });
const fields = useMemo(() => {
if (!isCreate) {
return createMemoryFields.filter((field: any) => field.name === 'name');
} else {
formInstance?.onFieldUpdate('llm', { options: modelOptions as any });
const tempFields = createMemoryFields.map((field: any) => {
if (field.name === 'llm_id') {
return {
...field,
options: modelOptions,
};
} else {
return {
...field,
};
}
});
return tempFields;
}
}, [modelOptions, formInstance, initialMemory]);
}, [modelOptions, isCreate]);
return (
<Modal
@ -48,7 +57,7 @@ export const AddOrEditModal = (props: IProps) => {
<div>
<HomeIcon name="memory" width={'24'} />
</div>
{t('memory.createMemory')}
{t('memories.createMemory')}
</div>
}
showfooter={false}
@ -56,7 +65,7 @@ export const AddOrEditModal = (props: IProps) => {
>
<DynamicForm.Root
ref={formCallbackRef}
fields={createMemoryFields}
fields={fields}
onSubmit={() => {}}
defaultValues={initialMemory}
>
@ -72,4 +81,4 @@ export const AddOrEditModal = (props: IProps) => {
</DynamicForm.Root>
</Modal>
);
};
});

View File

@ -4,16 +4,16 @@ import { t } from 'i18next';
export const createMemoryFields = [
{
name: 'memory_name',
label: t('memory.name'),
placeholder: t('memory.memoryNamePlaceholder'),
name: 'name',
label: t('memories.name'),
placeholder: t('memories.memoryNamePlaceholder'),
required: true,
},
{
name: 'memory_type',
label: t('memory.memoryType'),
label: t('memories.memoryType'),
type: FormFieldType.MultiSelect,
placeholder: t('memory.descriptionPlaceholder'),
placeholder: t('memories.descriptionPlaceholder'),
options: [
{ label: 'Raw', value: 'raw' },
{ label: 'Semantic', value: 'semantic' },
@ -23,18 +23,18 @@ export const createMemoryFields = [
required: true,
},
{
name: 'embedding',
label: t('memory.embeddingModel'),
placeholder: t('memory.selectModel'),
name: 'embd_id',
label: t('memories.embeddingModel'),
placeholder: t('memories.selectModel'),
required: true,
// hideLabel: true,
// type: 'custom',
render: (field) => <EmbeddingSelect field={field} isEdit={false} />,
},
{
name: 'llm',
label: t('memory.llm'),
placeholder: t('memory.selectModel'),
name: 'llm_id',
label: t('memories.llm'),
placeholder: t('memories.selectModel'),
required: true,
type: FormFieldType.Select,
},

View File

@ -7,6 +7,7 @@ import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
import memoryService, { updateMemoryById } from '@/services/memory-service';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useDebounce } from 'ahooks';
import { omit } from 'lodash';
import { useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useParams, useSearchParams } from 'umi';
@ -73,12 +74,12 @@ export const useFetchMemoryList = () => {
queryFn: async () => {
const { data: response } = await memoryService.getMemoryList(
{
params: {
data: {
keywords: debouncedSearchString,
page_size: pagination.pageSize,
page: pagination.current,
},
data: {},
params: {},
},
true,
);
@ -153,7 +154,9 @@ export const useDeleteMemory = () => {
} = useMutation<DeleteMemoryResponse, Error, DeleteMemoryProps>({
mutationKey: ['deleteMemory'],
mutationFn: async (props) => {
const { data: response } = await memoryService.deleteMemory(props);
const { data: response } = await memoryService.deleteMemory(
props.memory_id,
);
if (response.code !== 0) {
throw new Error(response.message || 'Failed to delete memory');
}
@ -189,7 +192,8 @@ export const useUpdateMemory = () => {
} = useMutation<any, Error, IMemoryAppDetailProps>({
mutationKey: ['updateMemory'],
mutationFn: async (formData) => {
const { data: response } = await updateMemoryById(formData.id, formData);
const param = omit(formData, ['id']);
const { data: response } = await updateMemoryById(formData.id, param);
if (response.code !== 0) {
throw new Error(response.message || 'Failed to update memory');
}
@ -259,7 +263,7 @@ export const useRenameMemory = () => {
// const { id, created_by, update_time, ...memoryDataTemp } = detail;
res = await updateMemory({
// ...memoryDataTemp,
name: data.memory_name,
name: data.name,
id: memory?.id,
} as unknown as IMemoryAppDetailProps);
} catch (e) {
@ -268,9 +272,9 @@ export const useRenameMemory = () => {
} else {
res = await createMemory(data);
}
if (res && !memory?.id) {
navigateToMemory(res?.id)();
}
// if (res && !memory?.id) {
// navigateToMemory(res?.id)();
// }
callBack?.();
setLoading(false);
handleHideModal();

View File

@ -7,7 +7,7 @@ import { RAGFlowPagination } from '@/components/ui/ragflow-pagination';
import { useTranslate } from '@/hooks/common-hooks';
import { pick } from 'lodash';
import { Plus } from 'lucide-react';
import { useCallback, useEffect } from 'react';
import { useCallback, useEffect, useState } from 'react';
import { useSearchParams } from 'umi';
import { AddOrEditModal } from './add-or-edit-modal';
import { useFetchMemoryList, useRenameMemory } from './hooks';
@ -16,7 +16,8 @@ import { MemoryCard } from './memory-card';
export default function MemoryList() {
// const { data } = useFetchFlowList();
const { t } = useTranslate('memory');
const { t } = useTranslate('memories');
const [addOrEditType, setAddOrEditType] = useState<'add' | 'edit'>('add');
// const [isEdit, setIsEdit] = useState(false);
const {
data: list,
@ -43,6 +44,7 @@ export default function MemoryList() {
};
const openCreateModalFun = useCallback(() => {
// setIsEdit(false);
setAddOrEditType('add');
showMemoryRenameModal();
}, [showMemoryRenameModal]);
const handlePageChange = useCallback(
@ -121,6 +123,7 @@ export default function MemoryList() {
key={x.id}
data={x}
showMemoryRenameModal={() => {
setAddOrEditType('edit');
showMemoryRenameModal(x);
}}
></MemoryCard>
@ -152,6 +155,7 @@ export default function MemoryList() {
{openCreateModal && (
<AddOrEditModal
initialMemory={initialMemory}
isCreate={addOrEditType === 'add'}
open={openCreateModal}
loading={searchRenameLoading}
onClose={hideMemoryModal}

View File

@ -1,10 +1,3 @@
export interface ICreateMemoryProps {
memory_name: string;
memory_type: Array<string>;
embedding: string;
llm: string;
}
export interface CreateMemoryResponse {
id: string;
name: string;
@ -24,17 +17,18 @@ export type MemoryType = 'raw' | 'semantic' | 'episodic' | 'procedural';
export type StorageType = 'table' | 'graph';
export type Permissions = 'me' | 'team';
export type ForgettingPolicy = 'fifo' | 'lru';
export interface IMemory {
id: string;
export interface ICreateMemoryProps {
name: string;
memory_type: MemoryType[];
embd_id: string;
llm_id: string;
}
export interface IMemory extends ICreateMemoryProps {
id: string;
avatar: string;
tenant_id: string;
owner_name: string;
memory_type: MemoryType[];
storage_type: StorageType;
embedding: string;
llm: string;
permissions: Permissions;
description: string;
memory_size: number;

View File

@ -20,7 +20,7 @@ export function MemoryCard({ data, showMemoryRenameModal }: IProps) {
}}
moreDropdown={
<MemoryDropdown
dataset={data}
memory={data}
showMemoryRenameModal={showMemoryRenameModal}
>
<MoreButton></MoreButton>

View File

@ -12,15 +12,16 @@ import {
import { PenLine, Trash2 } from 'lucide-react';
import { MouseEventHandler, PropsWithChildren, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { IMemoryAppProps, useDeleteMemory } from './hooks';
import { useDeleteMemory } from './hooks';
import { IMemory } from './interface';
export function MemoryDropdown({
children,
dataset,
memory,
showMemoryRenameModal,
}: PropsWithChildren & {
dataset: IMemoryAppProps;
showMemoryRenameModal: (dataset: IMemoryAppProps) => void;
memory: IMemory;
showMemoryRenameModal: (memory: IMemory) => void;
}) {
const { t } = useTranslation();
const { deleteMemory } = useDeleteMemory();
@ -28,13 +29,13 @@ export function MemoryDropdown({
useCallback(
(e) => {
e.stopPropagation();
showMemoryRenameModal(dataset);
showMemoryRenameModal(memory);
},
[dataset, showMemoryRenameModal],
[memory, showMemoryRenameModal],
);
const handleDelete: MouseEventHandler<HTMLDivElement> = useCallback(() => {
deleteMemory({ search_id: dataset.id });
}, [dataset.id, deleteMemory]);
deleteMemory({ memory_id: memory.id });
}, [memory, deleteMemory]);
return (
<DropdownMenu>
@ -50,8 +51,9 @@ export function MemoryDropdown({
content={{
node: (
<ConfirmDeleteDialogNode
avatar={{ avatar: dataset.avatar, name: dataset.name }}
name={dataset.name}
avatar={{ avatar: memory.avatar, name: memory.name }}
name={memory.name}
warnText={t('memories.delMemoryWarn')}
/>
),
}}