@qianjue/mcp-memory-server
Version:
A Model Context Protocol (MCP) server for intelligent memory management with vector search capabilities
276 lines • 8.76 kB
JavaScript
/**
* 记忆索引系统,用于快速搜索和过滤
*/
export class MemoryIndex {
// 内容索引:单词 -> 记忆ID集合
contentIndex = new Map();
// 标签索引:标签 -> 记忆ID集合
tagIndex = new Map();
// 类型索引:类型 -> 记忆ID集合
typeIndex = new Map();
// 对话索引:对话ID -> 记忆ID集合
conversationIndex = new Map();
// 元数据索引:键值对 -> 记忆ID集合
metadataIndex = new Map();
// 日期索引:日期字符串 -> 记忆ID集合
dateIndex = new Map();
/**
* 添加记忆到索引
*/
addMemory(memory) {
const memoryId = memory.id;
// 索引内容(分词)
this.indexContent(memory.content, memoryId);
// 索引标签
if (memory.tags) {
for (const tag of memory.tags) {
this.addToIndex(this.tagIndex, tag.toLowerCase(), memoryId);
}
}
// 索引类型
this.addToIndex(this.typeIndex, memory.type, memoryId);
// 索引对话ID
if (memory.conversationId) {
this.addToIndex(this.conversationIndex, memory.conversationId, memoryId);
}
// 索引元数据
if (memory.metadata) {
for (const [key, value] of Object.entries(memory.metadata)) {
const metadataKey = `${key}:${String(value)}`;
this.addToIndex(this.metadataIndex, metadataKey, memoryId);
}
}
// 索引日期
const createdDate = new Date(memory.createdAt).toISOString().split('T')[0];
this.addToIndex(this.dateIndex, createdDate, memoryId);
}
/**
* 从索引中移除记忆
*/
removeMemory(memory) {
const memoryId = memory.id;
// 从内容索引中移除
this.removeFromContentIndex(memory.content, memoryId);
// 从标签索引中移除
if (memory.tags) {
for (const tag of memory.tags) {
this.removeFromIndex(this.tagIndex, tag.toLowerCase(), memoryId);
}
}
// 从类型索引中移除
this.removeFromIndex(this.typeIndex, memory.type, memoryId);
// 从对话索引中移除
if (memory.conversationId) {
this.removeFromIndex(this.conversationIndex, memory.conversationId, memoryId);
}
// 从元数据索引中移除
if (memory.metadata) {
for (const [key, value] of Object.entries(memory.metadata)) {
const metadataKey = `${key}:${String(value)}`;
this.removeFromIndex(this.metadataIndex, metadataKey, memoryId);
}
}
// 从日期索引中移除
const createdDate = new Date(memory.createdAt).toISOString().split('T')[0];
this.removeFromIndex(this.dateIndex, createdDate, memoryId);
}
/**
* 更新记忆索引
*/
updateMemory(oldMemory, newMemory) {
this.removeMemory(oldMemory);
this.addMemory(newMemory);
}
/**
* 搜索记忆ID
*/
search(options) {
let resultIds = null;
// 文本搜索
if (options.searchText) {
const textIds = this.searchContent(options.searchText);
resultIds = this.intersectSets(resultIds, textIds);
}
// 标签搜索
if (options.tags && options.tags.length > 0) {
const tagIds = this.searchTags(options.tags);
resultIds = this.intersectSets(resultIds, tagIds);
}
// 类型搜索
if (options.type) {
const typeIds = this.typeIndex.get(options.type) || new Set();
resultIds = this.intersectSets(resultIds, typeIds);
}
// 对话搜索
if (options.conversationId) {
const convIds = this.conversationIndex.get(options.conversationId) || new Set();
resultIds = this.intersectSets(resultIds, convIds);
}
// 元数据搜索
if (options.metadata) {
const metadataIds = this.searchMetadata(options.metadata);
resultIds = this.intersectSets(resultIds, metadataIds);
}
// 日期范围搜索
if (options.dateRange) {
const dateIds = this.searchDateRange(options.dateRange);
resultIds = this.intersectSets(resultIds, dateIds);
}
return resultIds || new Set();
}
/**
* 获取索引统计信息
*/
getStats() {
return {
contentTerms: this.contentIndex.size,
tags: this.tagIndex.size,
types: this.typeIndex.size,
conversations: this.conversationIndex.size,
metadataKeys: this.metadataIndex.size,
dates: this.dateIndex.size,
};
}
/**
* 清空所有索引
*/
clear() {
this.contentIndex.clear();
this.tagIndex.clear();
this.typeIndex.clear();
this.conversationIndex.clear();
this.metadataIndex.clear();
this.dateIndex.clear();
}
// 私有辅助方法
/**
* 索引内容(简单分词)
*/
indexContent(content, memoryId) {
const words = this.tokenize(content);
for (const word of words) {
this.addToIndex(this.contentIndex, word, memoryId);
}
}
/**
* 从内容索引中移除
*/
removeFromContentIndex(content, memoryId) {
const words = this.tokenize(content);
for (const word of words) {
this.removeFromIndex(this.contentIndex, word, memoryId);
}
}
/**
* 简单分词器
*/
tokenize(text) {
return text
.toLowerCase()
.replace(/[^\w\s\u4e00-\u9fff]/g, ' ') // 保留中文字符
.split(/\s+/)
.filter((word) => word.length > 1); // 过滤单字符
}
/**
* 添加到索引
*/
addToIndex(index, key, memoryId) {
if (!index.has(key)) {
index.set(key, new Set());
}
index.get(key).add(memoryId);
}
/**
* 从索引中移除
*/
removeFromIndex(index, key, memoryId) {
const set = index.get(key);
if (set) {
set.delete(memoryId);
if (set.size === 0) {
index.delete(key);
}
}
}
/**
* 搜索内容
*/
searchContent(searchText) {
const words = this.tokenize(searchText);
let resultIds = null;
for (const word of words) {
const wordIds = this.contentIndex.get(word) || new Set();
resultIds = this.intersectSets(resultIds, wordIds);
}
return resultIds || new Set();
}
/**
* 搜索标签
*/
searchTags(tags) {
let resultIds = null;
for (const tag of tags) {
const tagIds = this.tagIndex.get(tag.toLowerCase()) || new Set();
if (resultIds === null) {
resultIds = new Set(tagIds);
}
else {
// 使用并集(OR 逻辑)
for (const id of tagIds) {
resultIds.add(id);
}
}
}
return resultIds || new Set();
}
/**
* 搜索元数据
*/
searchMetadata(metadata) {
let resultIds = null;
for (const [key, value] of Object.entries(metadata)) {
const metadataKey = `${key}:${String(value)}`;
const metadataIds = this.metadataIndex.get(metadataKey) || new Set();
resultIds = this.intersectSets(resultIds, metadataIds);
}
return resultIds || new Set();
}
/**
* 搜索日期范围
*/
searchDateRange(dateRange) {
let resultIds = null;
for (const [dateStr, ids] of this.dateIndex.entries()) {
const date = new Date(dateStr);
if (dateRange.from && date < new Date(dateRange.from))
continue;
if (dateRange.to && date > new Date(dateRange.to))
continue;
if (resultIds === null) {
resultIds = new Set(ids);
}
else {
for (const id of ids) {
resultIds.add(id);
}
}
}
return resultIds || new Set();
}
/**
* 集合交集操作
*/
intersectSets(set1, set2) {
if (set1 === null) {
return new Set(set2);
}
const result = new Set();
for (const item of set1) {
if (set2.has(item)) {
result.add(item);
}
}
return result;
}
}
//# sourceMappingURL=MemoryIndex.js.map