mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-24 18:50:56 +08:00
添加了记忆功能
This commit is contained in:
parent
e9347337b2
commit
51fc167b2a
@ -81,8 +81,34 @@ export class MemoryFileService {
|
||||
// 如果文件不存在或读取失败,使用空对象
|
||||
}
|
||||
|
||||
// 合并数据,优先使用新数据
|
||||
const mergedData = { ...existingData, ...data }
|
||||
// 合并数据,注意数组的处理
|
||||
const mergedData = { ...existingData }
|
||||
|
||||
// 处理每个属性
|
||||
Object.entries(data).forEach(([key, value]) => {
|
||||
// 如果是数组属性,需要特殊处理
|
||||
if (Array.isArray(value) && Array.isArray(mergedData[key])) {
|
||||
// 对于 memories 和 shortMemories,需要合并而不是覆盖
|
||||
if (key === 'memories' || key === 'shortMemories') {
|
||||
// 创建一个集合来跟踪已存在的记忆ID
|
||||
const existingIds = new Set(mergedData[key].map(item => item.id))
|
||||
|
||||
// 将新记忆添加到现有记忆中,避免重复
|
||||
value.forEach(item => {
|
||||
if (item.id && !existingIds.has(item.id)) {
|
||||
mergedData[key].push(item)
|
||||
existingIds.add(item.id)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
// 其他数组属性,使用新值
|
||||
mergedData[key] = value
|
||||
}
|
||||
} else {
|
||||
// 非数组属性,直接使用新值
|
||||
mergedData[key] = value
|
||||
}
|
||||
})
|
||||
|
||||
// 保存合并后的数据
|
||||
await fs.writeFile(memoryDataPath, JSON.stringify(mergedData, null, 2))
|
||||
|
||||
@ -1070,6 +1070,26 @@
|
||||
"enable": "启用智能优先级管理",
|
||||
"enableTip": "启用后,系统将根据重要性、访问频率和时间因素自动排序记忆",
|
||||
"decay": "记忆衰减",
|
||||
"decayRate": "衰减速率",
|
||||
"decayRateTip": "值越大,记忆衰减越快。0.05表示每天衰减5%",
|
||||
"freshness": "记忆鲜度",
|
||||
"freshnessTip": "考虑记忆的创建时间和最后访问时间,优先显示较新的记忆",
|
||||
"updateNow": "立即更新",
|
||||
"updateNowTip": "立即更新所有记忆的优先级排序",
|
||||
"update": "更新"
|
||||
},
|
||||
"contextualRecommendation": {
|
||||
"title": "上下文感知记忆推荐",
|
||||
"description": "根据当前对话上下文,智能推荐相关的记忆内容。",
|
||||
"enable": "启用上下文感知记忆推荐",
|
||||
"enableTip": "启用后,系统将根据当前对话上下文自动推荐相关记忆",
|
||||
"autoRecommend": "自动推荐记忆",
|
||||
"autoRecommendTip": "启用后,系统将定期自动分析当前对话并推荐相关记忆",
|
||||
"threshold": "推荐阈值",
|
||||
"thresholdTip": "设置记忆推荐的相似度阈值,值越高要求越严格",
|
||||
"clearRecommendations": "清除当前推荐",
|
||||
"clearRecommendationsTip": "清除当前的记忆推荐列表",
|
||||
"clear": "清除",
|
||||
"decayTip": "随着时间推移,未访问的记忆重要性会逐渐降低",
|
||||
"decayRate": "衰减速率",
|
||||
"decayRateTip": "值越大,记忆衰减越快。0.05表示每天衰减5%",
|
||||
|
||||
@ -9,7 +9,7 @@ import {
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { TopicManager } from '@renderer/hooks/useTopic'
|
||||
import { analyzeAndAddShortMemories, useMemoryService } from '@renderer/services/MemoryService'
|
||||
import store, { useAppDispatch, useAppSelector } from '@renderer/store'
|
||||
import { useAppDispatch, useAppSelector } from '@renderer/store'
|
||||
import {
|
||||
addMemory,
|
||||
clearMemories,
|
||||
@ -19,7 +19,8 @@ import {
|
||||
setAnalyzing,
|
||||
setAutoAnalyze,
|
||||
setMemoryActive,
|
||||
setShortMemoryAnalyzeModel
|
||||
setShortMemoryAnalyzeModel,
|
||||
saveMemoryData
|
||||
} from '@renderer/store/memory'
|
||||
import { Topic } from '@renderer/types'
|
||||
import { Button, Empty, Input, List, message, Modal, Radio, Select, Switch, Tabs, Tag, Tooltip } from 'antd'
|
||||
@ -260,18 +261,9 @@ const MemorySettings: FC = () => {
|
||||
dispatch(setAnalyzeModel(modelId))
|
||||
console.log('[Memory Settings] Analyze model set:', modelId)
|
||||
|
||||
// 手动保存到JSON文件
|
||||
// 使用Redux Thunk保存到JSON文件
|
||||
try {
|
||||
const state = store.getState().memory
|
||||
await window.api.memory.saveData({
|
||||
analyzeModel: modelId,
|
||||
shortMemoryAnalyzeModel: state.shortMemoryAnalyzeModel,
|
||||
vectorizeModel: state.vectorizeModel,
|
||||
// 确保其他必要的数据也被保存
|
||||
memoryLists: state.memoryLists || [],
|
||||
memories: state.memories || [],
|
||||
shortMemories: state.shortMemories || []
|
||||
})
|
||||
await dispatch(saveMemoryData({ analyzeModel: modelId })).unwrap()
|
||||
console.log('[Memory Settings] Analyze model saved to file successfully:', modelId)
|
||||
} catch (error) {
|
||||
console.error('[Memory Settings] Failed to save analyze model to file:', error)
|
||||
@ -283,18 +275,9 @@ const MemorySettings: FC = () => {
|
||||
dispatch(setShortMemoryAnalyzeModel(modelId))
|
||||
console.log('[Memory Settings] Short memory analyze model set:', modelId)
|
||||
|
||||
// 手动保存到JSON文件
|
||||
// 使用Redux Thunk保存到JSON文件
|
||||
try {
|
||||
const state = store.getState().memory
|
||||
await window.api.memory.saveData({
|
||||
analyzeModel: state.analyzeModel,
|
||||
shortMemoryAnalyzeModel: modelId,
|
||||
vectorizeModel: state.vectorizeModel,
|
||||
// 确保其他必要的数据也被保存
|
||||
memoryLists: state.memoryLists || [],
|
||||
memories: state.memories || [],
|
||||
shortMemories: state.shortMemories || []
|
||||
})
|
||||
await dispatch(saveMemoryData({ shortMemoryAnalyzeModel: modelId })).unwrap()
|
||||
console.log('[Memory Settings] Short memory analyze model saved to file successfully:', modelId)
|
||||
} catch (error) {
|
||||
console.error('[Memory Settings] Failed to save short memory analyze model to file:', error)
|
||||
|
||||
@ -899,33 +899,42 @@ export const analyzeAndAddShortMemories = async (topicId: string) => {
|
||||
|
||||
// 构建短期记忆分析提示词,包含已有记忆和新对话
|
||||
const prompt = `
|
||||
请对以下对话内容进行详细分析和总结,提取对当前对话至关重要的上下文信息。
|
||||
请对以下对话内容进行非常详细的分析和总结,提取对当前对话至关重要的上下文信息。请注意,这个分析将用于生成短期记忆,帮助AI理解当前对话的完整上下文。
|
||||
|
||||
分析要求:
|
||||
1. 详细总结用户的每一句话中表达的关键信息、需求和意图
|
||||
2. 分析AI回复中的重要内容和对用户问题的解决方案
|
||||
3. 识别对话中的重要事实、数据和具体细节
|
||||
4. 捕捉对话的逻辑发展和转折点
|
||||
1. 非常详细地总结用户的每一句话中表达的关键信息、需求和意图
|
||||
2. 全面分析AI回复中的重要内容和对用户问题的解决方案
|
||||
3. 详细记录对话中的重要事实、数据、代码示例和具体细节
|
||||
4. 清晰捕捉对话的逻辑发展、转折点和关键决策
|
||||
5. 提取对理解当前对话上下文必不可少的信息
|
||||
6. 记录用户提出的具体问题和关注点
|
||||
7. 捕捉用户在对话中表达的偏好、困惑和反馈
|
||||
8. 记录对话中提到的文件、路径、变量名等具体技术细节
|
||||
|
||||
与长期记忆不同,短期记忆应该关注当前对话的具体细节和上下文,而不是用户的长期偏好。每条短期记忆应该是对对话片段的精准总结,确保不遗漏任何重要信息。
|
||||
与长期记忆不同,短期记忆应该非常详细地关注当前对话的具体细节和上下文。每条短期记忆应该是对对话片段的精准总结,确保不遗漏任何重要信息。
|
||||
|
||||
请注意,对于长对话(超过5万字),您应该生成至少15-20条详细的记忆条目,确保完整捕捉对话的所有重要方面。对于超长对话(超过8万字),应生成至少20-30条记忆条目。
|
||||
|
||||
${
|
||||
existingMemoriesContent
|
||||
? `以下是已经提取的重要信息:
|
||||
${existingMemoriesContent}
|
||||
|
||||
请分析新的对话内容,提取出新的重要信息,避免重复已有信息。确保新提取的信息与已有信息形成连贯的上下文理解。`
|
||||
: '请对对话进行全面分析,确保不遗漏任何重要细节。每条总结应该是完整的句子,清晰表达一个重要的上下文信息。'
|
||||
请分析新的对话内容,提取出新的重要信息,避免重复已有信息。确保新提取的信息与已有信息形成连贯的上下文理解。对于新的对话内容,请提供非常详细的分析。`
|
||||
: '请对对话进行非常全面和详细的分析,确保不遗漏任何重要细节。每条总结应该是完整的句子,清晰表达一个重要的上下文信息。请确保总结足够详细,以便在没有原始对话的情况下也能理解完整的上下文。'
|
||||
}
|
||||
|
||||
输出格式:
|
||||
- 提供完整的上下文总结,数量不限,确保覆盖所有重要信息
|
||||
- 每条总结应该是一个完整的句子
|
||||
- 提供非常详细的上下文总结,数量不限,确保覆盖所有重要信息
|
||||
- 每条总结应该是一个完整的句子,包含充分的上下文信息
|
||||
- 确保总结内容精准、具体且与当前对话直接相关
|
||||
- 按重要性排序,最重要的信息放在前面
|
||||
- 对于复杂的对话,应提供足够多的条目(至少5-10条)以确保上下文的完整性
|
||||
- 如果对话内容简单,可以少于5条,但必须确保完整捕捉所有重要信息
|
||||
- 对于复杂的对话,必须提供足够多的条目(至少15-20条)以确保上下文的完整性
|
||||
- 对于技术内容,请包含具体的文件名、路径、变量名、函数名等技术细节
|
||||
- 对于代码相关的对话,请记录关键的代码片段和实现细节
|
||||
- 如果对话内容简单,可以少于15条,但必须确保完整捕捉所有重要信息
|
||||
|
||||
请记住,您的分析应该非常详细,不要过于简化或概括。对于8万字的对话,100字的总结是远远不够的,应该提供至少500-1000字的详细总结,分成多个条目。
|
||||
|
||||
如果没有找到新的重要信息,请返回空字符串。
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'
|
||||
import { nanoid } from 'nanoid'
|
||||
import log from 'electron-log'
|
||||
import store from '@renderer/store'
|
||||
|
||||
// 记忆列表接口
|
||||
export interface MemoryList {
|
||||
@ -851,12 +852,26 @@ export const saveMemoryData = createAsyncThunk(
|
||||
'memory/saveData',
|
||||
async (data: Partial<MemoryState>) => {
|
||||
try {
|
||||
// log.info('Saving memory data to file...') // Removed direct log call from renderer
|
||||
const result = await window.api.memory.saveData(data)
|
||||
// log.info('Memory data saved successfully') // Removed direct log call from renderer
|
||||
console.log('[Memory] Saving memory data to file...', Object.keys(data))
|
||||
|
||||
// 确保数据完整性
|
||||
const state = store.getState().memory
|
||||
const completeData = {
|
||||
...data,
|
||||
// 如果没有提供这些字段,则使用当前状态中的值
|
||||
memoryLists: data.memoryLists || state.memoryLists,
|
||||
memories: data.memories || state.memories,
|
||||
shortMemories: data.shortMemories || state.shortMemories,
|
||||
analyzeModel: data.analyzeModel || state.analyzeModel,
|
||||
shortMemoryAnalyzeModel: data.shortMemoryAnalyzeModel || state.shortMemoryAnalyzeModel,
|
||||
vectorizeModel: data.vectorizeModel || state.vectorizeModel
|
||||
}
|
||||
|
||||
const result = await window.api.memory.saveData(completeData)
|
||||
console.log('[Memory] Memory data saved successfully')
|
||||
return result
|
||||
} catch (error) {
|
||||
console.error('Failed to save memory data:', error) // Use console.error instead of log.error
|
||||
console.error('[Memory] Failed to save memory data:', error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user