Spaces:
Paused
Paused
Download local_model.py from twindinx/cs553-test: direct link, hf CLI and curl.
- Browser
- Download file 4.16 kB
-
https://huggingface.co/spaces/twindinx/cs553-test/resolve/main/local_model.py
- Command line
-
hf download hf://spaces/twindinx/cs553-test/local_model.py
-
curl -L -o local_model.py https://huggingface.co/spaces/twindinx/cs553-test/resolve/main/local_model.py
4.16 kB
| import logging | |
| import os | |
| import spaces | |
| import torch | |
| import torchvision.transforms as T | |
| from PIL import Image | |
| from torchvision.transforms.functional import InterpolationMode | |
| from transformers import AutoTokenizer | |
| from transformers.dynamic_module_utils import get_class_from_dynamic_module | |
| from config import ARTIMUSE_SCORE_QUESTION,LOCAL_MODEL, advice_question, LOCAL_MAX_TOKENS | |
| from critique import Critique | |
| logger = logging.getLogger(__name__) | |
| IMAGENET_MEAN = (0.485, 0.456, 0.406) | |
| IMAGENET_STD = (0.229, 0.224, 0.225) | |
| INPUT_SIZE = 448 | |
| # First letter selects the block of 25, second letter is the offset within it. | |
| _TOKEN_BASE = {"a": 0, "c": 26, "d": 51, "e": 76} | |
| _model = None | |
| _tokenizer = None | |
| def aestoken2score(token: str) -> int | None: | |
| # decode ArtiMuse's two-letter score code, e.g. 'dc' -> 53 | |
| # return None if receiving unexpected output | |
| token = token.strip().lower() | |
| if len(token) < 2: | |
| return None | |
| first, second = token[0], token[1] | |
| if first not in _TOKEN_BASE or not ("a" <= second <= "z"): | |
| return None | |
| score = _TOKEN_BASE[first] + (ord(second) - ord("a")) | |
| return score if 0 <= score <= 100 else None | |
| def load_image(image_path: str) -> torch.Tensor: | |
| # ArtiMuse was trained on 448px tiles, so we resize to that size | |
| transform = T.Compose( | |
| [ | |
| T.Lambda(lambda img: img.convert("RGB") if img.mode != "RGB" else img), | |
| T.Resize((INPUT_SIZE, INPUT_SIZE), interpolation=InterpolationMode.BICUBIC), | |
| T.ToTensor(), | |
| T.Normalize(mean=IMAGENET_MEAN, std=IMAGENET_STD), | |
| ] | |
| ) | |
| with Image.open(image_path) as image: | |
| return transform(image).unsqueeze(0) | |
| def _device_and_dtype(): | |
| if torch.cuda.is_available(): | |
| return "cuda", torch.bfloat16 | |
| if torch.backends.mps.is_available(): | |
| return "mps", torch.bfloat16 | |
| return "cpu", torch.float32 | |
| def _artimuse_class(): | |
| # Fetch ArtiMuse's bundled model class, patched for transformers 5.x | |
| cls = get_class_from_dynamic_module( | |
| "modeling_internvl_chat.InternVLChatModel", LOCAL_MODEL | |
| ) | |
| if not hasattr(cls, "all_tied_weights_keys"): | |
| cls.all_tied_weights_keys = {} | |
| return cls | |
| def _ensure_loaded(): | |
| # Load the 15.9GB checkpoint once at import | |
| global _model, _tokenizer | |
| if _model is not None: | |
| return _model, _tokenizer | |
| device, dtype = _device_and_dtype() | |
| logger.info("Loading %s on %s (%s)", LOCAL_MODEL, device, dtype) | |
| _model = ( | |
| _artimuse_class() | |
| .from_pretrained( | |
| LOCAL_MODEL, | |
| dtype=dtype, | |
| low_cpu_mem_usage=True, | |
| trust_remote_code=True, | |
| use_flash_attn=False, | |
| ) | |
| .eval() | |
| .to(device) | |
| ) | |
| _tokenizer = AutoTokenizer.from_pretrained( | |
| LOCAL_MODEL, trust_remote_code=True, use_fast=False | |
| ) | |
| return _model, _tokenizer | |
| def local_critique(image_path, aspect, temperature, top_p) -> Critique: | |
| model, tokenizer = _ensure_loaded() | |
| device, dtype = _device_and_dtype() | |
| pixel_values = load_image(image_path).to(dtype).to(device) | |
| # Scoring is a single forward pass: we only need the first generated token. | |
| score_config = dict(max_new_tokens=4, do_sample=False, pad_token_id=tokenizer.eos_token_id) | |
| raw_score = model.chat(tokenizer, pixel_values, ARTIMUSE_SCORE_QUESTION, score_config) | |
| score = aestoken2score(str(raw_score)) | |
| if score is None: | |
| raise RuntimeError(f"ArtiMuse returned an unparseable score token: {raw_score!r}") | |
| text_config = dict( | |
| max_new_tokens=LOCAL_MAX_TOKENS, | |
| do_sample=temperature > 0, | |
| temperature=max(float(temperature), 0.01), | |
| top_p=float(top_p), | |
| pad_token_id=tokenizer.eos_token_id, | |
| ) | |
| evaluation = model.chat(tokenizer, pixel_values, advice_question(aspect), text_config) | |
| return Critique( | |
| score=score, | |
| evaluation=str(evaluation), | |
| model_name=LOCAL_MODEL, | |
| route="Local", | |
| ) | |
| # Ensure the model is loaded at boot time of Space, not on first request | |
| if os.environ.get("SPACE_ID"): | |
| _ensure_loaded() | |