@cogitator-ai/memory 0.9.1 → 0.11.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/README.md +207 -90
- package/dist/adapters/postgres.d.ts +1 -0
- package/dist/adapters/postgres.d.ts.map +1 -1
- package/dist/adapters/postgres.js +78 -38
- package/dist/adapters/postgres.js.map +1 -1
- package/dist/adapters/qdrant.d.ts.map +1 -1
- package/dist/adapters/qdrant.js +16 -2
- package/dist/adapters/qdrant.js.map +1 -1
- package/dist/adapters/sqlite.d.ts +1 -0
- package/dist/adapters/sqlite.d.ts.map +1 -1
- package/dist/adapters/sqlite.js +17 -16
- package/dist/adapters/sqlite.js.map +1 -1
- package/dist/compaction.d.ts +14 -1
- package/dist/compaction.d.ts.map +1 -1
- package/dist/compaction.js +4 -1
- package/dist/compaction.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/knowledge-graph/entity-extractor.d.ts +24 -11
- package/dist/knowledge-graph/entity-extractor.d.ts.map +1 -1
- package/dist/knowledge-graph/entity-extractor.js +15 -3
- package/dist/knowledge-graph/entity-extractor.js.map +1 -1
- package/dist/knowledge-graph/graph-adapter.d.ts +1 -0
- package/dist/knowledge-graph/graph-adapter.d.ts.map +1 -1
- package/dist/knowledge-graph/graph-adapter.js +470 -448
- package/dist/knowledge-graph/graph-adapter.js.map +1 -1
- package/dist/knowledge-graph/sqlite-graph-adapter.d.ts +1 -0
- package/dist/knowledge-graph/sqlite-graph-adapter.d.ts.map +1 -1
- package/dist/knowledge-graph/sqlite-graph-adapter.js +459 -435
- package/dist/knowledge-graph/sqlite-graph-adapter.js.map +1 -1
- package/dist/result.d.ts +11 -0
- package/dist/result.d.ts.map +1 -0
- package/dist/result.js +14 -0
- package/dist/result.js.map +1 -0
- package/dist/schema.d.ts +4 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +2 -0
- package/dist/schema.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -15,6 +15,8 @@ pnpm add mongodb # For MongoDB adapter
|
|
|
15
15
|
pnpm add @qdrant/js-client-rest # For Qdrant embedding adapter
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
+
With `@cogitator-ai/core` you usually configure memory on the runtime (`new Cogitator({ memory: { adapter: 'postgres', postgres: { ... } } })`) and read it with `await cog.getMemory()`; the adapters below are for direct use. Website docs: [Memory](https://cogitator.app/docs/memory), [Adapters](https://cogitator.app/docs/memory/adapters), [Embeddings](https://cogitator.app/docs/memory/embeddings), [Hybrid Search](https://cogitator.app/docs/memory/hybrid-search), [Knowledge Graphs](https://cogitator.app/docs/memory/knowledge-graphs).
|
|
19
|
+
|
|
18
20
|
## Features
|
|
19
21
|
|
|
20
22
|
- **Multiple Adapters** - In-memory, Redis (standalone + cluster), PostgreSQL with pgvector, SQLite, MongoDB, Qdrant
|
|
@@ -24,10 +26,10 @@ pnpm add @qdrant/js-client-rest # For Qdrant embedding adapter
|
|
|
24
26
|
- **Context Builder** - Token-aware context with `recent`, `relevant` (embedding-ranked) and `hybrid` strategies
|
|
25
27
|
- **Scoped Semantic Memory** - Embeddings tagged with `metadata.agentId` / `metadata.threadId` never leak to other agents
|
|
26
28
|
- **Sessions & Compaction** - `SessionManager` for channel sessions, `CompactionService` for summarizing long histories
|
|
27
|
-
- **Embedding Services** - OpenAI and
|
|
29
|
+
- **Embedding Services** - OpenAI, Ollama and Google embedding integration
|
|
28
30
|
- **Semantic Search** - Vector similarity search with pgvector
|
|
29
31
|
- **Hybrid Search** - BM25 + Vector with Reciprocal Rank Fusion
|
|
30
|
-
- **Facts Storage** - Store and retrieve agent knowledge
|
|
32
|
+
- **Facts Storage** - Store and retrieve agent knowledge (`FactAdapter` on PostgreSQL, `CoreFactsStore` on SQLite)
|
|
31
33
|
- **Knowledge Graph** - Entity-relationship memory with multi-hop traversal
|
|
32
34
|
- **Zod Schemas** - Type-safe configuration validation
|
|
33
35
|
|
|
@@ -36,22 +38,23 @@ pnpm add @qdrant/js-client-rest # For Qdrant embedding adapter
|
|
|
36
38
|
## Quick Start
|
|
37
39
|
|
|
38
40
|
```typescript
|
|
39
|
-
import { InMemoryAdapter, ContextBuilder } from '@cogitator-ai/memory';
|
|
41
|
+
import { InMemoryAdapter, ContextBuilder, unwrap } from '@cogitator-ai/memory';
|
|
40
42
|
|
|
41
43
|
const memory = new InMemoryAdapter();
|
|
42
44
|
await memory.connect();
|
|
43
45
|
|
|
44
|
-
const
|
|
45
|
-
const thread = threadResult.data!;
|
|
46
|
+
const thread = unwrap(await memory.createThread('agent-1', { topic: 'greeting' }));
|
|
46
47
|
|
|
47
48
|
await memory.addEntry({
|
|
48
49
|
threadId: thread.id,
|
|
49
50
|
message: { role: 'user', content: 'Hello!' },
|
|
51
|
+
tokenCount: 2,
|
|
50
52
|
});
|
|
51
53
|
|
|
52
54
|
await memory.addEntry({
|
|
53
55
|
threadId: thread.id,
|
|
54
56
|
message: { role: 'assistant', content: 'Hi there!' },
|
|
57
|
+
tokenCount: 3,
|
|
55
58
|
});
|
|
56
59
|
|
|
57
60
|
const builder = new ContextBuilder(
|
|
@@ -68,6 +71,17 @@ const context = await builder.build({
|
|
|
68
71
|
console.log(context.messages);
|
|
69
72
|
```
|
|
70
73
|
|
|
74
|
+
Adapter calls return a `MemoryResult` — `{ success: true, data }` or `{ success: false, error }` — instead of throwing. `unwrap(result)` returns the data or throws an `Error` with the adapter's message; check `result.success` yourself where a failure is expected:
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
const result = await memory.getThread('thread_123');
|
|
78
|
+
if (!result.success) {
|
|
79
|
+
console.error('Memory unavailable:', result.error);
|
|
80
|
+
} else if (result.data) {
|
|
81
|
+
console.log(result.data.metadata);
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
71
85
|
---
|
|
72
86
|
|
|
73
87
|
## Memory Adapters
|
|
@@ -130,9 +144,11 @@ import { SQLiteAdapter } from '@cogitator-ai/memory';
|
|
|
130
144
|
|
|
131
145
|
const memory = new SQLiteAdapter({
|
|
132
146
|
provider: 'sqlite',
|
|
133
|
-
path: './cogitator.db',
|
|
147
|
+
path: './cogitator.db', // ':memory:' for an in-memory database
|
|
134
148
|
walMode: true,
|
|
135
149
|
});
|
|
150
|
+
|
|
151
|
+
await memory.connect();
|
|
136
152
|
```
|
|
137
153
|
|
|
138
154
|
### MongoDB Adapter
|
|
@@ -145,6 +161,8 @@ const memory = new MongoDBAdapter({
|
|
|
145
161
|
uri: 'mongodb://localhost:27017',
|
|
146
162
|
database: 'cogitator',
|
|
147
163
|
});
|
|
164
|
+
|
|
165
|
+
await memory.connect();
|
|
148
166
|
```
|
|
149
167
|
|
|
150
168
|
### Qdrant Adapter (Embedding)
|
|
@@ -158,8 +176,12 @@ const embeddings = new QdrantAdapter({
|
|
|
158
176
|
collection: 'cogitator',
|
|
159
177
|
dimensions: 1536,
|
|
160
178
|
});
|
|
179
|
+
|
|
180
|
+
await embeddings.connect();
|
|
161
181
|
```
|
|
162
182
|
|
|
183
|
+
`QdrantAdapter` is an `EmbeddingAdapter` (store and search vectors), not a thread store; pair it with one of the adapters above. Points are stored under a deterministic UUID derived from the embedding id (Qdrant accepts only integer and UUID point ids); the `emb_…` id stays in `payload.embeddingId` and is what `search` returns.
|
|
184
|
+
|
|
163
185
|
### Factory Function
|
|
164
186
|
|
|
165
187
|
```typescript
|
|
@@ -186,8 +208,12 @@ const qdrant = await createEmbeddingAdapter({
|
|
|
186
208
|
provider: 'qdrant',
|
|
187
209
|
dimensions: 1536,
|
|
188
210
|
});
|
|
211
|
+
|
|
212
|
+
await postgres.connect(); // the factories create adapters; connect them before use
|
|
189
213
|
```
|
|
190
214
|
|
|
215
|
+
`createMemoryAdapter` loads the adapter's driver lazily, so only the drivers you use need to be installed.
|
|
216
|
+
|
|
191
217
|
---
|
|
192
218
|
|
|
193
219
|
## MemoryAdapter Interface
|
|
@@ -219,13 +245,14 @@ interface MemoryAdapter {
|
|
|
219
245
|
`createThread(agentId, metadata, threadId)` with an existing `threadId` is an upsert: entries and `createdAt` are kept and only the metadata is updated, so it is safe to call on every run.
|
|
220
246
|
|
|
221
247
|
```typescript
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
248
|
+
const thread = unwrap(
|
|
249
|
+
await memory.createThread('agent-1', {
|
|
250
|
+
topic: 'support',
|
|
251
|
+
user: 'user-123',
|
|
252
|
+
})
|
|
253
|
+
);
|
|
227
254
|
|
|
228
|
-
const
|
|
255
|
+
const found = unwrap(await memory.getThread(thread.id)); // Thread | null
|
|
229
256
|
|
|
230
257
|
await memory.updateThread(thread.id, {
|
|
231
258
|
resolved: true,
|
|
@@ -237,21 +264,26 @@ await memory.deleteThread(thread.id);
|
|
|
237
264
|
### Entry Operations
|
|
238
265
|
|
|
239
266
|
```typescript
|
|
240
|
-
const entry =
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
267
|
+
const entry = unwrap(
|
|
268
|
+
await memory.addEntry({
|
|
269
|
+
threadId: thread.id,
|
|
270
|
+
message: { role: 'user', content: 'Hello' },
|
|
271
|
+
tokenCount: 10,
|
|
272
|
+
})
|
|
273
|
+
);
|
|
245
274
|
|
|
246
|
-
const entries =
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
275
|
+
const entries = unwrap(
|
|
276
|
+
await memory.getEntries({
|
|
277
|
+
threadId: thread.id,
|
|
278
|
+
limit: 50, // the most recent 50, oldest first
|
|
279
|
+
includeToolCalls: true,
|
|
280
|
+
// before / after: Date bounds
|
|
281
|
+
})
|
|
282
|
+
);
|
|
251
283
|
|
|
252
|
-
const single = await memory.getEntry(entry.
|
|
284
|
+
const single = unwrap(await memory.getEntry(entry.id));
|
|
253
285
|
|
|
254
|
-
await memory.deleteEntry(entry.
|
|
286
|
+
await memory.deleteEntry(entry.id);
|
|
255
287
|
|
|
256
288
|
await memory.clearThread(thread.id);
|
|
257
289
|
```
|
|
@@ -272,6 +304,8 @@ interface ContextBuilderConfig {
|
|
|
272
304
|
includeSystemPrompt?: boolean;
|
|
273
305
|
includeFacts?: boolean;
|
|
274
306
|
includeSemanticContext?: boolean;
|
|
307
|
+
includeGraphContext?: boolean;
|
|
308
|
+
graphContextOptions?: GraphContextOptions;
|
|
275
309
|
}
|
|
276
310
|
```
|
|
277
311
|
|
|
@@ -345,6 +379,7 @@ interface BuiltContext {
|
|
|
345
379
|
messages: Message[];
|
|
346
380
|
facts: Fact[];
|
|
347
381
|
semanticResults: (Embedding & { score: number })[];
|
|
382
|
+
graphContext?: GraphContext; // with includeGraphContext and a graph adapter
|
|
348
383
|
tokenCount: number;
|
|
349
384
|
truncated: boolean;
|
|
350
385
|
metadata: {
|
|
@@ -363,12 +398,26 @@ interface BuiltContext {
|
|
|
363
398
|
`SessionManager` maps channel conversations (user + channel + agent) onto memory threads. `CompactionService` replaces old history with an LLM summary placed before the most recent messages.
|
|
364
399
|
|
|
365
400
|
```typescript
|
|
401
|
+
import { createLLMBackend } from '@cogitator-ai/core';
|
|
366
402
|
import { InMemoryAdapter, SessionManager, CompactionService } from '@cogitator-ai/memory';
|
|
367
403
|
|
|
368
404
|
const memory = new InMemoryAdapter();
|
|
405
|
+
const llm = createLLMBackend('google', {
|
|
406
|
+
providers: { google: { apiKey: process.env.GOOGLE_API_KEY! } },
|
|
407
|
+
});
|
|
408
|
+
|
|
369
409
|
const compaction = new CompactionService({
|
|
370
410
|
adapter: memory,
|
|
371
|
-
summarize: async (messages
|
|
411
|
+
summarize: async (messages, { model, prompt } = {}) => {
|
|
412
|
+
const response = await llm.chat({
|
|
413
|
+
model: model ?? 'gemini-3.5-flash-lite',
|
|
414
|
+
messages: [
|
|
415
|
+
{ role: 'system', content: prompt ?? 'Summarize this conversation in a few sentences.' },
|
|
416
|
+
...messages,
|
|
417
|
+
],
|
|
418
|
+
});
|
|
419
|
+
return response.content;
|
|
420
|
+
},
|
|
372
421
|
});
|
|
373
422
|
const sessions = new SessionManager(memory, { compaction });
|
|
374
423
|
|
|
@@ -382,10 +431,36 @@ const session = await sessions.getOrCreate({
|
|
|
382
431
|
const all = await sessions.list();
|
|
383
432
|
const mine = await sessions.list({ userId: 'user-1', status: 'active', limit: 20 });
|
|
384
433
|
|
|
385
|
-
await sessions.compact(session.id, {
|
|
434
|
+
await sessions.compact(session.id, {
|
|
435
|
+
strategy: 'summary',
|
|
436
|
+
threshold: 8000,
|
|
437
|
+
keepRecent: 10,
|
|
438
|
+
summaryModel: 'gemini-3.5-flash',
|
|
439
|
+
summaryPrompt: 'Keep names, decisions and open questions.',
|
|
440
|
+
});
|
|
386
441
|
```
|
|
387
442
|
|
|
388
|
-
`list()` works with or without a `userId` filter (sessions are tracked in an index thread). `compact()` requires the `compaction` option; without it use `CompactionService` directly.
|
|
443
|
+
`list()` works with or without a `userId` filter (sessions are tracked in an index thread). `compact()` requires the `compaction` option; without it use `CompactionService` directly. The summarizer (`SummarizeFn`) is called as `summarize(messages, options)`, where `options` is a `SummarizeOptions` `{ model?, prompt? }` filled from the `summaryModel` / `summaryPrompt` of the compaction config.
|
|
444
|
+
|
|
445
|
+
---
|
|
446
|
+
|
|
447
|
+
## Core Facts
|
|
448
|
+
|
|
449
|
+
`CoreFactsStore` keeps a small set of key/value facts about the user in SQLite (with history), formatted for a system prompt:
|
|
450
|
+
|
|
451
|
+
```typescript
|
|
452
|
+
import { CoreFactsStore } from '@cogitator-ai/memory';
|
|
453
|
+
|
|
454
|
+
const facts = new CoreFactsStore({ path: './facts.db' }); // or { db } to share a better-sqlite3 database
|
|
455
|
+
await facts.initialize();
|
|
456
|
+
|
|
457
|
+
await facts.set('name', 'Alice');
|
|
458
|
+
await facts.get('name'); // 'Alice'
|
|
459
|
+
await facts.getAll(); // { name: 'Alice' }
|
|
460
|
+
await facts.getHistory('name'); // [{ value, setAt }]
|
|
461
|
+
const prompt = await facts.formatForPrompt();
|
|
462
|
+
await facts.close();
|
|
463
|
+
```
|
|
389
464
|
|
|
390
465
|
---
|
|
391
466
|
|
|
@@ -424,10 +499,12 @@ import { OpenAIEmbeddingService, createEmbeddingService } from '@cogitator-ai/me
|
|
|
424
499
|
|
|
425
500
|
const embeddings = new OpenAIEmbeddingService({
|
|
426
501
|
apiKey: process.env.OPENAI_API_KEY!,
|
|
427
|
-
model: 'text-embedding-3-small',
|
|
502
|
+
model: 'text-embedding-3-small', // default
|
|
503
|
+
dimensions: 512, // optional, text-embedding-3-* only
|
|
428
504
|
});
|
|
429
505
|
|
|
430
|
-
|
|
506
|
+
// or through the factory
|
|
507
|
+
const viaFactory = createEmbeddingService({
|
|
431
508
|
provider: 'openai',
|
|
432
509
|
apiKey: process.env.OPENAI_API_KEY!,
|
|
433
510
|
});
|
|
@@ -447,7 +524,7 @@ const embeddings = new OllamaEmbeddingService({
|
|
|
447
524
|
baseUrl: 'http://localhost:11434',
|
|
448
525
|
});
|
|
449
526
|
|
|
450
|
-
const
|
|
527
|
+
const viaFactory = createEmbeddingService({
|
|
451
528
|
provider: 'ollama',
|
|
452
529
|
model: 'nomic-embed-text',
|
|
453
530
|
});
|
|
@@ -466,7 +543,7 @@ const embeddings = new GoogleEmbeddingService({
|
|
|
466
543
|
dimensions: 768,
|
|
467
544
|
});
|
|
468
545
|
|
|
469
|
-
const
|
|
546
|
+
const viaFactory = createEmbeddingService({
|
|
470
547
|
provider: 'google',
|
|
471
548
|
apiKey: process.env.GOOGLE_API_KEY!,
|
|
472
549
|
});
|
|
@@ -529,15 +606,15 @@ const hybridResults = await search.search({
|
|
|
529
606
|
});
|
|
530
607
|
|
|
531
608
|
// Results include both scores
|
|
532
|
-
|
|
609
|
+
for (const result of unwrap(hybridResults)) {
|
|
533
610
|
console.log(`${result.content} — score: ${result.score}`);
|
|
534
611
|
console.log(` vector: ${result.vectorScore}, keyword: ${result.keywordScore}`);
|
|
535
|
-
}
|
|
612
|
+
}
|
|
536
613
|
```
|
|
537
614
|
|
|
538
615
|
### Document Indexing
|
|
539
616
|
|
|
540
|
-
|
|
617
|
+
With a `keywordAdapter`, keyword search runs on that adapter's own index (embeddings added to `InMemoryEmbeddingAdapter` or `PostgresAdapter` are searchable right away). Without one, `HybridSearch` keeps a local BM25 index that you fill yourself (it ignores `filter`):
|
|
541
618
|
|
|
542
619
|
```typescript
|
|
543
620
|
// Add documents to BM25 index
|
|
@@ -652,12 +729,12 @@ import type {
|
|
|
652
729
|
### Conversation History
|
|
653
730
|
|
|
654
731
|
```typescript
|
|
655
|
-
import { InMemoryAdapter } from '@cogitator-ai/memory';
|
|
732
|
+
import { InMemoryAdapter, countMessageTokens, unwrap } from '@cogitator-ai/memory';
|
|
656
733
|
|
|
657
734
|
const memory = new InMemoryAdapter();
|
|
658
735
|
await memory.connect();
|
|
659
736
|
|
|
660
|
-
const thread = await memory.createThread('chatbot');
|
|
737
|
+
const thread = unwrap(await memory.createThread('chatbot'));
|
|
661
738
|
|
|
662
739
|
const messages = [
|
|
663
740
|
{ role: 'user' as const, content: 'What is AI?' },
|
|
@@ -667,15 +744,18 @@ const messages = [
|
|
|
667
744
|
|
|
668
745
|
for (const msg of messages) {
|
|
669
746
|
await memory.addEntry({
|
|
670
|
-
threadId: thread.
|
|
747
|
+
threadId: thread.id,
|
|
671
748
|
message: msg,
|
|
749
|
+
tokenCount: countMessageTokens(msg),
|
|
672
750
|
});
|
|
673
751
|
}
|
|
674
752
|
|
|
675
|
-
const history =
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
753
|
+
const history = unwrap(
|
|
754
|
+
await memory.getEntries({
|
|
755
|
+
threadId: thread.id,
|
|
756
|
+
limit: 10,
|
|
757
|
+
})
|
|
758
|
+
);
|
|
679
759
|
```
|
|
680
760
|
|
|
681
761
|
### Token-Limited Context
|
|
@@ -707,7 +787,7 @@ console.log(
|
|
|
707
787
|
### Semantic Memory with PostgreSQL
|
|
708
788
|
|
|
709
789
|
```typescript
|
|
710
|
-
import { PostgresAdapter, OpenAIEmbeddingService } from '@cogitator-ai/memory';
|
|
790
|
+
import { PostgresAdapter, OpenAIEmbeddingService, unwrap } from '@cogitator-ai/memory';
|
|
711
791
|
|
|
712
792
|
const memory = new PostgresAdapter({
|
|
713
793
|
provider: 'postgres',
|
|
@@ -721,7 +801,22 @@ const embeddings = new OpenAIEmbeddingService({
|
|
|
721
801
|
await memory.connect();
|
|
722
802
|
|
|
723
803
|
const content = 'Machine learning is a subset of AI...';
|
|
724
|
-
|
|
804
|
+
await memory.addEmbedding({
|
|
805
|
+
sourceId: 'doc-1',
|
|
806
|
+
sourceType: 'document',
|
|
807
|
+
content,
|
|
808
|
+
vector: await embeddings.embed(content),
|
|
809
|
+
metadata: { agentId: 'agent-1' },
|
|
810
|
+
});
|
|
811
|
+
|
|
812
|
+
const matches = unwrap(
|
|
813
|
+
await memory.search({
|
|
814
|
+
vector: await embeddings.embed('What is ML?'),
|
|
815
|
+
limit: 5,
|
|
816
|
+
threshold: 0.7,
|
|
817
|
+
filter: { agentId: 'agent-1' },
|
|
818
|
+
})
|
|
819
|
+
);
|
|
725
820
|
```
|
|
726
821
|
|
|
727
822
|
---
|
|
@@ -732,32 +827,39 @@ Entity-relationship memory with multi-hop traversal and semantic reasoning.
|
|
|
732
827
|
|
|
733
828
|
### PostgresGraphAdapter
|
|
734
829
|
|
|
735
|
-
|
|
736
|
-
import { PostgresGraphAdapter } from '@cogitator-ai/memory';
|
|
830
|
+
Graph adapters return `MemoryResult`s like the memory adapters. `PostgresGraphAdapter` takes an existing `pg` pool and creates its tables on first use; `SQLiteGraphAdapter` takes `{ path, walMode? }`.
|
|
737
831
|
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
832
|
+
```typescript
|
|
833
|
+
import { PostgresGraphAdapter, unwrap } from '@cogitator-ai/memory';
|
|
834
|
+
import pg from 'pg';
|
|
741
835
|
|
|
742
|
-
|
|
836
|
+
const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL });
|
|
837
|
+
const graph = new PostgresGraphAdapter({ pool, vectorDimensions: 1536 }); // default 768
|
|
743
838
|
|
|
744
|
-
const person =
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
839
|
+
const person = unwrap(
|
|
840
|
+
await graph.addNode({
|
|
841
|
+
agentId: 'agent-1',
|
|
842
|
+
type: 'person',
|
|
843
|
+
name: 'Alice',
|
|
844
|
+
aliases: [],
|
|
845
|
+
description: 'Software engineer',
|
|
846
|
+
properties: { role: 'developer' },
|
|
847
|
+
confidence: 1.0,
|
|
848
|
+
source: 'user',
|
|
849
|
+
})
|
|
850
|
+
);
|
|
753
851
|
|
|
754
|
-
const company =
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
}
|
|
852
|
+
const company = unwrap(
|
|
853
|
+
await graph.addNode({
|
|
854
|
+
agentId: 'agent-1',
|
|
855
|
+
type: 'organization',
|
|
856
|
+
name: 'TechCorp',
|
|
857
|
+
aliases: [],
|
|
858
|
+
properties: {},
|
|
859
|
+
confidence: 1.0,
|
|
860
|
+
source: 'extracted',
|
|
861
|
+
})
|
|
862
|
+
);
|
|
761
863
|
|
|
762
864
|
await graph.addEdge({
|
|
763
865
|
agentId: 'agent-1',
|
|
@@ -765,6 +867,8 @@ await graph.addEdge({
|
|
|
765
867
|
targetNodeId: company.id,
|
|
766
868
|
type: 'works_at',
|
|
767
869
|
weight: 1.0,
|
|
870
|
+
bidirectional: false,
|
|
871
|
+
properties: {},
|
|
768
872
|
confidence: 0.95,
|
|
769
873
|
source: 'extracted',
|
|
770
874
|
});
|
|
@@ -773,12 +877,15 @@ await graph.addEdge({
|
|
|
773
877
|
### Multi-hop Traversal
|
|
774
878
|
|
|
775
879
|
```typescript
|
|
776
|
-
const result =
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
880
|
+
const result = unwrap(
|
|
881
|
+
await graph.traverse({
|
|
882
|
+
agentId: 'agent-1',
|
|
883
|
+
startNodeId: person.id,
|
|
884
|
+
maxDepth: 3,
|
|
885
|
+
direction: 'outgoing', // 'outgoing' | 'incoming' | 'both'
|
|
886
|
+
edgeTypes: ['works_at', 'knows', 'located_in'],
|
|
887
|
+
})
|
|
888
|
+
);
|
|
782
889
|
|
|
783
890
|
console.log('Visited nodes:', result.visitedNodes);
|
|
784
891
|
console.log('Paths found:', result.paths);
|
|
@@ -787,7 +894,7 @@ console.log('Paths found:', result.paths);
|
|
|
787
894
|
### Shortest Path
|
|
788
895
|
|
|
789
896
|
```typescript
|
|
790
|
-
const path = await graph.findShortestPath(
|
|
897
|
+
const path = unwrap(await graph.findShortestPath('agent-1', person.id, company.id, 5));
|
|
791
898
|
if (path) {
|
|
792
899
|
console.log('Path:', path.nodes.map((n) => n.name).join(' -> '));
|
|
793
900
|
console.log('Total weight:', path.totalWeight);
|
|
@@ -797,12 +904,14 @@ if (path) {
|
|
|
797
904
|
### Semantic Node Search
|
|
798
905
|
|
|
799
906
|
```typescript
|
|
800
|
-
const similar =
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
907
|
+
const similar = unwrap(
|
|
908
|
+
await graph.searchNodesSemantic({
|
|
909
|
+
agentId: 'agent-1',
|
|
910
|
+
vector: await embeddingService.embed('machine learning engineer'), // a vector is required
|
|
911
|
+
limit: 10,
|
|
912
|
+
threshold: 0.7,
|
|
913
|
+
})
|
|
914
|
+
); // nodes with a `score`
|
|
806
915
|
```
|
|
807
916
|
|
|
808
917
|
### LLM Entity Extraction
|
|
@@ -810,32 +919,39 @@ const similar = await graph.searchNodesSemantic({
|
|
|
810
919
|
```typescript
|
|
811
920
|
import { LLMEntityExtractor } from '@cogitator-ai/memory';
|
|
812
921
|
|
|
813
|
-
const
|
|
922
|
+
const backend = cog.getLLMBackend('openai/gpt-5.5');
|
|
923
|
+
|
|
924
|
+
const extractor = new LLMEntityExtractor(backend, {
|
|
925
|
+
model: 'gpt-5.5', // required with an LLMBackend
|
|
814
926
|
minConfidence: 0.7,
|
|
815
927
|
maxEntitiesPerText: 20,
|
|
928
|
+
maxRelationsPerText: 30,
|
|
816
929
|
});
|
|
817
930
|
|
|
818
931
|
const result = await extractor.extract(
|
|
819
|
-
'Alice works at TechCorp in San Francisco. She knows Bob from the AI conference.'
|
|
932
|
+
'Alice works at TechCorp in San Francisco. She knows Bob from the AI conference.',
|
|
933
|
+
{ agentId: 'agent-1' }
|
|
820
934
|
);
|
|
821
935
|
|
|
822
936
|
console.log('Entities:', result.entities);
|
|
823
937
|
console.log('Relations:', result.relations);
|
|
824
938
|
```
|
|
825
939
|
|
|
940
|
+
Any object with a `chat({ model?, messages, responseFormat })` method resolving to `{ content }` (`LLMBackendMinimal`) also works as the first argument; there `model` is optional and, when set, is passed through in each request.
|
|
941
|
+
|
|
826
942
|
### Graph Inference Engine
|
|
827
943
|
|
|
828
944
|
```typescript
|
|
829
945
|
import { GraphInferenceEngine } from '@cogitator-ai/memory';
|
|
830
946
|
|
|
831
|
-
const engine = new GraphInferenceEngine(graph
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
947
|
+
const engine = new GraphInferenceEngine(graph); // built-in rules; pass false to start without them
|
|
948
|
+
|
|
949
|
+
const inferred = await engine.infer('agent-1', { minConfidence: 0.5, maxInferences: 100 });
|
|
950
|
+
for (const edge of inferred) {
|
|
951
|
+
console.log(edge.type, edge.sourceNodeId, '->', edge.targetNodeId, 'via rule', edge.ruleId);
|
|
952
|
+
}
|
|
835
953
|
|
|
836
|
-
|
|
837
|
-
console.log('Inferred edges:', inferred.edges);
|
|
838
|
-
console.log('Rules applied:', inferred.rulesApplied);
|
|
954
|
+
await engine.materialize(inferred); // store them as edges
|
|
839
955
|
```
|
|
840
956
|
|
|
841
957
|
### Graph Context Builder
|
|
@@ -849,13 +965,14 @@ const contextBuilder = new GraphContextBuilder(graph, embeddingService, {
|
|
|
849
965
|
includeInferred: true,
|
|
850
966
|
});
|
|
851
967
|
|
|
852
|
-
const context = await contextBuilder.buildContext({
|
|
853
|
-
|
|
854
|
-
|
|
968
|
+
const context = await contextBuilder.buildContext('agent-1', 'Tell me about Alice and her work', {
|
|
969
|
+
maxDepth: 2,
|
|
970
|
+
userId: 'user-1', // leave out other users' nodes (metadata.userId)
|
|
855
971
|
});
|
|
856
972
|
|
|
857
973
|
console.log('Relevant nodes:', context.nodes);
|
|
858
974
|
console.log('Relationships:', context.edges);
|
|
975
|
+
console.log(context.formattedContext); // ready for a system prompt
|
|
859
976
|
```
|
|
860
977
|
|
|
861
978
|
---
|
|
@@ -44,6 +44,7 @@ export declare class PostgresAdapter extends BaseMemoryAdapter implements FactAd
|
|
|
44
44
|
* `metadata.threadId`, and a user filter also lets through embeddings of no user.
|
|
45
45
|
*/
|
|
46
46
|
private embeddingFilterClause;
|
|
47
|
+
private rowToThread;
|
|
47
48
|
setVectorDimensions(dimensions: number): void;
|
|
48
49
|
}
|
|
49
50
|
//# sourceMappingURL=postgres.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/adapters/postgres.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,MAAM,EACN,WAAW,EACX,kBAAkB,EAClB,YAAY,EACZ,qBAAqB,EACrB,cAAc,EACd,IAAI,EACJ,SAAS,EACT,qBAAqB,EACrB,WAAW,EACX,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EAEpB,YAAY,EACb,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAQ3C,qBAAa,eACX,SAAQ,iBACR,YAAW,WAAW,EAAE,gBAAgB,EAAE,oBAAoB;IAE9D,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAc;IAE/C,OAAO,CAAC,IAAI,CAAqB;IACjC,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,gBAAgB,CAAO;gBAEnB,MAAM,EAAE,qBAAqB;IAYnC,OAAO,IAAI,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;YAuB9B,UAAU;IA+FlB,UAAU,IAAI,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/adapters/postgres.ts"],"names":[],"mappings":"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"}
|