@@ -27,7 +27,9 @@ This example now follows a feature-first structure:
2727- ` lib/src/features/openai_api/ ` - OpenAI-compatible HTTP server and docs
2828- ` lib/src/features/chat_completion/ ` - chat request model, parser, mapper, and
2929 completion use cases
30- - ` lib/src/features/model_management/ ` - model path resolution and download
30+ - Model paths, URLs, and Hugging Face sources load through
31+ ` LlamaEngine.loadModelSource(...) ` , using the core runtime's cache and
32+ download policy
3133- ` lib/src/features/server_engine/ ` - engine contract + llama engine adapter
3234- ` lib/src/features/shared/ ` - shared API error types
3335- ` lib/src/bootstrap/ ` - CLI argument parsing and runtime wiring
@@ -38,30 +40,34 @@ Public APIs are exported directly from `lib/llamadart_server.dart`.
3840
3941- Supports a single generation at a time (returns 429 while busy)
4042- Supports ` n = 1 ` only
41- - By default, tools are passed through to the model prompt only (no server-side
42- execution). Use ` --enable-tool-execution ` to enable an example built-in tool
43- loop.
43+ - Function tools follow the standard client-managed Chat Completions flow: the
44+ server returns ` tool_calls ` , your client executes them, then submits the
45+ assistant tool-call message and matching ` role: "tool" ` result in a new
46+ request. The server never executes application tools.
4447- No legacy Completions endpoint
48+ - The default Qwen3.6 27B GGUF is loaded text-only; this example does not
49+ download or load its separate vision projector.
4550
4651## Run
4752
4853``` bash
4954dart pub get
50- dart run llamadart_server --model /path/to/model.gguf
55+ dart run llamadart_server
5156```
5257
53- Use a remote GGUF URL instead of a path if you want automatic download.
58+ With no ` --model ` override, the first launch downloads the default 17.6 GB
59+ Unsloth model. Pass ` --model /path/to/model.gguf ` to use a local GGUF instead.
60+ You can also pass a remote GGUF URL or an ` hf://owner/repo/path ` source for
61+ automatic resolution and download.
5462
5563Optional flags:
5664
5765- ` --model-id ` (default: ` llamadart-local ` )
5866- ` --host ` (default: ` 127.0.0.1 ` )
5967- ` --port ` (default: ` 8080 ` )
6068- ` --api-key ` (optional)
61- - ` --context-size ` (default: ` 4096 ` )
69+ - ` --context-size ` (default: ` 16384 ` )
6270- ` --gpu-layers ` (default: ` 999 ` )
63- - ` --enable-tool-execution ` (default: disabled; enables built-in demo handlers)
64- - ` --max-tool-rounds ` (default: ` 5 ` ; used only when tool execution is enabled)
6571- ` --log ` (enable verbose Dart + HTTP request logs; native logs stay error-only)
6672
6773### Exit codes
@@ -72,24 +78,50 @@ Optional flags:
7278
7379### Sampling defaults
7480
75- When omitted in a request body, this example server applies a stable default
76- ` GenerationParams ` baseline :
81+ When omitted in a request body, this example server applies the supported
82+ subset of Qwen3.6 27B's non-thinking text profile :
7783
78- - ` penalty = 1.0 `
79- - ` top_p = 0.95 `
80- - ` min_p = 0.05 `
84+ - ` temperature = 0.7 `
85+ - ` top_k = 20 `
86+ - ` top_p = 0.8 `
87+ - ` min_p = 0.0 `
88+ - ` repetition penalty = 1.0 `
8189
8290Request-provided sampling fields (for example ` temperature ` , ` top_p ` , ` seed ` ,
8391` max_tokens ` ) override these defaults per call.
8492
93+ Qwen also recommends a presence penalty, but this example's current backend
94+ does not expose presence-penalty control. Do not substitute repetition penalty
95+ for it; they have different effects.
96+
97+ ### Default model and thinking mode
98+
99+ The default is Unsloth's ` Qwen3.6-27B-UD-Q4_K_XL.gguf ` (about 17.6 GB). Plan
100+ for at least 32 GB of free unified memory or VRAM plus runtime headroom; use
101+ ` --gpu-layers 0 ` to force CPU inference when GPU memory is insufficient.
102+ The 16,384-token context is a practical server default that leaves room for
103+ normal chat;
104+ increase it cautiously because larger contexts need substantially more memory.
105+
106+ Qwen3.6 thinks by default, but this API server intentionally disables thinking
107+ unless a request sets ` "enable_thinking": true ` , so ordinary calls return
108+ assistant ` content ` promptly. Thinking responses use a separate
109+ ` reasoning_content ` channel and the Qwen thinking profile (` temperature: 1.0 ` ,
110+ ` top_p: 0.95 ` ). ` max_tokens ` covers both reasoning and the final answer; the
111+ server's inherited default is 4,096 tokens. Use streaming and raise the limit
112+ for thought-intensive requests while leaving room for the prompt in the
113+ 16,384-token context. A request that ends during reasoning can correctly have
114+ ` reasoning_content ` but no final ` content ` .
115+
85116## API Examples
86117
87118### 0. OpenAPI and Swagger UI
88119
89120- OpenAPI JSON: ` http://127.0.0.1:8080/openapi.json `
90121- Swagger UI: ` http://127.0.0.1:8080/docs `
91- - Swagger includes ready-made chat request examples (basic, streaming, tools)
92- and embeddings examples under ` POST /v1/embeddings ` .
122+ - Swagger includes ready-made chat request examples for basic and streaming
123+ completions, initial tool calls, streamed tool calls, thinking plus streamed
124+ tool calls, and the client-executed tool-result follow-up.
93125
94126``` bash
95127curl http://127.0.0.1:8080/openapi.json
@@ -115,7 +147,8 @@ curl http://127.0.0.1:8080/v1/chat/completions \
115147 {"role": "system", "content": "You are concise."},
116148 {"role": "user", "content": "Give me one sentence about Seoul."}
117149 ],
118- "max_tokens": 128
150+ "max_tokens": 128,
151+ "enable_thinking": false
119152 }'
120153```
121154
@@ -133,14 +166,40 @@ curl -N http://127.0.0.1:8080/v1/chat/completions \
133166 }'
134167```
135168
136- ### 4. With API key
169+ ### 4. Tool calling (client-executed)
170+
171+ This server uses the standard OpenAI Chat Completions sequence:
172+
173+ 1 . Send the user messages, ` tools ` , and a ` tool_choice ` .
174+ 2 . Receive an assistant response with ` finish_reason: "tool_calls" ` and
175+ ` message.tool_calls ` .
176+ 3 . Execute each function in your application.
177+ 4 . Append the entire assistant tool-call message and one ` role: "tool" ` message
178+ per result. Each result must use the exact returned ` tool_call_id ` .
179+ 5 . Send the expanded transcript in a new ` POST /v1/chat/completions ` request.
180+
181+ Set ` parallel_tool_calls: true ` to permit multiple calls in one response when
182+ the active model template supports it; append a result for every returned call.
183+
184+ Use Swagger's ** Tool call: request a function** example for step 1 and
185+ ** Tool call: submit the function result** for step 5. Swagger cannot transfer
186+ a runtime call ID between requests, so replace ` call_weather_example ` and its
187+ illustrative assistant message with the actual response from step 1. The
188+ minimal standard tool-result message does not need a ` name ` field.
189+
190+ For a streaming tool call, accumulate ` delta.tool_calls ` fragments by index
191+ until the terminal ` finish_reason ` is ` tool_calls ` ; then follow the same steps.
192+ The ** Tool call: reasoning + function request (SSE)** Swagger example also
193+ demonstrates Qwen's optional ` reasoning_content ` stream.
194+
195+ ### 5. With API key
137196
138197``` bash
139198curl http://127.0.0.1:8080/v1/models \
140199 -H " Authorization: Bearer YOUR_KEY"
141200```
142201
143- ### 5 . Embeddings
202+ ### 6 . Embeddings
144203
145204``` bash
146205curl http://127.0.0.1:8080/v1/embeddings \
0 commit comments