reasoning_parser/parsers/
nano_v3.rs1use crate::{
5 parsers::BaseReasoningParser,
6 traits::{ParseError, ParserConfig, ParserResult, ReasoningParser},
7};
8
9pub struct NanoV3Parser {
15 base: BaseReasoningParser,
16}
17
18impl NanoV3Parser {
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: true,
27 };
28
29 Self {
30 base: BaseReasoningParser::new(config).with_model_type("nano_v3".to_string()),
31 }
32 }
33}
34
35impl Default for NanoV3Parser {
36 fn default() -> Self {
37 Self::new()
38 }
39}
40
41impl ReasoningParser for NanoV3Parser {
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
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn test_nano_v3_initial_state() {
72 let mut parser = NanoV3Parser::new();
73
74 let result = parser
76 .detect_and_parse_reasoning("This is reasoning content")
77 .unwrap();
78 assert_eq!(result.normal_text, "");
79 assert_eq!(result.reasoning_text, "This is reasoning content");
80 }
81
82 #[test]
83 fn test_nano_v3_with_end_token() {
84 let mut parser = NanoV3Parser::new();
85
86 let result = parser
87 .detect_and_parse_reasoning("reasoning content</think>answer")
88 .unwrap();
89 assert_eq!(result.normal_text, "answer");
90 assert_eq!(result.reasoning_text, "reasoning content");
91 }
92
93 #[test]
94 fn test_nano_v3_with_both_tokens() {
95 let mut parser = NanoV3Parser::new();
96
97 let result = parser
98 .detect_and_parse_reasoning("<think>reasoning content</think>answer")
99 .unwrap();
100 assert_eq!(result.normal_text, "answer");
101 assert_eq!(result.reasoning_text, "reasoning content");
102 }
103
104 #[test]
105 fn test_nano_v3_streaming() {
106 let mut parser = NanoV3Parser::new();
107
108 let result1 = parser
109 .parse_reasoning_streaming_incremental("reasoning text ")
110 .unwrap();
111 assert_eq!(result1.normal_text, "");
112 assert_eq!(result1.reasoning_text, "reasoning text ");
113
114 let result2 = parser
115 .parse_reasoning_streaming_incremental("more reasoning</think>answer")
116 .unwrap();
117 assert_eq!(result2.normal_text, "answer");
118 assert_eq!(result2.reasoning_text, "more reasoning");
119 }
120
121 #[test]
122 fn test_model_type() {
123 let parser = NanoV3Parser::new();
124 assert_eq!(parser.model_type(), "nano_v3");
125 }
126}