Text Classification
Transformers
Safetensors
Russian
English
qwen3_5_text
text-generation
typed-decisions
system-one
russian
routing
agents
decider
Instructions to use smolnikov/migom-2b with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use smolnikov/migom-2b with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="smolnikov/migom-2b")# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("smolnikov/migom-2b") model = AutoModelForCausalLM.from_pretrained("smolnikov/migom-2b", device_map="auto") - Notebooks
- Google Colab
- Kaggle
Download server/decide_server.py from smolnikov/migom-2b: direct link, hf CLI and curl.
- Browser
- Download file 4.89 kB
-
https://huggingface.co/smolnikov/migom-2b/resolve/main/server/decide_server.py
- Command line
-
hf download hf://smolnikov/migom-2b/server/decide_server.py
-
curl -L -o decide_server.py https://huggingface.co/smolnikov/migom-2b/resolve/main/server/decide_server.py
4.89 kB
| """Open typed-decision server with a Jev-compatible API. | |
| POST /v1/systemone {"state": ..., "questions": {id: {"type": "choice|score|noul", "instructions": ..., "criteria": ...}}, | |
| "model": "kivok" | "migom" | "auto"} | |
| -> {"model": ..., "answers": {id: {...TypeSafe answer shape...}}, "usage": {...}} | |
| GET /v1/models | |
| Models: | |
| kivok - small (0.3B) and fast, runs on CPU; | |
| migom - larger (2B), better at reasoning; GPU recommended; | |
| auto - cascade: Kivok answers, questions where its top probability is below AUTO_THRESHOLD go to Migom. | |
| Env: KIVOK_PATH, MIGOM_PATH (either may be empty), DEVICE (cpu|cuda|xpu), DTYPE (fp16|bf16|fp32; use fp16 on Intel XPU), | |
| GRAPHS (0 disables graphs), AUTO_THRESHOLD (default 0.8), | |
| API_KEY (if set, require "Authorization: Bearer <key>"), HOST (default 127.0.0.1), PORT (default 8010). | |
| """ | |
| import hmac, os, threading, time | |
| from typing import Any, Dict, Optional | |
| from fastapi import FastAPI, HTTPException, Request | |
| from fastapi.responses import JSONResponse | |
| from pydantic import BaseModel | |
| KIVOK_PATH = os.environ.get('KIVOK_PATH', '') | |
| MIGOM_PATH = os.environ.get('MIGOM_PATH', '') | |
| DEVICE = os.environ.get('DEVICE') or None | |
| THRESHOLD = float(os.environ.get('AUTO_THRESHOLD', '0.8')) | |
| API_KEY = os.environ.get('API_KEY', '') | |
| DTYPE = os.environ.get('DTYPE', '') # fp16 on Intel XPU: bf16 gives wrong answers there | |
| GRAPHS = os.environ.get('GRAPHS', '') # '0' disables CUDA/XPU graphs | |
| app = FastAPI(title='typed-decision server', version='0.1') | |
| _lock = threading.Lock() | |
| _models: Dict[str, Any] = {} | |
| def kivok(): | |
| if 'kivok' not in _models: | |
| if not KIVOK_PATH: | |
| raise HTTPException(503, 'kivok is not configured (KIVOK_PATH)') | |
| import laya | |
| _models['kivok'] = laya.load(KIVOK_PATH, device=DEVICE) if DEVICE else laya.load(KIVOK_PATH) | |
| return _models['kivok'] | |
| def migom(): | |
| if 'migom' not in _models: | |
| if not MIGOM_PATH: | |
| raise HTTPException(503, 'migom is not configured (MIGOM_PATH)') | |
| from decider.infer import Decider | |
| import torch | |
| dt = {'fp16': torch.float16, 'bf16': torch.bfloat16, 'fp32': torch.float32}.get(DTYPE) | |
| _models['migom'] = Decider(MIGOM_PATH, device=DEVICE, dtype=dt, use_graphs=False if GRAPHS == '0' else None) | |
| return _models['migom'] | |
| def top_prob(ans: dict) -> float: | |
| if 'probabilities' in ans and ans['probabilities']: | |
| return max(ans['probabilities'].values()) | |
| if 'noul' in ans: | |
| p = float(ans['noul']); return max(p, 1 - p) | |
| return 1.0 | |
| def ask_kivok(state, questions): | |
| return kivok().predict(state, questions) | |
| def ask_migom(state, questions): | |
| return migom().system_one(state, questions) | |
| class Request_(BaseModel): | |
| state: Any | |
| questions: Dict[str, Dict[str, Any]] | |
| model: Optional[str] = 'auto' | |
| async def auth(request: Request, call_next): | |
| if API_KEY and request.url.path.startswith('/v1') and not hmac.compare_digest( | |
| request.headers.get('authorization', ''), f'Bearer {API_KEY}'): | |
| return JSONResponse({'detail': 'missing or invalid API key'}, 401) | |
| return await call_next(request) | |
| def models(): | |
| return {'data': [{'id': m, 'configured': bool(p)} for m, p in | |
| (('kivok', KIVOK_PATH), ('migom', MIGOM_PATH), ('auto', KIVOK_PATH or MIGOM_PATH))]} | |
| def systemone(req: Request_): | |
| if not req.questions: | |
| raise HTTPException(422, 'questions must not be empty') | |
| name = (req.model or 'auto').lower() | |
| t0 = time.time() | |
| with _lock: | |
| try: | |
| if name == 'kivok' or (name == 'auto' and not MIGOM_PATH): | |
| out = ask_kivok(req.state, req.questions); used = {k: 'kivok' for k in req.questions} | |
| elif name == 'migom' or (name == 'auto' and not KIVOK_PATH): | |
| out = ask_migom(req.state, req.questions); used = {k: 'migom' for k in req.questions} | |
| elif name == 'auto': | |
| out = ask_kivok(req.state, req.questions) | |
| used = {k: 'kivok' for k in req.questions} | |
| hard = {k: q for k, q in req.questions.items() if top_prob(out['answers'][k]) < THRESHOLD} | |
| if hard: | |
| second = ask_migom(req.state, hard) | |
| for k in hard: | |
| out['answers'][k] = second['answers'][k]; used[k] = 'migom' | |
| else: | |
| raise HTTPException(404, f'unknown model {name!r}') | |
| except ValueError as e: | |
| raise HTTPException(422, str(e)) | |
| return {'model': name, 'answers': out['answers'], 'routed': used, | |
| 'usage': {'latency_ms': round(1000 * (time.time() - t0), 1)}} | |
| if __name__ == '__main__': | |
| import uvicorn | |
| uvicorn.run(app, host=os.environ.get('HOST', '127.0.0.1'), port=int(os.environ.get('PORT', '8010'))) | |