@batonfx/memory 0.4.0 → 0.4.2
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 +5 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +14 -33120
- package/dist/semantic-recall.d.ts +15 -0
- package/dist/semantic-recall.js +90 -0
- package/dist/vector-store.d.ts +51 -0
- package/dist/vector-store.js +77 -0
- package/dist/working-memory.d.ts +19 -0
- package/dist/working-memory.js +143 -0
- package/package.json +29 -4
- package/.turbo/turbo-build.log +0 -5
- package/src/index.ts +0 -29
- package/src/semantic-recall.ts +0 -123
- package/src/vector-store.ts +0 -132
- package/src/working-memory.ts +0 -208
- package/test/index.test.ts +0 -55
- package/test/semantic-recall.test.ts +0 -154
- package/test/vector-store.test.ts +0 -121
- package/test/working-memory.test.ts +0 -155
- package/tsconfig.json +0 -7
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "@effect/vitest"
|
|
2
|
-
import { Effect, Layer, Stream } from "effect"
|
|
3
|
-
import { LanguageModel, Prompt } from "effect/unstable/ai"
|
|
4
|
-
import { Memory } from "@batonfx/core"
|
|
5
|
-
import { WorkingMemory } from "../src/index"
|
|
6
|
-
|
|
7
|
-
const key: Memory.Key = { agent: "memory-agent", subject: "subject-a" }
|
|
8
|
-
const otherKey: Memory.Key = { agent: "memory-agent", subject: "subject-b" }
|
|
9
|
-
|
|
10
|
-
const textPart = (text: string) => Prompt.makePart("text", { text })
|
|
11
|
-
const user = (text: string) => Prompt.makeMessage("user", { content: [textPart(text)] })
|
|
12
|
-
const assistant = (text: string) => Prompt.makeMessage("assistant", { content: [textPart(text)] })
|
|
13
|
-
const prompt = (...messages: ReadonlyArray<Prompt.Message>) => Prompt.fromMessages(messages)
|
|
14
|
-
|
|
15
|
-
const itemText = (item: Memory.Item): string =>
|
|
16
|
-
item.parts
|
|
17
|
-
.filter((part): part is Prompt.TextPart => part.type === "text")
|
|
18
|
-
.map((part) => part.text)
|
|
19
|
-
.join("")
|
|
20
|
-
|
|
21
|
-
describe("WorkingMemory", () => {
|
|
22
|
-
it.effect("keeps a bounded recent tail", () =>
|
|
23
|
-
Effect.gen(function* () {
|
|
24
|
-
const memory = yield* Memory.Memory
|
|
25
|
-
|
|
26
|
-
yield* memory.remember({
|
|
27
|
-
key,
|
|
28
|
-
turn: 0,
|
|
29
|
-
terminal: true,
|
|
30
|
-
transcript: prompt(user("one"), assistant("two"), user("three")),
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
const recalled = yield* memory.recall({ key, turn: 0, prompt: prompt(user("current")) })
|
|
34
|
-
|
|
35
|
-
expect(recalled.map(itemText)).toEqual(["Assistant: two", "User: three"])
|
|
36
|
-
}).pipe(Effect.provide(WorkingMemory.layer({ maxMessages: 2 }))),
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
it.effect("summarizes overflow once and recalls summary before the recent tail", () => {
|
|
40
|
-
let summaryCalls = 0
|
|
41
|
-
let summaryPrompt = ""
|
|
42
|
-
const summaryModel = Layer.effect(
|
|
43
|
-
LanguageModel.LanguageModel,
|
|
44
|
-
LanguageModel.make({
|
|
45
|
-
generateText: (options) =>
|
|
46
|
-
Effect.sync(() => {
|
|
47
|
-
summaryCalls += 1
|
|
48
|
-
summaryPrompt = JSON.stringify(options.prompt.content)
|
|
49
|
-
return [{ type: "text", text: "summary" }]
|
|
50
|
-
}),
|
|
51
|
-
streamText: () => Stream.empty,
|
|
52
|
-
}),
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
return Effect.gen(function* () {
|
|
56
|
-
const memory = yield* Memory.Memory
|
|
57
|
-
|
|
58
|
-
yield* memory.remember({
|
|
59
|
-
key,
|
|
60
|
-
turn: 0,
|
|
61
|
-
terminal: true,
|
|
62
|
-
transcript: prompt(user("one"), assistant("two"), user("three"), assistant("four")),
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
const recalled = yield* memory.recall({ key, turn: 0, prompt: prompt(user("current")) })
|
|
66
|
-
|
|
67
|
-
expect(summaryCalls).toBe(1)
|
|
68
|
-
expect(summaryPrompt).toContain("one")
|
|
69
|
-
expect(summaryPrompt).toContain("two")
|
|
70
|
-
expect(recalled.map(itemText)).toEqual([
|
|
71
|
-
"<working-memory-summary>\nsummary\n</working-memory-summary>",
|
|
72
|
-
"User: three",
|
|
73
|
-
"Assistant: four",
|
|
74
|
-
])
|
|
75
|
-
}).pipe(
|
|
76
|
-
Effect.provide(
|
|
77
|
-
WorkingMemory.layer({
|
|
78
|
-
maxMessages: 2,
|
|
79
|
-
summarize: { model: summaryModel },
|
|
80
|
-
}),
|
|
81
|
-
),
|
|
82
|
-
)
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
it.effect("isolates state by memory key", () =>
|
|
86
|
-
Effect.gen(function* () {
|
|
87
|
-
const memory = yield* Memory.Memory
|
|
88
|
-
|
|
89
|
-
yield* memory.remember({
|
|
90
|
-
key,
|
|
91
|
-
turn: 0,
|
|
92
|
-
terminal: true,
|
|
93
|
-
transcript: prompt(user("one"), assistant("two")),
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
const recalled = yield* memory.recall({ key: otherKey, turn: 0, prompt: prompt(user("current")) })
|
|
97
|
-
|
|
98
|
-
expect(recalled).toEqual([])
|
|
99
|
-
}).pipe(Effect.provide(WorkingMemory.layer({ maxMessages: 2 }))),
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
it.effect("forgets the exact memory key", () =>
|
|
103
|
-
Effect.gen(function* () {
|
|
104
|
-
const memory = yield* Memory.Memory
|
|
105
|
-
|
|
106
|
-
yield* memory.remember({
|
|
107
|
-
key,
|
|
108
|
-
turn: 0,
|
|
109
|
-
terminal: true,
|
|
110
|
-
transcript: prompt(user("one"), assistant("two")),
|
|
111
|
-
})
|
|
112
|
-
yield* memory.remember({
|
|
113
|
-
key: otherKey,
|
|
114
|
-
turn: 0,
|
|
115
|
-
terminal: true,
|
|
116
|
-
transcript: prompt(user("three"), assistant("four")),
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
yield* memory.forget({ key })
|
|
120
|
-
|
|
121
|
-
const forgotten = yield* memory.recall({ key, turn: 0, prompt: prompt(user("current")) })
|
|
122
|
-
const retained = yield* memory.recall({ key: otherKey, turn: 0, prompt: prompt(user("current")) })
|
|
123
|
-
|
|
124
|
-
expect(forgotten).toEqual([])
|
|
125
|
-
expect(retained.map(itemText)).toEqual(["User: three", "Assistant: four"])
|
|
126
|
-
}).pipe(Effect.provide(WorkingMemory.layer({ maxMessages: 2 }))),
|
|
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
|
-
)
|
|
155
|
-
})
|