async_dashscope/operation/
validate.rs1use crate::operation::request::RequestTrait;
2use crate::{
3 error::{DashScopeError, Result},
4 operation::{common::Parameters, embeddings::EmbeddingsParameters},
5};
6
7pub enum ModelValidator {
13 Default,
15 NotSupportResultFormatText,
17 NotSupportEnableThinking,
19 NotSupportToolCall,
20 NotSupportJsonOutput,
21 DimensionNotMatch,
23}
24
25pub trait Validator<T> {
26 fn validate<R: RequestTrait<P = T> + ?Sized>(&self, params: &R) -> Result<()>;
28}
29
30impl Validator<EmbeddingsParameters> for ModelValidator {
31 fn validate<R: RequestTrait<P = EmbeddingsParameters> + ?Sized>(
32 &self,
33 params: &R,
34 ) -> Result<()> {
35 match self {
36 ModelValidator::DimensionNotMatch => {
37 if let Some(p) = params.parameters() {
43 let valid_dimensions = match params.model() {
44 "text-embedding-v1" | "text-embedding-v2" => {
45 vec![1536]
46 }
47 "text-embedding-v3" => {
48 vec![1024, 768, 512, 256, 128, 64]
49 }
50 "text-embedding-v4" => {
51 vec![2048, 1536, 1024, 768, 512, 256, 128, 64]
52 }
53 _ => vec![], };
55 if let Some(dimension) = p.dimension {
56 if !valid_dimensions.contains(&dimension) {
57 return Err(DashScopeError::InvalidArgument(format!(
58 "Invalid dimension: {} for model: {}",
59 dimension,
60 params.model()
61 )));
62 }
63 }
64 }
65 Ok(())
66 }
67 _ => Ok(()),
68 }
69 }
70}
71impl Validator<Parameters> for ModelValidator {
72 fn validate<R: RequestTrait<P = Parameters> + ?Sized>(&self, params: &R) -> Result<()> {
73 match self {
74 ModelValidator::Default => {
75 Ok(())
77 }
78 ModelValidator::NotSupportResultFormatText => {
79 if let Some(p) = params.parameters() {
81 if let Some(format) = &p.result_format {
82 if format == "text" {
83 return Err(DashScopeError::InvalidArgument(
84 "deepseek-r1 does not support result_format = text".into(),
85 ));
86 }
87 }
88 }
89 Ok(())
90 }
91 ModelValidator::NotSupportEnableThinking => {
92 if let Some(p) = params.parameters() {
93 if let Some(thinking) = p.enable_thinking {
94 if thinking {
95 return Err(DashScopeError::InvalidArgument(
96 "The model does not support enable_thinking = true".into(),
97 ));
98 }
99 }
100 }
101 Ok(())
102 }
103 ModelValidator::NotSupportJsonOutput => {
104 if let Some(p) = params.parameters() {
105 if let Some(response_format) = p.response_format.as_ref() {
106 if response_format.type_ == "json_object" {
107 return Err(DashScopeError::InvalidArgument(
108 "The model does not support response_format=json_object".into(),
109 ));
110 }
111 }
112 }
113 Ok(())
114 }
115
116 ModelValidator::NotSupportToolCall => {
117 if let Some(p) = params.parameters() {
118 if p.tools.is_some() {
119 return Err(DashScopeError::InvalidArgument(
120 "The model does not support tool call".into(),
121 ));
122 }
123 }
124 Ok(())
125 }
126
127 _ => Ok(()),
128 }
129 }
130}
131
132pub(crate) fn check_model_parameters(model: &str) -> Vec<ModelValidator> {
142 match model {
143 "deepseek-r1" => vec![
144 ModelValidator::NotSupportResultFormatText,
145 ModelValidator::NotSupportJsonOutput,
146 ],
147 "qwen-vl" | "qwen-audio" => vec![ModelValidator::NotSupportToolCall],
148 "Moonshot-Kimi-K2-Instruct" => vec![
149 ModelValidator::NotSupportEnableThinking,
150 ModelValidator::NotSupportResultFormatText,
151 ModelValidator::NotSupportJsonOutput,
152 ModelValidator::NotSupportToolCall,
153 ],
154 "text-embedding-v4" | "text-embedding-v3" | "text-embedding-v2" | "text-embedding-v1" => {
155 vec![ModelValidator::DimensionNotMatch]
156 }
157 _ => vec![ModelValidator::Default],
158 }
159}