coderofpears commited on
Commit
933929e
·
verified ·
1 Parent(s): b5b2dd7

Upload memstore.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. memstore.py +112 -0
memstore.py ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ clankerDiffusion — learned secondary memory (side store).
3
+
4
+ The model controls a long-term store through special tokens it emits while
5
+ generating:
6
+
7
+ <mem_write>KEY<mem_kv>BLOB</mem_kv> -> persist BLOB under KEY
8
+ <mem_read>KEY</mem_read> -> recall BLOB for KEY
9
+ <mem_evict>KEY</mem_evict> -> delete KEY
10
+
11
+ BLOBs are packed into the token stream as <mem_kv>...</mem_kv> so the model can
12
+ read what it wrote. At inference, `MemoryStore` intercepts these tokens, performs
13
+ the read/write against an external store (dict / JSONL / vector index), and
14
+ replaces the in-stream content with the resolved value (or an <unk> if missing).
15
+
16
+ This is "knowledge brought in and out of memory": the weights never hold the
17
+ facts; only the keys/pointers do. Train 8k, but the store is unbounded, so the
18
+ effective secondary memory is far larger than the 128k normal window.
19
+
20
+ Training note: the data generator emits syntactically-valid mem_write / mem_read
21
+ / mem_evict spans using this same module, so the model learns the format and
22
+ when to invoke it.
23
+ """
24
+ import re
25
+ import json
26
+ import os
27
+
28
+
29
+ class MemoryStore:
30
+ def __init__(self, path=None):
31
+ self.path = path
32
+ self.store = {}
33
+ if path and os.path.exists(path):
34
+ try:
35
+ with open(path, "r", encoding="utf-8") as f:
36
+ self.store = json.load(f)
37
+ except Exception:
38
+ self.store = {}
39
+
40
+ # ---- token-stream helpers (used by data gen + inference) ----
41
+ def write(self, key, blob):
42
+ self.store[key] = blob
43
+ self._maybe_persist()
44
+ return blob
45
+
46
+ def read(self, key):
47
+ return self.store.get(key)
48
+
49
+ def evict(self, key):
50
+ return self.store.pop(key, None)
51
+
52
+ def _maybe_persist(self):
53
+ if self.path:
54
+ try:
55
+ with open(self.path, "w", encoding="utf-8") as f:
56
+ json.dump(self.store, f)
57
+ except Exception:
58
+ pass
59
+
60
+ # ---- stream rewriting for inference ----
61
+ @staticmethod
62
+ def _split_segments(text):
63
+ """Yield (is_mem, content) chunks where is_mem=True spans a full
64
+ <mem_*>...</mem_*> block we can act on."""
65
+ pat = re.compile(
66
+ r"<mem_write>(.*?)<mem_kv>(.*?)</mem_kv>|"
67
+ r"<mem_read>(.*?)</mem_read>|"
68
+ r"<mem_evict>(.*?)</mem_evict>",
69
+ re.DOTALL)
70
+ pos = 0
71
+ for m in pat.finditer(text):
72
+ if m.start() > pos:
73
+ yield (False, text[pos:m.start()])
74
+ if m.group(1) is not None:
75
+ key, blob = m.group(1), m.group(2)
76
+ yield (True, ("write", key, blob))
77
+ elif m.group(3) is not None:
78
+ yield (True, ("read", m.group(3)))
79
+ elif m.group(4) is not None:
80
+ yield (True, ("evict", m.group(4)))
81
+ pos = m.end()
82
+ if pos < len(text):
83
+ yield (False, text[pos:])
84
+
85
+ def resolve(self, text):
86
+ """Rewrite a generated stream: execute memory ops, replacing the op
87
+ with its resolved <mem_kv> value (or a miss marker). Returns the new
88
+ text and a list of (op, key) that were performed (for logging)."""
89
+ out = []
90
+ ops = []
91
+ for is_mem, chunk in self._split_segments(text):
92
+ if not is_mem:
93
+ out.append(chunk)
94
+ continue
95
+ op = chunk[0]
96
+ if op == "write":
97
+ _, key, blob = chunk
98
+ self.write(key, blob)
99
+ ops.append(("write", key))
100
+ out.append(f"<mem_kv>{blob}</mem_kv>")
101
+ elif op == "read":
102
+ key = chunk[1]
103
+ blob = self.read(key)
104
+ ops.append(("read", key))
105
+ out.append(f"<mem_kv>{blob}</mem_kv>" if blob is not None
106
+ else "<mem_kv><unk></mem_kv>")
107
+ elif op == "evict":
108
+ key = chunk[1]
109
+ self.evict(key)
110
+ ops.append(("evict", key))
111
+ out.append("")
112
+ return "".join(out), ops