refactor(preferences): update memory preference handling

- Replace direct Redux state access for memory preferences with preferenceService calls in multiple components.
- Introduce new preference mappings for memory settings, including 'feature.memory.auto_dimensions'.
- Remove deprecated preference mappings and update default preferences accordingly.
- Regenerate preference schemas to reflect the latest changes in memory configuration.
This commit is contained in:
fullex 2025-11-29 00:37:03 +08:00
parent dd7b76750b
commit 143b4c46c8
8 changed files with 35 additions and 36 deletions

View File

@ -1,6 +1,6 @@
/**
* Auto-generated preferences configuration
* Generated at: 2025-11-28T15:24:33.354Z
* Generated at: 2025-11-28T16:19:17.585Z
*
* This file is automatically generated from classification.json
* To update this file, modify classification.json and run:
@ -310,6 +310,8 @@ export interface PreferenceSchemas {
'feature.csaas.host': string
// redux/settings/apiServer.port
'feature.csaas.port': number
// redux/memory/memoryConfig.isAutoDimensions
'feature.memory.auto_dimensions': boolean
// redux/memory/currentUserId
'feature.memory.current_user_id': string
// redux/memory/memoryConfig.embedderDimensions
@ -318,8 +320,6 @@ export interface PreferenceSchemas {
'feature.memory.enabled': boolean
// redux/memory/memoryConfig.customFactExtractionPrompt
'feature.memory.fact_extraction_prompt': string
// redux/memory/memoryConfig.isAutoDimensions
'feature.memory.is_auto_dimensions': boolean
// redux/memory/memoryConfig.customUpdateMemoryPrompt
'feature.memory.update_memory_prompt': string
// redux/settings/maxKeepAliveMinapps
@ -585,11 +585,11 @@ export const DefaultPreferences: PreferenceSchemas = {
'feature.csaas.enabled': false,
'feature.csaas.host': 'localhost',
'feature.csaas.port': 23333,
'feature.memory.auto_dimensions': true,
'feature.memory.current_user_id': 'default-user',
'feature.memory.embedder_dimensions': 1536,
'feature.memory.enabled': false,
'feature.memory.fact_extraction_prompt': MEMORY_FACT_EXTRACTION_PROMPT,
'feature.memory.is_auto_dimensions': true,
'feature.memory.update_memory_prompt': MEMORY_UPDATE_SYSTEM_PROMPT,
'feature.minapp.max_keep_alive': 3,
'feature.minapp.open_link_external': false,

View File

@ -7,10 +7,11 @@
* 3. onRequestEnd: 自动记忆存储
*/
import { type AiRequestContext, definePlugin } from '@cherrystudio/ai-core'
import { preferenceService } from '@data/PreferenceService'
import { loggerService } from '@logger'
import { getDefaultModel, getProviderByModel } from '@renderer/services/AssistantService'
import store from '@renderer/store'
import { selectCurrentUserId, selectGlobalMemoryEnabled, selectMemoryConfig } from '@renderer/store/memory'
import { selectMemoryConfig } from '@renderer/store/memory'
import type { Assistant } from '@renderer/types'
import type { ExtractResults } from '@renderer/utils/extract'
import { extractInfoFromXML } from '@renderer/utils/extract'
@ -176,7 +177,7 @@ async function storeConversationMemory(
assistant: Assistant,
context: AiRequestContext
): Promise<void> {
const globalMemoryEnabled = selectGlobalMemoryEnabled(store.getState())
const globalMemoryEnabled = await preferenceService.get('feature.memory.enabled')
if (!globalMemoryEnabled || !assistant.enableMemory) {
return
@ -199,7 +200,7 @@ async function storeConversationMemory(
return
}
const currentUserId = selectCurrentUserId(store.getState())
const currentUserId = await preferenceService.get('feature.memory.current_user_id')
// const lastUserMessage = messages.findLast((m) => m.role === 'user')
const processorConfig = MemoryProcessor.getProcessorConfig(
@ -267,7 +268,7 @@ export const searchOrchestrationPlugin = (assistant: Assistant, topicId: string)
const knowledgeBaseIds = assistant.knowledge_bases?.map((base) => base.id)
const hasKnowledgeBase = !isEmpty(knowledgeBaseIds)
const knowledgeRecognition = assistant.knowledgeRecognition || 'on'
const globalMemoryEnabled = selectGlobalMemoryEnabled(store.getState())
const globalMemoryEnabled = await preferenceService.get('feature.memory.enabled')
const shouldWebSearch = !!assistant.webSearchProviderId
const shouldKnowledgeSearch = hasKnowledgeBase && knowledgeRecognition === 'on'
const shouldMemorySearch = globalMemoryEnabled && assistant.enableMemory
@ -369,7 +370,7 @@ export const searchOrchestrationPlugin = (assistant: Assistant, topicId: string)
}
// 🧠 记忆搜索工具配置
const globalMemoryEnabled = selectGlobalMemoryEnabled(store.getState())
const globalMemoryEnabled = await preferenceService.get('feature.memory.enabled')
if (globalMemoryEnabled && assistant.enableMemory) {
// logger.info('🧠 Adding memory search tool')
params.tools['builtin_memory_search'] = memorySearchTool()

View File

@ -1,5 +1,6 @@
import { preferenceService } from '@data/PreferenceService'
import store from '@renderer/store'
import { selectCurrentUserId, selectGlobalMemoryEnabled, selectMemoryConfig } from '@renderer/store/memory'
import { selectMemoryConfig } from '@renderer/store/memory'
import { type InferToolInput, type InferToolOutput, tool } from 'ai'
import * as z from 'zod'
@ -18,7 +19,7 @@ export const memorySearchTool = () => {
limit: z.number().min(1).max(20).default(5).describe('Maximum number of memories to return')
}),
execute: async ({ query, limit = 5 }) => {
const globalMemoryEnabled = selectGlobalMemoryEnabled(store.getState())
const globalMemoryEnabled = await preferenceService.get('feature.memory.enabled')
if (!globalMemoryEnabled) {
return []
}
@ -28,7 +29,7 @@ export const memorySearchTool = () => {
return []
}
const currentUserId = selectCurrentUserId(store.getState())
const currentUserId = await preferenceService.get('feature.memory.current_user_id')
const processorConfig = MemoryProcessor.getProcessorConfig(memoryConfig, 'default', currentUserId)
const memoryProcessor = new MemoryProcessor()

View File

@ -1,8 +1,9 @@
import { Box, Button, InfoTooltip, Switch, Tooltip } from '@cherrystudio/ui'
import { loggerService } from '@logger'
import { usePreference } from '@renderer/data/hooks/usePreference'
import MemoriesSettingsModal from '@renderer/pages/memory/settings-modal'
import MemoryService from '@renderer/services/MemoryService'
import { selectGlobalMemoryEnabled, selectMemoryConfig } from '@renderer/store/memory'
import { selectMemoryConfig } from '@renderer/store/memory'
import type { Assistant, AssistantSettings } from '@renderer/types'
import { Alert, Card, Space, Typography } from 'antd'
import { useForm } from 'antd/es/form/Form'
@ -26,7 +27,7 @@ interface Props {
const AssistantMemorySettings: React.FC<Props> = ({ assistant, updateAssistant, onClose }) => {
const { t } = useTranslation()
const memoryConfig = useSelector(selectMemoryConfig)
const globalMemoryEnabled = useSelector(selectGlobalMemoryEnabled)
const [globalMemoryEnabled] = usePreference('feature.memory.enabled')
const [memoryStats, setMemoryStats] = useState<{ count: number; loading: boolean }>({
count: 0,
loading: true

View File

@ -4,6 +4,7 @@ import { Flex } from '@cherrystudio/ui'
import { Switch } from '@cherrystudio/ui'
import { Button } from '@cherrystudio/ui'
import { cacheService } from '@data/CacheService'
import { usePreference } from '@data/hooks/usePreference'
import { loggerService } from '@logger'
import { DeleteIcon, EditIcon, LoadingIcon, RefreshIcon } from '@renderer/components/Icons'
import TextBadge from '@renderer/components/TextBadge'
@ -11,13 +12,7 @@ import { useTheme } from '@renderer/context/ThemeProvider'
import { useModel } from '@renderer/hooks/useModel'
import MemoriesSettingsModal from '@renderer/pages/memory/settings-modal'
import MemoryService from '@renderer/services/MemoryService'
import {
selectCurrentUserId,
selectGlobalMemoryEnabled,
selectMemoryConfig,
setCurrentUserId,
setGlobalMemoryEnabled
} from '@renderer/store/memory'
import { selectMemoryConfig } from '@renderer/store/memory'
import type { MemoryItem } from '@types'
import { Badge, Dropdown, Empty, Form, Input, Modal, Pagination, Space, Spin } from 'antd'
import dayjs from 'dayjs'
@ -25,7 +20,7 @@ import relativeTime from 'dayjs/plugin/relativeTime'
import { Brain, Calendar, MenuIcon, PlusIcon, Settings2, UserRound, UserRoundMinus, UserRoundPlus } from 'lucide-react'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useDispatch, useSelector } from 'react-redux'
import { useSelector } from 'react-redux'
import styled from 'styled-components'
import {
@ -281,9 +276,8 @@ const AddUserModal: React.FC<AddUserModalProps> = ({ visible, onCancel, onAdd, e
const MemorySettings = () => {
const { t } = useTranslation()
const dispatch = useDispatch()
const currentUser = useSelector(selectCurrentUserId)
const globalMemoryEnabled = useSelector(selectGlobalMemoryEnabled)
const [currentUser, setCurrentUserId] = usePreference('feature.memory.current_user_id')
const [globalMemoryEnabled, setGlobalMemoryEnabled] = usePreference('feature.memory.enabled')
const [allMemories, setAllMemories] = useState<MemoryItem[]>([])
const [loading, setLoading] = useState(false)
@ -436,8 +430,8 @@ const MemorySettings = () => {
const handleUserSwitch = async (userId: string) => {
logger.verbose(`Switching to user: ${userId}`)
// First update Redux state
dispatch(setCurrentUserId(userId))
// First update preference state
setCurrentUserId(userId)
// Clear current memories to show loading state immediately
setAllMemories([])
@ -483,7 +477,7 @@ const MemorySettings = () => {
await memoryService.updateConfig()
if (cacheService.get('memory.wait.settings')) {
cacheService.delete('memory.wait.settings')
dispatch(setGlobalMemoryEnabled(true))
setGlobalMemoryEnabled(true)
}
}
@ -560,7 +554,7 @@ const MemorySettings = () => {
return setSettingsModalVisible(true)
}
dispatch(setGlobalMemoryEnabled(enabled))
setGlobalMemoryEnabled(enabled)
if (enabled) {
return window.modal.confirm({

View File

@ -6,9 +6,9 @@ import {
FactRetrievalSchema,
getFactRetrievalMessages,
getUpdateMemoryMessages,
MemoryUpdateSchema,
updateMemorySystemPrompt
MemoryUpdateSchema
} from '@renderer/utils/memory-prompts'
import { MEMORY_UPDATE_SYSTEM_PROMPT } from '@shared/config/prompts'
import type { MemoryConfig, MemoryItem } from '@types'
import jaison from 'jaison/lib/index.js'
@ -122,7 +122,7 @@ export class MemoryProcessor {
const updateMemoryUserPrompt = getUpdateMemoryMessages(existingMemories, facts)
const responseContent = await fetchGenerate({
prompt: updateMemorySystemPrompt,
prompt: MEMORY_UPDATE_SYSTEM_PROMPT,
content: updateMemoryUserPrompt,
model: getModel(memoryConfig.llmApiClient.model, memoryConfig.llmApiClient.provider)
})

View File

@ -113,7 +113,9 @@ vi.mock(import('@renderer/config/providers'), async (importOriginal) => {
vi.mock('@shared/config/prompts', () => ({
WEB_SEARCH_PROMPT_FOR_OPENROUTER: 'mock-prompt',
TRANSLATE_PROMPT:
'You are a translation expert. Your only task is to translate text enclosed with <translate_input> from input language to {{target_language}}, provide the translation result directly without any explanation, without `TRANSLATE` and keep original format.'
'You are a translation expert. Your only task is to translate text enclosed with <translate_input> from input language to {{target_language}}, provide the translation result directly without any explanation, without `TRANSLATE` and keep original format.',
MEMORY_FACT_EXTRACTION_PROMPT: 'mock-memory-fact-extraction-prompt',
MEMORY_UPDATE_SYSTEM_PROMPT: 'mock-memory-update-system-prompt'
}))
vi.mock('@renderer/config/systemModels', () => ({

View File

@ -1,5 +1,5 @@
import { createSlice, type PayloadAction } from '@reduxjs/toolkit'
import { factExtractionPrompt, updateMemorySystemPrompt } from '@renderer/utils/memory-prompts'
import { MEMORY_FACT_EXTRACTION_PROMPT, MEMORY_UPDATE_SYSTEM_PROMPT } from '@shared/config/prompts'
import type { MemoryConfig } from '@types'
/**
@ -19,8 +19,8 @@ export interface MemoryState {
const defaultMemoryConfig: MemoryConfig = {
embedderDimensions: 1536,
isAutoDimensions: true,
customFactExtractionPrompt: factExtractionPrompt,
customUpdateMemoryPrompt: updateMemorySystemPrompt
customFactExtractionPrompt: MEMORY_FACT_EXTRACTION_PROMPT,
customUpdateMemoryPrompt: MEMORY_UPDATE_SYSTEM_PROMPT
}
/**