Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
4aba7a0
Update GPT OSS parser and related components
zhongdaor-nv Sep 10, 2025
de1a915
tmp
zhongdaor-nv Sep 10, 2025
da62e0c
feat(parsers): enhance harmony tool calling parser and add debug stat…
zhongdaor-nv Sep 10, 2025
471f1cb
tmp
zhongdaor-nv Sep 10, 2025
63d639a
remove code for debugging
zhongdaor-nv Sep 10, 2025
244d31c
resolve coderabit comment
zhongdaor-nv Sep 10, 2025
f50ed91
cargo fmt
zhongdaor-nv Sep 10, 2025
855fb29
coderabbit
zhongdaor-nv Sep 10, 2025
97f8f65
fix unit test
zhongdaor-nv Sep 10, 2025
bd56609
Merge branch 'main' into zhongdaor/gpt-oss-frontend
zhongdaor-nv Sep 10, 2025
33e7286
Merge branch 'main' into zhongdaor/gpt-oss-frontend
zhongdaor-nv Sep 11, 2025
c9485d7
Merge branch 'main' into zhongdaor/gpt-oss-frontend
zhongdaor-nv Sep 15, 2025
9a8ce48
Merge branch 'main' into zhongdaor/gpt-oss-frontend
zhongdaor-nv Sep 15, 2025
fbc5155
resolve comment
zhongdaor-nv Sep 15, 2025
031c965
Resolve merge conflicts in preprocessor.rs
zhongdaor-nv Sep 15, 2025
40c1d03
make ci/cd happy
zhongdaor-nv Sep 16, 2025
80b2ac8
Merge remote-tracking branch 'origin/main' into zhongdaor/gpt-oss-fro…
zhongdaor-nv Sep 18, 2025
9392353
merge to main
zhongdaor-nv Sep 18, 2025
489019a
Merge branch 'main' into zhongdaor/gpt-oss-frontend
zhongdaor-nv Sep 18, 2025
a733a8b
cargo fmt
zhongdaor-nv Sep 18, 2025
cdb9e7f
cargo test
zhongdaor-nv Sep 18, 2025
c0e22d7
Merge branch 'main' into zhongdaor/gpt-oss-frontend
zhongdaor-nv Sep 18, 2025
8c5d62b
add test for test_parse_tool_calls_harmony_complete_basic
zhongdaor-nv Sep 18, 2025
67995d7
Merge branch 'main' into zhongdaor/gpt-oss-frontend
zhongdaor-nv Sep 18, 2025
eb7855f
add more comment
zhongdaor-nv Sep 18, 2025
ca70608
Merge branch 'main' into zhongdaor/gpt-oss-frontend
zhongdaor-nv Sep 18, 2025
e579b3a
Merge branch 'main' into zhongdaor/gpt-oss-frontend
zhongdaor-nv Sep 18, 2025
fdc9f0d
Merge branch 'main' into zhongdaor/gpt-oss-frontend
zhongdaor-nv Sep 18, 2025
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
Prev Previous commit
Next Next commit
remove code for debugging
  • Loading branch information
zhongdaor-nv committed Sep 10, 2025
commit 63d639ab4a8ebd9b5ef23b1cd0632200af006db4
1 change: 0 additions & 1 deletion lib/llm/src/preprocessor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ impl OpenAIPreprocessor {
);
};
let model_info = model_info.get_model_info()?;
eprintln!("runtime_config: {:?}", mdc.runtime_config); // Optional: Remove or keep if runtime_config implements Debug

// Initialize runtime config; allow env override if not provided by backend/card
let runtime_config = mdc.runtime_config.clone();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ impl DeltaAggregator {

// After aggregation, inspect each choice's text for tool call syntax
for choice in aggregator.choices.values_mut() {
eprintln!("choice.text[+++] {:?}", choice.text);
if choice.tool_calls.is_none()
&& let Ok((tool_calls, normal_text)) = try_tool_call_parse_aggregate(
&choice.text,
Expand Down
1 change: 0 additions & 1 deletion lib/llm/src/protocols/openai/chat_completions/delta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ impl DeltaGenerator {
self.reasoning_parser = Some(ReasoningParserType::get_reasoning_parser_from_name(
parser_name,
));
eprintln!("reasoning_parser: {:?}", self.reasoning_parser);
}

/// Updates the prompt token usage count.
Expand Down
55 changes: 1 addition & 54 deletions lib/parsers/src/reasoning/gpt_oss_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,60 +174,10 @@ impl ReasoningParser for GptOssReasoningParser {
}
}

// Debug: append tokens and text to two files
// Write tokens to "tokens.txt" and text to "text.txt"
use std::io::Write;

// Convert token_ids to string for debugging
let tokens_str = token_ids
.iter()
.map(|id| id.to_string())
.collect::<Vec<_>>()
.join(",");

// Write tokens to file
if let Err(e) = std::fs::OpenOptions::new()
.create(true)
.append(true)
.open("tokens.txt")
.and_then(|mut file| writeln!(file, "{}", tokens_str))
{
tracing::warn!("Failed to write tokens to file: {}", e);
}

// Write text to file
if let Err(e) = std::fs::OpenOptions::new()
.create(true)
.append(true)
.open("text.txt")
.and_then(|mut file| writeln!(file, "{}", _text))
{
tracing::warn!("Failed to write text to file: {}", e);
}
// write the state json to file
if let Err(e) = std::fs::OpenOptions::new()
.create(true)
.append(true)
.open("state.json")
.and_then(|mut file| match self.parser.state_json() {
Ok(state_json) => writeln!(file, "{}", state_json),
Err(json_err) => {
tracing::warn!("Failed to serialize parser state: {}", json_err);
writeln!(
file,
"{{\"error\": \"Failed to serialize state: {}\"}}",
json_err
)
}
})
{
tracing::warn!("Failed to write state json to file: {}", e);
}

if let Some(channel) = self.parser.current_channel() {
tracing::debug!("Current channel {}", channel);
if channel == "final" {
tracing::debug!("In final channel, processing normal text");
// If we're in the final channel, we should not parse reasoning
if let Some(current) = self.parser.last_content_delta().unwrap_or_default() {
tracing::debug!("Got normal text delta of {} chars", current.len());
Expand All @@ -239,10 +189,7 @@ impl ReasoningParser for GptOssReasoningParser {
tracing::debug!("No content delta in final channel");
ParserResult::default()
} else if channel == "commentary" {
tracing::debug!(
"In final/commentary channel, returning raw token content for tool parser"
);
// If we're in the commentary channel, we should return raw token content
// If we're in the commentary channel, we should return raw token content and recover content that is been comsumed by the parser
// so that the tool parser can process it properly
if let Ok(enc) = get_harmony_encoding() {

Expand Down
31 changes: 23 additions & 8 deletions lib/parsers/src/tool_calling/harmony/harmony_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
use super::config::JsonParserConfig;
use super::response::{CalledFunction, ToolCallResponse, ToolCallType};
use openai_harmony::chat::{Content::Text, Role};
use openai_harmony::{load_harmony_encoding, HarmonyEncoding, HarmonyEncodingName, StreamableParser};
use openai_harmony::{
HarmonyEncoding, HarmonyEncodingName, StreamableParser, load_harmony_encoding,
};
use serde_json::Value;
use std::sync::OnceLock;

Expand Down Expand Up @@ -153,7 +155,25 @@ pub fn parse_tool_calls_harmony(
Ok((res, Some(normal_text.to_string())))
}

pub fn parse_tool_calls_harmony_chunk(
/// Parse tool calls from a complete Harmony Format text chunk using direct token parsing.
///
/// This function is optimized for parsing complete text chunks where the entire content
/// is available at once. It uses `parse_messages_from_completion_tokens` to directly
/// parse all tokens into Harmony Format messages, then extracts tool calls from messages
/// with the "commentary" channel and "functions.*" recipients.
///
/// Unlike `parse_tool_calls_harmony`, this function doesn't perform start token detection
/// or token-by-token streaming, making it more efficient for complete chunks.
///
/// # Arguments
/// * `text` - The complete Harmony Format text to parse
/// * `config` - Parser configuration (currently unused but kept for API consistency)
///
/// # Returns
/// * `Ok((tool_calls, normal_text))` - Tuple containing extracted tool calls and any normal text
/// * `Err(e)` - If parsing fails due to encoding or tokenization errors
/// <|channel|>commentary to=functions.get_current_weather <|constrain|>json<|message|>{"location":"San Francisco"}
pub fn parse_tool_calls_harmony_complete(
text: &str,
config: &JsonParserConfig,
) -> anyhow::Result<(Vec<ToolCallResponse>, Option<String>)> {
Expand All @@ -167,9 +187,7 @@ pub fn parse_tool_calls_harmony_chunk(
};

// // Encode the text into tokens using harmony encoding
let tokens = enc.tokenizer().encode_with_special_tokens(text);
eprintln!("tokens[+++] {:?}", tokens);
// let messages = enc.parse_messages_from_completion_tokens(tokens, Some(Role::Assistant)).unwrap();
let tokens: Vec<u32> = enc.tokenizer().encode_with_special_tokens(text);
let messages = match enc.parse_messages_from_completion_tokens(tokens, Some(Role::Assistant)) {
Ok(messages) => messages,
Err(e) => {
Expand All @@ -179,16 +197,13 @@ pub fn parse_tool_calls_harmony_chunk(
return Ok((vec![], Some(text.to_string())));
}
};
eprintln!("messages[+++] {:?}", messages);


let mut normal_text = String::new();

let mut res = Vec::with_capacity(messages.len());
let mut call_idx = 0usize; // Index of the tool call

for message in messages.iter() {
eprintln!("message[+++] {:?}", message);
if message.author.role == Role::Assistant
&& message.channel.as_deref() == Some("commentary")
&& message
Expand Down
2 changes: 1 addition & 1 deletion lib/parsers/src/tool_calling/harmony/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ pub mod harmony_parser;

pub use super::{config, response};
pub use harmony_parser::{
detect_tool_call_start_harmony, parse_tool_calls_harmony, parse_tool_calls_harmony_chunk,
detect_tool_call_start_harmony, parse_tool_calls_harmony, parse_tool_calls_harmony_complete,
};
2 changes: 1 addition & 1 deletion lib/parsers/src/tool_calling/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub mod tools;

// Re-export main types and functions for convenience
pub use config::{JsonParserConfig, ToolCallConfig, ToolCallParserType};
pub use harmony::{parse_tool_calls_harmony, parse_tool_calls_harmony_chunk};
pub use harmony::{parse_tool_calls_harmony, parse_tool_calls_harmony_complete};
pub use json::try_tool_call_parse_json;
pub use parsers::{detect_and_parse_tool_call, try_tool_call_parse};
pub use pythonic::try_tool_call_parse_pythonic;
Expand Down
4 changes: 2 additions & 2 deletions lib/parsers/src/tool_calling/parsers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

use super::config::{ToolCallConfig, ToolCallParserType};
use super::harmony::{detect_tool_call_start_harmony, parse_tool_calls_harmony_chunk};
use super::harmony::{detect_tool_call_start_harmony, parse_tool_calls_harmony_complete};
use super::json::{detect_tool_call_start_json, try_tool_call_parse_json};
use super::pythonic::{detect_tool_call_start_pythonic, try_tool_call_parse_pythonic};
use super::response::ToolCallResponse;
Expand Down Expand Up @@ -43,7 +43,7 @@ pub fn try_tool_call_parse(
Ok((results, normal_content))
}
ToolCallParserType::Harmony => {
let (results, normal_content) = parse_tool_calls_harmony_chunk(message, &config.json)?;
let (results, normal_content) = parse_tool_calls_harmony_complete(message, &config.json)?;
Ok((results, normal_content))
}
ToolCallParserType::Pythonic => {
Expand Down
Loading