Views
No views yet
image_url content parts alongside text.qwen3 reasoning parser.hermes tool-call parser.qwen3 reasoning
parser so its chain-of-thought is separated from the final answer:1# Launch the server, listening on port 8000 by default
2furiosa-llm serve furiosa-ai/Qwen3-VL-2B-Thinking \
3 --reasoning-parser qwen3hermes tool-call parser (the
parser used by the Qwen3 series); keep --reasoning-parser qwen3 so thinking is
still parsed into its own field:1furiosa-llm serve furiosa-ai/Qwen3-VL-2B-Thinking \
2 --reasoning-parser qwen3 \
3 --enable-auto-tool-choice \
4 --tool-call-parser hermes1INFO: Started server process [27507]
2INFO: Waiting for application startup.
3INFO: Application startup complete.
4INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)curl:1curl http://localhost:8000/v1/chat/completions \
2 -H "Content-Type: application/json" \
3 -d '{
4 "model": "furiosa-ai/Qwen3-VL-2B-Thinking",
5 "messages": [{"role": "user", "content": "What is the capital of France?"}]
6 }' \
7 | python -m json.toolimage_url content part in the message:1curl http://localhost:8000/v1/chat/completions \
2 -H "Content-Type: application/json" \
3 -d '{
4 "model": "furiosa-ai/Qwen3-VL-2B-Thinking",
5 "messages": [{
6 "role": "user",
7 "content": [
8 {"type": "image_url", "image_url": {"url": "https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-VL/assets/demo.jpeg"}},
9 {"type": "text", "text": "Describe this image."}
10 ]
11 }]
12 }' \
13 | python -m json.toolimage_url.url field accepts a remote http:///https:// URL, an inline
base64 data: URL, or a local file:// path (the last requires the
--allowed-local-media-path flag described under Advanced Usage).response.choices[].message.reasoning (non-streaming)response.choices[].delta.reasoning (streaming)1from openai import OpenAI
2
3client = OpenAI(base_url="http://localhost:8000/v1", api_key="EMPTY")
4
5response = client.chat.completions.create(
6 model="furiosa-ai/Qwen3-VL-2B-Thinking",
7 messages=[{"role": "user", "content": "How many r's are in 'strawberry'?"}],
8)
9
10print("Reasoning:", response.choices[0].message.reasoning)
11print("Answer:", response.choices[0].message.content)Note: Thereasoningfield is not part of the OpenAI API specification but is a widely followed convention (the OpenAI Agents SDK, vLLM, and others). It appears only in responses that contain reasoning content; accessing it otherwise raises anAttributeError.
furiosa-llm serve provides flags to control
multimodal behavior; requests that violate them are rejected with HTTP 400:--image-limit-per-prompt N / --video-limit-per-prompt N — maximum number of images/videos allowed per request (default: unlimited).--allowed-local-media-path PATH — allow file:// URLs whose resolved path is under PATH. Local file access is disabled unless this is set.--allowed-media-domains D [D ...] — whitelist of remote domains for SSRF protection. When set, only images from the listed domains are fetched.--interleave-mm-strings — keep image placeholders at their original positions when the model uses a string-format chat template (no-op for OpenAI-format templates, the common case).--mm-processor-cache-gb GB — size of the UUID-keyed multimodal processor cache (default: 4.0). Clients can tag an image_url part with a uuid field and re-reference it in follow-up requests without re-uploading the image bytes; set to 0 to disable./srv/media and restrict remote
fetches to a single domain:1furiosa-llm serve furiosa-ai/Qwen3-VL-2B-Thinking \
2 --reasoning-parser qwen3 \
3 --allowed-local-media-path /srv/media \
4 --allowed-media-domains cdn.example.com \
5 --image-limit-per-prompt 4enable_thinking switch (the Instruct editions are the non-thinking
counterparts).--reasoning-parser qwen3 --enable-auto-tool-choice --tool-call-parser hermes
(see Launch the server), pass tools in the request and
let the model decide when to call them. See the
Tool Calling guide
for a complete client example and details on tool-choice options.furiosa-llm serve) — full OpenAI-compatible API reference and serving options