Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/hipfire-arch-qwen35/map.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ _Generated by `scripts/check-crate-maps.py` from the tree — do not edit inside
| [`src/scheduler.rs`](src/scheduler.rs) | 142 | 3 | 4 |
| [`src/serve_engine.rs`](src/serve_engine.rs) | 1,273 | 8 | 2 |
| [`src/slot_batch.rs`](src/slot_batch.rs) | 123 | 4 | 6 |
| [`src/spec_emit.rs`](src/spec_emit.rs) | 908 | 4 | 12 |
| [`src/spec_emit.rs`](src/spec_emit.rs) | 913 | 4 | 12 |
| [`src/spec_impl.rs`](src/spec_impl.rs) | 643 | 1 | 0 |
| [`src/speculative.rs`](src/speculative.rs) | 7,743 | 69 | 13 |

Expand Down Expand Up @@ -97,6 +97,6 @@ _Generated by `scripts/check-crate-maps.py` from the tree — do not edit inside

### Totals

- 29 modules · 57,281 lines · 436 public items · 189 tests · 4 examples
- 29 modules · 57,286 lines · 436 public items · 189 tests · 4 examples

<!-- crate-map:generated:end -->
7 changes: 6 additions & 1 deletion crates/hipfire-arch-qwen35/src/spec_emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ impl<'a> Qwen35Emit<'a> {
let tool_protocol_enabled = ctx.tools.is_some();
let tool_schemas: Vec<grammar::ToolSchema> = ctx
.tools
.filter(|_| ctx.grammar)
.map(|arr| {
arr.iter()
.filter_map(|t| {
Expand Down Expand Up @@ -177,7 +178,8 @@ impl<'a> Qwen35Emit<'a> {
}
}
}
Err(_) => {
Err(e) => {
eprintln!("[qwen35-spec] {e}");
self.router_malformed = true;
}
}
Expand Down Expand Up @@ -613,6 +615,7 @@ mod tests {
eos: 9,
im_end: Some(1),
tools: Some(&[]),
grammar: true,
stop: Vec::new(),
max_think: 0,
max_tokens: 256,
Expand Down Expand Up @@ -837,6 +840,7 @@ mod tests {
eos: 9,
im_end: Some(1),
tools: None,
grammar: true,
stop: vec![first_text.clone()],
max_think: 0,
max_tokens: 256,
Expand Down Expand Up @@ -865,6 +869,7 @@ mod tests {
eos: 9,
im_end: Some(1),
tools: None,
grammar: true,
stop: vec!["STOP".to_string()],
max_think: 0,
max_tokens: 256,
Expand Down
4 changes: 2 additions & 2 deletions crates/hipfire-daemon/map.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ _Generated by `scripts/check-crate-maps.py` from the tree — do not edit inside
| File | Lines | Public items | Tests |
|---|---:|---:|---:|
| [`src/main.rs`](src/main.rs) | 4,148 | 1 | 0 |
| [`src/slots.rs`](src/slots.rs) | 1,526 | 22 | 14 |
| [`src/slots.rs`](src/slots.rs) | 1,527 | 22 | 14 |

### Public API surface

Expand All @@ -44,6 +44,6 @@ _Generated by `scripts/check-crate-maps.py` from the tree — do not edit inside

### Totals

- 2 modules · 5,674 lines · 23 public items · 14 tests · 0 examples
- 2 modules · 5,675 lines · 23 public items · 14 tests · 0 examples

<!-- crate-map:generated:end -->
1 change: 1 addition & 0 deletions crates/hipfire-daemon/src/slots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,7 @@ impl SlotBackend {
eos: self.tokenizer.eos_id,
im_end: self.tokenizer.special_token_id("<|im_end|>"),
tools: None,
grammar: true,
stop: Vec::new(),
max_think: 0,
max_tokens,
Expand Down
6 changes: 3 additions & 3 deletions crates/hipfire-generate/map.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ _Generated by `scripts/check-crate-maps.py` from the tree — do not edit inside
|---|---:|---:|---:|
| [`src/ar.rs`](src/ar.rs) | 4,623 | 49 | 0 |
| [`src/batch.rs`](src/batch.rs) | 3,465 | 8 | 0 |
| [`src/common.rs`](src/common.rs) | 1,569 | 48 | 1 |
| [`src/dense.rs`](src/dense.rs) | 8,455 | 91 | 4 |
| [`src/common.rs`](src/common.rs) | 1,570 | 48 | 1 |
| [`src/dense.rs`](src/dense.rs) | 8,456 | 91 | 4 |
| [`src/lib.rs`](src/lib.rs) | 58 | 7 | 0 |
| [`src/qwen.rs`](src/qwen.rs) | 6,312 | 60 | 1 |
| [`src/redline.rs`](src/redline.rs) | 4,361 | 49 | 1 |
Expand Down Expand Up @@ -55,6 +55,6 @@ _Generated by `scripts/check-crate-maps.py` from the tree — do not edit inside

### Totals

- 8 modules · 31,785 lines · 321 public items · 224 tests · 0 examples
- 8 modules · 31,787 lines · 321 public items · 224 tests · 0 examples

<!-- crate-map:generated:end -->
1 change: 1 addition & 0 deletions crates/hipfire-generate/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1255,6 +1255,7 @@ pub struct SpecEmitRequest {
pub im_end: Option<u32>,
/// Raw tool definitions (OpenAI-shape JSON); `None`/empty ⇒ no tool grammar.
pub tools: Option<Vec<serde_json::Value>>,
pub grammar: bool,
pub stop: Vec<String>,
pub max_think: usize,
pub assistant_prefix: hipfire_runtime::prompt_frame::AssistantPrefix,
Expand Down
1 change: 1 addition & 0 deletions crates/hipfire-generate/src/dense.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,7 @@ pub fn generate_deepseek4_spec(
SpecEmitRequest {
im_end: None,
tools: tools.map(|t| t.to_vec()),
grammar: true,
stop: Vec::new(),
max_think: 0,
assistant_prefix: hipfire_runtime::prompt_frame::AssistantPrefix::Plain,
Expand Down
10 changes: 5 additions & 5 deletions crates/hipfire-generate/src/qwen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2280,11 +2280,9 @@ pub fn generate_dflash(
std::env::var("HIPFIRE_QWEN35_GRAMMAR").ok().as_deref(),
&m.model_path,
);
let emit_tools: Option<Vec<serde_json::Value>> = if grammar_enabled {
tools.map(|t| t.to_vec())
} else {
None
};
// Tools always reach the emitter: they arm the tool-call PARSER. Whether the
// grammar matcher is armed rides on `grammar_enabled` alone.
let emit_tools: Option<Vec<serde_json::Value>> = tools.map(|t| t.to_vec());

// The decode core (slot guard, prefill, accept-window loop, bake, finish) is
// the arch-generic `generate_spec`. This wrapper owns the qwen35/llama-specific
Expand Down Expand Up @@ -2337,6 +2335,7 @@ pub fn generate_dflash(
SpecEmitRequest {
im_end: im_end_token,
tools: emit_tools,
grammar: grammar_enabled,
stop: stop.to_vec(),
max_think: max_think_tokens,
assistant_prefix: spec_assistant_prefix(started_in_think),
Expand Down Expand Up @@ -3100,6 +3099,7 @@ pub fn generate_spec(
eos: slot.eos_token(),
im_end: emit_req.im_end,
tools: emit_req.tools.as_deref(),
grammar: emit_req.grammar,
stop: emit_req.stop,
max_think: emit_req.max_think,
max_tokens,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,7 @@ use hipfire_engine::terminal::{set_active_attempt_id, ClientTerminalDecision};
eos: 7,
im_end: None,
tools: None,
grammar: true,
stop: Vec::new(),
max_think: 0,
max_tokens: 16,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ use hipfire_runtime::emit_text::extract_tool_calls_from_text;
eos: 9,
im_end: Some(1),
tools: Some(&[]),
grammar: true,
stop: Vec::new(),
max_think: 0,
max_tokens: 256,
Expand Down Expand Up @@ -820,6 +821,7 @@ use hipfire_runtime::emit_text::extract_tool_calls_from_text;
eos: 9,
im_end: Some(1),
tools: None,
grammar: true,
stop: Vec::new(),
max_think: 1,
max_tokens: 256,
Expand Down Expand Up @@ -2418,6 +2420,7 @@ use hipfire_runtime::emit_text::extract_tool_calls_from_text;
eos: 9,
im_end: Some(1),
tools: None,
grammar: true,
stop: vec![first_text.clone()],
max_think: 0,
max_tokens: 256,
Expand Down Expand Up @@ -2519,6 +2522,7 @@ use hipfire_runtime::emit_text::extract_tool_calls_from_text;
eos: 9,
im_end: Some(1),
tools: None,
grammar: true,
stop: vec![stop_text.clone()],
max_think: 0,
max_tokens: 256,
Expand Down Expand Up @@ -2699,6 +2703,7 @@ use hipfire_runtime::emit_text::extract_tool_calls_from_text;
eos: 9,
im_end: Some(1),
tools: None,
grammar: true,
stop: vec![first_text.clone()],
max_think: 0,
max_tokens: 1,
Expand Down
6 changes: 3 additions & 3 deletions crates/hipfire-runtime/map.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ _Generated by `scripts/check-crate-maps.py` from the tree — do not edit inside
| [`src/dflash_generic.rs`](src/dflash_generic.rs) | 1,365 | 3 | 13 |
| [`src/dspark_block_controller.rs`](src/dspark_block_controller.rs) | 442 | 0 | 10 |
| [`src/dspark_core.rs`](src/dspark_core.rs) | 1,773 | 11 | 0 |
| [`src/emit_text.rs`](src/emit_text.rs) | 1,702 | 20 | 39 |
| [`src/emit_text.rs`](src/emit_text.rs) | 1,707 | 20 | 39 |
| [`src/eos_filter.rs`](src/eos_filter.rs) | 919 | 9 | 27 |
| [`src/ep.rs`](src/ep.rs) | 287 | 2 | 0 |
| [`src/eval_common.rs`](src/eval_common.rs) | 231 | 3 | 0 |
Expand Down Expand Up @@ -70,7 +70,7 @@ _Generated by `scripts/check-crate-maps.py` from the tree — do not edit inside
| [`src/semantic.rs`](src/semantic.rs) | 773 | 29 | 16 |
| [`src/serve/mod.rs`](src/serve/mod.rs) | 215 | 12 | 3 |
| [`src/session_table.rs`](src/session_table.rs) | 654 | 19 | 24 |
| [`src/spec.rs`](src/spec.rs) | 1,923 | 35 | 15 |
| [`src/spec.rs`](src/spec.rs) | 1,928 | 35 | 15 |
| [`src/spec_ngram.rs`](src/spec_ngram.rs) | 491 | 4 | 3 |
| [`src/swap/mod.rs`](src/swap/mod.rs) | 176 | 10 | 3 |
| [`src/swap/snapshot.rs`](src/swap/snapshot.rs) | 392 | 9 | 7 |
Expand Down Expand Up @@ -156,6 +156,6 @@ _Generated by `scripts/check-crate-maps.py` from the tree — do not edit inside

### Totals

- 58 modules · 53,079 lines · 893 public items · 617 tests · 132 examples
- 58 modules · 53,089 lines · 893 public items · 617 tests · 132 examples

<!-- crate-map:generated:end -->
9 changes: 7 additions & 2 deletions crates/hipfire-runtime/src/emit_text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,10 @@ impl ToolOutputRouter {
Ok(true)
}
None => Err(self.latch_malformed(
"tool_call body is empty, truncated, or not fully valid JSON/Qwen XML",
&format!(
"tool_call body is empty, truncated, or not fully valid JSON/Qwen XML; body={:?}",
&body[..body.len().min(200)]
),
)),
}
}
Expand Down Expand Up @@ -1680,7 +1683,9 @@ mod tests {
fn disabled_router_keeps_tool_like_text_visible_and_non_executable() {
let text = "<tool_call>\n<function=cat\n</function>\n</tool_call>";
let mut router = ToolOutputRouter::disabled();
let events = router.push(text).expect("tool-free text must remain visible");
let events = router
.push(text)
.expect("tool-free text must remain visible");
assert_eq!(events.len(), 1);
match &events[0] {
ToolRouteEvent::VisibleText(visible) => assert_eq!(visible.as_str(), text),
Expand Down
5 changes: 5 additions & 0 deletions crates/hipfire-runtime/src/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1396,6 +1396,11 @@ pub struct SpecEmitCtx<'a> {
/// extracts its own grammar `ToolSchema` from these; `None`/empty ⇒ no
/// tool-call grammar.
pub tools: Option<&'a [serde_json::Value]>,
/// Arm grammar-guided decoding. Separate from `tools` on purpose: the
/// tool-call PARSER must follow the request carrying tools, while the
/// matcher follows the arch's grammar switch — coupling them left Qwen
/// native XML calls unparsed whenever grammar was off.
pub grammar: bool,
/// User stop sequences matched against the decoded suffix.
pub stop: Vec<String>,
/// `max_think_tokens` budget (0 ⇒ no think force-close).
Expand Down
Loading