@cogitator-ai/memory 0.2.0 → 0.3.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 +572 -21
- package/dist/context-builder.d.ts.map +1 -1
- package/dist/context-builder.js +4 -0
- package/dist/context-builder.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/knowledge-graph/entity-extractor.d.ts +30 -0
- package/dist/knowledge-graph/entity-extractor.d.ts.map +1 -0
- package/dist/knowledge-graph/entity-extractor.js +158 -0
- package/dist/knowledge-graph/entity-extractor.js.map +1 -0
- package/dist/knowledge-graph/graph-adapter.d.ts +56 -0
- package/dist/knowledge-graph/graph-adapter.d.ts.map +1 -0
- package/dist/knowledge-graph/graph-adapter.js +652 -0
- package/dist/knowledge-graph/graph-adapter.js.map +1 -0
- package/dist/knowledge-graph/graph-context-builder.d.ts +23 -0
- package/dist/knowledge-graph/graph-context-builder.d.ts.map +1 -0
- package/dist/knowledge-graph/graph-context-builder.js +202 -0
- package/dist/knowledge-graph/graph-context-builder.js.map +1 -0
- package/dist/knowledge-graph/index.d.ts +9 -0
- package/dist/knowledge-graph/index.d.ts.map +1 -0
- package/dist/knowledge-graph/index.js +6 -0
- package/dist/knowledge-graph/index.js.map +1 -0
- package/dist/knowledge-graph/inference-engine.d.ts +17 -0
- package/dist/knowledge-graph/inference-engine.d.ts.map +1 -0
- package/dist/knowledge-graph/inference-engine.js +270 -0
- package/dist/knowledge-graph/inference-engine.js.map +1 -0
- package/dist/knowledge-graph/schema.d.ts +854 -0
- package/dist/knowledge-graph/schema.d.ts.map +1 -0
- package/dist/knowledge-graph/schema.js +166 -0
- package/dist/knowledge-graph/schema.js.map +1 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -12,77 +12,628 @@ pnpm add ioredis # For Redis adapter
|
|
|
12
12
|
pnpm add pg # For PostgreSQL adapter
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## Features
|
|
16
|
+
|
|
17
|
+
- **Multiple Adapters** - In-memory, Redis, PostgreSQL with pgvector
|
|
18
|
+
- **Thread Management** - Create, update, delete conversation threads
|
|
19
|
+
- **Token Counting** - Estimate token usage without tiktoken dependency
|
|
20
|
+
- **Context Builder** - Build token-aware conversation context
|
|
21
|
+
- **Embedding Services** - OpenAI and Ollama embedding integration
|
|
22
|
+
- **Semantic Search** - Vector similarity search with pgvector
|
|
23
|
+
- **Facts Storage** - Store and retrieve agent knowledge
|
|
24
|
+
- **Zod Schemas** - Type-safe configuration validation
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import { InMemoryAdapter, ContextBuilder } from '@cogitator-ai/memory';
|
|
32
|
+
|
|
33
|
+
const memory = new InMemoryAdapter();
|
|
34
|
+
await memory.connect();
|
|
35
|
+
|
|
36
|
+
const threadResult = await memory.createThread('agent-1', { topic: 'greeting' });
|
|
37
|
+
const thread = threadResult.data!;
|
|
38
|
+
|
|
39
|
+
await memory.addEntry({
|
|
40
|
+
threadId: thread.id,
|
|
41
|
+
message: { role: 'user', content: 'Hello!' },
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
await memory.addEntry({
|
|
45
|
+
threadId: thread.id,
|
|
46
|
+
message: { role: 'assistant', content: 'Hi there!' },
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const builder = new ContextBuilder(
|
|
50
|
+
{ maxTokens: 4000, strategy: 'recent' },
|
|
51
|
+
{ memoryAdapter: memory }
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
const context = await builder.build({
|
|
55
|
+
threadId: thread.id,
|
|
56
|
+
agentId: 'agent-1',
|
|
57
|
+
systemPrompt: 'You are helpful.',
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
console.log(context.messages);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Memory Adapters
|
|
16
66
|
|
|
17
67
|
### In-Memory Adapter
|
|
18
68
|
|
|
69
|
+
Fast, non-persistent storage for development and testing.
|
|
70
|
+
|
|
19
71
|
```typescript
|
|
20
72
|
import { InMemoryAdapter } from '@cogitator-ai/memory';
|
|
21
73
|
|
|
22
|
-
const memory = new InMemoryAdapter(
|
|
23
|
-
|
|
24
|
-
role: 'user',
|
|
25
|
-
content: 'Hello!',
|
|
74
|
+
const memory = new InMemoryAdapter({
|
|
75
|
+
maxEntries: 1000,
|
|
26
76
|
});
|
|
77
|
+
|
|
78
|
+
await memory.connect();
|
|
27
79
|
```
|
|
28
80
|
|
|
29
81
|
### Redis Adapter
|
|
30
82
|
|
|
83
|
+
Persistent short-term memory with TTL support.
|
|
84
|
+
|
|
31
85
|
```typescript
|
|
32
86
|
import { RedisAdapter } from '@cogitator-ai/memory';
|
|
33
87
|
|
|
34
88
|
const memory = new RedisAdapter({
|
|
35
89
|
url: 'redis://localhost:6379',
|
|
36
|
-
|
|
90
|
+
keyPrefix: 'cogitator:',
|
|
91
|
+
ttl: 3600,
|
|
37
92
|
});
|
|
93
|
+
|
|
94
|
+
await memory.connect();
|
|
38
95
|
```
|
|
39
96
|
|
|
40
97
|
### PostgreSQL Adapter
|
|
41
98
|
|
|
99
|
+
Long-term storage with vector search via pgvector.
|
|
100
|
+
|
|
42
101
|
```typescript
|
|
43
102
|
import { PostgresAdapter } from '@cogitator-ai/memory';
|
|
44
103
|
|
|
45
104
|
const memory = new PostgresAdapter({
|
|
46
105
|
connectionString: 'postgresql://localhost:5432/cogitator',
|
|
106
|
+
schema: 'public',
|
|
107
|
+
poolSize: 10,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
await memory.connect();
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Factory Function
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
import { createMemoryAdapter } from '@cogitator-ai/memory';
|
|
117
|
+
|
|
118
|
+
const memory = createMemoryAdapter({ provider: 'memory' });
|
|
119
|
+
|
|
120
|
+
const redis = createMemoryAdapter({
|
|
121
|
+
provider: 'redis',
|
|
122
|
+
url: 'redis://localhost:6379',
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const postgres = createMemoryAdapter({
|
|
126
|
+
provider: 'postgres',
|
|
127
|
+
connectionString: 'postgresql://localhost:5432/db',
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## MemoryAdapter Interface
|
|
134
|
+
|
|
135
|
+
All adapters implement the `MemoryAdapter` interface:
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
interface MemoryAdapter {
|
|
139
|
+
readonly provider: MemoryProvider;
|
|
140
|
+
|
|
141
|
+
connect(): Promise<MemoryResult<void>>;
|
|
142
|
+
disconnect(): Promise<MemoryResult<void>>;
|
|
143
|
+
|
|
144
|
+
createThread(agentId: string, metadata?: Record<string, unknown>): Promise<MemoryResult<Thread>>;
|
|
145
|
+
getThread(threadId: string): Promise<MemoryResult<Thread | null>>;
|
|
146
|
+
updateThread(threadId: string, metadata: Record<string, unknown>): Promise<MemoryResult<Thread>>;
|
|
147
|
+
deleteThread(threadId: string): Promise<MemoryResult<void>>;
|
|
148
|
+
|
|
149
|
+
addEntry(entry: Omit<MemoryEntry, 'id' | 'createdAt'>): Promise<MemoryResult<MemoryEntry>>;
|
|
150
|
+
getEntries(options: MemoryQueryOptions): Promise<MemoryResult<MemoryEntry[]>>;
|
|
151
|
+
getEntry(entryId: string): Promise<MemoryResult<MemoryEntry | null>>;
|
|
152
|
+
deleteEntry(entryId: string): Promise<MemoryResult<void>>;
|
|
153
|
+
clearThread(threadId: string): Promise<MemoryResult<void>>;
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Thread Operations
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
const result = await memory.createThread('agent-1', {
|
|
161
|
+
topic: 'support',
|
|
162
|
+
user: 'user-123',
|
|
163
|
+
});
|
|
164
|
+
const thread = result.data!;
|
|
165
|
+
|
|
166
|
+
const threadResult = await memory.getThread(thread.id);
|
|
167
|
+
|
|
168
|
+
await memory.updateThread(thread.id, {
|
|
169
|
+
resolved: true,
|
|
47
170
|
});
|
|
171
|
+
|
|
172
|
+
await memory.deleteThread(thread.id);
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Entry Operations
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
const entry = await memory.addEntry({
|
|
179
|
+
threadId: thread.id,
|
|
180
|
+
message: { role: 'user', content: 'Hello' },
|
|
181
|
+
tokenCount: 10,
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
const entries = await memory.getEntries({
|
|
185
|
+
threadId: thread.id,
|
|
186
|
+
limit: 50,
|
|
187
|
+
includeToolCalls: true,
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
const single = await memory.getEntry(entry.data!.id);
|
|
191
|
+
|
|
192
|
+
await memory.deleteEntry(entry.data!.id);
|
|
193
|
+
|
|
194
|
+
await memory.clearThread(thread.id);
|
|
48
195
|
```
|
|
49
196
|
|
|
50
|
-
|
|
197
|
+
---
|
|
51
198
|
|
|
52
|
-
|
|
199
|
+
## Context Builder
|
|
200
|
+
|
|
201
|
+
Build token-aware conversation context from memory.
|
|
202
|
+
|
|
203
|
+
### Configuration
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
interface ContextBuilderConfig {
|
|
207
|
+
maxTokens: number;
|
|
208
|
+
reserveTokens?: number;
|
|
209
|
+
strategy: 'recent' | 'relevant' | 'hybrid';
|
|
210
|
+
includeSystemPrompt?: boolean;
|
|
211
|
+
includeFacts?: boolean;
|
|
212
|
+
includeSemanticContext?: boolean;
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Basic Usage
|
|
53
217
|
|
|
54
218
|
```typescript
|
|
55
219
|
import { ContextBuilder } from '@cogitator-ai/memory';
|
|
56
220
|
|
|
57
|
-
const builder = new ContextBuilder(
|
|
221
|
+
const builder = new ContextBuilder(
|
|
222
|
+
{
|
|
223
|
+
maxTokens: 4000,
|
|
224
|
+
reserveTokens: 400,
|
|
225
|
+
strategy: 'recent',
|
|
226
|
+
includeSystemPrompt: true,
|
|
227
|
+
},
|
|
228
|
+
{ memoryAdapter: memory }
|
|
229
|
+
);
|
|
230
|
+
|
|
231
|
+
const context = await builder.build({
|
|
232
|
+
threadId: 'thread_123',
|
|
233
|
+
agentId: 'agent-1',
|
|
234
|
+
systemPrompt: 'You are a helpful assistant.',
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
console.log(context.messages);
|
|
238
|
+
console.log(context.tokenCount);
|
|
239
|
+
console.log(context.truncated);
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### With Facts and Semantic Search
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
const builder = new ContextBuilder(
|
|
246
|
+
{
|
|
247
|
+
maxTokens: 8000,
|
|
248
|
+
strategy: 'recent',
|
|
249
|
+
includeFacts: true,
|
|
250
|
+
includeSemanticContext: true,
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
memoryAdapter: memory,
|
|
254
|
+
factAdapter: factStore,
|
|
255
|
+
embeddingAdapter: vectorStore,
|
|
256
|
+
embeddingService: embeddings,
|
|
257
|
+
}
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
const context = await builder.build({
|
|
261
|
+
threadId: 'thread_123',
|
|
262
|
+
agentId: 'agent-1',
|
|
263
|
+
systemPrompt: 'You are an expert.',
|
|
264
|
+
currentInput: 'What is machine learning?',
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
console.log(context.facts);
|
|
268
|
+
console.log(context.semanticResults);
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Built Context
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
interface BuiltContext {
|
|
275
|
+
messages: Message[];
|
|
276
|
+
facts: Fact[];
|
|
277
|
+
semanticResults: (Embedding & { score: number })[];
|
|
278
|
+
tokenCount: number;
|
|
279
|
+
truncated: boolean;
|
|
280
|
+
metadata: {
|
|
281
|
+
originalMessageCount: number;
|
|
282
|
+
includedMessageCount: number;
|
|
283
|
+
factsIncluded: number;
|
|
284
|
+
semanticResultsIncluded: number;
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## Token Counting
|
|
292
|
+
|
|
293
|
+
Simple token estimation without tiktoken dependency.
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
import {
|
|
297
|
+
countTokens,
|
|
298
|
+
countMessageTokens,
|
|
299
|
+
countMessagesTokens,
|
|
300
|
+
truncateToTokens,
|
|
301
|
+
} from '@cogitator-ai/memory';
|
|
302
|
+
|
|
303
|
+
const tokens = countTokens('Hello, world!');
|
|
304
|
+
|
|
305
|
+
const msgTokens = countMessageTokens({ role: 'user', content: 'Hello!' });
|
|
306
|
+
|
|
307
|
+
const totalTokens = countMessagesTokens([
|
|
308
|
+
{ role: 'user', content: 'Hello!' },
|
|
309
|
+
{ role: 'assistant', content: 'Hi there!' },
|
|
310
|
+
]);
|
|
311
|
+
|
|
312
|
+
const truncated = truncateToTokens('Very long text...', 100);
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
## Embedding Services
|
|
318
|
+
|
|
319
|
+
### OpenAI Embeddings
|
|
320
|
+
|
|
321
|
+
```typescript
|
|
322
|
+
import { OpenAIEmbeddingService, createEmbeddingService } from '@cogitator-ai/memory';
|
|
323
|
+
|
|
324
|
+
const embeddings = new OpenAIEmbeddingService({
|
|
325
|
+
apiKey: process.env.OPENAI_API_KEY!,
|
|
326
|
+
model: 'text-embedding-3-small',
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
const embeddings = createEmbeddingService({
|
|
330
|
+
provider: 'openai',
|
|
331
|
+
apiKey: process.env.OPENAI_API_KEY!,
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
const vector = await embeddings.embed('Hello, world!');
|
|
335
|
+
|
|
336
|
+
const vectors = await embeddings.embedBatch(['Hello', 'World']);
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Ollama Embeddings
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
import { OllamaEmbeddingService, createEmbeddingService } from '@cogitator-ai/memory';
|
|
343
|
+
|
|
344
|
+
const embeddings = new OllamaEmbeddingService({
|
|
345
|
+
model: 'nomic-embed-text',
|
|
346
|
+
baseUrl: 'http://localhost:11434',
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
const embeddings = createEmbeddingService({
|
|
350
|
+
provider: 'ollama',
|
|
351
|
+
model: 'nomic-embed-text',
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
const vector = await embeddings.embed('Hello, world!');
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
## Zod Schemas
|
|
360
|
+
|
|
361
|
+
Type-safe configuration validation:
|
|
362
|
+
|
|
363
|
+
```typescript
|
|
364
|
+
import {
|
|
365
|
+
MemoryProviderSchema,
|
|
366
|
+
InMemoryConfigSchema,
|
|
367
|
+
RedisConfigSchema,
|
|
368
|
+
PostgresConfigSchema,
|
|
369
|
+
MemoryAdapterConfigSchema,
|
|
370
|
+
ContextStrategySchema,
|
|
371
|
+
ContextBuilderConfigSchema,
|
|
372
|
+
EmbeddingProviderSchema,
|
|
373
|
+
OpenAIEmbeddingConfigSchema,
|
|
374
|
+
OllamaEmbeddingConfigSchema,
|
|
375
|
+
EmbeddingServiceConfigSchema,
|
|
376
|
+
} from '@cogitator-ai/memory';
|
|
377
|
+
|
|
378
|
+
const config = MemoryAdapterConfigSchema.parse({
|
|
379
|
+
provider: 'redis',
|
|
380
|
+
url: 'redis://localhost:6379',
|
|
381
|
+
ttl: 3600,
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
const builderConfig = ContextBuilderConfigSchema.parse({
|
|
58
385
|
maxTokens: 4000,
|
|
59
386
|
strategy: 'recent',
|
|
60
387
|
});
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
---
|
|
391
|
+
|
|
392
|
+
## Type Reference
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
import type {
|
|
396
|
+
MemoryType,
|
|
397
|
+
Thread,
|
|
398
|
+
MemoryEntry,
|
|
399
|
+
Fact,
|
|
400
|
+
Embedding,
|
|
401
|
+
MemoryProvider,
|
|
402
|
+
MemoryAdapterConfig,
|
|
403
|
+
RedisAdapterConfig,
|
|
404
|
+
PostgresAdapterConfig,
|
|
405
|
+
InMemoryAdapterConfig,
|
|
406
|
+
MemoryResult,
|
|
407
|
+
MemoryQueryOptions,
|
|
408
|
+
SemanticSearchOptions,
|
|
409
|
+
MemoryAdapter,
|
|
410
|
+
FactAdapter,
|
|
411
|
+
EmbeddingAdapter,
|
|
412
|
+
EmbeddingService,
|
|
413
|
+
EmbeddingProvider,
|
|
414
|
+
EmbeddingServiceConfig,
|
|
415
|
+
OpenAIEmbeddingConfig,
|
|
416
|
+
OllamaEmbeddingConfig,
|
|
417
|
+
ContextBuilderConfig,
|
|
418
|
+
ContextStrategy,
|
|
419
|
+
BuiltContext,
|
|
420
|
+
MemoryConfig,
|
|
421
|
+
} from '@cogitator-ai/memory';
|
|
422
|
+
```
|
|
61
423
|
|
|
62
|
-
|
|
63
|
-
|
|
424
|
+
---
|
|
425
|
+
|
|
426
|
+
## Examples
|
|
427
|
+
|
|
428
|
+
### Conversation History
|
|
429
|
+
|
|
430
|
+
```typescript
|
|
431
|
+
import { InMemoryAdapter } from '@cogitator-ai/memory';
|
|
432
|
+
|
|
433
|
+
const memory = new InMemoryAdapter();
|
|
434
|
+
await memory.connect();
|
|
435
|
+
|
|
436
|
+
const thread = await memory.createThread('chatbot');
|
|
437
|
+
|
|
438
|
+
const messages = [
|
|
439
|
+
{ role: 'user' as const, content: 'What is AI?' },
|
|
440
|
+
{ role: 'assistant' as const, content: 'AI is artificial intelligence...' },
|
|
441
|
+
{ role: 'user' as const, content: 'Tell me more' },
|
|
442
|
+
];
|
|
443
|
+
|
|
444
|
+
for (const msg of messages) {
|
|
445
|
+
await memory.addEntry({
|
|
446
|
+
threadId: thread.data!.id,
|
|
447
|
+
message: msg,
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
const history = await memory.getEntries({
|
|
452
|
+
threadId: thread.data!.id,
|
|
453
|
+
limit: 10,
|
|
454
|
+
});
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
### Token-Limited Context
|
|
458
|
+
|
|
459
|
+
```typescript
|
|
460
|
+
import { InMemoryAdapter, ContextBuilder, countMessagesTokens } from '@cogitator-ai/memory';
|
|
461
|
+
|
|
462
|
+
const memory = new InMemoryAdapter();
|
|
463
|
+
await memory.connect();
|
|
464
|
+
|
|
465
|
+
const builder = new ContextBuilder(
|
|
466
|
+
{ maxTokens: 2000, strategy: 'recent' },
|
|
467
|
+
{ memoryAdapter: memory }
|
|
468
|
+
);
|
|
469
|
+
|
|
470
|
+
const context = await builder.build({
|
|
471
|
+
threadId: 'thread_123',
|
|
472
|
+
agentId: 'agent-1',
|
|
473
|
+
systemPrompt: 'You are a concise assistant.',
|
|
64
474
|
});
|
|
475
|
+
|
|
476
|
+
console.log(`Using ${context.tokenCount} tokens`);
|
|
477
|
+
console.log(`Truncated: ${context.truncated}`);
|
|
478
|
+
console.log(
|
|
479
|
+
`Included ${context.metadata.includedMessageCount} of ${context.metadata.originalMessageCount} messages`
|
|
480
|
+
);
|
|
65
481
|
```
|
|
66
482
|
|
|
67
|
-
###
|
|
483
|
+
### Semantic Memory with PostgreSQL
|
|
68
484
|
|
|
69
485
|
```typescript
|
|
70
|
-
import {
|
|
486
|
+
import { PostgresAdapter, OpenAIEmbeddingService } from '@cogitator-ai/memory';
|
|
71
487
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
apiKey: process.env.OPENAI_API_KEY,
|
|
488
|
+
const memory = new PostgresAdapter({
|
|
489
|
+
connectionString: process.env.DATABASE_URL!,
|
|
75
490
|
});
|
|
76
491
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
492
|
+
const embeddings = new OpenAIEmbeddingService({
|
|
493
|
+
apiKey: process.env.OPENAI_API_KEY!,
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
await memory.connect();
|
|
497
|
+
|
|
498
|
+
const content = 'Machine learning is a subset of AI...';
|
|
499
|
+
const vector = await embeddings.embed(content);
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
---
|
|
503
|
+
|
|
504
|
+
## Knowledge Graph
|
|
505
|
+
|
|
506
|
+
Entity-relationship memory with multi-hop traversal and semantic reasoning.
|
|
507
|
+
|
|
508
|
+
### PostgresGraphAdapter
|
|
509
|
+
|
|
510
|
+
```typescript
|
|
511
|
+
import { PostgresGraphAdapter } from '@cogitator-ai/memory';
|
|
512
|
+
|
|
513
|
+
const graph = new PostgresGraphAdapter({
|
|
514
|
+
connectionString: process.env.DATABASE_URL!,
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
await graph.connect();
|
|
518
|
+
|
|
519
|
+
const person = await graph.addNode({
|
|
520
|
+
agentId: 'agent-1',
|
|
521
|
+
type: 'person',
|
|
522
|
+
name: 'Alice',
|
|
523
|
+
description: 'Software engineer',
|
|
524
|
+
properties: { role: 'developer' },
|
|
525
|
+
confidence: 1.0,
|
|
526
|
+
source: 'user',
|
|
80
527
|
});
|
|
528
|
+
|
|
529
|
+
const company = await graph.addNode({
|
|
530
|
+
agentId: 'agent-1',
|
|
531
|
+
type: 'organization',
|
|
532
|
+
name: 'TechCorp',
|
|
533
|
+
confidence: 1.0,
|
|
534
|
+
source: 'extracted',
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
await graph.addEdge({
|
|
538
|
+
agentId: 'agent-1',
|
|
539
|
+
sourceNodeId: person.id,
|
|
540
|
+
targetNodeId: company.id,
|
|
541
|
+
type: 'works_at',
|
|
542
|
+
weight: 1.0,
|
|
543
|
+
confidence: 0.95,
|
|
544
|
+
source: 'extracted',
|
|
545
|
+
});
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
### Multi-hop Traversal
|
|
549
|
+
|
|
550
|
+
```typescript
|
|
551
|
+
const result = await graph.traverse({
|
|
552
|
+
startNodeId: person.id,
|
|
553
|
+
maxDepth: 3,
|
|
554
|
+
direction: 'outgoing',
|
|
555
|
+
edgeTypes: ['works_at', 'knows', 'located_in'],
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
console.log('Visited nodes:', result.visitedNodes);
|
|
559
|
+
console.log('Paths found:', result.paths);
|
|
81
560
|
```
|
|
82
561
|
|
|
83
|
-
|
|
562
|
+
### Shortest Path
|
|
563
|
+
|
|
564
|
+
```typescript
|
|
565
|
+
const path = await graph.findShortestPath(startNodeId, endNodeId);
|
|
566
|
+
if (path) {
|
|
567
|
+
console.log('Path:', path.nodes.map((n) => n.name).join(' -> '));
|
|
568
|
+
console.log('Total weight:', path.totalWeight);
|
|
569
|
+
}
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
### Semantic Node Search
|
|
573
|
+
|
|
574
|
+
```typescript
|
|
575
|
+
const similar = await graph.searchNodesSemantic({
|
|
576
|
+
agentId: 'agent-1',
|
|
577
|
+
query: 'machine learning engineer',
|
|
578
|
+
limit: 10,
|
|
579
|
+
threshold: 0.7,
|
|
580
|
+
});
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
### LLM Entity Extraction
|
|
584
|
+
|
|
585
|
+
```typescript
|
|
586
|
+
import { LLMEntityExtractor } from '@cogitator-ai/memory';
|
|
587
|
+
|
|
588
|
+
const extractor = new LLMEntityExtractor(llmBackend, {
|
|
589
|
+
minConfidence: 0.7,
|
|
590
|
+
maxEntitiesPerText: 20,
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
const result = await extractor.extract(
|
|
594
|
+
'Alice works at TechCorp in San Francisco. She knows Bob from the AI conference.'
|
|
595
|
+
);
|
|
596
|
+
|
|
597
|
+
console.log('Entities:', result.entities);
|
|
598
|
+
console.log('Relations:', result.relations);
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
### Graph Inference Engine
|
|
602
|
+
|
|
603
|
+
```typescript
|
|
604
|
+
import { GraphInferenceEngine } from '@cogitator-ai/memory';
|
|
605
|
+
|
|
606
|
+
const engine = new GraphInferenceEngine(graph, {
|
|
607
|
+
minConfidence: 0.5,
|
|
608
|
+
maxInferredEdges: 100,
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
const inferred = await engine.infer('agent-1');
|
|
612
|
+
console.log('Inferred edges:', inferred.edges);
|
|
613
|
+
console.log('Rules applied:', inferred.rulesApplied);
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
### Graph Context Builder
|
|
617
|
+
|
|
618
|
+
```typescript
|
|
619
|
+
import { GraphContextBuilder } from '@cogitator-ai/memory';
|
|
620
|
+
|
|
621
|
+
const contextBuilder = new GraphContextBuilder(graph, embeddingService, {
|
|
622
|
+
maxNodes: 20,
|
|
623
|
+
maxEdges: 50,
|
|
624
|
+
includeInferred: true,
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
const context = await contextBuilder.buildContext({
|
|
628
|
+
agentId: 'agent-1',
|
|
629
|
+
query: 'Tell me about Alice and her work',
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
console.log('Relevant nodes:', context.nodes);
|
|
633
|
+
console.log('Relationships:', context.edges);
|
|
634
|
+
```
|
|
84
635
|
|
|
85
|
-
|
|
636
|
+
---
|
|
86
637
|
|
|
87
638
|
## License
|
|
88
639
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-builder.d.ts","sourceRoot":"","sources":["../src/context-builder.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAKV,oBAAoB,EACpB,YAAY,EACZ,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,qBAAqB,CAAC;AAG7B,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,aAAa,CAAC;IAC7B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,IAAI,CAAqB;gBAErB,MAAM,EAAE,oBAAoB,EAAE,IAAI,EAAE,kBAAkB;
|
|
1
|
+
{"version":3,"file":"context-builder.d.ts","sourceRoot":"","sources":["../src/context-builder.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAKV,oBAAoB,EACpB,YAAY,EACZ,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,qBAAqB,CAAC;AAG7B,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,aAAa,CAAC;IAC7B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,IAAI,CAAqB;gBAErB,MAAM,EAAE,oBAAoB,EAAE,IAAI,EAAE,kBAAkB;IAe5D,KAAK,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,CAAC;IA+HhE,OAAO,CAAC,mBAAmB;CAgB5B"}
|
package/dist/context-builder.js
CHANGED
|
@@ -16,6 +16,8 @@ export class ContextBuilder {
|
|
|
16
16
|
includeSystemPrompt: config.includeSystemPrompt ?? true,
|
|
17
17
|
includeFacts: config.includeFacts ?? false,
|
|
18
18
|
includeSemanticContext: config.includeSemanticContext ?? false,
|
|
19
|
+
includeGraphContext: config.includeGraphContext ?? false,
|
|
20
|
+
graphContextOptions: config.graphContextOptions ?? {},
|
|
19
21
|
};
|
|
20
22
|
this.deps = deps;
|
|
21
23
|
}
|
|
@@ -120,6 +122,8 @@ export class ContextBuilder {
|
|
|
120
122
|
includedMessageCount: messages.length - (this.config.includeSystemPrompt && options.systemPrompt ? 1 : 0),
|
|
121
123
|
factsIncluded: facts.length,
|
|
122
124
|
semanticResultsIncluded: semanticResults.length,
|
|
125
|
+
graphNodesIncluded: 0,
|
|
126
|
+
graphEdgesIncluded: 0,
|
|
123
127
|
},
|
|
124
128
|
};
|
|
125
129
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-builder.js","sourceRoot":"","sources":["../src/context-builder.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAcH,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAgBlE,MAAM,OAAO,cAAc;IACjB,MAAM,CAAiC;IACvC,IAAI,CAAqB;IAEjC,YAAY,MAA4B,EAAE,IAAwB;QAChE,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC;QACzE,IAAI,CAAC,MAAM,GAAG;YACZ,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,aAAa,EAAE,MAAM,CAAC,aAAa,IAAI,cAAc;YACrD,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,mBAAmB,EAAE,MAAM,CAAC,mBAAmB,IAAI,IAAI;YACvD,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,KAAK;YAC1C,sBAAsB,EAAE,MAAM,CAAC,sBAAsB,IAAI,KAAK;
|
|
1
|
+
{"version":3,"file":"context-builder.js","sourceRoot":"","sources":["../src/context-builder.ts"],"names":[],"mappings":"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"}
|