@unblocklabs/unblock-memory 0.3.29 → 0.4.0
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 +2 -2
- package/dist/src/config.d.ts +0 -1
- package/dist/src/config.js +2 -6
- package/dist/src/diagnostics.d.ts +1 -3
- package/dist/src/manager.d.ts +4 -8
- package/dist/src/manager.js +17 -45
- package/dist/src/memory-passage.d.ts +26 -0
- package/dist/src/memory-passage.js +48 -0
- package/dist/src/memory-whisperer.d.ts +2 -1
- package/dist/src/memory-whisperer.js +21 -17
- package/dist/src/mlx-query.d.ts +3 -10
- package/dist/src/mlx-query.js +49 -25
- package/dist/src/query-contract.d.ts +31 -0
- package/dist/src/query-contract.js +58 -0
- package/dist/src/query-tokenizer/contract.json +10 -0
- package/dist/src/response-stages.d.ts +3 -3
- package/dist/src/training-candidates.d.ts +2 -1
- package/dist/src/training-candidates.js +12 -9
- package/dist/src/training-input.d.ts +13 -10
- package/dist/src/training-input.js +22 -18
- package/dist/src/training-judge.d.ts +16 -46
- package/dist/src/training-judge.js +6 -53
- package/dist/src/training-models.d.ts +15 -7
- package/dist/src/training-models.js +36 -38
- package/dist/src/training-queries.d.ts +23 -7
- package/dist/src/training-queries.js +247 -102
- package/dist/src/training-retrieval.d.ts +9 -2
- package/dist/src/training-retrieval.js +36 -12
- package/dist/src/training-runtime.js +8 -7
- package/dist/src/training-store.d.ts +46 -16
- package/dist/src/training-store.js +83 -29
- package/dist/src/training.d.ts +10 -0
- package/dist/src/training.js +7 -5
- package/dist/src/typesafe.d.ts +58 -8
- package/dist/src/typesafe.js +47 -29
- package/dist/src/whisperer-context.d.ts +0 -8
- package/dist/src/whisperer-context.js +0 -23
- package/docs/configuration.md +3 -3
- package/docs/memory-training.md +114 -58
- package/docs/retrieval.md +34 -24
- package/openclaw.plugin.json +2 -3
- package/package.json +5 -2
- package/src/mlx-query-worker.py +5 -8
- package/src/query-tokenizer/LICENSE +71 -0
- package/src/query-tokenizer/README.md +21 -0
- package/src/query-tokenizer/chat_template.jinja +115 -0
- package/src/query-tokenizer/contract.json +10 -0
- package/src/query-tokenizer/tokenizer.json +323830 -0
- package/src/query-tokenizer/tokenizer_config.json +19 -0
- package/src/query_contract.py +60 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"backend": "tokenizers",
|
|
3
|
+
"bos_token": "<|startoftext|>",
|
|
4
|
+
"clean_up_tokenization_spaces": false,
|
|
5
|
+
"eos_token": "<|im_end|>",
|
|
6
|
+
"is_local": true,
|
|
7
|
+
"legacy": false,
|
|
8
|
+
"model_input_names": [
|
|
9
|
+
"input_ids",
|
|
10
|
+
"attention_mask"
|
|
11
|
+
],
|
|
12
|
+
"model_max_length": 1000000000000000019884624838656,
|
|
13
|
+
"pad_token": "<|pad|>",
|
|
14
|
+
"sp_model_kwargs": {},
|
|
15
|
+
"spaces_between_special_tokens": false,
|
|
16
|
+
"tokenizer_class": "TokenizersBackend",
|
|
17
|
+
"use_default_system_prompt": false,
|
|
18
|
+
"use_fast": true
|
|
19
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""One student prompt, pinned tokenizer, serialization and target contract for v2."""
|
|
2
|
+
import hashlib
|
|
3
|
+
import json
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
ASSETS = Path(__file__).with_name("query-tokenizer")
|
|
7
|
+
CONTRACT = json.loads((ASSETS / "contract.json").read_text())
|
|
8
|
+
MODEL, REVISION, SYSTEM = (CONTRACT[key] for key in ("model", "revision", "system"))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def serialize_conversation(conversation):
|
|
12
|
+
return json.dumps({"history": conversation["history"], "currentRequest": conversation["currentRequest"]},
|
|
13
|
+
ensure_ascii=False, separators=(",", ":")).replace("<", "\\u003c")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def validate_conversation(conversation, tokenizer):
|
|
17
|
+
if not isinstance(conversation, dict) or set(conversation) != {"history", "currentRequest"} or \
|
|
18
|
+
not isinstance(conversation["currentRequest"], str) or not conversation["currentRequest"] or \
|
|
19
|
+
not isinstance(conversation["history"], list):
|
|
20
|
+
raise ValueError("Invalid prepared conversation")
|
|
21
|
+
for message in conversation["history"]:
|
|
22
|
+
if not isinstance(message, dict) or set(message) != {"role", "content"} or \
|
|
23
|
+
message["role"] not in ("user", "assistant") or not isinstance(message["content"], str):
|
|
24
|
+
raise ValueError("Invalid prepared conversation history")
|
|
25
|
+
serialized = serialize_conversation(conversation)
|
|
26
|
+
if len(serialized.encode("utf-8")) > CONTRACT["conversationBytes"] or \
|
|
27
|
+
len(tokenizer.encode(serialized, add_special_tokens=False)) > CONTRACT["conversationTokens"]:
|
|
28
|
+
raise ValueError("Prepared conversation exceeds shared window")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def validate_query_pair(value):
|
|
32
|
+
if not isinstance(value, dict) or set(value) != {"lex", "vec"} or \
|
|
33
|
+
any(not isinstance(value[key], str) or not value[key].strip() for key in ("lex", "vec")):
|
|
34
|
+
raise ValueError("Expected exactly one nonempty lex/vec query pair")
|
|
35
|
+
return {key: value[key].strip() for key in ("lex", "vec")}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def student_messages(conversation):
|
|
39
|
+
return [{"role": "system", "content": SYSTEM},
|
|
40
|
+
{"role": "user", "content": "<conversation_data>\n" + serialize_conversation(conversation) + "\n</conversation_data>"}]
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def student_prompt_tokens(tokenizer, conversation):
|
|
44
|
+
validate_conversation(conversation, tokenizer)
|
|
45
|
+
# Transformers 5 may return BatchEncoding for tokenize=True. Encode the
|
|
46
|
+
# rendered template explicitly, exactly as dataset preparation does.
|
|
47
|
+
text = tokenizer.apply_chat_template(student_messages(conversation), tokenize=False, add_generation_prompt=True)
|
|
48
|
+
return tokenizer.encode(text, add_special_tokens=False)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def load_tokenizer():
|
|
52
|
+
from transformers import AutoTokenizer
|
|
53
|
+
return AutoTokenizer.from_pretrained(ASSETS, local_files_only=True, trust_remote_code=False)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def verify_model_tokenizer(root):
|
|
57
|
+
# The model package must carry the exact tokenizer/template used for collection.
|
|
58
|
+
for name in ("tokenizer.json", "tokenizer_config.json", "chat_template.jinja"):
|
|
59
|
+
if hashlib.sha256((root / name).read_bytes()).digest() != hashlib.sha256((ASSETS / name).read_bytes()).digest():
|
|
60
|
+
raise ValueError("Incompatible model tokenizer or chat template")
|