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
File size: 6,886 Bytes
f0304c9 f202293 f0304c9 f202293 f0304c9 bc2527c f0304c9 f202293 f0304c9 bc2527c f202293 f0304c9 f202293 f0304c9 f202293 bc2527c f202293 f0304c9 f202293 bc2527c f202293 f0304c9 bc2527c f202293 f0304c9 f202293 f0304c9 f202293 f0304c9 f202293 f0304c9 f202293 f0304c9 f202293 f0304c9 f202293 bc2527c f202293 f0304c9 f202293 f0304c9 f202293 bc2527c f202293 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | # 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()
|