@ppagent/memory 0.1.4 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +1187 -0
- package/dist/index.d.ts +397 -137
- package/dist/index.js +1372 -853
- package/dist/provider.resolver-2KS2YYNV.js +616 -0
- package/llms.txt +150 -87
- package/package.json +19 -7
package/dist/index.d.ts
CHANGED
|
@@ -27,7 +27,7 @@ interface Paginated<T> {
|
|
|
27
27
|
* 多模态消息的单个内容块,与 OpenAI content part 对齐
|
|
28
28
|
*/
|
|
29
29
|
interface ContentPart {
|
|
30
|
-
type:
|
|
30
|
+
type: string;
|
|
31
31
|
/** type 为 "text" 时的文本内容 */
|
|
32
32
|
text?: string;
|
|
33
33
|
/** type 为 "image_url" 时的图片信息 */
|
|
@@ -39,6 +39,8 @@ interface ContentPart {
|
|
|
39
39
|
url: string;
|
|
40
40
|
name?: string;
|
|
41
41
|
};
|
|
42
|
+
/** 保留宿主框架自定义 content part,写入和回读时不丢字段。 */
|
|
43
|
+
[key: string]: unknown;
|
|
42
44
|
}
|
|
43
45
|
interface RawMessage {
|
|
44
46
|
messageId?: string;
|
|
@@ -57,6 +59,8 @@ interface RawMessage {
|
|
|
57
59
|
* 序列化后存入 LanceDB 的 parts 字段。
|
|
58
60
|
*/
|
|
59
61
|
parts?: ContentPart[];
|
|
62
|
+
/** 宿主框架的原始消息载荷;记忆框架仅透明保存和回读。 */
|
|
63
|
+
payload?: unknown;
|
|
60
64
|
usage?: number;
|
|
61
65
|
metadata?: Record<string, unknown>;
|
|
62
66
|
createdAt?: number;
|
|
@@ -72,6 +76,8 @@ interface StoredMessage {
|
|
|
72
76
|
content: string;
|
|
73
77
|
/** JSON.stringify(ContentPart[]),纯文本消息为 "[]" */
|
|
74
78
|
parts: string;
|
|
79
|
+
/** JSON.stringify(payload),未提供时为 undefined。 */
|
|
80
|
+
payload?: string;
|
|
75
81
|
usage: number;
|
|
76
82
|
metadata: string;
|
|
77
83
|
vector: number[];
|
|
@@ -84,9 +90,17 @@ interface Topic {
|
|
|
84
90
|
chatId: string;
|
|
85
91
|
/** 压缩时自动生成的主题标题(一句话),存量数据可能为空串 */
|
|
86
92
|
title: string;
|
|
87
|
-
|
|
93
|
+
/** 唯一的压缩正文。长度由内容重要性动态决定。 */
|
|
88
94
|
summary: string;
|
|
89
|
-
|
|
95
|
+
/** 压缩结果的 token 数;旧数据缺失时由本地 tokenizer 回填。 */
|
|
96
|
+
tokens: number;
|
|
97
|
+
/** 本 Topic 覆盖的首尾原始消息 id,便于同毫秒边界精确恢复。 */
|
|
98
|
+
startMessageId?: string;
|
|
99
|
+
endMessageId?: string;
|
|
100
|
+
/** @deprecated 仅用于读取尚未迁移的 0.3.x 数据。 */
|
|
101
|
+
detail?: string;
|
|
102
|
+
/** @deprecated 仅用于读取尚未迁移的 0.3.x 数据。 */
|
|
103
|
+
concise?: string;
|
|
90
104
|
startTime: number;
|
|
91
105
|
endTime: number;
|
|
92
106
|
createdAt: number;
|
|
@@ -100,8 +114,12 @@ interface Fact {
|
|
|
100
114
|
chatId: string;
|
|
101
115
|
sessionId: string;
|
|
102
116
|
userId: string;
|
|
117
|
+
/** 同一 level/owner 内用于 upsert 的稳定键;旧数据可能为空。 */
|
|
118
|
+
key?: string;
|
|
103
119
|
content: string;
|
|
104
120
|
createdAt: number;
|
|
121
|
+
/** 最近一次同 key 更新时刻;旧数据回落 createdAt。 */
|
|
122
|
+
updatedAt?: number;
|
|
105
123
|
}
|
|
106
124
|
interface EntityMeta {
|
|
107
125
|
messageId?: string;
|
|
@@ -179,9 +197,9 @@ interface UpdateEntityOptions {
|
|
|
179
197
|
interface CompressOutput {
|
|
180
198
|
/** 自动生成的主题标题(一句话) */
|
|
181
199
|
title: string;
|
|
182
|
-
detail: string;
|
|
183
200
|
summary: string;
|
|
184
|
-
|
|
201
|
+
/** 模型报告的摘要输出 token;缺失时由本地 tokenizer 计算。 */
|
|
202
|
+
tokens?: number;
|
|
185
203
|
entities: Array<{
|
|
186
204
|
name: string;
|
|
187
205
|
type: string;
|
|
@@ -198,10 +216,44 @@ interface CompressOutput {
|
|
|
198
216
|
interface SessionEntry {
|
|
199
217
|
messages: StoredMessage[];
|
|
200
218
|
totalTokens: number;
|
|
219
|
+
topics: Topic[];
|
|
220
|
+
topicTokens: number;
|
|
201
221
|
ids: {
|
|
202
222
|
chatId: string;
|
|
203
223
|
userId: string;
|
|
204
224
|
};
|
|
225
|
+
lastModelContextTokens?: number;
|
|
226
|
+
lastAccessAt: number;
|
|
227
|
+
}
|
|
228
|
+
/** getHistoryWindow 返回的原始消息;字段形态与 updateChat 输入保持一致。 */
|
|
229
|
+
interface MemoryRawMessage {
|
|
230
|
+
messageId: string;
|
|
231
|
+
talkerId: string;
|
|
232
|
+
chatId: string;
|
|
233
|
+
userId: string;
|
|
234
|
+
sessionId: string;
|
|
235
|
+
type: MessageType;
|
|
236
|
+
content: string;
|
|
237
|
+
parts?: ContentPart[];
|
|
238
|
+
payload?: unknown;
|
|
239
|
+
usage: number;
|
|
240
|
+
metadata?: Record<string, unknown>;
|
|
241
|
+
createdAt: number;
|
|
242
|
+
}
|
|
243
|
+
interface MemoryContextWindowUsage {
|
|
244
|
+
modelContextTokens: number;
|
|
245
|
+
usableContextTokens: number;
|
|
246
|
+
compressedTokenLimit: number;
|
|
247
|
+
compressedTokens: number;
|
|
248
|
+
rawTokenLimit: number;
|
|
249
|
+
rawTokens: number;
|
|
250
|
+
}
|
|
251
|
+
/** 固定预算的压缩记忆 + 近期未压缩原始消息。 */
|
|
252
|
+
interface MemoryContextWindow {
|
|
253
|
+
sessionId: string;
|
|
254
|
+
compressedContext: string;
|
|
255
|
+
recentMessages: MemoryRawMessage[];
|
|
256
|
+
usage: MemoryContextWindowUsage;
|
|
205
257
|
}
|
|
206
258
|
/** 是否为文档构建知识图谱:true/false 显式控制,"auto" 由内置 LLM 判定 */
|
|
207
259
|
type BuildGraphMode = boolean | "auto";
|
|
@@ -264,6 +316,8 @@ interface AddDocumentOptions {
|
|
|
264
316
|
userId?: string;
|
|
265
317
|
chatId?: string;
|
|
266
318
|
sessionId?: string;
|
|
319
|
+
/** 内容哈希去重范围;默认 session(兼容旧行为)。 */
|
|
320
|
+
scope?: SearchScope;
|
|
267
321
|
/** 不传则从首个 H1 / sourceName 推断 */
|
|
268
322
|
title?: string;
|
|
269
323
|
sourceName?: string;
|
|
@@ -305,7 +359,18 @@ interface KnowledgeSearchResult {
|
|
|
305
359
|
}
|
|
306
360
|
|
|
307
361
|
interface MemoryConfig {
|
|
362
|
+
/**
|
|
363
|
+
* 向量存储后端:
|
|
364
|
+
* - "auto"(默认):运行时探测 @lancedb/lancedb 原生绑定,可用则 lancedb,否则回退 sqlite
|
|
365
|
+
* (覆盖 Intel Mac / musl 等无预编译二进制的平台)。首次选定后写入数据目录 marker 固化,
|
|
366
|
+
* 避免环境变化导致静默换库(表现为「记忆丢失」)。
|
|
367
|
+
* - "lancedb" / "sqlite":显式指定。
|
|
368
|
+
* 注意:两个后端的数据文件互不相通,切换需自行迁移。
|
|
369
|
+
*/
|
|
370
|
+
provider?: "auto" | "lancedb" | "sqlite";
|
|
308
371
|
lancedbPath: string;
|
|
372
|
+
/** sqlite 后端的数据库文件路径(默认 lancedbPath 同级目录下的 memory.sqlite3) */
|
|
373
|
+
sqlitePath?: string;
|
|
309
374
|
grafeoPath: string;
|
|
310
375
|
embeddingBaseUrl: string;
|
|
311
376
|
embeddingApiKey: string;
|
|
@@ -322,16 +387,42 @@ interface MemoryConfig {
|
|
|
322
387
|
embeddingBatchSize?: number;
|
|
323
388
|
/** embedding 批次并发数(默认 2)。*/
|
|
324
389
|
embeddingConcurrency?: number;
|
|
390
|
+
/** 压缩 Topic 在历史窗口中的固定预算,默认 16K。 */
|
|
391
|
+
compressedContextTokenLimit?: number;
|
|
392
|
+
/** 模型上下文中允许历史记忆使用的比例,默认 0.75。 */
|
|
393
|
+
contextUsageRatio?: number;
|
|
394
|
+
/** 原始消息达到其可用预算的此比例时后台预压缩,默认 0.75。 */
|
|
395
|
+
precompressionRatio?: number;
|
|
396
|
+
/** 单次压缩目标占原始消息预算的比例,默认 0.5。 */
|
|
397
|
+
compressionBatchRatio?: number;
|
|
398
|
+
/** 单次压缩硬上限;0 表示只受 compressionBatchRatio 控制。 */
|
|
399
|
+
compressionBatchTokenLimit?: number;
|
|
400
|
+
/** 单条 Topic 摘要硬上限,实际长度由重要性决定,默认 2048。 */
|
|
401
|
+
topicSummaryMaxTokens?: number;
|
|
402
|
+
/** 未传 getHistoryWindow 模型窗口时使用,默认 256K。 */
|
|
403
|
+
defaultModelContextTokens?: number;
|
|
404
|
+
/** 冷启动最多恢复多久以前的压缩 Topic;0 表示永久。 */
|
|
405
|
+
maxHistoryAgeMs?: number;
|
|
406
|
+
/** 会话缓存空闲释放时间,默认 30 分钟;<=0 关闭。 */
|
|
407
|
+
sessionIdleTtlMs?: number;
|
|
408
|
+
/** 空闲会话扫描周期,默认 1 分钟。 */
|
|
409
|
+
sessionSweepIntervalMs?: number;
|
|
410
|
+
/** @deprecated 0.3.x 原始消息固定阈值;仅为配置兼容保留。 */
|
|
325
411
|
sessionTokenLimit?: number;
|
|
412
|
+
/** @deprecated 使用 compressedContextTokenLimit。 */
|
|
326
413
|
historyWindowTokenLimit?: number;
|
|
414
|
+
/** @deprecated 三级 Topic 窗口已移除。 */
|
|
327
415
|
topicRatio?: [number, number, number];
|
|
416
|
+
/** @deprecated 使用 topicSummaryMaxTokens。 */
|
|
328
417
|
detailMaxTokens?: number;
|
|
418
|
+
/** 文档摘要仍使用此限制;对话 Topic 使用 topicSummaryMaxTokens。 */
|
|
329
419
|
summaryMaxTokens?: number;
|
|
420
|
+
/** @deprecated 三级 Topic 窗口已移除。 */
|
|
330
421
|
conciseMaxTokens?: number;
|
|
331
422
|
maxConcurrentCompressions?: number;
|
|
332
423
|
entitySimilarityThreshold?: number;
|
|
333
424
|
defaultSearchLimit?: number;
|
|
334
|
-
/**
|
|
425
|
+
/** @deprecated 连续历史窗口不再按召回热度重排。 */
|
|
335
426
|
recallBoostMs?: number;
|
|
336
427
|
/** 切块策略,目前仅 "markdown-heading"(默认)*/
|
|
337
428
|
chunkStrategy?: "markdown-heading";
|
|
@@ -389,7 +480,122 @@ interface MemoryConfig {
|
|
|
389
480
|
interface ResolvedConfig extends Required<MemoryConfig> {
|
|
390
481
|
}
|
|
391
482
|
|
|
392
|
-
/**
|
|
483
|
+
/**
|
|
484
|
+
* 向量存储后端抽象层的类型定义。
|
|
485
|
+
*
|
|
486
|
+
* 设计原则:接口只表达「语义」(结果意味着什么),不表达「机制」(怎么算出来的)。
|
|
487
|
+
* - 混合检索(RRF 融合)、回退策略、业务重排等组合逻辑在共享域层 memory.store.ts 实现,
|
|
488
|
+
* provider 只需提供 vectorSearch / ftsSearch 两个检索原语,保证跨后端行为一致。
|
|
489
|
+
* - ANN、索引维护、存储压实等机制细节由各 provider 自行决定,接口仅以声明式
|
|
490
|
+
* IndexSpec 提示与 capabilities 能力声明的方式暴露。
|
|
491
|
+
* - 过滤条件为结构化对象(而非 SQL 字符串),各 provider 翻译为自己的方言,
|
|
492
|
+
* 从根上消除转义/注入问题。
|
|
493
|
+
*/
|
|
494
|
+
type FilterCondition =
|
|
495
|
+
/** 等值匹配 */
|
|
496
|
+
{
|
|
497
|
+
op: "eq";
|
|
498
|
+
field: string;
|
|
499
|
+
value: string | number;
|
|
500
|
+
}
|
|
501
|
+
/** 数值大于 */
|
|
502
|
+
| {
|
|
503
|
+
op: "gt";
|
|
504
|
+
field: string;
|
|
505
|
+
value: number;
|
|
506
|
+
}
|
|
507
|
+
/** 数值大于等于 */
|
|
508
|
+
| {
|
|
509
|
+
op: "gte";
|
|
510
|
+
field: string;
|
|
511
|
+
value: number;
|
|
512
|
+
}
|
|
513
|
+
/** 字段值属于集合。values 为空数组表示「不匹配任何行」 */
|
|
514
|
+
| {
|
|
515
|
+
op: "in";
|
|
516
|
+
field: string;
|
|
517
|
+
values: string[];
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* 匹配序列化为 JSON 字符串的 metadata 列中的键值对。
|
|
521
|
+
* 语义等同旧 LanceService.buildMetadataFilter 的 LIKE '%"key":value%' 模式:
|
|
522
|
+
* 仅适合标量值精确匹配,嵌套对象/含特殊字符的值不保证可靠。
|
|
523
|
+
*/
|
|
524
|
+
| {
|
|
525
|
+
op: "jsonContains";
|
|
526
|
+
field: string;
|
|
527
|
+
key: string;
|
|
528
|
+
value: string | number | boolean;
|
|
529
|
+
};
|
|
530
|
+
/** 多个条件为 AND 关系。空数组等同于不过滤。 */
|
|
531
|
+
type Filter = FilterCondition[];
|
|
532
|
+
type ColumnType =
|
|
533
|
+
/** UTF-8 文本 */
|
|
534
|
+
"text"
|
|
535
|
+
/** 32 位整数 */
|
|
536
|
+
| "int"
|
|
537
|
+
/** 64 位整数(毫秒时间戳等)。JS 侧统一以 number 读写 */
|
|
538
|
+
| "long"
|
|
539
|
+
/** 定长 float32 向量,维度由 TableDef.vectorDimension 决定 */
|
|
540
|
+
| "vector";
|
|
541
|
+
interface ColumnDef {
|
|
542
|
+
name: string;
|
|
543
|
+
type: ColumnType;
|
|
544
|
+
/** 默认 false。nullable 列用于 schema 演进的兼容(旧数据无此列) */
|
|
545
|
+
nullable?: boolean;
|
|
546
|
+
}
|
|
547
|
+
interface IndexSpec {
|
|
548
|
+
column: string;
|
|
549
|
+
/**
|
|
550
|
+
* - scalar:标量索引(btree 等价物),加速等值/范围过滤
|
|
551
|
+
* - fts:全文检索索引(BM25)
|
|
552
|
+
* - vector:向量检索加速提示。当前所有 provider 均为精确暴力扫描(ANN 暂不启用,
|
|
553
|
+
* 见 plans/vector-db-replacement-research.md 决议),该值仅作为将来启用 ANN 的声明位。
|
|
554
|
+
*/
|
|
555
|
+
kind: "scalar" | "fts" | "vector";
|
|
556
|
+
}
|
|
557
|
+
interface TableDef {
|
|
558
|
+
name: string;
|
|
559
|
+
columns: ColumnDef[];
|
|
560
|
+
/** 有 vector 列时必填 */
|
|
561
|
+
vectorDimension?: number;
|
|
562
|
+
indexes: IndexSpec[];
|
|
563
|
+
}
|
|
564
|
+
interface OrderBySpec {
|
|
565
|
+
column: string;
|
|
566
|
+
ascending: boolean;
|
|
567
|
+
}
|
|
568
|
+
interface QueryOptions {
|
|
569
|
+
filter?: Filter;
|
|
570
|
+
orderBy?: OrderBySpec[];
|
|
571
|
+
limit?: number;
|
|
572
|
+
/** 只取指定列(性能优化,如 trendDaily 只读 created_at)。省略取全部列 */
|
|
573
|
+
select?: string[];
|
|
574
|
+
}
|
|
575
|
+
interface VectorSearchOptions {
|
|
576
|
+
filter?: Filter;
|
|
577
|
+
limit: number;
|
|
578
|
+
}
|
|
579
|
+
interface FtsSearchOptions {
|
|
580
|
+
/** 参与全文匹配的列(须已建 fts 索引) */
|
|
581
|
+
columns: string[];
|
|
582
|
+
filter?: Filter;
|
|
583
|
+
limit: number;
|
|
584
|
+
}
|
|
585
|
+
/** 通用行类型:列名 → 值。vector 列为 number[],long 列为 number */
|
|
586
|
+
type Row = Record<string, unknown>;
|
|
587
|
+
/**
|
|
588
|
+
* 向量检索结果附带 _distance(L2 平方距离,越小越相近)。
|
|
589
|
+
* 各 provider 必须保持相同度量(L2),依赖距离阈值的上层逻辑才能跨后端一致。
|
|
590
|
+
*/
|
|
591
|
+
type ScoredRow = Row & {
|
|
592
|
+
_distance: number;
|
|
593
|
+
};
|
|
594
|
+
/** FTS 检索结果附带 _score(BM25 相关度,越大越相关;仅用于排序,绝对值跨后端无可比性) */
|
|
595
|
+
type FtsRow = Row & {
|
|
596
|
+
_score: number;
|
|
597
|
+
};
|
|
598
|
+
/** 单表压实结果。不同后端的语义映射:LanceDB=碎片合并+版本清理;SQLite=incremental vacuum 等 */
|
|
393
599
|
interface StorageOptimizeResult {
|
|
394
600
|
table: string;
|
|
395
601
|
fragmentsRemoved: number;
|
|
@@ -398,133 +604,46 @@ interface StorageOptimizeResult {
|
|
|
398
604
|
oldVersionsRemoved: number;
|
|
399
605
|
bytesRemoved: number;
|
|
400
606
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
*/
|
|
437
|
-
private _ensureTopicTitleColumn;
|
|
438
|
-
addMessages(messages: StoredMessage[]): Promise<void>;
|
|
439
|
-
addTopic(topic: Topic): Promise<void>;
|
|
440
|
-
updateTopicRecallCount(summaryId: string, count: number): Promise<void>;
|
|
441
|
-
getRecentTopics(chatId: string, userId: string, n1: number, n2: number, n3: number): Promise<{
|
|
442
|
-
detail: Topic[];
|
|
443
|
-
summary: Topic[];
|
|
444
|
-
concise: Topic[];
|
|
445
|
-
}>;
|
|
446
|
-
getMessagesSince(sessionId: string, since: number, limit?: number): Promise<StoredMessage[]>;
|
|
447
|
-
getLatestMessages(sessionId: string, limit: number): Promise<StoredMessage[]>;
|
|
448
|
-
/** 取某会话的全部消息(按 createdAt 升序),供管理面板分页切片使用 */
|
|
449
|
-
getAllMessagesBySession(sessionId: string): Promise<StoredMessage[]>;
|
|
450
|
-
searchMessages(vector: number[], filter?: string, limit?: number): Promise<Array<StoredMessage & {
|
|
451
|
-
_distance: number;
|
|
452
|
-
}>>;
|
|
453
|
-
hybridSearchMessages(query: string, vector: number[], filter?: string, limit?: number): Promise<StoredMessage[]>;
|
|
454
|
-
hybridSearchTopics(query: string, vector: number[], filter?: string, limit?: number): Promise<Topic[]>;
|
|
455
|
-
saveFact(fact: Fact): Promise<void>;
|
|
456
|
-
getAllFacts(): Promise<Fact[]>;
|
|
457
|
-
getAllSessionIds(): Promise<string[]>;
|
|
458
|
-
insertSession(session: Session): Promise<void>;
|
|
459
|
-
upsertSession(session: Session): Promise<void>;
|
|
460
|
-
getAllSessions(): Promise<Session[]>;
|
|
461
|
-
deleteSession(sessionId: string): Promise<void>;
|
|
462
|
-
/** 全量读取 topics(管理面板列表用,不做 recall 加权排序,按 endTime 倒序)*/
|
|
463
|
-
getAllTopics(): Promise<Topic[]>;
|
|
464
|
-
/** 删除单条 fact */
|
|
465
|
-
deleteFact(factId: string): Promise<void>;
|
|
466
|
-
/** 删除某会话下的全部消息(级联删除会话时使用)*/
|
|
467
|
-
deleteMessagesBySession(sessionId: string): Promise<void>;
|
|
468
|
-
/** 删除某会话下的全部 topics(级联删除会话时使用)*/
|
|
469
|
-
deleteTopicsBySession(sessionId: string): Promise<void>;
|
|
470
|
-
/** 各表行数统计(概览卡片用)*/
|
|
471
|
-
countAll(): Promise<{
|
|
472
|
-
sessions: number;
|
|
473
|
-
messages: number;
|
|
474
|
-
topics: number;
|
|
475
|
-
facts: number;
|
|
476
|
-
}>;
|
|
477
|
-
/**
|
|
478
|
-
* 按天聚合最近 days 天的活跃趋势(概览图表用)。
|
|
479
|
-
* 返回连续日期序列(含无数据的零值天),按本地日期分桶。
|
|
480
|
-
*/
|
|
481
|
-
trendDaily(days: number): Promise<{
|
|
482
|
-
date: string;
|
|
483
|
-
sessions: number;
|
|
484
|
-
messages: number;
|
|
485
|
-
facts: number;
|
|
486
|
-
}[]>;
|
|
487
|
-
addDocument(doc: Document): Promise<void>;
|
|
488
|
-
addChunks(chunks: Chunk[]): Promise<void>;
|
|
489
|
-
updateDocumentGraphFlag(docId: string, hasGraph: boolean): Promise<void>;
|
|
490
|
-
getDocument(docId: string): Promise<Document | null>;
|
|
491
|
-
/** 查找同域同 hash 的文档(去重用)*/
|
|
492
|
-
findDocumentByHash(contentHash: string, filter?: string): Promise<Document | null>;
|
|
493
|
-
/** 按域过滤返回 docId 列表(chunkRedundantIds=false 时用于 chunk 过滤)*/
|
|
494
|
-
getDocIdsByDomain(filter?: string): Promise<string[]>;
|
|
495
|
-
/** 文档级粗召回:对摘要向量做向量搜索,定位候选文档 */
|
|
496
|
-
searchDocuments(vector: number[], filter?: string, limit?: number): Promise<Array<Document & {
|
|
497
|
-
_distance: number;
|
|
498
|
-
}>>;
|
|
499
|
-
/** 知识片段混合检索(BM25 + 向量),失败回退纯向量 */
|
|
500
|
-
searchChunks(query: string, vector: number[], filter?: string, limit?: number): Promise<Chunk[]>;
|
|
501
|
-
deleteDocument(docId: string): Promise<void>;
|
|
502
|
-
deleteChunksByDoc(docId: string): Promise<void>;
|
|
503
|
-
/** 全量读取文档(管理面板用),按更新时间倒序 */
|
|
504
|
-
getAllDocuments(): Promise<Document[]>;
|
|
505
|
-
/** 知识库行数统计 */
|
|
506
|
-
countKnowledge(): Promise<{
|
|
507
|
-
documents: number;
|
|
508
|
-
chunks: number;
|
|
509
|
-
}>;
|
|
510
|
-
/**
|
|
511
|
-
* 根据 metadata 字段内容构建 SQL LIKE 过滤条件。
|
|
512
|
-
*
|
|
513
|
-
* metadata 以 JSON 字符串存储,此方法将键值对转换为 SQL LIKE 表达式,
|
|
514
|
-
* 可直接传给 searchMessages / hybridSearchTopics 的 filter 参数。
|
|
515
|
-
*
|
|
516
|
-
* 示例:buildMetadataFilter({ env: "prod", version: 2 })
|
|
517
|
-
* → `metadata LIKE '%"env":"prod"%' AND metadata LIKE '%"version":2%'`
|
|
518
|
-
*
|
|
519
|
-
* 注意:仅适合简单标量值(字符串、数字、布尔)的精确匹配。
|
|
520
|
-
* 复杂嵌套对象或含空格的 JSON 值可能无法可靠匹配。
|
|
521
|
-
*/
|
|
522
|
-
static buildMetadataFilter(conditions: Record<string, string | number | boolean>): string;
|
|
607
|
+
interface ProviderCapabilities {
|
|
608
|
+
/** 是否支持原生 FTS(BM25)。false 时域层混合检索自动降级为纯向量 */
|
|
609
|
+
fts: boolean;
|
|
610
|
+
/** 向量检索是否为 ANN 近似(false = 精确暴力)。当前所有 provider 均为 false */
|
|
611
|
+
ann: boolean;
|
|
612
|
+
/** optimize() 是否有实际效果(LanceDB 版本回收必需;SQLite 可选) */
|
|
613
|
+
optimize: boolean;
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* 向量存储后端需要实现的最小原语集合。
|
|
617
|
+
*
|
|
618
|
+
* 实现约定:
|
|
619
|
+
* - init 必须幂等:表已存在则打开并按 TableDef 补齐缺失的列(schema 演进)与索引;
|
|
620
|
+
* 不存在则创建。
|
|
621
|
+
* - 所有 filter 参数为结构化 Filter,provider 内部翻译为自己的方言并负责转义/参数化。
|
|
622
|
+
* - vectorSearch 使用 L2 距离,返回按 _distance 升序的前 limit 行。
|
|
623
|
+
* - ftsSearch 返回按 _score(BM25)降序的前 limit 行;查询词的分词由 provider 负责
|
|
624
|
+
* (中文场景 sqlite provider 使用 jieba;lancedb provider 使用 tantivy 内置分词)。
|
|
625
|
+
* - add/update/delete 需保证同一表内的派生结构(如 sqlite 的 FTS 影子表)事务一致。
|
|
626
|
+
*/
|
|
627
|
+
interface VectorStoreProvider {
|
|
628
|
+
/** provider 标识,用于日志与数据目录 marker */
|
|
629
|
+
readonly kind: string;
|
|
630
|
+
init(tables: TableDef[]): Promise<void>;
|
|
631
|
+
add(table: string, rows: Row[]): Promise<void>;
|
|
632
|
+
update(table: string, values: Row, filter: Filter): Promise<void>;
|
|
633
|
+
deleteWhere(table: string, filter: Filter): Promise<void>;
|
|
634
|
+
query(table: string, opts?: QueryOptions): Promise<Row[]>;
|
|
635
|
+
vectorSearch(table: string, vector: number[], opts: VectorSearchOptions): Promise<ScoredRow[]>;
|
|
636
|
+
ftsSearch(table: string, query: string, opts: FtsSearchOptions): Promise<FtsRow[]>;
|
|
637
|
+
count(table: string, filter?: Filter): Promise<number>;
|
|
638
|
+
/** 存储压实与历史版本回收。retentionMs:保留多久内的历史版本(不支持版本概念的后端可忽略) */
|
|
639
|
+
optimize(retentionMs: number): Promise<StorageOptimizeResult[]>;
|
|
640
|
+
capabilities(): ProviderCapabilities;
|
|
641
|
+
close(): Promise<void>;
|
|
523
642
|
}
|
|
524
643
|
|
|
525
644
|
declare class MemoryManager {
|
|
526
645
|
private readonly config;
|
|
527
|
-
private readonly
|
|
646
|
+
private readonly store;
|
|
528
647
|
private readonly grafeo;
|
|
529
648
|
private readonly embed;
|
|
530
649
|
private readonly llm;
|
|
@@ -534,7 +653,13 @@ declare class MemoryManager {
|
|
|
534
653
|
private readonly knowledgeManager;
|
|
535
654
|
private readonly sessionMap;
|
|
536
655
|
private optimizeTimer?;
|
|
656
|
+
private sessionSweepTimer?;
|
|
537
657
|
private optimizeRunning;
|
|
658
|
+
private optimizeTask?;
|
|
659
|
+
private destroyTask?;
|
|
660
|
+
private readonly hydration;
|
|
661
|
+
private readonly pendingWrites;
|
|
662
|
+
private warnedDefaultModelContext;
|
|
538
663
|
constructor(config: MemoryConfig);
|
|
539
664
|
init(): Promise<void>;
|
|
540
665
|
/** 后台压实的统一入口:防重入(上一轮未结束则跳过),失败仅告警不影响服务。*/
|
|
@@ -544,13 +669,17 @@ declare class MemoryManager {
|
|
|
544
669
|
* @param retentionMs 保留多久内的历史版本,默认取配置 optimizeVersionRetentionMs
|
|
545
670
|
*/
|
|
546
671
|
optimizeStorage(retentionMs?: number): Promise<StorageOptimizeResult[]>;
|
|
547
|
-
private
|
|
672
|
+
private ensureSessionHydrated;
|
|
673
|
+
private isSessionBusy;
|
|
674
|
+
private waitForPendingWrites;
|
|
675
|
+
private queueSessionWrite;
|
|
548
676
|
updateChat(messages: RawMessage[], opts?: UpdateChatOptions): Promise<void>;
|
|
677
|
+
private doUpdateChat;
|
|
549
678
|
flushChat(sessionId?: string, opts?: {
|
|
550
679
|
wait?: boolean;
|
|
551
680
|
waitGraph?: boolean;
|
|
552
681
|
}): Promise<void>;
|
|
553
|
-
updateFacts(content: string, level: FactLevel, userId: string, chatId: string, sessionId?: string): Promise<void>;
|
|
682
|
+
updateFacts(content: string, level: FactLevel, userId: string, chatId: string, sessionId?: string, key?: string): Promise<void>;
|
|
554
683
|
updateEntity(entities: Entity[], relations: Relation[], context?: UpdateEntityOptions): Promise<void>;
|
|
555
684
|
search(opts: SearchOptions): Promise<SearchResult[]>;
|
|
556
685
|
ask(opts: SearchOptions & {
|
|
@@ -566,8 +695,9 @@ declare class MemoryManager {
|
|
|
566
695
|
* 返回 user 级(userId) ∪ chat 级(chatId),按时间正序拼接。
|
|
567
696
|
*/
|
|
568
697
|
getFactsForContext(userId: string, chatId: string): Promise<string>;
|
|
569
|
-
getHistoryWindow(sessionId: string):
|
|
570
|
-
private
|
|
698
|
+
getHistoryWindow(sessionId: string, modelContextTokens?: number): Promise<MemoryContextWindow>;
|
|
699
|
+
private calculateWindowUsage;
|
|
700
|
+
private buildScopeFilter;
|
|
571
701
|
private deserializeSession;
|
|
572
702
|
private serializeSession;
|
|
573
703
|
getRecentMessages(sessionId: string, limit: number): Promise<StoredMessage[]>;
|
|
@@ -652,7 +782,7 @@ declare class MemoryManager {
|
|
|
652
782
|
/** 由 chatId 反查所属 userId:优先用会话表映射,兜底用 chat 级 fact 自身。 */
|
|
653
783
|
private resolveChatOwner;
|
|
654
784
|
/** 手动新增一条事实 */
|
|
655
|
-
addFact(content: string, level: FactLevel, userId: string, chatId: string, sessionId?: string): Promise<void>;
|
|
785
|
+
addFact(content: string, level: FactLevel, userId: string, chatId: string, sessionId?: string, key?: string): Promise<void>;
|
|
656
786
|
/** 删除单条事实,返回是否命中 */
|
|
657
787
|
deleteFact(factId: string): Promise<boolean>;
|
|
658
788
|
/**
|
|
@@ -703,9 +833,139 @@ declare class MemoryManager {
|
|
|
703
833
|
chatId?: string;
|
|
704
834
|
sessionId?: string;
|
|
705
835
|
} | undefined, page: PageParams): Promise<Paginated<Document>>;
|
|
706
|
-
destroy(): void
|
|
836
|
+
destroy(): Promise<void>;
|
|
707
837
|
}
|
|
708
838
|
|
|
839
|
+
interface MemoryMigrationReport {
|
|
840
|
+
provider: string;
|
|
841
|
+
topicsScanned: number;
|
|
842
|
+
topicsUpdated: number;
|
|
843
|
+
messagesScanned: number;
|
|
844
|
+
messagesUpdated: number;
|
|
845
|
+
factsScanned: number;
|
|
846
|
+
factsUpdated: number;
|
|
847
|
+
}
|
|
848
|
+
/**
|
|
849
|
+
* 记忆系统的存储域层:保持原 LanceService 的公开方法面,内部组合
|
|
850
|
+
* VectorStoreProvider 的通用原语实现。业务逻辑(混合检索融合、话题回退、
|
|
851
|
+
* recall 加权重排)全部在此层,各后端 provider 不感知。
|
|
852
|
+
*/
|
|
853
|
+
declare class MemoryStore {
|
|
854
|
+
private readonly config;
|
|
855
|
+
private provider;
|
|
856
|
+
private readonly providerOverride?;
|
|
857
|
+
/** provider 省略时在 init() 阶段经 provider.resolver 自动探测创建(测试可显式注入) */
|
|
858
|
+
constructor(config: ResolvedConfig, provider?: VectorStoreProvider);
|
|
859
|
+
/** 当前后端 provider 标识(日志/诊断用) */
|
|
860
|
+
get providerKind(): string;
|
|
861
|
+
init(): Promise<void>;
|
|
862
|
+
close(): Promise<void>;
|
|
863
|
+
/**
|
|
864
|
+
* 存储压实(碎片合并 + 历史版本清理)。
|
|
865
|
+
* LanceDB 后端长期运行必须定期执行;SQLite 后端为可选的空间回收。
|
|
866
|
+
*/
|
|
867
|
+
optimizeStorage(retentionMs?: number): Promise<StorageOptimizeResult[]>;
|
|
868
|
+
addMessages(messages: StoredMessage[]): Promise<void>;
|
|
869
|
+
/** 0.3.x → 0.4.x 数据回填;幂等,不调用 LLM、不删除原始消息。 */
|
|
870
|
+
migrateLegacyData(): Promise<MemoryMigrationReport>;
|
|
871
|
+
/** message_id 稳定时更新原行,否则新增;用于流式 assistant 消息最终态覆盖。 */
|
|
872
|
+
upsertMessages(messages: StoredMessage[]): Promise<void>;
|
|
873
|
+
getMessagesSince(sessionId: string, since: number, limit?: number): Promise<StoredMessage[]>;
|
|
874
|
+
getMessagesAfterBoundary(sessionId: string, endTime: number, endMessageId?: string): Promise<StoredMessage[]>;
|
|
875
|
+
getLatestMessages(sessionId: string, limit: number): Promise<StoredMessage[]>;
|
|
876
|
+
/** 取某会话的全部消息(按 createdAt 升序),供管理面板分页切片使用 */
|
|
877
|
+
getAllMessagesBySession(sessionId: string): Promise<StoredMessage[]>;
|
|
878
|
+
searchMessages(vector: number[], filter?: Filter, limit?: number): Promise<Array<StoredMessage & {
|
|
879
|
+
_distance: number;
|
|
880
|
+
}>>;
|
|
881
|
+
hybridSearchMessages(query: string, vector: number[], filter?: Filter, limit?: number): Promise<StoredMessage[]>;
|
|
882
|
+
hybridSearchTopics(query: string, vector: number[], filter?: Filter, limit?: number): Promise<Topic[]>;
|
|
883
|
+
/**
|
|
884
|
+
* 通用混合检索:FTS(BM25)与向量两路各取 limit*HYBRID_OVERFETCH 候选,RRF 融合。
|
|
885
|
+
* FTS 不可用(后端不支持或查询失败)时降级为纯向量。返回融合后的完整候选序列(未截断)。
|
|
886
|
+
*/
|
|
887
|
+
private hybridSearch;
|
|
888
|
+
private keyColumnOf;
|
|
889
|
+
addTopic(topic: Topic): Promise<void>;
|
|
890
|
+
updateTopic(topic: Topic): Promise<void>;
|
|
891
|
+
updateTopicRecallCount(summaryId: string, count: number): Promise<void>;
|
|
892
|
+
incrementTopicRecallCounts(topics: Topic[]): Promise<void>;
|
|
893
|
+
getTopicsBySession(sessionId: string, since?: number): Promise<Topic[]>;
|
|
894
|
+
getRecentTopics(chatId: string, userId: string, n1: number, n2: number, n3: number): Promise<{
|
|
895
|
+
detail: Topic[];
|
|
896
|
+
summary: Topic[];
|
|
897
|
+
concise: Topic[];
|
|
898
|
+
}>;
|
|
899
|
+
/** 全量读取 topics(管理面板列表用,不做 recall 加权排序,按 endTime 倒序)*/
|
|
900
|
+
getAllTopics(): Promise<Topic[]>;
|
|
901
|
+
deleteTopicsBySession(sessionId: string): Promise<void>;
|
|
902
|
+
deleteTopicsByIds(summaryIds: string[]): Promise<void>;
|
|
903
|
+
saveFact(fact: Fact): Promise<void>;
|
|
904
|
+
updateFact(fact: Fact): Promise<void>;
|
|
905
|
+
getAllFacts(): Promise<Fact[]>;
|
|
906
|
+
/** 删除单条 fact */
|
|
907
|
+
deleteFact(factId: string): Promise<void>;
|
|
908
|
+
getAllSessionIds(): Promise<string[]>;
|
|
909
|
+
insertSession(session: Session): Promise<void>;
|
|
910
|
+
upsertSession(session: Session): Promise<void>;
|
|
911
|
+
getAllSessions(): Promise<Session[]>;
|
|
912
|
+
deleteSession(sessionId: string): Promise<void>;
|
|
913
|
+
/** 删除某会话下的全部消息(级联删除会话时使用)*/
|
|
914
|
+
deleteMessagesBySession(sessionId: string): Promise<void>;
|
|
915
|
+
/** 各表行数统计(概览卡片用)*/
|
|
916
|
+
countAll(): Promise<{
|
|
917
|
+
sessions: number;
|
|
918
|
+
messages: number;
|
|
919
|
+
topics: number;
|
|
920
|
+
facts: number;
|
|
921
|
+
}>;
|
|
922
|
+
/**
|
|
923
|
+
* 按天聚合最近 days 天的活跃趋势(概览图表用)。
|
|
924
|
+
* 返回连续日期序列(含无数据的零值天),按本地日期分桶。
|
|
925
|
+
*/
|
|
926
|
+
trendDaily(days: number): Promise<{
|
|
927
|
+
date: string;
|
|
928
|
+
sessions: number;
|
|
929
|
+
messages: number;
|
|
930
|
+
facts: number;
|
|
931
|
+
}[]>;
|
|
932
|
+
addDocument(doc: Document): Promise<void>;
|
|
933
|
+
addChunks(chunks: Chunk[]): Promise<void>;
|
|
934
|
+
updateDocumentGraphFlag(docId: string, hasGraph: boolean): Promise<void>;
|
|
935
|
+
getDocument(docId: string): Promise<Document | null>;
|
|
936
|
+
/** 查找同域同 hash 的文档(去重用)*/
|
|
937
|
+
findDocumentByHash(contentHash: string, filter?: Filter): Promise<Document | null>;
|
|
938
|
+
/** 按域过滤返回 docId 列表(chunkRedundantIds=false 时用于 chunk 过滤)*/
|
|
939
|
+
getDocIdsByDomain(filter?: Filter): Promise<string[]>;
|
|
940
|
+
/** 文档级粗召回:对摘要向量做向量搜索,定位候选文档 */
|
|
941
|
+
searchDocuments(vector: number[], filter?: Filter, limit?: number): Promise<Array<Document & {
|
|
942
|
+
_distance: number;
|
|
943
|
+
}>>;
|
|
944
|
+
/** 知识片段混合检索(BM25 + 向量),失败回退纯向量 */
|
|
945
|
+
searchChunks(query: string, vector: number[], filter?: Filter, limit?: number): Promise<Chunk[]>;
|
|
946
|
+
deleteDocument(docId: string): Promise<void>;
|
|
947
|
+
deleteChunksByDoc(docId: string): Promise<void>;
|
|
948
|
+
/** 全量读取文档(管理面板用),按更新时间倒序 */
|
|
949
|
+
getAllDocuments(): Promise<Document[]>;
|
|
950
|
+
/** 知识库行数统计 */
|
|
951
|
+
countKnowledge(): Promise<{
|
|
952
|
+
documents: number;
|
|
953
|
+
chunks: number;
|
|
954
|
+
}>;
|
|
955
|
+
/**
|
|
956
|
+
* 根据 metadata 字段内容构建结构化过滤条件。
|
|
957
|
+
*
|
|
958
|
+
* metadata 以 JSON 字符串存储,此方法将键值对转换为 jsonContains 条件,
|
|
959
|
+
* 可直接传给 searchMessages / hybridSearchTopics 的 filter 参数。
|
|
960
|
+
*
|
|
961
|
+
* 注意:仅适合简单标量值(字符串、数字、布尔)的精确匹配。
|
|
962
|
+
* 复杂嵌套对象或含空格的 JSON 值可能无法可靠匹配。
|
|
963
|
+
*/
|
|
964
|
+
static buildMetadataFilter(conditions: Record<string, string | number | boolean>): Filter;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
type ProviderKind = "lancedb" | "sqlite";
|
|
968
|
+
|
|
709
969
|
declare const DEFAULT_NODE_TYPES: readonly ["Person", "Group", "Organization", "Project", "Task", "Decision", "Plan", "Event", "Product", "Technology", "Data", "Document", "Topic", "Concept", "Preference", "Habit", "Goal", "Skill", "Attribute", "Value", "Status", "Time", "Location", "Resource", "Relationship"];
|
|
710
970
|
declare const DEFAULT_RELATION_TYPES: readonly ["is_a", "part_of", "belongs_to", "contains", "has_member", "mentioned_in", "refers_to", "same_as", "alias_of", "related_to", "associated_with", "uses", "creates", "updates", "buys", "owns", "consumes", "works_on", "prefers", "likes", "dislikes", "interested_in", "favorite", "plans", "decides", "habit_of", "tends_to", "avoids", "skilled_in", "learning", "knows", "friends_with", "married_to", "parent_of", "child_of", "lives_with", "depends_on", "built_with", "integrates_with", "deployed_on", "inputs", "outputs", "trained_on", "predicts", "happens_at", "started_at", "ended_at", "affects", "causes", "leads_to", "improves", "reduces", "assigned_to", "executed_by", "blocks", "completes", "describes", "explains", "references"];
|
|
711
971
|
type NodeType = (typeof DEFAULT_NODE_TYPES)[number];
|
|
@@ -714,4 +974,4 @@ type RelationType = (typeof DEFAULT_RELATION_TYPES)[number];
|
|
|
714
974
|
declare const KIND_CONVERSATION = "conversation";
|
|
715
975
|
declare const KIND_KNOWLEDGE = "knowledge";
|
|
716
976
|
|
|
717
|
-
export { type AddDocumentOptions, type BuildGraphMode, type Chunk, type ChunkHit, type ChunkPiece, type CompressOutput, type ContentPart, DEFAULT_NODE_TYPES, DEFAULT_RELATION_TYPES, type Document, type DomainIds, type Entity, type EntityMeta, type Fact, type FactLevel, KIND_CONVERSATION, KIND_KNOWLEDGE, type KnowledgeSearchOptions, type KnowledgeSearchResult,
|
|
977
|
+
export { type AddDocumentOptions, type BuildGraphMode, type Chunk, type ChunkHit, type ChunkPiece, type CompressOutput, type ContentPart, DEFAULT_NODE_TYPES, DEFAULT_RELATION_TYPES, type Document, type DomainIds, type Entity, type EntityMeta, type Fact, type FactLevel, type Filter, type FilterCondition, KIND_CONVERSATION, KIND_KNOWLEDGE, type KnowledgeSearchOptions, type KnowledgeSearchResult, type MemoryConfig, type MemoryContextWindow, type MemoryContextWindowUsage, MemoryManager, type MemoryMigrationReport, type MemoryRawMessage, MemoryStore, type MessageType, type NodeType, type PageParams, type Paginated, type ProviderCapabilities, type ProviderKind, type RawMessage, type Relation, type RelationType, type SearchMode, type SearchOptions, type SearchResult, type SearchScope, type Session, type SessionEntry, type SessionSearchOptions, type SessionView, type StorageOptimizeResult, type StoredMessage, type Topic, type UpdateChatOptions, type UpdateEntityOptions, type UpdateSessionOptions, type VectorStoreProvider };
|