From 894bf995bb0d06008b8ac0f23abeaf14bba56e61 Mon Sep 17 00:00:00 2001
From: chanx <1243304602@qq.com>
Date: Fri, 26 Dec 2025 12:24:05 +0800
Subject: [PATCH] Fix: Memory-related bug fixes (#12226)
### What problem does this PR solve?
Fix: bugs fix
- table -> Table
- memory delete fail
- memory copywriting modified
### Type of change
- [x] Bug Fix (non-breaking change which fixes an issue)
---
web/src/hooks/use-document-request.ts | 7 +-
web/src/locales/en.ts | 9 +-
web/src/locales/zh.ts | 10 +-
web/src/pages/dataset/dataset/index.tsx | 18 +-
.../dataset/dataset/parsing-status-cell.tsx | 72 ++++----
.../pages/dataset/dataset/reparse-dialog.tsx | 154 ++++++++++++++++++
.../dataset/use-bulk-operate-dataset.tsx | 25 +--
.../pages/dataset/dataset/use-run-document.ts | 11 +-
web/src/pages/memory/memory-message/index.tsx | 2 +-
.../pages/memory/memory-message/interface.ts | 2 +-
.../memory/memory-message/message-table.tsx | 1 +
.../memory-setting/advanced-settings-form.tsx | 6 +-
.../memory-setting/memory-model-form.tsx | 9 +-
web/src/utils/api.ts | 2 +-
14 files changed, 270 insertions(+), 58 deletions(-)
create mode 100644 web/src/pages/dataset/dataset/reparse-dialog.tsx
diff --git a/web/src/hooks/use-document-request.ts b/web/src/hooks/use-document-request.ts
index aa88628e1..22a4a86ef 100644
--- a/web/src/hooks/use-document-request.ts
+++ b/web/src/hooks/use-document-request.ts
@@ -266,20 +266,19 @@ export const useRunDocument = () => {
mutationFn: async ({
documentIds,
run,
- shouldDelete,
+ option,
}: {
documentIds: string[];
run: number;
- shouldDelete: boolean;
+ option?: { delete: boolean; apply_kb: boolean };
}) => {
queryClient.invalidateQueries({
queryKey: [DocumentApiAction.FetchDocumentList],
});
-
const ret = await kbService.document_run({
doc_ids: documentIds,
run,
- delete: shouldDelete,
+ ...option,
});
const code = get(ret, 'data.code');
if (code === 0) {
diff --git a/web/src/locales/en.ts b/web/src/locales/en.ts
index 1779129ee..335e17ad6 100644
--- a/web/src/locales/en.ts
+++ b/web/src/locales/en.ts
@@ -125,8 +125,9 @@ Procedural Memory: Learned skills, habits, and automated procedures.`,
},
memory: {
messages: {
+ forgetMessageTip: 'Are you sure you want to forget?',
messageDescription:
- 'Memory retrieval is configured with Similarity threshold, Keyword similarity weight, and Top N from Advanced Settings.',
+ 'Memory extract is configured with Prompts and Temperature from Advanced Settings.',
copied: 'Copied!',
contentEmbed: 'Content embed',
content: 'Content',
@@ -216,6 +217,10 @@ Procedural Memory: Learned skills, habits, and automated procedures.`,
deleteSettingFieldWarn: `This field will be deleted; existing metadata won't be affected.`,
deleteSettingValueWarn: `This value will be deleted; existing metadata won't be affected.`,
},
+ redoAll: 'Clear existing chunks',
+ applyAutoMetadataSettings: 'Apply global auto-metadata settings',
+ parseFileTip: 'Are you sure to parse?',
+ parseFile: 'Parse file',
emptyMetadata: 'No metadata',
metadataField: 'Metadata field',
systemAttribute: 'System attribute',
@@ -455,7 +460,7 @@ Procedural Memory: Learned skills, habits, and automated procedures.`,
manualSetup: 'Choose pipeline',
builtIn: 'Built-in',
titleDescription:
- 'Update your knowledge base configuration here, particularly the chunking method.',
+ 'Update your memory configuration here, particularly the LLM and prompts.',
name: 'Knowledge base name',
photo: 'Knowledge base photo',
photoTip: 'You can upload a file with 4 MB',
diff --git a/web/src/locales/zh.ts b/web/src/locales/zh.ts
index 4570233ca..da3874bc0 100644
--- a/web/src/locales/zh.ts
+++ b/web/src/locales/zh.ts
@@ -117,8 +117,8 @@ export default {
},
memory: {
messages: {
- messageDescription:
- '记忆检索已在高级设置中配置相似度阈值、关键词相似度权重和前N个结果。',
+ forgetMessageTip: '确定遗忘吗?',
+ messageDescription: '记忆提取使用高级设置中的提示词和温度值进行配置。',
copied: '已复制!',
contentEmbed: '内容嵌入',
content: '内容',
@@ -201,6 +201,10 @@ export default {
deleteSettingFieldWarn: `此字段将被删除;现有元数据不会受到影响。`,
deleteSettingValueWarn: `此值将被删除;现有元数据不会受到影响。`,
},
+ redoAll: '清除现有分块',
+ applyAutoMetadataSettings: '应用全局自动元数据设置',
+ parseFileTip: '您确定要解析吗?',
+ parseFile: '解析文件',
emptyMetadata: '无元数据',
localUpload: '本地上传',
fileSize: '文件大小',
@@ -418,7 +422,7 @@ export default {
parseType: '解析方法',
manualSetup: '选择pipeline',
builtIn: '内置',
- titleDescription: '在这里更新您的知识库详细信息,尤其是切片方法。',
+ titleDescription: '在这里更新您的记忆配置,特别是大语言模型和提示词。',
name: '知识库名称',
photo: '知识库图片',
photoTip: '你可以上传4MB的文件',
diff --git a/web/src/pages/dataset/dataset/index.tsx b/web/src/pages/dataset/dataset/index.tsx
index 1d2908d5d..f2c4b9667 100644
--- a/web/src/pages/dataset/dataset/index.tsx
+++ b/web/src/pages/dataset/dataset/index.tsx
@@ -23,6 +23,7 @@ import {
import { ManageMetadataModal } from '../components/metedata/manage-modal';
import { DatasetTable } from './dataset-table';
import Generate from './generate-button/generate';
+import { ReparseDialog } from './reparse-dialog';
import { useBulkOperateDataset } from './use-bulk-operate-dataset';
import { useCreateEmptyDocument } from './use-create-empty-document';
import { useSelectDatasetFilters } from './use-select-filters';
@@ -77,7 +78,12 @@ export default function Dataset() {
const { rowSelection, rowSelectionIsEmpty, setRowSelection, selectedCount } =
useRowSelection();
- const { list } = useBulkOperateDataset({
+ const {
+ list,
+ visible: reparseDialogVisible,
+ hideModal: hideReparseDialogModal,
+ handleRunClick: handleOperationIconClick,
+ } = useBulkOperateDataset({
documents,
rowSelection,
setRowSelection,
@@ -207,6 +213,16 @@ export default function Dataset() {
otherData={metadataConfig.record}
/>
)}
+ {reparseDialogVisible && (
+
+ )}
>
);
diff --git a/web/src/pages/dataset/dataset/parsing-status-cell.tsx b/web/src/pages/dataset/dataset/parsing-status-cell.tsx
index 102b6db54..ea6019b98 100644
--- a/web/src/pages/dataset/dataset/parsing-status-cell.tsx
+++ b/web/src/pages/dataset/dataset/parsing-status-cell.tsx
@@ -1,4 +1,3 @@
-import { ConfirmDeleteDialog } from '@/components/confirm-delete-dialog';
import { IconFontFill } from '@/components/icon-font';
import {
DropdownMenu,
@@ -19,6 +18,7 @@ import { useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { DocumentType, RunningStatus } from './constant';
import { ParsingCard } from './parsing-card';
+import { ReparseDialog } from './reparse-dialog';
import { UseChangeDocumentParserShowType } from './use-change-document-parser';
import { useHandleRunDocumentByIds } from './use-run-document';
import { UseSaveMetaShowType } from './use-save-meta';
@@ -63,15 +63,21 @@ export function ParsingStatusCell({
} = record;
const operationIcon = IconMap[run];
const p = Number((progress * 100).toFixed(2));
- const { handleRunDocumentByIds } = useHandleRunDocumentByIds(id);
+ const {
+ handleRunDocumentByIds,
+ visible: reparseDialogVisible,
+ showModal: showReparseDialogModal,
+ hideModal: hideReparseDialogModal,
+ } = useHandleRunDocumentByIds(id);
const isRunning = isParserRunning(run);
const isZeroChunk = chunk_num === 0;
- const handleOperationIconClick =
- (shouldDelete: boolean = false) =>
- () => {
- handleRunDocumentByIds(record.id, isRunning, shouldDelete);
- };
+ const handleOperationIconClick = (option: {
+ delete: boolean;
+ apply_kb: boolean;
+ }) => {
+ handleRunDocumentByIds(record.id, isRunning, option);
+ };
const handleShowChangeParserModal = useCallback(() => {
showChangeParserModal(record);
@@ -129,23 +135,20 @@ export function ParsingStatusCell({
{!isParserRunning(run) && (
-
+ {
+ showReparseDialogModal();
+ }}
>
-
{}
- }
- >
- {!isParserRunning(run) && operationIcon}
-
-
+ {!isParserRunning(run) && operationIcon}
+
+ // {/* */}
)}
{isParserRunning(run) ? (
<>
@@ -158,11 +161,14 @@ export function ParsingStatusCell({
{}
- }
+ onClick={() => {
+ showReparseDialogModal();
+ }}
+ // onClick={
+ // isZeroChunk || isRunning
+ // ? handleOperationIconClick(false)
+ // : () => {}
+ // }
>
{operationIcon}
@@ -175,6 +181,16 @@ export function ParsingStatusCell({
)}
)}
+ {reparseDialogVisible && (
+
+ )}
);
}
diff --git a/web/src/pages/dataset/dataset/reparse-dialog.tsx b/web/src/pages/dataset/dataset/reparse-dialog.tsx
new file mode 100644
index 000000000..31a217a21
--- /dev/null
+++ b/web/src/pages/dataset/dataset/reparse-dialog.tsx
@@ -0,0 +1,154 @@
+import { ConfirmDeleteDialog } from '@/components/confirm-delete-dialog';
+import {
+ DynamicForm,
+ DynamicFormRef,
+ FormFieldType,
+} from '@/components/dynamic-form';
+import { Checkbox } from '@/components/ui/checkbox';
+import { DialogProps } from '@radix-ui/react-dialog';
+import { t } from 'i18next';
+import { useCallback, useState } from 'react';
+
+export const ReparseDialog = ({
+ handleOperationIconClick,
+ chunk_num,
+ hidden = false,
+ visible = true,
+ hideModal,
+ children,
+}: DialogProps & {
+ chunk_num: number;
+ handleOperationIconClick: (options: {
+ delete: boolean;
+ apply_kb: boolean;
+ }) => void;
+ visible: boolean;
+ hideModal: () => void;
+ hidden?: boolean;
+}) => {
+ const [formInstance, setFormInstance] = useState(null);
+
+ const formCallbackRef = useCallback((node: DynamicFormRef | null) => {
+ if (node) {
+ setFormInstance(node);
+ console.log('Form instance assigned:', node);
+ } else {
+ console.log('Form instance removed');
+ }
+ }, []);
+
+ const handleCancel = useCallback(() => {
+ // handleOperationIconClick(false);
+ hideModal?.();
+ formInstance?.reset();
+ }, [formInstance]);
+
+ const handleSave = useCallback(async () => {
+ const instance = formInstance;
+ if (!instance) {
+ console.error('Form instance is null');
+ return;
+ }
+
+ const check = await instance.trigger();
+ if (check) {
+ instance.submit();
+ const formValues = instance.getValues();
+ console.log(formValues);
+ handleOperationIconClick({
+ delete: formValues.delete,
+ apply_kb: formValues.apply_kb,
+ });
+ }
+ }, [formInstance, handleOperationIconClick]);
+
+ // useEffect(() => {
+ // if (!hidden) {
+ // const timer = setTimeout(() => {
+ // if (!formInstance) {
+ // console.warn(
+ // 'Form ref is still null after component should be mounted',
+ // );
+ // } else {
+ // console.log('Form ref is properly set');
+ // }
+ // }, 1000);
+
+ // return () => clearTimeout(timer);
+ // }
+ // }, [hidden, formInstance]);
+
+ return (
+ handleSave()}
+ onCancel={() => handleCancel()}
+ hidden={hidden}
+ open={visible}
+ content={{
+ title: t(`knowledgeDetails.parseFileTip`),
+ node: (
+
+
{
+ console.log('submit', data);
+ }}
+ ref={formCallbackRef}
+ fields={[
+ {
+ name: 'delete',
+ label: '',
+ type: FormFieldType.Checkbox,
+ render: (fieldProps) => (
+
+ {
+ fieldProps.onChange(checked);
+ }}
+ />
+
+ {chunk_num > 0
+ ? t(`knowledgeDetails.redo`, { chunkNum: chunk_num })
+ : t('knowledgeDetails.redoAll')}
+
+
+ ),
+ },
+ {
+ name: 'apply_kb',
+ label: '',
+ type: FormFieldType.Checkbox,
+ render: (fieldProps) => (
+
+ {
+ fieldProps.onChange(checked);
+ }}
+ />
+
+ {t('knowledgeDetails.applyAutoMetadataSettings')}
+
+
+ ),
+ },
+ ]}
+ >
+ {/* handleOperationIconClick(false)}
+ cancelText={t('common.cancel')}
+ />
+ */}
+
+
+ ),
+ }}
+ >
+ {/* {children} */}
+
+ );
+};
diff --git a/web/src/pages/dataset/dataset/use-bulk-operate-dataset.tsx b/web/src/pages/dataset/dataset/use-bulk-operate-dataset.tsx
index ea8eeaebc..b0527c264 100644
--- a/web/src/pages/dataset/dataset/use-bulk-operate-dataset.tsx
+++ b/web/src/pages/dataset/dataset/use-bulk-operate-dataset.tsx
@@ -1,3 +1,4 @@
+import { useSetModalState } from '@/hooks/common-hooks';
import {
UseRowSelectionType,
useSelectedIds,
@@ -30,9 +31,9 @@ export function useBulkOperateDataset({
const { runDocumentByIds } = useRunDocument();
const { setDocumentStatus } = useSetDocumentStatus();
const { removeDocument } = useRemoveDocument();
-
+ const { visible, showModal, hideModal } = useSetModalState();
const runDocument = useCallback(
- (run: number) => {
+ async (run: number, option?: { delete: boolean; apply_kb: boolean }) => {
const nonVirtualKeys = selectedRowKeys.filter(
(x) =>
!documents.some((y) => x === y.id && y.type === DocumentType.Virtual),
@@ -42,18 +43,22 @@ export function useBulkOperateDataset({
toast.error(t('Please select a non-empty file list'));
return;
}
- runDocumentByIds({
+ await runDocumentByIds({
documentIds: nonVirtualKeys,
run,
- shouldDelete: false,
+ option,
});
+ hideModal();
},
- [documents, runDocumentByIds, selectedRowKeys, t],
+ [documents, runDocumentByIds, selectedRowKeys, hideModal, t],
);
- const handleRunClick = useCallback(() => {
- runDocument(1);
- }, [runDocument]);
+ const handleRunClick = useCallback(
+ (option: { delete: boolean; apply_kb: boolean }) => {
+ runDocument(1, option);
+ },
+ [runDocument],
+ );
const handleCancelClick = useCallback(() => {
runDocument(2);
@@ -106,7 +111,7 @@ export function useBulkOperateDataset({
id: 'run',
label: t('knowledgeDetails.run'),
icon: ,
- onClick: handleRunClick,
+ onClick: () => showModal(),
},
{
id: 'cancel',
@@ -127,5 +132,5 @@ export function useBulkOperateDataset({
},
];
- return { list };
+ return { list, visible, hideModal, showModal, handleRunClick };
}
diff --git a/web/src/pages/dataset/dataset/use-run-document.ts b/web/src/pages/dataset/dataset/use-run-document.ts
index c17235f9b..b7a92401c 100644
--- a/web/src/pages/dataset/dataset/use-run-document.ts
+++ b/web/src/pages/dataset/dataset/use-run-document.ts
@@ -1,3 +1,4 @@
+import { useSetModalState } from '@/hooks/common-hooks';
import { useRunDocument } from '@/hooks/use-document-request';
import { useState } from 'react';
@@ -5,11 +6,11 @@ export const useHandleRunDocumentByIds = (id: string) => {
const { runDocumentByIds, loading } = useRunDocument();
const [currentId, setCurrentId] = useState('');
const isLoading = loading && currentId !== '' && currentId === id;
-
+ const { visible, showModal, hideModal } = useSetModalState();
const handleRunDocumentByIds = async (
documentId: string,
isRunning: boolean,
- shouldDelete: boolean = false,
+ option: { delete: boolean; apply_kb: boolean },
) => {
if (isLoading) {
return;
@@ -19,16 +20,20 @@ export const useHandleRunDocumentByIds = (id: string) => {
await runDocumentByIds({
documentIds: [documentId],
run: isRunning ? 2 : 1,
- shouldDelete,
+ option,
});
setCurrentId('');
} catch (error) {
setCurrentId('');
}
+ hideModal();
};
return {
handleRunDocumentByIds,
loading: isLoading,
+ visible,
+ showModal,
+ hideModal,
};
};
diff --git a/web/src/pages/memory/memory-message/index.tsx b/web/src/pages/memory/memory-message/index.tsx
index 9e65612fd..943fad706 100644
--- a/web/src/pages/memory/memory-message/index.tsx
+++ b/web/src/pages/memory/memory-message/index.tsx
@@ -39,7 +39,7 @@ export default function MemoryMessage() {
messages={data?.messages?.message_list ?? []}
pagination={pagination}
setPagination={setPagination}
- total={data?.messages?.total ?? 0}
+ total={data?.messages?.total_count ?? 0}
// rowSelection={rowSelection}
// setRowSelection={setRowSelection}
// loading={loading}
diff --git a/web/src/pages/memory/memory-message/interface.ts b/web/src/pages/memory/memory-message/interface.ts
index 347f3db0c..09bd51e75 100644
--- a/web/src/pages/memory/memory-message/interface.ts
+++ b/web/src/pages/memory/memory-message/interface.ts
@@ -14,7 +14,7 @@ export interface IMessageInfo {
}
export interface IMessageTableProps {
- messages: { message_list: Array; total: number };
+ messages: { message_list: Array; total_count: number };
storage_type: string;
}
diff --git a/web/src/pages/memory/memory-message/message-table.tsx b/web/src/pages/memory/memory-message/message-table.tsx
index 68f735899..1d9c486fb 100644
--- a/web/src/pages/memory/memory-message/message-table.tsx
+++ b/web/src/pages/memory/memory-message/message-table.tsx
@@ -252,6 +252,7 @@ export function MemoryTable({
open={showDeleteDialog}
onOpenChange={setShowDeleteDialog}
content={{
+ title: t('memory.messages.forgetMessageTip'),
node: (
{
horizontal: true,
placeholder: t('memory.config.storageTypePlaceholder'),
options: [
- { label: 'table', value: 'table' },
- // { label: 'graph', value: 'graph' },
+ { label: 'Table', value: 'table' },
+ // { label: 'Graph', value: 'graph' },
],
required: false,
}}
@@ -95,7 +95,7 @@ export const AdvancedSettingsForm = () => {
// placeholder: t('memory.config.storageTypePlaceholder'),
options: [
// { label: 'LRU', value: 'LRU' },
- { label: 'FIFO', value: 'FIFO' },
+ { label: 'FIFO', value: 'fifo' },
],
required: false,
}}
diff --git a/web/src/pages/memory/memory-setting/memory-model-form.tsx b/web/src/pages/memory/memory-setting/memory-model-form.tsx
index c700de577..97c64208b 100644
--- a/web/src/pages/memory/memory-setting/memory-model-form.tsx
+++ b/web/src/pages/memory/memory-setting/memory-model-form.tsx
@@ -4,6 +4,7 @@ import { EmbeddingSelect } from '@/pages/dataset/dataset-setting/configuration/c
import { MemoryType } from '@/pages/memories/constants';
import { useTranslation } from 'react-i18next';
import { z } from 'zod';
+import { useFetchMemoryMessageList } from '../memory-message/hook';
export const memoryModelFormSchema = {
embd_id: z.string(),
@@ -20,6 +21,7 @@ export const defaultMemoryModelForm = {
export const MemoryModelForm = () => {
const { modelOptions } = useModelOptions();
const { t } = useTranslation();
+ const { data } = useFetchMemoryMessageList();
return (
<>
{
type: FormFieldType.Custom,
disabled: true,
render: (field) => (
-
+ 0}
+ />
),
tooltip: t('memories.embeddingModelTooltip'),
@@ -47,6 +53,7 @@ export const MemoryModelForm = () => {
required: true,
horizontal: true,
type: FormFieldType.Select,
+ disabled: data?.messages?.total_count > 0,
options: modelOptions as { value: string; label: string }[],
tooltip: t('memories.llmTooltip'),
}}
diff --git a/web/src/utils/api.ts b/web/src/utils/api.ts
index 251158000..b43ca9e89 100644
--- a/web/src/utils/api.ts
+++ b/web/src/utils/api.ts
@@ -239,7 +239,7 @@ export default {
createMemory: `${api_host}/memories`,
getMemoryList: `${api_host}/memories`,
getMemoryConfig: (id: string) => `${api_host}/memories/${id}/config`,
- deleteMemory: (id: string) => `${api_host}/memory/rm/${id}`,
+ deleteMemory: (id: string) => `${api_host}/memories/${id}`,
getMemoryDetail: (id: string) => `${api_host}/memories/${id}`,
updateMemorySetting: (id: string) => `${api_host}/memories/${id}`,
deleteMemoryMessage: (data: { memory_id: string; message_id: string }) =>