Text Generation
Transformers
Safetensors
Mongolian
rdt
traditional-mongolian
recurrent-depth-transformer
mamba
causal-lm
custom-code
custom_code
Instructions to use Montlok/DoL-1.2-Base with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Montlok/DoL-1.2-Base with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="Montlok/DoL-1.2-Base", trust_remote_code=True)# pip install -U transformers accelerate # Load model directly from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("Montlok/DoL-1.2-Base", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use Montlok/DoL-1.2-Base with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "Montlok/DoL-1.2-Base" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Montlok/DoL-1.2-Base", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/Montlok/DoL-1.2-Base
- SGLang
How to use Montlok/DoL-1.2-Base with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "Montlok/DoL-1.2-Base" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Montlok/DoL-1.2-Base", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "Montlok/DoL-1.2-Base" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Montlok/DoL-1.2-Base", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use Montlok/DoL-1.2-Base with Docker Model Runner:
docker model run hf.co/Montlok/DoL-1.2-Base
Download Tokenizer/morphbpe/tokenizer.py from Montlok/DoL-1.2-Base: direct link, hf CLI and curl.
- Browser
- Download file 6.67 kB
-
https://huggingface.co/Montlok/DoL-1.2-Base/resolve/main/Tokenizer/morphbpe/tokenizer.py
- Command line
-
hf download hf://Montlok/DoL-1.2-Base/Tokenizer/morphbpe/tokenizer.py
-
curl -L -o tokenizer.py https://huggingface.co/Montlok/DoL-1.2-Base/resolve/main/Tokenizer/morphbpe/tokenizer.py
6.67 kB
| # -*- coding: utf-8 -*- | |
| """Morphology-constrained BPE tokenizer for traditional Mongolian.""" | |
| from __future__ import annotations | |
| from typing import Any | |
| from Tokenizer.traditional_mongolian.stemmer import MongolStemmer | |
| from Tokenizer.traditional_mongolian.unicode_norm import CTRL_ALL, strip_all_with_map | |
| from . import serialization | |
| from .offsets import MorphToken, Piece, split_on_ascii_space | |
| class MorphBPETokenizer: | |
| def __init__( | |
| self, | |
| vocab: dict[str, int] | None = None, | |
| merges: dict[tuple[str, str], tuple[str, int]] | None = None, | |
| stemmer: MongolStemmer | None = None, | |
| min_boundary_confidence: float = 0.60, | |
| seed_alphabet: bool = False, | |
| ): | |
| self.vocab = vocab or {"<unk>": 0} | |
| self.merges = merges or {} | |
| self.stemmer = stemmer | |
| self.min_boundary_confidence = min_boundary_confidence | |
| self.seed_alphabet = seed_alphabet | |
| self._id_to_token = {i: tok for tok, i in self.vocab.items()} | |
| # MVS/FVS preservation is gated on the vocab: vocabularies that carry | |
| # the control characters as tokens (v3+ builds) keep them in the id | |
| # stream; older vocabularies fold them exactly as before, so v2 | |
| # bundles stay bit-identical. | |
| self._preserve_controls = all(ch in self.vocab for ch in CTRL_ALL) | |
| # ---- io ---- | |
| def from_file( | |
| cls, path: str, stemmer: MongolStemmer | None = None | |
| ) -> "MorphBPETokenizer": | |
| payload = serialization.load(path) | |
| merges = serialization.merges_from_payload(payload) | |
| return cls( | |
| vocab={str(k): int(v) for k, v in payload.get("vocab", {}).items()}, | |
| merges=merges, | |
| stemmer=stemmer, | |
| min_boundary_confidence=float( | |
| payload.get("config", {}).get("min_boundary_confidence", 0.60) | |
| ), | |
| seed_alphabet=bool(payload.get("config", {}).get("seed_alphabet", False)), | |
| ) | |
| def save(self, path: str, extra_config: dict[str, Any] | None = None) -> None: | |
| serialization.dump(self, path, extra_config=extra_config) | |
| # ---- encode ---- | |
| def encode(self, text: str) -> list[int]: | |
| return [tok.id for tok in self.encode_with_offsets(text)] | |
| def encode_with_offsets(self, text: str, base_start: int = 0) -> list[MorphToken]: | |
| tokens: list[MorphToken] = [] | |
| for start, end in split_on_ascii_space(text): | |
| for tok in self.tokenize_word(text[start:end], base_start + start): | |
| tokens.append(tok) | |
| return tokens | |
| def tokenize_word(self, word: str, base_start: int = 0) -> list[MorphToken]: | |
| if not self._preserve_controls: | |
| return self._tokenize_clean_word(word, base_start) | |
| # Controls are hard segmentation boundaries: each control character | |
| # becomes its own token at its original position and BPE runs on the | |
| # control-free segments between them. MVS only ever marks the | |
| # stem/separated-suffix junction, so splitting there is exactly the | |
| # morpheme boundary MorphBPE wants anyway; FVS/NIRUGU are rare (2.4‰) | |
| # word-internal marks where the fertility cost is negligible. Within | |
| # a clean segment skeleton offsets equal original offsets, which also | |
| # sidesteps the skeleton-vs-original coordinate drift the legacy path | |
| # has for multi-boundary words with embedded controls. | |
| tokens: list[MorphToken] = [] | |
| seg_start = 0 | |
| for i, ch in enumerate(word): | |
| if ch not in CTRL_ALL: | |
| continue | |
| if i > seg_start: | |
| tokens.extend( | |
| self._tokenize_clean_word(word[seg_start:i], base_start + seg_start) | |
| ) | |
| tokens.append( | |
| MorphToken(ch, self.vocab[ch], base_start + i, base_start + i + 1) | |
| ) | |
| seg_start = i + 1 | |
| if seg_start < len(word): | |
| tokens.extend( | |
| self._tokenize_clean_word(word[seg_start:], base_start + seg_start) | |
| ) | |
| return tokens | |
| def _tokenize_clean_word(self, word: str, base_start: int = 0) -> list[MorphToken]: | |
| skeleton, boundary_map = strip_all_with_map(word) | |
| if not skeleton: | |
| return [] | |
| analysis = self.stemmer.analyze(word) if self.stemmer else None | |
| forbidden: set[int] = set() | |
| if analysis is not None and analysis.confidence >= self.min_boundary_confidence: | |
| forbidden = set(analysis.skeleton_boundaries[1:-1]) | |
| pieces = [ | |
| Piece(ch, boundary_map[i], boundary_map[i + 1]) | |
| for i, ch in enumerate(skeleton) | |
| ] | |
| pieces = self._apply_merges(pieces, forbidden) | |
| return [ | |
| MorphToken( | |
| p.text, | |
| self._piece_id(p.text), | |
| base_start + p.start, | |
| base_start + p.end, | |
| ) | |
| for p in pieces | |
| ] | |
| def _apply_merges(self, pieces: list[Piece], forbidden: set[int]) -> list[Piece]: | |
| if not self.merges: | |
| return pieces | |
| changed = True | |
| while changed: | |
| changed = False | |
| best_index: int | None = None | |
| best_rank: int | None = None | |
| best_text = "" | |
| for i in range(len(pieces) - 1): | |
| if pieces[i].end in forbidden: | |
| continue | |
| merge = self.merges.get((pieces[i].text, pieces[i + 1].text)) | |
| if merge is None: | |
| continue | |
| merged, rank = merge | |
| if best_rank is None or rank < best_rank: | |
| best_index = i | |
| best_rank = rank | |
| best_text = merged | |
| if best_index is not None: | |
| left = pieces[best_index] | |
| right = pieces[best_index + 1] | |
| pieces[best_index : best_index + 2] = [ | |
| Piece(best_text, left.start, right.end) | |
| ] | |
| changed = True | |
| return pieces | |
| def _piece_id(self, piece: str) -> int: | |
| if piece in self.vocab: | |
| return self.vocab[piece] | |
| return self.vocab.get("<unk>", 0) | |
| # ---- decode ---- | |
| def decode(self, ids: list[int]) -> str: | |
| if not self._id_to_token: | |
| self._id_to_token = {i: tok for tok, i in self.vocab.items()} | |
| out: list[str] = [] | |
| for i in ids: | |
| tok = self._id_to_token.get(i, "") | |
| if tok == "<unk>": | |
| out.append("\ufffd") | |
| continue | |
| out.append(tok) | |
| return "".join(out) | |