226 lines
7.5 KiB
Markdown
226 lines
7.5 KiB
Markdown
# Model-Specific Parameter Flow
|
|
|
|
This document records how model-family-specific parameters are wired through the
|
|
node layer. It exists to prevent configuration maps from becoming declarations
|
|
that are not actually consumed by a runtime path.
|
|
|
|
## Qwen3.5 Reference Flow
|
|
|
|
Qwen3.5 currently uses all three model-specific maps:
|
|
|
|
```python
|
|
CHAT_HANDLER_KWARGS_MAP["qwen3.5"] = {
|
|
"enable_thinking": False,
|
|
"image_min_tokens": 1024,
|
|
}
|
|
|
|
TEXT_CHAT_BUILDER_CONFIG_MAP["qwen3.5"] = {
|
|
"enable_thinking": False,
|
|
}
|
|
|
|
SUMMARY_TEXT_CHAT_BUILDER_FORCE_MAP["qwen3.5"] = {
|
|
"enable_thinking": False,
|
|
}
|
|
```
|
|
|
|
These maps serve different runtime paths. Adding a key to a map is not enough by
|
|
itself; the corresponding execution path must read and consume that key.
|
|
|
|
Gemma4 follows the same design for `enable_thinking`:
|
|
|
|
```python
|
|
CHAT_HANDLER_KWARGS_MAP["gemma4"] = {
|
|
"enable_thinking": False,
|
|
}
|
|
|
|
TEXT_CHAT_BUILDER_CONFIG_MAP["gemma4"] = {
|
|
"enable_thinking": False,
|
|
}
|
|
|
|
SUMMARY_TEXT_CHAT_BUILDER_FORCE_MAP["gemma4"] = {
|
|
"enable_thinking": False,
|
|
}
|
|
```
|
|
|
|
MiniCPM-V-4.6 also uses all three maps for `enable_thinking`. The chat-handler
|
|
entry applies only to Vision mode, while the text-builder entries apply only to
|
|
Text-only completion-style prompts:
|
|
|
|
```python
|
|
CHAT_HANDLER_KWARGS_MAP["minicpm-v-4.6"] = {
|
|
"enable_thinking": False,
|
|
}
|
|
|
|
TEXT_CHAT_BUILDER_CONFIG_MAP["minicpm-v-4.6"] = {
|
|
"enable_thinking": False,
|
|
}
|
|
|
|
SUMMARY_TEXT_CHAT_BUILDER_FORCE_MAP["minicpm-v-4.6"] = {
|
|
"enable_thinking": False,
|
|
}
|
|
```
|
|
|
|
## Chat Handler Path
|
|
|
|
The chat handler path is used when a model family is detected and an mmproj is
|
|
available, or auto-detected, so the model is loaded with vision support.
|
|
|
|
Flow:
|
|
|
|
1. `CHAT_HANDLER_KWARGS_MAP` defines built-in kwargs for each chat format.
|
|
2. `_load_available_chat_handlers()` builds handler factories from that map at
|
|
module import time.
|
|
3. `GGUFModelManager.load_model()` detects the model family from the model file
|
|
name.
|
|
4. `_get_chat_handler_kwargs()` starts with
|
|
`CHAT_HANDLER_KWARGS_MAP[model_family]`.
|
|
5. If `chat_handler_overrides` contains the same model family, those values are
|
|
merged on top.
|
|
6. The selected chat handler is instantiated through the compatibility helper:
|
|
|
|
```python
|
|
_instantiate_chat_handler(
|
|
handler_cls,
|
|
mmproj_path,
|
|
active_chat_handler_kwargs,
|
|
)
|
|
```
|
|
|
|
The helper prefers `mmproj_path`, which is the current MTMD argument name in
|
|
recent JamePeng `llama-cpp-python` builds. If the installed handler stack rejects
|
|
that keyword with an mmproj-specific unexpected-keyword `TypeError`, the helper
|
|
falls back to the older `clip_model_path` keyword.
|
|
|
|
For Qwen3.5 vision/chat-handler mode, this is where `enable_thinking` and
|
|
`image_min_tokens` are consumed.
|
|
|
|
## Text Chat Builder Path
|
|
|
|
The text chat builder path is used only when `_build_text_chat_request()` returns
|
|
a request. It is intended for chat formats that need completion-style prompts
|
|
instead of normal `create_chat_completion()` messages.
|
|
|
|
Flow:
|
|
|
|
1. `TEXT_CHAT_BUILDER_CONFIG_MAP` declares model families that may use a text
|
|
builder and their default builder config.
|
|
2. `_build_text_chat_request()` rejects the text-builder path if `mmproj_path` is
|
|
present, or if any message content includes non-text parts.
|
|
3. `_detect_model_family()` maps aliases such as `qwen3.5`, `qwen35`,
|
|
`qwen3.6`, and `qwen36` to `qwen3.5`.
|
|
4. `_get_text_chat_builder_config()` starts with
|
|
`TEXT_CHAT_BUILDER_CONFIG_MAP[model_family]`.
|
|
5. If `text_chat_builder_overrides` contains the same model family, those values
|
|
are merged on top.
|
|
6. `_build_text_chat_request()` must explicitly dispatch the model family to a
|
|
prompt builder.
|
|
|
|
For Qwen3.5, the dispatch is:
|
|
|
|
```python
|
|
if model_family == "qwen3.5":
|
|
prompt, stop = _build_qwen35_text_prompt(messages, config)
|
|
```
|
|
|
|
For Gemma4, the dispatch follows the same rule:
|
|
|
|
```python
|
|
if model_family == "gemma4":
|
|
prompt, stop = _build_gemma4_text_prompt(messages, config)
|
|
```
|
|
|
|
For MiniCPM-V-4.6, the dispatch follows the same rule:
|
|
|
|
```python
|
|
if model_family == "minicpm-v-4.6":
|
|
prompt, stop = _build_minicpm_v46_text_prompt(messages, config)
|
|
```
|
|
|
|
`_build_qwen35_text_prompt()` consumes `config["enable_thinking"]`:
|
|
|
|
- `True`: appends an opening `<think>` marker.
|
|
- `False`: appends an empty `<think></think>` block to discourage thinking
|
|
output.
|
|
|
|
`_build_gemma4_text_prompt()` also consumes `config["enable_thinking"]`:
|
|
|
|
- `True`: prepends `<|think|>` to the effective system prompt before it is
|
|
folded into the first user turn.
|
|
- `False`: does not add any thinking marker or empty thought-channel prefix.
|
|
|
|
`_build_minicpm_v46_text_prompt()` consumes `config["enable_thinking"]`:
|
|
|
|
- `True`: appends an opening `<think>` marker after
|
|
`<|im_start|>assistant`.
|
|
- `False`: appends an empty `<think></think>` block after
|
|
`<|im_start|>assistant` to discourage thinking output.
|
|
|
|
The resulting request is later executed by `_create_text_or_chat_completion()`
|
|
using `llm.create_completion(...)`.
|
|
|
|
Important: a model family listed in `TEXT_CHAT_BUILDER_CONFIG_MAP` still needs an
|
|
explicit dispatch branch in `_build_text_chat_request()`. Without that branch,
|
|
the config is declared but not consumed.
|
|
|
|
## Summary Text Builder Forced Overrides
|
|
|
|
Summarization uses the same text-or-chat completion helper as normal chat, but
|
|
it may force stricter builder config to avoid reasoning in summaries.
|
|
|
|
Flow:
|
|
|
|
1. `_summarize_with_model()` and `maybe_compact_summary()` call
|
|
`_create_text_or_chat_completion()`.
|
|
2. They pass:
|
|
|
|
```python
|
|
forced_text_chat_builder_overrides_map=SUMMARY_TEXT_CHAT_BUILDER_FORCE_MAP
|
|
```
|
|
|
|
3. `_create_text_or_chat_completion()` calls
|
|
`_merge_text_chat_builder_overrides()`.
|
|
4. `_merge_text_chat_builder_overrides()` detects the model family from
|
|
`model_path`.
|
|
5. It starts with request-level `text_chat_builder_overrides`, then applies
|
|
`SUMMARY_TEXT_CHAT_BUILDER_FORCE_MAP[model_family]` on top.
|
|
6. `_build_text_chat_request()` must still dispatch the model family to a real
|
|
builder before the forced config can affect runtime behavior.
|
|
|
|
For Qwen3.5 summaries, `SUMMARY_TEXT_CHAT_BUILDER_FORCE_MAP["qwen3.5"]` forces
|
|
`enable_thinking=False`, then `_build_qwen35_text_prompt()` consumes that value.
|
|
MiniCPM-V-4.6 follows the same summary rule through
|
|
`_build_minicpm_v46_text_prompt()`.
|
|
|
|
## Override Precedence
|
|
|
|
For normal user-facing generation, the intended precedence is documented in
|
|
`docs/architecture.md`:
|
|
|
|
1. Explicit per-model config overrides
|
|
2. Explicit Full-node UI input values
|
|
3. Simple built-in defaults / Full UI defaults
|
|
4. Model-family fallback maps
|
|
|
|
For summary generation, `SUMMARY_TEXT_CHAT_BUILDER_FORCE_MAP` is intentionally
|
|
stronger than request-level builder overrides because summaries should be compact
|
|
and should not expose reasoning.
|
|
|
|
## Checklist For Adding A Model-Specific Parameter
|
|
|
|
When adding a model-specific parameter to one of these maps, verify all relevant
|
|
items:
|
|
|
|
1. The map declaration exists in the correct map.
|
|
2. Simple config loading reads the key if users can override it.
|
|
3. Full UI merge preserves explicit Simple config overrides.
|
|
4. The runtime path consumes the key:
|
|
- chat handler kwargs are passed to the handler constructor, or
|
|
- text builder config is passed to a concrete prompt builder, or
|
|
- summary forced config reaches a concrete text builder.
|
|
5. `_build_text_chat_request()` has an explicit dispatch branch for any model
|
|
listed in `TEXT_CHAT_BUILDER_CONFIG_MAP`.
|
|
6. Tests cover both:
|
|
- precedence, so explicit config is not overwritten by defaults
|
|
- consumption, so the configured key changes the built request or constructor
|
|
kwargs used by the relevant path
|