Text Classification
Transformers
Safetensors
English
decision-model
decision-index
system-one
gemma4
qwen3_5
Instructions to use Poindexter-Labs/Copernicus-57B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Poindexter-Labs/Copernicus-57B with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="Poindexter-Labs/Copernicus-57B")# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("Poindexter-Labs/Copernicus-57B", device_map="auto") - Notebooks
- Google Colab
- Kaggle
Download engine/copernicus_engine.py from Poindexter-Labs/Copernicus-57B: direct link, hf CLI and curl.
- Browser
- Download file 6.89 kB
-
https://huggingface.co/Poindexter-Labs/Copernicus-57B/resolve/main/engine/copernicus_engine.py
- Command line
-
hf download hf://Poindexter-Labs/Copernicus-57B/engine/copernicus_engine.py
-
curl -L -o copernicus_engine.py https://huggingface.co/Poindexter-Labs/Copernicus-57B/resolve/main/engine/copernicus_engine.py
6.89 kB
| # SPDX-License-Identifier: MIT | |
| """Single-process Copernicus variant of the REAX 1.3 engine contract.""" | |
| import gc | |
| import json | |
| import os | |
| import threading | |
| import time | |
| from pathlib import Path | |
| from concurrent.futures import ThreadPoolExecutor | |
| from copernicus_workers import InputLimitError, load_gemma, load_qwen | |
| from probabilities import mix | |
| try: | |
| from decision_index.engines import Engine, Unsupported | |
| except ImportError: | |
| class Engine: | |
| def __init__(self, **options): pass | |
| class Unsupported(ValueError): pass | |
| class CopernicusEngine(Engine): | |
| name = 'copernicus-57b' | |
| latency = 'One request at a time; Gemma and Qwen run concurrently on CUDA streams; Qwen batches equal-length questions; includes in-process work and excludes startup and warmup.' | |
| def __init__(self, config=None, model=None, **options): | |
| super().__init__(**options) | |
| self.config = json.loads(Path(config or Path(__file__).with_name('copernicus57.json')).read_text()) | |
| self.config.update(options) | |
| root = Path(model or self.config['model_root']).resolve() | |
| paths = [root/'part-g', root/'part-q'] | |
| if any(not p.is_dir() for p in paths):raise FileNotFoundError('Model root must contain part-g and part-q') | |
| precision = self.config.get('precision', 'fp8') | |
| devices = self.config.get('devices', ['cuda:0','cuda:0']) | |
| if precision not in ('fp8','bf16') or len(devices) != 2:raise ValueError('Invalid precision or devices') | |
| import torch | |
| import transformers | |
| torch.set_num_threads(4) | |
| if precision == 'fp8': | |
| import fast_fp8_gemm | |
| from autotune_guard import install as install_autotune_guard | |
| install_autotune_guard() | |
| fast_fp8_gemm.install() | |
| self.lock = threading.Lock() | |
| self._alive = False | |
| self.gemma = self.qwen = None | |
| try: | |
| self.gemma = load_gemma(str(paths[0]), devices[0], precision) | |
| self.qwen = load_qwen(str(paths[1]), devices[1], precision, | |
| batch_size=int(self.config.get('qwen_batch_size', 8)), | |
| batch_tokens=int(self.config.get('qwen_batch_tokens', 4096))) | |
| self.pool = ThreadPoolExecutor(max_workers=2, thread_name_prefix='copernicus') | |
| self.streams = [torch.cuda.Stream(device=d) for d in devices] | |
| for stream in self.streams: | |
| stream.wait_stream(torch.cuda.current_stream(device=stream.device)) | |
| self._alive = True | |
| except BaseException: | |
| self.close() | |
| raise | |
| self.provenance = {'model':str(root), 'model_repo':'Poindexter-Labs/Copernicus-57B', 'model_revision':'28a57bbc72a752a60acc8c4af7c9071b76d71e35', 'engine_repo':'https://github.com/poindexter-stk/copernicus-engine', 'engine_commit':os.environ.get('COPERNICUS_ENGINE_COMMIT','unspecified'), 'qwen_reader_revision':'0c1efcc7abad11c56eefc866334aab4b01ec38ec', 'precision':precision, 'devices':devices, 'mix':'0.5 Gemma + 0.5 Qwen probabilities', 'execution':'one request at a time; Gemma and Qwen concurrent CUDA streams; Qwen equal-length question batching', 'qwen_question_batch_size':int(self.config.get('qwen_batch_size', 8)), 'qwen_batch_tokens':int(self.config.get('qwen_batch_tokens', 4096)), 'gemma_question_workers':1, 'concurrent_proxy_limit':int(self.config.get('concurrent_proxy_limit', 16000)), 'max_input_proxy_tokens':int(self.config['max_input_proxy_tokens']), 'max_rendered_tokens_per_model':32768} | |
| self.ready = {'mode':'copernicus-57b', 'precision':precision, 'devices':devices, 'gpu':torch.cuda.get_device_name(devices[0]), 'torch':torch.__version__, 'transformers':transformers.__version__, 'allocated_bytes':torch.cuda.memory_allocated(devices[0]), 'reserved_bytes':torch.cuda.memory_reserved(devices[0])} | |
| def alive(self):return self._alive | |
| def __call__(self, state, questions): | |
| if not questions or len(questions)>64:raise Unsupported('Supports 1..64 questions') | |
| for q in questions.values(): | |
| typ=q.get('type');criteria=q.get('criteria') | |
| if typ == 'choice' and (not isinstance(criteria,dict) or not 2<=len(criteria)<=255):raise Unsupported('choice requires 2..255 options') | |
| if typ == 'score' and (not isinstance(criteria,list) or not 2<=len(criteria)<=10):raise Unsupported('score requires 2..10 options') | |
| if typ not in ('choice','score','noul'):raise Unsupported('Unsupported question type') | |
| size=len(json.dumps({'model':'jev-1.13.0','state':state,'questions':questions},ensure_ascii=False,separators=(',',':'))) // 4 | |
| if size > int(self.config['max_input_proxy_tokens']):raise Unsupported('Input exceeds proxy token limit') | |
| with self.lock: | |
| if not self.alive():raise RuntimeError('Engine is closed') | |
| request={'state':state,'questions':questions};start=time.monotonic() | |
| try: | |
| import torch | |
| def invoke(fn, stream): | |
| with torch.cuda.stream(stream): | |
| return fn(state, questions) | |
| if size > int(self.config.get('concurrent_proxy_limit', 16000)): | |
| # Long requests run the same model paths serially to bound activation memory. | |
| results=[invoke(self.gemma, self.streams[0]), invoke(self.qwen, self.streams[1])] | |
| errors=[] | |
| else: | |
| futures=[self.pool.submit(invoke, self.gemma, self.streams[0]), | |
| self.pool.submit(invoke, self.qwen, self.streams[1])] | |
| results=[]; errors=[] | |
| for future in futures: | |
| try: results.append(future.result()); errors.append(None) | |
| except BaseException as exc: results.append(None); errors.append(exc) | |
| for device in set(self.config.get('devices', ['cuda:0', 'cuda:0'])): | |
| torch.cuda.synchronize(device) | |
| if any(errors): raise next(e for e in errors if e is not None) | |
| gemma,qwen=results | |
| except InputLimitError as exc: | |
| raise Unsupported(str(exc)) from exc | |
| result=mix(request,gemma,qwen);result['model']='copernicus-57b' | |
| return result, {'elapsed_ms':1000*(time.monotonic()-start),'precision':self.config.get('precision','fp8'),'devices':self.config.get('devices',['cuda:0','cuda:0'])} | |
| def warmup(self): | |
| self('', {'warmup':{'type':'choice','instructions':'Choose one.', 'criteria':{'a':'A','b':'B'}}}) | |
| def runtime(self):return self.ready | |
| def close(self): | |
| self._alive=False | |
| pool=getattr(self,'pool',None) | |
| if pool is not None: | |
| pool.shutdown(wait=True) | |
| self.pool=None | |
| self.gemma=self.qwen=None | |
| gc.collect() | |