# Noris: vLLM Reasoning Format Behavior ## Observed Behavior (ai.noris.de, vLLM 0.22.1) Models on the Noris vLLM cluster that have chain-of-thought reasoning enabled return **only a `reasoning` field**, with `content: null`: ```json { "choices": [{ "message": { "role": "assistant", "content": null, "reasoning": "Here's a thinking process:\n\n1. **Analyze User Input:** ...", "reasoning_details": [{ "index": 0, "type": "reasoning.text", "text": "Here's a thinking process:\n\n1. **Analyze User Input:** ..." }] } }], "usage": { "prompt_tokens": 21, "completion_tokens": 100, "total_tokens": 121 }, "system_fingerprint": "vllm-0.22.1-a8c0978c", "extra_fields": { "request_type": "chat_completion", "provider": "vllm", "latency": 1738, "chunk_index": 0 } } ``` ## What This Means for Clients | Field | Value | Implication | |-------|-------|-------------| | `content` | `null` | No final assistant message text | | `reasoning` | Non-empty string | Chain-of-thought thinking process | | `reasoning_details` | Array of blocks | Token-level reasoning decomposition | | `finish_reason` | `"length"` | Fixed length responses even if reasoning completes mid-sentence | ## Models Affected | Model | Reasoning Field | |-------|-----------------| | `vllm/qwen3.6-27b-nvfp4` | ✅ reasoning-only | | `vllm/moonshotai/kimi-k2.6` | Unknown (not tested for this pattern) | | `vllm/gpt-oss-120b` | Unknown | | `vllm/gemma-4-31b-it` | Unknown | ## Client Handling When integrating with Noris vLLM reasoning models, clients must: 1. **Check `reasoning` before `content`** — `content` will be `null` 2. **Extract text from `reasoning` field** for user-facing output 3. **Account for `finish_reason: "length"`** — reasoning may be truncated mid-thought 4. **Consider latency** — reasoning models are slower (~890ms–1700ms for 50–100 tokens on Noris) ## Example: Minimal curl test with reasoning extraction ```bash curl -sS -X POST "https://ai.noris.de/v1/chat/completions" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-bf-..." \ -d '{ "model": "vllm/qwen3.6-27b-nvfp4", "max_tokens": 100, "messages": [{"role": "user", "content": "What is prompt caching?"}] }' | python3 -c " import sys, json d = json.load(sys.stdin) msg = d['choices'][0]['message'] print('Content:', msg.get('content')) print('Has reasoning:', 'reasoning' in msg) print('Reasoning preview:', msg.get('reasoning', 'N/A')[:200]) print('Usage:', d['usage']) " ``` ## OpenAI API Spec Compliance This is **non-standard** OpenAI-format behavior. Per OpenAI spec, `content` should contain the assistant's message text. vLLM with reasoning enabled diverges by putting the model output in `reasoning` and leaving `content` null. Clients expecting standard OpenAI responses will see empty assistant messages unless they handle this field.