Image-to-Text
Transformers
Safetensors
molparser_vision_encoder_decoder
image-text-to-text
chemistry
custom_code
Instructions to use UniParser/MolParser-Mobile with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use UniParser/MolParser-Mobile with Transformers:
# Use a pipeline as a high-level helper # Warning: Pipeline type "image-to-text" is no longer supported in transformers v5. # You must load the model directly (see below) or downgrade to v4.x with: # 'pip install "transformers<5.0.0' from transformers import pipeline pipe = pipeline("image-to-text", model="UniParser/MolParser-Mobile", trust_remote_code=True)# Load model directly from transformers import AutoModelForImageTextToText model = AutoModelForImageTextToText.from_pretrained("UniParser/MolParser-Mobile", trust_remote_code=True, dtype="auto") - Notebooks
- Google Colab
- Kaggle
| """MolParser Mobile tokenizer for Hugging Face Hub remote loading.""" | |
| from __future__ import annotations | |
| import json | |
| import os | |
| import re | |
| from pathlib import Path | |
| from typing import Dict, Iterable, List, Optional, Sequence, Union | |
| from huggingface_hub import hf_hub_download | |
| from transformers import PreTrainedTokenizer | |
| TOKENIZER_CONFIG_NAME = "tokenizer_config.json" | |
| VOCAB_NAME = "vocab.txt" | |
| class MolParserTokenizer(PreTrainedTokenizer): | |
| model_input_names = ["input_ids", "attention_mask"] | |
| padding_side = "right" | |
| def __init__( | |
| self, | |
| vocab_list: Optional[List[str]] = None, | |
| special_tokens: Optional[Dict[str, str]] = None, | |
| additional_special_tokens: Optional[Sequence[str]] = None, | |
| **kwargs, | |
| ): | |
| if vocab_list is None: | |
| vocab_list = [] | |
| if special_tokens is None: | |
| special_tokens = {} | |
| if additional_special_tokens is None: | |
| additional_special_tokens = [] | |
| self.special_tokens = { | |
| "cls_token": special_tokens.get("cls_token", "[CLS]"), | |
| "pad_token": special_tokens.get("pad_token", "[PAD]"), | |
| "sep_token": special_tokens.get("sep_token", "[SEP]"), | |
| "unk_token": special_tokens.get("unk_token", "[UNK]"), | |
| } | |
| self.additional_special_tokens = list(dict.fromkeys(additional_special_tokens)) | |
| self.vocab_list = list(vocab_list) | |
| all_tokens = self._build_full_vocab(self.vocab_list) | |
| self.vocab = {token: idx for idx, token in enumerate(all_tokens)} | |
| self.ids_to_tokens = {idx: token for token, idx in self.vocab.items()} | |
| self._decode_skip_tokens = set(self.special_tokens.values()) | |
| self._compile_pattern() | |
| super().__init__( | |
| cls_token=self.special_tokens["cls_token"], | |
| pad_token=self.special_tokens["pad_token"], | |
| sep_token=self.special_tokens["sep_token"], | |
| unk_token=self.special_tokens["unk_token"], | |
| bos_token=self.special_tokens["cls_token"], | |
| eos_token=self.special_tokens["sep_token"], | |
| additional_special_tokens=self.additional_special_tokens, | |
| **kwargs, | |
| ) | |
| def _build_full_vocab(self, vocab_list: Sequence[str]) -> List[str]: | |
| ordered_tokens: List[str] = [] | |
| for token in list(self.special_tokens.values()) + list(vocab_list) + list(self.additional_special_tokens): | |
| if token not in ordered_tokens: | |
| ordered_tokens.append(token) | |
| return ordered_tokens | |
| def _compile_pattern(self) -> None: | |
| multi_char_tokens = sorted(self.vocab.keys(), key=len, reverse=True) | |
| pattern = "(" + "|".join(re.escape(token) for token in multi_char_tokens) + "|.)" | |
| self.pattern = re.compile(pattern) | |
| def vocab_size(self) -> int: | |
| return len(self.vocab) | |
| def __len__(self) -> int: | |
| return len(self.vocab) | |
| def get_vocab(self) -> Dict[str, int]: | |
| return dict(self.vocab) | |
| def _tokenize(self, text: str) -> List[str]: | |
| return [token for token in self.pattern.findall(str(text)) if token] | |
| def tokenize(self, text: str, **kwargs) -> List[str]: | |
| return self._tokenize(text) | |
| def _convert_token_to_id(self, token: str) -> int: | |
| return self.vocab.get(token, self.unk_token_id) | |
| def _convert_id_to_token(self, index: int) -> str: | |
| return self.ids_to_tokens.get(int(index), self.unk_token) | |
| def convert_tokens_to_string(self, tokens: Sequence[str]) -> str: | |
| return "".join(tokens) | |
| def build_inputs_with_special_tokens(self, token_ids_0, token_ids_1=None): | |
| if token_ids_1 is None: | |
| return list(token_ids_0) | |
| return list(token_ids_0) + list(token_ids_1) | |
| def encode(self, text: str, add_special_tokens: bool = False, **kwargs) -> List[int]: | |
| token_ids = [self._convert_token_to_id(token) for token in self._tokenize(text)] | |
| if add_special_tokens: | |
| return [self.bos_token_id] + token_ids + [self.eos_token_id] | |
| return token_ids | |
| def decode(self, token_ids: Iterable[int], skip_special_tokens: bool = False, **kwargs) -> str: | |
| tokens = [self._convert_id_to_token(idx) for idx in token_ids] | |
| if skip_special_tokens: | |
| # Match deploy/tokenizer.py: keep MolParser business tokens such as | |
| # <sep>, <a>, </a>, <r>, </r>, <c>, </c>, and |Sg:n|. | |
| tokens = [token for token in tokens if token not in self._decode_skip_tokens] | |
| return "".join(tokens) | |
| def batch_encode(self, texts: Sequence[str], add_special_tokens: bool = False) -> List[List[int]]: | |
| return [self.encode(text, add_special_tokens=add_special_tokens) for text in texts] | |
| def batch_decode( | |
| self, | |
| sequences: Sequence[Sequence[int]], | |
| skip_special_tokens: bool = False, | |
| **kwargs, | |
| ) -> List[str]: | |
| return [self.decode(ids, skip_special_tokens=skip_special_tokens, **kwargs) for ids in sequences] | |
| def to_dict(self) -> Dict[str, object]: | |
| return { | |
| "vocab_list": self.vocab_list, | |
| "special_tokens": self.special_tokens, | |
| "additional_special_tokens": self.additional_special_tokens, | |
| "tokenizer_class": self.__class__.__name__, | |
| "auto_map": { | |
| "AutoTokenizer": [ | |
| "tokenization_molparser_mobile.MolParserTokenizer", | |
| None, | |
| ] | |
| }, | |
| } | |
| def from_dict(cls, config: Dict[str, object]) -> "MolParserTokenizer": | |
| return cls( | |
| vocab_list=list(config["vocab_list"]), | |
| special_tokens=dict(config["special_tokens"]), | |
| additional_special_tokens=list(config.get("additional_special_tokens", [])), | |
| ) | |
| def save_vocabulary(self, save_directory: str, filename_prefix: Optional[str] = None): | |
| path = Path(save_directory) | |
| path.mkdir(parents=True, exist_ok=True) | |
| name = f"{filename_prefix}-{VOCAB_NAME}" if filename_prefix else VOCAB_NAME | |
| vocab_path = path / name | |
| vocab_path.write_text("\n".join(self.vocab_list) + "\n", encoding="utf-8") | |
| return (str(vocab_path),) | |
| def save_pretrained(self, save_directory: str, **kwargs): | |
| os.makedirs(save_directory, exist_ok=True) | |
| config_path = os.path.join(save_directory, TOKENIZER_CONFIG_NAME) | |
| with open(config_path, "w", encoding="utf-8") as f: | |
| json.dump(self.to_dict(), f, ensure_ascii=False, indent=2) | |
| vocab_files = self.save_vocabulary(save_directory) | |
| return (config_path, *vocab_files) | |
| def from_pretrained(cls, pretrained_model_name_or_path: str, *args, **kwargs) -> "MolParserTokenizer": | |
| config_path = Path(pretrained_model_name_or_path) | |
| if config_path.is_dir(): | |
| config_path = config_path / TOKENIZER_CONFIG_NAME | |
| elif config_path.is_file(): | |
| pass | |
| else: | |
| config_path = Path( | |
| hf_hub_download( | |
| repo_id=str(pretrained_model_name_or_path), | |
| filename=TOKENIZER_CONFIG_NAME, | |
| repo_type=kwargs.get("repo_type"), | |
| revision=kwargs.get("revision"), | |
| cache_dir=kwargs.get("cache_dir"), | |
| token=kwargs.get("token"), | |
| local_files_only=kwargs.get("local_files_only", False), | |
| ) | |
| ) | |
| with open(config_path, "r", encoding="utf-8") as f: | |
| config = json.load(f) | |
| return cls.from_dict(config) | |
| __all__ = ["MolParserTokenizer"] | |