Text Generation
Transformers
Safetensors
English
Russian
qwen3_5
image-text-to-text
weight-space-programming
wspforge
math
experimental
conversational
Instructions to use end000/Qwen3.5-0.8B-WSPForge-Math-v1 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use end000/Qwen3.5-0.8B-WSPForge-Math-v1 with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="end000/Qwen3.5-0.8B-WSPForge-Math-v1") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] pipe(text=messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoProcessor, AutoModelForMultimodalLM processor = AutoProcessor.from_pretrained("end000/Qwen3.5-0.8B-WSPForge-Math-v1") model = AutoModelForMultimodalLM.from_pretrained("end000/Qwen3.5-0.8B-WSPForge-Math-v1", device_map="auto") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] inputs = processor.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=256) print(processor.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use end000/Qwen3.5-0.8B-WSPForge-Math-v1 with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "end000/Qwen3.5-0.8B-WSPForge-Math-v1" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "end000/Qwen3.5-0.8B-WSPForge-Math-v1", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/end000/Qwen3.5-0.8B-WSPForge-Math-v1
- SGLang
How to use end000/Qwen3.5-0.8B-WSPForge-Math-v1 with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "end000/Qwen3.5-0.8B-WSPForge-Math-v1" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "end000/Qwen3.5-0.8B-WSPForge-Math-v1", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "end000/Qwen3.5-0.8B-WSPForge-Math-v1" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "end000/Qwen3.5-0.8B-WSPForge-Math-v1", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use end000/Qwen3.5-0.8B-WSPForge-Math-v1 with Docker Model Runner:
docker model run hf.co/end000/Qwen3.5-0.8B-WSPForge-Math-v1
Download wspforge/research_code/src/weights.py from end000/Qwen3.5-0.8B-WSPForge-Math-v1: direct link, hf CLI and curl.
- Browser
- Download file 9.68 kB
-
https://huggingface.co/end000/Qwen3.5-0.8B-WSPForge-Math-v1/resolve/main/wspforge/research_code/src/weights.py
- Command line
-
hf download hf://end000/Qwen3.5-0.8B-WSPForge-Math-v1/wspforge/research_code/src/weights.py
-
curl -L -o weights.py https://huggingface.co/end000/Qwen3.5-0.8B-WSPForge-Math-v1/resolve/main/wspforge/research_code/src/weights.py
9.68 kB
| import argparse | |
| import hashlib | |
| import json | |
| import math | |
| from pathlib import Path | |
| import shutil | |
| import struct | |
| import time | |
| import numpy as np | |
| import torch | |
| from safetensors import safe_open | |
| from safetensors.torch import save_file | |
| from common import ROOT, inside, save_json, append, permit_compute | |
| torch.set_grad_enabled(False) | |
| FROZEN = ('embed_tokens', 'lm_head', 'model.language_model.norm.weight', 'model.norm.weight') | |
| def headers(model): | |
| result = {} | |
| for file in sorted(inside(model).glob('*.safetensors')): | |
| with file.open('rb') as f: | |
| length = struct.unpack('<Q', f.read(8))[0] | |
| head = json.loads(f.read(length)) | |
| for name, info in head.items(): | |
| if name != '__metadata__': | |
| if name in result: | |
| raise ValueError(f'Duplicate tensor: {name}') | |
| result[name] = dict(info, file=str(file)) | |
| return result | |
| def load(model, name): | |
| info = headers(model)[name] | |
| with safe_open(info['file'], framework='pt', device='cpu') as f: | |
| return f.get_tensor(name) | |
| def validate(name, original, value): | |
| if not name.startswith('model.language_model.layers.') or any(x in name for x in FROZEN): | |
| raise ValueError('Разрешены только внутренние слои языковой модели') | |
| if value.shape != original.shape or not torch.isfinite(value).all(): | |
| raise ValueError('Неверная форма или нечисловые значения') | |
| w, v = original.float(), value.float() | |
| if torch.equal(w, v): | |
| raise ValueError('Правка не меняет веса') | |
| ratio = (w * v).sum() / w.square().sum().clamp_min(1e-30) | |
| if (v - ratio * w).norm() <= 1e-6 * v.norm().clamp_min(1e-30): | |
| raise ValueError('Масштабирование всего тензора запрещено') | |
| cast = value.to(original.dtype).contiguous() | |
| if not torch.isfinite(cast).all() or torch.equal(cast, original): | |
| raise ValueError('Правка исчезла или стала нечисловой после приведения dtype') | |
| return cast | |
| def digest(tensor): | |
| return hashlib.sha256(tensor.contiguous().view(torch.uint8).numpy().tobytes()).hexdigest() | |
| def save_edit(model, directory, name, value, hypothesis): | |
| permit_compute() | |
| directory = inside(directory) | |
| if not directory.is_relative_to(ROOT / 'edits'): | |
| raise ValueError('Правки сохраняются только в edits/') | |
| if not hypothesis.strip(): | |
| raise ValueError('Нужна техническая гипотеза') | |
| original = load(model, name) | |
| cast = validate(name, original, value) | |
| directory.mkdir(parents=True, exist_ok=True) | |
| file = directory / (name + '.safetensors') | |
| save_file({name: cast}, str(file)) | |
| record = {'time': time.time(), 'source_model': str(inside(model)), 'tensor': name, 'hypothesis': hypothesis, 'status': 'unconfirmed', | |
| 'changed_entries': int((cast != original).sum()), 'tensor_entries': original.numel(), | |
| 'base_sha256': digest(original), 'edited_sha256': digest(cast), | |
| 'relative_frobenius': float((cast.float()-original.float()).norm()/original.float().norm())} | |
| save_json(directory / (name + '.json'), record) | |
| append(ROOT / 'logs/experiments.jsonl', record) | |
| return record | |
| def project_writers(w, direction, columns, alpha): | |
| w = w.float() | |
| u = torch.as_tensor(direction, dtype=torch.float32) | |
| if not torch.isfinite(u).all() or u.norm() == 0: | |
| raise ValueError('Некорректное направление') | |
| u = u / u.norm() | |
| coeff = u @ w | |
| mask = torch.zeros_like(coeff) | |
| mask[columns] = coeff[columns] | |
| return w - float(alpha) * torch.outer(u, mask) | |
| def lineage(model): | |
| current, ancestors, inherited = inside(model), [], set() | |
| while True: | |
| if str(current) in ancestors: | |
| raise ValueError('Цикл в происхождении модели') | |
| ancestors.append(str(current)) | |
| manifest = current / 'wsp_manifest.json' | |
| if not manifest.exists(): | |
| return current, ancestors, inherited | |
| record = json.loads(manifest.read_text()) | |
| inherited.update(record['tensors']) | |
| current = inside(record['source']) | |
| def weight_fingerprint(model): | |
| result = [] | |
| for path in sorted(inside(model).glob('*.safetensors')): | |
| with path.open('rb') as stream: | |
| result.append([path.name, hashlib.file_digest(stream, 'sha256').hexdigest()]) | |
| return result | |
| def export(model, edits, out): | |
| permit_compute() | |
| model, edits, out = inside(model), inside(edits), inside(out) | |
| if out.exists(): | |
| raise ValueError('Каталог назначения должен быть новым') | |
| if not out.is_relative_to(ROOT / 'models') or out == ROOT / 'models/original': | |
| raise ValueError('Недопустимый каталог модели') | |
| metadata = headers(model) | |
| changes = {} | |
| for file in edits.glob('*.safetensors'): | |
| with safe_open(str(file), framework='pt', device='cpu') as f: | |
| for name in f.keys(): | |
| if name in changes: | |
| raise ValueError('Повторная правка тензора') | |
| base = load(model, name) | |
| changes[name] = validate(name, base, f.get_tensor(name)) | |
| manifest = json.loads((edits / (name + '.json')).read_text()) | |
| if manifest['base_sha256'] != digest(base) or manifest['edited_sha256'] != digest(changes[name]): | |
| raise ValueError('Хеш правки не совпал') | |
| if not changes: | |
| raise ValueError('Нет правок для экспорта') | |
| original, ancestors, inherited = lineage(model) | |
| original_metadata = headers(original) | |
| if metadata.keys() != original_metadata.keys() or any( | |
| metadata[name]['shape'] != original_metadata[name]['shape'] or | |
| metadata[name]['dtype'] != original_metadata[name]['dtype'] for name in metadata): | |
| raise ValueError('Архитектура родителя отличается от исходной модели') | |
| cumulative = {} | |
| for name in sorted(inherited | changes.keys()): | |
| value = changes[name] if name in changes else load(model, name) | |
| cumulative[name] = int((value != load(original, name)).sum()) | |
| parent_fingerprint = weight_fingerprint(model) | |
| original_fingerprint = parent_fingerprint if original == model else weight_fingerprint(original) | |
| staging = out.with_name(out.name + '.building') | |
| if staging.exists(): | |
| raise ValueError('Обнаружен незавершённый экспорт') | |
| staging.mkdir(parents=True) | |
| for file in model.iterdir(): | |
| if file.is_file() and file.suffix != '.safetensors': | |
| shutil.copyfile(file, staging / file.name) | |
| for shard in sorted({x['file'] for x in metadata.values()}): | |
| with safe_open(shard, framework='pt', device='cpu') as f: | |
| tensors = {name: changes[name] if name in changes else f.get_tensor(name) for name in f.keys()} | |
| save_file(tensors, str(staging / Path(shard).name), metadata={'format': 'pt'}) | |
| del tensors | |
| total = sum(math.prod(x['shape']) for x in metadata.values() if x['dtype'].startswith(('BF', 'F'))) | |
| language_total = sum(math.prod(x['shape']) for name, x in metadata.items() | |
| if name.startswith('model.language_model.') and x['dtype'].startswith(('BF', 'F'))) | |
| changed = sum(int((value != load(model, name)).sum()) for name, value in changes.items()) | |
| cumulative_changed = sum(cumulative.values()) | |
| save_json(staging / 'wsp_manifest.json', {'schema_version': 2, | |
| 'source': str(model), 'edits': str(edits), 'tensors': list(changes), | |
| 'changed_entries': changed, 'stored_parameter_entries': total, | |
| 'changed_percent': 100 * changed / total, | |
| 'language_parameter_entries': language_total, | |
| 'changed_percent_language': 100 * changed / language_total, | |
| 'changed_entries_reference': 'immediate_parent', | |
| 'parent_weight_fingerprint': parent_fingerprint, | |
| 'original_source': str(original), 'ancestor_chain_parent_first': ancestors, | |
| 'original_weight_fingerprint': original_fingerprint, | |
| 'changed_entries_vs_original': cumulative_changed, | |
| 'changed_percent_vs_original': 100 * cumulative_changed / total, | |
| 'changed_percent_language_vs_original': 100 * cumulative_changed / language_total, | |
| 'changed_entries_vs_original_by_tensor': cumulative, | |
| 'status': 'unconfirmed'}) | |
| staging.rename(out) | |
| if __name__ == '__main__': | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument('command', choices=['inventory', 'export']) | |
| parser.add_argument('--model', default=str(ROOT / 'models/original')) | |
| parser.add_argument('--edits') | |
| parser.add_argument('--out') | |
| args = parser.parse_args() | |
| if args.command == 'inventory': | |
| save_json(ROOT / 'reports/tensor_inventory.json', headers(args.model)) | |
| else: | |
| export(args.model, args.edits, args.out) | |