///|
/// ProviderSchema — 各 Provider 请求/响应字段约束定义
///
/// 每个 Provider 适配器可声明自己的字段取值范围、是否必需、格式要求等。
/// SDK 在 encode/decode 时用这些约束做输入校验(请求)和输出校验(响应)。
///
/// 使用方式:
/// ```
/// let schema = ProviderSchema::openai()
/// let errors = schema.validate_request(lux_req)
/// ```
///|
/// FieldConstraint — 单字段约束
pub struct FieldConstraint {
min_val : Double?
max_val : Double?
required : Bool
allowed_values : Array[String]?
}
///|
pub fn FieldConstraint::new(
min_val : Double?,
max_val : Double?,
required : Bool,
allowed_values : Array[String]?,
) -> FieldConstraint {
{ min_val, max_val, required, allowed_values }
}
///|
/// ProviderSchema — 单个 Provider 的请求/响应字段约束集合
pub struct ProviderSchema {
provider_name : String
/// 请求字段约束
temperature : FieldConstraint
top_p : FieldConstraint
top_k : FieldConstraint
max_output_tokens : FieldConstraint
/// 响应字段约束
resp_min_choices : Int
/// 是否允许发送函数/工具调用字段(部分 provider 不支持)
supports_tools : Bool
/// 是否支持 system 指令作为顶层字段(而非消息列表中)
supports_system_instruction : Bool
/// 支持的 reasoning effort 值列表(None 表示不支持 reasoning;空数组表示全部支持)
supported_reasoning_efforts : Array[String]?
/// 额外约束:自定义校验函数列表 (field_name, error_msg)
extra_checks : Array[() -> Array[String]]?
}
///|
/// === 各 Provider 默认约束 ===
///|
/// OpenAI Chat Completions / Responses
pub fn ProviderSchema::openai() -> ProviderSchema {
{
provider_name: "openai",
temperature: {
min_val: Some(0.0),
max_val: Some(2.0),
required: false,
allowed_values: None,
},
top_p: {
min_val: Some(0.0),
max_val: Some(1.0),
required: false,
allowed_values: None,
},
top_k: {
min_val: None,
max_val: None,
required: false,
allowed_values: None,
},
max_output_tokens: {
min_val: Some(1.0),
max_val: None,
required: false,
allowed_values: None,
},
resp_min_choices: 1,
supports_tools: true,
supports_system_instruction: true,
supported_reasoning_efforts: None,
extra_checks: None,
}
}
///|
/// Anthropic Messages
pub fn ProviderSchema::anthropic() -> ProviderSchema {
{
provider_name: "anthropic",
temperature: {
min_val: Some(0.0),
max_val: Some(1.0),
required: false,
allowed_values: None,
},
top_p: {
min_val: Some(0.0),
max_val: Some(1.0),
required: false,
allowed_values: None,
},
top_k: {
min_val: Some(1.0),
max_val: None,
required: false,
allowed_values: None,
},
max_output_tokens: {
min_val: Some(1.0),
max_val: None,
required: false,
allowed_values: None,
},
resp_min_choices: 1,
supports_tools: true,
supports_system_instruction: true,
supported_reasoning_efforts: None,
extra_checks: None,
}
}
///|
/// Google Gemini
pub fn ProviderSchema::gemini() -> ProviderSchema {
{
provider_name: "gemini",
temperature: {
min_val: Some(0.0),
max_val: Some(1.0),
required: false,
allowed_values: None,
},
top_p: {
min_val: Some(0.0),
max_val: Some(1.0),
required: false,
allowed_values: None,
},
top_k: {
min_val: Some(1.0),
max_val: None,
required: false,
allowed_values: None,
},
max_output_tokens: {
min_val: Some(1.0),
max_val: None,
required: false,
allowed_values: None,
},
resp_min_choices: 1,
supports_tools: true,
supports_system_instruction: true,
supported_reasoning_efforts: None,
extra_checks: None,
}
}
///|
/// Azure OpenAI
pub fn ProviderSchema::azure() -> ProviderSchema {
// Azure OpenAI 与 OpenAI 约束大体相同
ProviderSchema::openai()
}
///|
/// 根据 provider 名获取对应 schema(自动匹配主名、别名与模型名)
pub fn get_schema(provider : String) -> ProviderSchema? {
// 1. 直接精确匹配主名
match schema_for_provider_name(provider) {
Some(schema) => Some(schema)
None =>
// 2. 别名/模型名:经注册表解析为主名后重查
match match_provider_name(provider) {
Some(reg) => schema_for_provider_name(reg.name)
None => None
}
}
}
///|
/// provider 名(主名/别名)→ schema
fn schema_for_provider_name(name : String) -> ProviderSchema? {
match name {
"openai" | "openai-chat" | "openai-codex" => Some(ProviderSchema::openai())
"anthropic" | "claude" => Some(ProviderSchema::anthropic())
"gemini" | "google" | "google-vertex" => Some(ProviderSchema::gemini())
"azure-openai" | "azure" => Some(ProviderSchema::azure())
_ => None
}
}
///|
/// 校验请求是否符合 Provider 的字段约束
/// 返回校验错误列表,空列表表示校验通过
pub fn ProviderSchema::validate_request(
self : ProviderSchema,
req : @lux.LucentRequest,
) -> Array[String] {
let errors : Array[String] = []
// 1. 通用校验(model 非空等)
let base = req.validate()
for e in base.errors {
errors.push(e)
}
// 2. Provider 特有约束
match req.options.temperature {
Some(t) => {
match self.temperature.min_val {
Some(min) =>
if t < min {
errors.push(
self.provider_name +
" temperature must be >= " +
min.to_string() +
", got " +
t.to_string(),
)
}
None => ()
}
match self.temperature.max_val {
Some(max) =>
if t > max {
errors.push(
self.provider_name +
" temperature must be <= " +
max.to_string() +
", got " +
t.to_string(),
)
}
None => ()
}
}
None =>
if self.temperature.required {
errors.push(self.provider_name + " temperature is required")
}
}
match req.options.top_p {
Some(p) => {
match self.top_p.min_val {
Some(min) =>
if p < min {
errors.push(
self.provider_name + " top_p must be >= " + min.to_string(),
)
}
None => ()
}
match self.top_p.max_val {
Some(max) =>
if p > max {
errors.push(
self.provider_name + " top_p must be <= " + max.to_string(),
)
}
None => ()
}
}
None => ()
}
match req.options.top_k {
Some(k) =>
match self.top_k.min_val {
Some(min) =>
if k < min.to_int() {
errors.push(
self.provider_name + " top_k must be >= " + min.to_string(),
)
}
None => ()
}
None => ()
}
match req.options.max_output_tokens {
Some(m) =>
match self.max_output_tokens.min_val {
Some(min) =>
if m < min.to_int() {
errors.push(
self.provider_name +
" max_output_tokens must be >= " +
min.to_string(),
)
}
None => ()
}
None => ()
}
// 3. 额外自定义校验
match self.extra_checks {
Some(checks) =>
for check in checks {
for e in check() {
errors.push(e)
}
}
None => ()
}
errors
}
///|
/// 校验响应是否符合 Provider 的字段约束
/// 返回校验错误列表,空列表表示校验通过
pub fn ProviderSchema::validate_response(
self : ProviderSchema,
resp : @lux.LucentResponse,
) -> Array[String] {
let errors : Array[String] = []
// 通用校验
let base = resp.validate()
for e in base.errors {
errors.push(e)
}
// 最少 choices 数
if resp.choices.length() < self.resp_min_choices {
errors.push(
self.provider_name +
" response must have at least " +
self.resp_min_choices.to_string() +
" choice(s)",
)
}
errors
}