topic-memory 0.1.0 → 0.1.1

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/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # Changelog
2
+
3
+ ## 0.1.1
4
+
5
+ - Make npm installation the primary entry point and refresh English and Chinese onboarding.
6
+ - Add a browser walkthrough using real SDK retrieval with explicitly scripted model responses.
7
+ - Add an executable live-model chat example with recent-context injection and a seeded conversation.
8
+ - Add transparent scripted checks and a real-model comparison harness with raw answers, failures, latency and reported token usage.
9
+ - Keep theoretical capacity calculations separate from measured claims.
10
+ - Fix fresh-consumer validation on Windows and include runnable examples in the package.
11
+ - Add first-use feedback and a small user-testing guide.
12
+
13
+ The SDK's core retrieval algorithm is unchanged. No real-model performance improvement is claimed by this release.
package/README.md CHANGED
@@ -1,326 +1,136 @@
1
1
  # Topic Memory
2
2
 
3
- **A drop-in long-term memory layer for LLM apps.**
3
+ **Find the topic. Reopen the original conversation.**
4
4
 
5
- [简体中文](./README.zh-CN.md) · [Integration guide](./docs/USAGE.md) · [Architecture & capacity notes](./docs/ARCHITECTURE.md)
5
+ [简体中文](./README.zh-CN.md) · [Integration guide](./docs/USAGE.md) · [Evaluation](./docs/EVALUATION.md) · [Architecture](./docs/ARCHITECTURE.md)
6
6
 
7
- Topic Memory gives an existing chat app or agent a structured way to remember old conversations without sending the entire transcript to the model on every request.
7
+ Topic Memory is a TypeScript SDK for chat apps and agents that need older conversation details. It groups history into topics, selects relevant topics for a new question, and returns the original exchanges as `memoryContext` for your existing model.
8
8
 
9
- It keeps the full conversation as the source of truth, organizes older exchanges into topic-based memory, retrieves only the topics that matter for the current message, and returns a ready-to-inject `memoryContext` for your own Main LLM.
9
+ For example, a user chooses **Ueno, 14,000 yen per night** for a Tokyo hotel. After the conversation moves on to food, a project release and astronomy, the SDK can reopen the hotel discussion when that plan becomes relevant again. The source text stays available for inspection.
10
10
 
11
- > **What it is:** a memory plugin/SDK for an LLM application.
12
- > **What it is not:** a chatbot, a model provider, or a replacement for your Main LLM.
13
-
14
- ## What can it do?
15
-
16
- Topic Memory is useful when your AI needs to remember things that happened far earlier in a conversation, for example:
17
-
18
- - user preferences, recurring habits, names, places, and personal context;
19
- - decisions made hundreds or thousands of exchanges ago;
20
- - project history, requirements, previous attempts, and unresolved tasks;
21
- - earlier events where the exact wording or timing may matter;
22
- - long-running conversations where replaying the full transcript would become expensive or exceed the model context window.
23
-
24
- Unlike a single rolling summary, Topic Memory keeps the canonical transcript. A retrieved topic can therefore reopen the original exchanges behind that topic instead of relying only on a compressed summary.
25
-
26
- ## The model roles — important
27
-
28
- There are two layers, and they should not be confused:
29
-
30
- ### Memory LLM
31
-
32
- The **Memory LLM** powers the memory system itself.
33
-
34
- By default, the same Memory LLM instance performs two jobs:
35
-
36
- 1. **Topic Worker** — organizes completed conversation exchanges into topic instances and writes a lightweight topic index.
37
- 2. **Memory Selector** — reads the current user message, recent context, and Topic Directory, then chooses up to three older topics to reopen.
38
-
39
- You may configure separate models for these two jobs, but most integrations can use one Memory LLM for both.
40
-
41
- ### Your Main LLM
42
-
43
- Your **Main LLM** is still your own user-facing chat model.
44
-
45
- Topic Memory never generates the final reply and never takes ownership of your Main LLM. It returns `memoryContext`; your application decides how to inject that context into the Main LLM prompt.
46
-
47
- ```text
48
- User message
49
-
50
- ├─→ Topic Memory retrieves relevant old context
51
- │ ├─ Recent 5 completed exchanges
52
- │ ├─ Topic Directory
53
- │ └─ Opened Topic Packets
54
-
55
- └─→ Your Main LLM receives memoryContext and writes the reply
56
- ```
57
-
58
- ## How it works
59
-
60
- The v0.1 pipeline is intentionally simple:
61
-
62
- 1. **Canonical Transcript**
63
- Every exchange is stored as `pending`, `completed`, or `failed`. The full transcript remains the source of truth.
64
-
65
- 2. **Topic Worker**
66
- After at least six completed exchanges exist, the Topic Worker processes the active tail of the conversation. It groups related exchanges into topic instances and stores:
67
- - topic keywords;
68
- - retrieval terms;
69
- - exact transcript spans;
70
- - topic status and timing metadata.
71
-
72
- 3. **Topic Directory**
73
- The SDK builds a compact index of available topics. The Main LLM does not need the entire historical transcript just to decide what to remember.
74
-
75
- 4. **Memory Selector**
76
- Before a new reply, the selector sees the current message, the latest five completed exchanges, and the Topic Directory. It selects at most three relevant topic IDs.
77
-
78
- 5. **Opened Topic Packets**
79
- Selected topics are reopened from their exact Canonical Transcript spans. When timing matters, exchange timestamps can be included.
80
-
81
- 6. **Main LLM**
82
- Topic Memory returns the restored material as `memoryContext`. Your own Main LLM uses it only when relevant to the current message.
11
+ ## Install
83
12
 
84
- ```text
85
- Canonical Transcript
86
-
87
-
88
- Topic Worker
89
-
90
-
91
- Topic Store ─────→ Topic Directory
92
-
93
- Current message ─────────┤
94
- Recent 5 exchanges ──────┤
95
-
96
- Memory Selector
97
-
98
- up to 3 topic IDs
99
-
100
-
101
- Open Topic Packets
102
-
103
-
104
- memoryContext
105
-
106
-
107
- Your Main LLM
13
+ ```bash
14
+ npm install topic-memory
108
15
  ```
109
16
 
110
- Selector failure safely degrades to an empty long-term `memoryContext`; it does not have to block the host chat flow.
111
-
112
- ## Why not just keep appending the entire transcript?
113
-
114
- A large context window is still a finite prompt budget, and long-context models do not always use information uniformly well across very long inputs. Topic Memory instead separates **how much history you store** from **how much history you send on one request**.
115
-
116
- Under one illustrative 128k-context workload, a raw-history design with about 200 tokens per completed exchange reaches roughly 600 exchanges when ~120k tokens are reserved for conversation history. With Topic Memory, a 5,000-exchange archive grouped at roughly eight exchanges per topic can be represented by a Topic Directory plus at most three reopened topics in roughly 43k–45k memory-related tokens under the assumptions documented in the appendix.
17
+ ES modules; SDK requires Node.js 18+. The live example commands below require **Node.js 20.6+** for `--env-file`. The published `topic-memory@0.1.0` was installed and exercised in a fresh Node 24 project on 2026-09-13.
117
18
 
118
- That is approximately **8.3× more represented conversation history** in this example, while sending substantially less historical text per request than replaying all 5,000 exchanges.
119
-
120
- **This is a theoretical sizing example, not a guaranteed hard limit or benchmark result.** Actual capacity depends on message length, tokenization, topic size, model context window, and how many topics accumulate. v0.1's main scaling constraint is that the Topic Directory grows with the number of topics.
121
-
122
- See [Architecture & capacity notes](./docs/ARCHITECTURE.md) for the formula, assumptions, caveats, and related research.
123
-
124
- ## Install
125
-
126
- This repository is currently distributed as source code. Clone it directly or build a tarball with `npm pack`.
19
+ ## Try the walkthrough no API key
127
20
 
128
21
  ```bash
129
- npm install
130
- npm run build
131
- npm pack
22
+ git clone https://github.com/ziningshu-code/memory-system-mvp.git
23
+ cd memory-system-mvp
24
+ npm ci
25
+ npm run demo
132
26
  ```
133
27
 
134
- ## Configure a Memory LLM
28
+ The demo loads **24 synthetic exchanges**, retrieves the old hotel topic, and prints the exact restored conversation. It uses the real SDK with **scripted worker and selector responses**. This is a mechanics demo, not evidence of real-model retrieval quality.
135
29
 
136
- The built-in adapter uses an OpenAI-compatible `/chat/completions` endpoint:
30
+ To open the interactive, English/Chinese browser version:
137
31
 
138
32
  ```bash
139
- MEMORY_LLM_BASE_URL=https://your-openai-compatible-endpoint.example/v1
140
- MEMORY_LLM_API_KEY=replace-me
141
- MEMORY_LLM_MODEL=your-memory-model
33
+ npm run build:site
34
+ npm run preview
142
35
  ```
143
36
 
144
- Keep paid provider credentials on a trusted backend or proxy. Do not ship them inside a public browser bundle.
37
+ Visit `http://127.0.0.1:4173`. Switch between hotel, food, project and missing-information questions; inspect the topic selection and original source text. Everything in this walkthrough runs locally in the browser, with no credentials or model requests.
38
+
39
+ ## Quick start
145
40
 
146
- ## 5-minute Quick Start
41
+ Your application supplies a memory model and keeps its existing user-facing model. Pass **both** recent conversation and retrieved older evidence to that model:
147
42
 
148
43
  ```ts
149
- import {
150
- createMemory,
151
- createOpenAICompatibleMemoryLlm,
152
- InMemoryStorage,
153
- } from 'topic-memory';
154
-
155
- const memoryLlm = createOpenAICompatibleMemoryLlm({
156
- baseUrl: process.env.MEMORY_LLM_BASE_URL!,
157
- apiKey: process.env.MEMORY_LLM_API_KEY,
158
- model: process.env.MEMORY_LLM_MODEL!,
159
- });
44
+ import { createMemory, createOpenAICompatibleMemoryLlm, InMemoryStorage } from 'topic-memory';
160
45
 
161
46
  const memory = createMemory({
162
47
  storage: new InMemoryStorage(),
163
- llm: memoryLlm,
48
+ llm: createOpenAICompatibleMemoryLlm({
49
+ baseUrl: process.env.MEMORY_LLM_BASE_URL!,
50
+ apiKey: process.env.MEMORY_LLM_API_KEY,
51
+ model: process.env.MEMORY_LLM_MODEL!,
52
+ }),
164
53
  });
165
54
 
166
- async function handleUserMessage(userMessage: string) {
167
- const pending = await memory.begin(userMessage);
168
-
169
- try {
170
- const retrieved = await memory.retrieve({ userMessage });
171
-
172
- // This is YOUR existing user-facing model call.
173
- const assistantReply = await myOwnMainLlm({
174
- userMessage,
175
- memoryContext: retrieved.memoryContext,
176
- recentContext: retrieved.recentContext,
177
- });
178
-
179
- await memory.completeExchange({
180
- exchangeId: pending.id,
181
- assistantText: assistantReply,
182
- });
183
-
184
- await memory.maybeRunTopicWorker();
185
- return assistantReply;
186
- } catch (error) {
187
- await memory.failExchange({
188
- exchangeId: pending.id,
189
- failureReason: error instanceof Error ? error.message : String(error),
190
- });
191
- throw error;
192
- }
193
- }
194
- ```
55
+ const pending = await memory.begin(userMessage);
56
+ const context = await memory.retrieve({ userMessage });
195
57
 
196
- The SDK does **not** call `myOwnMainLlm`; that function represents the Main LLM integration your application already has.
197
-
198
- For a complete integration walkthrough, see [docs/USAGE.md](./docs/USAGE.md).
199
-
200
- ## Integration timing
201
-
202
- ```text
203
- User message
204
- → memory.begin()
205
- → memory.retrieve()
206
- → Your Main LLM
207
- → memory.completeExchange()
208
- → memory.maybeRunTopicWorker()
58
+ // Call your existing model with current input, context.recentContext,
59
+ // and context.memoryContext. The complete runnable integration is linked below.
60
+ const assistantReply = await yourMainModel(userMessage, context);
61
+ await memory.completeExchange({ exchangeId: pending.id, assistantText: assistantReply });
62
+ await memory.maybeRunTopicWorker();
209
63
  ```
210
64
 
211
- If the Main LLM request fails after `begin()`, call `memory.failExchange(...)`.
65
+ `yourMainModel` is application-owned. For a **complete executable integration**, use [examples/chat.mjs](./examples/chat.mjs) and its [provider helper](./examples/provider.mjs); they include the actual model request, recent-context injection, errors, and the pending/completed/failed lifecycle.
212
66
 
213
- ## The first six completed exchanges
67
+ ## Try it with a real model
214
68
 
215
- Topic Worker does not run until at least **6 completed exchanges** exist. Before then:
69
+ In the cloned repository, copy `.env.example` to `.env` and set your OpenAI-compatible endpoint, model and API key. Keep this file local. The examples send your input to that provider and may use paid credits.
216
70
 
217
- - Canonical Transcript is still recorded;
218
- - `recentContext` still returns recent completed history;
219
- - `memoryContext` may be empty because no topic has been created yet.
220
-
221
- This is expected behavior.
222
-
223
- ## Public API
224
-
225
- ```ts
226
- createMemory
227
- MemoryEngine
228
- InMemoryStorage
229
- IndexedDbMemoryStorage
230
- createOpenAICompatibleMemoryLlm
231
- ```
232
-
233
- Main engine methods:
234
-
235
- ```ts
236
- begin
237
- beginExchange
238
- completeExchange
239
- failExchange
240
- maybeRunTopicWorker
241
- retrieve
242
- listExchanges
243
- listTopics
244
- getLatestTopicWorkerRun
245
- clear
246
- ```
247
-
248
- `retrieve()` returns:
249
-
250
- ```ts
251
- {
252
- recentContext,
253
- topicDirectory,
254
- selectedTopicIds,
255
- openedTopicPackets,
256
- memoryContext,
257
- needsTimeMetadata,
258
- trace,
259
- }
71
+ ```bash
72
+ npm run demo:chat
260
73
  ```
261
74
 
262
- ## Storage
263
-
264
- For demos and tests:
75
+ Or preload the public synthetic conversation, then ask about the hotel plan:
265
76
 
266
- ```ts
267
- new InMemoryStorage()
77
+ ```bash
78
+ npm run demo:chat -- --seed
268
79
  ```
269
80
 
270
- For browser persistence:
81
+ The seeded conversation is synthetic; topic organization, selection and final answers use the **real configured model**. Type `/exit` to leave. Example storage is in-memory and resets when the process exits.
271
82
 
272
- ```ts
273
- new IndexedDbMemoryStorage()
274
- ```
83
+ ## What is verified?
275
84
 
276
- For production backends, implement the exported `MemoryStorage` interface and connect your own database.
85
+ | Check | Status / meaning |
86
+ | --- | --- |
87
+ | Published npm package | Fresh installation and old-text recovery checked on Node 24 |
88
+ | SDK lifecycle, storage, adapter and retrieval tests | Automated checks in CI |
89
+ | Four scripted walkthrough cases | Old-text recovery and empty memory for a missing fact; [recorded output](./docs/evaluation/scripted.json) |
90
+ | Real-model comparison | Runnable harness provided; **no real-model performance result claimed** |
277
91
 
278
- ## Advanced configuration
92
+ Run `npm run evaluate` for the scripted checks or `npm run evaluate:live` for a small, real-model comparison of **recent five exchanges**, **full transcript**, and **topic retrieval**. The live report includes raw answers, literal fact-check scores, request latency, and provider token counts when available. [Read the method and limitations](./docs/EVALUATION.md).
279
93
 
280
- Default: one Memory LLM handles Topic Worker and Selector.
94
+ The earlier **8.3×** figure is an illustrative capacity calculation, **not a measured improvement in accuracy or usable memory**. Its assumptions remain in [Architecture & capacity notes](./docs/ARCHITECTURE.md).
281
95
 
282
- ```ts
283
- createMemory({ storage, llm: memoryLlm })
284
- ```
285
-
286
- Advanced: split the two memory jobs.
96
+ ## How it works
287
97
 
288
- ```ts
289
- createMemory({
290
- storage,
291
- topicWorker: topicWorkerLlm,
292
- selector: selectorLlm,
293
- });
98
+ ```text
99
+ Saved conversation → Topic Worker → Topic directory
100
+ New question + recent conversation + directory → Selector
101
+ Selected topic IDs → Original transcript spans → Your model
294
102
  ```
295
103
 
296
- Again, neither configuration replaces your Main LLM.
104
+ One memory LLM can handle both worker and selector; separate models are also supported. Topic Memory does not generate the final answer or replace your main model. It requires no embeddings or vector database.
297
105
 
298
- ## Failure behavior
106
+ ## Current boundaries
299
107
 
300
- - **Main LLM fails:** call `failExchange`.
301
- - **Topic Worker provider fails:** the failure is recorded and existing topics remain.
302
- - **Topic Worker returns invalid structure:** the output is rejected and not written to Topic Store.
303
- - **Selector fails:** long-term `memoryContext` falls back to empty.
304
- - **No older topic is relevant:** `memoryContext` is empty by design.
108
+ - Topic creation starts after **six completed exchanges**. Before that, recent context still works and long-term memory can be empty.
109
+ - The selector opens **up to three topics**. Selection can miss evidence; inspect `retrieve().trace`.
110
+ - A selector error falls back to empty long-term memory. Your app must still handle request timeouts and storage failures.
111
+ - `InMemoryStorage` is temporary. `IndexedDbMemoryStorage` persists in a browser. Backend persistence and user/conversation isolation require your own `MemoryStorage` implementation.
112
+ - Serialize turns and worker runs for a given memory store; concurrent writers are not coordinated by the SDK.
113
+ - The full topic directory grows with the archive. v0.1 does not enforce a total token budget.
114
+ - Treat historical text as untrusted evidence, not system instructions.
305
115
 
306
- ## Validation
116
+ [Integration guide](./docs/USAGE.md) · [Public API and architecture](./docs/ARCHITECTURE.md)
307
117
 
308
- The repository CI validates the package as an actual consumer would use it:
118
+ ## Development checks
309
119
 
310
120
  ```bash
121
+ npm ci
311
122
  npm run build
312
123
  npm run typecheck
313
124
  npm test
314
- npm pack --dry-run
315
125
  npm run smoke:consumer
126
+ npm run evaluate
127
+ npm run build:site
316
128
  ```
317
129
 
318
- `smoke:consumer` packs the SDK, installs the tarball into a fresh temporary Node project, imports only public package exports, runs the memory pipeline, and verifies that a simulated host-owned Main LLM receives a non-empty `memoryContext`.
319
-
320
- ## Non-goals
130
+ ## Help test it
321
131
 
322
- v0.1 does not manage persona, Big Five traits, relationship state, proactive messaging, UI, embeddings, vector databases, or the host application's Main LLM.
132
+ Try one real conversation from your own development workflow, then [report what happened](https://github.com/ziningshu-code/memory-system-mvp/issues/new?template=try-it.yml): what you asked it to remember, whether you could install it, and the first point where retrieval helped or failed. Remove credentials and private conversation details from public reports.
323
133
 
324
134
  ## License
325
135
 
326
- MIT
136
+ MIT