@batonfx/memory 0.3.4 → 0.3.5
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/.turbo/turbo-build.log +1 -1
- package/dist/index.js +24 -3
- package/package.json +2 -2
- package/src/semantic-recall.ts +1 -1
- package/src/vector-store.ts +7 -1
- package/src/working-memory.ts +16 -1
- package/test/semantic-recall.test.ts +33 -0
- package/test/vector-store.test.ts +20 -0
- package/test/working-memory.test.ts +27 -0
package/.turbo/turbo-build.log
CHANGED
package/dist/index.js
CHANGED
|
@@ -32865,7 +32865,11 @@ var make37 = exports_Ref.make(exports_HashMap.empty()).pipe(exports_Effect.map((
|
|
|
32865
32865
|
}
|
|
32866
32866
|
return matches.toSorted((left, right) => right.score - left.score).slice(0, input.limit);
|
|
32867
32867
|
}),
|
|
32868
|
-
delete: (input) => exports_Ref.update(documents, (current) => exports_HashMap.filter(current, (document) =>
|
|
32868
|
+
delete: (input) => exports_Ref.update(documents, (current) => exports_HashMap.filter(current, (document) => {
|
|
32869
|
+
if (!sameKey(document.key, input.key))
|
|
32870
|
+
return true;
|
|
32871
|
+
return input.id === undefined ? false : document.id !== input.id;
|
|
32872
|
+
}))
|
|
32869
32873
|
})));
|
|
32870
32874
|
var memoryLayer2 = exports_Layer.effect(VectorStore, make37.pipe(exports_Effect.map(VectorStore.of)));
|
|
32871
32875
|
var testLayer2 = (implementation) => exports_Layer.succeed(VectorStore, VectorStore.of(implementation));
|
|
@@ -32943,7 +32947,7 @@ var make38 = (options = {}) => exports_Effect.gen(function* () {
|
|
|
32943
32947
|
}
|
|
32944
32948
|
])))), exports_Effect.mapError(memoryError));
|
|
32945
32949
|
},
|
|
32946
|
-
forget: (input) => store.delete(
|
|
32950
|
+
forget: (input) => store.delete(input).pipe(exports_Effect.mapError(memoryError))
|
|
32947
32951
|
};
|
|
32948
32952
|
});
|
|
32949
32953
|
var makeSemanticRecall = make38;
|
|
@@ -33069,7 +33073,24 @@ var make39 = (options = {}) => exports_Ref.make(exports_HashMap.empty()).pipe(ex
|
|
|
33069
33073
|
yield* exports_Ref.update(states, exports_HashMap.set(id2, nextState));
|
|
33070
33074
|
});
|
|
33071
33075
|
},
|
|
33072
|
-
forget: (input) => exports_Ref.update(states,
|
|
33076
|
+
forget: (input) => exports_Ref.update(states, (current) => {
|
|
33077
|
+
const id2 = keyId(input.key);
|
|
33078
|
+
if (input.id === undefined)
|
|
33079
|
+
return exports_HashMap.remove(current, id2);
|
|
33080
|
+
const existing = exports_HashMap.get(current, id2);
|
|
33081
|
+
if (existing._tag === "None")
|
|
33082
|
+
return current;
|
|
33083
|
+
const summary = input.id === "working-summary" ? undefined : existing.value.summary;
|
|
33084
|
+
const recent = existing.value.recent.filter((item) => item.id !== input.id);
|
|
33085
|
+
if (summary === undefined && recent.length === 0)
|
|
33086
|
+
return exports_HashMap.remove(current, id2);
|
|
33087
|
+
const nextState = {
|
|
33088
|
+
recent,
|
|
33089
|
+
counter: existing.value.counter,
|
|
33090
|
+
...summary === undefined ? {} : { summary }
|
|
33091
|
+
};
|
|
33092
|
+
return exports_HashMap.set(current, id2, nextState);
|
|
33093
|
+
})
|
|
33073
33094
|
};
|
|
33074
33095
|
}));
|
|
33075
33096
|
var makeWorkingMemory = make39;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@batonfx/memory",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.5",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
7
7
|
"exports": {
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"typecheck": "bun tsc --noEmit"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@batonfx/core": "0.3.
|
|
17
|
+
"@batonfx/core": "0.3.5",
|
|
18
18
|
"effect": "4.0.0-beta.93"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
package/src/semantic-recall.ts
CHANGED
|
@@ -109,7 +109,7 @@ export const make = (
|
|
|
109
109
|
Effect.mapError(memoryError),
|
|
110
110
|
)
|
|
111
111
|
},
|
|
112
|
-
forget: (input) => store.delete(
|
|
112
|
+
forget: (input) => store.delete(input).pipe(Effect.mapError(memoryError)),
|
|
113
113
|
}
|
|
114
114
|
})
|
|
115
115
|
|
package/src/vector-store.ts
CHANGED
|
@@ -31,6 +31,7 @@ export interface Query {
|
|
|
31
31
|
/** @experimental */
|
|
32
32
|
export interface DeleteInput {
|
|
33
33
|
readonly key: Memory.Key
|
|
34
|
+
readonly id?: string | undefined
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
/** @experimental */
|
|
@@ -113,7 +114,12 @@ const make = Ref.make(HashMap.empty<string, Embedded>()).pipe(
|
|
|
113
114
|
return matches.toSorted((left, right) => right.score - left.score).slice(0, input.limit)
|
|
114
115
|
}),
|
|
115
116
|
delete: (input) =>
|
|
116
|
-
Ref.update(documents, (current) =>
|
|
117
|
+
Ref.update(documents, (current) =>
|
|
118
|
+
HashMap.filter(current, (document) => {
|
|
119
|
+
if (!sameKey(document.key, input.key)) return true
|
|
120
|
+
return input.id === undefined ? false : document.id !== input.id
|
|
121
|
+
}),
|
|
122
|
+
),
|
|
117
123
|
}),
|
|
118
124
|
),
|
|
119
125
|
)
|
package/src/working-memory.ts
CHANGED
|
@@ -180,7 +180,22 @@ export const make = (options: Options = {}): Effect.Effect<Memory.Interface> =>
|
|
|
180
180
|
yield* Ref.update(states, HashMap.set(id, nextState))
|
|
181
181
|
})
|
|
182
182
|
},
|
|
183
|
-
forget: (input) =>
|
|
183
|
+
forget: (input) =>
|
|
184
|
+
Ref.update(states, (current) => {
|
|
185
|
+
const id = keyId(input.key)
|
|
186
|
+
if (input.id === undefined) return HashMap.remove(current, id)
|
|
187
|
+
const existing = HashMap.get(current, id)
|
|
188
|
+
if (existing._tag === "None") return current
|
|
189
|
+
const summary = input.id === "working-summary" ? undefined : existing.value.summary
|
|
190
|
+
const recent = existing.value.recent.filter((item) => item.id !== input.id)
|
|
191
|
+
if (summary === undefined && recent.length === 0) return HashMap.remove(current, id)
|
|
192
|
+
const nextState: KeyState = {
|
|
193
|
+
recent,
|
|
194
|
+
counter: existing.value.counter,
|
|
195
|
+
...(summary === undefined ? {} : { summary }),
|
|
196
|
+
}
|
|
197
|
+
return HashMap.set(current, id, nextState)
|
|
198
|
+
}),
|
|
184
199
|
}
|
|
185
200
|
}),
|
|
186
201
|
)
|
|
@@ -91,6 +91,39 @@ describe("SemanticRecall", () => {
|
|
|
91
91
|
}).pipe(Effect.provide(memoryLayer)),
|
|
92
92
|
)
|
|
93
93
|
|
|
94
|
+
it.effect("forgets one semantic memory id within the exact memory key", () =>
|
|
95
|
+
Effect.gen(function* () {
|
|
96
|
+
const memory = yield* Memory.Memory
|
|
97
|
+
|
|
98
|
+
yield* memory.remember({
|
|
99
|
+
key,
|
|
100
|
+
turn: 0,
|
|
101
|
+
terminal: true,
|
|
102
|
+
transcript: prompt(user("What color is the sky?"), assistant("blue")),
|
|
103
|
+
})
|
|
104
|
+
yield* memory.remember({
|
|
105
|
+
key,
|
|
106
|
+
turn: 1,
|
|
107
|
+
terminal: true,
|
|
108
|
+
transcript: prompt(user("What color is the ocean?"), assistant("blue")),
|
|
109
|
+
})
|
|
110
|
+
yield* memory.remember({
|
|
111
|
+
key: otherKey,
|
|
112
|
+
turn: 0,
|
|
113
|
+
terminal: true,
|
|
114
|
+
transcript: prompt(user("What color is the door?"), assistant("blue")),
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
yield* memory.forget({ key, id: "semantic-1" })
|
|
118
|
+
|
|
119
|
+
const retained = yield* memory.recall({ key, turn: 0, prompt: prompt(user("color")) })
|
|
120
|
+
const otherRetained = yield* memory.recall({ key: otherKey, turn: 0, prompt: prompt(user("color")) })
|
|
121
|
+
|
|
122
|
+
expect(retained.map(itemText)).toEqual(["User: What color is the ocean?\nAssistant: blue"])
|
|
123
|
+
expect(otherRetained.map(itemText)).toEqual(["User: What color is the door?\nAssistant: blue"])
|
|
124
|
+
}).pipe(Effect.provide(memoryLayer)),
|
|
125
|
+
)
|
|
126
|
+
|
|
94
127
|
it.effect("maps embedding failures to MemoryError", () => {
|
|
95
128
|
const embeddingError = AiError.make({
|
|
96
129
|
module: "SemanticRecallTest",
|
|
@@ -98,4 +98,24 @@ describe("VectorStore", () => {
|
|
|
98
98
|
expect(remainingMatches.map((match) => match.document.text)).toEqual(["other subject"])
|
|
99
99
|
}).pipe(Effect.provide(VectorStore.memoryLayer)),
|
|
100
100
|
)
|
|
101
|
+
|
|
102
|
+
it.effect("deletes one document id within the exact memory key", () =>
|
|
103
|
+
Effect.gen(function* () {
|
|
104
|
+
const store = yield* VectorStore.VectorStore
|
|
105
|
+
|
|
106
|
+
yield* store.upsert([
|
|
107
|
+
document("first", key, "first", [1, 0]),
|
|
108
|
+
document("second", key, "second", [0, 1]),
|
|
109
|
+
document("first", otherSubject, "other subject", [1, 0]),
|
|
110
|
+
])
|
|
111
|
+
|
|
112
|
+
yield* store.delete({ key, id: "first" })
|
|
113
|
+
|
|
114
|
+
const deletedKeyMatches = yield* store.query({ key, embedding: [1, 0], limit: 10 })
|
|
115
|
+
const otherSubjectMatches = yield* store.query({ key: otherSubject, embedding: [1, 0], limit: 10 })
|
|
116
|
+
|
|
117
|
+
expect(deletedKeyMatches.map((match) => match.document.text)).toEqual(["second"])
|
|
118
|
+
expect(otherSubjectMatches.map((match) => match.document.text)).toEqual(["other subject"])
|
|
119
|
+
}).pipe(Effect.provide(VectorStore.memoryLayer)),
|
|
120
|
+
)
|
|
101
121
|
})
|
|
@@ -125,4 +125,31 @@ describe("WorkingMemory", () => {
|
|
|
125
125
|
expect(retained.map(itemText)).toEqual(["User: three", "Assistant: four"])
|
|
126
126
|
}).pipe(Effect.provide(WorkingMemory.layer({ maxMessages: 2 }))),
|
|
127
127
|
)
|
|
128
|
+
|
|
129
|
+
it.effect("forgets one recalled item id within the exact memory key", () =>
|
|
130
|
+
Effect.gen(function* () {
|
|
131
|
+
const memory = yield* Memory.Memory
|
|
132
|
+
|
|
133
|
+
yield* memory.remember({
|
|
134
|
+
key,
|
|
135
|
+
turn: 0,
|
|
136
|
+
terminal: true,
|
|
137
|
+
transcript: prompt(user("one"), assistant("two")),
|
|
138
|
+
})
|
|
139
|
+
yield* memory.remember({
|
|
140
|
+
key: otherKey,
|
|
141
|
+
turn: 0,
|
|
142
|
+
terminal: true,
|
|
143
|
+
transcript: prompt(user("three"), assistant("four")),
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
yield* memory.forget({ key, id: "working-1" })
|
|
147
|
+
|
|
148
|
+
const retained = yield* memory.recall({ key, turn: 0, prompt: prompt(user("current")) })
|
|
149
|
+
const otherRetained = yield* memory.recall({ key: otherKey, turn: 0, prompt: prompt(user("current")) })
|
|
150
|
+
|
|
151
|
+
expect(retained.map(itemText)).toEqual(["Assistant: two"])
|
|
152
|
+
expect(otherRetained.map(itemText)).toEqual(["User: three", "Assistant: four"])
|
|
153
|
+
}).pipe(Effect.provide(WorkingMemory.layer({ maxMessages: 2 }))),
|
|
154
|
+
)
|
|
128
155
|
})
|