reasoning_parser/parsers/
kimi.rs1use crate::{
5 parsers::BaseReasoningParser,
6 traits::{ParseError, ParserConfig, ParserResult, ReasoningParser, DEFAULT_MAX_BUFFER_SIZE},
7};
8
9pub struct KimiParser {
14 base: BaseReasoningParser,
15}
16
17impl KimiParser {
18 pub fn new() -> Self {
20 let config = ParserConfig {
21 think_start_token: "◁think▷".to_string(),
22 think_end_token: "◁/think▷".to_string(),
23 stream_reasoning: true,
24 max_buffer_size: DEFAULT_MAX_BUFFER_SIZE,
25 initial_in_reasoning: false, };
27
28 Self {
29 base: BaseReasoningParser::new(config).with_model_type("kimi".to_string()),
30 }
31 }
32}
33
34impl Default for KimiParser {
35 fn default() -> Self {
36 Self::new()
37 }
38}
39
40impl ReasoningParser for KimiParser {
41 fn detect_and_parse_reasoning(&mut self, text: &str) -> Result<ParserResult, ParseError> {
42 self.base.detect_and_parse_reasoning(text)
43 }
44
45 fn parse_reasoning_streaming_incremental(
46 &mut self,
47 text: &str,
48 ) -> Result<ParserResult, ParseError> {
49 self.base.parse_reasoning_streaming_incremental(text)
50 }
51
52 fn reset(&mut self) {
53 self.base.reset();
54 }
55
56 fn model_type(&self) -> &str {
57 self.base.model_type()
58 }
59
60 fn is_in_reasoning(&self) -> bool {
61 self.base.is_in_reasoning()
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68
69 #[test]
70 fn test_kimi_initial_state() {
71 let mut parser = KimiParser::new();
72
73 let result = parser
75 .detect_and_parse_reasoning("This is normal content")
76 .unwrap();
77 assert_eq!(result.normal_text, "This is normal content");
78 assert_eq!(result.reasoning_text, "");
79 }
80
81 #[test]
82 fn test_kimi_with_unicode_tokens() {
83 let mut parser = KimiParser::new();
84
85 let result = parser
87 .detect_and_parse_reasoning("◁think▷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_kimi_partial_unicode() {
95 let mut parser = KimiParser::new();
96
97 let result1 = parser
98 .parse_reasoning_streaming_incremental("◁thi")
99 .unwrap();
100 assert_eq!(result1.normal_text, "");
101 assert_eq!(result1.reasoning_text, "");
102
103 let result2 = parser
105 .parse_reasoning_streaming_incremental("nk▷reasoning")
106 .unwrap();
107 assert_eq!(result2.normal_text, "");
108 assert_eq!(result2.reasoning_text, "reasoning");
109 }
110
111 #[test]
112 fn test_kimi_streaming() {
113 let mut parser = KimiParser::new();
114
115 let result1 = parser
117 .parse_reasoning_streaming_incremental("normal ")
118 .unwrap();
119 assert_eq!(result1.normal_text, "normal ");
120 assert_eq!(result1.reasoning_text, "");
121
122 let result2 = parser
124 .parse_reasoning_streaming_incremental("◁think▷thinking")
125 .unwrap();
126 assert_eq!(result2.normal_text, "");
127 assert_eq!(result2.reasoning_text, "thinking");
128
129 let result3 = parser
131 .parse_reasoning_streaming_incremental("◁/think▷answer")
132 .unwrap();
133 assert_eq!(result3.normal_text, "answer");
134 assert_eq!(result3.reasoning_text, ""); }
136
137 #[test]
138 fn test_model_type() {
139 let parser = KimiParser::new();
140 assert_eq!(parser.model_type(), "kimi");
141 }
142}