Skip to main content

zai_rs/model/
chat_models.rs

1//! # AI Model Type Definitions
2//!
3//! Defines all available AI model types for the Zhipu AI API, together with
4//! their capability markers and message-type bindings.
5//!
6//! # Naming convention
7//!
8//! Each model struct mirrors the vendor's model string as closely as Rust's
9//! identifier rules allow: the `GLM` prefix and version segments use
10//! underscores for the version dot (e.g. `glm-4.5-air` → `GLM4_5_air`), and
11//! the tier suffix is appended verbatim (e.g. `glm-4.7-flashx` →
12//! `GLM4_7_flashx`). Because these intentionally echo API
13//! strings rather than follow Rust's `UpperCamelCase` convention, every model
14//! struct carries `#[allow(non_camel_case_types)]`.
15//!
16//! # Model Categories
17//!
18//! ## Text Models
19//!
20//! | Model | Struct | Thinking | ReasoningEffort | Async | ToolStream |
21//! |-------|--------|----------|-----------------|-------|------------|
22//! | glm-5.2 | [`GLM5_2`] | yes | yes | yes | yes |
23//! | glm-5.1 | [`GLM5_1`] | yes | no | yes | yes |
24//! | glm-5 | [`GLM5`] | yes | no | yes | yes |
25//! | glm-5-turbo | [`GLM5_turbo`] | yes | no | yes | yes |
26//! | glm-4.7 | [`GLM4_7`] | yes | no | yes | yes |
27//! | glm-4.7-flash | [`GLM4_7_flash`] | yes | no | no | no |
28//! | glm-4.7-flashx | [`GLM4_7_flashx`] | yes | no | no | no |
29//! | glm-4.6 | [`GLM4_6`] | yes | no | yes | yes |
30//! | glm-4.5-flash | [`GLM4_5_flash`] | yes | no | yes | no |
31//! | glm-4.5-air | [`GLM4_5_air`] | yes | no | yes | no |
32//! | glm-4.5-airx | [`GLM4_5_airx`] | yes | no | yes | no |
33//! | glm-4-flash-250414 | [`GLM4_flash_250414`] | no | no | yes | no |
34//! | glm-4-flashx-250414 | [`GLM4_flashx_250414`] | no | no | yes | no |
35//!
36//! Text models accept the complete chat tool union and `response_format`.
37//!
38//! ## Vision Models
39//!
40//! | Model | Struct | Thinking | Message Type |
41//! |-------|--------|----------|--------------|
42//! | autoglm-phone | [`autoglm_phone`] | no | [`VisionMessage`] |
43//! | glm-4.6v | [`GLM4_6v`] | no | [`VisionMessage`] |
44//! | glm-4.6v-flash | [`GLM4_6v_flash`] | no | [`VisionMessage`] |
45//! | glm-4.6v-flashx | [`GLM4_6v_flashx`] | no | [`VisionMessage`] |
46//! | glm-4v-flash | [`GLM4v_flash`] | no | [`VisionMessage`] |
47//! | glm-4.1v-thinking-flash | [`GLM4_1v_thinking_flash`] | yes | [`VisionMessage`] |
48//! | glm-4.1v-thinking-flashx | [`GLM4_1v_thinking_flashx`] | yes | [`VisionMessage`] |
49//! | glm-5v-turbo | [`GLM5V_turbo`] | yes | [`VisionMessage`] |
50//!
51//! Vision models accept function tools only and do not expose
52//! `response_format`.
53//!
54//! ## Voice Models
55//!
56//! | Model | Struct | Message Type |
57//! |-------|--------|--------------|
58//! | glm-4-voice | [`GLM4_voice`] | [`VoiceMessage`] |
59//!
60//! `GLM4_voice` exposes `watermark_enabled`, but not tools, `tool_choice`, or
61//! `response_format`.
62//!
63//! ## Realtime Models
64//!
65//! | Model | Struct |
66//! |-------|--------|
67//! | glm-realtime-flash | [`GLM_realtime_flash`] |
68//! | glm-realtime-air | [`GLM_realtime_air`] |
69//!
70//! # Usage
71//!
72//! ```
73//! use zai_rs::model::{
74//!     chat::ChatCompletion,
75//!     chat_message_types::TextMessage,
76//!     chat_models::GLM5_2,
77//! };
78//!
79//! let model = GLM5_2 {};
80//! let messages = TextMessage::user("Hello");
81//! let request = ChatCompletion::new(model, messages);
82//! ```
83//!
84//! # Frozen capabilities
85//!
86//! Synchronous, asynchronous, and request-schema capabilities are sealed to
87//! the model ids listed above. Downstream crates cannot opt an arbitrary
88//! identifier into these operations.
89
90use super::{
91    chat_message_types::{TextMessage, VisionMessage, VoiceMessage},
92    tools::{Function, Tools},
93    traits::{define_model_type, impl_message_binding, impl_model_markers, *},
94};
95
96define_model_type!(GLM5_2, "glm-5.2");
97impl_message_binding!(GLM5_2, TextMessage);
98impl_model_markers!(GLM5_2: Chat, AsyncChat, ThinkEnable, ReasoningEffortEnable, ToolStreamEnable);
99
100define_model_type!(GLM5_1, "glm-5.1");
101impl_message_binding!(GLM5_1, TextMessage);
102impl_model_markers!(GLM5_1: Chat, AsyncChat, ThinkEnable, ToolStreamEnable);
103
104define_model_type!(
105    #[allow(non_camel_case_types)]
106    GLM5_turbo,
107    "glm-5-turbo"
108);
109impl_message_binding!(GLM5_turbo, TextMessage);
110impl_model_markers!(GLM5_turbo: Chat, AsyncChat, ThinkEnable, ToolStreamEnable);
111
112define_model_type!(GLM5, "glm-5");
113impl_message_binding!(GLM5, TextMessage);
114impl_model_markers!(GLM5: Chat, AsyncChat, ThinkEnable, ToolStreamEnable);
115
116define_model_type!(
117    #[allow(non_camel_case_types)]
118    GLM5V_turbo,
119    "glm-5v-turbo"
120);
121impl_message_binding!(GLM5V_turbo, VisionMessage);
122impl_model_markers!(GLM5V_turbo: Chat, AsyncChat, ThinkEnable);
123
124define_model_type!(GLM4_7, "glm-4.7");
125impl_message_binding!(GLM4_7, TextMessage);
126impl_model_markers!(GLM4_7: Chat, AsyncChat, ThinkEnable, ToolStreamEnable);
127
128define_model_type!(
129    #[allow(non_camel_case_types)]
130    GLM4_7_flash,
131    "glm-4.7-flash"
132);
133impl_message_binding!(GLM4_7_flash, TextMessage);
134impl_model_markers!(GLM4_7_flash: Chat, ThinkEnable);
135
136define_model_type!(
137    #[allow(non_camel_case_types)]
138    GLM4_7_flashx,
139    "glm-4.7-flashx"
140);
141impl_message_binding!(GLM4_7_flashx, TextMessage);
142impl_model_markers!(GLM4_7_flashx: Chat, ThinkEnable);
143
144define_model_type!(GLM4_6, "glm-4.6");
145impl_message_binding!(GLM4_6, TextMessage);
146impl_model_markers!(GLM4_6: Chat, AsyncChat, ThinkEnable, ToolStreamEnable);
147
148define_model_type!(
149    #[allow(non_camel_case_types)]
150    GLM4_5_flash,
151    "glm-4.5-flash"
152);
153impl_message_binding!(GLM4_5_flash, TextMessage);
154impl_model_markers!(GLM4_5_flash: Chat, AsyncChat, ThinkEnable);
155
156define_model_type!(
157    #[allow(non_camel_case_types)]
158    GLM4_5_air,
159    "glm-4.5-air"
160);
161impl_message_binding!(GLM4_5_air, TextMessage);
162impl_model_markers!(GLM4_5_air: Chat, AsyncChat, ThinkEnable);
163
164define_model_type!(
165    #[allow(non_camel_case_types)]
166    GLM4_5_airx,
167    "glm-4.5-airx"
168);
169impl_message_binding!(GLM4_5_airx, TextMessage);
170impl_model_markers!(GLM4_5_airx: Chat, AsyncChat, ThinkEnable);
171
172define_model_type!(
173    #[allow(non_camel_case_types)]
174    GLM4_flash_250414,
175    "glm-4-flash-250414"
176);
177impl_message_binding!(GLM4_flash_250414, TextMessage);
178impl_model_markers!(GLM4_flash_250414: Chat, AsyncChat);
179
180define_model_type!(
181    #[allow(non_camel_case_types)]
182    GLM4_flashx_250414,
183    "glm-4-flashx-250414"
184);
185impl_message_binding!(GLM4_flashx_250414, TextMessage);
186impl_model_markers!(GLM4_flashx_250414: Chat, AsyncChat);
187
188define_model_type!(
189    #[allow(non_camel_case_types)]
190    autoglm_phone,
191    "autoglm-phone"
192);
193impl_message_binding!(autoglm_phone, VisionMessage);
194impl_model_markers!(autoglm_phone: Chat);
195
196define_model_type!(
197    #[allow(non_camel_case_types)]
198    GLM4_6v,
199    "glm-4.6v"
200);
201impl_message_binding!(GLM4_6v, VisionMessage);
202impl_model_markers!(GLM4_6v: Chat, AsyncChat);
203
204define_model_type!(
205    #[allow(non_camel_case_types)]
206    GLM4_6v_flash,
207    "glm-4.6v-flash"
208);
209impl_message_binding!(GLM4_6v_flash, VisionMessage);
210impl_model_markers!(GLM4_6v_flash: Chat, AsyncChat);
211
212define_model_type!(
213    #[allow(non_camel_case_types)]
214    GLM4_6v_flashx,
215    "glm-4.6v-flashx"
216);
217impl_message_binding!(GLM4_6v_flashx, VisionMessage);
218impl_model_markers!(GLM4_6v_flashx: Chat, AsyncChat);
219
220define_model_type!(
221    #[allow(non_camel_case_types)]
222    GLM4v_flash,
223    "glm-4v-flash"
224);
225impl_message_binding!(GLM4v_flash, VisionMessage);
226impl_model_markers!(GLM4v_flash: Chat, AsyncChat);
227
228define_model_type!(
229    #[allow(non_camel_case_types)]
230    GLM4_1v_thinking_flash,
231    "glm-4.1v-thinking-flash"
232);
233impl_message_binding!(GLM4_1v_thinking_flash, VisionMessage);
234impl_model_markers!(GLM4_1v_thinking_flash: Chat, AsyncChat, ThinkEnable);
235
236define_model_type!(
237    #[allow(non_camel_case_types)]
238    GLM4_1v_thinking_flashx,
239    "glm-4.1v-thinking-flashx"
240);
241impl_message_binding!(GLM4_1v_thinking_flashx, VisionMessage);
242impl_model_markers!(GLM4_1v_thinking_flashx: Chat, AsyncChat, ThinkEnable);
243
244define_model_type!(
245    #[allow(non_camel_case_types)]
246    GLM4_voice,
247    "glm-4-voice"
248);
249impl_message_binding!(GLM4_voice, VoiceMessage);
250impl_model_markers!(GLM4_voice: Chat, AsyncChat);
251
252macro_rules! impl_text_request_schema {
253    ($($model:ty),+ $(,)?) => {
254        $(
255            impl ChatRequestModel for $model {
256                const MAX_TOKENS: u32 = 131_072;
257            }
258
259            impl ChatToolSupport for $model {
260                type Tool = Tools;
261            }
262
263            impl ResponseFormatEnable for $model {}
264        )+
265    };
266}
267
268macro_rules! impl_vision_request_schema {
269    ($($model:ty),+ $(,)?) => {
270        $(
271            impl ChatRequestModel for $model {
272                const MAX_TOKENS: u32 = 131_072;
273            }
274
275            impl ChatToolSupport for $model {
276                type Tool = Function;
277            }
278        )+
279    };
280}
281
282impl_text_request_schema!(
283    GLM5_2,
284    GLM5_1,
285    GLM5_turbo,
286    GLM5,
287    GLM4_7,
288    GLM4_7_flash,
289    GLM4_7_flashx,
290    GLM4_6,
291    GLM4_5_flash,
292    GLM4_5_air,
293    GLM4_5_airx,
294    GLM4_flash_250414,
295    GLM4_flashx_250414,
296);
297
298impl_vision_request_schema!(
299    GLM5V_turbo,
300    autoglm_phone,
301    GLM4_6v,
302    GLM4_6v_flash,
303    GLM4_6v_flashx,
304    GLM4v_flash,
305    GLM4_1v_thinking_flash,
306    GLM4_1v_thinking_flashx,
307);
308
309impl ChatRequestModel for GLM4_voice {
310    const MAX_TOKENS: u32 = 4_096;
311}
312
313impl WatermarkEnable for GLM4_voice {}
314
315define_model_type!(
316    #[allow(non_camel_case_types)]
317    GLM_realtime_flash,
318    "glm-realtime-flash"
319);
320
321define_model_type!(
322    #[allow(non_camel_case_types)]
323    GLM_realtime_air,
324    "glm-realtime-air"
325);
326
327#[cfg(test)]
328mod tests {
329    use super::*;
330
331    fn assert_sync_model<N, M>()
332    where
333        N: Chat,
334        (N, M): Bounded,
335    {
336    }
337
338    fn assert_async_model<N, M>()
339    where
340        N: AsyncChat,
341        (N, M): Bounded,
342    {
343    }
344
345    fn assert_text_request_schema<N>()
346    where
347        N: ChatRequestModel + ChatToolSupport<Tool = Tools> + ResponseFormatEnable,
348    {
349    }
350
351    fn assert_vision_request_schema<N>()
352    where
353        N: ChatRequestModel + ChatToolSupport<Tool = Function>,
354    {
355    }
356
357    fn assert_audio_request_schema<N>()
358    where
359        N: ChatRequestModel + WatermarkEnable,
360    {
361    }
362
363    #[test]
364    fn request_schema_capabilities_are_typed_by_model_family() {
365        assert_text_request_schema::<GLM5_2>();
366        assert_text_request_schema::<GLM5_1>();
367        assert_text_request_schema::<GLM5_turbo>();
368        assert_text_request_schema::<GLM5>();
369        assert_text_request_schema::<GLM4_7>();
370        assert_text_request_schema::<GLM4_7_flash>();
371        assert_text_request_schema::<GLM4_7_flashx>();
372        assert_text_request_schema::<GLM4_6>();
373        assert_text_request_schema::<GLM4_5_flash>();
374        assert_text_request_schema::<GLM4_5_air>();
375        assert_text_request_schema::<GLM4_5_airx>();
376        assert_text_request_schema::<GLM4_flash_250414>();
377        assert_text_request_schema::<GLM4_flashx_250414>();
378
379        assert_vision_request_schema::<GLM5V_turbo>();
380        assert_vision_request_schema::<autoglm_phone>();
381        assert_vision_request_schema::<GLM4_6v>();
382        assert_vision_request_schema::<GLM4_6v_flash>();
383        assert_vision_request_schema::<GLM4_6v_flashx>();
384        assert_vision_request_schema::<GLM4v_flash>();
385        assert_vision_request_schema::<GLM4_1v_thinking_flash>();
386        assert_vision_request_schema::<GLM4_1v_thinking_flashx>();
387
388        assert_audio_request_schema::<GLM4_voice>();
389        assert_eq!(GLM5_2::MAX_TOKENS, 131_072);
390        assert_eq!(GLM4_voice::MAX_TOKENS, 4_096);
391    }
392
393    #[test]
394    fn official_chat_model_names_match_snapshot() {
395        let models = [
396            String::from(GLM5_2 {}),
397            String::from(GLM5_1 {}),
398            String::from(GLM5_turbo {}),
399            String::from(GLM5 {}),
400            String::from(GLM4_7 {}),
401            String::from(GLM4_7_flash {}),
402            String::from(GLM4_7_flashx {}),
403            String::from(GLM4_6 {}),
404            String::from(GLM4_5_air {}),
405            String::from(GLM4_5_airx {}),
406            String::from(GLM4_5_flash {}),
407            String::from(GLM4_flash_250414 {}),
408            String::from(GLM4_flashx_250414 {}),
409        ];
410
411        assert_eq!(
412            models,
413            [
414                "glm-5.2",
415                "glm-5.1",
416                "glm-5-turbo",
417                "glm-5",
418                "glm-4.7",
419                "glm-4.7-flash",
420                "glm-4.7-flashx",
421                "glm-4.6",
422                "glm-4.5-air",
423                "glm-4.5-airx",
424                "glm-4.5-flash",
425                "glm-4-flash-250414",
426                "glm-4-flashx-250414",
427            ]
428        );
429    }
430
431    #[test]
432    fn official_vision_model_names_match_snapshot() {
433        let models = [
434            String::from(GLM5V_turbo {}),
435            String::from(GLM4_6v {}),
436            String::from(autoglm_phone {}),
437            String::from(GLM4_6v_flash {}),
438            String::from(GLM4_6v_flashx {}),
439            String::from(GLM4v_flash {}),
440            String::from(GLM4_1v_thinking_flashx {}),
441            String::from(GLM4_1v_thinking_flash {}),
442        ];
443        assert_eq!(
444            models,
445            [
446                "glm-5v-turbo",
447                "glm-4.6v",
448                "autoglm-phone",
449                "glm-4.6v-flash",
450                "glm-4.6v-flashx",
451                "glm-4v-flash",
452                "glm-4.1v-thinking-flashx",
453                "glm-4.1v-thinking-flash",
454            ]
455        );
456    }
457
458    #[test]
459    fn official_realtime_model_names_match_asyncapi() {
460        assert_eq!(String::from(GLM_realtime_flash {}), "glm-realtime-flash");
461        assert_eq!(String::from(GLM_realtime_air {}), "glm-realtime-air");
462    }
463
464    #[test]
465    fn capability_markers_cover_the_frozen_sync_and_async_enums() {
466        assert_sync_model::<GLM5_2, TextMessage>();
467        assert_sync_model::<GLM5_1, TextMessage>();
468        assert_sync_model::<GLM5_turbo, TextMessage>();
469        assert_sync_model::<GLM5, TextMessage>();
470        assert_sync_model::<GLM4_7, TextMessage>();
471        assert_sync_model::<GLM4_7_flash, TextMessage>();
472        assert_sync_model::<GLM4_7_flashx, TextMessage>();
473        assert_sync_model::<GLM4_6, TextMessage>();
474        assert_sync_model::<GLM4_5_air, TextMessage>();
475        assert_sync_model::<GLM4_5_airx, TextMessage>();
476        assert_sync_model::<GLM4_5_flash, TextMessage>();
477        assert_sync_model::<GLM4_flash_250414, TextMessage>();
478        assert_sync_model::<GLM4_flashx_250414, TextMessage>();
479
480        assert_async_model::<GLM5_2, TextMessage>();
481        assert_async_model::<GLM5_1, TextMessage>();
482        assert_async_model::<GLM5_turbo, TextMessage>();
483        assert_async_model::<GLM5, TextMessage>();
484        assert_async_model::<GLM4_7, TextMessage>();
485        assert_async_model::<GLM4_6, TextMessage>();
486        assert_async_model::<GLM4_5_air, TextMessage>();
487        assert_async_model::<GLM4_5_airx, TextMessage>();
488        assert_async_model::<GLM4_5_flash, TextMessage>();
489        assert_async_model::<GLM4_flash_250414, TextMessage>();
490        assert_async_model::<GLM4_flashx_250414, TextMessage>();
491
492        assert_sync_model::<GLM5V_turbo, VisionMessage>();
493        assert_sync_model::<GLM4_6v, VisionMessage>();
494        assert_sync_model::<autoglm_phone, VisionMessage>();
495        assert_sync_model::<GLM4_6v_flash, VisionMessage>();
496        assert_sync_model::<GLM4_6v_flashx, VisionMessage>();
497        assert_sync_model::<GLM4v_flash, VisionMessage>();
498        assert_sync_model::<GLM4_1v_thinking_flash, VisionMessage>();
499        assert_sync_model::<GLM4_1v_thinking_flashx, VisionMessage>();
500
501        assert_async_model::<GLM5V_turbo, VisionMessage>();
502        assert_async_model::<GLM4_6v, VisionMessage>();
503        assert_async_model::<GLM4_6v_flash, VisionMessage>();
504        assert_async_model::<GLM4_6v_flashx, VisionMessage>();
505        assert_async_model::<GLM4v_flash, VisionMessage>();
506        assert_async_model::<GLM4_1v_thinking_flash, VisionMessage>();
507        assert_async_model::<GLM4_1v_thinking_flashx, VisionMessage>();
508
509        assert_sync_model::<GLM4_voice, VoiceMessage>();
510        assert_async_model::<GLM4_voice, VoiceMessage>();
511    }
512}