Text Generation
Transformers
Safetensors
mistral3
image-text-to-text
decision-model
typed-decisions
jev
jevbench
calibration
decode-free
multilingual
vision-language
conversational
Instructions to use StandardThinking/StandardOne-3B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use StandardThinking/StandardOne-3B with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="StandardThinking/StandardOne-3B") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] pipe(text=messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoProcessor, AutoModelForMultimodalLM processor = AutoProcessor.from_pretrained("StandardThinking/StandardOne-3B") model = AutoModelForMultimodalLM.from_pretrained("StandardThinking/StandardOne-3B", device_map="auto") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] inputs = processor.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=256) print(processor.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use StandardThinking/StandardOne-3B with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "StandardThinking/StandardOne-3B" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "StandardThinking/StandardOne-3B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/StandardThinking/StandardOne-3B
- SGLang
How to use StandardThinking/StandardOne-3B 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 "StandardThinking/StandardOne-3B" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "StandardThinking/StandardOne-3B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'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 "StandardThinking/StandardOne-3B" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "StandardThinking/StandardOne-3B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use StandardThinking/StandardOne-3B with Docker Model Runner:
docker model run hf.co/StandardThinking/StandardOne-3B
Download server/tests/test_labels.py from StandardThinking/StandardOne-3B: direct link, hf CLI and curl.
- Browser
- Download file 16.2 kB
-
https://huggingface.co/StandardThinking/StandardOne-3B/resolve/main/server/tests/test_labels.py
- Command line
-
hf download hf://StandardThinking/StandardOne-3B/server/tests/test_labels.py
-
curl -L -o test_labels.py https://huggingface.co/StandardThinking/StandardOne-3B/resolve/main/server/tests/test_labels.py
16.2 kB
| """Answer-label schemes: exact lists, the <=26 guarantee, and end-to-end mapping.""" | |
| import hashlib | |
| import json | |
| import re | |
| import string | |
| from pathlib import Path | |
| import httpx | |
| import pytest | |
| from jev_adapter.labels import ( | |
| DEFAULT_LABEL_SCHEME, | |
| MAX_LABELS, | |
| follows_scheme_order, | |
| label_candidates, | |
| resolve_label_scheme, | |
| select_labels, | |
| ) | |
| from jev_adapter.server import create_app | |
| from jev_adapter.sglang import SGLangBackend | |
| GOLDEN_PATH = Path(__file__).parent / "data" / "upper-labels-ministral3.json" | |
| GOLDEN = json.loads(GOLDEN_PATH.read_text()) | |
| UPPER = GOLDEN["labels"] | |
| COUNTS = (2, 26, 27, 77, 151, 255) | |
| class VocabularyTokenizer: | |
| """Every character is one token; listed multi-letter strings are one token. | |
| With the golden vocabulary this has exactly the pinned Ministral-3 | |
| single-token pattern for the upper labels (e.g. AJ and AQ are split). | |
| """ | |
| all_special_ids = (0,) | |
| def __init__(self, words): | |
| self.word_ids = {word: 100_000 + index for index, word in enumerate(words)} | |
| self.words = {token: word for word, token in self.word_ids.items()} | |
| def encode(self, text, add_special_tokens=False): | |
| ids, position = [], 0 | |
| while position < len(text): | |
| for length in (3, 2): | |
| piece = text[position : position + length] | |
| if len(piece) == length and piece in self.word_ids: | |
| ids.append(self.word_ids[piece]) | |
| position += length | |
| break | |
| else: | |
| ids.append(ord(text[position]) + 1000) | |
| position += 1 | |
| return ids | |
| def decode(self, ids, skip_special_tokens=True): | |
| return "".join( | |
| self.words[token] if token in self.words else chr(token - 1000) | |
| for token in ids | |
| ) | |
| def ministral_like(): | |
| return VocabularyTokenizer([label for label in UPPER if len(label) > 1]) | |
| def test_default_and_resolution(): | |
| assert DEFAULT_LABEL_SCHEME == "upper" | |
| assert resolve_label_scheme(environ={}) == "upper" | |
| assert resolve_label_scheme(environ={"JEV_LABEL_SCHEME": "served"}) == "served" | |
| assert resolve_label_scheme("upper", {"JEV_LABEL_SCHEME": "served"}) == "upper" | |
| assert resolve_label_scheme("", {"JEV_LABEL_SCHEME": ""}) == "upper" | |
| for bad in ("lower", "UPPER", 3): | |
| with pytest.raises(ValueError, match="label scheme"): | |
| resolve_label_scheme(bad, {}) | |
| with pytest.raises(ValueError, match="label scheme"): | |
| resolve_label_scheme(None, {"JEV_LABEL_SCHEME": "lower"}) | |
| def test_candidate_orders(): | |
| upper = label_candidates("upper") | |
| assert upper[:28] == [*string.ascii_uppercase, "AA", "AB"] | |
| assert upper[26 + 675] == "ZZ" and upper[26 + 676] == "AAA" | |
| assert upper[-1] == "ZZZ" and len(upper) == 26 + 26**2 + 26**3 | |
| assert all(re.fullmatch(r"[A-Z]{1,3}", label) for label in upper) | |
| served = label_candidates("served") | |
| # The served order is unchanged from before the scheme option existed. | |
| assert served[:62] == list( | |
| string.ascii_uppercase + string.ascii_lowercase + string.digits | |
| ) | |
| assert served[62:64] == ["000", "001"] and served[1062:1064] == ["AA", "AB"] | |
| assert served[-1] == "zz" and len(served) == 62 + 1000 + 2 * 26**2 | |
| def test_upper_lists_for_each_option_count(count): | |
| labels, token_ids = select_labels(ministral_like(), "upper", limit=count) | |
| assert labels == UPPER[:count] | |
| assert len(set(labels)) == len(set(token_ids)) == count | |
| assert all(re.fullmatch(r"[A-Z]{1,2}", label) for label in labels) | |
| assert labels[: min(count, 26)] == list(string.ascii_uppercase[:count]) | |
| if count > 26: | |
| assert labels[26:29] == ["AA", "AB", "AC"][: count - 26] | |
| # AJ, AQ and AW are not single Ministral-3 tokens, so they are skipped. | |
| assert not {"AJ", "AQ", "AW"} & set(labels) | |
| def test_exact_boundary_labels(): | |
| labels, _ = select_labels(ministral_like(), "upper") | |
| assert len(labels) == MAX_LABELS | |
| assert labels[26] == "AA" | |
| assert labels[76] == "CG" # the 77th label: the last of BANKING77's options | |
| assert labels[150] == "FT" # the 151st: the last of CLINC150 with oos | |
| assert labels[254] == "MH" | |
| def test_at_most_26_options_keep_a_to_z_in_both_schemes(count): | |
| tokenizer = ministral_like() | |
| upper = select_labels(tokenizer, "upper", limit=count) | |
| served = select_labels(tokenizer, "served", limit=count) | |
| assert upper == served | |
| assert upper[0] == list(string.ascii_uppercase[:count]) | |
| def test_served_scheme_still_uses_lowercase_after_z(): | |
| labels, _ = select_labels(ministral_like(), "served") | |
| assert labels[26:30] == ["a", "b", "c", "d"] | |
| assert labels[52:62] == list(string.digits) | |
| assert labels[62] == "AA" | |
| def test_label_index_round_trip(count): | |
| labels, token_ids = select_labels(ministral_like(), "upper", limit=count) | |
| index = {label: position for position, label in enumerate(labels)} | |
| token_index = {token: position for position, token in enumerate(token_ids)} | |
| assert len(index) == len(token_index) == count | |
| for position, (label, token) in enumerate(zip(labels, token_ids)): | |
| assert index[label] == token_index[token] == position | |
| assert labels[index[label]] == label | |
| # Every label is also a prefix-free answer at the list level: a longer label | |
| # is one token, never the token of a shorter label followed by another. | |
| tokenizer = ministral_like() | |
| assert all( | |
| tokenizer.encode(label) == [token] for label, token in zip(labels, token_ids) | |
| ) | |
| def test_three_letter_continuation_when_two_letters_run_out(): | |
| # Only AA..AJ are two-letter tokens; the list continues with AAA, AAB, ... | |
| two = [f"A{letter}" for letter in "ABCDEFGHIJ"] | |
| three = ["AAA", "AAB", "ABA", "ZZZ"] | |
| tokenizer = VocabularyTokenizer(two + three) | |
| labels, _ = select_labels(tokenizer, "upper") | |
| assert labels == list(string.ascii_uppercase) + two + three | |
| def test_special_duplicate_and_lossy_tokens_are_skipped(): | |
| class Tricky(VocabularyTokenizer): | |
| all_special_ids = (ord("B") + 1000,) | |
| def decode(self, ids, skip_special_tokens=True): | |
| text = super().decode(ids, skip_special_tokens) | |
| return "ab" if text == "AB" else text | |
| def encode(self, text, add_special_tokens=False): | |
| return [ord("C") + 1000] if text == "AC" else super().encode(text) | |
| labels, _ = select_labels(Tricky(["AA", "AB", "AC", "AD"]), "upper") | |
| assert labels[:3] == ["A", "C", "D"] and "B" not in labels | |
| assert labels[25:] == ["AA", "AD"] | |
| def test_scheme_order_check(): | |
| assert follows_scheme_order("upper", ["A", "B", "AA", "AB", "MH", "AAA"]) | |
| assert not follows_scheme_order("upper", ["A", "a"]) | |
| assert not follows_scheme_order("upper", ["B", "A"]) | |
| assert not follows_scheme_order("upper", ["AA", "Z"]) | |
| assert follows_scheme_order("served", ["A", "Z", "a", "0", "AA", "aa"]) | |
| assert not follows_scheme_order("served", ["a", "A"]) | |
| assert not follows_scheme_order("served", ["A", "AAA"]) | |
| def test_pinned_ministral3_tokenizer_matches_the_golden_list(): | |
| transformers = pytest.importorskip("transformers") | |
| tokenizer_info = GOLDEN["tokenizer"] | |
| try: | |
| tokenizer = transformers.AutoTokenizer.from_pretrained( | |
| tokenizer_info["id"], | |
| revision=tokenizer_info["revision"], | |
| local_files_only=True, | |
| ) | |
| except Exception: # noqa: BLE001 - absent from this machine's HF cache | |
| pytest.skip("pinned Ministral-3 tokenizer is not cached locally") | |
| labels, token_ids = select_labels(tokenizer, "upper") | |
| assert labels == GOLDEN["labels"] | |
| assert token_ids == GOLDEN["token_ids"] | |
| # The recorded probe below is what this tokenizer really does. | |
| for candidate, ids in PROBE["encode"].items(): | |
| assert tokenizer.encode(candidate, add_special_tokens=False) == ids | |
| for token, text in PROBE["decode"].items(): | |
| assert tokenizer.decode([int(token)], skip_special_tokens=True) == text | |
| assert set(tokenizer.all_special_ids) <= ProbeTokenizer().all_special_ids | |
| from jev_adapter.native_tokenizer import NativeTokenizer | |
| # Every label continues the native chat prompt by exactly its token. | |
| NativeTokenizer(tokenizer).prepare("Choose.", tuple(labels), tuple(token_ids), None) | |
| # Raw encode/decode results of the pinned Ministral-3 tokenizer for every one- | |
| # and two-letter uppercase candidate, recorded on the GPU host with | |
| # AutoTokenizer and cross-checked against tekken.json (mistral_common) and the | |
| # release tokenizer.json. Unlike ministral_like(), which is built from the | |
| # golden list, this table is tokenizer data only, so the tests below check the | |
| # selection rule against the real tokenizer on every CI run. | |
| PROBE_PATH = Path(__file__).parent / "data" / "ministral3-label-probe.json" | |
| PROBE = json.loads(PROBE_PATH.read_text()) | |
| class ProbeTokenizer: | |
| """Replays the recorded tokenizer; a string outside the table is an error.""" | |
| def __init__(self): | |
| self.all_special_ids = { | |
| token | |
| for first, last in PROBE["special_id_ranges"] | |
| for token in range(first, last + 1) | |
| } | |
| def encode(self, text, add_special_tokens=False): | |
| assert add_special_tokens is False | |
| return list(PROBE["encode"][text]) | |
| def decode(self, ids, skip_special_tokens=True): | |
| assert skip_special_tokens is True | |
| return "".join(PROBE["decode"][str(token)] for token in ids) | |
| def test_probe_records_the_golden_lists_tokenizer(): | |
| assert PROBE["schema"] == "jev-tokenizer-probe-v1" | |
| assert PROBE["tokenizer"] == GOLDEN["tokenizer"] | |
| expected = PROBE["expected_upper"] | |
| assert expected["labels"] == GOLDEN["labels"] | |
| assert expected["token_ids"] == GOLDEN["token_ids"] | |
| assert expected["source_sha256"] == hashlib.sha256( | |
| GOLDEN_PATH.read_bytes() | |
| ).hexdigest() | |
| candidates = [*string.ascii_uppercase] + [ | |
| first + second | |
| for first in string.ascii_uppercase | |
| for second in string.ascii_uppercase | |
| ] | |
| assert list(PROBE["encode"]) == candidates | |
| singles = [label for label, ids in PROBE["encode"].items() if len(ids) == 1] | |
| counts = GOLDEN["single_token_counts"] | |
| assert sum(len(label) == 1 for label in singles) == counts["one_letter"] == 26 | |
| assert sum(len(label) == 2 for label in singles) == counts["two_letter"] == 439 | |
| def test_rule_on_the_recorded_ministral3_tokenizer_gives_the_golden_list(): | |
| # Three-letter candidates are absent from the table, so consulting one | |
| # would raise: 255 labels must come from one and two letters. | |
| labels, token_ids = select_labels(ProbeTokenizer(), "upper") | |
| assert labels == GOLDEN["labels"] | |
| assert token_ids == GOLDEN["token_ids"] | |
| for count in COUNTS: | |
| assert select_labels(ProbeTokenizer(), "upper", limit=count) == ( | |
| GOLDEN["labels"][:count], | |
| GOLDEN["token_ids"][:count], | |
| ) | |
| async def test_http_backend_picks_the_golden_list_from_the_recorded_tokenizer(): | |
| engine = LabelEngine(ProbeTokenizer(), "A") | |
| async with httpx.AsyncClient(transport=httpx.MockTransport(engine)) as upstream: | |
| backend = SGLangBackend( | |
| "http://engine", "standard-one", client=upstream, label_scheme="upper" | |
| ) | |
| await backend.start() | |
| try: | |
| for count in COUNTS: | |
| assert backend.labels(count) == ( | |
| tuple(GOLDEN["labels"][:count]), | |
| tuple(GOLDEN["token_ids"][:count]), | |
| ) | |
| finally: | |
| await backend.close() | |
| class LabelEngine: | |
| """A remote engine whose tokenizer has two-letter tokens and prefers one label.""" | |
| def __init__(self, tokenizer, preferred): | |
| self.tokenizer = tokenizer | |
| self.preferred = preferred | |
| self.prompts = [] | |
| def __call__(self, request): | |
| body = json.loads(request.content) if request.content else None | |
| path = request.url.path | |
| if path == "/model_info": | |
| return httpx.Response( | |
| 200, | |
| json={ | |
| "served_model_name": "standard-one", | |
| "model_path": "org/standard-one", | |
| "is_generation": True, | |
| }, | |
| ) | |
| if path == "/server_info": | |
| return httpx.Response(200, json={"speculative_algorithm": None}) | |
| encode = self.tokenizer.encode | |
| if path == "/v1/tokenize": | |
| if "messages" in body: | |
| content = body["messages"][-1]["content"] | |
| self.prompts.append(content) | |
| return httpx.Response( | |
| 200, json={"tokens": encode(f"<u>{content}</u><a>")} | |
| ) | |
| return httpx.Response( | |
| 200, json={"tokens": [encode(text) for text in body["prompt"]]} | |
| ) | |
| if path == "/v1/detokenize": | |
| tokens = body["tokens"] | |
| decode = self.tokenizer.decode | |
| text = ( | |
| [decode(ids) for ids in tokens] | |
| if isinstance(tokens[0], list) | |
| else decode(tokens) | |
| ) | |
| return httpx.Response(200, json={"text": text}) | |
| if path == "/generate": | |
| preferred = encode(self.preferred)[0] | |
| entries = [ | |
| [-0.1 if token == preferred else -9.0, token, None] | |
| for token in body["token_ids_logprob"] | |
| ] | |
| return httpx.Response( | |
| 200, | |
| json={ | |
| "meta_info": { | |
| "completion_tokens": 0, | |
| "prompt_tokens": len(body["input_ids"]), | |
| "cached_tokens": 0, | |
| "output_token_ids_logprobs": [entries], | |
| } | |
| }, | |
| ) | |
| raise AssertionError(path) | |
| async def test_label_maps_to_its_option_through_the_http_stack( | |
| scheme, count, preferred, expected_option | |
| ): | |
| engine = LabelEngine(ministral_like(), preferred) | |
| async with httpx.AsyncClient(transport=httpx.MockTransport(engine)) as upstream: | |
| backend = SGLangBackend( | |
| "http://engine", "standard-one", client=upstream, label_scheme=scheme | |
| ) | |
| app = create_app(backend) | |
| async with ( | |
| app.router.lifespan_context(app), | |
| httpx.AsyncClient( | |
| transport=httpx.ASGITransport(app), base_url="http://adapter" | |
| ) as client, | |
| ): | |
| models = (await client.get("/v1/models")).json() | |
| assert models["data"][0]["label_scheme"] == scheme | |
| options = {f"intent-{index}": None for index in range(count)} | |
| response = await client.post( | |
| "/v1/systemone", | |
| json={ | |
| "model": "standard-one", | |
| "state": "I lost my card.", | |
| "questions": { | |
| "intent": { | |
| "type": "choice", | |
| "instructions": "Which intent?", | |
| "criteria": options, | |
| } | |
| }, | |
| }, | |
| ) | |
| assert response.status_code == 200, response.text | |
| result = response.json() | |
| assert result["metadata"]["label_scheme"] == scheme | |
| assert result["answers"]["intent"]["choice"] == f"intent-{expected_option}" | |
| lines = engine.prompts[-1].split("Options:\n")[1].splitlines() | |
| labels = [line.split(":", 1)[0] for line in lines] | |
| expected, _ = select_labels(ministral_like(), scheme, limit=count) | |
| assert labels == expected | |
| assert lines[expected_option] == f"{preferred}: intent-{expected_option}" | |