reasoning_parser/parsers/
qwen3.rs1use crate::{
6 parsers::BaseReasoningParser,
7 traits::{ParseError, ParserConfig, ParserResult, ReasoningParser},
8};
9
10pub struct Qwen3Parser {
15 base: BaseReasoningParser,
16}
17
18impl Qwen3Parser {
19 pub fn new() -> Self {
21 let config = ParserConfig {
22 think_start_token: "<think>".to_string(),
23 think_end_token: "</think>".to_string(),
24 stream_reasoning: true,
25 max_buffer_size: 65536,
26 initial_in_reasoning: false, };
28
29 Self {
30 base: BaseReasoningParser::new(config).with_model_type("qwen3".to_string()),
31 }
32 }
33}
34
35impl Default for Qwen3Parser {
36 fn default() -> Self {
37 Self::new()
38 }
39}
40
41impl ReasoningParser for Qwen3Parser {
42 fn detect_and_parse_reasoning(&mut self, text: &str) -> Result<ParserResult, ParseError> {
43 self.base.detect_and_parse_reasoning(text)
44 }
45
46 fn parse_reasoning_streaming_incremental(
47 &mut self,
48 text: &str,
49 ) -> Result<ParserResult, ParseError> {
50 self.base.parse_reasoning_streaming_incremental(text)
51 }
52
53 fn reset(&mut self) {
54 self.base.reset()
55 }
56
57 fn model_type(&self) -> &str {
58 self.base.model_type()
59 }
60
61 fn is_in_reasoning(&self) -> bool {
62 self.base.is_in_reasoning()
63 }
64}
65
66pub struct QwenThinkingParser {
70 base: BaseReasoningParser,
71}
72
73impl QwenThinkingParser {
74 pub fn new() -> Self {
76 let config = ParserConfig {
77 think_start_token: "<think>".to_string(),
78 think_end_token: "</think>".to_string(),
79 stream_reasoning: true,
80 max_buffer_size: 65536,
81 initial_in_reasoning: true, };
83
84 Self {
85 base: BaseReasoningParser::new(config).with_model_type("qwen_thinking".to_string()),
86 }
87 }
88}
89
90impl Default for QwenThinkingParser {
91 fn default() -> Self {
92 Self::new()
93 }
94}
95
96impl ReasoningParser for QwenThinkingParser {
97 fn detect_and_parse_reasoning(&mut self, text: &str) -> Result<ParserResult, ParseError> {
98 self.base.detect_and_parse_reasoning(text)
99 }
100
101 fn parse_reasoning_streaming_incremental(
102 &mut self,
103 text: &str,
104 ) -> Result<ParserResult, ParseError> {
105 self.base.parse_reasoning_streaming_incremental(text)
106 }
107
108 fn reset(&mut self) {
109 self.base.reset()
110 }
111
112 fn model_type(&self) -> &str {
113 self.base.model_type()
114 }
115
116 fn is_in_reasoning(&self) -> bool {
117 self.base.is_in_reasoning()
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use super::*;
124
125 #[test]
126 fn test_qwen3_initial_state() {
127 let mut parser = Qwen3Parser::new();
128
129 let result = parser
131 .detect_and_parse_reasoning("This is normal content")
132 .unwrap();
133 assert_eq!(result.normal_text, "This is normal content");
134 assert_eq!(result.reasoning_text, "");
135 }
136
137 #[test]
138 fn test_qwen3_with_tokens() {
139 let mut parser = Qwen3Parser::new();
140
141 let result = parser
143 .detect_and_parse_reasoning("<think>reasoning</think>answer")
144 .unwrap();
145 assert_eq!(result.normal_text, "answer");
146 assert_eq!(result.reasoning_text, "reasoning");
147 }
148
149 #[test]
150 fn test_qwen_thinking_initial_state() {
151 let mut parser = QwenThinkingParser::new();
152
153 let result = parser
155 .detect_and_parse_reasoning("This is reasoning content")
156 .unwrap();
157 assert_eq!(result.normal_text, "");
158 assert_eq!(result.reasoning_text, "This is reasoning content");
159 }
160
161 #[test]
162 fn test_qwen3_streaming() {
163 let mut parser = Qwen3Parser::new();
164
165 let result1 = parser
167 .parse_reasoning_streaming_incremental("normal text ")
168 .unwrap();
169 assert_eq!(result1.normal_text, "normal text ");
170 assert_eq!(result1.reasoning_text, "");
171
172 let result2 = parser
174 .parse_reasoning_streaming_incremental("<think>reasoning")
175 .unwrap();
176 assert_eq!(result2.normal_text, "");
177 assert_eq!(result2.reasoning_text, "reasoning");
178 }
179
180 #[test]
181 fn test_model_types() {
182 let qwen3 = Qwen3Parser::new();
183 assert_eq!(qwen3.model_type(), "qwen3");
184
185 let qwen_thinking = QwenThinkingParser::new();
186 assert_eq!(qwen_thinking.model_type(), "qwen_thinking");
187 }
188}