Text Generation
PEFT
Safetensors
GGUF
MLX
English
lora
gemma4
agent-memory
memory
structured-output
json
ollama
contradiction-detection
Eval Results (legacy)
conversational
Instructions to use sebs-clude/CludeMem-e4b with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use sebs-clude/CludeMem-e4b with PEFT:
from peft import PeftModel from transformers import AutoModelForCausalLM base_model = AutoModelForCausalLM.from_pretrained("google/gemma-4-e4b-it") model = PeftModel.from_pretrained(base_model, "sebs-clude/CludeMem-e4b") - MLX
How to use sebs-clude/CludeMem-e4b with MLX:
# Make sure mlx-lm is installed # pip install --upgrade mlx-lm # Generate text with mlx-lm from mlx_lm import load, generate model, tokenizer = load("sebs-clude/CludeMem-e4b") prompt = "Write a story about Einstein" messages = [{"role": "user", "content": prompt}] prompt = tokenizer.apply_chat_template( messages, add_generation_prompt=True ) text = generate(model, tokenizer, prompt=prompt, verbose=True) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use sebs-clude/CludeMem-e4b with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf sebs-clude/CludeMem-e4b:Q4_K_M # Run inference directly in the terminal: llama cli -hf sebs-clude/CludeMem-e4b:Q4_K_M
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf sebs-clude/CludeMem-e4b:Q4_K_M # Run inference directly in the terminal: llama cli -hf sebs-clude/CludeMem-e4b:Q4_K_M
Use pre-built binary
# Download pre-built binary from: # https://github.com/ggerganov/llama.cpp/releases # Start a local OpenAI-compatible server with a web UI: ./llama-server -hf sebs-clude/CludeMem-e4b:Q4_K_M # Run inference directly in the terminal: ./llama-cli -hf sebs-clude/CludeMem-e4b:Q4_K_M
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-server llama-cli # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama-server -hf sebs-clude/CludeMem-e4b:Q4_K_M # Run inference directly in the terminal: ./build/bin/llama-cli -hf sebs-clude/CludeMem-e4b:Q4_K_M
Use Docker
docker model run hf.co/sebs-clude/CludeMem-e4b:Q4_K_M
- LM Studio
- Jan
- vLLM
How to use sebs-clude/CludeMem-e4b with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "sebs-clude/CludeMem-e4b" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "sebs-clude/CludeMem-e4b", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/sebs-clude/CludeMem-e4b:Q4_K_M
- Ollama
How to use sebs-clude/CludeMem-e4b with Ollama:
ollama run hf.co/sebs-clude/CludeMem-e4b:Q4_K_M
- Unsloth Desktop
- Pi
How to use sebs-clude/CludeMem-e4b with Pi:
Start the MLX server
# Install MLX LM: uv tool install mlx-lm # Start a local OpenAI-compatible server: mlx_lm.server --model "sebs-clude/CludeMem-e4b"
Configure the model in Pi
# Install Pi: npm install -g @earendil-works/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "mlx-lm": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "sebs-clude/CludeMem-e4b" } ] } } }Run Pi
# Start Pi in your project directory: pi
- MLX LM
How to use sebs-clude/CludeMem-e4b with MLX LM:
Generate or start a chat session
# Install MLX LM uv tool install mlx-lm # Interactive chat REPL mlx_lm.chat --model "sebs-clude/CludeMem-e4b"
Run an OpenAI-compatible server
# Install MLX LM uv tool install mlx-lm # Start the server mlx_lm.server --model "sebs-clude/CludeMem-e4b" # Calling the OpenAI-compatible server with curl curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "sebs-clude/CludeMem-e4b", "messages": [ {"role": "user", "content": "Hello"} ] }' - Docker Model Runner
How to use sebs-clude/CludeMem-e4b with Docker Model Runner:
docker model run hf.co/sebs-clude/CludeMem-e4b:Q4_K_M
- Lemonade
How to use sebs-clude/CludeMem-e4b with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull sebs-clude/CludeMem-e4b:Q4_K_M
Run and chat with the model
lemonade run user.CludeMem-e4b-Q4_K_M
List all available models
lemonade list
- Hermes Agent
How to use sebs-clude/CludeMem-e4b with Hermes Agent:
Start the MLX server
# Install MLX LM: uv tool install mlx-lm # Start a local OpenAI-compatible server: mlx_lm.server --model "sebs-clude/CludeMem-e4b"
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default sebs-clude/CludeMem-e4b
Run Hermes
hermes
- Atomic Chat
- OpenClaw
How to use sebs-clude/CludeMem-e4b with OpenClaw:
Start the MLX server
# Install MLX LM: uv tool install mlx-lm # Start a local OpenAI-compatible server: mlx_lm.server --model "sebs-clude/CludeMem-e4b"
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "sebs-clude/CludeMem-e4b" \ --custom-provider-id mlx-lm \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
|
Download README.md from sebs-clude/CludeMem-e4b: direct link, hf CLI and curl.
- Browser
- Download file 22.3 kB
-
https://huggingface.co/sebs-clude/CludeMem-e4b/resolve/main/README.md
- Command line
-
hf download hf://sebs-clude/CludeMem-e4b/README.md
-
curl -L -o README.md https://huggingface.co/sebs-clude/CludeMem-e4b/resolve/main/README.md
22.3 kB
| base_model: google/gemma-4-e4b-it | |
| library_name: peft | |
| license: apache-2.0 | |
| language: [en] | |
| pipeline_tag: text-generation | |
| tags: [lora, peft, gemma4, agent-memory, memory, structured-output, json, gguf, ollama, mlx, contradiction-detection] | |
| model-index: | |
| - name: CludeMem-E4B | |
| results: | |
| - task: {type: text-generation, name: "Contradiction detection (RECONCILE)"} | |
| dataset: {type: dnli, name: "DNLI_gp (Dialogue NLI gate-passing test subset)", split: test} | |
| metrics: | |
| - {type: accuracy, name: "Strict 4-way accuracy", value: 74.0} | |
| - {type: precision, name: "Contradiction precision", value: 93.5} | |
| - task: {type: text-generation, name: "Contradiction detection (RECONCILE)"} | |
| dataset: {type: decode, name: "DECODE_gp (DECODE gate-passing test subset)", split: test} | |
| metrics: | |
| - {type: accuracy, name: "Strict 4-way accuracy", value: 77.3} | |
| - {type: precision, name: "Contradiction precision", value: 92.9} | |
| # CludeMem-E4B | |
| **Structured memory operations for AI agents, on your own hardware.** | |
| CludeMem-E4B is a LoRA adapter for Gemma 4 E4B that gives an agent a working memory: nine operations, from | |
| extracting and classifying memories to reconciling contradictions and answering from cited evidence. Each | |
| operation is trained to return one JSON object with a fixed schema, so replies can be validated and stored | |
| directly, and the merged GGUF builds run offline in Ollama, so the memories an agent keeps about its user never | |
| have to leave the device. RECONCILE, the operation that catches contradictions, is measured on two human-labelled | |
| dialogue benchmarks and on four runtimes; the other eight ship with reference pairs checked on every runtime. | |
| ## At a glance | |
| - **Measured on human-labelled dialogue: 74.0% and 77.3% strict 4-way accuracy.** RECONCILE, the | |
| contradiction-detection operation, scores **74.0%** (95% CI 70.7–77.0) on DNLI_gp and **77.3%** (74.0–80.2) on | |
| DECODE_gp, 1,450 human-labelled pairs in all. The majority class scores 33.3% and 50.0%, and the | |
| strongest surface-cue baseline 36.4% and 54.1%. | |
| - **Contradiction flags you can act on: 93.5% and 92.9% precision.** On these label-balanced samples, | |
| 93.5% (DNLI_gp) and 92.9% (DECODE_gp) of its contradiction flags are correct, and it flags only 2.6% and | |
| 5.1% of the pairs that do not contradict. As a yes/no contradiction detector it is right on 89.7% and | |
| 81.0% of the pairs, against 66.7% and 50.0% for the majority class. Precision depends on how common | |
| contradictions are in your data; the false-flag rate is the figure to carry over (*Usage notes*). | |
| - **When it misses, it keeps both memories.** It finds 74.4% and 67.1% of the gold contradictions; | |
| 177 of the 179 it misses come back as `consistent`, so a missed contradiction leaves both memories in place | |
| rather than dropping one. | |
| - **Runs offline in Ollama on a 5.3 GB file, within 1.1 points of PyTorch.** On the same items, GGUF Q8_0 scores | |
| 73.7 / 77.9, GGUF Q4_K_M 72.9 / 76.7 and MLX 74.1 / 77.9, each within 1.1 points of | |
| PyTorch (74.0 / 77.3). PyTorch and MLX gave the same verdict on 1,440 of the 1,450 pairs. The Q4_K_M build is | |
| 5.3 GB, the Q8_0 build 8.0 GB; both include the base model. | |
| - **JSON without a grammar: 5,798 of 5,800 replies parsed.** Across those four RECONCILE runs, under plain greedy | |
| decoding with no grammar or schema constraint, 5,798 of 5,800 replies parsed as a JSON object with all four keys, | |
| including all 1,450 from PyTorch. Of the parsed replies, 25 carried a verdict outside the four labels; they and | |
| the 2 that did not parse were scored as wrong and count against the accuracies above. | |
| - **No DNLI or DECODE data was used in training.** The adapter was trained on synthetic persona timelines and | |
| tested on human-written dialogue (*Training* has the overlap check). | |
| ## The nine operations | |
| Each call sends the operation's system prompt as the system message and the memory data as the user message, | |
| rendered with the Gemma 4 chat template and decoded greedily. Pass `enable_thinking=True`: it only adds the | |
| `<|think|>` line that opened the system turn in training. The model does not write a thinking block; it replies | |
| with one JSON object. `prompts.json` documents each input format, the output keys and values, and a reference | |
| input/output pair. | |
| | Operation | What it does | System prompt (exact) | | |
| |---|---|---| | |
| | `CLASSIFY` | Types one memory as episodic or semantic and scores its importance and emotional valence, with tags and concepts. | `Classify the memory. Output JSON: {type, importance (0-1), tags[], concepts[], emotional_valence (-1..1)}.` | | |
| | `EXTRACT` | Turns a dialogue into atomic memories, skipping lines that carry none (logs, tables, tool-call JSON, code). | `Extract atomic memories from the text. Output JSON: {memories:[{content, summary, type}]}.` | | |
| | `ENTITIES` | Extracts people, locations, organizations and projects, with aliases and relations such as `lives_in`. | `Extract entities and relations. Output JSON: {entities:[{name,type,aliases}], relations:[{head,type,tail}]}.` | | |
| | `TEMPORAL` | Dates a new event and links it as before or after the known events. | `Extract the event date and its temporal links to the known events. Output JSON: {event_date, precision, links:[{type,target}]}.` | | |
| | `CONSOLIDATE` | Consolidates a set of memories into insights, each citing its evidence ids. | `Consolidate the memories into evidence-linked insights. Output JSON: {insights:[{content, evidence[]}]}.` | | |
| | `COMPACT` | Compacts old memories into one summary that preserves the entities and the date range. | `Compact the old memories into one summary, preserving entities and the date range. Output JSON: {summary, preserved_entities[], date_range:{start,end}}.` | | |
| | `RECONCILE` | Decides whether two memories are consistent, contradict, duplicate, or one supersedes the other; names the weaker one. | `Decide how the two memories relate. Output JSON: {verdict, resolution, weaker_id, confidence}.` | | |
| | `QUERY` | Expands a question into search queries, entities, time constraints and an intent. | `Understand the query. Output JSON: {expanded_queries[], temporal_constraints, type_filters[], entities[], intent}.` | | |
| | `ANSWER` | Answers only from the supplied memories, cites them, and abstains when they do not support an answer. | `Answer ONLY from the provided memories; abstain if unsupported. Output JSON: {rationale, answer, citations[], confidence, abstain}.` | | |
| ## Quick start | |
| All three examples send the ANSWER prompt with a test item from `prompts.json`. | |
| ### Ollama (offline) | |
| ```bash | |
| hf download sebs-clude/CludeMem-e4b gguf/cludemem-e4b-v3.Q4_K_M.gguf gguf/Modelfile --local-dir cludemem-v3 | |
| cd cludemem-v3/gguf | |
| ollama create cludemem-e4b-v3 -f Modelfile # the Modelfile's FROM line names cludemem-e4b-v3.Q4_K_M.gguf | |
| curl -s http://localhost:11434/api/chat -d '{ | |
| "model": "cludemem-e4b-v3", "stream": false, "options": {"temperature": 0}, | |
| "messages": [ | |
| {"role": "system", "content": "Answer ONLY from the provided memories; abstain if unsupported. Output JSON: {rationale, answer, citations[], confidence, abstain}."}, | |
| {"role": "user", "content": "Question: Where does Maya live now?\n\nMemories:\n[f2] Maya moved to Austin on 2026-10-22.\n[f1] Maya lives in Lisbon.\n[f3] Maya currently resides in Austin."} | |
| ] | |
| }' | |
| ``` | |
| Leave `think` unset: the prompt then matches the training prompt token for token, while `"think": false` drops | |
| the `<|think|>` line. Recorded `message.content`, parsed (Q4_K_M, Ollama 0.34.2): `{"rationale": "Supported by f2.", "answer": "Austin", "citations": ["f2"], "confidence": 0.9, "abstain": false}` | |
| ### Transformers + PEFT | |
| ```python | |
| import json, torch | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| from peft import PeftModel | |
| BASE = "google/gemma-4-e4b-it" # full precision (bf16), not 4-bit; "unsloth/gemma-4-E4B-it" has the same weights | |
| tok = AutoTokenizer.from_pretrained(BASE) | |
| model = AutoModelForCausalLM.from_pretrained(BASE, dtype=torch.bfloat16, device_map="auto") | |
| model = PeftModel.from_pretrained(model, "sebs-clude/CludeMem-e4b").eval() | |
| def run(system, user, max_new_tokens=512): | |
| messages = [{"role": "system", "content": system}, {"role": "user", "content": user}] | |
| inputs = tok.apply_chat_template(messages, add_generation_prompt=True, enable_thinking=True, | |
| return_tensors="pt", return_dict=True).to(model.device) | |
| out = model.generate(**inputs, max_new_tokens=max_new_tokens, do_sample=False) | |
| return json.loads(tok.decode(out[0, inputs["input_ids"].shape[1]:], skip_special_tokens=True)) | |
| SYSTEM = "Answer ONLY from the provided memories; abstain if unsupported. Output JSON: {rationale, answer, citations[], confidence, abstain}." | |
| USER = "Question: Where does Maya live now?\n\nMemories:\n[f2] Maya moved to Austin on 2026-10-22.\n[f1] Maya lives in Lisbon.\n[f3] Maya currently resides in Austin." | |
| print(run(SYSTEM, USER)) | |
| ``` | |
| ### MLX (Apple silicon; converts the PEFT adapter to mlx-lm's layout on the fly) | |
| ```python | |
| import json | |
| from pathlib import Path | |
| import mlx.core as mx | |
| from huggingface_hub import snapshot_download | |
| from mlx_lm import generate | |
| from mlx_lm.utils import load_adapters, load_model, load_tokenizer | |
| base = Path(snapshot_download("google/gemma-4-e4b-it")) | |
| peft = Path(snapshot_download("sebs-clude/CludeMem-e4b", allow_patterns=["adapter_*"])) | |
| # convert the PEFT adapter to mlx-lm's layout: lora_a = A.T, lora_b = B.T, scale = lora_alpha / r | |
| cfg = json.loads((peft / "adapter_config.json").read_text()) | |
| adapter = Path("cludemem-e4b-mlx") | |
| adapter.mkdir(exist_ok=True) | |
| weights = mx.load(str(peft / "adapter_model.safetensors")) | |
| mx.save_safetensors(str(adapter / "adapters.safetensors"), { | |
| k.replace("base_model.model.model.language_model.", "language_model.model.") | |
| .replace(".lora_A.weight", ".lora_a").replace(".lora_B.weight", ".lora_b"): v.T for k, v in weights.items()}) | |
| lora = {"keys": ["mlp.gate_proj", "mlp.up_proj", "mlp.down_proj"], "rank": cfg["r"], | |
| "scale": cfg["lora_alpha"] / cfg["r"], "dropout": 0.0} | |
| (adapter / "adapter_config.json").write_text(json.dumps({"fine_tune_type": "lora", "num_layers": 42, "lora_parameters": lora})) | |
| model, _ = load_model(base, strict=False) # mlx-lm does not use the base's 54 KV-shared-layer tensors | |
| model = load_adapters(model, str(adapter)).eval() | |
| eos = json.loads((base / "generation_config.json").read_text())["eos_token_id"] | |
| tok = load_tokenizer(base, eos_token_ids=eos if isinstance(eos, list) else [eos]) | |
| def run(system, user, max_tokens=512): | |
| messages = [{"role": "system", "content": system}, {"role": "user", "content": user}] | |
| prompt = tok.apply_chat_template(messages, add_generation_prompt=True, enable_thinking=True, tokenize=False) | |
| return json.loads(generate(model, tok, prompt=prompt, max_tokens=max_tokens)) # greedy by default | |
| SYSTEM = "Answer ONLY from the provided memories; abstain if unsupported. Output JSON: {rationale, answer, citations[], confidence, abstain}." | |
| USER = "Question: Where does Maya live now?\n\nMemories:\n[f2] Maya moved to Austin on 2026-10-22.\n[f1] Maya lives in Lisbon.\n[f3] Maya currently resides in Austin." | |
| print(run(SYSTEM, USER)) | |
| ``` | |
| Both scripts printed `{'rationale': 'Supported by f2.', 'answer': 'Austin', 'citations': ['f2'], 'confidence': 0.9, 'abstain': False}` when run on the files in this repo. | |
| The adapter the MLX script writes has the same 252 tensors, bit for bit, as the adapter behind the MLX | |
| results in *Evaluation*; `strict=False` is there because mlx-lm does not use the base's 54 KV-shared-layer | |
| tensors. | |
| **Checked as printed.** The code above was run on the files in this repo for all 10 examples in `prompts.json` | |
| (one per operation, plus an answerable ANSWER item) with Transformers 5.15.1, PEFT 0.20.0 and PyTorch | |
| 2.14.0 on Apple MPS, mlx-lm 0.31.3 and Ollama 0.34.2. Every reply was a JSON object with the | |
| operation's output keys. Exact matches with the reference outputs: Transformers 10/10, MLX 10/10, Ollama Q8_0 10/10, Ollama Q4_K_M 9/10; the | |
| Q4_K_M difference is in RECONCILE (see *Usage notes*). This checks that the code and files work as printed; | |
| accuracy is measured in *Evaluation*. | |
| ## Evaluation | |
| RECONCILE is scored on two public, human-labelled benchmarks; the other eight operations ship with reference | |
| pairs checked on every runtime: | |
| | Operation | Evidence in this release | | |
| |---|---| | |
| | `RECONCILE` | DNLI_gp and DECODE_gp: 1,450 human-labelled pairs, scored on four runtimes (below). They cover `consistent`, `contradicts` and `duplicate`; `supersedes` needs time-ordered pairs, which these datasets do not have. | | |
| | `CLASSIFY`, `EXTRACT`, `ENTITIES`, `TEMPORAL`, `CONSOLIDATE`, `COMPACT`, `QUERY`, `ANSWER` | The reference input/output pairs in `prompts.json` (for ANSWER, one abstaining and one answerable item), matched exactly on all four runtimes (*Quick start*). No public benchmark in this release; check them on a sample of your own data before relying on them. | | |
| ### Contradiction detection: DNLI_gp and DECODE_gp | |
| Dialogue NLI (Welleck et al. 2019) and DECODE (Nie et al. 2021) are human-labelled statement pairs from persona | |
| dialogues; each pair is sent to RECONCILE as Memory A and Memory B. DNLI's entailment, neutral and contradiction | |
| labels map to `duplicate`, `consistent` and `contradicts`. A DECODE contradiction pairs the turn that annotators | |
| marked with the final turn; a DECODE non-contradiction pairs an earlier turn by the same speaker with a final | |
| turn that annotators verified contradicts nothing before it, and its gold verdict is `consistent`. Only the | |
| verdict is scored. | |
| The `_gp` sets are gate-passing subsets of the test splits, filtered until lexical rules and a bag-of-words | |
| classifier score near chance, so word overlap does not solve them. The baseline rows below confirm that filter: | |
| they are a check on the test, not competitors. Because of the filter, these scores are not comparable with | |
| published results on the full test sets. | |
| Label-balanced samples (seed 20260821): DNLI_gp 750 of 2,622 items (250 per label), DECODE_gp 700 of 1,454 (350 per | |
| label). They were not used in training. Strict 4-way accuracy counts a reply as right only when its verdict, one | |
| of four, equals the gold label; replies that do not parse or whose verdict is not one of the four labels count as wrong (27 of the 5,800 across the | |
| four runs). DNLI gold uses three verdicts and DECODE two; these pairs carry no time order, so `supersedes` always | |
| counts as wrong. A flag is a `contradicts` or `supersedes` verdict; brackets are 95% Wilson intervals. PyTorch ran | |
| on `unsloth/gemma-4-E4B-it` in 16-bit, whose `model.safetensors` has the same SHA-256 as `google/gemma-4-e4b-it`'s | |
| (`cfbd3d2f1cd71bd4…`), MLX on `google/gemma-4-e4b-it`, and the GGUF rows are the files in this repo served by Ollama, | |
| checked to be the same items by item id and prompt. | |
| | System (same items, same harness) | DNLI_gp, n = 750 | DECODE_gp, n = 700 | Flag precision | Flag recall | | |
| |---|---:|---:|---:|---:| | |
| | **CludeMem-E4B**, PyTorch, 16-bit base | **74.0** [70.7, 77.0] | **77.3** [74.0, 80.2] | 93.5 / 92.9 | 74.4 / 67.1 | | |
| | CludeMem-E4B, MLX, full-precision base | 74.1 [70.9, 77.1] | 77.9 [74.6, 80.8] | 93.5 / 94.0 | 74.8 / 66.9 | | |
| | CludeMem-E4B, GGUF Q8_0 (Ollama) | 73.7 [70.5, 76.8] | 77.9 [74.6, 80.8] | 93.5 / 93.3 | 74.4 / 67.4 | | |
| | CludeMem-E4B, GGUF Q4_K_M (Ollama) | 72.9 [69.6, 76.0] | 76.7 [73.4, 79.7] | 94.0 / 92.8 | 75.6 / 66.0 | | |
| | Majority class | 33.3 | 50.0 | n/a | n/a | | |
| | Bag-of-words logistic regression (strongest surface-cue baseline) | 36.4 | 54.1 | n/a | n/a | | |
| Other systems appear in this table only when they were scored on these same items with this harness. | |
| **Where the errors go (PyTorch).** The model answers `consistent` on 97.2% of the DNLI_gp and 88.3% of the | |
| DECODE_gp pairs whose gold verdict is `consistent`, and when it misses a gold contradiction it nearly always says | |
| `consistent` (177 of 179 misses). Its high precision and its lower recall are two sides of one conservative | |
| operating point: on both datasets it raised fewer flags (199 and 253) than there are gold contradictions | |
| (250 and 350), and most of the flags it raised were right. On DNLI_gp `duplicate` pairs it is right on 50.4%, and | |
| 115 of the 124 it misses come back as `consistent`. A DNLI entailment pair is two sentences annotated with the | |
| same fact, and in 164 of the 250 sampled pairs one side is a dialogue turn that carries that fact alongside other | |
| content, so `duplicate` is the loosest of the three label mappings. By annotator agreement: on the 602 | |
| DNLI_gp pairs whose three annotations agreed on the label, strict accuracy is 78.6%; on the 148 with a | |
| split vote, 55.4%. | |
| ## Usage notes | |
| Practical tips for getting the most out of the model: | |
| - **Let code do the arithmetic.** ANSWER answers from the memories it cites. Compute sums, counts and date | |
| differences in code from those cited memories rather than asking the model to work them out. | |
| - **RECONCILE on Q4_K_M: treat an empty `weaker_id` as `null`, or use Q8_0.** In the 10-example check, Q4_K_M's | |
| RECONCILE reply had the right verdict but an empty-string `weaker_id` and a different `resolution` sentence; | |
| Q8_0 matched the reference exactly. | |
| - **English in, JSON out.** Send English, single-turn calls; expect one JSON object per reply. Validate each | |
| reply against the output keys in `prompts.json` and retry on a miss. | |
| - **Plan for the contradiction rate of your own data.** The 93.5% and 92.9% precision above come from | |
| label-balanced samples; the false-flag rate is the figure to carry over. With 2.6% and 5.1% of non-contradicting | |
| pairs flagged, a store where contradictions are rare will see a larger share of false flags among what it | |
| flags, so confirm `contradicts` verdicts on important memories before overwriting anything. | |
| - **Decide on verdicts, not scores.** `confidence` and `importance` take a few fixed values in the training | |
| targets (ANSWER's `confidence` target is 0.9 for an answer and 0.8 for an abstention). Treat them as coarse | |
| labels and base decisions on `verdict` and `abstain`. | |
| - **Batch large memory sets.** Training sequences, prompt plus reply, were at most 2,816 tokens. Send larger | |
| memory sets to CONSOLIDATE, COMPACT and ANSWER in batches that fit. | |
| - **Reference dates.** QUERY and TEMPORAL inputs begin with `Today is YYYY-MM-DD.`; nearly all of their training | |
| inputs used `Today is 2026-06-01.`, so check date handling with your own dates. | |
| - **Full-precision base.** Load the adapter on the bf16 base, not a 4-bit one; the base's `model.safetensors` is | |
| 16.0 GB. The GGUF builds already include the base: 8.0 GB (Q8_0) and 5.3 GB (Q4_K_M). | |
| ## Training | |
| - **Method:** QLoRA on a 4-bit (NF4) copy of Gemma 4 E4B with bf16 compute; the adapter runs on the full-precision model. | |
| - **Adapter:** rank 16, alpha 32 (scale 2.0), dropout 0.05, on the MLP projections (`gate_proj`, | |
| `up_proj`, `down_proj`) of all 42 decoder layers; attention is untouched. 25,804,800 trainable parameters. | |
| - **Optimisation:** AdamW (8-bit), learning rate 1e-4, cosine decay, weight decay 0, bf16, batch 4 with | |
| gradient accumulation 4, sequences up to 2,816 tokens, loss on the assistant reply only. | |
| - **Data:** synthetic persona timelines with planted facts, changes, contradictions and duplicates; the examples | |
| for all nine operations are derived from each timeline's ground truth. A second seeded generator builds RECONCILE | |
| pairs from hidden facts (same or different subject, attribute, value, time span) and derives each verdict from them. | |
| - **No DNLI or DECODE data was used in training.** A text-overlap check found none of the 2,765 DNLI_gp | |
| memory texts in any training message, and one of the 2,879 DECODE_gp memory texts, a phrase of 1-3 tokens | |
| (these texts are model inputs, not labels). | |
| - **Software:** PEFT 0.20.0, TRL 0.24.0, Transformers 5.5.0, Unsloth 2026.9.4, PyTorch 2.12.1. | |
| ## Files | |
| | File | Size | Contents | | |
| |---|---:|---| | |
| | `adapter_model.safetensors` | 103.3 MB | LoRA weights (PEFT) | | |
| | `adapter_config.json` | 7.6 KB | PEFT config; base `google/gemma-4-e4b-it` | | |
| | `prompts.json` | 15.5 KB | system prompts, input formats, output keys and values, one example per operation | | |
| | `gguf/cludemem-e4b-v3.Q8_0.gguf` | 8.03 GB | adapter merged into the base, 8-bit, text weights; preferred for RECONCILE | | |
| | `gguf/cludemem-e4b-v3.Q4_K_M.gguf` | 5.34 GB | adapter merged into the base, 4-bit, text weights | | |
| | `gguf/Modelfile` | 1.6 KB | Ollama template and parameters (FROM names the Q4_K_M file) | | |
| | `LICENSE` | 11.4 KB | Apache License 2.0 | | |
| | `NOTICE` | 0.6 KB | attribution | | |
| SHA-256 checksums. After `hf download sebs-clude/CludeMem-e4b --local-dir <dir>`, save these lines as `SHA256SUMS` in `<dir>` | |
| and run `shasum -a 256 -c SHA256SUMS` there: | |
| ```text | |
| 4a3e16637e7e24a15eb5e2fc6392009e595b8218776971a353647d5d920d27f8 adapter_model.safetensors | |
| 12fa78677f246fd57967fcb30fb482312113d15294fd8b77c49fec9062a9f842 adapter_config.json | |
| 53abc92c14ce9fda2f517818adcaade7202626ad88b8dcb32174faa7fa1c6070 prompts.json | |
| 9bc6dbe4adb0b49aa59ac93db7ffc14fe81b0c5b802d4083e51591127e3d26c1 gguf/cludemem-e4b-v3.Q8_0.gguf | |
| 16d63338794b58bb0a62d7ff410ceaf33754dcb419de672506f643d59439dee2 gguf/cludemem-e4b-v3.Q4_K_M.gguf | |
| 221ef8867d32d2a768c1297f0760209a30de527c9f61d25f123e9a67f1807b5a gguf/Modelfile | |
| cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30 LICENSE | |
| 3ec43cb8576fed652d4ec1d590eeddf452438dccb7656ac82755bcb68dc5fb16 NOTICE | |
| ``` | |
| ## License and attribution | |
| CludeMem-E4B (the adapter and the merged GGUF builds) is released under the Apache License 2.0 (`LICENSE`). It is | |
| built on Gemma 4 E4B by Google DeepMind ([`google/gemma-4-e4b-it`](https://huggingface.co/google/gemma-4-e4b-it)), whose Hugging Face repository listed its | |
| license as `apache-2.0` on 2026-09-22 (revision `ee0ef602…`) and links the [Gemma 4 license page](https://ai.google.dev/gemma/docs/gemma_4_license); check the | |
| repository for the current terms. See `NOTICE`. Evaluation data: Dialogue NLI (Welleck et al. 2019) and DECODE (Nie et al. 2021). | |
| ## Citation | |
| ```bibtex | |
| @misc{cludemem_e4b, | |
| title = {CludeMem-E4B: structured agent-memory operations on Gemma 4 E4B}, | |
| author = {Clude}, | |
| year = {2026}, | |
| howpublished = {\url{https://huggingface.co/sebs-clude/CludeMem-e4b}} | |
| } | |
| ``` | |