@rudderjs/ai 1.18.2 → 1.18.3
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/budget-orm/index.d.ts +95 -1
- package/dist/budget-orm/index.d.ts.map +1 -1
- package/dist/budget-orm/index.js +176 -4
- package/dist/budget-orm/index.js.map +1 -1
- package/dist/conversation-orm/index.d.ts +115 -1
- package/dist/conversation-orm/index.d.ts.map +1 -1
- package/dist/conversation-orm/index.js +214 -4
- package/dist/conversation-orm/index.js.map +1 -1
- package/dist/doctor.d.ts +1 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +67 -4
- package/dist/doctor.js.map +1 -1
- package/dist/memory-embedding/index.d.ts +120 -1
- package/dist/memory-embedding/index.d.ts.map +1 -1
- package/dist/memory-embedding/index.js +228 -4
- package/dist/memory-embedding/index.js.map +1 -1
- package/dist/memory-orm/index.d.ts +117 -1
- package/dist/memory-orm/index.d.ts.map +1 -1
- package/dist/memory-orm/index.js +186 -4
- package/dist/memory-orm/index.js.map +1 -1
- package/package.json +10 -4
package/dist/memory-orm/index.js
CHANGED
|
@@ -1,5 +1,187 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
/**
|
|
2
|
+
* `@rudderjs/ai/memory-orm` — ORM-backed {@link UserMemory} for #A4 Phase 4.
|
|
3
|
+
*
|
|
4
|
+
* Stores per-user facts in a `UserMemory` table via the registered
|
|
5
|
+
* `@rudderjs/orm` adapter (Prisma today; Drizzle as well once the user's
|
|
6
|
+
* tables are wired). Drop-in alongside Phase 1's in-process
|
|
7
|
+
* `MemoryUserMemory`.
|
|
8
|
+
*
|
|
9
|
+
* Wire it from your AI config:
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* // config/ai.ts
|
|
13
|
+
* import type { AiConfig } from '@gemstack/ai-sdk'
|
|
14
|
+
* import { OrmUserMemory } from '@rudderjs/ai/memory-orm'
|
|
15
|
+
*
|
|
16
|
+
* export default {
|
|
17
|
+
* default: 'anthropic/claude-sonnet-4-5',
|
|
18
|
+
* providers: { ... },
|
|
19
|
+
* memory: new OrmUserMemory(),
|
|
20
|
+
* } satisfies AiConfig
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* The schema lives at `@rudderjs/ai/memory-orm`'s {@link userMemoryPrismaSchema}
|
|
24
|
+
* — copy it into your Prisma schema. The optional `embedding Bytes?`
|
|
25
|
+
* column is shipped here in Phase 4 (intentionally nullable) so Phase 5's
|
|
26
|
+
* `EmbeddingUserMemory` can populate it without forcing an additive
|
|
27
|
+
* migration.
|
|
28
|
+
*/
|
|
29
|
+
import { Model } from '@rudderjs/orm';
|
|
30
|
+
// ─── ORM Model ────────────────────────────────────────────
|
|
31
|
+
/**
|
|
32
|
+
* The Model row backing {@link OrmUserMemory}. Exposed so apps that
|
|
33
|
+
* want their own queries (admin views, audit dumps) can use the
|
|
34
|
+
* familiar `UserMemoryRecord.where(...).get()` instead of routing
|
|
35
|
+
* everything through the {@link UserMemory} interface.
|
|
36
|
+
*
|
|
37
|
+
* Tags persist as a JSON-encoded string in the `tags` column — both
|
|
38
|
+
* Prisma's portable `String?` and Drizzle's `text` work without
|
|
39
|
+
* needing native array columns. The {@link UserMemory.recall} path
|
|
40
|
+
* filters tags in JavaScript for the same reason.
|
|
41
|
+
*
|
|
42
|
+
* The `embedding Bytes?` column is in the schema as of Phase 4
|
|
43
|
+
* (nullable) so `@rudderjs/ai/memory-embedding`'s `EmbeddingUserMemory`
|
|
44
|
+
* (Phase 5) writes the Float32-packed vector here on `remember()` and
|
|
45
|
+
* reads it for cosine recall. `OrmUserMemory` ignores it — the
|
|
46
|
+
* column stays `null` for any row stored without the embedding
|
|
47
|
+
* composer.
|
|
48
|
+
*/
|
|
49
|
+
export class UserMemoryRecord extends Model {
|
|
50
|
+
static table = 'userMemory';
|
|
51
|
+
static fillable = ['userId', 'fact', 'tags', 'score', 'embedding'];
|
|
52
|
+
/** Parsed tags array; empty when nothing was stored. */
|
|
53
|
+
getTags() {
|
|
54
|
+
if (this.tags == null || this.tags === '')
|
|
55
|
+
return [];
|
|
56
|
+
try {
|
|
57
|
+
const parsed = JSON.parse(this.tags);
|
|
58
|
+
return Array.isArray(parsed) ? parsed.filter(t => typeof t === 'string') : [];
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// ─── UserMemory adapter ───────────────────────────────────
|
|
66
|
+
/**
|
|
67
|
+
* `UserMemory` implementation that persists rows to the registered
|
|
68
|
+
* ORM adapter. Designed for production use — the in-process
|
|
69
|
+
* `MemoryUserMemory` is for tests and dev.
|
|
70
|
+
*
|
|
71
|
+
* Adapter coverage:
|
|
72
|
+
* - Prisma — works out of the box; copy {@link userMemoryPrismaSchema}
|
|
73
|
+
* into your schema.
|
|
74
|
+
* - Drizzle — works once you define a table matching the schema's
|
|
75
|
+
* columns and register it via `tables: { userMemory: <table> }` on
|
|
76
|
+
* the `drizzle()` config.
|
|
77
|
+
*
|
|
78
|
+
* Recall semantics: case-insensitive **token-OR-LIKE** matching against
|
|
79
|
+
* the `fact` column. The query is tokenized on non-alphanumeric
|
|
80
|
+
* boundaries (≥3-char tokens) and any row whose `fact` matches at
|
|
81
|
+
* least one token via `LIKE %tok%` is returned. Mirrors Phase 1's
|
|
82
|
+
* `MemoryUserMemory.recall()` behavior so the two backends are
|
|
83
|
+
* swap-compatible. Tag scope is applied JS-side after fetch — pushing
|
|
84
|
+
* tag-array filtering into the WHERE is adapter-specific and lands in a
|
|
85
|
+
* follow-up.
|
|
86
|
+
*/
|
|
87
|
+
export class OrmUserMemory {
|
|
88
|
+
async remember(userId, fact, opts) {
|
|
89
|
+
const data = { userId, fact };
|
|
90
|
+
if (opts?.tags !== undefined)
|
|
91
|
+
data['tags'] = JSON.stringify(opts.tags);
|
|
92
|
+
if (opts?.score !== undefined)
|
|
93
|
+
data['score'] = opts.score;
|
|
94
|
+
const created = await UserMemoryRecord.create(data);
|
|
95
|
+
return rowToEntry(created);
|
|
96
|
+
}
|
|
97
|
+
async recall(userId, query, opts) {
|
|
98
|
+
const tokens = tokenize(query);
|
|
99
|
+
let q = UserMemoryRecord.where('userId', userId);
|
|
100
|
+
if (tokens.size > 0) {
|
|
101
|
+
const tokenList = [...tokens];
|
|
102
|
+
q = q.whereGroup(g => {
|
|
103
|
+
for (const tok of tokenList)
|
|
104
|
+
g.orWhere('fact', 'LIKE', `%${tok}%`);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
const rows = await q.orderBy('createdAt', 'ASC').get();
|
|
108
|
+
const entries = rows.map(rowToEntry).filter(e => matchesTags(e, opts?.tags));
|
|
109
|
+
return capLimit(entries, opts?.limit);
|
|
110
|
+
}
|
|
111
|
+
async forget(userId, factId) {
|
|
112
|
+
const row = await UserMemoryRecord.where('id', factId).where('userId', userId).first();
|
|
113
|
+
if (row)
|
|
114
|
+
await row.delete();
|
|
115
|
+
}
|
|
116
|
+
async list(userId, opts) {
|
|
117
|
+
const rows = await UserMemoryRecord.where('userId', userId).orderBy('createdAt', 'ASC').get();
|
|
118
|
+
const entries = rows.map(rowToEntry).filter(e => matchesTags(e, opts?.tags));
|
|
119
|
+
return capLimit(entries, opts?.limit);
|
|
120
|
+
}
|
|
121
|
+
async forgetAll(userId) {
|
|
122
|
+
await UserMemoryRecord.where('userId', userId).deleteAll();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// ─── Schema reference ─────────────────────────────────────
|
|
126
|
+
/**
|
|
127
|
+
* Reference Prisma schema for `OrmUserMemory`. Copy into your
|
|
128
|
+
* `prisma/schema/<file>.prisma` (or paste alongside an existing
|
|
129
|
+
* model). The `embedding Bytes?` column is intentionally nullable so
|
|
130
|
+
* Phase 5's `EmbeddingUserMemory` becomes additive — no schema
|
|
131
|
+
* migration when you upgrade.
|
|
132
|
+
*
|
|
133
|
+
* SQLite stores `Bytes` as `BLOB`; Postgres stores it as `bytea`.
|
|
134
|
+
* Both work for the dot-product implementation Phase 5 will use.
|
|
135
|
+
*/
|
|
136
|
+
export const userMemoryPrismaSchema = `model UserMemory {
|
|
137
|
+
id String @id @default(cuid())
|
|
138
|
+
userId String
|
|
139
|
+
fact String
|
|
140
|
+
/// JSON-encoded \`string[]\` of tags, or null
|
|
141
|
+
tags String?
|
|
142
|
+
/// Confidence score in [0, 1] — extract sets this from the model's self-rating
|
|
143
|
+
score Float?
|
|
144
|
+
/// Phase 5 — vector embedding for cosine recall (nullable so Phase 4 ignores it)
|
|
145
|
+
embedding Bytes?
|
|
146
|
+
createdAt DateTime @default(now())
|
|
147
|
+
updatedAt DateTime @updatedAt
|
|
148
|
+
|
|
149
|
+
@@index([userId])
|
|
150
|
+
}
|
|
151
|
+
`;
|
|
152
|
+
// ─── Helpers ──────────────────────────────────────────────
|
|
153
|
+
function rowToEntry(row) {
|
|
154
|
+
const tags = row.getTags();
|
|
155
|
+
const out = {
|
|
156
|
+
id: row.id,
|
|
157
|
+
userId: row.userId,
|
|
158
|
+
fact: row.fact,
|
|
159
|
+
createdAt: row.createdAt,
|
|
160
|
+
};
|
|
161
|
+
if (tags.length > 0)
|
|
162
|
+
out.tags = tags;
|
|
163
|
+
if (row.score != null)
|
|
164
|
+
out.score = row.score;
|
|
165
|
+
if (row.updatedAt != null)
|
|
166
|
+
out.updatedAt = row.updatedAt;
|
|
167
|
+
return out;
|
|
168
|
+
}
|
|
169
|
+
function tokenize(s) {
|
|
170
|
+
const out = new Set();
|
|
171
|
+
for (const tok of s.toLowerCase().split(/[^a-z0-9]+/)) {
|
|
172
|
+
if (tok.length >= 3)
|
|
173
|
+
out.add(tok);
|
|
174
|
+
}
|
|
175
|
+
return out;
|
|
176
|
+
}
|
|
177
|
+
function matchesTags(entry, wanted) {
|
|
178
|
+
if (!wanted || wanted.length === 0)
|
|
179
|
+
return true;
|
|
180
|
+
if (!entry.tags || entry.tags.length === 0)
|
|
181
|
+
return false;
|
|
182
|
+
return wanted.every(t => entry.tags.includes(t));
|
|
183
|
+
}
|
|
184
|
+
function capLimit(items, limit) {
|
|
185
|
+
return limit !== undefined && limit > 0 ? items.slice(0, limit) : items;
|
|
186
|
+
}
|
|
5
187
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/memory-orm/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/memory-orm/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rudderjs/ai",
|
|
3
|
-
"version": "1.18.
|
|
3
|
+
"version": "1.18.3",
|
|
4
4
|
"description": "[Deprecated] Moved to @gemstack/ai-sdk. This package now re-exports it for backwards compatibility.",
|
|
5
5
|
"rudderjs": {
|
|
6
6
|
"provider": "AiProvider",
|
|
@@ -99,10 +99,14 @@
|
|
|
99
99
|
"peerDependencies": {
|
|
100
100
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
101
101
|
"react": ">=19.2.0",
|
|
102
|
-
"@rudderjs/
|
|
103
|
-
"@rudderjs/orm": "^1.22.0"
|
|
102
|
+
"@rudderjs/console": "^1.4.3",
|
|
103
|
+
"@rudderjs/orm": "^1.22.0",
|
|
104
|
+
"@rudderjs/core": "^1.13.3"
|
|
104
105
|
},
|
|
105
106
|
"peerDependenciesMeta": {
|
|
107
|
+
"@rudderjs/console": {
|
|
108
|
+
"optional": true
|
|
109
|
+
},
|
|
106
110
|
"@rudderjs/core": {
|
|
107
111
|
"optional": true
|
|
108
112
|
},
|
|
@@ -131,6 +135,7 @@
|
|
|
131
135
|
"@types/react": "^19.2.0",
|
|
132
136
|
"react": "^19.2.0",
|
|
133
137
|
"typescript": "^5.4.0",
|
|
138
|
+
"@rudderjs/console": "^1.4.3",
|
|
134
139
|
"@rudderjs/core": "^1.13.3",
|
|
135
140
|
"@rudderjs/orm": "^1.22.0"
|
|
136
141
|
},
|
|
@@ -139,6 +144,7 @@
|
|
|
139
144
|
"build": "tsc -p tsconfig.build.json",
|
|
140
145
|
"dev": "tsc -p tsconfig.build.json --watch",
|
|
141
146
|
"typecheck": "tsc --noEmit",
|
|
142
|
-
"
|
|
147
|
+
"test": "tsc -p tsconfig.test.json && node --test \"dist-test/**/*.test.js\"",
|
|
148
|
+
"clean": "rm -rf dist dist-test"
|
|
143
149
|
}
|
|
144
150
|
}
|