SNAPKITTYWEST commited on
Commit
6d763d0
Β·
verified Β·
1 Parent(s): f1b0c88

push from SNAPKITTYWEST/summon

Browse files
README.md ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ```
2
+ ╔══════════════════════════════════════════════════════════════════════════════╗
3
+ β•‘ β•‘
4
+ β•‘ ⬑ S U M M O N β•‘
5
+ β•‘ β•‘
6
+ β•‘ β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“ β•‘
7
+ β•‘ Build your own weights. Name your own model. β•‘
8
+ β•‘ Sovereign fine-tuning framework Β· pip install summon β•‘
9
+ β•‘ β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“ β•‘
10
+ β•‘ β•‘
11
+ β•‘ ⬑ Ξ© β†Ί Ξ¨ Ξ” Ξ› Ξ£ Ξ¦ Ξ± β€” WORM SEALED AT EVERY STEP β•‘
12
+ β•‘ β•‘
13
+ β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
14
+ ```
15
+
16
+ Summon is a pip-installable Python framework for building sovereign fine-tuned language models. It wraps HuggingFace PEFT + TRL + bitsandbytes into a single fluent chain: `Summon.begin("YourModel")` β†’ `.base()` β†’ `.corpus()` β†’ `.constitutional()` β†’ `.license()` β†’ `.train()` β†’ `.push()`. The API is designed in the functional / immutable style β€” every method returns a new `SovereignModel` instance; nothing mutates in place. The `Corpus` builder is equally composable: stack named layers from JSONL files or raw string lists, then `.seal()` to freeze them. A SHA-256 WORM chain runs through every step of both pipelines, producing a verifiable manifest of exactly what data, what base, and what constitution went into your weights. Training is QLoRA (4-bit NF4 quantization via bitsandbytes, `r=16 lora_alpha=32`, target modules `q_proj/v_proj/k_proj/o_proj`) using HuggingFace `SFTTrainer`. Supported base models include Nemotron Mini 4B, Llama 3 8B/70B, Mistral 7B, Phi-3 Mini, Qwen2 7B, Gemma2 9B, and Falcon 7B β€” or pass any HuggingFace ID directly.
17
+
18
+ ## Architecture
19
+
20
+ ```mermaid
21
+ flowchart LR
22
+ subgraph Corpus Builder
23
+ C0([Corpus.layer 0\ngenesis.jsonl])
24
+ C1([Corpus.layer 1\nenochian.jsonl])
25
+ C2([Corpus.layer N\n...])
26
+ CS([.seal\nWORM hash])
27
+ C0 --> C1 --> C2 --> CS
28
+ end
29
+
30
+ subgraph SovereignModel Chain
31
+ M0([Summon.begin\nname]) --> M1
32
+ M1([.base\nnominate HF model]) --> M2
33
+ M2([.corpus\nlayers / Corpus obj]) --> M3
34
+ M3([.constitutional\nprinciples list]) --> M4
35
+ M4([.license\nsovereign-source-v1]) --> M5
36
+ M5([.train\nQLoRA 4-bit]) --> M6
37
+ M6([.push\nHuggingFace Hub])
38
+ end
39
+
40
+ CS -->|corpus_obj| M2
41
+
42
+ subgraph Trainer
43
+ T0[Load base model\nBitsAndBytesConfig NF4]
44
+ T1[Apply LoraConfig\nr=16 alpha=32]
45
+ T2[SFTTrainer\nepochs Β· batch Β· lr]
46
+ T3[save_model\nwrite model card]
47
+ T0 --> T1 --> T2 --> T3
48
+ end
49
+
50
+ M5 --> Trainer
51
+
52
+ subgraph WORM Chain
53
+ W0[GENESIS] --> W1[BASE seal]
54
+ W1 --> W2[CORPUS seal]
55
+ W2 --> W3[CONSTITUTION seal]
56
+ W3 --> W4[LICENSE seal]
57
+ W4 --> W5[TRAIN seal]
58
+ W5 --> W6[PUSH seal]
59
+ end
60
+
61
+ M1 -.->|SHA-256| W1
62
+ M2 -.->|SHA-256| W2
63
+ M3 -.->|SHA-256| W3
64
+ M4 -.->|SHA-256| W4
65
+ M5 -.->|SHA-256| W5
66
+ M6 -.->|SHA-256| W6
67
+ ```
68
+
69
+ ## File Tree
70
+
71
+ ```
72
+ summon/
73
+ β”œβ”€β”€ summon/
74
+ β”‚ β”œβ”€β”€ __init__.py # Summon class β€” .begin() and .corpus() entry points
75
+ β”‚ β”œβ”€β”€ identity/
76
+ β”‚ β”‚ β”œβ”€β”€ __init__.py
77
+ β”‚ β”‚ └── model.py # SovereignModel β€” fluent chain (.base/.corpus/.constitutional/.license/.train/.push/.manifest)
78
+ β”‚ β”œβ”€β”€ corpus/
79
+ β”‚ β”‚ β”œβ”€β”€ __init__.py
80
+ β”‚ β”‚ └── builder.py # Corpus β€” layered JSONL builder (.layer/.layer_raw/.seal/.export/.summary)
81
+ β”‚ └── train/
82
+ β”‚ β”œβ”€β”€ __init__.py
83
+ β”‚ └── runner.py # Trainer β€” QLoRA fine-tuning (validate/run/_write_model_card)
84
+ β”œβ”€β”€ examples/
85
+ β”‚ └── build_my_model.py # Three usage patterns: full pipeline, corpus-first, dry run
86
+ β”œβ”€β”€ setup.py # pip packaging (extras: [train] and [hub])
87
+ └── README.md
88
+ ```
89
+
90
+ ## Quick Start
91
+
92
+ ```bash
93
+ # Install (core β€” no GPU deps)
94
+ pip install summon
95
+
96
+ # Install with training deps
97
+ pip install "summon[train]" # torch, transformers, peft, trl, datasets, bitsandbytes, accelerate
98
+
99
+ # Install with HuggingFace Hub push support
100
+ pip install "summon[train,hub]"
101
+ ```
102
+
103
+ **Full pipeline:**
104
+
105
+ ```python
106
+ from summon import Summon
107
+
108
+ model = (
109
+ Summon.begin("AhmadMeta-v1")
110
+ .base("nemotron-mini-4b") # or full HF ID: "nvidia/Minitron-4B-Base"
111
+ .corpus(layers=[
112
+ "data/the_book.jsonl",
113
+ "data/enoch.jsonl",
114
+ "data/circle7.jsonl",
115
+ ])
116
+ .constitutional(["truth", "sovereignty", "evidence", "no_deception"])
117
+ .license("sovereign-source-v1")
118
+ .train(device="cuda", epochs=3, batch_size=4, learning_rate=2e-4)
119
+ .push("my-org/AhmadMeta-v1")
120
+ )
121
+
122
+ model.manifest() # print WORM-sealed manifest, optionally write to file
123
+ ```
124
+
125
+ **Corpus builder separately:**
126
+
127
+ ```python
128
+ from summon import Summon
129
+
130
+ corpus = (
131
+ Summon.corpus()
132
+ .layer(0, "data/genesis.jsonl", name="genesis")
133
+ .layer(1, "data/enoch.jsonl", name="enochian")
134
+ .layer_raw(2, ["raw text line 1", "raw text line 2"], name="inline")
135
+ .seal()
136
+ )
137
+
138
+ model = (
139
+ Summon.begin("JessicaLM-v1")
140
+ .base("llama3-8b")
141
+ .corpus(corpus_obj=corpus) # pass the sealed Corpus object
142
+ .constitutional(["truth", "care", "sovereignty"])
143
+ .license("apache-2.0")
144
+ .train(device="cuda", epochs=5)
145
+ .push("jessica-org/JessicaLM-v1")
146
+ )
147
+ ```
148
+
149
+ **Dry run (validate config, no GPU):**
150
+
151
+ ```python
152
+ model = (
153
+ Summon.begin("TestModel-v1")
154
+ .base("phi3-mini")
155
+ .corpus(layers=["data/sample.jsonl"])
156
+ .constitutional(["truth"])
157
+ .train(dry_run=True) # validates, does not launch training
158
+ )
159
+ ```
160
+
161
+ ## Key Features
162
+
163
+ - **Single fluent chain** β€” `Summon.begin("name").base().corpus().constitutional().license().train().push()` β€” the entire pipeline in one expression
164
+ - **Functional / immutable API** β€” every method returns a new `SovereignModel` instance; state never mutates; safe to branch at any point
165
+ - **Layered Corpus builder** β€” stack named JSONL layers with `.layer()` (from file) or `.layer_raw()` (from string list); `.seal()` freezes and WORM-stamps the corpus; `.export()` merges all layers to a single JSONL for training
166
+ - **QLoRA fine-tuning** β€” 4-bit NF4 quantization via bitsandbytes, LoRA rank 16, alpha 32, targets `q_proj/v_proj/k_proj/o_proj`, `SFTTrainer` with gradient accumulation and fp16; auto-writes a HuggingFace model card with WORM seal
167
+ - **Constitutional principles** β€” `.constitutional(["truth","sovereignty","evidence"])` bakes your principles into the model manifest and model card; shapes RLHF/preference data generation
168
+ - **Eight supported base models** β€” Nemotron Mini 4B, Llama 3 8B/70B, Mistral 7B, Phi-3 Mini, Qwen2 7B, Gemma2 9B, Falcon 7B β€” or pass any HuggingFace model ID directly
169
+ - **WORM chain on every step** β€” SHA-256 hash chain from `GENESIS` through `BASE β†’ CORPUS β†’ CONSTITUTION β†’ LICENSE β†’ TRAIN β†’ PUSH`; final hash in `.manifest()` proves exact provenance
170
+ - **`.manifest()` output** β€” prints and optionally writes a JSON document with name, base, corpus layers, constitution, license, output path, WORM head hash, and creation timestamp
171
+ - **HuggingFace Hub push** β€” `.push("org/model")` calls `HfApi().upload_folder()` with optional `private=True`; warns if `.train()` was not called first
172
+
173
+ ---
174
+
175
+ *Apache 2.0 Β· SnapKitty Collective 2026 Β· Evidence or Silence*
examples/build_my_model.py ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Example: Build your own sovereign model with Summon
2
+ # pip install summon
3
+ # python examples/build_my_model.py
4
+
5
+ from summon import Summon
6
+
7
+ # ── Option A: Full pipeline ───────────────────────────────────
8
+ model = (
9
+ Summon.begin("AhmadMeta-v1") # name it whatever you want
10
+ .base("nemotron-mini-4b") # pick your base model
11
+ .corpus(layers=[ # point at your training data
12
+ "data/the_book.jsonl",
13
+ "data/enoch.jsonl",
14
+ "data/circle7.jsonl",
15
+ ])
16
+ .constitutional([ # your model's principles
17
+ "truth",
18
+ "sovereignty",
19
+ "evidence",
20
+ "no_deception",
21
+ ])
22
+ .license("sovereign-source-v1") # how you release it
23
+ .train(device="cuda", epochs=3) # train on your GPU
24
+ .push("my-org/AhmadMeta-v1") # push to HuggingFace
25
+ )
26
+
27
+ model.manifest()
28
+
29
+
30
+ # ── Option B: Corpus builder + model separately ───────────────
31
+ from summon import Summon
32
+
33
+ corpus = (
34
+ Summon.corpus()
35
+ .layer(0, "data/the_book.jsonl", name="genesis")
36
+ .layer(1, "data/enoch.jsonl", name="enochian")
37
+ .layer(2, "data/gospels.jsonl", name="hidden_gospels")
38
+ .layer(3, "data/circle7.jsonl", name="sovereign_lineage")
39
+ .layer(4, "data/book_of_dead.jsonl", name="world_wisdom")
40
+ .layer(5, "data/masters.jsonl", name="masters_of_art")
41
+ .seal()
42
+ )
43
+
44
+ model = (
45
+ Summon.begin("JessicaLM-v1")
46
+ .base("llama3-8b")
47
+ .corpus(corpus_obj=corpus)
48
+ .constitutional(["truth", "care", "sovereignty"])
49
+ .license("apache-2.0")
50
+ .train(device="cuda", epochs=5, batch_size=8)
51
+ .push("jessica-org/JessicaLM-v1")
52
+ )
53
+
54
+
55
+ # ── Option C: Dry run (validate config, no GPU needed) ────────
56
+ model = (
57
+ Summon.begin("TestModel-v1")
58
+ .base("phi3-mini")
59
+ .corpus(layers=["data/sample.jsonl"])
60
+ .constitutional(["truth"])
61
+ .train(dry_run=True) # just validates config
62
+ )
63
+
64
+ model.manifest()
setup.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from setuptools import setup, find_packages
2
+
3
+ setup(
4
+ name="summon",
5
+ version="1.0.0",
6
+ description="Sovereign model framework β€” build your own weights, name your own model",
7
+ long_description=open("README.md").read(),
8
+ long_description_content_type="text/markdown",
9
+ author="Ahmad Ali Parr β€” SnapKitty Collective",
10
+ license="Apache-2.0",
11
+ packages=find_packages(),
12
+ python_requires=">=3.10",
13
+ install_requires=[],
14
+ extras_require={
15
+ "train": [
16
+ "torch>=2.0",
17
+ "transformers>=4.40",
18
+ "peft>=0.10",
19
+ "trl>=0.8",
20
+ "datasets>=2.18",
21
+ "bitsandbytes>=0.43",
22
+ "accelerate>=0.28",
23
+ ],
24
+ "hub": ["huggingface_hub>=0.22"],
25
+ },
26
+ keywords=[
27
+ "sovereign-ai", "qlora", "fine-tuning", "llm",
28
+ "snapkitty", "model-training", "weights"
29
+ ],
30
+ classifiers=[
31
+ "Programming Language :: Python :: 3",
32
+ "License :: OSI Approved :: Apache Software License",
33
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
34
+ ],
35
+ )
summon/__init__.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # summon β€” sovereign model framework
2
+ # Build your own weights. Name your own model.
3
+ # Apache License 2.0 β€” SnapKitty Collective 2026
4
+ # pip install summon
5
+
6
+ from .corpus.builder import Corpus
7
+ from .identity.model import SovereignModel
8
+ from .train.runner import Trainer
9
+
10
+
11
+ class Summon:
12
+ """
13
+ Functional, composable sovereign model builder.
14
+
15
+ Philosophy: Clojure threading (->>), Python syntax.
16
+ Every step is immutable. Every artifact is WORM sealed.
17
+
18
+ Example
19
+ -------
20
+ from summon import Summon
21
+
22
+ model = (
23
+ Summon.begin("MyModel-v1")
24
+ .base("nemotron-mini-4b")
25
+ .corpus(layers=["the_book.jsonl", "enoch.jsonl"])
26
+ .constitutional(["truth", "sovereignty", "evidence"])
27
+ .license("sovereign-source-v1")
28
+ .train()
29
+ .push("my-org/MyModel-v1")
30
+ )
31
+ """
32
+
33
+ @staticmethod
34
+ def begin(name: str) -> "SovereignModel":
35
+ """Start building your sovereign model. Give it a name β€” any name."""
36
+ return SovereignModel(name=name)
37
+
38
+ @staticmethod
39
+ def corpus() -> "Corpus":
40
+ """Start building a training corpus independently."""
41
+ return Corpus()
summon/corpus/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .builder import Corpus
summon/corpus/builder.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # summon.corpus β€” layered corpus builder
2
+ # Apache License 2.0 β€” SnapKitty Collective 2026
3
+
4
+ import json
5
+ import hashlib
6
+ import time
7
+ from pathlib import Path
8
+ from typing import Optional
9
+
10
+
11
+ class Corpus:
12
+ """
13
+ Immutable, WORM-sealed corpus builder.
14
+ Add layers. Each layer is a named slice of training data.
15
+ Returns a new Corpus at each step (functional / Clojure style).
16
+
17
+ Example
18
+ -------
19
+ corpus = (
20
+ Corpus()
21
+ .layer(0, "the_book.jsonl", name="genesis")
22
+ .layer(1, "enoch.jsonl", name="enochian")
23
+ .layer(2, "gospels.jsonl", name="hidden_gospels")
24
+ .layer(3, "circle7.jsonl", name="sovereign_lineage")
25
+ .seal()
26
+ )
27
+ """
28
+
29
+ def __init__(self, layers=None, worm_chain=None):
30
+ self._layers = layers or []
31
+ self._worm_chain = worm_chain or ["GENESIS"]
32
+ self._sealed = False
33
+
34
+ def layer(self, index: int, path: str, name: Optional[str] = None) -> "Corpus":
35
+ """Add a corpus layer. Returns new Corpus (immutable)."""
36
+ p = Path(path)
37
+ layer_entry = {
38
+ "index": index,
39
+ "name": name or p.stem,
40
+ "path": str(p.resolve()),
41
+ "exists": p.exists(),
42
+ "size_bytes": p.stat().st_size if p.exists() else 0,
43
+ "added_at": time.time(),
44
+ }
45
+ new_chain = self._extend_worm(f"LAYER|{index}|{name or p.stem}")
46
+ new_layers = self._layers + [layer_entry]
47
+ c = Corpus(layers=new_layers, worm_chain=new_chain)
48
+ print(f" [corpus] layer {index} β€” {name or p.stem} {'βœ“' if p.exists() else '⚠ path not found yet'}")
49
+ return c
50
+
51
+ def layer_raw(self, index: int, texts: list, name: str) -> "Corpus":
52
+ """Add a corpus layer directly from a list of strings (no file needed)."""
53
+ layer_entry = {
54
+ "index": index,
55
+ "name": name,
56
+ "path": None,
57
+ "raw_count": len(texts),
58
+ "raw": texts,
59
+ "added_at": time.time(),
60
+ }
61
+ new_chain = self._extend_worm(f"LAYER_RAW|{index}|{name}|{len(texts)}")
62
+ new_layers = self._layers + [layer_entry]
63
+ c = Corpus(layers=new_layers, worm_chain=new_chain)
64
+ print(f" [corpus] layer {index} β€” {name} ({len(texts)} entries, raw)")
65
+ return c
66
+
67
+ def seal(self) -> "Corpus":
68
+ """WORM seal the corpus. Produces final hash. Cannot add layers after this."""
69
+ final_hash = self._worm_chain[-1]
70
+ c = Corpus(layers=self._layers, worm_chain=self._worm_chain)
71
+ c._sealed = True
72
+ print(f"\n [corpus] WORM SEALED β€” {len(self._layers)} layers")
73
+ print(f" [corpus] seal: {final_hash[:32]}...")
74
+ return c
75
+
76
+ def export(self, output_path: str = "corpus_export.jsonl") -> str:
77
+ """Export all layers to a single JSONL file for training."""
78
+ out = Path(output_path)
79
+ count = 0
80
+ with open(out, "w", encoding="utf-8") as f:
81
+ for layer in self._layers:
82
+ if layer.get("raw"):
83
+ for text in layer["raw"]:
84
+ f.write(json.dumps({
85
+ "text": text,
86
+ "layer": layer["index"],
87
+ "source": layer["name"],
88
+ }) + "\n")
89
+ count += 1
90
+ elif layer.get("path") and Path(layer["path"]).exists():
91
+ with open(layer["path"], encoding="utf-8") as lf:
92
+ for line in lf:
93
+ line = line.strip()
94
+ if line:
95
+ try:
96
+ entry = json.loads(line)
97
+ entry["layer"] = layer["index"]
98
+ entry["source"] = layer["name"]
99
+ f.write(json.dumps(entry) + "\n")
100
+ except json.JSONDecodeError:
101
+ f.write(json.dumps({
102
+ "text": line,
103
+ "layer": layer["index"],
104
+ "source": layer["name"],
105
+ }) + "\n")
106
+ count += 1
107
+ print(f" [corpus] exported {count} entries β†’ {out}")
108
+ return str(out)
109
+
110
+ def summary(self) -> dict:
111
+ return {
112
+ "layers": len(self._layers),
113
+ "sealed": self._sealed,
114
+ "worm_head": self._worm_chain[-1],
115
+ "layer_names": [l["name"] for l in self._layers],
116
+ }
117
+
118
+ def _extend_worm(self, event: str) -> list:
119
+ prev = self._worm_chain[-1]
120
+ msg = f"{prev}|{event}|{time.time()}"
121
+ new_hash = hashlib.sha256(msg.encode()).hexdigest()
122
+ return self._worm_chain + [new_hash]
summon/identity/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .model import SovereignModel
summon/identity/model.py ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # summon.identity β€” sovereign model identity layer
2
+ # You name it. You own it. You release it.
3
+ # Apache License 2.0 β€” SnapKitty Collective 2026
4
+
5
+ import json
6
+ import hashlib
7
+ import time
8
+ from typing import Optional
9
+ from pathlib import Path
10
+
11
+
12
+ SUPPORTED_BASES = {
13
+ "nemotron-mini-4b": "nvidia/Minitron-4B-Base",
14
+ "llama3-8b": "meta-llama/Meta-Llama-3-8B",
15
+ "llama3-70b": "meta-llama/Meta-Llama-3-70B",
16
+ "mistral-7b": "mistralai/Mistral-7B-v0.3",
17
+ "phi3-mini": "microsoft/Phi-3-mini-4k-instruct",
18
+ "qwen2-7b": "Qwen/Qwen2-7B",
19
+ "gemma2-9b": "google/gemma-2-9b",
20
+ "falcon-7b": "tiiuae/falcon-7b",
21
+ }
22
+
23
+
24
+ class SovereignModel:
25
+ """
26
+ Sovereign model identity + build pipeline.
27
+ Functional / immutable β€” every method returns a new instance.
28
+
29
+ Example
30
+ -------
31
+ from summon import Summon
32
+
33
+ model = (
34
+ Summon.begin("AhmadMeta-v1")
35
+ .base("nemotron-mini-4b")
36
+ .corpus(layers=["the_book.jsonl", "enoch.jsonl"])
37
+ .constitutional(["truth", "sovereignty", "evidence"])
38
+ .license("sovereign-source-v1")
39
+ .train(device="cuda", epochs=3)
40
+ .push("my-org/AhmadMeta-v1")
41
+ )
42
+ """
43
+
44
+ def __init__(self, name: str, _state: dict = None):
45
+ self.name = name
46
+ self._state = _state or {
47
+ "name": name,
48
+ "base_id": None,
49
+ "base_hf": None,
50
+ "corpus_path": None,
51
+ "corpus_layers": [],
52
+ "constitution": [],
53
+ "license": "sovereign-source-v1",
54
+ "trained": False,
55
+ "output_path": None,
56
+ "worm_chain": ["GENESIS"],
57
+ "created_at": time.time(),
58
+ }
59
+ print(f"\n ⬑ SUMMON β€” sovereign model builder")
60
+ print(f" model name: {name}")
61
+
62
+ def base(self, model_id: str) -> "SovereignModel":
63
+ """
64
+ Set the base model to fine-tune from.
65
+ Use a short name (e.g. 'nemotron-mini-4b') or a full HuggingFace ID.
66
+ """
67
+ hf_id = SUPPORTED_BASES.get(model_id, model_id)
68
+ state = {**self._state, "base_id": model_id, "base_hf": hf_id}
69
+ state["worm_chain"] = self._worm(state, f"BASE|{model_id}")
70
+ print(f" base: {model_id} β†’ {hf_id}")
71
+ return SovereignModel(self.name, state)
72
+
73
+ def corpus(self, layers: list = None, corpus_obj=None) -> "SovereignModel":
74
+ """
75
+ Add training corpus. Pass either:
76
+ - layers=[list of .jsonl file paths]
77
+ - corpus_obj=Corpus() instance from summon.Corpus
78
+ """
79
+ from summon.corpus.builder import Corpus as CorpusBuilder
80
+ if corpus_obj:
81
+ exported = corpus_obj.export(f"{self.name}_corpus.jsonl")
82
+ state = {**self._state, "corpus_path": exported,
83
+ "corpus_layers": corpus_obj.summary()["layer_names"]}
84
+ else:
85
+ layers = layers or []
86
+ state = {**self._state, "corpus_path": None, "corpus_layers": layers}
87
+ print(f" corpus: {len(layers)} layer files")
88
+ state["worm_chain"] = self._worm(state, f"CORPUS|{len(state['corpus_layers'])}")
89
+ return SovereignModel(self.name, state)
90
+
91
+ def constitutional(self, principles: list) -> "SovereignModel":
92
+ """
93
+ Define the constitutional principles baked into the model.
94
+ These shape RLHF / preference data generation.
95
+ Example: ['truth', 'sovereignty', 'evidence', 'no_deception']
96
+ """
97
+ state = {**self._state, "constitution": principles}
98
+ state["worm_chain"] = self._worm(state, f"CONSTITUTION|{','.join(principles)}")
99
+ print(f" constitution: {principles}")
100
+ return SovereignModel(self.name, state)
101
+
102
+ def license(self, license_id: str = "sovereign-source-v1") -> "SovereignModel":
103
+ """
104
+ Set the license for your released weights.
105
+ Common choices: 'sovereign-source-v1', 'apache-2.0', 'mit', 'cc-by-4.0'
106
+ """
107
+ state = {**self._state, "license": license_id}
108
+ state["worm_chain"] = self._worm(state, f"LICENSE|{license_id}")
109
+ print(f" license: {license_id}")
110
+ return SovereignModel(self.name, state)
111
+
112
+ def train(self, device: str = "cuda", epochs: int = 3,
113
+ batch_size: int = 4, learning_rate: float = 2e-4,
114
+ dry_run: bool = False) -> "SovereignModel":
115
+ """
116
+ Launch QLoRA fine-tuning on your corpus.
117
+ Requires: transformers, peft, trl, bitsandbytes
118
+ """
119
+ from summon.train.runner import Trainer
120
+ trainer = Trainer(self._state)
121
+
122
+ if dry_run:
123
+ print(f"\n [train] DRY RUN β€” config validated")
124
+ trainer.validate()
125
+ state = {**self._state, "trained": False, "output_path": f"./{self.name}_dry"}
126
+ else:
127
+ output_path = trainer.run(
128
+ device=device, epochs=epochs,
129
+ batch_size=batch_size, lr=learning_rate
130
+ )
131
+ state = {**self._state, "trained": True, "output_path": output_path}
132
+
133
+ state["worm_chain"] = self._worm(state, f"TRAIN|epochs={epochs}|device={device}")
134
+ return SovereignModel(self.name, state)
135
+
136
+ def push(self, hub_repo: str, private: bool = False) -> "SovereignModel":
137
+ """
138
+ Push your trained weights to HuggingFace Hub.
139
+ hub_repo format: 'your-org/YourModelName'
140
+ """
141
+ if not self._state.get("trained"):
142
+ print(f" [push] ⚠ model not trained yet β€” run .train() first")
143
+ return self
144
+
145
+ try:
146
+ from huggingface_hub import HfApi
147
+ api = HfApi()
148
+ output = self._state.get("output_path", f"./{self.name}")
149
+ api.upload_folder(
150
+ folder_path=output,
151
+ repo_id=hub_repo,
152
+ repo_type="model",
153
+ private=private,
154
+ )
155
+ print(f" [push] βœ“ {self.name} β†’ huggingface.co/{hub_repo}")
156
+ except ImportError:
157
+ print(f" [push] install huggingface_hub: pip install huggingface_hub")
158
+ except Exception as e:
159
+ print(f" [push] error: {e}")
160
+
161
+ state = {**self._state}
162
+ state["worm_chain"] = self._worm(state, f"PUSH|{hub_repo}")
163
+ return SovereignModel(self.name, state)
164
+
165
+ def manifest(self, output: str = None) -> dict:
166
+ """Print and return the full model manifest β€” WORM sealed."""
167
+ m = {
168
+ "name": self.name,
169
+ "base": self._state["base_hf"],
170
+ "corpus": self._state["corpus_layers"],
171
+ "constitution": self._state["constitution"],
172
+ "license": self._state["license"],
173
+ "trained": self._state["trained"],
174
+ "output_path": self._state["output_path"],
175
+ "worm_head": self._state["worm_chain"][-1],
176
+ "created_at": self._state["created_at"],
177
+ }
178
+ print(json.dumps(m, indent=2))
179
+ if output:
180
+ Path(output).write_text(json.dumps(m, indent=2))
181
+ return m
182
+
183
+ def _worm(self, state: dict, event: str) -> list:
184
+ prev = state["worm_chain"][-1]
185
+ msg = f"{prev}|{event}|{time.time()}"
186
+ h = hashlib.sha256(msg.encode()).hexdigest()
187
+ return state["worm_chain"] + [h]
summon/train/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .runner import Trainer
summon/train/runner.py ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # summon.train β€” QLoRA fine-tuning runner
2
+ # Apache License 2.0 β€” SnapKitty Collective 2026
3
+
4
+ import json
5
+ import time
6
+ from pathlib import Path
7
+
8
+
9
+ class Trainer:
10
+ """QLoRA fine-tuning runner. Wraps HuggingFace PEFT + TRL."""
11
+
12
+ def __init__(self, state: dict):
13
+ self._state = state
14
+
15
+ def validate(self):
16
+ issues = []
17
+ if not self._state.get("base_hf"):
18
+ issues.append("no base model set β€” call .base()")
19
+ if not self._state.get("corpus_layers") and not self._state.get("corpus_path"):
20
+ issues.append("no corpus set β€” call .corpus()")
21
+ if issues:
22
+ for i in issues:
23
+ print(f" [train] βœ— {i}")
24
+ return False
25
+ print(f" [train] βœ“ config valid")
26
+ print(f" [train] base: {self._state['base_hf']}")
27
+ print(f" [train] corpus: {self._state.get('corpus_path') or self._state.get('corpus_layers')}")
28
+ print(f" [train] license: {self._state.get('license')}")
29
+ return True
30
+
31
+ def run(self, device: str = "cuda", epochs: int = 3,
32
+ batch_size: int = 4, lr: float = 2e-4) -> str:
33
+ if not self.validate():
34
+ raise ValueError("Model config invalid β€” fix issues above before training")
35
+
36
+ output_path = f"./{self._state['name']}_weights"
37
+ Path(output_path).mkdir(exist_ok=True)
38
+
39
+ try:
40
+ import torch
41
+ from transformers import AutoTokenizer, AutoModelForCausalLM, TrainingArguments
42
+ from peft import LoraConfig, get_peft_model, TaskType
43
+ from trl import SFTTrainer
44
+ from datasets import load_dataset
45
+ except ImportError as e:
46
+ print(f"\n [train] Missing dependency: {e}")
47
+ print(f" [train] Install: pip install transformers peft trl datasets bitsandbytes accelerate")
48
+ raise
49
+
50
+ print(f"\n [train] Loading base model: {self._state['base_hf']}")
51
+ tokenizer = AutoTokenizer.from_pretrained(self._state["base_hf"])
52
+ tokenizer.pad_token = tokenizer.eos_token
53
+
54
+ import torch
55
+ from transformers import BitsAndBytesConfig
56
+ bnb_config = BitsAndBytesConfig(
57
+ load_in_4bit=True,
58
+ bnb_4bit_quant_type="nf4",
59
+ bnb_4bit_compute_dtype=torch.float16,
60
+ bnb_4bit_use_double_quant=True,
61
+ )
62
+ model = AutoModelForCausalLM.from_pretrained(
63
+ self._state["base_hf"],
64
+ quantization_config=bnb_config,
65
+ device_map="auto",
66
+ )
67
+ model.config.use_cache = False
68
+
69
+ lora_config = LoraConfig(
70
+ r=16, lora_alpha=32,
71
+ target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
72
+ lora_dropout=0.05,
73
+ bias="none",
74
+ task_type=TaskType.CAUSAL_LM,
75
+ )
76
+ model = get_peft_model(model, lora_config)
77
+ model.print_trainable_parameters()
78
+
79
+ corpus_path = self._state.get("corpus_path")
80
+ if not corpus_path:
81
+ raise ValueError("Export corpus first: corpus.export()")
82
+
83
+ dataset = load_dataset("json", data_files=corpus_path, split="train")
84
+
85
+ training_args = TrainingArguments(
86
+ output_dir=output_path,
87
+ num_train_epochs=epochs,
88
+ per_device_train_batch_size=batch_size,
89
+ gradient_accumulation_steps=4,
90
+ learning_rate=lr,
91
+ fp16=True,
92
+ logging_steps=10,
93
+ save_strategy="epoch",
94
+ report_to="none",
95
+ )
96
+
97
+ trainer = SFTTrainer(
98
+ model=model,
99
+ train_dataset=dataset,
100
+ args=training_args,
101
+ tokenizer=tokenizer,
102
+ dataset_text_field="text",
103
+ max_seq_length=2048,
104
+ )
105
+
106
+ print(f" [train] Starting QLoRA β€” {epochs} epochs on {device}")
107
+ trainer.train()
108
+ trainer.save_model(output_path)
109
+ tokenizer.save_pretrained(output_path)
110
+
111
+ # Write model card
112
+ self._write_model_card(output_path)
113
+ print(f"\n [train] βœ“ Complete β€” weights at {output_path}")
114
+ return output_path
115
+
116
+ def _write_model_card(self, output_path: str):
117
+ state = self._state
118
+ card = f"""---
119
+ license: {state.get('license', 'sovereign-source-v1')}
120
+ base_model: {state.get('base_hf')}
121
+ tags:
122
+ - sovereign-ai
123
+ - snapkitty
124
+ - qlora
125
+ - summon
126
+ ---
127
+
128
+ # {state['name']}
129
+
130
+ Built with [Summon](https://github.com/SNAPKITTYWEST/summon) β€” SnapKitty sovereign model framework.
131
+
132
+ ## Model Details
133
+
134
+ - **Base model**: {state.get('base_hf')}
135
+ - **Training**: QLoRA (4-bit quantized fine-tuning)
136
+ - **License**: {state.get('license')}
137
+ - **Constitution**: {state.get('constitution', [])}
138
+ - **Built by**: {state['name']} β€” powered by Summon
139
+
140
+ ## Corpus Layers
141
+
142
+ {chr(10).join(f'- {l}' for l in state.get('corpus_layers', []))}
143
+
144
+ ## WORM Seal
145
+
146
+ `{state['worm_chain'][-1]}`
147
+
148
+ ---
149
+ *Built with Summon β€” SnapKitty Collective β€” Evidence or Silence*
150
+ """
151
+ Path(output_path, "README.md").write_text(card)