@cogitator-ai/memory 0.10.0 → 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 +204 -88
- 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 +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -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/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 +3 -3
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
|
|
|
@@ -46,11 +48,13 @@ const thread = unwrap(await memory.createThread('agent-1', { topic: 'greeting' }
|
|
|
46
48
|
await memory.addEntry({
|
|
47
49
|
threadId: thread.id,
|
|
48
50
|
message: { role: 'user', content: 'Hello!' },
|
|
51
|
+
tokenCount: 2,
|
|
49
52
|
});
|
|
50
53
|
|
|
51
54
|
await memory.addEntry({
|
|
52
55
|
threadId: thread.id,
|
|
53
56
|
message: { role: 'assistant', content: 'Hi there!' },
|
|
57
|
+
tokenCount: 3,
|
|
54
58
|
});
|
|
55
59
|
|
|
56
60
|
const builder = new ContextBuilder(
|
|
@@ -67,7 +71,16 @@ const context = await builder.build({
|
|
|
67
71
|
console.log(context.messages);
|
|
68
72
|
```
|
|
69
73
|
|
|
70
|
-
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
|
|
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
|
+
```
|
|
71
84
|
|
|
72
85
|
---
|
|
73
86
|
|
|
@@ -131,9 +144,11 @@ import { SQLiteAdapter } from '@cogitator-ai/memory';
|
|
|
131
144
|
|
|
132
145
|
const memory = new SQLiteAdapter({
|
|
133
146
|
provider: 'sqlite',
|
|
134
|
-
path: './cogitator.db',
|
|
147
|
+
path: './cogitator.db', // ':memory:' for an in-memory database
|
|
135
148
|
walMode: true,
|
|
136
149
|
});
|
|
150
|
+
|
|
151
|
+
await memory.connect();
|
|
137
152
|
```
|
|
138
153
|
|
|
139
154
|
### MongoDB Adapter
|
|
@@ -146,6 +161,8 @@ const memory = new MongoDBAdapter({
|
|
|
146
161
|
uri: 'mongodb://localhost:27017',
|
|
147
162
|
database: 'cogitator',
|
|
148
163
|
});
|
|
164
|
+
|
|
165
|
+
await memory.connect();
|
|
149
166
|
```
|
|
150
167
|
|
|
151
168
|
### Qdrant Adapter (Embedding)
|
|
@@ -159,8 +176,12 @@ const embeddings = new QdrantAdapter({
|
|
|
159
176
|
collection: 'cogitator',
|
|
160
177
|
dimensions: 1536,
|
|
161
178
|
});
|
|
179
|
+
|
|
180
|
+
await embeddings.connect();
|
|
162
181
|
```
|
|
163
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
|
+
|
|
164
185
|
### Factory Function
|
|
165
186
|
|
|
166
187
|
```typescript
|
|
@@ -187,8 +208,12 @@ const qdrant = await createEmbeddingAdapter({
|
|
|
187
208
|
provider: 'qdrant',
|
|
188
209
|
dimensions: 1536,
|
|
189
210
|
});
|
|
211
|
+
|
|
212
|
+
await postgres.connect(); // the factories create adapters; connect them before use
|
|
190
213
|
```
|
|
191
214
|
|
|
215
|
+
`createMemoryAdapter` loads the adapter's driver lazily, so only the drivers you use need to be installed.
|
|
216
|
+
|
|
192
217
|
---
|
|
193
218
|
|
|
194
219
|
## MemoryAdapter Interface
|
|
@@ -220,13 +245,14 @@ interface MemoryAdapter {
|
|
|
220
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.
|
|
221
246
|
|
|
222
247
|
```typescript
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
248
|
+
const thread = unwrap(
|
|
249
|
+
await memory.createThread('agent-1', {
|
|
250
|
+
topic: 'support',
|
|
251
|
+
user: 'user-123',
|
|
252
|
+
})
|
|
253
|
+
);
|
|
228
254
|
|
|
229
|
-
const
|
|
255
|
+
const found = unwrap(await memory.getThread(thread.id)); // Thread | null
|
|
230
256
|
|
|
231
257
|
await memory.updateThread(thread.id, {
|
|
232
258
|
resolved: true,
|
|
@@ -238,21 +264,26 @@ await memory.deleteThread(thread.id);
|
|
|
238
264
|
### Entry Operations
|
|
239
265
|
|
|
240
266
|
```typescript
|
|
241
|
-
const entry =
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
267
|
+
const entry = unwrap(
|
|
268
|
+
await memory.addEntry({
|
|
269
|
+
threadId: thread.id,
|
|
270
|
+
message: { role: 'user', content: 'Hello' },
|
|
271
|
+
tokenCount: 10,
|
|
272
|
+
})
|
|
273
|
+
);
|
|
246
274
|
|
|
247
|
-
const entries =
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
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
|
+
);
|
|
252
283
|
|
|
253
|
-
const single = await memory.getEntry(entry.
|
|
284
|
+
const single = unwrap(await memory.getEntry(entry.id));
|
|
254
285
|
|
|
255
|
-
await memory.deleteEntry(entry.
|
|
286
|
+
await memory.deleteEntry(entry.id);
|
|
256
287
|
|
|
257
288
|
await memory.clearThread(thread.id);
|
|
258
289
|
```
|
|
@@ -273,6 +304,8 @@ interface ContextBuilderConfig {
|
|
|
273
304
|
includeSystemPrompt?: boolean;
|
|
274
305
|
includeFacts?: boolean;
|
|
275
306
|
includeSemanticContext?: boolean;
|
|
307
|
+
includeGraphContext?: boolean;
|
|
308
|
+
graphContextOptions?: GraphContextOptions;
|
|
276
309
|
}
|
|
277
310
|
```
|
|
278
311
|
|
|
@@ -346,6 +379,7 @@ interface BuiltContext {
|
|
|
346
379
|
messages: Message[];
|
|
347
380
|
facts: Fact[];
|
|
348
381
|
semanticResults: (Embedding & { score: number })[];
|
|
382
|
+
graphContext?: GraphContext; // with includeGraphContext and a graph adapter
|
|
349
383
|
tokenCount: number;
|
|
350
384
|
truncated: boolean;
|
|
351
385
|
metadata: {
|
|
@@ -364,12 +398,26 @@ interface BuiltContext {
|
|
|
364
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.
|
|
365
399
|
|
|
366
400
|
```typescript
|
|
401
|
+
import { createLLMBackend } from '@cogitator-ai/core';
|
|
367
402
|
import { InMemoryAdapter, SessionManager, CompactionService } from '@cogitator-ai/memory';
|
|
368
403
|
|
|
369
404
|
const memory = new InMemoryAdapter();
|
|
405
|
+
const llm = createLLMBackend('google', {
|
|
406
|
+
providers: { google: { apiKey: process.env.GOOGLE_API_KEY! } },
|
|
407
|
+
});
|
|
408
|
+
|
|
370
409
|
const compaction = new CompactionService({
|
|
371
410
|
adapter: memory,
|
|
372
|
-
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
|
+
},
|
|
373
421
|
});
|
|
374
422
|
const sessions = new SessionManager(memory, { compaction });
|
|
375
423
|
|
|
@@ -383,10 +431,36 @@ const session = await sessions.getOrCreate({
|
|
|
383
431
|
const all = await sessions.list();
|
|
384
432
|
const mine = await sessions.list({ userId: 'user-1', status: 'active', limit: 20 });
|
|
385
433
|
|
|
386
|
-
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
|
+
});
|
|
387
441
|
```
|
|
388
442
|
|
|
389
|
-
`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
|
+
```
|
|
390
464
|
|
|
391
465
|
---
|
|
392
466
|
|
|
@@ -425,10 +499,12 @@ import { OpenAIEmbeddingService, createEmbeddingService } from '@cogitator-ai/me
|
|
|
425
499
|
|
|
426
500
|
const embeddings = new OpenAIEmbeddingService({
|
|
427
501
|
apiKey: process.env.OPENAI_API_KEY!,
|
|
428
|
-
model: 'text-embedding-3-small',
|
|
502
|
+
model: 'text-embedding-3-small', // default
|
|
503
|
+
dimensions: 512, // optional, text-embedding-3-* only
|
|
429
504
|
});
|
|
430
505
|
|
|
431
|
-
|
|
506
|
+
// or through the factory
|
|
507
|
+
const viaFactory = createEmbeddingService({
|
|
432
508
|
provider: 'openai',
|
|
433
509
|
apiKey: process.env.OPENAI_API_KEY!,
|
|
434
510
|
});
|
|
@@ -448,7 +524,7 @@ const embeddings = new OllamaEmbeddingService({
|
|
|
448
524
|
baseUrl: 'http://localhost:11434',
|
|
449
525
|
});
|
|
450
526
|
|
|
451
|
-
const
|
|
527
|
+
const viaFactory = createEmbeddingService({
|
|
452
528
|
provider: 'ollama',
|
|
453
529
|
model: 'nomic-embed-text',
|
|
454
530
|
});
|
|
@@ -467,7 +543,7 @@ const embeddings = new GoogleEmbeddingService({
|
|
|
467
543
|
dimensions: 768,
|
|
468
544
|
});
|
|
469
545
|
|
|
470
|
-
const
|
|
546
|
+
const viaFactory = createEmbeddingService({
|
|
471
547
|
provider: 'google',
|
|
472
548
|
apiKey: process.env.GOOGLE_API_KEY!,
|
|
473
549
|
});
|
|
@@ -530,15 +606,15 @@ const hybridResults = await search.search({
|
|
|
530
606
|
});
|
|
531
607
|
|
|
532
608
|
// Results include both scores
|
|
533
|
-
|
|
609
|
+
for (const result of unwrap(hybridResults)) {
|
|
534
610
|
console.log(`${result.content} — score: ${result.score}`);
|
|
535
611
|
console.log(` vector: ${result.vectorScore}, keyword: ${result.keywordScore}`);
|
|
536
|
-
}
|
|
612
|
+
}
|
|
537
613
|
```
|
|
538
614
|
|
|
539
615
|
### Document Indexing
|
|
540
616
|
|
|
541
|
-
|
|
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`):
|
|
542
618
|
|
|
543
619
|
```typescript
|
|
544
620
|
// Add documents to BM25 index
|
|
@@ -653,12 +729,12 @@ import type {
|
|
|
653
729
|
### Conversation History
|
|
654
730
|
|
|
655
731
|
```typescript
|
|
656
|
-
import { InMemoryAdapter } from '@cogitator-ai/memory';
|
|
732
|
+
import { InMemoryAdapter, countMessageTokens, unwrap } from '@cogitator-ai/memory';
|
|
657
733
|
|
|
658
734
|
const memory = new InMemoryAdapter();
|
|
659
735
|
await memory.connect();
|
|
660
736
|
|
|
661
|
-
const thread = await memory.createThread('chatbot');
|
|
737
|
+
const thread = unwrap(await memory.createThread('chatbot'));
|
|
662
738
|
|
|
663
739
|
const messages = [
|
|
664
740
|
{ role: 'user' as const, content: 'What is AI?' },
|
|
@@ -668,15 +744,18 @@ const messages = [
|
|
|
668
744
|
|
|
669
745
|
for (const msg of messages) {
|
|
670
746
|
await memory.addEntry({
|
|
671
|
-
threadId: thread.
|
|
747
|
+
threadId: thread.id,
|
|
672
748
|
message: msg,
|
|
749
|
+
tokenCount: countMessageTokens(msg),
|
|
673
750
|
});
|
|
674
751
|
}
|
|
675
752
|
|
|
676
|
-
const history =
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
753
|
+
const history = unwrap(
|
|
754
|
+
await memory.getEntries({
|
|
755
|
+
threadId: thread.id,
|
|
756
|
+
limit: 10,
|
|
757
|
+
})
|
|
758
|
+
);
|
|
680
759
|
```
|
|
681
760
|
|
|
682
761
|
### Token-Limited Context
|
|
@@ -708,7 +787,7 @@ console.log(
|
|
|
708
787
|
### Semantic Memory with PostgreSQL
|
|
709
788
|
|
|
710
789
|
```typescript
|
|
711
|
-
import { PostgresAdapter, OpenAIEmbeddingService } from '@cogitator-ai/memory';
|
|
790
|
+
import { PostgresAdapter, OpenAIEmbeddingService, unwrap } from '@cogitator-ai/memory';
|
|
712
791
|
|
|
713
792
|
const memory = new PostgresAdapter({
|
|
714
793
|
provider: 'postgres',
|
|
@@ -722,7 +801,22 @@ const embeddings = new OpenAIEmbeddingService({
|
|
|
722
801
|
await memory.connect();
|
|
723
802
|
|
|
724
803
|
const content = 'Machine learning is a subset of AI...';
|
|
725
|
-
|
|
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
|
+
);
|
|
726
820
|
```
|
|
727
821
|
|
|
728
822
|
---
|
|
@@ -733,32 +827,39 @@ Entity-relationship memory with multi-hop traversal and semantic reasoning.
|
|
|
733
827
|
|
|
734
828
|
### PostgresGraphAdapter
|
|
735
829
|
|
|
736
|
-
|
|
737
|
-
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? }`.
|
|
738
831
|
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
832
|
+
```typescript
|
|
833
|
+
import { PostgresGraphAdapter, unwrap } from '@cogitator-ai/memory';
|
|
834
|
+
import pg from 'pg';
|
|
742
835
|
|
|
743
|
-
|
|
836
|
+
const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL });
|
|
837
|
+
const graph = new PostgresGraphAdapter({ pool, vectorDimensions: 1536 }); // default 768
|
|
744
838
|
|
|
745
|
-
const person =
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
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
|
+
);
|
|
754
851
|
|
|
755
|
-
const company =
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
}
|
|
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
|
+
);
|
|
762
863
|
|
|
763
864
|
await graph.addEdge({
|
|
764
865
|
agentId: 'agent-1',
|
|
@@ -766,6 +867,8 @@ await graph.addEdge({
|
|
|
766
867
|
targetNodeId: company.id,
|
|
767
868
|
type: 'works_at',
|
|
768
869
|
weight: 1.0,
|
|
870
|
+
bidirectional: false,
|
|
871
|
+
properties: {},
|
|
769
872
|
confidence: 0.95,
|
|
770
873
|
source: 'extracted',
|
|
771
874
|
});
|
|
@@ -774,12 +877,15 @@ await graph.addEdge({
|
|
|
774
877
|
### Multi-hop Traversal
|
|
775
878
|
|
|
776
879
|
```typescript
|
|
777
|
-
const result =
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
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
|
+
);
|
|
783
889
|
|
|
784
890
|
console.log('Visited nodes:', result.visitedNodes);
|
|
785
891
|
console.log('Paths found:', result.paths);
|
|
@@ -788,7 +894,7 @@ console.log('Paths found:', result.paths);
|
|
|
788
894
|
### Shortest Path
|
|
789
895
|
|
|
790
896
|
```typescript
|
|
791
|
-
const path = await graph.findShortestPath(
|
|
897
|
+
const path = unwrap(await graph.findShortestPath('agent-1', person.id, company.id, 5));
|
|
792
898
|
if (path) {
|
|
793
899
|
console.log('Path:', path.nodes.map((n) => n.name).join(' -> '));
|
|
794
900
|
console.log('Total weight:', path.totalWeight);
|
|
@@ -798,12 +904,14 @@ if (path) {
|
|
|
798
904
|
### Semantic Node Search
|
|
799
905
|
|
|
800
906
|
```typescript
|
|
801
|
-
const similar =
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
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`
|
|
807
915
|
```
|
|
808
916
|
|
|
809
917
|
### LLM Entity Extraction
|
|
@@ -811,32 +919,39 @@ const similar = await graph.searchNodesSemantic({
|
|
|
811
919
|
```typescript
|
|
812
920
|
import { LLMEntityExtractor } from '@cogitator-ai/memory';
|
|
813
921
|
|
|
814
|
-
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
|
|
815
926
|
minConfidence: 0.7,
|
|
816
927
|
maxEntitiesPerText: 20,
|
|
928
|
+
maxRelationsPerText: 30,
|
|
817
929
|
});
|
|
818
930
|
|
|
819
931
|
const result = await extractor.extract(
|
|
820
|
-
'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' }
|
|
821
934
|
);
|
|
822
935
|
|
|
823
936
|
console.log('Entities:', result.entities);
|
|
824
937
|
console.log('Relations:', result.relations);
|
|
825
938
|
```
|
|
826
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
|
+
|
|
827
942
|
### Graph Inference Engine
|
|
828
943
|
|
|
829
944
|
```typescript
|
|
830
945
|
import { GraphInferenceEngine } from '@cogitator-ai/memory';
|
|
831
946
|
|
|
832
|
-
const engine = new GraphInferenceEngine(graph
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
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
|
+
}
|
|
836
953
|
|
|
837
|
-
|
|
838
|
-
console.log('Inferred edges:', inferred.edges);
|
|
839
|
-
console.log('Rules applied:', inferred.rulesApplied);
|
|
954
|
+
await engine.materialize(inferred); // store them as edges
|
|
840
955
|
```
|
|
841
956
|
|
|
842
957
|
### Graph Context Builder
|
|
@@ -850,13 +965,14 @@ const contextBuilder = new GraphContextBuilder(graph, embeddingService, {
|
|
|
850
965
|
includeInferred: true,
|
|
851
966
|
});
|
|
852
967
|
|
|
853
|
-
const context = await contextBuilder.buildContext({
|
|
854
|
-
|
|
855
|
-
|
|
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)
|
|
856
971
|
});
|
|
857
972
|
|
|
858
973
|
console.log('Relevant nodes:', context.nodes);
|
|
859
974
|
console.log('Relationships:', context.edges);
|
|
975
|
+
console.log(context.formattedContext); // ready for a system prompt
|
|
860
976
|
```
|
|
861
977
|
|
|
862
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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"}
|