Instructions to use moonshotai/Kimi-K3 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use moonshotai/Kimi-K3 with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-text-to-text", model="moonshotai/Kimi-K3", trust_remote_code=True) 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)# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("moonshotai/Kimi-K3", trust_remote_code=True, device_map="auto") - Inference
- HuggingChat
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use moonshotai/Kimi-K3 with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "moonshotai/Kimi-K3" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "moonshotai/Kimi-K3", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'Use Docker
docker model run hf.co/moonshotai/Kimi-K3
- SGLang
How to use moonshotai/Kimi-K3 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 "moonshotai/Kimi-K3" \ --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": "moonshotai/Kimi-K3", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'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 "moonshotai/Kimi-K3" \ --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": "moonshotai/Kimi-K3", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }' - Docker Model Runner
How to use moonshotai/Kimi-K3 with Docker Model Runner:
docker model run hf.co/moonshotai/Kimi-K3
Upload tokenizer.json (HF-compatible tokenizer without trust_remote_code)
Thanks for preparing a standard tokenizer.json. I ran an independent compatibility check against the current custom TikTokenTokenizer.
Environment: Linux x86_64 / Python 3.12.13 / transformers==5.14.1 / tokenizers==0.22.2.
What passed
- 1,016 deterministic English, Chinese, Unicode, code, whitespace, control-token, and randomized strings
add_special_tokens=FalseandTrue- 0 token-ID mismatches
- 0 ordinary decode round-trip mismatches
So the underlying BPE conversion looks accurate for ordinary encoding.
Blocking compatibility regressions
1. Kimi K3 chat templating stops working
This PR changes tokenizer_class from TikTokenTokenizer to PreTrainedTokenizerFast, but the new tokenizer_config.json does not provide a Jinja chat_template. The current tokenizer implements K3's XTML/tools/images/thinking formatting in Python.
Minimal repro:
from transformers import AutoTokenizer
messages = [{"role": "user", "content": "Hello from Kimi K3!"}]
tok = AutoTokenizer.from_pretrained(
"MoonshotAI/Kimi-K3",
revision="refs/pr/60",
)
tok.apply_chat_template(messages, tokenize=True)
Result:
ValueError: Cannot use chat template functions because tokenizer.chat_template is not set
The same call on main succeeds and produces the K3 XTML prompt. This also affects KimiK3Processor, which delegates its message path to self.tokenizer.apply_chat_template(...).
2. allow_special_tokens=False is silently lost
The custom tokenizer can encode literal user text without interpreting K3 control markers:
text = "hello <|end_of_msg|> world"
main.encode(text, allow_special_tokens=False)
# [22931, 22652, 517, 5118, 14222, 91, 29, 2695]
With the tokenizer from this PR:
fast.encode(text, add_special_tokens=False, allow_special_tokens=False)
# [22931, 220, 163586, 2695]
allow_special_tokens=False is accepted but ignored, so the literal string becomes the control-token ID 163586. The same occurs for media and header markers. This changes the user/tool-text isolation behavior used by the custom segmented chat encoder.
3. Special-token classification changes
Eight existing control markers become members of all_special_tokens in the fast tokenizer even though the current custom tokenizer does not classify them that way. For example, decode([163586], skip_special_tokens=True) returns <|end_of_msg|> on main but an empty string on this PR. That may be intentional, but it is another observable compatibility change that should be decided explicitly.
Recommendation
I would not replace the repository's default tokenizer class yet. One safe intermediate option is to upload tokenizer.json while retaining the custom tokenizer as the default, then expose/document the fast tokenizer as an opt-in path until it has parity for:
- K3 chat/tool/multimodal templating;
- literal control-token handling in untrusted user/tool text;
- agreed special-token decode semantics.
I can rerun the corpus after an update or contribute a compact regression test if useful.
As promised, here is a compact self-contained regression suite that can be copied and run without downloading model weights.
uv run --with "transformers==5.14.1" --with tiktoken --with protobuf \
python test_kimi_k3_tokenizer_compat.py
from __future__ import annotations
import random
import string
import sys
from transformers import AutoTokenizer
REPO = "MoonshotAI/Kimi-K3"
BASE_REVISION = "main"
CANDIDATE_REVISION = "refs/pr/60"
base = AutoTokenizer.from_pretrained(
REPO,
revision=BASE_REVISION,
trust_remote_code=True,
)
candidate = AutoTokenizer.from_pretrained(
REPO,
revision=CANDIDATE_REVISION,
trust_remote_code=False,
)
failures: list[str] = []
# Ordinary BPE parity: compact deterministic multilingual corpus.
cases = [
"Hello from Kimi K3!",
"你好,Kimi K3!",
"def hello(name: str) -> str:\n return f'Hello, {name}!'",
'{"tool":"search","arguments":{"q":"Kimi K3"}}',
"😀🚀 e\u0301 café 𠮷野家",
" spaces\tand\nnewlines ",
]
rng = random.Random(20260728)
alphabet = string.ascii_letters + string.digits + string.punctuation + " \t\n中文😀"
for _ in range(64):
cases.append("".join(rng.choice(alphabet) for _ in range(rng.randrange(0, 160))))
for index, text in enumerate(cases):
for add_special_tokens in (False, True):
expected = base.encode(text, add_special_tokens=add_special_tokens)
actual = candidate.encode(text, add_special_tokens=add_special_tokens)
if actual != expected:
failures.append(
f"BPE mismatch case={index} add_special_tokens={add_special_tokens}"
)
print(f"ordinary_cases={len(cases)}")
print(f"ordinary_encode_mismatches={sum(x.startswith('BPE') for x in failures)}")
# The default tokenizer must retain the K3 XTML/tool/thinking chat path.
messages = [{"role": "user", "content": "Hello from Kimi K3!"}]
try:
base.apply_chat_template(messages, tokenize=True, add_generation_prompt=True)
print("chat_template_main=PASS")
except Exception as exc: # pragma: no cover - base contract sanity check
failures.append(f"main chat template failed: {type(exc).__name__}: {exc}")
print("chat_template_main=FAIL")
try:
candidate.apply_chat_template(messages, tokenize=True, add_generation_prompt=True)
print("chat_template_candidate=PASS")
except Exception as exc:
failures.append(f"candidate chat template failed: {type(exc).__name__}: {exc}")
print(f"chat_template_candidate=FAIL ({type(exc).__name__})")
# Literal user/tool text must not be promoted to structural control-token IDs.
literal = "hello <|end_of_msg|> world"
expected_literal_ids = base.encode(literal, allow_special_tokens=False)
candidate_literal_ids = candidate.encode(
literal,
add_special_tokens=False,
allow_special_tokens=False,
)
if candidate_literal_ids != expected_literal_ids:
failures.append(
"candidate ignores allow_special_tokens=False for literal control markers"
)
print("literal_control_token_isolation=FAIL")
else:
print("literal_control_token_isolation=PASS")
if failures:
print("\nFAILURES:")
for failure in failures:
print(f"- {failure}")
sys.exit(1)
print("all_regressions=PASS")
On the current refs/pr/60 revision, the output is intentionally focused:
ordinary_cases=70
ordinary_encode_mismatches=0
chat_template_main=PASS
chat_template_candidate=FAIL (ValueError)
literal_control_token_isolation=FAIL
The process exits with status 1 until the two compatibility contracts are restored. This keeps ordinary BPE parity and K3-specific chat/control-token behavior in one small check.