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-8B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use StandardThinking/StandardOne-8B with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="StandardThinking/StandardOne-8B") 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-8B") model = AutoModelForMultimodalLM.from_pretrained("StandardThinking/StandardOne-8B", 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-8B with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "StandardThinking/StandardOne-8B" # 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-8B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/StandardThinking/StandardOne-8B
- SGLang
How to use StandardThinking/StandardOne-8B 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-8B" \ --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-8B", "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-8B" \ --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-8B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use StandardThinking/StandardOne-8B with Docker Model Runner:
docker model run hf.co/StandardThinking/StandardOne-8B
Update weights
Browse files- MERGE_REPORT.json +15 -16
- SHA256SUMS +22 -17
- model-00001-of-00004.safetensors +1 -1
- model-00002-of-00004.safetensors +1 -1
- model-00003-of-00004.safetensors +1 -1
- model-00004-of-00004.safetensors +1 -1
- release-manifest.json +16 -18
- server/README.md +7 -5
- server/jev_adapter/__main__.py +21 -1
- server/jev_adapter/labels.py +146 -0
- server/jev_adapter/protocol.py +3 -0
- server/jev_adapter/server.py +5 -0
- server/jev_adapter/service.py +5 -0
- server/jev_adapter/sglang.py +66 -68
- server/tests/conftest.py +7 -0
- server/tests/data/ministral3-label-probe.json +1183 -0
- server/tests/data/upper-labels-ministral3.json +535 -0
- server/tests/test_labels.py +406 -0
- server/tests/test_main.py +32 -0
- server/tests/test_protocol.py +16 -0
MERGE_REPORT.json
CHANGED
|
@@ -1,31 +1,31 @@
|
|
| 1 |
{
|
| 2 |
"snapshot": "mistralai/Ministral-3-8B-Instruct-2512-BF16@f6fae9795746f63c9be8344932f01275f3c63734",
|
| 3 |
-
"adapter": "StandardOne-8B-LoRA v2
|
| 4 |
-
"adapter_sha256": "
|
| 5 |
"changed_params": 238,
|
| 6 |
"unchanged_params": 293,
|
| 7 |
"changed_outside_lm_projections": [],
|
| 8 |
-
"max_abs_delta": 0.
|
| 9 |
"changed_sample": [
|
| 10 |
[
|
| 11 |
"model.language_model.layers.0.self_attn.q_proj.weight",
|
| 12 |
-
0.
|
| 13 |
],
|
| 14 |
[
|
| 15 |
"model.language_model.layers.0.self_attn.k_proj.weight",
|
| 16 |
-
0.
|
| 17 |
],
|
| 18 |
[
|
| 19 |
"model.language_model.layers.0.self_attn.v_proj.weight",
|
| 20 |
-
0.
|
| 21 |
],
|
| 22 |
[
|
| 23 |
"model.language_model.layers.0.self_attn.o_proj.weight",
|
| 24 |
-
0.
|
| 25 |
],
|
| 26 |
[
|
| 27 |
"model.language_model.layers.0.mlp.gate_proj.weight",
|
| 28 |
-
0.
|
| 29 |
],
|
| 30 |
[
|
| 31 |
"model.language_model.layers.0.mlp.up_proj.weight",
|
|
@@ -33,7 +33,7 @@
|
|
| 33 |
],
|
| 34 |
[
|
| 35 |
"model.language_model.layers.0.mlp.down_proj.weight",
|
| 36 |
-
0.
|
| 37 |
],
|
| 38 |
[
|
| 39 |
"model.language_model.layers.1.self_attn.q_proj.weight",
|
|
@@ -45,10 +45,10 @@
|
|
| 45 |
"chat_template.jinja": "74eeb55fd3341286ec3fd44e902b7120721acc81cd394e96b431f85e93a1ea56",
|
| 46 |
"config.json": "111827aa7ae6d936f48afb2f0776f51b00add45c857c708af2b893499f76d882",
|
| 47 |
"generation_config.json": "e0923390059f84a9180b00e5501778acc45ea9856cd7f2fd68208b360927c677",
|
| 48 |
-
"model-00001-of-00004.safetensors": "
|
| 49 |
-
"model-00002-of-00004.safetensors": "
|
| 50 |
-
"model-00003-of-00004.safetensors": "
|
| 51 |
-
"model-00004-of-00004.safetensors": "
|
| 52 |
"model.safetensors.index.json": "71e022361d37d84c2b6224acbddca2c74bedcc7addc523cfc6a57420d4b22ceb",
|
| 53 |
"params.json": "81b8377f36c5b3d60900b333214d85160a0500b84576e969092c6fd214f69538",
|
| 54 |
"processor_config.json": "ece2373c2ae391bce18785a1810543bc6173a1f28b6767cffab2c35dbea5f002",
|
|
@@ -56,6 +56,5 @@
|
|
| 56 |
"tekken.json": "600bb27946565481ecf51ba8aee252e49b9a68507866080ac9c30185bb312843",
|
| 57 |
"tokenizer.json": "d5f6046775b112f0e2d456ee9dba450684ab964fe5c4e231599bdc6773028135",
|
| 58 |
"tokenizer_config.json": "f59f7294e4f26383d0ea93840fe21cf197784be0842a8301a0343e8c34ed0d6d"
|
| 59 |
-
}
|
| 60 |
-
|
| 61 |
-
}
|
|
|
|
| 1 |
{
|
| 2 |
"snapshot": "mistralai/Ministral-3-8B-Instruct-2512-BF16@f6fae9795746f63c9be8344932f01275f3c63734",
|
| 3 |
+
"adapter": "StandardOne-8B-LoRA v2.2",
|
| 4 |
+
"adapter_sha256": "123ddd039f4053e82e8ca18d7c247691dc49cbcabb6e1b7d98077bb7c5c7446e",
|
| 5 |
"changed_params": 238,
|
| 6 |
"unchanged_params": 293,
|
| 7 |
"changed_outside_lm_projections": [],
|
| 8 |
+
"max_abs_delta": 0.002109527587890625,
|
| 9 |
"changed_sample": [
|
| 10 |
[
|
| 11 |
"model.language_model.layers.0.self_attn.q_proj.weight",
|
| 12 |
+
0.00152587890625
|
| 13 |
],
|
| 14 |
[
|
| 15 |
"model.language_model.layers.0.self_attn.k_proj.weight",
|
| 16 |
+
0.00091552734375
|
| 17 |
],
|
| 18 |
[
|
| 19 |
"model.language_model.layers.0.self_attn.v_proj.weight",
|
| 20 |
+
0.0012216567993164062
|
| 21 |
],
|
| 22 |
[
|
| 23 |
"model.language_model.layers.0.self_attn.o_proj.weight",
|
| 24 |
+
0.001377105712890625
|
| 25 |
],
|
| 26 |
[
|
| 27 |
"model.language_model.layers.0.mlp.gate_proj.weight",
|
| 28 |
+
0.00113677978515625
|
| 29 |
],
|
| 30 |
[
|
| 31 |
"model.language_model.layers.0.mlp.up_proj.weight",
|
|
|
|
| 33 |
],
|
| 34 |
[
|
| 35 |
"model.language_model.layers.0.mlp.down_proj.weight",
|
| 36 |
+
0.0006103515625
|
| 37 |
],
|
| 38 |
[
|
| 39 |
"model.language_model.layers.1.self_attn.q_proj.weight",
|
|
|
|
| 45 |
"chat_template.jinja": "74eeb55fd3341286ec3fd44e902b7120721acc81cd394e96b431f85e93a1ea56",
|
| 46 |
"config.json": "111827aa7ae6d936f48afb2f0776f51b00add45c857c708af2b893499f76d882",
|
| 47 |
"generation_config.json": "e0923390059f84a9180b00e5501778acc45ea9856cd7f2fd68208b360927c677",
|
| 48 |
+
"model-00001-of-00004.safetensors": "cac498368970b8ffb9785583c954648a40472b3cfa061ad0924af7babdee3f53",
|
| 49 |
+
"model-00002-of-00004.safetensors": "9a9fbec75dc4013463a57ad1cf61c2ed6fb558db9d379fb671dba0e448326be0",
|
| 50 |
+
"model-00003-of-00004.safetensors": "2f89f2111ee337b3b8b1278d0ec32bce3c20bfe5f2bab8caa6dd3e01a3c76ad5",
|
| 51 |
+
"model-00004-of-00004.safetensors": "125adfa505e3f9c1b33767601060c773a421876c3630fb8172dcdc886adf137f",
|
| 52 |
"model.safetensors.index.json": "71e022361d37d84c2b6224acbddca2c74bedcc7addc523cfc6a57420d4b22ceb",
|
| 53 |
"params.json": "81b8377f36c5b3d60900b333214d85160a0500b84576e969092c6fd214f69538",
|
| 54 |
"processor_config.json": "ece2373c2ae391bce18785a1810543bc6173a1f28b6767cffab2c35dbea5f002",
|
|
|
|
| 56 |
"tekken.json": "600bb27946565481ecf51ba8aee252e49b9a68507866080ac9c30185bb312843",
|
| 57 |
"tokenizer.json": "d5f6046775b112f0e2d456ee9dba450684ab964fe5c4e231599bdc6773028135",
|
| 58 |
"tokenizer_config.json": "f59f7294e4f26383d0ea93840fe21cf197784be0842a8301a0343e8c34ed0d6d"
|
| 59 |
+
}
|
| 60 |
+
}
|
|
|
SHA256SUMS
CHANGED
|
@@ -1,8 +1,8 @@
|
|
| 1 |
1495e1e757ef4d0925a2350563cf5754bb23c51701a8ec4fb3c5cdcbedae6747 LICENSE
|
| 2 |
-
|
| 3 |
20486cf6b2e42440b0aea913ea475c818664f34e76e4501651d6cb21987a508b NOTICE
|
| 4 |
-
|
| 5 |
-
|
| 6 |
66e0fda8c8ab269ccd010dca6196931d475a22c3f2eebe5b6b3a2ec33a354d0e SYSTEM_PROMPT.txt
|
| 7 |
74eeb55fd3341286ec3fd44e902b7120721acc81cd394e96b431f85e93a1ea56 chat_template.jinja
|
| 8 |
111827aa7ae6d936f48afb2f0776f51b00add45c857c708af2b893499f76d882 config.json
|
|
@@ -17,7 +17,7 @@ dd888be78c0e32894cf04a8e3fbf8757e7218873668fa4443ba47c7c1c48b6dc docs/assets/04
|
|
| 17 |
22396bd8908b697d912bd1ec54a510eff2b2b1884cd00b5e1bedd81db450d2fa docs/assets/05-gain-over-base.svg
|
| 18 |
c43fb809f0b6bff34530fe2970fbd59817ae56e93813da7f45af32a8b9413987 docs/assets/06-vs-jev.png
|
| 19 |
23fe4cfc32b756068dd3967339bae947391a18f1c4c0de5bad5c0dceeaff3463 docs/assets/06-vs-jev.svg
|
| 20 |
-
|
| 21 |
7866009cccf468a71c56163d0ec27eee5185e5d8dc4c1a495f91445229eb4c95 evidence/calibration-leaderboard-ablate-nosys.json
|
| 22 |
e3b7eb0fff1504035ab7ddbe01af976db48236872e6b77fc7bcdc766a60fd000 evidence/calibration-leaderboard-merged-native.json
|
| 23 |
a717a16ab338fb5a3aefe0822a5421732cb2f68d965691fdb8138ded0b4d70b3 evidence/calibration-per-type-served.json
|
|
@@ -27,17 +27,17 @@ a33036e10498a440481258cbbc8611b531498d6239115a9278c3e6cafe10f6ad evidence/serve
|
|
| 27 |
d47f43be5bd7767b80ed27a96a9a85ece1495b37fb9365e575b1df6b32fbc509 evidence/served-nosys-latency-idle-gpu.json
|
| 28 |
262f5c7f85fcc5b8a9ccfaa7485d8b9f11a70f3d5a2ff60868ff9ccd1e887b43 evidence/served-nosys-original-report.json
|
| 29 |
e0923390059f84a9180b00e5501778acc45ea9856cd7f2fd68208b360927c677 generation_config.json
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
71e022361d37d84c2b6224acbddca2c74bedcc7addc523cfc6a57420d4b22ceb model.safetensors.index.json
|
| 35 |
81b8377f36c5b3d60900b333214d85160a0500b84576e969092c6fd214f69538 params.json
|
| 36 |
ece2373c2ae391bce18785a1810543bc6173a1f28b6767cffab2c35dbea5f002 processor_config.json
|
| 37 |
-
|
| 38 |
1495e1e757ef4d0925a2350563cf5754bb23c51701a8ec4fb3c5cdcbedae6747 server/LICENSE
|
| 39 |
0f1f023b916d38d7c12af3a71e09f5e82b819a7e156e4992118bb160ee63ede1 server/NOTICE
|
| 40 |
-
|
| 41 |
88e4dea8cc92f467a03bdd45a5fb968e402517116b09e24edcea85bb15f121e5 server/benchmarks/DECISION_BENCHMARK_SELECTION.md
|
| 42 |
7fea6b9dc44e34ce448f1d80a9f2d273b76ab9b0ac1859c032fa4faa4f458501 server/benchmarks/METRIC_VALIDATION.md
|
| 43 |
bb88f12ef294680e389147d781bf1f8680ea0a5ca9ed554730d8ea29f1c25eb9 server/benchmarks/PUBLIC_DATASETS.md
|
|
@@ -59,7 +59,7 @@ fee797d1a2ff128a5d61dd436e8252d63bc726b8ce4ba72641a1ffd9196135a6 server/benchma
|
|
| 59 |
2544280dd3e669985bf57dfc61c2212bcf16d27230a79cea76f9f4e822476429 server/examples/request.json
|
| 60 |
7a14fe0f5bf73aca7a4930423c310c0a3b1f9b546d07abc8d3fd5d9f38c9a5d7 server/examples/smoke.py
|
| 61 |
e589f268969c87f82ddd2c81c0432c6335c08a9f9f2537ce68ddd5708f1e6f9e server/jev_adapter/__init__.py
|
| 62 |
-
|
| 63 |
e2f84bb7867934533f8f2a87034cad76af695ca1bbdbf096c545fe60b790c6fa server/jev_adapter/backend.py
|
| 64 |
2cd67e71c1a601fc9333c266d909197031b7c0dc746b9a2d5475a5fb0c085e95 server/jev_adapter/benchmarks/__init__.py
|
| 65 |
44104bc2d6431c05345cd697dd2c377cc6ba9fd57f2177df7b548490cf5f53fc server/jev_adapter/benchmarks/compare.py
|
|
@@ -68,21 +68,26 @@ a66e6ec289b4c32f79ac990261650870be6b923e47753b9c89ff9e58fe2f982f server/jev_ada
|
|
| 68 |
1b78c52f723cb3a3e614d1be4ca531e7595e0a6690e704d6f1bb3045dd948bf0 server/jev_adapter/benchmarks/metrics.py
|
| 69 |
9c51ce87269c587f1353b9dd32d886f9f0a51613a996721a7bb81695af445c02 server/jev_adapter/benchmarks/prepare.py
|
| 70 |
0fef99cd01164c5548de530c9ab93255e2a95d17757c12e8e3d23016afd1a03c server/jev_adapter/benchmarks/run.py
|
|
|
|
| 71 |
86e113a3ee9d15d9be93ba5e964d5f5d51171619e7856cc7dde812c6c90f4a37 server/jev_adapter/native_tokenizer.py
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
159eb400efb830c762a36f81e51ba79888570284ffa70326301adfeee50b5bd3 server/pyproject.toml
|
|
|
|
|
|
|
|
|
|
| 77 |
f5bf6e9b916ff0d24a2551b4f9f24ed353e7343f5be343b141d38c4c04bd1101 server/tests/test_benchmark_data.py
|
| 78 |
c197a90d57c7516eb615f7f0626f4c3e95b2fd0773d74e8f32601251804fca66 server/tests/test_benchmark_matrix.py
|
| 79 |
56a48c36d322d7131978809397da79d0f9abbb6801ab6176d27ed2f9dfb26063 server/tests/test_benchmark_run.py
|
| 80 |
c492b41c07050d9b76c6c9d7d21bbfcdac6ec137346cf995df3f624cb1e345c8 server/tests/test_disconnect_cleanup.py
|
| 81 |
83769ec3f35f5034787ffa8160a5ea7c9c7e23200b303d8b908500d71e3fe13f server/tests/test_http_integration.py
|
| 82 |
746cc73422976ec22b460a74a7c70d937c0ba4fd9fb7151fa6745641dbca5616 server/tests/test_jevbench.py
|
| 83 |
-
|
|
|
|
| 84 |
83084f098020374a4abfa3d4402e74e357d45170ca840843e58dba13162e9986 server/tests/test_native_tokenizer.py
|
| 85 |
-
|
| 86 |
617f08c82448932cf13320166c4df66a1a85b5056a354aa8e9f748ce9b6f57d3 server/tests/test_service.py
|
| 87 |
340e91fb9a6c870990187386da8d165fafcbcb5f08559056fd9da4e4e78b681f server/tests/test_sglang.py
|
| 88 |
0a5c981e8c5c6f8886ee007a6d4543a0be6b221cb9ca32a8709384a4c6fc8cbb special_tokens_map.json
|
|
|
|
| 1 |
1495e1e757ef4d0925a2350563cf5754bb23c51701a8ec4fb3c5cdcbedae6747 LICENSE
|
| 2 |
+
78430ac850a7b8182093fadb6fafa36d70ad79f548b5369d261ef81034343b24 MERGE_REPORT.json
|
| 3 |
20486cf6b2e42440b0aea913ea475c818664f34e76e4501651d6cb21987a508b NOTICE
|
| 4 |
+
7fdc581f9a4e8bb935e3c883435b456d283aea2e439f4560103e0923c39080be QUICKSTART.md
|
| 5 |
+
33f44c5a637384c0153be71319eafeee6013241d801efa06b41183bdc4e30faa README.md
|
| 6 |
66e0fda8c8ab269ccd010dca6196931d475a22c3f2eebe5b6b3a2ec33a354d0e SYSTEM_PROMPT.txt
|
| 7 |
74eeb55fd3341286ec3fd44e902b7120721acc81cd394e96b431f85e93a1ea56 chat_template.jinja
|
| 8 |
111827aa7ae6d936f48afb2f0776f51b00add45c857c708af2b893499f76d882 config.json
|
|
|
|
| 17 |
22396bd8908b697d912bd1ec54a510eff2b2b1884cd00b5e1bedd81db450d2fa docs/assets/05-gain-over-base.svg
|
| 18 |
c43fb809f0b6bff34530fe2970fbd59817ae56e93813da7f45af32a8b9413987 docs/assets/06-vs-jev.png
|
| 19 |
23fe4cfc32b756068dd3967339bae947391a18f1c4c0de5bad5c0dceeaff3463 docs/assets/06-vs-jev.svg
|
| 20 |
+
58d920ce53f77d10b78f857e67bd5fecec86405a23a5643101e3b0d2d367f4db docs/public-classification-suites.md
|
| 21 |
7866009cccf468a71c56163d0ec27eee5185e5d8dc4c1a495f91445229eb4c95 evidence/calibration-leaderboard-ablate-nosys.json
|
| 22 |
e3b7eb0fff1504035ab7ddbe01af976db48236872e6b77fc7bcdc766a60fd000 evidence/calibration-leaderboard-merged-native.json
|
| 23 |
a717a16ab338fb5a3aefe0822a5421732cb2f68d965691fdb8138ded0b4d70b3 evidence/calibration-per-type-served.json
|
|
|
|
| 27 |
d47f43be5bd7767b80ed27a96a9a85ece1495b37fb9365e575b1df6b32fbc509 evidence/served-nosys-latency-idle-gpu.json
|
| 28 |
262f5c7f85fcc5b8a9ccfaa7485d8b9f11a70f3d5a2ff60868ff9ccd1e887b43 evidence/served-nosys-original-report.json
|
| 29 |
e0923390059f84a9180b00e5501778acc45ea9856cd7f2fd68208b360927c677 generation_config.json
|
| 30 |
+
cac498368970b8ffb9785583c954648a40472b3cfa061ad0924af7babdee3f53 model-00001-of-00004.safetensors
|
| 31 |
+
9a9fbec75dc4013463a57ad1cf61c2ed6fb558db9d379fb671dba0e448326be0 model-00002-of-00004.safetensors
|
| 32 |
+
2f89f2111ee337b3b8b1278d0ec32bce3c20bfe5f2bab8caa6dd3e01a3c76ad5 model-00003-of-00004.safetensors
|
| 33 |
+
125adfa505e3f9c1b33767601060c773a421876c3630fb8172dcdc886adf137f model-00004-of-00004.safetensors
|
| 34 |
71e022361d37d84c2b6224acbddca2c74bedcc7addc523cfc6a57420d4b22ceb model.safetensors.index.json
|
| 35 |
81b8377f36c5b3d60900b333214d85160a0500b84576e969092c6fd214f69538 params.json
|
| 36 |
ece2373c2ae391bce18785a1810543bc6173a1f28b6767cffab2c35dbea5f002 processor_config.json
|
| 37 |
+
6741d6b57b543a839be57e56b6189562bd098050a0eca7bf53b8016500e4324c release-manifest.json
|
| 38 |
1495e1e757ef4d0925a2350563cf5754bb23c51701a8ec4fb3c5cdcbedae6747 server/LICENSE
|
| 39 |
0f1f023b916d38d7c12af3a71e09f5e82b819a7e156e4992118bb160ee63ede1 server/NOTICE
|
| 40 |
+
6385bb6dba77ed768d7214a8f17a311db266ea99bdd34e1fab2f0735e4a41e0f server/README.md
|
| 41 |
88e4dea8cc92f467a03bdd45a5fb968e402517116b09e24edcea85bb15f121e5 server/benchmarks/DECISION_BENCHMARK_SELECTION.md
|
| 42 |
7fea6b9dc44e34ce448f1d80a9f2d273b76ab9b0ac1859c032fa4faa4f458501 server/benchmarks/METRIC_VALIDATION.md
|
| 43 |
bb88f12ef294680e389147d781bf1f8680ea0a5ca9ed554730d8ea29f1c25eb9 server/benchmarks/PUBLIC_DATASETS.md
|
|
|
|
| 59 |
2544280dd3e669985bf57dfc61c2212bcf16d27230a79cea76f9f4e822476429 server/examples/request.json
|
| 60 |
7a14fe0f5bf73aca7a4930423c310c0a3b1f9b546d07abc8d3fd5d9f38c9a5d7 server/examples/smoke.py
|
| 61 |
e589f268969c87f82ddd2c81c0432c6335c08a9f9f2537ce68ddd5708f1e6f9e server/jev_adapter/__init__.py
|
| 62 |
+
caacf020f66bbfbf1e09ac303a7e9adbe493ad4154a1339c203c8ff87fb3392a server/jev_adapter/__main__.py
|
| 63 |
e2f84bb7867934533f8f2a87034cad76af695ca1bbdbf096c545fe60b790c6fa server/jev_adapter/backend.py
|
| 64 |
2cd67e71c1a601fc9333c266d909197031b7c0dc746b9a2d5475a5fb0c085e95 server/jev_adapter/benchmarks/__init__.py
|
| 65 |
44104bc2d6431c05345cd697dd2c377cc6ba9fd57f2177df7b548490cf5f53fc server/jev_adapter/benchmarks/compare.py
|
|
|
|
| 68 |
1b78c52f723cb3a3e614d1be4ca531e7595e0a6690e704d6f1bb3045dd948bf0 server/jev_adapter/benchmarks/metrics.py
|
| 69 |
9c51ce87269c587f1353b9dd32d886f9f0a51613a996721a7bb81695af445c02 server/jev_adapter/benchmarks/prepare.py
|
| 70 |
0fef99cd01164c5548de530c9ab93255e2a95d17757c12e8e3d23016afd1a03c server/jev_adapter/benchmarks/run.py
|
| 71 |
+
9a3d1c89d7451a52383709487acb883f683dbdcb2ca73b5a9b39b9b75407a09e server/jev_adapter/labels.py
|
| 72 |
86e113a3ee9d15d9be93ba5e964d5f5d51171619e7856cc7dde812c6c90f4a37 server/jev_adapter/native_tokenizer.py
|
| 73 |
+
0acba8046427725f4275cd971cfc29f48c04c64e73f96115b83ce8ac1bcbe8b7 server/jev_adapter/protocol.py
|
| 74 |
+
4375a9eafb6d252a76b2b57dd7cecfd600baae04a9ab4dd0abbd6c86a3778be9 server/jev_adapter/server.py
|
| 75 |
+
24667f1c1d6967f5a1c90d6e9bf13922bdfe1ce1a3aea8709c18a1837d2fe09c server/jev_adapter/service.py
|
| 76 |
+
18b3191db6a3e43a2ad01243c709bab2c8db771b1363638de64ab4871b0f1d7b server/jev_adapter/sglang.py
|
| 77 |
159eb400efb830c762a36f81e51ba79888570284ffa70326301adfeee50b5bd3 server/pyproject.toml
|
| 78 |
+
d4d01e7e2c0d49ccce56516db8aaef0eb32d001b42e8f394e7e355e90047db71 server/tests/conftest.py
|
| 79 |
+
63046320ac89d71770afccf8f3ad861c795151ede968354f34f59aabff9ec5c3 server/tests/data/ministral3-label-probe.json
|
| 80 |
+
27119a52ee9a0417809c3a50b5b07e77aa723d4a63266d1065ba8ca82589d512 server/tests/data/upper-labels-ministral3.json
|
| 81 |
f5bf6e9b916ff0d24a2551b4f9f24ed353e7343f5be343b141d38c4c04bd1101 server/tests/test_benchmark_data.py
|
| 82 |
c197a90d57c7516eb615f7f0626f4c3e95b2fd0773d74e8f32601251804fca66 server/tests/test_benchmark_matrix.py
|
| 83 |
56a48c36d322d7131978809397da79d0f9abbb6801ab6176d27ed2f9dfb26063 server/tests/test_benchmark_run.py
|
| 84 |
c492b41c07050d9b76c6c9d7d21bbfcdac6ec137346cf995df3f624cb1e345c8 server/tests/test_disconnect_cleanup.py
|
| 85 |
83769ec3f35f5034787ffa8160a5ea7c9c7e23200b303d8b908500d71e3fe13f server/tests/test_http_integration.py
|
| 86 |
746cc73422976ec22b460a74a7c70d937c0ba4fd9fb7151fa6745641dbca5616 server/tests/test_jevbench.py
|
| 87 |
+
de052504cc7d82c964ef7cf4d6d2fafabf3ec61e4c4b359b9baadeea6b27c7f2 server/tests/test_labels.py
|
| 88 |
+
af1ebfb5c57e2de76b8f90bdb6eec89abaa29ae3a1873595d4de287788c991af server/tests/test_main.py
|
| 89 |
83084f098020374a4abfa3d4402e74e357d45170ca840843e58dba13162e9986 server/tests/test_native_tokenizer.py
|
| 90 |
+
b296814c9f0837d7c2625e1867b3197021f11c0b1c7ab5b74aa9c4b298b82396 server/tests/test_protocol.py
|
| 91 |
617f08c82448932cf13320166c4df66a1a85b5056a354aa8e9f748ce9b6f57d3 server/tests/test_service.py
|
| 92 |
340e91fb9a6c870990187386da8d165fafcbcb5f08559056fd9da4e4e78b681f server/tests/test_sglang.py
|
| 93 |
0a5c981e8c5c6f8886ee007a6d4543a0be6b221cb9ca32a8709384a4c6fc8cbb special_tokens_map.json
|
model-00001-of-00004.safetensors
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
size 4999724576
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:cac498368970b8ffb9785583c954648a40472b3cfa061ad0924af7babdee3f53
|
| 3 |
size 4999724576
|
model-00002-of-00004.safetensors
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
size 4999820896
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:9a9fbec75dc4013463a57ad1cf61c2ed6fb558db9d379fb671dba0e448326be0
|
| 3 |
size 4999820896
|
model-00003-of-00004.safetensors
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
size 4915917688
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:2f89f2111ee337b3b8b1278d0ec32bce3c20bfe5f2bab8caa6dd3e01a3c76ad5
|
| 3 |
size 4915917688
|
model-00004-of-00004.safetensors
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
size 2920659992
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:125adfa505e3f9c1b33767601060c773a421876c3630fb8172dcdc886adf137f
|
| 3 |
size 2920659992
|
release-manifest.json
CHANGED
|
@@ -1,40 +1,38 @@
|
|
| 1 |
{
|
| 2 |
"release": "StandardOne-8B",
|
| 3 |
-
"version": "v2",
|
| 4 |
"base_model": {
|
| 5 |
"repo": "mistralai/Ministral-3-8B-Instruct-2512-BF16",
|
| 6 |
"revision": "f6fae9795746f63c9be8344932f01275f3c63734"
|
| 7 |
},
|
| 8 |
"adapter": {
|
| 9 |
-
"
|
| 10 |
-
"adapter_model_sha256": "53e41238cd55567cfbc75efdf61d354da39771573f56f74bb1440c9ffdd1bd4a"
|
| 11 |
},
|
| 12 |
"merge_report_summary": {
|
| 13 |
"changed_params": 238,
|
| 14 |
"unchanged_params": 293,
|
| 15 |
"changed_outside_lm_projections": [],
|
| 16 |
-
"max_abs_delta": 0.
|
| 17 |
},
|
| 18 |
"serving": {
|
| 19 |
-
"wording": "
|
| 20 |
"system_prompt": null,
|
|
|
|
| 21 |
"served_model_name": "standard-one-8b",
|
| 22 |
"engine": "SGLang 0.5.20",
|
| 23 |
-
"
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
"score": 0.7
|
| 27 |
-
},
|
| 28 |
-
"default_temperature": 0.85,
|
| 29 |
-
"selection": "wording and temperatures chosen on non-JevBench data (evidence/prompt-wording-choice.json, evidence/calibration-per-type-served.json)",
|
| 30 |
"alternative_wording": {
|
| 31 |
-
"wording": "
|
| 32 |
-
"
|
|
|
|
| 33 |
"temperature_by_type": {
|
| 34 |
-
"choice": 0.
|
| 35 |
-
"noul": 0.
|
| 36 |
-
"score": 0.
|
| 37 |
-
}
|
|
|
|
| 38 |
}
|
| 39 |
}
|
| 40 |
}
|
|
|
|
| 1 |
{
|
| 2 |
"release": "StandardOne-8B",
|
| 3 |
+
"version": "v2.2",
|
| 4 |
"base_model": {
|
| 5 |
"repo": "mistralai/Ministral-3-8B-Instruct-2512-BF16",
|
| 6 |
"revision": "f6fae9795746f63c9be8344932f01275f3c63734"
|
| 7 |
},
|
| 8 |
"adapter": {
|
| 9 |
+
"adapter_model_sha256": "123ddd039f4053e82e8ca18d7c247691dc49cbcabb6e1b7d98077bb7c5c7446e"
|
|
|
|
| 10 |
},
|
| 11 |
"merge_report_summary": {
|
| 12 |
"changed_params": 238,
|
| 13 |
"unchanged_params": 293,
|
| 14 |
"changed_outside_lm_projections": [],
|
| 15 |
+
"max_abs_delta": 0.002109527587890625
|
| 16 |
},
|
| 17 |
"serving": {
|
| 18 |
+
"wording": "served",
|
| 19 |
"system_prompt": null,
|
| 20 |
+
"label_scheme": "upper",
|
| 21 |
"served_model_name": "standard-one-8b",
|
| 22 |
"engine": "SGLang 0.5.20",
|
| 23 |
+
"context_length": 32768,
|
| 24 |
+
"default_temperature": 1.65,
|
| 25 |
+
"selection": "the configuration used for the v2.2 measurements; no temperature was refit for v2.2",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
"alternative_wording": {
|
| 27 |
+
"wording": "native",
|
| 28 |
+
"max_options": 26,
|
| 29 |
+
"default_temperature": 0.85,
|
| 30 |
"temperature_by_type": {
|
| 31 |
+
"choice": 0.85,
|
| 32 |
+
"noul": 0.85,
|
| 33 |
+
"score": 0.7
|
| 34 |
+
},
|
| 35 |
+
"note": "temperatures fitted on v2"
|
| 36 |
}
|
| 37 |
}
|
| 38 |
}
|
server/README.md
CHANGED
|
@@ -11,7 +11,7 @@ pip install -e './server[native-tokenizer]'
|
|
| 11 |
CUDA_VISIBLE_DEVICES=0 SGLANG_VLM_CACHE_SIZE_MB=0 python -m sglang.launch_server \
|
| 12 |
--model-path . --served-model-name standard-one-8b \
|
| 13 |
--host 127.0.0.1 --port 30000 --tp-size 1 --model-impl sglang --dtype bfloat16 \
|
| 14 |
-
--context-length
|
| 15 |
--chunked-prefill-size -1 --disable-radix-cache --mm-preprocess-cache-size-mb 0 \
|
| 16 |
--model-config-parser hf --load-format safetensors
|
| 17 |
|
|
@@ -20,13 +20,13 @@ jev-adapter --engine-url http://127.0.0.1:30000 --model standard-one-8b --alias
|
|
| 20 |
--host 0.0.0.0 --port 30120 --max-concurrency 1 \
|
| 21 |
--tokenizer-model mistralai/Ministral-3-8B-Instruct-2512-BF16 \
|
| 22 |
--tokenizer-revision f6fae9795746f63c9be8344932f01275f3c63734 \
|
| 23 |
-
--prompt-wording
|
| 24 |
```
|
| 25 |
|
| 26 |
-
The adapter supports two prompt wordings
|
| 27 |
|
| 28 |
-
- `
|
| 29 |
-
- `
|
| 30 |
|
| 31 |
`--temperature-by-type` sets one default temperature per answer type (`choice`, `noul`, `score`); a request's own
|
| 32 |
`options.temperature` still wins. Let only this adapter talk to the engine port. The recommended values and the full
|
|
@@ -69,6 +69,8 @@ python3 -m venv .venv
|
|
| 69 |
|
| 70 |
`--default-temperature T` (환경 변수 `JEV_DEFAULT_TEMPERATURE`)는 요청이 `options.temperature`를 생략했을 때만 적용되는 서버 기본 온도입니다. 요청이 온도를 명시하면 요청 값이 우선하고, `options.temperature_scaling: false`이면 기본값과 무관하게 스케일링하지 않습니다. 지정하지 않으면 기존과 같이 1.0입니다. 실제 적용된 온도는 응답의 `metadata.temperature`로 확인합니다.
|
| 71 |
|
|
|
|
|
|
|
| 72 |
`SGLANG_API_KEY`는 엔진에 보낼 키, `JEV_API_KEY`는 클라이언트가 어댑터에 보낼 키입니다. 설정했다면 각각 `Authorization: Bearer ...` 인증을 사용합니다. 키를 설정하지 않은 어댑터는 인증 없이 동작합니다.
|
| 73 |
|
| 74 |
시작할 때 엔진 정보를 확인하고, 엔진 토크나이저로 라벨을 검증합니다. 엔진을 먼저 실행해야 합니다. 모델/토크나이저를 교체하면 어댑터도 재시작합니다.
|
|
|
|
| 11 |
CUDA_VISIBLE_DEVICES=0 SGLANG_VLM_CACHE_SIZE_MB=0 python -m sglang.launch_server \
|
| 12 |
--model-path . --served-model-name standard-one-8b \
|
| 13 |
--host 127.0.0.1 --port 30000 --tp-size 1 --model-impl sglang --dtype bfloat16 \
|
| 14 |
+
--context-length 32768 --max-running-requests 32 --mem-fraction-static 0.8 \
|
| 15 |
--chunked-prefill-size -1 --disable-radix-cache --mm-preprocess-cache-size-mb 0 \
|
| 16 |
--model-config-parser hf --load-format safetensors
|
| 17 |
|
|
|
|
| 20 |
--host 0.0.0.0 --port 30120 --max-concurrency 1 \
|
| 21 |
--tokenizer-model mistralai/Ministral-3-8B-Instruct-2512-BF16 \
|
| 22 |
--tokenizer-revision f6fae9795746f63c9be8344932f01275f3c63734 \
|
| 23 |
+
--prompt-wording served --label-scheme upper --default-temperature 1.65
|
| 24 |
```
|
| 25 |
|
| 26 |
+
The adapter supports two prompt wordings (details on the model card):
|
| 27 |
|
| 28 |
+
- `served` (the default, recommended; used for the v2.2 measurements): `--prompt-wording served --label-scheme upper --default-temperature 1.65`; up to 255 options per question
|
| 29 |
+
- `native`: `--prompt-wording native --native-system-prompt none --default-temperature 0.85 --temperature-by-type choice=0.85,noul=0.85,score=0.70` (temperatures fitted on v2); at most 26 options per question
|
| 30 |
|
| 31 |
`--temperature-by-type` sets one default temperature per answer type (`choice`, `noul`, `score`); a request's own
|
| 32 |
`options.temperature` still wins. Let only this adapter talk to the engine port. The recommended values and the full
|
|
|
|
| 69 |
|
| 70 |
`--default-temperature T` (환경 변수 `JEV_DEFAULT_TEMPERATURE`)는 요청이 `options.temperature`를 생략했을 때만 적용되는 서버 기본 온도입니다. 요청이 온도를 명시하면 요청 값이 우선하고, `options.temperature_scaling: false`이면 기본값과 무관하게 스케일링하지 않습니다. 지정하지 않으면 기존과 같이 1.0입니다. 실제 적용된 온도는 응답의 `metadata.temperature`로 확인합니다.
|
| 71 |
|
| 72 |
+
`--label-scheme {upper,served}` (환경 변수 `JEV_LABEL_SCHEME`)는 선택지가 26개를 넘는 질문의 답 라벨 순서입니다. 기본값 `upper`는 v2.2가 학습한 A–Z 다음 AA, AB, … 순서(한 토큰인 라벨만, 최대 255개)이고, `served`는 v2.2 이전의 A–Z, a–z, 0–9, AA, … 순서입니다. 26개 이하에서는 둘 다 A–Z입니다.
|
| 73 |
+
|
| 74 |
`SGLANG_API_KEY`는 엔진에 보낼 키, `JEV_API_KEY`는 클라이언트가 어댑터에 보낼 키입니다. 설정했다면 각각 `Authorization: Bearer ...` 인증을 사용합니다. 키를 설정하지 않은 어댑터는 인증 없이 동작합니다.
|
| 75 |
|
| 76 |
시작할 때 엔진 정보를 확인하고, 엔진 토크나이저로 라벨을 검증합니다. 엔진을 먼저 실행해야 합니다. 모델/토크나이저를 교체하면 어댑터도 재시작합니다.
|
server/jev_adapter/__main__.py
CHANGED
|
@@ -5,6 +5,8 @@ import logging
|
|
| 5 |
import math
|
| 6 |
import os
|
| 7 |
|
|
|
|
|
|
|
| 8 |
logger = logging.getLogger(__name__)
|
| 9 |
|
| 10 |
|
|
@@ -98,9 +100,25 @@ def main():
|
|
| 98 |
"Ministral default is 531 tokens, about 80%% of a typical request). "
|
| 99 |
"Env: JEV_NATIVE_SYSTEM_PROMPT.",
|
| 100 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 101 |
# argparse runs the type converter on the string default too, so a bad
|
| 102 |
# JEV_DEFAULT_TEMPERATURE fails at startup with the same message.
|
| 103 |
args = parser.parse_args()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
if args.timeout <= 0 or args.max_concurrency < 1:
|
| 105 |
parser.error("timeout and max-concurrency must be positive")
|
| 106 |
if bool(args.tokenizer_model) != bool(args.tokenizer_revision):
|
|
@@ -135,12 +153,13 @@ def main():
|
|
| 135 |
"defines none); serving the native wording text without it."
|
| 136 |
)
|
| 137 |
logger.info(
|
| 138 |
-
"prompt_wording=%s native_system_prompt=%s (%s)",
|
| 139 |
args.prompt_wording,
|
| 140 |
args.native_system_prompt,
|
| 141 |
"system message attached"
|
| 142 |
if native_system_prompt
|
| 143 |
else "no system message attached",
|
|
|
|
| 144 |
)
|
| 145 |
backend = SGLangBackend(
|
| 146 |
args.engine_url,
|
|
@@ -151,6 +170,7 @@ def main():
|
|
| 151 |
native_tokenizer=native_tokenizer,
|
| 152 |
prompt_wording=args.prompt_wording,
|
| 153 |
native_system_prompt=native_system_prompt,
|
|
|
|
| 154 |
)
|
| 155 |
app = create_app(
|
| 156 |
backend,
|
|
|
|
| 5 |
import math
|
| 6 |
import os
|
| 7 |
|
| 8 |
+
from .labels import DEFAULT_LABEL_SCHEME, LABEL_SCHEME_ENV, LABEL_SCHEMES
|
| 9 |
+
|
| 10 |
logger = logging.getLogger(__name__)
|
| 11 |
|
| 12 |
|
|
|
|
| 100 |
"Ministral default is 531 tokens, about 80%% of a typical request). "
|
| 101 |
"Env: JEV_NATIVE_SYSTEM_PROMPT.",
|
| 102 |
)
|
| 103 |
+
parser.add_argument(
|
| 104 |
+
"--label-scheme",
|
| 105 |
+
choices=LABEL_SCHEMES,
|
| 106 |
+
default=os.environ.get(LABEL_SCHEME_ENV) or DEFAULT_LABEL_SCHEME,
|
| 107 |
+
help="Answer labels for questions with more than 26 options. 'upper' "
|
| 108 |
+
"(default): A-Z, then AA, AB, ... (uppercase only; labels that are not "
|
| 109 |
+
"single tokens are skipped). 'served': the original A-Z, a-z, 0-9, "
|
| 110 |
+
"then AA, ... order (pre-v2.2 serving). Both give A-Z to "
|
| 111 |
+
"questions with at most 26 options. Reported in /v1/models and in "
|
| 112 |
+
"response metadata. Env: JEV_LABEL_SCHEME.",
|
| 113 |
+
)
|
| 114 |
# argparse runs the type converter on the string default too, so a bad
|
| 115 |
# JEV_DEFAULT_TEMPERATURE fails at startup with the same message.
|
| 116 |
args = parser.parse_args()
|
| 117 |
+
if args.label_scheme not in LABEL_SCHEMES:
|
| 118 |
+
parser.error(
|
| 119 |
+
f"JEV_LABEL_SCHEME must be one of {', '.join(LABEL_SCHEMES)}; "
|
| 120 |
+
f"got {args.label_scheme!r}"
|
| 121 |
+
)
|
| 122 |
if args.timeout <= 0 or args.max_concurrency < 1:
|
| 123 |
parser.error("timeout and max-concurrency must be positive")
|
| 124 |
if bool(args.tokenizer_model) != bool(args.tokenizer_revision):
|
|
|
|
| 153 |
"defines none); serving the native wording text without it."
|
| 154 |
)
|
| 155 |
logger.info(
|
| 156 |
+
"prompt_wording=%s native_system_prompt=%s (%s) label_scheme=%s",
|
| 157 |
args.prompt_wording,
|
| 158 |
args.native_system_prompt,
|
| 159 |
"system message attached"
|
| 160 |
if native_system_prompt
|
| 161 |
else "no system message attached",
|
| 162 |
+
args.label_scheme,
|
| 163 |
)
|
| 164 |
backend = SGLangBackend(
|
| 165 |
args.engine_url,
|
|
|
|
| 170 |
native_tokenizer=native_tokenizer,
|
| 171 |
prompt_wording=args.prompt_wording,
|
| 172 |
native_system_prompt=native_system_prompt,
|
| 173 |
+
label_scheme=args.label_scheme,
|
| 174 |
)
|
| 175 |
app = create_app(
|
| 176 |
backend,
|
server/jev_adapter/labels.py
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Answer-label schemes shared by serving, readout export, and training data.
|
| 2 |
+
|
| 3 |
+
A scheme is an ordered list of candidate label strings. A model's labels are
|
| 4 |
+
the candidates that its tokenizer encodes as one distinct, non-special token
|
| 5 |
+
which decodes back to exactly the candidate, taken in candidate order, at most
|
| 6 |
+
``MAX_LABELS``. A question with ``n`` options always uses the first ``n``.
|
| 7 |
+
|
| 8 |
+
``upper`` (the default): ``A``..``Z``, then two-letter ``AA``, ``AB``, ...,
|
| 9 |
+
``ZZ``, then three-letter ``AAA``..``ZZZ``; uppercase ASCII only, ordered by
|
| 10 |
+
length and then alphabetically. Three-letter candidates are only consulted
|
| 11 |
+
when the one- and two-letter single tokens number fewer than ``MAX_LABELS``.
|
| 12 |
+
|
| 13 |
+
``served`` (the original order, kept to reproduce pre-v2.2 serving): ``A``..``Z``, ``a``..``z``,
|
| 14 |
+
``0``..``9``, ``000``..``999``, ``AA``..``ZZ``, ``aa``..``zz``. No v2 training
|
| 15 |
+
row had more than 26 options, so beyond Z neither order is what v2 learned.
|
| 16 |
+
|
| 17 |
+
Both schemes give ``A``..``Z`` to questions with at most 26 options whenever
|
| 18 |
+
the tokenizer has those 26 single-token letters.
|
| 19 |
+
"""
|
| 20 |
+
|
| 21 |
+
import itertools
|
| 22 |
+
import os
|
| 23 |
+
import re
|
| 24 |
+
import string
|
| 25 |
+
from collections.abc import Mapping, Sequence
|
| 26 |
+
from typing import Any
|
| 27 |
+
|
| 28 |
+
LABEL_SCHEMES = ("served", "upper")
|
| 29 |
+
DEFAULT_LABEL_SCHEME = "upper"
|
| 30 |
+
LABEL_SCHEME_ENV = "JEV_LABEL_SCHEME"
|
| 31 |
+
MAX_LABELS = 255
|
| 32 |
+
UPPER_MAX_LENGTH = 3
|
| 33 |
+
_UPPER_LABEL = re.compile(r"[A-Z]{1,3}")
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
def validate_label_scheme(value: Any) -> str:
|
| 37 |
+
if value not in LABEL_SCHEMES:
|
| 38 |
+
raise ValueError(
|
| 39 |
+
f"label scheme must be one of {', '.join(LABEL_SCHEMES)}; got {value!r}"
|
| 40 |
+
)
|
| 41 |
+
return value
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
def resolve_label_scheme(
|
| 45 |
+
value: str | None = None, environ: Mapping[str, str] | None = None
|
| 46 |
+
) -> str:
|
| 47 |
+
"""An explicit value, else ``JEV_LABEL_SCHEME``, else the default (upper)."""
|
| 48 |
+
if value is None or value == "":
|
| 49 |
+
environ = os.environ if environ is None else environ
|
| 50 |
+
value = environ.get(LABEL_SCHEME_ENV) or DEFAULT_LABEL_SCHEME
|
| 51 |
+
return validate_label_scheme(value)
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
def _served_candidates() -> tuple[str, ...]:
|
| 55 |
+
letters = string.ascii_uppercase + string.ascii_lowercase + string.digits
|
| 56 |
+
return tuple(
|
| 57 |
+
list(letters)
|
| 58 |
+
+ [f"{value:03d}" for value in range(1000)]
|
| 59 |
+
+ [
|
| 60 |
+
first + second
|
| 61 |
+
for alphabet in (string.ascii_uppercase, string.ascii_lowercase)
|
| 62 |
+
for first in alphabet
|
| 63 |
+
for second in alphabet
|
| 64 |
+
]
|
| 65 |
+
)
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
def _upper_length(length: int) -> tuple[str, ...]:
|
| 69 |
+
return tuple(
|
| 70 |
+
"".join(chars)
|
| 71 |
+
for chars in itertools.product(string.ascii_uppercase, repeat=length)
|
| 72 |
+
)
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
def candidate_tiers(scheme: str) -> tuple[tuple[str, ...], ...]:
|
| 76 |
+
"""Candidates in order, grouped so a caller may stop after an early group.
|
| 77 |
+
|
| 78 |
+
A later group is consulted only while fewer than MAX_LABELS labels were
|
| 79 |
+
found; the concatenated order is the scheme's order either way.
|
| 80 |
+
"""
|
| 81 |
+
validate_label_scheme(scheme)
|
| 82 |
+
if scheme == "served":
|
| 83 |
+
return (_served_candidates(),)
|
| 84 |
+
return (
|
| 85 |
+
_upper_length(1) + _upper_length(2),
|
| 86 |
+
_upper_length(3),
|
| 87 |
+
)
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
def label_candidates(scheme: str) -> list[str]:
|
| 91 |
+
return [label for tier in candidate_tiers(scheme) for label in tier]
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def select_labels(
|
| 95 |
+
tokenizer: Any, scheme: str, *, limit: int = MAX_LABELS
|
| 96 |
+
) -> tuple[list[str], list[int]]:
|
| 97 |
+
"""The scheme's labels for a tokenizer with ``encode`` and ``decode``.
|
| 98 |
+
|
| 99 |
+
A candidate is kept when it encodes (without special tokens) to exactly
|
| 100 |
+
one token that is not special, not already taken, and decodes back to the
|
| 101 |
+
candidate. This is the rule every exporter, backend, and training-data
|
| 102 |
+
writer must share; it needs only the tokenizer files.
|
| 103 |
+
"""
|
| 104 |
+
if type(limit) is not int or not 1 <= limit <= MAX_LABELS:
|
| 105 |
+
raise ValueError(f"limit must be an integer from 1 to {MAX_LABELS}")
|
| 106 |
+
special = set(getattr(tokenizer, "all_special_ids", ()) or ())
|
| 107 |
+
labels: list[str] = []
|
| 108 |
+
token_ids: list[int] = []
|
| 109 |
+
seen: set[int] = set()
|
| 110 |
+
for tier in candidate_tiers(scheme):
|
| 111 |
+
for label in tier:
|
| 112 |
+
ids = tokenizer.encode(label, add_special_tokens=False)
|
| 113 |
+
if not isinstance(ids, list) or len(ids) != 1 or type(ids[0]) is not int:
|
| 114 |
+
continue
|
| 115 |
+
token = ids[0]
|
| 116 |
+
if token < 0 or token in seen or token in special:
|
| 117 |
+
continue
|
| 118 |
+
if tokenizer.decode([token], skip_special_tokens=True) != label:
|
| 119 |
+
continue
|
| 120 |
+
labels.append(label)
|
| 121 |
+
token_ids.append(token)
|
| 122 |
+
seen.add(token)
|
| 123 |
+
if len(labels) == limit:
|
| 124 |
+
return labels, token_ids
|
| 125 |
+
return labels, token_ids
|
| 126 |
+
|
| 127 |
+
|
| 128 |
+
def follows_scheme_order(scheme: str, labels: Sequence[str]) -> bool:
|
| 129 |
+
"""Whether labels are distinct candidates of the scheme in scheme order.
|
| 130 |
+
|
| 131 |
+
A structural check that needs no tokenizer: it cannot tell whether a
|
| 132 |
+
skipped candidate was a single token, only that nothing is out of order.
|
| 133 |
+
"""
|
| 134 |
+
validate_label_scheme(scheme)
|
| 135 |
+
if not labels or any(not isinstance(label, str) for label in labels):
|
| 136 |
+
return False
|
| 137 |
+
if scheme == "upper":
|
| 138 |
+
if any(_UPPER_LABEL.fullmatch(label) is None for label in labels):
|
| 139 |
+
return False
|
| 140 |
+
ranks = [(len(label), label) for label in labels]
|
| 141 |
+
else:
|
| 142 |
+
index = {label: position for position, label in enumerate(_served_candidates())}
|
| 143 |
+
if any(label not in index for label in labels):
|
| 144 |
+
return False
|
| 145 |
+
ranks = [index[label] for label in labels]
|
| 146 |
+
return all(before < after for before, after in itertools.pairwise(ranks))
|
server/jev_adapter/protocol.py
CHANGED
|
@@ -79,6 +79,9 @@ class NoulQuestion(_SystemOneModel):
|
|
| 79 |
@field_validator("criteria")
|
| 80 |
@classmethod
|
| 81 |
def validate_boolean_criteria(cls, criteria):
|
|
|
|
|
|
|
|
|
|
| 82 |
if criteria is not None and set(criteria) != {"true", "false"}:
|
| 83 |
raise ValueError('noul criteria must contain exactly "true" and "false"')
|
| 84 |
return criteria
|
|
|
|
| 79 |
@field_validator("criteria")
|
| 80 |
@classmethod
|
| 81 |
def validate_boolean_criteria(cls, criteria):
|
| 82 |
+
# An empty map means "no descriptions", same as omitting the field.
|
| 83 |
+
if criteria == {}:
|
| 84 |
+
return None
|
| 85 |
if criteria is not None and set(criteria) != {"true", "false"}:
|
| 86 |
raise ValueError('noul criteria must contain exactly "true" and "false"')
|
| 87 |
return criteria
|
server/jev_adapter/server.py
CHANGED
|
@@ -95,6 +95,11 @@ def create_app(
|
|
| 95 |
"id": backend.model,
|
| 96 |
"object": "model",
|
| 97 |
"owned_by": "inference-engine",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 98 |
},
|
| 99 |
],
|
| 100 |
}
|
|
|
|
| 95 |
"id": backend.model,
|
| 96 |
"object": "model",
|
| 97 |
"owned_by": "inference-engine",
|
| 98 |
+
**(
|
| 99 |
+
{"label_scheme": backend.label_scheme}
|
| 100 |
+
if getattr(backend, "label_scheme", None)
|
| 101 |
+
else {}
|
| 102 |
+
),
|
| 103 |
},
|
| 104 |
],
|
| 105 |
}
|
server/jev_adapter/service.py
CHANGED
|
@@ -166,6 +166,11 @@ class SystemOneService:
|
|
| 166 |
else {}
|
| 167 |
),
|
| 168 |
"evaluations": len(jobs),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
"adapter_elapsed_ms": (time.perf_counter() - started) * 1000,
|
| 170 |
},
|
| 171 |
}
|
|
|
|
| 166 |
else {}
|
| 167 |
),
|
| 168 |
"evaluations": len(jobs),
|
| 169 |
+
**(
|
| 170 |
+
{"label_scheme": self.backend.label_scheme}
|
| 171 |
+
if getattr(self.backend, "label_scheme", None)
|
| 172 |
+
else {}
|
| 173 |
+
),
|
| 174 |
"adapter_elapsed_ms": (time.perf_counter() - started) * 1000,
|
| 175 |
},
|
| 176 |
}
|
server/jev_adapter/sglang.py
CHANGED
|
@@ -7,27 +7,18 @@ No SGLang, CUDA, or model weights are imported into this process.
|
|
| 7 |
|
| 8 |
import asyncio
|
| 9 |
import math
|
| 10 |
-
import string
|
| 11 |
import uuid
|
| 12 |
from typing import Any
|
| 13 |
|
| 14 |
import httpx
|
| 15 |
|
| 16 |
from .backend import AdapterError, ScoringResult
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
+ [f"{value:03d}" for value in range(1000)]
|
| 24 |
-
+ [
|
| 25 |
-
first + second
|
| 26 |
-
for alphabet in (string.ascii_uppercase, string.ascii_lowercase)
|
| 27 |
-
for first in alphabet
|
| 28 |
-
for second in alphabet
|
| 29 |
-
]
|
| 30 |
-
)
|
| 31 |
|
| 32 |
|
| 33 |
_IMAGE_MODEL_TYPES = {
|
|
@@ -76,11 +67,14 @@ class SGLangBackend:
|
|
| 76 |
native_tokenizer: Any | None = None,
|
| 77 |
prompt_wording: str = "served",
|
| 78 |
native_system_prompt: str | None = None,
|
|
|
|
| 79 |
):
|
| 80 |
if not math.isfinite(timeout) or timeout <= 0 or max_connections < 1:
|
| 81 |
raise ValueError("timeout and max_connections must be positive")
|
| 82 |
if prompt_wording not in ("served", "native"):
|
| 83 |
raise ValueError('prompt_wording must be "served" or "native"')
|
|
|
|
|
|
|
| 84 |
url = httpx.URL(base_url)
|
| 85 |
if (
|
| 86 |
url.scheme not in ("http", "https")
|
|
@@ -217,61 +211,13 @@ class SGLangBackend:
|
|
| 217 |
if isinstance(arch, str)
|
| 218 |
)
|
| 219 |
)
|
| 220 |
-
candidates = _label_candidates()
|
| 221 |
-
tokenized = await self._request(
|
| 222 |
-
"POST",
|
| 223 |
-
"/v1/tokenize",
|
| 224 |
-
{
|
| 225 |
-
"model": self.model,
|
| 226 |
-
"prompt": candidates,
|
| 227 |
-
"add_special_tokens": False,
|
| 228 |
-
},
|
| 229 |
-
)
|
| 230 |
-
batches = tokenized.get("tokens")
|
| 231 |
-
if (
|
| 232 |
-
not isinstance(batches, list)
|
| 233 |
-
or len(batches) != len(candidates)
|
| 234 |
-
or not all(_token_list(ids) for ids in batches)
|
| 235 |
-
):
|
| 236 |
-
raise _bad_response(
|
| 237 |
-
"The inference engine returned malformed label tokenization."
|
| 238 |
-
)
|
| 239 |
-
singles = [
|
| 240 |
-
(label, ids[0])
|
| 241 |
-
for label, ids in zip(candidates, batches)
|
| 242 |
-
if len(ids) == 1
|
| 243 |
-
]
|
| 244 |
-
if not singles:
|
| 245 |
-
raise AdapterError(
|
| 246 |
-
"labels_unavailable",
|
| 247 |
-
"The tokenizer has no usable single-token labels.",
|
| 248 |
-
)
|
| 249 |
-
decoded = await self._request(
|
| 250 |
-
"POST",
|
| 251 |
-
"/v1/detokenize",
|
| 252 |
-
{
|
| 253 |
-
"model": self.model,
|
| 254 |
-
"tokens": [[token] for _, token in singles],
|
| 255 |
-
"skip_special_tokens": True,
|
| 256 |
-
},
|
| 257 |
-
)
|
| 258 |
-
texts = decoded.get("text")
|
| 259 |
-
if (
|
| 260 |
-
not isinstance(texts, list)
|
| 261 |
-
or len(texts) != len(singles)
|
| 262 |
-
or not all(isinstance(item, str) for item in texts)
|
| 263 |
-
):
|
| 264 |
-
raise _bad_response(
|
| 265 |
-
"The inference engine returned malformed label detokenization."
|
| 266 |
-
)
|
| 267 |
valid: list[tuple[str, int]] = []
|
| 268 |
seen: set[int] = set()
|
| 269 |
-
|
| 270 |
-
|
| 271 |
-
|
| 272 |
-
|
| 273 |
-
|
| 274 |
-
break
|
| 275 |
if len(valid) < 2:
|
| 276 |
raise AdapterError(
|
| 277 |
"labels_unavailable",
|
|
@@ -280,6 +226,58 @@ class SGLangBackend:
|
|
| 280 |
self._label_strings, self._label_ids = tuple(zip(*valid))
|
| 281 |
self._ready = True
|
| 282 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 283 |
async def close(self) -> None:
|
| 284 |
if self._owns_client:
|
| 285 |
await self._client.aclose()
|
|
|
|
| 7 |
|
| 8 |
import asyncio
|
| 9 |
import math
|
|
|
|
| 10 |
import uuid
|
| 11 |
from typing import Any
|
| 12 |
|
| 13 |
import httpx
|
| 14 |
|
| 15 |
from .backend import AdapterError, ScoringResult
|
| 16 |
+
from .labels import (
|
| 17 |
+
DEFAULT_LABEL_SCHEME,
|
| 18 |
+
MAX_LABELS,
|
| 19 |
+
candidate_tiers,
|
| 20 |
+
validate_label_scheme,
|
| 21 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
|
| 23 |
|
| 24 |
_IMAGE_MODEL_TYPES = {
|
|
|
|
| 67 |
native_tokenizer: Any | None = None,
|
| 68 |
prompt_wording: str = "served",
|
| 69 |
native_system_prompt: str | None = None,
|
| 70 |
+
label_scheme: str = DEFAULT_LABEL_SCHEME,
|
| 71 |
):
|
| 72 |
if not math.isfinite(timeout) or timeout <= 0 or max_connections < 1:
|
| 73 |
raise ValueError("timeout and max_connections must be positive")
|
| 74 |
if prompt_wording not in ("served", "native"):
|
| 75 |
raise ValueError('prompt_wording must be "served" or "native"')
|
| 76 |
+
# Which candidate order answer labels come from (jev_adapter.labels).
|
| 77 |
+
self.label_scheme = validate_label_scheme(label_scheme)
|
| 78 |
url = httpx.URL(base_url)
|
| 79 |
if (
|
| 80 |
url.scheme not in ("http", "https")
|
|
|
|
| 211 |
if isinstance(arch, str)
|
| 212 |
)
|
| 213 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 214 |
valid: list[tuple[str, int]] = []
|
| 215 |
seen: set[int] = set()
|
| 216 |
+
# A later candidate group is tokenized only while labels are short.
|
| 217 |
+
for candidates in candidate_tiers(self.label_scheme):
|
| 218 |
+
if len(valid) == MAX_LABELS:
|
| 219 |
+
break
|
| 220 |
+
await self._select_tier(list(candidates), valid, seen)
|
|
|
|
| 221 |
if len(valid) < 2:
|
| 222 |
raise AdapterError(
|
| 223 |
"labels_unavailable",
|
|
|
|
| 226 |
self._label_strings, self._label_ids = tuple(zip(*valid))
|
| 227 |
self._ready = True
|
| 228 |
|
| 229 |
+
async def _select_tier(
|
| 230 |
+
self, candidates: list[str], valid: list[tuple[str, int]], seen: set[int]
|
| 231 |
+
) -> None:
|
| 232 |
+
"""Append this group's reversible single-token labels, in order."""
|
| 233 |
+
tokenized = await self._request(
|
| 234 |
+
"POST",
|
| 235 |
+
"/v1/tokenize",
|
| 236 |
+
{
|
| 237 |
+
"model": self.model,
|
| 238 |
+
"prompt": candidates,
|
| 239 |
+
"add_special_tokens": False,
|
| 240 |
+
},
|
| 241 |
+
)
|
| 242 |
+
batches = tokenized.get("tokens")
|
| 243 |
+
if (
|
| 244 |
+
not isinstance(batches, list)
|
| 245 |
+
or len(batches) != len(candidates)
|
| 246 |
+
or not all(_token_list(ids) for ids in batches)
|
| 247 |
+
):
|
| 248 |
+
raise _bad_response(
|
| 249 |
+
"The inference engine returned malformed label tokenization."
|
| 250 |
+
)
|
| 251 |
+
singles = [
|
| 252 |
+
(label, ids[0]) for label, ids in zip(candidates, batches) if len(ids) == 1
|
| 253 |
+
]
|
| 254 |
+
if not singles:
|
| 255 |
+
return
|
| 256 |
+
decoded = await self._request(
|
| 257 |
+
"POST",
|
| 258 |
+
"/v1/detokenize",
|
| 259 |
+
{
|
| 260 |
+
"model": self.model,
|
| 261 |
+
"tokens": [[token] for _, token in singles],
|
| 262 |
+
"skip_special_tokens": True,
|
| 263 |
+
},
|
| 264 |
+
)
|
| 265 |
+
texts = decoded.get("text")
|
| 266 |
+
if (
|
| 267 |
+
not isinstance(texts, list)
|
| 268 |
+
or len(texts) != len(singles)
|
| 269 |
+
or not all(isinstance(item, str) for item in texts)
|
| 270 |
+
):
|
| 271 |
+
raise _bad_response(
|
| 272 |
+
"The inference engine returned malformed label detokenization."
|
| 273 |
+
)
|
| 274 |
+
for (label, token), decoded_label in zip(singles, texts):
|
| 275 |
+
if label == decoded_label and token not in seen:
|
| 276 |
+
valid.append((label, token))
|
| 277 |
+
seen.add(token)
|
| 278 |
+
if len(valid) == MAX_LABELS:
|
| 279 |
+
return
|
| 280 |
+
|
| 281 |
async def close(self) -> None:
|
| 282 |
if self._owns_client:
|
| 283 |
await self._client.aclose()
|
server/tests/conftest.py
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pytest
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
@pytest.fixture(autouse=True)
|
| 5 |
+
def _no_label_scheme_env(monkeypatch):
|
| 6 |
+
# The label scheme defaults from JEV_LABEL_SCHEME; tests set it explicitly.
|
| 7 |
+
monkeypatch.delenv("JEV_LABEL_SCHEME", raising=False)
|
server/tests/data/ministral3-label-probe.json
ADDED
|
@@ -0,0 +1,1183 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"schema": "jev-tokenizer-probe-v1",
|
| 3 |
+
"note": "Raw tokenizer behaviour on the one- and two-letter uppercase label candidates, recorded with AutoTokenizer at the pinned revision and cross-checked against tekken.json (mistral_common) and the release tokenizer.json. encode = encode(candidate, add_special_tokens=False); decode = decode([id], skip_special_tokens=True) for every single-token id.",
|
| 4 |
+
"tokenizer": {"id": "mistralai/Ministral-3-8B-Instruct-2512-BF16", "revision": "f6fae9795746f63c9be8344932f01275f3c63734", "class": "MistralCommonBackend", "tekken_json_sha256": "600bb27946565481ecf51ba8aee252e49b9a68507866080ac9c30185bb312843", "tokenizer_config_json_sha256": "f59f7294e4f26383d0ea93840fe21cf197784be0842a8301a0343e8c34ed0d6d", "release_tokenizer_json_sha256": "d5f6046775b112f0e2d456ee9dba450684ab964fe5c4e231599bdc6773028135"},
|
| 5 |
+
"special_id_ranges": [[0, 999]],
|
| 6 |
+
"expected_upper": {
|
| 7 |
+
"source": "upper-labels-ministral3.json",
|
| 8 |
+
"source_sha256": "27119a52ee9a0417809c3a50b5b07e77aa723d4a63266d1065ba8ca82589d512",
|
| 9 |
+
"labels": ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA", "AB", "AC", "AD", "AE", "AF", "AG", "AH", "AI", "AK", "AL", "AM", "AN", "AO", "AP", "AR", "AS", "AT", "AU", "AV", "AX", "AY", "AZ", "BA", "BB", "BC", "BD", "BE", "BF", "BG", "BI", "BJ", "BL", "BM", "BN", "BO", "BP", "BR", "BS", "BT", "BU", "BV", "BW", "BY", "CA", "CB", "CC", "CD", "CE", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CP", "CR", "CS", "CT", "CU", "CV", "CX", "CY", "DA", "DB", "DC", "DD", "DE", "DF", "DG", "DH", "DI", "DJ", "DK", "DL", "DM", "DN", "DO", "DP", "DR", "DS", "DT", "DU", "DX", "EA", "EB", "EC", "ED", "EE", "EF", "EG", "EK", "EL", "EM", "EN", "EO", "EP", "EQ", "ER", "ES", "ET", "EU", "EV", "EW", "EX", "FA", "FB", "FC", "FD", "FE", "FF", "FG", "FI", "FK", "FL", "FM", "FN", "FO", "FP", "FR", "FS", "FT", "FW", "FX", "GA", "GB", "GC", "GD", "GE", "GF", "GG", "GH", "GI", "GL", "GM", "GN", "GO", "GP", "GR", "GS", "GT", "GV", "GW", "HA", "HB", "HC", "HD", "HE", "HF", "HG", "HH", "HI", "HK", "HL", "HM", "HO", "HP", "HR", "HS", "HT", "HV", "IA", "IB", "IC", "ID", "IE", "IF", "IG", "II", "IK", "IL", "IM", "IN", "IO", "IP", "IR", "IS", "IT", "IU", "IV", "IX", "IZ", "JA", "JB", "JK", "JO", "JP", "JR", "JS", "KA", "KB", "KC", "KE", "KG", "KM", "KN", "KO", "KR", "KS", "KT", "LA", "LB", "LC", "LD", "LE", "LF", "LG", "LI", "LL", "LM", "LO", "LP", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MB", "MC", "MD", "ME", "MF", "MG", "MH"],
|
| 10 |
+
"token_ids": [1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 14229, 8062, 5193, 5516, 32484, 12763, 6970, 91939, 33613, 26039, 4286, 6758, 5010, 106550, 6292, 3905, 6003, 3313, 117778, 29970, 13339, 25698, 75317, 10574, 28235, 6535, 18704, 34817, 71042, 87478, 17782, 119492, 30631, 20195, 90805, 18412, 22133, 35846, 7814, 54206, 115497, 130196, 114957, 82317, 9467, 43379, 7619, 8584, 9158, 26910, 39176, 7247, 15466, 17131, 8534, 41183, 47271, 9335, 13943, 12540, 13754, 4061, 97829, 34456, 114741, 130282, 10878, 12223, 22561, 27789, 5088, 28562, 92842, 47909, 29951, 52972, 49329, 42559, 28081, 57310, 24151, 16108, 13705, 14249, 46565, 33674, 52885, 26759, 34112, 13275, 7051, 16748, 35971, 17238, 82787, 11213, 15187, 4456, 92580, 20573, 44943, 2794, 5548, 4321, 78963, 66703, 49942, 10164, 6507, 62311, 10858, 61930, 44675, 7762, 63511, 31638, 66480, 15869, 45746, 88826, 15740, 31994, 53744, 21313, 17310, 70351, 75215, 19454, 12737, 16497, 77858, 19527, 10624, 67199, 96633, 74536, 17899, 28533, 123165, 28649, 31714, 32874, 27735, 35985, 109488, 102348, 23303, 68291, 24093, 26205, 7626, 41999, 122632, 79438, 56611, 64447, 46862, 103147, 74873, 13719, 24498, 30316, 8395, 126227, 20501, 16433, 6048, 3084, 20851, 11098, 4351, 3022, 65015, 9387, 10667, 3174, 11364, 9918, 9474, 6673, 4778, 124666, 6217, 10445, 15152, 71794, 124356, 92274, 128992, 72267, 69496, 32452, 39711, 60305, 120387, 12623, 99414, 128745, 49744, 44338, 128762, 110718, 81092, 10265, 72458, 13515, 20008, 3561, 55938, 106747, 34732, 23947, 45623, 7618, 28547, 23356, 18369, 71905, 73275, 51489, 38180, 8900, 21291, 16126, 14534, 5180, 96790, 64937, 91805]
|
| 11 |
+
},
|
| 12 |
+
"encode": {
|
| 13 |
+
"A": [1065],
|
| 14 |
+
"B": [1066],
|
| 15 |
+
"C": [1067],
|
| 16 |
+
"D": [1068],
|
| 17 |
+
"E": [1069],
|
| 18 |
+
"F": [1070],
|
| 19 |
+
"G": [1071],
|
| 20 |
+
"H": [1072],
|
| 21 |
+
"I": [1073],
|
| 22 |
+
"J": [1074],
|
| 23 |
+
"K": [1075],
|
| 24 |
+
"L": [1076],
|
| 25 |
+
"M": [1077],
|
| 26 |
+
"N": [1078],
|
| 27 |
+
"O": [1079],
|
| 28 |
+
"P": [1080],
|
| 29 |
+
"Q": [1081],
|
| 30 |
+
"R": [1082],
|
| 31 |
+
"S": [1083],
|
| 32 |
+
"T": [1084],
|
| 33 |
+
"U": [1085],
|
| 34 |
+
"V": [1086],
|
| 35 |
+
"W": [1087],
|
| 36 |
+
"X": [1088],
|
| 37 |
+
"Y": [1089],
|
| 38 |
+
"Z": [1090],
|
| 39 |
+
"AA": [14229],
|
| 40 |
+
"AB": [8062],
|
| 41 |
+
"AC": [5193],
|
| 42 |
+
"AD": [5516],
|
| 43 |
+
"AE": [32484],
|
| 44 |
+
"AF": [12763],
|
| 45 |
+
"AG": [6970],
|
| 46 |
+
"AH": [91939],
|
| 47 |
+
"AI": [33613],
|
| 48 |
+
"AJ": [1065, 1074],
|
| 49 |
+
"AK": [26039],
|
| 50 |
+
"AL": [4286],
|
| 51 |
+
"AM": [6758],
|
| 52 |
+
"AN": [5010],
|
| 53 |
+
"AO": [106550],
|
| 54 |
+
"AP": [6292],
|
| 55 |
+
"AQ": [1065, 1081],
|
| 56 |
+
"AR": [3905],
|
| 57 |
+
"AS": [6003],
|
| 58 |
+
"AT": [3313],
|
| 59 |
+
"AU": [117778],
|
| 60 |
+
"AV": [29970],
|
| 61 |
+
"AW": [1065, 1087],
|
| 62 |
+
"AX": [13339],
|
| 63 |
+
"AY": [25698],
|
| 64 |
+
"AZ": [75317],
|
| 65 |
+
"BA": [10574],
|
| 66 |
+
"BB": [28235],
|
| 67 |
+
"BC": [6535],
|
| 68 |
+
"BD": [18704],
|
| 69 |
+
"BE": [34817],
|
| 70 |
+
"BF": [71042],
|
| 71 |
+
"BG": [87478],
|
| 72 |
+
"BH": [1066, 1072],
|
| 73 |
+
"BI": [17782],
|
| 74 |
+
"BJ": [119492],
|
| 75 |
+
"BK": [1066, 1075],
|
| 76 |
+
"BL": [30631],
|
| 77 |
+
"BM": [20195],
|
| 78 |
+
"BN": [90805],
|
| 79 |
+
"BO": [18412],
|
| 80 |
+
"BP": [22133],
|
| 81 |
+
"BQ": [1066, 1081],
|
| 82 |
+
"BR": [35846],
|
| 83 |
+
"BS": [7814],
|
| 84 |
+
"BT": [54206],
|
| 85 |
+
"BU": [115497],
|
| 86 |
+
"BV": [130196],
|
| 87 |
+
"BW": [114957],
|
| 88 |
+
"BX": [1066, 1088],
|
| 89 |
+
"BY": [82317],
|
| 90 |
+
"BZ": [1066, 1090],
|
| 91 |
+
"CA": [9467],
|
| 92 |
+
"CB": [43379],
|
| 93 |
+
"CC": [7619],
|
| 94 |
+
"CD": [8584],
|
| 95 |
+
"CE": [9158],
|
| 96 |
+
"CF": [26910],
|
| 97 |
+
"CG": [39176],
|
| 98 |
+
"CH": [7247],
|
| 99 |
+
"CI": [15466],
|
| 100 |
+
"CJ": [1067, 1074],
|
| 101 |
+
"CK": [17131],
|
| 102 |
+
"CL": [8534],
|
| 103 |
+
"CM": [41183],
|
| 104 |
+
"CN": [47271],
|
| 105 |
+
"CO": [9335],
|
| 106 |
+
"CP": [13943],
|
| 107 |
+
"CQ": [1067, 1081],
|
| 108 |
+
"CR": [12540],
|
| 109 |
+
"CS": [13754],
|
| 110 |
+
"CT": [4061],
|
| 111 |
+
"CU": [97829],
|
| 112 |
+
"CV": [34456],
|
| 113 |
+
"CW": [1067, 1087],
|
| 114 |
+
"CX": [114741],
|
| 115 |
+
"CY": [130282],
|
| 116 |
+
"CZ": [1067, 1090],
|
| 117 |
+
"DA": [10878],
|
| 118 |
+
"DB": [12223],
|
| 119 |
+
"DC": [22561],
|
| 120 |
+
"DD": [27789],
|
| 121 |
+
"DE": [5088],
|
| 122 |
+
"DF": [28562],
|
| 123 |
+
"DG": [92842],
|
| 124 |
+
"DH": [47909],
|
| 125 |
+
"DI": [29951],
|
| 126 |
+
"DJ": [52972],
|
| 127 |
+
"DK": [49329],
|
| 128 |
+
"DL": [42559],
|
| 129 |
+
"DM": [28081],
|
| 130 |
+
"DN": [57310],
|
| 131 |
+
"DO": [24151],
|
| 132 |
+
"DP": [16108],
|
| 133 |
+
"DQ": [1068, 1081],
|
| 134 |
+
"DR": [13705],
|
| 135 |
+
"DS": [14249],
|
| 136 |
+
"DT": [46565],
|
| 137 |
+
"DU": [33674],
|
| 138 |
+
"DV": [1068, 1086],
|
| 139 |
+
"DW": [1068, 1087],
|
| 140 |
+
"DX": [52885],
|
| 141 |
+
"DY": [1068, 1089],
|
| 142 |
+
"DZ": [1068, 1090],
|
| 143 |
+
"EA": [26759],
|
| 144 |
+
"EB": [34112],
|
| 145 |
+
"EC": [13275],
|
| 146 |
+
"ED": [7051],
|
| 147 |
+
"EE": [16748],
|
| 148 |
+
"EF": [35971],
|
| 149 |
+
"EG": [17238],
|
| 150 |
+
"EH": [1069, 1072],
|
| 151 |
+
"EI": [1069, 1073],
|
| 152 |
+
"EJ": [1069, 1074],
|
| 153 |
+
"EK": [82787],
|
| 154 |
+
"EL": [11213],
|
| 155 |
+
"EM": [15187],
|
| 156 |
+
"EN": [4456],
|
| 157 |
+
"EO": [92580],
|
| 158 |
+
"EP": [20573],
|
| 159 |
+
"EQ": [44943],
|
| 160 |
+
"ER": [2794],
|
| 161 |
+
"ES": [5548],
|
| 162 |
+
"ET": [4321],
|
| 163 |
+
"EU": [78963],
|
| 164 |
+
"EV": [66703],
|
| 165 |
+
"EW": [49942],
|
| 166 |
+
"EX": [10164],
|
| 167 |
+
"EY": [1069, 1089],
|
| 168 |
+
"EZ": [1069, 1090],
|
| 169 |
+
"FA": [6507],
|
| 170 |
+
"FB": [62311],
|
| 171 |
+
"FC": [10858],
|
| 172 |
+
"FD": [61930],
|
| 173 |
+
"FE": [44675],
|
| 174 |
+
"FF": [7762],
|
| 175 |
+
"FG": [63511],
|
| 176 |
+
"FH": [1070, 1072],
|
| 177 |
+
"FI": [31638],
|
| 178 |
+
"FJ": [1070, 1074],
|
| 179 |
+
"FK": [66480],
|
| 180 |
+
"FL": [15869],
|
| 181 |
+
"FM": [45746],
|
| 182 |
+
"FN": [88826],
|
| 183 |
+
"FO": [15740],
|
| 184 |
+
"FP": [31994],
|
| 185 |
+
"FQ": [1070, 1081],
|
| 186 |
+
"FR": [53744],
|
| 187 |
+
"FS": [21313],
|
| 188 |
+
"FT": [17310],
|
| 189 |
+
"FU": [1070, 1085],
|
| 190 |
+
"FV": [1070, 1086],
|
| 191 |
+
"FW": [70351],
|
| 192 |
+
"FX": [75215],
|
| 193 |
+
"FY": [1070, 1089],
|
| 194 |
+
"FZ": [1070, 1090],
|
| 195 |
+
"GA": [19454],
|
| 196 |
+
"GB": [12737],
|
| 197 |
+
"GC": [16497],
|
| 198 |
+
"GD": [77858],
|
| 199 |
+
"GE": [19527],
|
| 200 |
+
"GF": [10624],
|
| 201 |
+
"GG": [67199],
|
| 202 |
+
"GH": [96633],
|
| 203 |
+
"GI": [74536],
|
| 204 |
+
"GJ": [1071, 1074],
|
| 205 |
+
"GK": [1071, 1075],
|
| 206 |
+
"GL": [17899],
|
| 207 |
+
"GM": [28533],
|
| 208 |
+
"GN": [123165],
|
| 209 |
+
"GO": [28649],
|
| 210 |
+
"GP": [31714],
|
| 211 |
+
"GQ": [1071, 1081],
|
| 212 |
+
"GR": [32874],
|
| 213 |
+
"GS": [27735],
|
| 214 |
+
"GT": [35985],
|
| 215 |
+
"GU": [1071, 1085],
|
| 216 |
+
"GV": [109488],
|
| 217 |
+
"GW": [102348],
|
| 218 |
+
"GX": [1071, 1088],
|
| 219 |
+
"GY": [1071, 1089],
|
| 220 |
+
"GZ": [1071, 1090],
|
| 221 |
+
"HA": [23303],
|
| 222 |
+
"HB": [68291],
|
| 223 |
+
"HC": [24093],
|
| 224 |
+
"HD": [26205],
|
| 225 |
+
"HE": [7626],
|
| 226 |
+
"HF": [41999],
|
| 227 |
+
"HG": [122632],
|
| 228 |
+
"HH": [79438],
|
| 229 |
+
"HI": [56611],
|
| 230 |
+
"HJ": [1072, 1074],
|
| 231 |
+
"HK": [64447],
|
| 232 |
+
"HL": [46862],
|
| 233 |
+
"HM": [103147],
|
| 234 |
+
"HN": [1072, 1078],
|
| 235 |
+
"HO": [74873],
|
| 236 |
+
"HP": [13719],
|
| 237 |
+
"HQ": [1072, 1081],
|
| 238 |
+
"HR": [24498],
|
| 239 |
+
"HS": [30316],
|
| 240 |
+
"HT": [8395],
|
| 241 |
+
"HU": [1072, 1085],
|
| 242 |
+
"HV": [126227],
|
| 243 |
+
"HW": [1072, 1087],
|
| 244 |
+
"HX": [1072, 1088],
|
| 245 |
+
"HY": [1072, 1089],
|
| 246 |
+
"HZ": [1072, 1090],
|
| 247 |
+
"IA": [20501],
|
| 248 |
+
"IB": [16433],
|
| 249 |
+
"IC": [6048],
|
| 250 |
+
"ID": [3084],
|
| 251 |
+
"IE": [20851],
|
| 252 |
+
"IF": [11098],
|
| 253 |
+
"IG": [4351],
|
| 254 |
+
"IH": [1073, 1072],
|
| 255 |
+
"II": [3022],
|
| 256 |
+
"IJ": [1073, 1074],
|
| 257 |
+
"IK": [65015],
|
| 258 |
+
"IL": [9387],
|
| 259 |
+
"IM": [10667],
|
| 260 |
+
"IN": [3174],
|
| 261 |
+
"IO": [11364],
|
| 262 |
+
"IP": [9918],
|
| 263 |
+
"IQ": [1073, 1081],
|
| 264 |
+
"IR": [9474],
|
| 265 |
+
"IS": [6673],
|
| 266 |
+
"IT": [4778],
|
| 267 |
+
"IU": [124666],
|
| 268 |
+
"IV": [6217],
|
| 269 |
+
"IW": [1073, 1087],
|
| 270 |
+
"IX": [10445],
|
| 271 |
+
"IY": [1073, 1089],
|
| 272 |
+
"IZ": [15152],
|
| 273 |
+
"JA": [71794],
|
| 274 |
+
"JB": [124356],
|
| 275 |
+
"JC": [1074, 1067],
|
| 276 |
+
"JD": [1074, 1068],
|
| 277 |
+
"JE": [1074, 1069],
|
| 278 |
+
"JF": [1074, 1070],
|
| 279 |
+
"JG": [1074, 1071],
|
| 280 |
+
"JH": [1074, 1072],
|
| 281 |
+
"JI": [1074, 1073],
|
| 282 |
+
"JJ": [1074, 1074],
|
| 283 |
+
"JK": [92274],
|
| 284 |
+
"JL": [1074, 1076],
|
| 285 |
+
"JM": [1074, 1077],
|
| 286 |
+
"JN": [1074, 1078],
|
| 287 |
+
"JO": [128992],
|
| 288 |
+
"JP": [72267],
|
| 289 |
+
"JQ": [1074, 1081],
|
| 290 |
+
"JR": [69496],
|
| 291 |
+
"JS": [32452],
|
| 292 |
+
"JT": [1074, 1084],
|
| 293 |
+
"JU": [1074, 1085],
|
| 294 |
+
"JV": [1074, 1086],
|
| 295 |
+
"JW": [1074, 1087],
|
| 296 |
+
"JX": [1074, 1088],
|
| 297 |
+
"JY": [1074, 1089],
|
| 298 |
+
"JZ": [1074, 1090],
|
| 299 |
+
"KA": [39711],
|
| 300 |
+
"KB": [60305],
|
| 301 |
+
"KC": [120387],
|
| 302 |
+
"KD": [1075, 1068],
|
| 303 |
+
"KE": [12623],
|
| 304 |
+
"KF": [1075, 1070],
|
| 305 |
+
"KG": [99414],
|
| 306 |
+
"KH": [1075, 1072],
|
| 307 |
+
"KI": [1075, 1073],
|
| 308 |
+
"KJ": [1075, 1074],
|
| 309 |
+
"KK": [1075, 1075],
|
| 310 |
+
"KL": [1075, 1076],
|
| 311 |
+
"KM": [128745],
|
| 312 |
+
"KN": [49744],
|
| 313 |
+
"KO": [44338],
|
| 314 |
+
"KP": [1075, 1080],
|
| 315 |
+
"KQ": [1075, 1081],
|
| 316 |
+
"KR": [128762],
|
| 317 |
+
"KS": [110718],
|
| 318 |
+
"KT": [81092],
|
| 319 |
+
"KU": [1075, 1085],
|
| 320 |
+
"KV": [1075, 1086],
|
| 321 |
+
"KW": [1075, 1087],
|
| 322 |
+
"KX": [1075, 1088],
|
| 323 |
+
"KY": [1075, 1089],
|
| 324 |
+
"KZ": [1075, 1090],
|
| 325 |
+
"LA": [10265],
|
| 326 |
+
"LB": [72458],
|
| 327 |
+
"LC": [13515],
|
| 328 |
+
"LD": [20008],
|
| 329 |
+
"LE": [3561],
|
| 330 |
+
"LF": [55938],
|
| 331 |
+
"LG": [106747],
|
| 332 |
+
"LH": [1076, 1072],
|
| 333 |
+
"LI": [34732],
|
| 334 |
+
"LJ": [1076, 1074],
|
| 335 |
+
"LK": [1076, 1075],
|
| 336 |
+
"LL": [23947],
|
| 337 |
+
"LM": [45623],
|
| 338 |
+
"LN": [1076, 1078],
|
| 339 |
+
"LO": [7618],
|
| 340 |
+
"LP": [28547],
|
| 341 |
+
"LQ": [1076, 1081],
|
| 342 |
+
"LR": [23356],
|
| 343 |
+
"LS": [18369],
|
| 344 |
+
"LT": [71905],
|
| 345 |
+
"LU": [73275],
|
| 346 |
+
"LV": [51489],
|
| 347 |
+
"LW": [1076, 1087],
|
| 348 |
+
"LX": [1076, 1088],
|
| 349 |
+
"LY": [38180],
|
| 350 |
+
"LZ": [1076, 1090],
|
| 351 |
+
"MA": [8900],
|
| 352 |
+
"MB": [21291],
|
| 353 |
+
"MC": [16126],
|
| 354 |
+
"MD": [14534],
|
| 355 |
+
"ME": [5180],
|
| 356 |
+
"MF": [96790],
|
| 357 |
+
"MG": [64937],
|
| 358 |
+
"MH": [91805],
|
| 359 |
+
"MI": [13460],
|
| 360 |
+
"MJ": [1077, 1074],
|
| 361 |
+
"MK": [67375],
|
| 362 |
+
"ML": [6243],
|
| 363 |
+
"MM": [20451],
|
| 364 |
+
"MN": [113464],
|
| 365 |
+
"MO": [28497],
|
| 366 |
+
"MP": [7690],
|
| 367 |
+
"MQ": [94031],
|
| 368 |
+
"MR": [15755],
|
| 369 |
+
"MS": [7985],
|
| 370 |
+
"MT": [15901],
|
| 371 |
+
"MU": [1077, 1085],
|
| 372 |
+
"MV": [54258],
|
| 373 |
+
"MW": [93272],
|
| 374 |
+
"MX": [115032],
|
| 375 |
+
"MY": [61997],
|
| 376 |
+
"MZ": [1077, 1090],
|
| 377 |
+
"NA": [3251],
|
| 378 |
+
"NB": [46713],
|
| 379 |
+
"NC": [27822],
|
| 380 |
+
"ND": [6999],
|
| 381 |
+
"NE": [29156],
|
| 382 |
+
"NF": [17766],
|
| 383 |
+
"NG": [16705],
|
| 384 |
+
"NH": [19644],
|
| 385 |
+
"NI": [42859],
|
| 386 |
+
"NJ": [1078, 1074],
|
| 387 |
+
"NK": [41360],
|
| 388 |
+
"NL": [70818],
|
| 389 |
+
"NM": [99056],
|
| 390 |
+
"NN": [35756],
|
| 391 |
+
"NO": [16071],
|
| 392 |
+
"NP": [26640],
|
| 393 |
+
"NQ": [1078, 1081],
|
| 394 |
+
"NR": [36995],
|
| 395 |
+
"NS": [8772],
|
| 396 |
+
"NT": [15913],
|
| 397 |
+
"NU": [44113],
|
| 398 |
+
"NV": [63081],
|
| 399 |
+
"NW": [1078, 1087],
|
| 400 |
+
"NX": [1078, 1088],
|
| 401 |
+
"NY": [77192],
|
| 402 |
+
"NZ": [88653],
|
| 403 |
+
"OA": [89987],
|
| 404 |
+
"OB": [53045],
|
| 405 |
+
"OC": [11815],
|
| 406 |
+
"OD": [7460],
|
| 407 |
+
"OE": [55184],
|
| 408 |
+
"OF": [37979],
|
| 409 |
+
"OG": [48368],
|
| 410 |
+
"OH": [16724],
|
| 411 |
+
"OI": [1079, 1073],
|
| 412 |
+
"OJ": [1079, 1074],
|
| 413 |
+
"OK": [13257],
|
| 414 |
+
"OL": [8568],
|
| 415 |
+
"OM": [11135],
|
| 416 |
+
"ON": [2918],
|
| 417 |
+
"OO": [82414],
|
| 418 |
+
"OP": [14748],
|
| 419 |
+
"OQ": [1079, 1081],
|
| 420 |
+
"OR": [3749],
|
| 421 |
+
"OS": [6964],
|
| 422 |
+
"OT": [6918],
|
| 423 |
+
"OU": [32913],
|
| 424 |
+
"OV": [108230],
|
| 425 |
+
"OW": [12381],
|
| 426 |
+
"OX": [60261],
|
| 427 |
+
"OY": [1079, 1089],
|
| 428 |
+
"OZ": [1079, 1090],
|
| 429 |
+
"PA": [12118],
|
| 430 |
+
"PB": [76628],
|
| 431 |
+
"PC": [9793],
|
| 432 |
+
"PD": [9315],
|
| 433 |
+
"PE": [7134],
|
| 434 |
+
"PF": [74287],
|
| 435 |
+
"PG": [54406],
|
| 436 |
+
"PH": [45587],
|
| 437 |
+
"PI": [5119],
|
| 438 |
+
"PJ": [1080, 1074],
|
| 439 |
+
"PK": [47053],
|
| 440 |
+
"PL": [24520],
|
| 441 |
+
"PM": [25285],
|
| 442 |
+
"PN": [28666],
|
| 443 |
+
"PO": [7836],
|
| 444 |
+
"PP": [11388],
|
| 445 |
+
"PQ": [1080, 1081],
|
| 446 |
+
"PR": [17554],
|
| 447 |
+
"PS": [8148],
|
| 448 |
+
"PT": [11130],
|
| 449 |
+
"PU": [81208],
|
| 450 |
+
"PV": [61159],
|
| 451 |
+
"PW": [109996],
|
| 452 |
+
"PX": [1080, 1088],
|
| 453 |
+
"PY": [45242],
|
| 454 |
+
"PZ": [1080, 1090],
|
| 455 |
+
"QA": [1081, 1065],
|
| 456 |
+
"QB": [1081, 1066],
|
| 457 |
+
"QC": [1081, 1067],
|
| 458 |
+
"QD": [1081, 1068],
|
| 459 |
+
"QE": [1081, 1069],
|
| 460 |
+
"QF": [1081, 1070],
|
| 461 |
+
"QG": [1081, 1071],
|
| 462 |
+
"QH": [1081, 1072],
|
| 463 |
+
"QI": [1081, 1073],
|
| 464 |
+
"QJ": [1081, 1074],
|
| 465 |
+
"QK": [1081, 1075],
|
| 466 |
+
"QL": [7972],
|
| 467 |
+
"QM": [1081, 1077],
|
| 468 |
+
"QN": [1081, 1078],
|
| 469 |
+
"QO": [1081, 1079],
|
| 470 |
+
"QP": [1081, 1080],
|
| 471 |
+
"QQ": [1081, 1081],
|
| 472 |
+
"QR": [55582],
|
| 473 |
+
"QS": [1081, 1083],
|
| 474 |
+
"QT": [1081, 1084],
|
| 475 |
+
"QU": [27289],
|
| 476 |
+
"QV": [1081, 1086],
|
| 477 |
+
"QW": [1081, 1087],
|
| 478 |
+
"QX": [1081, 1088],
|
| 479 |
+
"QY": [1081, 1089],
|
| 480 |
+
"QZ": [1081, 1090],
|
| 481 |
+
"RA": [9295],
|
| 482 |
+
"RB": [84165],
|
| 483 |
+
"RC": [22805],
|
| 484 |
+
"RD": [50289],
|
| 485 |
+
"RE": [3609],
|
| 486 |
+
"RF": [43456],
|
| 487 |
+
"RG": [94542],
|
| 488 |
+
"RH": [82104],
|
| 489 |
+
"RI": [8707],
|
| 490 |
+
"RJ": [1082, 1074],
|
| 491 |
+
"RK": [105157],
|
| 492 |
+
"RL": [10397],
|
| 493 |
+
"RM": [72554],
|
| 494 |
+
"RN": [109334],
|
| 495 |
+
"RO": [4755],
|
| 496 |
+
"RP": [40773],
|
| 497 |
+
"RQ": [1082, 1081],
|
| 498 |
+
"RR": [60853],
|
| 499 |
+
"RS": [19693],
|
| 500 |
+
"RT": [19891],
|
| 501 |
+
"RU": [1082, 1085],
|
| 502 |
+
"RV": [101080],
|
| 503 |
+
"RW": [1082, 1087],
|
| 504 |
+
"RX": [130864],
|
| 505 |
+
"RY": [58675],
|
| 506 |
+
"RZ": [1082, 1090],
|
| 507 |
+
"SA": [11941],
|
| 508 |
+
"SB": [5038],
|
| 509 |
+
"SC": [7408],
|
| 510 |
+
"SD": [17173],
|
| 511 |
+
"SE": [3932],
|
| 512 |
+
"SF": [28036],
|
| 513 |
+
"SG": [29834],
|
| 514 |
+
"SH": [18731],
|
| 515 |
+
"SI": [27239],
|
| 516 |
+
"SJ": [1083, 1074],
|
| 517 |
+
"SK": [51753],
|
| 518 |
+
"SL": [27893],
|
| 519 |
+
"SM": [23162],
|
| 520 |
+
"SN": [54061],
|
| 521 |
+
"SO": [19124],
|
| 522 |
+
"SP": [8504],
|
| 523 |
+
"SQ": [1083, 1081],
|
| 524 |
+
"SR": [21967],
|
| 525 |
+
"SS": [4290],
|
| 526 |
+
"ST": [3074],
|
| 527 |
+
"SU": [50885],
|
| 528 |
+
"SV": [24592],
|
| 529 |
+
"SW": [74938],
|
| 530 |
+
"SX": [1083, 1088],
|
| 531 |
+
"SY": [101289],
|
| 532 |
+
"SZ": [1083, 1090],
|
| 533 |
+
"TA": [12887],
|
| 534 |
+
"TB": [64833],
|
| 535 |
+
"TC": [10504],
|
| 536 |
+
"TD": [30975],
|
| 537 |
+
"TE": [9265],
|
| 538 |
+
"TF": [34083],
|
| 539 |
+
"TG": [118593],
|
| 540 |
+
"TH": [12001],
|
| 541 |
+
"TI": [100838],
|
| 542 |
+
"TJ": [1084, 1074],
|
| 543 |
+
"TK": [105765],
|
| 544 |
+
"TL": [35570],
|
| 545 |
+
"TM": [40139],
|
| 546 |
+
"TN": [109975],
|
| 547 |
+
"TO": [9197],
|
| 548 |
+
"TP": [8426],
|
| 549 |
+
"TQ": [1084, 1081],
|
| 550 |
+
"TR": [13404],
|
| 551 |
+
"TS": [9983],
|
| 552 |
+
"TT": [26025],
|
| 553 |
+
"TU": [1084, 1085],
|
| 554 |
+
"TV": [11488],
|
| 555 |
+
"TW": [1084, 1087],
|
| 556 |
+
"TX": [100203],
|
| 557 |
+
"TY": [54462],
|
| 558 |
+
"TZ": [1084, 1090],
|
| 559 |
+
"UA": [69940],
|
| 560 |
+
"UB": [17982],
|
| 561 |
+
"UC": [24859],
|
| 562 |
+
"UD": [23855],
|
| 563 |
+
"UE": [8489],
|
| 564 |
+
"UF": [52359],
|
| 565 |
+
"UG": [17869],
|
| 566 |
+
"UH": [1085, 1072],
|
| 567 |
+
"UI": [8442],
|
| 568 |
+
"UJ": [1085, 1074],
|
| 569 |
+
"UK": [35960],
|
| 570 |
+
"UL": [4614],
|
| 571 |
+
"UM": [11458],
|
| 572 |
+
"UN": [8929],
|
| 573 |
+
"UO": [1085, 1079],
|
| 574 |
+
"UP": [15401],
|
| 575 |
+
"UQ": [1085, 1081],
|
| 576 |
+
"UR": [5553],
|
| 577 |
+
"US": [5507],
|
| 578 |
+
"UT": [5489],
|
| 579 |
+
"UU": [1085, 1085],
|
| 580 |
+
"UV": [34483],
|
| 581 |
+
"UW": [1085, 1087],
|
| 582 |
+
"UX": [82838],
|
| 583 |
+
"UY": [1085, 1089],
|
| 584 |
+
"UZ": [1085, 1090],
|
| 585 |
+
"VA": [15725],
|
| 586 |
+
"VB": [103461],
|
| 587 |
+
"VC": [20500],
|
| 588 |
+
"VD": [10566],
|
| 589 |
+
"VE": [16578],
|
| 590 |
+
"VF": [28198],
|
| 591 |
+
"VG": [122406],
|
| 592 |
+
"VH": [1086, 1072],
|
| 593 |
+
"VI": [31416],
|
| 594 |
+
"VJ": [1086, 1074],
|
| 595 |
+
"VK": [1086, 1075],
|
| 596 |
+
"VL": [1086, 1076],
|
| 597 |
+
"VM": [30569],
|
| 598 |
+
"VN": [98832],
|
| 599 |
+
"VO": [25313],
|
| 600 |
+
"VP": [22580],
|
| 601 |
+
"VQ": [1086, 1081],
|
| 602 |
+
"VR": [56994],
|
| 603 |
+
"VS": [73553],
|
| 604 |
+
"VT": [96527],
|
| 605 |
+
"VU": [1086, 1085],
|
| 606 |
+
"VV": [1086, 1086],
|
| 607 |
+
"VW": [1086, 1087],
|
| 608 |
+
"VX": [1086, 1088],
|
| 609 |
+
"VY": [1086, 1089],
|
| 610 |
+
"VZ": [1086, 1090],
|
| 611 |
+
"WA": [32111],
|
| 612 |
+
"WB": [126602],
|
| 613 |
+
"WC": [61778],
|
| 614 |
+
"WD": [51577],
|
| 615 |
+
"WE": [21147],
|
| 616 |
+
"WF": [81310],
|
| 617 |
+
"WG": [1087, 1071],
|
| 618 |
+
"WH": [25841],
|
| 619 |
+
"WI": [107939],
|
| 620 |
+
"WJ": [1087, 1074],
|
| 621 |
+
"WK": [79469],
|
| 622 |
+
"WL": [130049],
|
| 623 |
+
"WM": [52532],
|
| 624 |
+
"WN": [1087, 1078],
|
| 625 |
+
"WO": [69643],
|
| 626 |
+
"WP": [64557],
|
| 627 |
+
"WQ": [1087, 1081],
|
| 628 |
+
"WR": [44407],
|
| 629 |
+
"WS": [20266],
|
| 630 |
+
"WT": [38315],
|
| 631 |
+
"WU": [1087, 1085],
|
| 632 |
+
"WV": [1087, 1086],
|
| 633 |
+
"WW": [118278],
|
| 634 |
+
"WX": [1087, 1088],
|
| 635 |
+
"WY": [1087, 1089],
|
| 636 |
+
"WZ": [1087, 1090],
|
| 637 |
+
"XA": [1088, 1065],
|
| 638 |
+
"XB": [1088, 1066],
|
| 639 |
+
"XC": [1088, 1067],
|
| 640 |
+
"XD": [1088, 1068],
|
| 641 |
+
"XE": [1088, 1069],
|
| 642 |
+
"XF": [1088, 1070],
|
| 643 |
+
"XG": [1088, 1071],
|
| 644 |
+
"XH": [1088, 1072],
|
| 645 |
+
"XI": [107321],
|
| 646 |
+
"XJ": [1088, 1074],
|
| 647 |
+
"XK": [1088, 1075],
|
| 648 |
+
"XL": [113479],
|
| 649 |
+
"XM": [1088, 1077],
|
| 650 |
+
"XN": [1088, 1078],
|
| 651 |
+
"XO": [1088, 1079],
|
| 652 |
+
"XP": [1088, 1080],
|
| 653 |
+
"XQ": [1088, 1081],
|
| 654 |
+
"XR": [1088, 1082],
|
| 655 |
+
"XS": [1088, 1083],
|
| 656 |
+
"XT": [32225],
|
| 657 |
+
"XU": [1088, 1085],
|
| 658 |
+
"XV": [1088, 1086],
|
| 659 |
+
"XW": [1088, 1087],
|
| 660 |
+
"XX": [18860],
|
| 661 |
+
"XY": [50706],
|
| 662 |
+
"XZ": [1088, 1090],
|
| 663 |
+
"YA": [114400],
|
| 664 |
+
"YB": [1089, 1066],
|
| 665 |
+
"YC": [1089, 1067],
|
| 666 |
+
"YD": [1089, 1068],
|
| 667 |
+
"YE": [1089, 1069],
|
| 668 |
+
"YF": [1089, 1070],
|
| 669 |
+
"YG": [1089, 1071],
|
| 670 |
+
"YH": [1089, 1072],
|
| 671 |
+
"YI": [1089, 1073],
|
| 672 |
+
"YJ": [1089, 1074],
|
| 673 |
+
"YK": [1089, 1075],
|
| 674 |
+
"YL": [1089, 1076],
|
| 675 |
+
"YM": [1089, 1077],
|
| 676 |
+
"YN": [1089, 1078],
|
| 677 |
+
"YO": [45370],
|
| 678 |
+
"YP": [31130],
|
| 679 |
+
"YQ": [1089, 1081],
|
| 680 |
+
"YR": [1089, 1082],
|
| 681 |
+
"YS": [61300],
|
| 682 |
+
"YT": [1089, 1084],
|
| 683 |
+
"YU": [1089, 1085],
|
| 684 |
+
"YV": [1089, 1086],
|
| 685 |
+
"YW": [1089, 1087],
|
| 686 |
+
"YX": [1089, 1088],
|
| 687 |
+
"YY": [28131],
|
| 688 |
+
"YZ": [1089, 1090],
|
| 689 |
+
"ZA": [124622],
|
| 690 |
+
"ZB": [1090, 1066],
|
| 691 |
+
"ZC": [1090, 1067],
|
| 692 |
+
"ZD": [1090, 1068],
|
| 693 |
+
"ZE": [90133],
|
| 694 |
+
"ZF": [1090, 1070],
|
| 695 |
+
"ZG": [1090, 1071],
|
| 696 |
+
"ZH": [1090, 1072],
|
| 697 |
+
"ZI": [1090, 1073],
|
| 698 |
+
"ZJ": [1090, 1074],
|
| 699 |
+
"ZK": [1090, 1075],
|
| 700 |
+
"ZL": [1090, 1076],
|
| 701 |
+
"ZM": [1090, 1077],
|
| 702 |
+
"ZN": [1090, 1078],
|
| 703 |
+
"ZO": [1090, 1079],
|
| 704 |
+
"ZP": [1090, 1080],
|
| 705 |
+
"ZQ": [1090, 1081],
|
| 706 |
+
"ZR": [1090, 1082],
|
| 707 |
+
"ZS": [1090, 1083],
|
| 708 |
+
"ZT": [1090, 1084],
|
| 709 |
+
"ZU": [1090, 1085],
|
| 710 |
+
"ZV": [1090, 1086],
|
| 711 |
+
"ZW": [1090, 1087],
|
| 712 |
+
"ZX": [1090, 1088],
|
| 713 |
+
"ZY": [1090, 1089],
|
| 714 |
+
"ZZ": [105156]
|
| 715 |
+
},
|
| 716 |
+
"decode": {
|
| 717 |
+
"1065": "A",
|
| 718 |
+
"1066": "B",
|
| 719 |
+
"1067": "C",
|
| 720 |
+
"1068": "D",
|
| 721 |
+
"1069": "E",
|
| 722 |
+
"1070": "F",
|
| 723 |
+
"1071": "G",
|
| 724 |
+
"1072": "H",
|
| 725 |
+
"1073": "I",
|
| 726 |
+
"1074": "J",
|
| 727 |
+
"1075": "K",
|
| 728 |
+
"1076": "L",
|
| 729 |
+
"1077": "M",
|
| 730 |
+
"1078": "N",
|
| 731 |
+
"1079": "O",
|
| 732 |
+
"1080": "P",
|
| 733 |
+
"1081": "Q",
|
| 734 |
+
"1082": "R",
|
| 735 |
+
"1083": "S",
|
| 736 |
+
"1084": "T",
|
| 737 |
+
"1085": "U",
|
| 738 |
+
"1086": "V",
|
| 739 |
+
"1087": "W",
|
| 740 |
+
"1088": "X",
|
| 741 |
+
"1089": "Y",
|
| 742 |
+
"1090": "Z",
|
| 743 |
+
"2794": "ER",
|
| 744 |
+
"2918": "ON",
|
| 745 |
+
"3022": "II",
|
| 746 |
+
"3074": "ST",
|
| 747 |
+
"3084": "ID",
|
| 748 |
+
"3174": "IN",
|
| 749 |
+
"3251": "NA",
|
| 750 |
+
"3313": "AT",
|
| 751 |
+
"3561": "LE",
|
| 752 |
+
"3609": "RE",
|
| 753 |
+
"3749": "OR",
|
| 754 |
+
"3905": "AR",
|
| 755 |
+
"3932": "SE",
|
| 756 |
+
"4061": "CT",
|
| 757 |
+
"4286": "AL",
|
| 758 |
+
"4290": "SS",
|
| 759 |
+
"4321": "ET",
|
| 760 |
+
"4351": "IG",
|
| 761 |
+
"4456": "EN",
|
| 762 |
+
"4614": "UL",
|
| 763 |
+
"4755": "RO",
|
| 764 |
+
"4778": "IT",
|
| 765 |
+
"5010": "AN",
|
| 766 |
+
"5038": "SB",
|
| 767 |
+
"5088": "DE",
|
| 768 |
+
"5119": "PI",
|
| 769 |
+
"5180": "ME",
|
| 770 |
+
"5193": "AC",
|
| 771 |
+
"5489": "UT",
|
| 772 |
+
"5507": "US",
|
| 773 |
+
"5516": "AD",
|
| 774 |
+
"5548": "ES",
|
| 775 |
+
"5553": "UR",
|
| 776 |
+
"6003": "AS",
|
| 777 |
+
"6048": "IC",
|
| 778 |
+
"6217": "IV",
|
| 779 |
+
"6243": "ML",
|
| 780 |
+
"6292": "AP",
|
| 781 |
+
"6507": "FA",
|
| 782 |
+
"6535": "BC",
|
| 783 |
+
"6673": "IS",
|
| 784 |
+
"6758": "AM",
|
| 785 |
+
"6918": "OT",
|
| 786 |
+
"6964": "OS",
|
| 787 |
+
"6970": "AG",
|
| 788 |
+
"6999": "ND",
|
| 789 |
+
"7051": "ED",
|
| 790 |
+
"7134": "PE",
|
| 791 |
+
"7247": "CH",
|
| 792 |
+
"7408": "SC",
|
| 793 |
+
"7460": "OD",
|
| 794 |
+
"7618": "LO",
|
| 795 |
+
"7619": "CC",
|
| 796 |
+
"7626": "HE",
|
| 797 |
+
"7690": "MP",
|
| 798 |
+
"7762": "FF",
|
| 799 |
+
"7814": "BS",
|
| 800 |
+
"7836": "PO",
|
| 801 |
+
"7972": "QL",
|
| 802 |
+
"7985": "MS",
|
| 803 |
+
"8062": "AB",
|
| 804 |
+
"8148": "PS",
|
| 805 |
+
"8395": "HT",
|
| 806 |
+
"8426": "TP",
|
| 807 |
+
"8442": "UI",
|
| 808 |
+
"8489": "UE",
|
| 809 |
+
"8504": "SP",
|
| 810 |
+
"8534": "CL",
|
| 811 |
+
"8568": "OL",
|
| 812 |
+
"8584": "CD",
|
| 813 |
+
"8707": "RI",
|
| 814 |
+
"8772": "NS",
|
| 815 |
+
"8900": "MA",
|
| 816 |
+
"8929": "UN",
|
| 817 |
+
"9158": "CE",
|
| 818 |
+
"9197": "TO",
|
| 819 |
+
"9265": "TE",
|
| 820 |
+
"9295": "RA",
|
| 821 |
+
"9315": "PD",
|
| 822 |
+
"9335": "CO",
|
| 823 |
+
"9387": "IL",
|
| 824 |
+
"9467": "CA",
|
| 825 |
+
"9474": "IR",
|
| 826 |
+
"9793": "PC",
|
| 827 |
+
"9918": "IP",
|
| 828 |
+
"9983": "TS",
|
| 829 |
+
"10164": "EX",
|
| 830 |
+
"10265": "LA",
|
| 831 |
+
"10397": "RL",
|
| 832 |
+
"10445": "IX",
|
| 833 |
+
"10504": "TC",
|
| 834 |
+
"10566": "VD",
|
| 835 |
+
"10574": "BA",
|
| 836 |
+
"10624": "GF",
|
| 837 |
+
"10667": "IM",
|
| 838 |
+
"10858": "FC",
|
| 839 |
+
"10878": "DA",
|
| 840 |
+
"11098": "IF",
|
| 841 |
+
"11130": "PT",
|
| 842 |
+
"11135": "OM",
|
| 843 |
+
"11213": "EL",
|
| 844 |
+
"11364": "IO",
|
| 845 |
+
"11388": "PP",
|
| 846 |
+
"11458": "UM",
|
| 847 |
+
"11488": "TV",
|
| 848 |
+
"11815": "OC",
|
| 849 |
+
"11941": "SA",
|
| 850 |
+
"12001": "TH",
|
| 851 |
+
"12118": "PA",
|
| 852 |
+
"12223": "DB",
|
| 853 |
+
"12381": "OW",
|
| 854 |
+
"12540": "CR",
|
| 855 |
+
"12623": "KE",
|
| 856 |
+
"12737": "GB",
|
| 857 |
+
"12763": "AF",
|
| 858 |
+
"12887": "TA",
|
| 859 |
+
"13257": "OK",
|
| 860 |
+
"13275": "EC",
|
| 861 |
+
"13339": "AX",
|
| 862 |
+
"13404": "TR",
|
| 863 |
+
"13460": "MI",
|
| 864 |
+
"13515": "LC",
|
| 865 |
+
"13705": "DR",
|
| 866 |
+
"13719": "HP",
|
| 867 |
+
"13754": "CS",
|
| 868 |
+
"13943": "CP",
|
| 869 |
+
"14229": "AA",
|
| 870 |
+
"14249": "DS",
|
| 871 |
+
"14534": "MD",
|
| 872 |
+
"14748": "OP",
|
| 873 |
+
"15152": "IZ",
|
| 874 |
+
"15187": "EM",
|
| 875 |
+
"15401": "UP",
|
| 876 |
+
"15466": "CI",
|
| 877 |
+
"15725": "VA",
|
| 878 |
+
"15740": "FO",
|
| 879 |
+
"15755": "MR",
|
| 880 |
+
"15869": "FL",
|
| 881 |
+
"15901": "MT",
|
| 882 |
+
"15913": "NT",
|
| 883 |
+
"16071": "NO",
|
| 884 |
+
"16108": "DP",
|
| 885 |
+
"16126": "MC",
|
| 886 |
+
"16433": "IB",
|
| 887 |
+
"16497": "GC",
|
| 888 |
+
"16578": "VE",
|
| 889 |
+
"16705": "NG",
|
| 890 |
+
"16724": "OH",
|
| 891 |
+
"16748": "EE",
|
| 892 |
+
"17131": "CK",
|
| 893 |
+
"17173": "SD",
|
| 894 |
+
"17238": "EG",
|
| 895 |
+
"17310": "FT",
|
| 896 |
+
"17554": "PR",
|
| 897 |
+
"17766": "NF",
|
| 898 |
+
"17782": "BI",
|
| 899 |
+
"17869": "UG",
|
| 900 |
+
"17899": "GL",
|
| 901 |
+
"17982": "UB",
|
| 902 |
+
"18369": "LS",
|
| 903 |
+
"18412": "BO",
|
| 904 |
+
"18704": "BD",
|
| 905 |
+
"18731": "SH",
|
| 906 |
+
"18860": "XX",
|
| 907 |
+
"19124": "SO",
|
| 908 |
+
"19454": "GA",
|
| 909 |
+
"19527": "GE",
|
| 910 |
+
"19644": "NH",
|
| 911 |
+
"19693": "RS",
|
| 912 |
+
"19891": "RT",
|
| 913 |
+
"20008": "LD",
|
| 914 |
+
"20195": "BM",
|
| 915 |
+
"20266": "WS",
|
| 916 |
+
"20451": "MM",
|
| 917 |
+
"20500": "VC",
|
| 918 |
+
"20501": "IA",
|
| 919 |
+
"20573": "EP",
|
| 920 |
+
"20851": "IE",
|
| 921 |
+
"21147": "WE",
|
| 922 |
+
"21291": "MB",
|
| 923 |
+
"21313": "FS",
|
| 924 |
+
"21967": "SR",
|
| 925 |
+
"22133": "BP",
|
| 926 |
+
"22561": "DC",
|
| 927 |
+
"22580": "VP",
|
| 928 |
+
"22805": "RC",
|
| 929 |
+
"23162": "SM",
|
| 930 |
+
"23303": "HA",
|
| 931 |
+
"23356": "LR",
|
| 932 |
+
"23855": "UD",
|
| 933 |
+
"23947": "LL",
|
| 934 |
+
"24093": "HC",
|
| 935 |
+
"24151": "DO",
|
| 936 |
+
"24498": "HR",
|
| 937 |
+
"24520": "PL",
|
| 938 |
+
"24592": "SV",
|
| 939 |
+
"24859": "UC",
|
| 940 |
+
"25285": "PM",
|
| 941 |
+
"25313": "VO",
|
| 942 |
+
"25698": "AY",
|
| 943 |
+
"25841": "WH",
|
| 944 |
+
"26025": "TT",
|
| 945 |
+
"26039": "AK",
|
| 946 |
+
"26205": "HD",
|
| 947 |
+
"26640": "NP",
|
| 948 |
+
"26759": "EA",
|
| 949 |
+
"26910": "CF",
|
| 950 |
+
"27239": "SI",
|
| 951 |
+
"27289": "QU",
|
| 952 |
+
"27735": "GS",
|
| 953 |
+
"27789": "DD",
|
| 954 |
+
"27822": "NC",
|
| 955 |
+
"27893": "SL",
|
| 956 |
+
"28036": "SF",
|
| 957 |
+
"28081": "DM",
|
| 958 |
+
"28131": "YY",
|
| 959 |
+
"28198": "VF",
|
| 960 |
+
"28235": "BB",
|
| 961 |
+
"28497": "MO",
|
| 962 |
+
"28533": "GM",
|
| 963 |
+
"28547": "LP",
|
| 964 |
+
"28562": "DF",
|
| 965 |
+
"28649": "GO",
|
| 966 |
+
"28666": "PN",
|
| 967 |
+
"29156": "NE",
|
| 968 |
+
"29834": "SG",
|
| 969 |
+
"29951": "DI",
|
| 970 |
+
"29970": "AV",
|
| 971 |
+
"30316": "HS",
|
| 972 |
+
"30569": "VM",
|
| 973 |
+
"30631": "BL",
|
| 974 |
+
"30975": "TD",
|
| 975 |
+
"31130": "YP",
|
| 976 |
+
"31416": "VI",
|
| 977 |
+
"31638": "FI",
|
| 978 |
+
"31714": "GP",
|
| 979 |
+
"31994": "FP",
|
| 980 |
+
"32111": "WA",
|
| 981 |
+
"32225": "XT",
|
| 982 |
+
"32452": "JS",
|
| 983 |
+
"32484": "AE",
|
| 984 |
+
"32874": "GR",
|
| 985 |
+
"32913": "OU",
|
| 986 |
+
"33613": "AI",
|
| 987 |
+
"33674": "DU",
|
| 988 |
+
"34083": "TF",
|
| 989 |
+
"34112": "EB",
|
| 990 |
+
"34456": "CV",
|
| 991 |
+
"34483": "UV",
|
| 992 |
+
"34732": "LI",
|
| 993 |
+
"34817": "BE",
|
| 994 |
+
"35570": "TL",
|
| 995 |
+
"35756": "NN",
|
| 996 |
+
"35846": "BR",
|
| 997 |
+
"35960": "UK",
|
| 998 |
+
"35971": "EF",
|
| 999 |
+
"35985": "GT",
|
| 1000 |
+
"36995": "NR",
|
| 1001 |
+
"37979": "OF",
|
| 1002 |
+
"38180": "LY",
|
| 1003 |
+
"38315": "WT",
|
| 1004 |
+
"39176": "CG",
|
| 1005 |
+
"39711": "KA",
|
| 1006 |
+
"40139": "TM",
|
| 1007 |
+
"40773": "RP",
|
| 1008 |
+
"41183": "CM",
|
| 1009 |
+
"41360": "NK",
|
| 1010 |
+
"41999": "HF",
|
| 1011 |
+
"42559": "DL",
|
| 1012 |
+
"42859": "NI",
|
| 1013 |
+
"43379": "CB",
|
| 1014 |
+
"43456": "RF",
|
| 1015 |
+
"44113": "NU",
|
| 1016 |
+
"44338": "KO",
|
| 1017 |
+
"44407": "WR",
|
| 1018 |
+
"44675": "FE",
|
| 1019 |
+
"44943": "EQ",
|
| 1020 |
+
"45242": "PY",
|
| 1021 |
+
"45370": "YO",
|
| 1022 |
+
"45587": "PH",
|
| 1023 |
+
"45623": "LM",
|
| 1024 |
+
"45746": "FM",
|
| 1025 |
+
"46565": "DT",
|
| 1026 |
+
"46713": "NB",
|
| 1027 |
+
"46862": "HL",
|
| 1028 |
+
"47053": "PK",
|
| 1029 |
+
"47271": "CN",
|
| 1030 |
+
"47909": "DH",
|
| 1031 |
+
"48368": "OG",
|
| 1032 |
+
"49329": "DK",
|
| 1033 |
+
"49744": "KN",
|
| 1034 |
+
"49942": "EW",
|
| 1035 |
+
"50289": "RD",
|
| 1036 |
+
"50706": "XY",
|
| 1037 |
+
"50885": "SU",
|
| 1038 |
+
"51489": "LV",
|
| 1039 |
+
"51577": "WD",
|
| 1040 |
+
"51753": "SK",
|
| 1041 |
+
"52359": "UF",
|
| 1042 |
+
"52532": "WM",
|
| 1043 |
+
"52885": "DX",
|
| 1044 |
+
"52972": "DJ",
|
| 1045 |
+
"53045": "OB",
|
| 1046 |
+
"53744": "FR",
|
| 1047 |
+
"54061": "SN",
|
| 1048 |
+
"54206": "BT",
|
| 1049 |
+
"54258": "MV",
|
| 1050 |
+
"54406": "PG",
|
| 1051 |
+
"54462": "TY",
|
| 1052 |
+
"55184": "OE",
|
| 1053 |
+
"55582": "QR",
|
| 1054 |
+
"55938": "LF",
|
| 1055 |
+
"56611": "HI",
|
| 1056 |
+
"56994": "VR",
|
| 1057 |
+
"57310": "DN",
|
| 1058 |
+
"58675": "RY",
|
| 1059 |
+
"60261": "OX",
|
| 1060 |
+
"60305": "KB",
|
| 1061 |
+
"60853": "RR",
|
| 1062 |
+
"61159": "PV",
|
| 1063 |
+
"61300": "YS",
|
| 1064 |
+
"61778": "WC",
|
| 1065 |
+
"61930": "FD",
|
| 1066 |
+
"61997": "MY",
|
| 1067 |
+
"62311": "FB",
|
| 1068 |
+
"63081": "NV",
|
| 1069 |
+
"63511": "FG",
|
| 1070 |
+
"64447": "HK",
|
| 1071 |
+
"64557": "WP",
|
| 1072 |
+
"64833": "TB",
|
| 1073 |
+
"64937": "MG",
|
| 1074 |
+
"65015": "IK",
|
| 1075 |
+
"66480": "FK",
|
| 1076 |
+
"66703": "EV",
|
| 1077 |
+
"67199": "GG",
|
| 1078 |
+
"67375": "MK",
|
| 1079 |
+
"68291": "HB",
|
| 1080 |
+
"69496": "JR",
|
| 1081 |
+
"69643": "WO",
|
| 1082 |
+
"69940": "UA",
|
| 1083 |
+
"70351": "FW",
|
| 1084 |
+
"70818": "NL",
|
| 1085 |
+
"71042": "BF",
|
| 1086 |
+
"71794": "JA",
|
| 1087 |
+
"71905": "LT",
|
| 1088 |
+
"72267": "JP",
|
| 1089 |
+
"72458": "LB",
|
| 1090 |
+
"72554": "RM",
|
| 1091 |
+
"73275": "LU",
|
| 1092 |
+
"73553": "VS",
|
| 1093 |
+
"74287": "PF",
|
| 1094 |
+
"74536": "GI",
|
| 1095 |
+
"74873": "HO",
|
| 1096 |
+
"74938": "SW",
|
| 1097 |
+
"75215": "FX",
|
| 1098 |
+
"75317": "AZ",
|
| 1099 |
+
"76628": "PB",
|
| 1100 |
+
"77192": "NY",
|
| 1101 |
+
"77858": "GD",
|
| 1102 |
+
"78963": "EU",
|
| 1103 |
+
"79438": "HH",
|
| 1104 |
+
"79469": "WK",
|
| 1105 |
+
"81092": "KT",
|
| 1106 |
+
"81208": "PU",
|
| 1107 |
+
"81310": "WF",
|
| 1108 |
+
"82104": "RH",
|
| 1109 |
+
"82317": "BY",
|
| 1110 |
+
"82414": "OO",
|
| 1111 |
+
"82787": "EK",
|
| 1112 |
+
"82838": "UX",
|
| 1113 |
+
"84165": "RB",
|
| 1114 |
+
"87478": "BG",
|
| 1115 |
+
"88653": "NZ",
|
| 1116 |
+
"88826": "FN",
|
| 1117 |
+
"89987": "OA",
|
| 1118 |
+
"90133": "ZE",
|
| 1119 |
+
"90805": "BN",
|
| 1120 |
+
"91805": "MH",
|
| 1121 |
+
"91939": "AH",
|
| 1122 |
+
"92274": "JK",
|
| 1123 |
+
"92580": "EO",
|
| 1124 |
+
"92842": "DG",
|
| 1125 |
+
"93272": "MW",
|
| 1126 |
+
"94031": "MQ",
|
| 1127 |
+
"94542": "RG",
|
| 1128 |
+
"96527": "VT",
|
| 1129 |
+
"96633": "GH",
|
| 1130 |
+
"96790": "MF",
|
| 1131 |
+
"97829": "CU",
|
| 1132 |
+
"98832": "VN",
|
| 1133 |
+
"99056": "NM",
|
| 1134 |
+
"99414": "KG",
|
| 1135 |
+
"100203": "TX",
|
| 1136 |
+
"100838": "TI",
|
| 1137 |
+
"101080": "RV",
|
| 1138 |
+
"101289": "SY",
|
| 1139 |
+
"102348": "GW",
|
| 1140 |
+
"103147": "HM",
|
| 1141 |
+
"103461": "VB",
|
| 1142 |
+
"105156": "ZZ",
|
| 1143 |
+
"105157": "RK",
|
| 1144 |
+
"105765": "TK",
|
| 1145 |
+
"106550": "AO",
|
| 1146 |
+
"106747": "LG",
|
| 1147 |
+
"107321": "XI",
|
| 1148 |
+
"107939": "WI",
|
| 1149 |
+
"108230": "OV",
|
| 1150 |
+
"109334": "RN",
|
| 1151 |
+
"109488": "GV",
|
| 1152 |
+
"109975": "TN",
|
| 1153 |
+
"109996": "PW",
|
| 1154 |
+
"110718": "KS",
|
| 1155 |
+
"113464": "MN",
|
| 1156 |
+
"113479": "XL",
|
| 1157 |
+
"114400": "YA",
|
| 1158 |
+
"114741": "CX",
|
| 1159 |
+
"114957": "BW",
|
| 1160 |
+
"115032": "MX",
|
| 1161 |
+
"115497": "BU",
|
| 1162 |
+
"117778": "AU",
|
| 1163 |
+
"118278": "WW",
|
| 1164 |
+
"118593": "TG",
|
| 1165 |
+
"119492": "BJ",
|
| 1166 |
+
"120387": "KC",
|
| 1167 |
+
"122406": "VG",
|
| 1168 |
+
"122632": "HG",
|
| 1169 |
+
"123165": "GN",
|
| 1170 |
+
"124356": "JB",
|
| 1171 |
+
"124622": "ZA",
|
| 1172 |
+
"124666": "IU",
|
| 1173 |
+
"126227": "HV",
|
| 1174 |
+
"126602": "WB",
|
| 1175 |
+
"128745": "KM",
|
| 1176 |
+
"128762": "KR",
|
| 1177 |
+
"128992": "JO",
|
| 1178 |
+
"130049": "WL",
|
| 1179 |
+
"130196": "BV",
|
| 1180 |
+
"130282": "CY",
|
| 1181 |
+
"130864": "RX"
|
| 1182 |
+
}
|
| 1183 |
+
}
|
server/tests/data/upper-labels-ministral3.json
ADDED
|
@@ -0,0 +1,535 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"schema": "jev-label-list-v1",
|
| 3 |
+
"label_scheme": "upper",
|
| 4 |
+
"tokenizer": {
|
| 5 |
+
"id": "mistralai/Ministral-3-8B-Instruct-2512-BF16",
|
| 6 |
+
"revision": "f6fae9795746f63c9be8344932f01275f3c63734",
|
| 7 |
+
"class": "MistralCommonBackend",
|
| 8 |
+
"tekken_json_sha256": "600bb27946565481ecf51ba8aee252e49b9a68507866080ac9c30185bb312843",
|
| 9 |
+
"tokenizer_config_json_sha256": "f59f7294e4f26383d0ea93840fe21cf197784be0842a8301a0343e8c34ed0d6d",
|
| 10 |
+
"release_tokenizer_json_sha256": "d5f6046775b112f0e2d456ee9dba450684ab964fe5c4e231599bdc6773028135"
|
| 11 |
+
},
|
| 12 |
+
"rule": "Candidates in order: A..Z, then AA..ZZ, then AAA..ZZZ (uppercase ASCII, by length then alphabetically). Keep a candidate when tokenizer.encode(label, add_special_tokens=False) is exactly one token id that is not a special id, not already used, and decode([id], skip_special_tokens=True) == label. Stop at 255. A question with n options (2 <= n <= 255) uses labels[:n] in display order.",
|
| 13 |
+
"single_token_counts": {
|
| 14 |
+
"one_letter": 26,
|
| 15 |
+
"two_letter": 439,
|
| 16 |
+
"three_letter": 425
|
| 17 |
+
},
|
| 18 |
+
"three_letter_used": false,
|
| 19 |
+
"answer_boundary_checked": "all 255 labels continue the native [/INST] chat prompt by exactly their token id",
|
| 20 |
+
"count": 255,
|
| 21 |
+
"labels": [
|
| 22 |
+
"A",
|
| 23 |
+
"B",
|
| 24 |
+
"C",
|
| 25 |
+
"D",
|
| 26 |
+
"E",
|
| 27 |
+
"F",
|
| 28 |
+
"G",
|
| 29 |
+
"H",
|
| 30 |
+
"I",
|
| 31 |
+
"J",
|
| 32 |
+
"K",
|
| 33 |
+
"L",
|
| 34 |
+
"M",
|
| 35 |
+
"N",
|
| 36 |
+
"O",
|
| 37 |
+
"P",
|
| 38 |
+
"Q",
|
| 39 |
+
"R",
|
| 40 |
+
"S",
|
| 41 |
+
"T",
|
| 42 |
+
"U",
|
| 43 |
+
"V",
|
| 44 |
+
"W",
|
| 45 |
+
"X",
|
| 46 |
+
"Y",
|
| 47 |
+
"Z",
|
| 48 |
+
"AA",
|
| 49 |
+
"AB",
|
| 50 |
+
"AC",
|
| 51 |
+
"AD",
|
| 52 |
+
"AE",
|
| 53 |
+
"AF",
|
| 54 |
+
"AG",
|
| 55 |
+
"AH",
|
| 56 |
+
"AI",
|
| 57 |
+
"AK",
|
| 58 |
+
"AL",
|
| 59 |
+
"AM",
|
| 60 |
+
"AN",
|
| 61 |
+
"AO",
|
| 62 |
+
"AP",
|
| 63 |
+
"AR",
|
| 64 |
+
"AS",
|
| 65 |
+
"AT",
|
| 66 |
+
"AU",
|
| 67 |
+
"AV",
|
| 68 |
+
"AX",
|
| 69 |
+
"AY",
|
| 70 |
+
"AZ",
|
| 71 |
+
"BA",
|
| 72 |
+
"BB",
|
| 73 |
+
"BC",
|
| 74 |
+
"BD",
|
| 75 |
+
"BE",
|
| 76 |
+
"BF",
|
| 77 |
+
"BG",
|
| 78 |
+
"BI",
|
| 79 |
+
"BJ",
|
| 80 |
+
"BL",
|
| 81 |
+
"BM",
|
| 82 |
+
"BN",
|
| 83 |
+
"BO",
|
| 84 |
+
"BP",
|
| 85 |
+
"BR",
|
| 86 |
+
"BS",
|
| 87 |
+
"BT",
|
| 88 |
+
"BU",
|
| 89 |
+
"BV",
|
| 90 |
+
"BW",
|
| 91 |
+
"BY",
|
| 92 |
+
"CA",
|
| 93 |
+
"CB",
|
| 94 |
+
"CC",
|
| 95 |
+
"CD",
|
| 96 |
+
"CE",
|
| 97 |
+
"CF",
|
| 98 |
+
"CG",
|
| 99 |
+
"CH",
|
| 100 |
+
"CI",
|
| 101 |
+
"CK",
|
| 102 |
+
"CL",
|
| 103 |
+
"CM",
|
| 104 |
+
"CN",
|
| 105 |
+
"CO",
|
| 106 |
+
"CP",
|
| 107 |
+
"CR",
|
| 108 |
+
"CS",
|
| 109 |
+
"CT",
|
| 110 |
+
"CU",
|
| 111 |
+
"CV",
|
| 112 |
+
"CX",
|
| 113 |
+
"CY",
|
| 114 |
+
"DA",
|
| 115 |
+
"DB",
|
| 116 |
+
"DC",
|
| 117 |
+
"DD",
|
| 118 |
+
"DE",
|
| 119 |
+
"DF",
|
| 120 |
+
"DG",
|
| 121 |
+
"DH",
|
| 122 |
+
"DI",
|
| 123 |
+
"DJ",
|
| 124 |
+
"DK",
|
| 125 |
+
"DL",
|
| 126 |
+
"DM",
|
| 127 |
+
"DN",
|
| 128 |
+
"DO",
|
| 129 |
+
"DP",
|
| 130 |
+
"DR",
|
| 131 |
+
"DS",
|
| 132 |
+
"DT",
|
| 133 |
+
"DU",
|
| 134 |
+
"DX",
|
| 135 |
+
"EA",
|
| 136 |
+
"EB",
|
| 137 |
+
"EC",
|
| 138 |
+
"ED",
|
| 139 |
+
"EE",
|
| 140 |
+
"EF",
|
| 141 |
+
"EG",
|
| 142 |
+
"EK",
|
| 143 |
+
"EL",
|
| 144 |
+
"EM",
|
| 145 |
+
"EN",
|
| 146 |
+
"EO",
|
| 147 |
+
"EP",
|
| 148 |
+
"EQ",
|
| 149 |
+
"ER",
|
| 150 |
+
"ES",
|
| 151 |
+
"ET",
|
| 152 |
+
"EU",
|
| 153 |
+
"EV",
|
| 154 |
+
"EW",
|
| 155 |
+
"EX",
|
| 156 |
+
"FA",
|
| 157 |
+
"FB",
|
| 158 |
+
"FC",
|
| 159 |
+
"FD",
|
| 160 |
+
"FE",
|
| 161 |
+
"FF",
|
| 162 |
+
"FG",
|
| 163 |
+
"FI",
|
| 164 |
+
"FK",
|
| 165 |
+
"FL",
|
| 166 |
+
"FM",
|
| 167 |
+
"FN",
|
| 168 |
+
"FO",
|
| 169 |
+
"FP",
|
| 170 |
+
"FR",
|
| 171 |
+
"FS",
|
| 172 |
+
"FT",
|
| 173 |
+
"FW",
|
| 174 |
+
"FX",
|
| 175 |
+
"GA",
|
| 176 |
+
"GB",
|
| 177 |
+
"GC",
|
| 178 |
+
"GD",
|
| 179 |
+
"GE",
|
| 180 |
+
"GF",
|
| 181 |
+
"GG",
|
| 182 |
+
"GH",
|
| 183 |
+
"GI",
|
| 184 |
+
"GL",
|
| 185 |
+
"GM",
|
| 186 |
+
"GN",
|
| 187 |
+
"GO",
|
| 188 |
+
"GP",
|
| 189 |
+
"GR",
|
| 190 |
+
"GS",
|
| 191 |
+
"GT",
|
| 192 |
+
"GV",
|
| 193 |
+
"GW",
|
| 194 |
+
"HA",
|
| 195 |
+
"HB",
|
| 196 |
+
"HC",
|
| 197 |
+
"HD",
|
| 198 |
+
"HE",
|
| 199 |
+
"HF",
|
| 200 |
+
"HG",
|
| 201 |
+
"HH",
|
| 202 |
+
"HI",
|
| 203 |
+
"HK",
|
| 204 |
+
"HL",
|
| 205 |
+
"HM",
|
| 206 |
+
"HO",
|
| 207 |
+
"HP",
|
| 208 |
+
"HR",
|
| 209 |
+
"HS",
|
| 210 |
+
"HT",
|
| 211 |
+
"HV",
|
| 212 |
+
"IA",
|
| 213 |
+
"IB",
|
| 214 |
+
"IC",
|
| 215 |
+
"ID",
|
| 216 |
+
"IE",
|
| 217 |
+
"IF",
|
| 218 |
+
"IG",
|
| 219 |
+
"II",
|
| 220 |
+
"IK",
|
| 221 |
+
"IL",
|
| 222 |
+
"IM",
|
| 223 |
+
"IN",
|
| 224 |
+
"IO",
|
| 225 |
+
"IP",
|
| 226 |
+
"IR",
|
| 227 |
+
"IS",
|
| 228 |
+
"IT",
|
| 229 |
+
"IU",
|
| 230 |
+
"IV",
|
| 231 |
+
"IX",
|
| 232 |
+
"IZ",
|
| 233 |
+
"JA",
|
| 234 |
+
"JB",
|
| 235 |
+
"JK",
|
| 236 |
+
"JO",
|
| 237 |
+
"JP",
|
| 238 |
+
"JR",
|
| 239 |
+
"JS",
|
| 240 |
+
"KA",
|
| 241 |
+
"KB",
|
| 242 |
+
"KC",
|
| 243 |
+
"KE",
|
| 244 |
+
"KG",
|
| 245 |
+
"KM",
|
| 246 |
+
"KN",
|
| 247 |
+
"KO",
|
| 248 |
+
"KR",
|
| 249 |
+
"KS",
|
| 250 |
+
"KT",
|
| 251 |
+
"LA",
|
| 252 |
+
"LB",
|
| 253 |
+
"LC",
|
| 254 |
+
"LD",
|
| 255 |
+
"LE",
|
| 256 |
+
"LF",
|
| 257 |
+
"LG",
|
| 258 |
+
"LI",
|
| 259 |
+
"LL",
|
| 260 |
+
"LM",
|
| 261 |
+
"LO",
|
| 262 |
+
"LP",
|
| 263 |
+
"LR",
|
| 264 |
+
"LS",
|
| 265 |
+
"LT",
|
| 266 |
+
"LU",
|
| 267 |
+
"LV",
|
| 268 |
+
"LY",
|
| 269 |
+
"MA",
|
| 270 |
+
"MB",
|
| 271 |
+
"MC",
|
| 272 |
+
"MD",
|
| 273 |
+
"ME",
|
| 274 |
+
"MF",
|
| 275 |
+
"MG",
|
| 276 |
+
"MH"
|
| 277 |
+
],
|
| 278 |
+
"token_ids": [
|
| 279 |
+
1065,
|
| 280 |
+
1066,
|
| 281 |
+
1067,
|
| 282 |
+
1068,
|
| 283 |
+
1069,
|
| 284 |
+
1070,
|
| 285 |
+
1071,
|
| 286 |
+
1072,
|
| 287 |
+
1073,
|
| 288 |
+
1074,
|
| 289 |
+
1075,
|
| 290 |
+
1076,
|
| 291 |
+
1077,
|
| 292 |
+
1078,
|
| 293 |
+
1079,
|
| 294 |
+
1080,
|
| 295 |
+
1081,
|
| 296 |
+
1082,
|
| 297 |
+
1083,
|
| 298 |
+
1084,
|
| 299 |
+
1085,
|
| 300 |
+
1086,
|
| 301 |
+
1087,
|
| 302 |
+
1088,
|
| 303 |
+
1089,
|
| 304 |
+
1090,
|
| 305 |
+
14229,
|
| 306 |
+
8062,
|
| 307 |
+
5193,
|
| 308 |
+
5516,
|
| 309 |
+
32484,
|
| 310 |
+
12763,
|
| 311 |
+
6970,
|
| 312 |
+
91939,
|
| 313 |
+
33613,
|
| 314 |
+
26039,
|
| 315 |
+
4286,
|
| 316 |
+
6758,
|
| 317 |
+
5010,
|
| 318 |
+
106550,
|
| 319 |
+
6292,
|
| 320 |
+
3905,
|
| 321 |
+
6003,
|
| 322 |
+
3313,
|
| 323 |
+
117778,
|
| 324 |
+
29970,
|
| 325 |
+
13339,
|
| 326 |
+
25698,
|
| 327 |
+
75317,
|
| 328 |
+
10574,
|
| 329 |
+
28235,
|
| 330 |
+
6535,
|
| 331 |
+
18704,
|
| 332 |
+
34817,
|
| 333 |
+
71042,
|
| 334 |
+
87478,
|
| 335 |
+
17782,
|
| 336 |
+
119492,
|
| 337 |
+
30631,
|
| 338 |
+
20195,
|
| 339 |
+
90805,
|
| 340 |
+
18412,
|
| 341 |
+
22133,
|
| 342 |
+
35846,
|
| 343 |
+
7814,
|
| 344 |
+
54206,
|
| 345 |
+
115497,
|
| 346 |
+
130196,
|
| 347 |
+
114957,
|
| 348 |
+
82317,
|
| 349 |
+
9467,
|
| 350 |
+
43379,
|
| 351 |
+
7619,
|
| 352 |
+
8584,
|
| 353 |
+
9158,
|
| 354 |
+
26910,
|
| 355 |
+
39176,
|
| 356 |
+
7247,
|
| 357 |
+
15466,
|
| 358 |
+
17131,
|
| 359 |
+
8534,
|
| 360 |
+
41183,
|
| 361 |
+
47271,
|
| 362 |
+
9335,
|
| 363 |
+
13943,
|
| 364 |
+
12540,
|
| 365 |
+
13754,
|
| 366 |
+
4061,
|
| 367 |
+
97829,
|
| 368 |
+
34456,
|
| 369 |
+
114741,
|
| 370 |
+
130282,
|
| 371 |
+
10878,
|
| 372 |
+
12223,
|
| 373 |
+
22561,
|
| 374 |
+
27789,
|
| 375 |
+
5088,
|
| 376 |
+
28562,
|
| 377 |
+
92842,
|
| 378 |
+
47909,
|
| 379 |
+
29951,
|
| 380 |
+
52972,
|
| 381 |
+
49329,
|
| 382 |
+
42559,
|
| 383 |
+
28081,
|
| 384 |
+
57310,
|
| 385 |
+
24151,
|
| 386 |
+
16108,
|
| 387 |
+
13705,
|
| 388 |
+
14249,
|
| 389 |
+
46565,
|
| 390 |
+
33674,
|
| 391 |
+
52885,
|
| 392 |
+
26759,
|
| 393 |
+
34112,
|
| 394 |
+
13275,
|
| 395 |
+
7051,
|
| 396 |
+
16748,
|
| 397 |
+
35971,
|
| 398 |
+
17238,
|
| 399 |
+
82787,
|
| 400 |
+
11213,
|
| 401 |
+
15187,
|
| 402 |
+
4456,
|
| 403 |
+
92580,
|
| 404 |
+
20573,
|
| 405 |
+
44943,
|
| 406 |
+
2794,
|
| 407 |
+
5548,
|
| 408 |
+
4321,
|
| 409 |
+
78963,
|
| 410 |
+
66703,
|
| 411 |
+
49942,
|
| 412 |
+
10164,
|
| 413 |
+
6507,
|
| 414 |
+
62311,
|
| 415 |
+
10858,
|
| 416 |
+
61930,
|
| 417 |
+
44675,
|
| 418 |
+
7762,
|
| 419 |
+
63511,
|
| 420 |
+
31638,
|
| 421 |
+
66480,
|
| 422 |
+
15869,
|
| 423 |
+
45746,
|
| 424 |
+
88826,
|
| 425 |
+
15740,
|
| 426 |
+
31994,
|
| 427 |
+
53744,
|
| 428 |
+
21313,
|
| 429 |
+
17310,
|
| 430 |
+
70351,
|
| 431 |
+
75215,
|
| 432 |
+
19454,
|
| 433 |
+
12737,
|
| 434 |
+
16497,
|
| 435 |
+
77858,
|
| 436 |
+
19527,
|
| 437 |
+
10624,
|
| 438 |
+
67199,
|
| 439 |
+
96633,
|
| 440 |
+
74536,
|
| 441 |
+
17899,
|
| 442 |
+
28533,
|
| 443 |
+
123165,
|
| 444 |
+
28649,
|
| 445 |
+
31714,
|
| 446 |
+
32874,
|
| 447 |
+
27735,
|
| 448 |
+
35985,
|
| 449 |
+
109488,
|
| 450 |
+
102348,
|
| 451 |
+
23303,
|
| 452 |
+
68291,
|
| 453 |
+
24093,
|
| 454 |
+
26205,
|
| 455 |
+
7626,
|
| 456 |
+
41999,
|
| 457 |
+
122632,
|
| 458 |
+
79438,
|
| 459 |
+
56611,
|
| 460 |
+
64447,
|
| 461 |
+
46862,
|
| 462 |
+
103147,
|
| 463 |
+
74873,
|
| 464 |
+
13719,
|
| 465 |
+
24498,
|
| 466 |
+
30316,
|
| 467 |
+
8395,
|
| 468 |
+
126227,
|
| 469 |
+
20501,
|
| 470 |
+
16433,
|
| 471 |
+
6048,
|
| 472 |
+
3084,
|
| 473 |
+
20851,
|
| 474 |
+
11098,
|
| 475 |
+
4351,
|
| 476 |
+
3022,
|
| 477 |
+
65015,
|
| 478 |
+
9387,
|
| 479 |
+
10667,
|
| 480 |
+
3174,
|
| 481 |
+
11364,
|
| 482 |
+
9918,
|
| 483 |
+
9474,
|
| 484 |
+
6673,
|
| 485 |
+
4778,
|
| 486 |
+
124666,
|
| 487 |
+
6217,
|
| 488 |
+
10445,
|
| 489 |
+
15152,
|
| 490 |
+
71794,
|
| 491 |
+
124356,
|
| 492 |
+
92274,
|
| 493 |
+
128992,
|
| 494 |
+
72267,
|
| 495 |
+
69496,
|
| 496 |
+
32452,
|
| 497 |
+
39711,
|
| 498 |
+
60305,
|
| 499 |
+
120387,
|
| 500 |
+
12623,
|
| 501 |
+
99414,
|
| 502 |
+
128745,
|
| 503 |
+
49744,
|
| 504 |
+
44338,
|
| 505 |
+
128762,
|
| 506 |
+
110718,
|
| 507 |
+
81092,
|
| 508 |
+
10265,
|
| 509 |
+
72458,
|
| 510 |
+
13515,
|
| 511 |
+
20008,
|
| 512 |
+
3561,
|
| 513 |
+
55938,
|
| 514 |
+
106747,
|
| 515 |
+
34732,
|
| 516 |
+
23947,
|
| 517 |
+
45623,
|
| 518 |
+
7618,
|
| 519 |
+
28547,
|
| 520 |
+
23356,
|
| 521 |
+
18369,
|
| 522 |
+
71905,
|
| 523 |
+
73275,
|
| 524 |
+
51489,
|
| 525 |
+
38180,
|
| 526 |
+
8900,
|
| 527 |
+
21291,
|
| 528 |
+
16126,
|
| 529 |
+
14534,
|
| 530 |
+
5180,
|
| 531 |
+
96790,
|
| 532 |
+
64937,
|
| 533 |
+
91805
|
| 534 |
+
]
|
| 535 |
+
}
|
server/tests/test_labels.py
ADDED
|
@@ -0,0 +1,406 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Answer-label schemes: exact lists, the <=26 guarantee, and end-to-end mapping."""
|
| 2 |
+
|
| 3 |
+
import hashlib
|
| 4 |
+
import json
|
| 5 |
+
import re
|
| 6 |
+
import string
|
| 7 |
+
from pathlib import Path
|
| 8 |
+
|
| 9 |
+
import httpx
|
| 10 |
+
import pytest
|
| 11 |
+
|
| 12 |
+
from jev_adapter.labels import (
|
| 13 |
+
DEFAULT_LABEL_SCHEME,
|
| 14 |
+
MAX_LABELS,
|
| 15 |
+
follows_scheme_order,
|
| 16 |
+
label_candidates,
|
| 17 |
+
resolve_label_scheme,
|
| 18 |
+
select_labels,
|
| 19 |
+
)
|
| 20 |
+
from jev_adapter.server import create_app
|
| 21 |
+
from jev_adapter.sglang import SGLangBackend
|
| 22 |
+
|
| 23 |
+
GOLDEN_PATH = Path(__file__).parent / "data" / "upper-labels-ministral3.json"
|
| 24 |
+
GOLDEN = json.loads(GOLDEN_PATH.read_text())
|
| 25 |
+
UPPER = GOLDEN["labels"]
|
| 26 |
+
COUNTS = (2, 26, 27, 77, 151, 255)
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
class VocabularyTokenizer:
|
| 30 |
+
"""Every character is one token; listed multi-letter strings are one token.
|
| 31 |
+
|
| 32 |
+
With the golden vocabulary this has exactly the pinned Ministral-3
|
| 33 |
+
single-token pattern for the upper labels (e.g. AJ and AQ are split).
|
| 34 |
+
"""
|
| 35 |
+
|
| 36 |
+
all_special_ids = (0,)
|
| 37 |
+
|
| 38 |
+
def __init__(self, words):
|
| 39 |
+
self.word_ids = {word: 100_000 + index for index, word in enumerate(words)}
|
| 40 |
+
self.words = {token: word for word, token in self.word_ids.items()}
|
| 41 |
+
|
| 42 |
+
def encode(self, text, add_special_tokens=False):
|
| 43 |
+
ids, position = [], 0
|
| 44 |
+
while position < len(text):
|
| 45 |
+
for length in (3, 2):
|
| 46 |
+
piece = text[position : position + length]
|
| 47 |
+
if len(piece) == length and piece in self.word_ids:
|
| 48 |
+
ids.append(self.word_ids[piece])
|
| 49 |
+
position += length
|
| 50 |
+
break
|
| 51 |
+
else:
|
| 52 |
+
ids.append(ord(text[position]) + 1000)
|
| 53 |
+
position += 1
|
| 54 |
+
return ids
|
| 55 |
+
|
| 56 |
+
def decode(self, ids, skip_special_tokens=True):
|
| 57 |
+
return "".join(
|
| 58 |
+
self.words[token] if token in self.words else chr(token - 1000)
|
| 59 |
+
for token in ids
|
| 60 |
+
)
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
def ministral_like():
|
| 64 |
+
return VocabularyTokenizer([label for label in UPPER if len(label) > 1])
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def test_default_and_resolution():
|
| 68 |
+
assert DEFAULT_LABEL_SCHEME == "upper"
|
| 69 |
+
assert resolve_label_scheme(environ={}) == "upper"
|
| 70 |
+
assert resolve_label_scheme(environ={"JEV_LABEL_SCHEME": "served"}) == "served"
|
| 71 |
+
assert resolve_label_scheme("upper", {"JEV_LABEL_SCHEME": "served"}) == "upper"
|
| 72 |
+
assert resolve_label_scheme("", {"JEV_LABEL_SCHEME": ""}) == "upper"
|
| 73 |
+
for bad in ("lower", "UPPER", 3):
|
| 74 |
+
with pytest.raises(ValueError, match="label scheme"):
|
| 75 |
+
resolve_label_scheme(bad, {})
|
| 76 |
+
with pytest.raises(ValueError, match="label scheme"):
|
| 77 |
+
resolve_label_scheme(None, {"JEV_LABEL_SCHEME": "lower"})
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
def test_candidate_orders():
|
| 81 |
+
upper = label_candidates("upper")
|
| 82 |
+
assert upper[:28] == [*string.ascii_uppercase, "AA", "AB"]
|
| 83 |
+
assert upper[26 + 675] == "ZZ" and upper[26 + 676] == "AAA"
|
| 84 |
+
assert upper[-1] == "ZZZ" and len(upper) == 26 + 26**2 + 26**3
|
| 85 |
+
assert all(re.fullmatch(r"[A-Z]{1,3}", label) for label in upper)
|
| 86 |
+
served = label_candidates("served")
|
| 87 |
+
# The served order is unchanged from before the scheme option existed.
|
| 88 |
+
assert served[:62] == list(
|
| 89 |
+
string.ascii_uppercase + string.ascii_lowercase + string.digits
|
| 90 |
+
)
|
| 91 |
+
assert served[62:64] == ["000", "001"] and served[1062:1064] == ["AA", "AB"]
|
| 92 |
+
assert served[-1] == "zz" and len(served) == 62 + 1000 + 2 * 26**2
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
@pytest.mark.parametrize("count", COUNTS)
|
| 96 |
+
def test_upper_lists_for_each_option_count(count):
|
| 97 |
+
labels, token_ids = select_labels(ministral_like(), "upper", limit=count)
|
| 98 |
+
assert labels == UPPER[:count]
|
| 99 |
+
assert len(set(labels)) == len(set(token_ids)) == count
|
| 100 |
+
assert all(re.fullmatch(r"[A-Z]{1,2}", label) for label in labels)
|
| 101 |
+
assert labels[: min(count, 26)] == list(string.ascii_uppercase[:count])
|
| 102 |
+
if count > 26:
|
| 103 |
+
assert labels[26:29] == ["AA", "AB", "AC"][: count - 26]
|
| 104 |
+
# AJ, AQ and AW are not single Ministral-3 tokens, so they are skipped.
|
| 105 |
+
assert not {"AJ", "AQ", "AW"} & set(labels)
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
def test_exact_boundary_labels():
|
| 109 |
+
labels, _ = select_labels(ministral_like(), "upper")
|
| 110 |
+
assert len(labels) == MAX_LABELS
|
| 111 |
+
assert labels[26] == "AA"
|
| 112 |
+
assert labels[76] == "CG" # the 77th label: the last of BANKING77's options
|
| 113 |
+
assert labels[150] == "FT" # the 151st: the last of CLINC150 with oos
|
| 114 |
+
assert labels[254] == "MH"
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
@pytest.mark.parametrize("count", range(2, 27))
|
| 118 |
+
def test_at_most_26_options_keep_a_to_z_in_both_schemes(count):
|
| 119 |
+
tokenizer = ministral_like()
|
| 120 |
+
upper = select_labels(tokenizer, "upper", limit=count)
|
| 121 |
+
served = select_labels(tokenizer, "served", limit=count)
|
| 122 |
+
assert upper == served
|
| 123 |
+
assert upper[0] == list(string.ascii_uppercase[:count])
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
def test_served_scheme_still_uses_lowercase_after_z():
|
| 127 |
+
labels, _ = select_labels(ministral_like(), "served")
|
| 128 |
+
assert labels[26:30] == ["a", "b", "c", "d"]
|
| 129 |
+
assert labels[52:62] == list(string.digits)
|
| 130 |
+
assert labels[62] == "AA"
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
@pytest.mark.parametrize("count", COUNTS)
|
| 134 |
+
def test_label_index_round_trip(count):
|
| 135 |
+
labels, token_ids = select_labels(ministral_like(), "upper", limit=count)
|
| 136 |
+
index = {label: position for position, label in enumerate(labels)}
|
| 137 |
+
token_index = {token: position for position, token in enumerate(token_ids)}
|
| 138 |
+
assert len(index) == len(token_index) == count
|
| 139 |
+
for position, (label, token) in enumerate(zip(labels, token_ids)):
|
| 140 |
+
assert index[label] == token_index[token] == position
|
| 141 |
+
assert labels[index[label]] == label
|
| 142 |
+
# Every label is also a prefix-free answer at the list level: a longer label
|
| 143 |
+
# is one token, never the token of a shorter label followed by another.
|
| 144 |
+
tokenizer = ministral_like()
|
| 145 |
+
assert all(
|
| 146 |
+
tokenizer.encode(label) == [token] for label, token in zip(labels, token_ids)
|
| 147 |
+
)
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
def test_three_letter_continuation_when_two_letters_run_out():
|
| 151 |
+
# Only AA..AJ are two-letter tokens; the list continues with AAA, AAB, ...
|
| 152 |
+
two = [f"A{letter}" for letter in "ABCDEFGHIJ"]
|
| 153 |
+
three = ["AAA", "AAB", "ABA", "ZZZ"]
|
| 154 |
+
tokenizer = VocabularyTokenizer(two + three)
|
| 155 |
+
labels, _ = select_labels(tokenizer, "upper")
|
| 156 |
+
assert labels == list(string.ascii_uppercase) + two + three
|
| 157 |
+
|
| 158 |
+
|
| 159 |
+
def test_special_duplicate_and_lossy_tokens_are_skipped():
|
| 160 |
+
class Tricky(VocabularyTokenizer):
|
| 161 |
+
all_special_ids = (ord("B") + 1000,)
|
| 162 |
+
|
| 163 |
+
def decode(self, ids, skip_special_tokens=True):
|
| 164 |
+
text = super().decode(ids, skip_special_tokens)
|
| 165 |
+
return "ab" if text == "AB" else text
|
| 166 |
+
|
| 167 |
+
def encode(self, text, add_special_tokens=False):
|
| 168 |
+
return [ord("C") + 1000] if text == "AC" else super().encode(text)
|
| 169 |
+
|
| 170 |
+
labels, _ = select_labels(Tricky(["AA", "AB", "AC", "AD"]), "upper")
|
| 171 |
+
assert labels[:3] == ["A", "C", "D"] and "B" not in labels
|
| 172 |
+
assert labels[25:] == ["AA", "AD"]
|
| 173 |
+
|
| 174 |
+
|
| 175 |
+
def test_scheme_order_check():
|
| 176 |
+
assert follows_scheme_order("upper", ["A", "B", "AA", "AB", "MH", "AAA"])
|
| 177 |
+
assert not follows_scheme_order("upper", ["A", "a"])
|
| 178 |
+
assert not follows_scheme_order("upper", ["B", "A"])
|
| 179 |
+
assert not follows_scheme_order("upper", ["AA", "Z"])
|
| 180 |
+
assert follows_scheme_order("served", ["A", "Z", "a", "0", "AA", "aa"])
|
| 181 |
+
assert not follows_scheme_order("served", ["a", "A"])
|
| 182 |
+
assert not follows_scheme_order("served", ["A", "AAA"])
|
| 183 |
+
|
| 184 |
+
|
| 185 |
+
def test_pinned_ministral3_tokenizer_matches_the_golden_list():
|
| 186 |
+
transformers = pytest.importorskip("transformers")
|
| 187 |
+
tokenizer_info = GOLDEN["tokenizer"]
|
| 188 |
+
try:
|
| 189 |
+
tokenizer = transformers.AutoTokenizer.from_pretrained(
|
| 190 |
+
tokenizer_info["id"],
|
| 191 |
+
revision=tokenizer_info["revision"],
|
| 192 |
+
local_files_only=True,
|
| 193 |
+
)
|
| 194 |
+
except Exception: # noqa: BLE001 - absent from this machine's HF cache
|
| 195 |
+
pytest.skip("pinned Ministral-3 tokenizer is not cached locally")
|
| 196 |
+
labels, token_ids = select_labels(tokenizer, "upper")
|
| 197 |
+
assert labels == GOLDEN["labels"]
|
| 198 |
+
assert token_ids == GOLDEN["token_ids"]
|
| 199 |
+
# The recorded probe below is what this tokenizer really does.
|
| 200 |
+
for candidate, ids in PROBE["encode"].items():
|
| 201 |
+
assert tokenizer.encode(candidate, add_special_tokens=False) == ids
|
| 202 |
+
for token, text in PROBE["decode"].items():
|
| 203 |
+
assert tokenizer.decode([int(token)], skip_special_tokens=True) == text
|
| 204 |
+
assert set(tokenizer.all_special_ids) <= ProbeTokenizer().all_special_ids
|
| 205 |
+
from jev_adapter.native_tokenizer import NativeTokenizer
|
| 206 |
+
|
| 207 |
+
# Every label continues the native chat prompt by exactly its token.
|
| 208 |
+
NativeTokenizer(tokenizer).prepare("Choose.", tuple(labels), tuple(token_ids), None)
|
| 209 |
+
|
| 210 |
+
|
| 211 |
+
# Raw encode/decode results of the pinned Ministral-3 tokenizer for every one-
|
| 212 |
+
# and two-letter uppercase candidate, recorded on the GPU host with
|
| 213 |
+
# AutoTokenizer and cross-checked against tekken.json (mistral_common) and the
|
| 214 |
+
# release tokenizer.json. Unlike ministral_like(), which is built from the
|
| 215 |
+
# golden list, this table is tokenizer data only, so the tests below check the
|
| 216 |
+
# selection rule against the real tokenizer on every CI run.
|
| 217 |
+
PROBE_PATH = Path(__file__).parent / "data" / "ministral3-label-probe.json"
|
| 218 |
+
PROBE = json.loads(PROBE_PATH.read_text())
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
class ProbeTokenizer:
|
| 222 |
+
"""Replays the recorded tokenizer; a string outside the table is an error."""
|
| 223 |
+
|
| 224 |
+
def __init__(self):
|
| 225 |
+
self.all_special_ids = {
|
| 226 |
+
token
|
| 227 |
+
for first, last in PROBE["special_id_ranges"]
|
| 228 |
+
for token in range(first, last + 1)
|
| 229 |
+
}
|
| 230 |
+
|
| 231 |
+
def encode(self, text, add_special_tokens=False):
|
| 232 |
+
assert add_special_tokens is False
|
| 233 |
+
return list(PROBE["encode"][text])
|
| 234 |
+
|
| 235 |
+
def decode(self, ids, skip_special_tokens=True):
|
| 236 |
+
assert skip_special_tokens is True
|
| 237 |
+
return "".join(PROBE["decode"][str(token)] for token in ids)
|
| 238 |
+
|
| 239 |
+
|
| 240 |
+
def test_probe_records_the_golden_lists_tokenizer():
|
| 241 |
+
assert PROBE["schema"] == "jev-tokenizer-probe-v1"
|
| 242 |
+
assert PROBE["tokenizer"] == GOLDEN["tokenizer"]
|
| 243 |
+
expected = PROBE["expected_upper"]
|
| 244 |
+
assert expected["labels"] == GOLDEN["labels"]
|
| 245 |
+
assert expected["token_ids"] == GOLDEN["token_ids"]
|
| 246 |
+
assert expected["source_sha256"] == hashlib.sha256(
|
| 247 |
+
GOLDEN_PATH.read_bytes()
|
| 248 |
+
).hexdigest()
|
| 249 |
+
candidates = [*string.ascii_uppercase] + [
|
| 250 |
+
first + second
|
| 251 |
+
for first in string.ascii_uppercase
|
| 252 |
+
for second in string.ascii_uppercase
|
| 253 |
+
]
|
| 254 |
+
assert list(PROBE["encode"]) == candidates
|
| 255 |
+
singles = [label for label, ids in PROBE["encode"].items() if len(ids) == 1]
|
| 256 |
+
counts = GOLDEN["single_token_counts"]
|
| 257 |
+
assert sum(len(label) == 1 for label in singles) == counts["one_letter"] == 26
|
| 258 |
+
assert sum(len(label) == 2 for label in singles) == counts["two_letter"] == 439
|
| 259 |
+
|
| 260 |
+
|
| 261 |
+
def test_rule_on_the_recorded_ministral3_tokenizer_gives_the_golden_list():
|
| 262 |
+
# Three-letter candidates are absent from the table, so consulting one
|
| 263 |
+
# would raise: 255 labels must come from one and two letters.
|
| 264 |
+
labels, token_ids = select_labels(ProbeTokenizer(), "upper")
|
| 265 |
+
assert labels == GOLDEN["labels"]
|
| 266 |
+
assert token_ids == GOLDEN["token_ids"]
|
| 267 |
+
for count in COUNTS:
|
| 268 |
+
assert select_labels(ProbeTokenizer(), "upper", limit=count) == (
|
| 269 |
+
GOLDEN["labels"][:count],
|
| 270 |
+
GOLDEN["token_ids"][:count],
|
| 271 |
+
)
|
| 272 |
+
|
| 273 |
+
|
| 274 |
+
@pytest.mark.asyncio
|
| 275 |
+
async def test_http_backend_picks_the_golden_list_from_the_recorded_tokenizer():
|
| 276 |
+
engine = LabelEngine(ProbeTokenizer(), "A")
|
| 277 |
+
async with httpx.AsyncClient(transport=httpx.MockTransport(engine)) as upstream:
|
| 278 |
+
backend = SGLangBackend(
|
| 279 |
+
"http://engine", "standard-one", client=upstream, label_scheme="upper"
|
| 280 |
+
)
|
| 281 |
+
await backend.start()
|
| 282 |
+
try:
|
| 283 |
+
for count in COUNTS:
|
| 284 |
+
assert backend.labels(count) == (
|
| 285 |
+
tuple(GOLDEN["labels"][:count]),
|
| 286 |
+
tuple(GOLDEN["token_ids"][:count]),
|
| 287 |
+
)
|
| 288 |
+
finally:
|
| 289 |
+
await backend.close()
|
| 290 |
+
|
| 291 |
+
|
| 292 |
+
class LabelEngine:
|
| 293 |
+
"""A remote engine whose tokenizer has two-letter tokens and prefers one label."""
|
| 294 |
+
|
| 295 |
+
def __init__(self, tokenizer, preferred):
|
| 296 |
+
self.tokenizer = tokenizer
|
| 297 |
+
self.preferred = preferred
|
| 298 |
+
self.prompts = []
|
| 299 |
+
|
| 300 |
+
def __call__(self, request):
|
| 301 |
+
body = json.loads(request.content) if request.content else None
|
| 302 |
+
path = request.url.path
|
| 303 |
+
if path == "/model_info":
|
| 304 |
+
return httpx.Response(
|
| 305 |
+
200,
|
| 306 |
+
json={
|
| 307 |
+
"served_model_name": "standard-one",
|
| 308 |
+
"model_path": "org/standard-one",
|
| 309 |
+
"is_generation": True,
|
| 310 |
+
},
|
| 311 |
+
)
|
| 312 |
+
if path == "/server_info":
|
| 313 |
+
return httpx.Response(200, json={"speculative_algorithm": None})
|
| 314 |
+
encode = self.tokenizer.encode
|
| 315 |
+
if path == "/v1/tokenize":
|
| 316 |
+
if "messages" in body:
|
| 317 |
+
content = body["messages"][-1]["content"]
|
| 318 |
+
self.prompts.append(content)
|
| 319 |
+
return httpx.Response(
|
| 320 |
+
200, json={"tokens": encode(f"<u>{content}</u><a>")}
|
| 321 |
+
)
|
| 322 |
+
return httpx.Response(
|
| 323 |
+
200, json={"tokens": [encode(text) for text in body["prompt"]]}
|
| 324 |
+
)
|
| 325 |
+
if path == "/v1/detokenize":
|
| 326 |
+
tokens = body["tokens"]
|
| 327 |
+
decode = self.tokenizer.decode
|
| 328 |
+
text = (
|
| 329 |
+
[decode(ids) for ids in tokens]
|
| 330 |
+
if isinstance(tokens[0], list)
|
| 331 |
+
else decode(tokens)
|
| 332 |
+
)
|
| 333 |
+
return httpx.Response(200, json={"text": text})
|
| 334 |
+
if path == "/generate":
|
| 335 |
+
preferred = encode(self.preferred)[0]
|
| 336 |
+
entries = [
|
| 337 |
+
[-0.1 if token == preferred else -9.0, token, None]
|
| 338 |
+
for token in body["token_ids_logprob"]
|
| 339 |
+
]
|
| 340 |
+
return httpx.Response(
|
| 341 |
+
200,
|
| 342 |
+
json={
|
| 343 |
+
"meta_info": {
|
| 344 |
+
"completion_tokens": 0,
|
| 345 |
+
"prompt_tokens": len(body["input_ids"]),
|
| 346 |
+
"cached_tokens": 0,
|
| 347 |
+
"output_token_ids_logprobs": [entries],
|
| 348 |
+
}
|
| 349 |
+
},
|
| 350 |
+
)
|
| 351 |
+
raise AssertionError(path)
|
| 352 |
+
|
| 353 |
+
|
| 354 |
+
@pytest.mark.asyncio
|
| 355 |
+
@pytest.mark.parametrize(
|
| 356 |
+
"scheme,count,preferred,expected_option",
|
| 357 |
+
[
|
| 358 |
+
("upper", 77, "CG", 76),
|
| 359 |
+
("upper", 77, "AA", 26),
|
| 360 |
+
("upper", 151, "FT", 150),
|
| 361 |
+
("upper", 26, "Z", 25),
|
| 362 |
+
("served", 77, "a", 26),
|
| 363 |
+
("served", 26, "Z", 25),
|
| 364 |
+
],
|
| 365 |
+
)
|
| 366 |
+
async def test_label_maps_to_its_option_through_the_http_stack(
|
| 367 |
+
scheme, count, preferred, expected_option
|
| 368 |
+
):
|
| 369 |
+
engine = LabelEngine(ministral_like(), preferred)
|
| 370 |
+
async with httpx.AsyncClient(transport=httpx.MockTransport(engine)) as upstream:
|
| 371 |
+
backend = SGLangBackend(
|
| 372 |
+
"http://engine", "standard-one", client=upstream, label_scheme=scheme
|
| 373 |
+
)
|
| 374 |
+
app = create_app(backend)
|
| 375 |
+
async with (
|
| 376 |
+
app.router.lifespan_context(app),
|
| 377 |
+
httpx.AsyncClient(
|
| 378 |
+
transport=httpx.ASGITransport(app), base_url="http://adapter"
|
| 379 |
+
) as client,
|
| 380 |
+
):
|
| 381 |
+
models = (await client.get("/v1/models")).json()
|
| 382 |
+
assert models["data"][0]["label_scheme"] == scheme
|
| 383 |
+
options = {f"intent-{index}": None for index in range(count)}
|
| 384 |
+
response = await client.post(
|
| 385 |
+
"/v1/systemone",
|
| 386 |
+
json={
|
| 387 |
+
"model": "standard-one",
|
| 388 |
+
"state": "I lost my card.",
|
| 389 |
+
"questions": {
|
| 390 |
+
"intent": {
|
| 391 |
+
"type": "choice",
|
| 392 |
+
"instructions": "Which intent?",
|
| 393 |
+
"criteria": options,
|
| 394 |
+
}
|
| 395 |
+
},
|
| 396 |
+
},
|
| 397 |
+
)
|
| 398 |
+
assert response.status_code == 200, response.text
|
| 399 |
+
result = response.json()
|
| 400 |
+
assert result["metadata"]["label_scheme"] == scheme
|
| 401 |
+
assert result["answers"]["intent"]["choice"] == f"intent-{expected_option}"
|
| 402 |
+
lines = engine.prompts[-1].split("Options:\n")[1].splitlines()
|
| 403 |
+
labels = [line.split(":", 1)[0] for line in lines]
|
| 404 |
+
expected, _ = select_labels(ministral_like(), scheme, limit=count)
|
| 405 |
+
assert labels == expected
|
| 406 |
+
assert lines[expected_option] == f"{preferred}: intent-{expected_option}"
|
server/tests/test_main.py
CHANGED
|
@@ -44,6 +44,7 @@ def run_main(monkeypatch, argv, env=None):
|
|
| 44 |
"JEV_PROMPT_WORDING",
|
| 45 |
"JEV_DEFAULT_TEMPERATURE",
|
| 46 |
"JEV_NATIVE_SYSTEM_PROMPT",
|
|
|
|
| 47 |
):
|
| 48 |
monkeypatch.delenv(key, raising=False)
|
| 49 |
for key, value in (env or {}).items():
|
|
@@ -366,3 +367,34 @@ def test_native_system_prompt_startup_log_line(monkeypatch, capture, caplog):
|
|
| 366 |
message = info_records[0].getMessage()
|
| 367 |
assert "prompt_wording=native" in message
|
| 368 |
assert "native_system_prompt=none" in message
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
"JEV_PROMPT_WORDING",
|
| 45 |
"JEV_DEFAULT_TEMPERATURE",
|
| 46 |
"JEV_NATIVE_SYSTEM_PROMPT",
|
| 47 |
+
"JEV_LABEL_SCHEME",
|
| 48 |
):
|
| 49 |
monkeypatch.delenv(key, raising=False)
|
| 50 |
for key, value in (env or {}).items():
|
|
|
|
| 367 |
message = info_records[0].getMessage()
|
| 368 |
assert "prompt_wording=native" in message
|
| 369 |
assert "native_system_prompt=none" in message
|
| 370 |
+
assert "label_scheme=upper" in message
|
| 371 |
+
|
| 372 |
+
|
| 373 |
+
def test_label_scheme_defaults_to_upper(monkeypatch, capture):
|
| 374 |
+
run_main(monkeypatch, ["--model", "decision-model"])
|
| 375 |
+
assert capture.backend_kwargs["label_scheme"] == "upper"
|
| 376 |
+
|
| 377 |
+
|
| 378 |
+
def test_label_scheme_flag_and_env_var(monkeypatch, capture):
|
| 379 |
+
run_main(monkeypatch, ["--model", "m"], env={"JEV_LABEL_SCHEME": "served"})
|
| 380 |
+
assert capture.backend_kwargs["label_scheme"] == "served"
|
| 381 |
+
run_main(
|
| 382 |
+
monkeypatch,
|
| 383 |
+
["--model", "m", "--label-scheme", "upper"],
|
| 384 |
+
env={"JEV_LABEL_SCHEME": "served"},
|
| 385 |
+
)
|
| 386 |
+
assert capture.backend_kwargs["label_scheme"] == "upper"
|
| 387 |
+
|
| 388 |
+
|
| 389 |
+
@pytest.mark.parametrize(
|
| 390 |
+
"argv,env",
|
| 391 |
+
[
|
| 392 |
+
(["--label-scheme", "lower"], {}),
|
| 393 |
+
([], {"JEV_LABEL_SCHEME": "lower"}),
|
| 394 |
+
],
|
| 395 |
+
)
|
| 396 |
+
def test_invalid_label_scheme_rejected(monkeypatch, capture, argv, env):
|
| 397 |
+
with pytest.raises(SystemExit):
|
| 398 |
+
run_main(monkeypatch, ["--model", "m", *argv], env=env)
|
| 399 |
+
assert capture.backend_kwargs is None
|
| 400 |
+
|
server/tests/test_protocol.py
CHANGED
|
@@ -115,6 +115,22 @@ class TestSystemOneValidation(unittest.TestCase):
|
|
| 115 |
with self.subTest(question=question), self.assertRaises(ValidationError):
|
| 116 |
request_for(question)
|
| 117 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 118 |
def test_required_fields_and_request_limits(self):
|
| 119 |
for updates in (
|
| 120 |
{"model": " "},
|
|
|
|
| 115 |
with self.subTest(question=question), self.assertRaises(ValidationError):
|
| 116 |
request_for(question)
|
| 117 |
|
| 118 |
+
def test_empty_noul_criteria_mean_no_descriptions(self):
|
| 119 |
+
# {} is the same as omitting criteria (the released server's fix).
|
| 120 |
+
empty = request_for({"type": "noul", "instructions": "Urgent?", "criteria": {}})
|
| 121 |
+
omitted = request_for({"type": "noul", "instructions": "Urgent?"})
|
| 122 |
+
self.assertIsNone(empty.questions["routing"].criteria)
|
| 123 |
+
plan = plan_question(empty.questions["routing"])
|
| 124 |
+
self.assertEqual(plan, plan_question(omitted.questions["routing"]))
|
| 125 |
+
self.assertEqual(plan.descriptions, (None, None))
|
| 126 |
+
self.assertTrue(build_prompt("s", plan, ["A", "B"]).endswith("A: yes\nB: no"))
|
| 127 |
+
# Only an empty map is relaxed; a partial or foreign map still fails.
|
| 128 |
+
for criteria in ({"true": None}, {"yes": None, "no": None}):
|
| 129 |
+
with self.subTest(criteria=criteria), self.assertRaises(ValidationError):
|
| 130 |
+
request_for(
|
| 131 |
+
{"type": "noul", "instructions": "Urgent?", "criteria": criteria}
|
| 132 |
+
)
|
| 133 |
+
|
| 134 |
def test_required_fields_and_request_limits(self):
|
| 135 |
for updates in (
|
| 136 |
{"model": " "},
|