Instructions to use RecursiveSI/flint with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use RecursiveSI/flint with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="RecursiveSI/flint") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("RecursiveSI/flint") model = AutoModelForCausalLM.from_pretrained("RecursiveSI/flint", device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = tokenizer.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(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use RecursiveSI/flint with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "RecursiveSI/flint" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "RecursiveSI/flint", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/RecursiveSI/flint
- SGLang
How to use RecursiveSI/flint 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 "RecursiveSI/flint" \ --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": "RecursiveSI/flint", "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 "RecursiveSI/flint" \ --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": "RecursiveSI/flint", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use RecursiveSI/flint with Docker Model Runner:
docker model run hf.co/RecursiveSI/flint
Download sglang/README.md from RecursiveSI/flint: direct link, hf CLI and curl.
- Browser
- Download file 13.7 kB
-
https://huggingface.co/RecursiveSI/flint/resolve/main/sglang/README.md
- Command line
-
hf download hf://RecursiveSI/flint/sglang/README.md
-
curl -L -o README.md https://huggingface.co/RecursiveSI/flint/resolve/main/sglang/README.md
Serving Flint with SGLang
This directory is Flint's serving kit for SGLang 0.5.16: the flint_sglang model package (a wheel), a
Dockerfile, install.sh for existing containers, the FA4 learned-sink patch, serve scripts and two
example clients. The commands below pin a commit of this repository.
Flint reasons at length on hard problems (see max_tokens below).
Quick start (Docker, one GPU)
Requirements:
- One GPU with ≥141 GB per replica: B300/B200 (Blackwell) or H200 (Hopper). 80 GB GPUs are not supported.
- NVIDIA driver ≥ 580 (CUDA 13). Older datacenter drivers (e.g. R570) work through the CUDA
forward-compatibility libraries in the image (
/usr/local/cuda/compat), which recent NVIDIA Container Toolkit and enroot setups pick up automatically. Tested: B300 with 580.126.20, H200 with 570.133.20. - Building the image needs access to Docker Hub, pypi.org/files.pythonhosted.org, flashinfer.ai and github.com (FlashInfer release assets).
- About 80 GB of disk for the weights plus about 50 GB for the image.
pip install -U huggingface_hub openai
REV=$(python3 -c "from huggingface_hub import HfApi; print(HfApi().model_info('RecursiveSI/flint').sha)")
hf download RecursiveSI/flint --revision "$REV" --local-dir "flint-$REV"
cd "flint-$REV" && hf cache verify RecursiveSI/flint --revision "$REV" --local-dir . # verify the download
docker build -t "flint-sglang:${REV:0:12}" sglang
docker run -d --name flint --gpus '"device=0"' --ipc=host -p 127.0.0.1:30000:30000 \
-v "$PWD:/model" -e MODEL=/model "flint-sglang:${REV:0:12}" \
bash /model/sglang/serve_b300.sh # on H200: serve_h200.sh
until curl -sf localhost:30000/health_generate >/dev/null; do sleep 15; done # progress: docker logs -f flint
python3 sglang/example_client.py --base-url http://localhost:30000/v1
python3 sglang/example_tools.py --base-url http://localhost:30000/v1 # nested tool arguments, parallel calls
The first start takes about 4 minutes on a B300 with the weights on fast local storage (longer when
many replicas read the weights from network storage at once; budget up to 15 minutes). The log
shows Flint weights loaded: 585 parameters matched the checkpoint. and then
The server is fired up and ready to roll!. example_client.py prints the reasoning, a
get_weather call for Paris, and a final answer that uses the tool result (sunny, 21C).
example_tools.py books a meeting and fills a cart through tools with nested argument schemas
(enums, patterns, bounds, arrays of objects) and makes three parallel weather calls. It answers each
call with a canned result, which Flint's final answers report.
Serve scripts
Requests use the model name flint. Arguments after the script name are appended to
sglang.launch_server, so a repeated flag overrides the script's value, e.g.
bash /model/sglang/serve_b300.sh --mem-fraction-static 0.85.
| Variable | Default | Notes |
|---|---|---|
MODEL |
RecursiveSI/flint |
Use the local download (/model in Docker). With the Hub id the server downloads 79.6 GB at start-up. |
REVISION |
unset | Hub commit when MODEL is a Hub id (ignored for local paths). |
PORT |
30000 |
Replica port. |
CUDA_VISIBLE_DEVICES |
all GPUs | GPU of a single replica (the server uses the first visible GPU). |
FLINT_TRITON_CACHE_BASE |
$HOME/.triton/cache |
Kernel cache root; each replica uses its own flint-<host>-<port> subdirectory. Mount a volume here to keep compiled kernels across container restarts. |
The servers listen on 0.0.0.0 without authentication: publish ports only on localhost or a private
network, or append --api-key <key> and give clients the same key.
Validated configurations
One GPU per replica:
- B300 (x86_64):
serve_b300.sh(--attention-backend fa4 --moe-runner-backend flashinfer_trtllm_routed). B200 and GB200/GB300 (arm64) use the same flags but are not validated yet. - H200:
serve_h200.sh(--attention-backend fa3 --moe-runner-backend triton).
Both use --enable-fp32-lm-head --context-length 262144. The other settings are those Flint was
evaluated with on each GPU type (B300: --mem-fraction-static 0.8 --swa-full-tokens-ratio 0.05;
H200: 0.9 / 0.4).
The model refuses to start with a MoE runner other than flashinfer_trtllm_routed, triton or
auto (flashinfer_trtllm and triton_kernel bypass Flint's sigmoid routing), with any
--moe-a2a-backend, with an unpatched FA4 kernel, or if FlashInfer does not use its CUDA RMSNorm
kernels (FLASHINFER_USE_CUDA_NORM=1, which the image and flint_sglang set). --attention-backend flashinfer does not support attention sinks. Tensor, expert or pipeline parallelism, DP attention,
quantized weights or KV cache (e.g. FP8) and speculative decoding are not validated.
Several replicas behind a router
Replicas are independent single-GPU servers; the router (sglang_router 0.3.2, included in the
image) spreads requests over them.
# 8 replicas on one 8-GPU node, ports 30000-30007 (Blackwell; on H200 add -e SERVE_SCRIPT=serve_h200.sh)
docker run -d --name flint-8x --gpus all --ipc=host -p 30000-30007:30000-30007 \
-v "$PWD:/model" -e MODEL=/model "flint-sglang:${REV:0:12}" bash /model/sglang/serve_node_8x.sh
# router on any host that can reach every replica
docker run -d --name flint-router --network host "flint-sglang:${REV:0:12}" \
python3 -m sglang_router.launch_router --host 0.0.0.0 --port 8000 --policy cache_aware \
--worker-urls $(for n in node0 node1; do for p in $(seq 30000 30007); do printf 'http://%s:%d ' $n $p; done; done)
serve_node_8x.sh stops all 8 replicas when one exits; for independent restarts run one container
per GPU instead (--gpus '"device=N"', -e PORT=3000N).
Existing container (no image build), e.g. enroot/pyxis
Inside a container of the base image pinned in sglang/Dockerfile (lmsysorg/sglang:v0.5.16-cu130),
with network access:
bash flint-$REV/sglang/install.sh flint-$REV/sglang # ends with: Flint support installed (flint_sglang-0.1.4-py3-none-any.whl).
MODEL=$PWD/flint-$REV PORT=30000 bash flint-$REV/sglang/serve_h200.sh # Blackwell: serve_b300.sh
install.sh changes the container in place (FlashInfer 0.6.16.post1, CUTLASS DSL 4.6.2, the patched
FA4 kernel, flint_sglang), can be re-run, and works without root if the container's system Python
is writable (enroot/pyxis containers are). Keep or save that container (pyxis:
--container-save=flint-sglang.sqsh); a fresh copy of the base image has no Flint support. On H200
the FA4 patch is applied but unused.
Capacity and tuning
- KV cache per token: 28 KiB on the 14 full-attention layers (≈7.5 GB for one 262,144-token sequence) plus 70 KiB on the 35 sliding-window layers, which keep only the last 513 tokens of each running request.
--mem-fraction-staticis the share of GPU memory for the weights (79.6 GB) plus the KV pools.--swa-full-tokens-ratiosizes the sliding-window pool relative to the full-attention pool: raise it for many concurrent short requests, lower it for few long ones.
Chat format and API usage
Tool definitions appear after leading system messages, before the first developer or other role.
- Use
/v1/chat/completionswith the parsers and grammar backend in the serve scripts (--tool-call-parser flint --reasoning-parser flint --grammar-backend flint). Flint refuses to start without--grammar-backend flintand--reasoning-parser flint, or with--enable-strict-thinkingor--constrained-json-disable-any-whitespace, which that backend doesn't support. Without a tool-call parser, tool calls stay as literal<tool_call>text incontent. - Tool-call grammar:
--tool-call-parser flintparses Flint's tool calls and constrains every request withtools(unlesstool_choiceisnone) with XGrammar to Flint's format: an optional<think>…</think>(from--grammar-backend flint), text without protocol markers, then tool calls to the request's tools: any number withtool_choiceauto, at least one withrequired, exactly one call of the named function with a named choice. As in OpenAI's API, a tool's arguments must match its JSON schema only when the tool is sent with"strict": true; they are then also written in the order the tool declares its parameters (list optional parameters where they belong). Follow OpenAI's strict-mode rules: give every objectpropertiesoradditionalPropertiesand every arrayitems(otherwise XGrammar accepts no value for the object and only[]for the array); a strict schema XGrammar can't compile (for example a pattern with a lookahead) fails the request. Other tools keep the call format but not their schema.parallel_tool_calls: falseallows a single call. The turn still ends with Flint's stop tokens. - Tool-call limits:
- A strict string value (an enum,
const,pattern,formatormaxLength) written with whitespace around it fails its schema: XGrammar allows the whitespace and the parser keeps it. Flint rarely does this; it has been seen on a prompt that asks it to print a tool call as text. - A string argument can't contain the literal text
</tool_call>. The format has no escaping, so the parser ends the call there and reads the rest as output: text Flint copies into an argument can add a call, without arguments, to a listed tool. - When streaming, a call whose last argument is a JSON object can arrive without its final
}. SGLang adds it back only for the response's last call. - With
tool_choice: "none"nothing is constrained, so call markup Flint writes can reachcontent.
- A strict string value (an enum,
- Structured output:
response_format(json_schema,json_objectorstructural_tag) and SGLang'sregexandebnfparameters constraincontent. Flint may first reason in<think>…</think>(returned inreasoning_content), and the constraint applies to the answer after it. A request with bothtoolsand a response format gets only the response format, and<tool_call>text in the answer is still read as a tool call. Use/v1/chat/completions:/generateand/v1/completionsreturn Flint's raw text, including any<think>…</think>written before a constrained answer. - Sampling: temperature 1.0, top_p 0.95, top_k 20. These are the
generation_config.jsondefaults the server applies when a request omits them; OpenAI clients passtop_kviaextra_body. Greedy decoding is not validated. - Reasoning: the model decides on each turn whether to reason in
<think>…</think>(there is no switch or budget). Reasoning is returned inreasoning_contentand counts towardmax_tokens: on GPQA-Diamond it used a median of 4.3K tokens (p95 33K, p99 46K; about 5% of answers exceed 32K). Usemax_tokensof at least 32768 for hard problems (Flint was evaluated with up to 81920);finish_reason: "length"means the turn was cut off, possibly before any content or tool call. Keepreasoning_contenton assistant messages when you send the conversation back.thinking/enable_thinkinginchat_template_kwargshave no effect: theflintreasoning parser reads<think>…</think>when Flint writes it and never assumes a turn starts in reasoning, so turns without reasoning keep their content and their tool-call grammar. - Messages: content must be a string (flatten content-part arrays). A
developermessage uses its own<|developer|>role marker (token ID 150018). There is no default system prompt. As in training, the template removes NUL characters and<think>/</think>from system, developer, user and tool text and escapes role markers there (<|user|>becomes<|user|>). It does not escape the tool tags (<tool_call>,<tool_response>,<arg_key>,<arg_value>); strip those from untrusted tool output. - Tools: send
toolswith every request. Each function definition is rendered as the template receives it; through the server that isdescription,name,parametersandstrict(other fields are dropped). Sendfunction.argumentsback unchanged (the JSON string you received) and onetoolmessage per call, in the order oftool_calls. When callingapply_chat_templatedirectly, decode argument strings into dictionaries first. - Generation stops at
<|end_of_text|>,<|user|>,<|observation|>or<|developer|>(ids 150001, 150003, 150005, 150018). No BOS token is used for chat.
Versions and verification
- Quote the full commit SHA (
$REV) in results and bug reports. Download each commit into a new directory (hf downloaddoes not delete files removed upstream). - Serving kit: SGLang 0.5.16 (base image pinned by digest in
sglang/Dockerfile; includes transformers 5.12.1, torch 2.11.0+cu130, sglang-router 0.3.2),flint_sglang0.1.4, FlashInfer 0.6.16.post1, nvidia-cutlass-dsl 4.6.2, quack-kernels 0.6.4, apache-tvm-ffi 0.1.12.
When reporting a problem, include the commit SHA, the image ID (docker inspect --format '{{.Id}}' flint-sglang:<tag>), nvidia-smi output, the launch command including extra arguments, the start-up
log and, for output problems, the request JSON and the raw response.
Transformers
The tokenizer and chat template load with AutoTokenizer.from_pretrained; decode each
tool_calls[].function.arguments string into a dict before apply_chat_template. Transformers does
not support Flint yet, so config.json loads with FlintConfig.from_pretrained from
flint_sglang.configuration_flint (transformers ≥ 5.8, tested with 5.12.1) rather than AutoConfig.