From e56e099c1fa89877b22755cb45136747d838bdc7 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Thu, 10 Oct 2024 18:18:09 -0700 Subject: [PATCH 1/2] Add support for allowing clients to limit which finish_reasons they allow. Clients can do: ``` client MyClient { provider "openai" options { finish_reason_whitelist ["stop"] } } client MyClient { provider "openai" options { finish_reason_blacklist ["content_policy"] } } ``` --- .../snippets/clients/providers/anthropic.mdx | 1 + .../clients/providers/aws-bedrock.mdx | 1 + .../docs/snippets/clients/providers/azure.mdx | 1 + .../snippets/clients/providers/gemini.mdx | 1 + docs/docs/snippets/clients/providers/groq.mdx | 1 + .../snippets/clients/providers/ollama.mdx | 1 + .../clients/providers/openai-generic.mdx | 3 + .../snippets/clients/providers/openai.mdx | 1 + .../snippets/clients/providers/vertex.mdx | 1 + docs/snippets/finish-reason.mdx | 13 + engine/baml-runtime/src/cli/serve/error.rs | 1 + .../src/internal/llm_client/mod.rs | 14 +- .../internal/llm_client/orchestrator/call.rs | 17 +- .../internal/llm_client/orchestrator/mod.rs | 13 +- .../llm_client/orchestrator/stream.rs | 17 +- .../primitive/anthropic/anthropic_client.rs | 72 ++-- .../llm_client/primitive/aws/aws_client.rs | 51 ++- .../primitive/google/googleai_client.rs | 70 ++-- .../src/internal/llm_client/primitive/mod.rs | 3 + .../primitive/openai/openai_client.rs | 42 +-- .../primitive/openai/properties/azure.rs | 87 ++--- .../primitive/openai/properties/generic.rs | 60 ++-- .../primitive/openai/properties/mod.rs | 5 +- .../primitive/openai/properties/ollama.rs | 49 +-- .../primitive/openai/properties/openai.rs | 52 +-- .../primitive/vertex/vertex_client.rs | 157 ++++----- .../internal/llm_client/properties_hander.rs | 193 +++++++++++ .../internal/llm_client/strategy/fallback.rs | 19 +- .../llm_client/strategy/roundrobin.rs | 25 +- .../src/internal/llm_client/traits/mod.rs | 6 +- .../src/python/templates/async_client.py.j2 | 4 +- .../src/python/templates/sync_client.py.j2 | 4 +- .../src/python/templates/type_builder.py.j2 | 22 +- .../python_src/baml_py/errors.py | 3 +- engine/language_client_python/src/errors.rs | 1 + .../language_client_typescript/src/errors.rs | 1 + .../python/baml_client/async_client.py | 312 +++++++++--------- integ-tests/python/baml_client/sync_client.py | 312 +++++++++--------- .../python/baml_client/type_builder.py | 113 ++++--- integ-tests/python/tests/test_functions.py | 91 +++-- .../typescript/tests/integ-tests.test.ts | 44 +++ 41 files changed, 1014 insertions(+), 870 deletions(-) create mode 100644 docs/snippets/finish-reason.mdx create mode 100644 engine/baml-runtime/src/internal/llm_client/properties_hander.rs diff --git a/docs/docs/snippets/clients/providers/anthropic.mdx b/docs/docs/snippets/clients/providers/anthropic.mdx index 6477d781b..6773e23b0 100644 --- a/docs/docs/snippets/clients/providers/anthropic.mdx +++ b/docs/docs/snippets/clients/providers/anthropic.mdx @@ -68,6 +68,7 @@ client MyClient { ``` + ## Forwarded options diff --git a/docs/docs/snippets/clients/providers/aws-bedrock.mdx b/docs/docs/snippets/clients/providers/aws-bedrock.mdx index 47d986749..8d022e400 100644 --- a/docs/docs/snippets/clients/providers/aws-bedrock.mdx +++ b/docs/docs/snippets/clients/providers/aws-bedrock.mdx @@ -43,6 +43,7 @@ limited to: We don't have any checks for this field, you can pass any string you wish. + ## Forwarded options diff --git a/docs/docs/snippets/clients/providers/azure.mdx b/docs/docs/snippets/clients/providers/azure.mdx index 88667812a..340bd7df8 100644 --- a/docs/docs/snippets/clients/providers/azure.mdx +++ b/docs/docs/snippets/clients/providers/azure.mdx @@ -96,6 +96,7 @@ client MyClient { ``` + ## Forwarded options diff --git a/docs/docs/snippets/clients/providers/gemini.mdx b/docs/docs/snippets/clients/providers/gemini.mdx index a3cadfa26..75643203f 100644 --- a/docs/docs/snippets/clients/providers/gemini.mdx +++ b/docs/docs/snippets/clients/providers/gemini.mdx @@ -82,6 +82,7 @@ client MyClient { ``` + ## Forwarded options diff --git a/docs/docs/snippets/clients/providers/groq.mdx b/docs/docs/snippets/clients/providers/groq.mdx index 1d5326768..76c1ac0f2 100644 --- a/docs/docs/snippets/clients/providers/groq.mdx +++ b/docs/docs/snippets/clients/providers/groq.mdx @@ -16,6 +16,7 @@ client MyClient { base_url "https://api.groq.com/openai/v1" api_key env.GROQ_API_KEY model "llama3-70b-8192" + default_role "user" } } ``` diff --git a/docs/docs/snippets/clients/providers/ollama.mdx b/docs/docs/snippets/clients/providers/ollama.mdx index 664af9ca2..b233b7b68 100644 --- a/docs/docs/snippets/clients/providers/ollama.mdx +++ b/docs/docs/snippets/clients/providers/ollama.mdx @@ -62,6 +62,7 @@ client MyClient { ``` + ## Forwarded options diff --git a/docs/docs/snippets/clients/providers/openai-generic.mdx b/docs/docs/snippets/clients/providers/openai-generic.mdx index c19063e50..ae4f4899d 100644 --- a/docs/docs/snippets/clients/providers/openai-generic.mdx +++ b/docs/docs/snippets/clients/providers/openai-generic.mdx @@ -63,6 +63,9 @@ client MyClient { + + + ## Forwarded options MyClient { + ## Forwarded options diff --git a/docs/docs/snippets/clients/providers/vertex.mdx b/docs/docs/snippets/clients/providers/vertex.mdx index 7d9fddfbf..cf5c15bc8 100644 --- a/docs/docs/snippets/clients/providers/vertex.mdx +++ b/docs/docs/snippets/clients/providers/vertex.mdx @@ -218,6 +218,7 @@ client MyClient { ``` + ## Forwarded options diff --git a/docs/snippets/finish-reason.mdx b/docs/snippets/finish-reason.mdx new file mode 100644 index 000000000..4035a41da --- /dev/null +++ b/docs/snippets/finish-reason.mdx @@ -0,0 +1,13 @@ + + A list of finish reasons to allow. If set, any response with a finish reason not in this list will be rejected. + Empty finish reasons are always allowed. + + **Default: `[]`** + + + + A list of finish reasons to reject. If set, any response with a finish reason in this list will be rejected. + Empty finish reasons are always allowed. + + **Default: `[]`** + \ No newline at end of file diff --git a/engine/baml-runtime/src/cli/serve/error.rs b/engine/baml-runtime/src/cli/serve/error.rs index 236e4015f..91d467427 100644 --- a/engine/baml-runtime/src/cli/serve/error.rs +++ b/engine/baml-runtime/src/cli/serve/error.rs @@ -61,6 +61,7 @@ impl BamlError { message: format!("Something went wrong with the LLM client: {:?}", err), }, crate::internal::llm_client::ErrorCode::Other(_) + | crate::internal::llm_client::ErrorCode::BadRequest | crate::internal::llm_client::ErrorCode::InvalidAuthentication | crate::internal::llm_client::ErrorCode::NotSupported | crate::internal::llm_client::ErrorCode::RateLimited diff --git a/engine/baml-runtime/src/internal/llm_client/mod.rs b/engine/baml-runtime/src/internal/llm_client/mod.rs index 934526e17..30c2f61ad 100644 --- a/engine/baml-runtime/src/internal/llm_client/mod.rs +++ b/engine/baml-runtime/src/internal/llm_client/mod.rs @@ -6,6 +6,7 @@ pub mod llm_provider; pub mod orchestrator; pub mod primitive; +mod properties_hander; pub mod retry_policy; mod strategy; pub mod traits; @@ -169,6 +170,7 @@ pub enum ErrorCode { RateLimited, // 429 ServerError, // 500 ServiceUnavailable, // 503 + BadRequest, // 400 // We failed to parse the response UnsupportedResponse(u16), @@ -184,6 +186,7 @@ impl ErrorCode { ErrorCode::NotSupported => "NotSupported (403)".into(), ErrorCode::RateLimited => "RateLimited (429)".into(), ErrorCode::ServerError => "ServerError (500)".into(), + ErrorCode::BadRequest => "BadRequest (400)".into(), ErrorCode::ServiceUnavailable => "ServiceUnavailable (503)".into(), ErrorCode::UnsupportedResponse(code) => format!("BadResponse {}", code), ErrorCode::Other(code) => format!("Unspecified error code: {}", code), @@ -192,6 +195,7 @@ impl ErrorCode { pub fn from_status(status: StatusCode) -> Self { match status.as_u16() { + 400 => ErrorCode::BadRequest, 401 => ErrorCode::InvalidAuthentication, 403 => ErrorCode::NotSupported, 429 => ErrorCode::RateLimited, @@ -203,6 +207,7 @@ impl ErrorCode { pub fn from_u16(code: u16) -> Self { match code { + 400 => ErrorCode::BadRequest, 401 => ErrorCode::InvalidAuthentication, 403 => ErrorCode::NotSupported, 429 => ErrorCode::RateLimited, @@ -214,6 +219,7 @@ impl ErrorCode { pub fn to_u16(&self) -> u16 { match self { + ErrorCode::BadRequest => 400, ErrorCode::InvalidAuthentication => 401, ErrorCode::NotSupported => 403, ErrorCode::RateLimited => 429, @@ -339,9 +345,9 @@ impl crate::tracing::Visualize for LLMErrorResponse { fn resolve_properties_walker( client: &ClientWalker, ctx: &crate::RuntimeContext, -) -> Result> { +) -> Result { use anyhow::Context; - (&client.item.elem.options) + let result = (&client.item.elem.options) .iter() .map(|(k, v)| { Ok(( @@ -354,5 +360,7 @@ fn resolve_properties_walker( ))?, )) }) - .collect::>>() + .collect::>>()?; + + Ok(properties_hander::PropertiesHandler::new(result)) } diff --git a/engine/baml-runtime/src/internal/llm_client/orchestrator/call.rs b/engine/baml-runtime/src/internal/llm_client/orchestrator/call.rs index f16408694..d69263e31 100644 --- a/engine/baml-runtime/src/internal/llm_client/orchestrator/call.rs +++ b/engine/baml-runtime/src/internal/llm_client/orchestrator/call.rs @@ -39,13 +39,26 @@ pub async fn orchestrate( let prompt = match node.render_prompt(ir, prompt, ctx, params).await { Ok(p) => p, Err(e) => { - results.push((node.scope, LLMResponse::InternalFailure(e.to_string()), None)); + results.push(( + node.scope, + LLMResponse::InternalFailure(e.to_string()), + None, + )); continue; } }; let response = node.single_call(&ctx, &prompt).await; let parsed_response = match &response { - LLMResponse::Success(s) => Some(parse_fn(&s.content)), + LLMResponse::Success(s) => { + if node.is_valid_finish_reason(s) { + Some(parse_fn(&s.content)) + } else { + Some(Err(anyhow::anyhow!( + "Non-terminal finish reason: {}", + s.metadata.finish_reason.as_deref().unwrap_or("") + ))) + } + } _ => None, }; diff --git a/engine/baml-runtime/src/internal/llm_client/orchestrator/mod.rs b/engine/baml-runtime/src/internal/llm_client/orchestrator/mod.rs index c8069a961..29446e686 100644 --- a/engine/baml-runtime/src/internal/llm_client/orchestrator/mod.rs +++ b/engine/baml-runtime/src/internal/llm_client/orchestrator/mod.rs @@ -9,7 +9,9 @@ use crate::{ RuntimeContext, }; -use super::traits::WithRenderRawCurl; +use super::properties_hander::FinishReasonOptions; +use super::traits::{WithClientProperties, WithRenderRawCurl}; +use super::LLMCompleteResponse; use super::{ strategy::roundrobin::RoundRobinStrategy, traits::{StreamResponse, WithPrompt, WithSingleCallable, WithStreamable}, @@ -81,6 +83,15 @@ impl OrchestratorNode { _ => None, }) } + + pub fn is_valid_finish_reason(&self, response: &LLMCompleteResponse) -> bool { + let Some(finish_reason) = response.metadata.finish_reason.as_deref() else { + return true; + }; + self.provider + .finish_reason_handling() + .map_or(true, |options| options.is_allowed(finish_reason)) + } } #[derive(Default, Clone, Serialize)] diff --git a/engine/baml-runtime/src/internal/llm_client/orchestrator/stream.rs b/engine/baml-runtime/src/internal/llm_client/orchestrator/stream.rs index ecf0ac5fb..a3dc7fcf8 100644 --- a/engine/baml-runtime/src/internal/llm_client/orchestrator/stream.rs +++ b/engine/baml-runtime/src/internal/llm_client/orchestrator/stream.rs @@ -46,7 +46,11 @@ where let prompt = match node.render_prompt(ir, prompt, ctx, params).await { Ok(p) => p, Err(e) => { - results.push((node.scope, LLMResponse::InternalFailure(e.to_string()), None)); + results.push(( + node.scope, + LLMResponse::InternalFailure(e.to_string()), + None, + )); continue; } }; @@ -89,7 +93,16 @@ where }; let parsed_response = match &final_response { - LLMResponse::Success(s) => Some(parse_fn(&s.content)), + LLMResponse::Success(s) => { + if node.is_valid_finish_reason(s) { + Some(parse_fn(&s.content)) + } else { + Some(Err(anyhow::anyhow!( + "Non-terminal finish reason: {}", + s.metadata.finish_reason.as_deref().unwrap_or("") + ))) + } + } _ => None, }; let sleep_duration = node.error_sleep_duration().cloned(); diff --git a/engine/baml-runtime/src/internal/llm_client/primitive/anthropic/anthropic_client.rs b/engine/baml-runtime/src/internal/llm_client/primitive/anthropic/anthropic_client.rs index 807f08b0f..82b5241c1 100644 --- a/engine/baml-runtime/src/internal/llm_client/primitive/anthropic/anthropic_client.rs +++ b/engine/baml-runtime/src/internal/llm_client/primitive/anthropic/anthropic_client.rs @@ -1,4 +1,5 @@ use crate::internal::llm_client::{ + properties_hander::PropertiesHandler, traits::{ToProviderMessage, ToProviderMessageExt, WithClientProperties}, AllowedMetadata, ResolveMediaUrls, }; @@ -43,6 +44,7 @@ struct PostRequestProperities { headers: HashMap, proxy_url: Option, allowed_metadata: AllowedMetadata, + finish_reason: Option, // These are passed directly to the Anthropic API. properties: HashMap, } @@ -62,56 +64,32 @@ pub struct AnthropicClient { // resolves/constructs PostRequestProperties from the client's options and runtime context, fleshing out the needed headers and parameters // basically just reads the client's options and matches them to needed properties or defaults them fn resolve_properties( - mut properties: HashMap, + mut properties: PropertiesHandler, ctx: &RuntimeContext, ) -> Result { // this is a required field - properties - .entry("max_tokens".into()) - .or_insert_with(|| 4096.into()); - - let default_role = properties - .remove("default_role") - .and_then(|v| v.as_str().map(|s| s.to_string())) - .unwrap_or_else(|| "system".to_string()); + let default_role = properties.pull_default_role("system")?; let base_url = properties - .remove("base_url") - .and_then(|v| v.as_str().map(|s| s.to_string())) - .unwrap_or_else(|| "https://api.anthropic.com".to_string()); - + .pull_base_url()? + .unwrap_or_else(|| "https://api.anthropic.com".into()); let api_key = properties - .remove("api_key") - .and_then(|v| v.as_str().map(|s| s.to_string())) + .pull_api_key()? .or_else(|| ctx.env.get("ANTHROPIC_API_KEY").map(|s| s.to_string())); - let allowed_metadata = match properties.remove("allowed_role_metadata") { - Some(allowed_metadata) => serde_json::from_value(allowed_metadata).context( - "allowed_role_metadata must be an array of keys. For example: ['key1', 'key2']", - )?, - None => AllowedMetadata::None, - }; - - let mut headers = match properties.remove("headers") { - Some(headers) => headers - .as_object() - .context("headers must be a map of strings to strings")? - .iter() - .map(|(k, v)| { - Ok(( - k.to_string(), - v.as_str() - .context(format!("Header '{}' must be a string", k))? - .to_string(), - )) - }) - .collect::>>()?, - None => Default::default(), - }; - + let allowed_metadata = properties.pull_allowed_role_metadata()?; + let mut headers = properties.pull_headers()?; headers .entry("anthropic-version".to_string()) .or_insert("2023-06-01".to_string()); + let finish_reason = properties.pull_finish_reason_options()?; + + let mut properties = properties.finalize(); + // Anthropic has a very low max_tokens by default, so we increase it to 4096. + properties + .entry("max_tokens".into()) + .or_insert_with(|| 4096.into()); + let properties = properties; Ok(PostRequestProperities { default_role, @@ -119,6 +97,7 @@ fn resolve_properties( api_key, headers, allowed_metadata, + finish_reason, properties, proxy_url: ctx.env.get("BOUNDARY_PROXY_URL").map(|s| s.to_string()), }) @@ -138,6 +117,12 @@ impl WithClientProperties for AnthropicClient { fn client_properties(&self) -> &HashMap { &self.properties.properties } + + fn finish_reason_handling( + &self, + ) -> Option<&crate::internal::llm_client::properties_hander::FinishReasonOptions> { + self.properties.finish_reason.as_ref() + } } impl WithClient for AnthropicClient { @@ -308,14 +293,7 @@ impl WithStreamChat for AnthropicClient { // constructs base client and resolves properties based on context impl AnthropicClient { pub fn dynamic_new(client: &ClientProperty, ctx: &RuntimeContext) -> Result { - let properties = resolve_properties( - client - .options - .iter() - .map(|(k, v)| Ok((k.clone(), json!(v)))) - .collect::>>()?, - ctx, - )?; + let properties = resolve_properties(client.property_handler()?, ctx)?; let default_role = properties.default_role.clone(); Ok(Self { name: client.name.clone(), diff --git a/engine/baml-runtime/src/internal/llm_client/primitive/aws/aws_client.rs b/engine/baml-runtime/src/internal/llm_client/primitive/aws/aws_client.rs index 84a2bfcd2..7ac55792b 100644 --- a/engine/baml-runtime/src/internal/llm_client/primitive/aws/aws_client.rs +++ b/engine/baml-runtime/src/internal/llm_client/primitive/aws/aws_client.rs @@ -17,6 +17,7 @@ use serde_json::Map; use web_time::Instant; use web_time::SystemTime; +use crate::internal::llm_client::properties_hander::FinishReasonOptions; use crate::internal::llm_client::traits::{ToProviderMessageExt, WithClientProperties}; use crate::internal::llm_client::AllowedMetadata; use crate::internal::llm_client::{ @@ -38,6 +39,7 @@ struct RequestProperties { default_role: String, inference_config: Option, allowed_metadata: AllowedMetadata, + finish_reason: Option, request_options: HashMap, ctx_env: HashMap, @@ -53,38 +55,18 @@ pub struct AwsClient { } fn resolve_properties(client: &ClientWalker, ctx: &RuntimeContext) -> Result { - let mut properties = (&client.item.elem.options) - .iter() - .map(|(k, v)| { - Ok(( - k.into(), - ctx.resolve_expression::(v) - .context(format!( - "client {} could not resolve options.{}", - client.name(), - k - ))?, - )) - }) - .collect::>>()?; - - let model_id = properties - .remove("model_id") - .context("model_id is required")? - .as_str() - .context("model_id should be a string")? - .to_string(); - - let default_role = properties - .remove("default_role") - .and_then(|v| v.as_str().map(|s| s.to_string())) - .unwrap_or_else(|| "user".to_string()); - let allowed_metadata = match properties.remove("allowed_role_metadata") { - Some(allowed_metadata) => serde_json::from_value(allowed_metadata) - .context("allowed_role_metadata must be an array of keys. For example: ['key1', 'key2']")?, - None => AllowedMetadata::None, + let mut properties = super::super::resolve_properties_walker(client, ctx)?; + + let model_id = match properties.remove_str("model_id")? { + Some(model_id) => model_id, + None => { + anyhow::bail!("model_id is required for AWS Bedrock client"); + } }; - let inference_config = match properties.remove("inference_configuration") { + let default_role = properties.pull_default_role("user")?; + let allowed_metadata = properties.pull_allowed_role_metadata()?; + + let inference_config = match properties.remove("inference_configuration")? { Some(v) => Some( super::types::InferenceConfiguration::deserialize(v) .context("Failed to parse inference_configuration")? @@ -92,13 +74,15 @@ fn resolve_properties(client: &ClientWalker, ctx: &RuntimeContext) -> Result None, }; + let finish_reason = properties.pull_finish_reason_options()?; Ok(RequestProperties { model_id, default_role, inference_config, allowed_metadata, - request_options: properties, + finish_reason, + request_options: properties.finalize(), ctx_env: ctx.env.clone(), }) } @@ -301,6 +285,9 @@ impl WithClientProperties for AwsClient { fn allowed_metadata(&self) -> &crate::internal::llm_client::AllowedMetadata { &self.properties.allowed_metadata } + fn finish_reason_handling(&self) -> Option<&FinishReasonOptions> { + self.properties.finish_reason.as_ref() + } } impl WithClient for AwsClient { diff --git a/engine/baml-runtime/src/internal/llm_client/primitive/google/googleai_client.rs b/engine/baml-runtime/src/internal/llm_client/primitive/google/googleai_client.rs index 12c59081f..e08d9ee94 100644 --- a/engine/baml-runtime/src/internal/llm_client/primitive/google/googleai_client.rs +++ b/engine/baml-runtime/src/internal/llm_client/primitive/google/googleai_client.rs @@ -1,4 +1,5 @@ use crate::client_registry::ClientProperty; +use crate::internal::llm_client::properties_hander::{FinishReasonOptions, PropertiesHandler}; use crate::internal::llm_client::traits::{ ToProviderMessage, ToProviderMessageExt, WithClientProperties, }; @@ -23,6 +24,7 @@ use anyhow::{Context, Result}; use baml_types::{BamlMedia, BamlMediaContent}; use eventsource_stream::Eventsource; use futures::StreamExt; +use http::header; use internal_baml_core::ir::ClientWalker; use internal_baml_jinja::{ChatMessagePart, RenderContext_Client, RenderedChatMessage}; use serde_json::json; @@ -36,6 +38,7 @@ struct PostRequestProperities { model_id: Option, properties: HashMap, allowed_metadata: AllowedMetadata, + finish_reason: Option, } pub struct GoogleAIClient { @@ -48,65 +51,34 @@ pub struct GoogleAIClient { } fn resolve_properties( - mut properties: HashMap, + mut properties: PropertiesHandler, ctx: &RuntimeContext, ) -> Result { - let default_role = properties - .remove("default_role") - .and_then(|v| v.as_str().map(|s| s.to_string())) - .unwrap_or_else(|| "user".to_string()); - + let default_role = properties.pull_default_role("user")?; let api_key = properties - .remove("api_key") - .and_then(|v| v.as_str().map(|s| s.to_string())) + .pull_api_key()? .or_else(|| ctx.env.get("GOOGLE_API_KEY").map(|s| s.to_string())); let model_id = properties - .remove("model") - .and_then(|v| v.as_str().map(|s| s.to_string())) - .or_else(|| Some("gemini-1.5-flash".to_string())); + .remove_str("model")? + .unwrap_or_else(|| "gemini-1.5-flash".to_string()); let base_url = properties - .remove("base_url") - .and_then(|v| v.as_str().map(|s| s.to_string())) + .pull_base_url()? .unwrap_or_else(|| "https://generativelanguage.googleapis.com/v1beta".to_string()); - let allowed_metadata = match properties.remove("allowed_role_metadata") { - Some(allowed_metadata) => serde_json::from_value(allowed_metadata).context( - "allowed_role_metadata must be an array of keys. For example: ['key1', 'key2']", - )?, - None => AllowedMetadata::None, - }; - - let headers = properties.remove("headers").map(|v| { - if let Some(v) = v.as_object() { - v.iter() - .map(|(k, v)| { - Ok(( - k.to_string(), - match v { - serde_json::Value::String(s) => s.to_string(), - _ => anyhow::bail!("Header '{k}' must be a string"), - }, - )) - }) - .collect::>>() - } else { - Ok(Default::default()) - } - }); - let headers = match headers { - Some(h) => h?, - None => Default::default(), - }; + let allowed_metadata = properties.pull_allowed_role_metadata()?; + let headers = properties.pull_headers()?; + let finish_reason = properties.pull_finish_reason_options()?; Ok(PostRequestProperities { default_role, api_key, headers, - properties, + properties: properties.finalize(), base_url, - model_id, + model_id: Some(model_id), + finish_reason, proxy_url: ctx.env.get("BOUNDARY_PROXY_URL").map(|s| s.to_string()), allowed_metadata, }) @@ -125,6 +97,9 @@ impl WithClientProperties for GoogleAIClient { fn allowed_metadata(&self) -> &crate::internal::llm_client::AllowedMetadata { &self.properties.allowed_metadata } + fn finish_reason_handling(&self) -> Option<&FinishReasonOptions> { + self.properties.finish_reason.as_ref() + } } impl WithClient for GoogleAIClient { @@ -275,14 +250,7 @@ impl GoogleAIClient { } pub fn dynamic_new(client: &ClientProperty, ctx: &RuntimeContext) -> Result { - let properties = resolve_properties( - client - .options - .iter() - .map(|(k, v)| Ok((k.clone(), json!(v)))) - .collect::>>()?, - ctx, - )?; + let properties = resolve_properties(client.property_handler()?, ctx)?; let default_role = properties.default_role.clone(); Ok(Self { diff --git a/engine/baml-runtime/src/internal/llm_client/primitive/mod.rs b/engine/baml-runtime/src/internal/llm_client/primitive/mod.rs index 4dd21f4e4..321731aac 100644 --- a/engine/baml-runtime/src/internal/llm_client/primitive/mod.rs +++ b/engine/baml-runtime/src/internal/llm_client/primitive/mod.rs @@ -93,6 +93,9 @@ impl WithClientProperties for LLMPrimitiveProvider { fn allowed_metadata(&self) -> &super::AllowedMetadata { match_llm_provider!(self, allowed_metadata) } + fn finish_reason_handling(&self) -> Option<&super::properties_hander::FinishReasonOptions> { + match_llm_provider!(self, finish_reason_handling) + } } impl TryFrom<(&ClientProperty, &RuntimeContext)> for LLMPrimitiveProvider { diff --git a/engine/baml-runtime/src/internal/llm_client/primitive/openai/openai_client.rs b/engine/baml-runtime/src/internal/llm_client/primitive/openai/openai_client.rs index cde24f897..ac079011d 100644 --- a/engine/baml-runtime/src/internal/llm_client/primitive/openai/openai_client.rs +++ b/engine/baml-runtime/src/internal/llm_client/primitive/openai/openai_client.rs @@ -57,6 +57,11 @@ impl WithClientProperties for OpenAIClient { fn allowed_metadata(&self) -> &crate::internal::llm_client::AllowedMetadata { &self.properties.allowed_metadata } + fn finish_reason_handling( + &self, + ) -> Option<&crate::internal::llm_client::properties_hander::FinishReasonOptions> { + self.properties.finish_reason.as_ref() + } } impl WithClient for OpenAIClient { @@ -204,6 +209,7 @@ impl WithChat for OpenAIClient { finish_reason: match response.choices.get(0) { Some(c) => match c.finish_reason { Some(FinishReason::Stop) => Some(FinishReason::Stop.to_string()), + Some(other) => Some(other.to_string()), _ => None, }, None => None, @@ -485,14 +491,7 @@ impl OpenAIClient { } pub fn dynamic_new(client: &ClientProperty, ctx: &RuntimeContext) -> Result { - let properties = properties::openai::resolve_properties( - client - .options - .iter() - .map(|(k, v)| Ok((k.clone(), json!(v)))) - .collect::>>()?, - &ctx, - )?; + let properties = properties::openai::resolve_properties(client.property_handler()?, &ctx)?; make_openai_client!(client, properties, "openai", dynamic) } @@ -500,14 +499,7 @@ impl OpenAIClient { client: &ClientProperty, ctx: &RuntimeContext, ) -> Result { - let properties = properties::generic::resolve_properties( - client - .options - .iter() - .map(|(k, v)| Ok((k.clone(), json!(v)))) - .collect::>>()?, - ctx, - )?; + let properties = properties::generic::resolve_properties(client.property_handler()?, ctx)?; make_openai_client!(client, properties, "openai-generic", dynamic) } @@ -515,14 +507,7 @@ impl OpenAIClient { client: &ClientProperty, ctx: &RuntimeContext, ) -> Result { - let properties = properties::ollama::resolve_properties( - client - .options - .iter() - .map(|(k, v)| Ok((k.clone(), json!(v)))) - .collect::>>()?, - ctx, - )?; + let properties = properties::ollama::resolve_properties(client.property_handler()?, ctx)?; make_openai_client!(client, properties, "ollama", dynamic) } @@ -530,14 +515,7 @@ impl OpenAIClient { client: &ClientProperty, ctx: &RuntimeContext, ) -> Result { - let properties = properties::azure::resolve_properties( - client - .options - .iter() - .map(|(k, v)| Ok((k.clone(), json!(v)))) - .collect::>>()?, - ctx, - )?; + let properties = properties::azure::resolve_properties(client.property_handler()?, ctx)?; make_openai_client!(client, properties, "azure", dynamic) } } diff --git a/engine/baml-runtime/src/internal/llm_client/primitive/openai/properties/azure.rs b/engine/baml-runtime/src/internal/llm_client/primitive/openai/properties/azure.rs index 75f9383e8..1e5fa019b 100644 --- a/engine/baml-runtime/src/internal/llm_client/primitive/openai/properties/azure.rs +++ b/engine/baml-runtime/src/internal/llm_client/primitive/openai/properties/azure.rs @@ -2,93 +2,59 @@ use std::collections::HashMap; use anyhow::{Context, Result}; -use crate::{internal::llm_client::AllowedMetadata, RuntimeContext}; +use crate::{ + internal::llm_client::{properties_hander::PropertiesHandler, AllowedMetadata}, + RuntimeContext, +}; use super::PostRequestProperties; pub fn resolve_properties( - mut properties: HashMap, + mut properties: PropertiesHandler, ctx: &RuntimeContext, ) -> Result { // POST https://{your-resource-name}.openai.azure.com/openai/deployments/{deployment-id}/chat/completions?api-version={api-version} - let default_role = properties - .remove("default_role") - .and_then(|v| v.as_str().map(|s| s.to_string())) - .unwrap_or_else(|| "system".to_string()); - let allowed_metadata = match properties.remove("allowed_role_metadata") { - Some(allowed_metadata) => serde_json::from_value(allowed_metadata) - .context("allowed_role_metadata must be an array of keys. For example: ['key1', 'key2']")?, - None => AllowedMetadata::None, - }; - // Ensure that either (resource_name, deployment_id) or base_url is provided - let base_url = properties.remove("base_url"); - let resource_name = properties.remove("resource_name"); - let deployment_id = properties.remove("deployment_id"); - let api_version = properties.remove("api_version"); + let default_role = properties.pull_default_role("system")?; + let allowed_metadata = properties.pull_allowed_role_metadata()?; + + let base_url = properties.pull_base_url()?; + let resource_name = properties.remove_str("resource_name")?; + let deployment_id = properties.remove_str("deployment_id")?; + let api_version = properties.remove_str("api_version")?; + // Ensure that either (resource_name, deployment_id) or base_url is provided let base_url = match (base_url, resource_name, deployment_id) { - (Some(base_url), None, None) => base_url - .as_str() - .map(|s| s.to_string()) - .context("base_url must be a string")?, + (Some(base_url), None, None) => base_url, (None, Some(resource_name), Some(deployment_id)) => { - format!( - "https://{}.openai.azure.com/openai/deployments/{}", - resource_name - .as_str() - .context("resource_name must be a string")?, - deployment_id - .as_str() - .context("deployment_id must be a string")? - ) + format!("https://{resource_name}.openai.azure.com/openai/deployments/{deployment_id}") + } + _ => { + anyhow::bail!("Either base_url or both (resource_name, deployment_id) must be provided") } - _ => anyhow::bail!("Either base_url or (resource_name, deployment_id) must be provided"), }; let api_key = properties - .remove("api_key") - .and_then(|v| v.as_str().map(|s| s.to_string())) + .pull_api_key()? .or_else(|| ctx.env.get("AZURE_OPENAI_API_KEY").map(|s| s.to_string())); - - let headers = properties.remove("headers").map(|v| { - if let Some(v) = v.as_object() { - v.iter() - .map(|(k, v)| { - Ok(( - k.to_string(), - match v { - serde_json::Value::String(s) => s.to_string(), - _ => anyhow::bail!("Header '{k}' must be a string"), - }, - )) - }) - .collect::>>() - } else { - Ok(Default::default()) - } - }); - let mut headers = match headers { - Some(h) => h?, - None => Default::default(), - }; - + let mut headers = properties.pull_headers()?; if let Some(api_key) = &api_key { headers.insert("API-KEY".to_string(), api_key.clone()); } + let headers = headers; let mut query_params = HashMap::new(); if let Some(v) = api_version { - if let Some(v) = v.as_str() { - query_params.insert("api-version".to_string(), v.to_string()); - } else { - anyhow::bail!("api_version must be a string") - } + query_params.insert("api-version".to_string(), v.to_string()); }; + let finish_reason = properties.pull_finish_reason_options()?; + + let mut properties = properties.finalize(); properties .entry("max_tokens".into()) .or_insert_with(|| 4096.into()); + let properties = properties; Ok(PostRequestProperties { default_role, @@ -97,6 +63,7 @@ pub fn resolve_properties( headers, properties, allowed_metadata, + finish_reason, // Replace proxy_url with code below to disable proxying // proxy_url: None, proxy_url: ctx.env.get("BOUNDARY_PROXY_URL").map(|s| s.to_string()), diff --git a/engine/baml-runtime/src/internal/llm_client/primitive/openai/properties/generic.rs b/engine/baml-runtime/src/internal/llm_client/primitive/openai/properties/generic.rs index b7cbd4d7e..c7053c700 100644 --- a/engine/baml-runtime/src/internal/llm_client/primitive/openai/properties/generic.rs +++ b/engine/baml-runtime/src/internal/llm_client/primitive/openai/properties/generic.rs @@ -1,56 +1,35 @@ -use std::collections::HashMap; +use std::{collections::HashMap, default}; use anyhow::{Context, Result}; -use crate::{internal::llm_client::AllowedMetadata, RuntimeContext}; +use crate::{ + internal::llm_client::{properties_hander::PropertiesHandler, AllowedMetadata}, + RuntimeContext, +}; use super::PostRequestProperties; pub fn resolve_properties( - mut properties: HashMap, + mut properties: PropertiesHandler, ctx: &RuntimeContext, ) -> Result { - let default_role = properties - .remove("default_role") - .and_then(|v| v.as_str().map(|s| s.to_string())) - .unwrap_or_else(|| "system".to_string()); + let default_role = properties.pull_default_role("system")?; - let base_url = properties - .remove("base_url") - .and_then(|v| v.as_str().map(|s| s.to_string())) - .context("When using 'openai-generic', you must specify a base_url")?; - let allowed_metadata = match properties.remove("allowed_role_metadata") { - Some(allowed_metadata) => serde_json::from_value(allowed_metadata).context( - "allowed_role_metadata must be an array of keys. For example: ['key1', 'key2']", - )?, - None => AllowedMetadata::None, + let base_url = properties.pull_base_url()?; + let base_url = match base_url { + Some(base_url) => base_url, + None => anyhow::bail!("When using 'openai-generic', you must specify a base_url"), }; - let headers = properties.remove("headers").map(|v| { - if let Some(v) = v.as_object() { - v.iter() - .map(|(k, v)| { - Ok(( - k.to_string(), - match v { - serde_json::Value::String(s) => s.to_string(), - _ => anyhow::bail!("Header '{k}' must be a string"), - }, - )) - }) - .collect::>>() - } else { - Ok(Default::default()) - } - }); - let headers = match headers { - Some(h) => h?, - None => Default::default(), + let allowed_metadata = properties.pull_allowed_role_metadata()?; + + let headers = properties.pull_headers()?; + let api_key = match properties.pull_api_key()? { + Some(api_key) if !api_key.is_empty() => Some(api_key), + _ => None, }; + let finish_reason = properties.pull_finish_reason_options()?; - let api_key = properties - .remove("api_key") - .and_then(|v| v.as_str().map(|s| s.to_string())) - .filter(|s| !s.is_empty()); + let properties = properties.finalize(); Ok(PostRequestProperties { default_role, @@ -58,6 +37,7 @@ pub fn resolve_properties( api_key, headers, properties, + finish_reason, proxy_url: ctx .env .get("BOUNDARY_PROXY_URL") diff --git a/engine/baml-runtime/src/internal/llm_client/primitive/openai/properties/mod.rs b/engine/baml-runtime/src/internal/llm_client/primitive/openai/properties/mod.rs index 2a03618ee..0cb4d05dd 100644 --- a/engine/baml-runtime/src/internal/llm_client/primitive/openai/properties/mod.rs +++ b/engine/baml-runtime/src/internal/llm_client/primitive/openai/properties/mod.rs @@ -3,9 +3,9 @@ pub(crate) mod generic; pub(crate) mod ollama; pub(crate) mod openai; -use std::collections::HashMap; - +use crate::internal::llm_client::properties_hander::FinishReasonOptions; use crate::internal::llm_client::AllowedMetadata; +use std::collections::HashMap; pub struct PostRequestProperties { pub default_role: String, @@ -14,6 +14,7 @@ pub struct PostRequestProperties { pub headers: HashMap, pub query_params: HashMap, pub proxy_url: Option, + pub finish_reason: Option, // These are passed directly to the OpenAI API. pub properties: HashMap, pub allowed_metadata: AllowedMetadata, diff --git a/engine/baml-runtime/src/internal/llm_client/primitive/openai/properties/ollama.rs b/engine/baml-runtime/src/internal/llm_client/primitive/openai/properties/ollama.rs index 3fddd56a6..1cee16eb4 100644 --- a/engine/baml-runtime/src/internal/llm_client/primitive/openai/properties/ollama.rs +++ b/engine/baml-runtime/src/internal/llm_client/primitive/openai/properties/ollama.rs @@ -2,58 +2,33 @@ use std::collections::HashMap; use anyhow::{Context, Result}; -use crate::{internal::llm_client::AllowedMetadata, RuntimeContext}; +use crate::{ + internal::llm_client::{properties_hander::PropertiesHandler, AllowedMetadata}, + RuntimeContext, +}; use super::PostRequestProperties; pub fn resolve_properties( - mut properties: HashMap, + mut properties: PropertiesHandler, ctx: &RuntimeContext, ) -> Result { - let default_role = properties - .remove("default_role") - .and_then(|v| v.as_str().map(|s| s.to_string())) - .unwrap_or_else(|| "system".to_string()); - + let default_role = properties.pull_default_role("system")?; let base_url = properties - .remove("base_url") - .and_then(|v| v.as_str().map(|s| s.to_string())) + .pull_base_url()? .unwrap_or_else(|| "http://localhost:11434/v1".to_string()); - let allowed_metadata = match properties.remove("allowed_role_metadata") { - Some(allowed_metadata) => serde_json::from_value(allowed_metadata) - .context("allowed_role_metadata must be an array of keys. For example: ['key1', 'key2']")?, - None => AllowedMetadata::None, - }; - - let headers = properties.remove("headers").map(|v| { - if let Some(v) = v.as_object() { - v.iter() - .map(|(k, v)| { - Ok(( - k.to_string(), - match v { - serde_json::Value::String(s) => s.to_string(), - _ => anyhow::bail!("Header '{k}' must be a string"), - }, - )) - }) - .collect::>>() - } else { - Ok(Default::default()) - } - }); - let headers = match headers { - Some(h) => h?, - None => Default::default(), - }; + let allowed_metadata = properties.pull_allowed_role_metadata()?; + let headers = properties.pull_headers()?; + let finish_reason = properties.pull_finish_reason_options()?; Ok(PostRequestProperties { default_role, base_url, api_key: None, headers, - properties, + properties: properties.finalize(), allowed_metadata, + finish_reason, proxy_url: ctx .env .get("BOUNDARY_PROXY_URL") diff --git a/engine/baml-runtime/src/internal/llm_client/primitive/openai/properties/openai.rs b/engine/baml-runtime/src/internal/llm_client/primitive/openai/properties/openai.rs index c094393d9..baa70d5f8 100644 --- a/engine/baml-runtime/src/internal/llm_client/primitive/openai/properties/openai.rs +++ b/engine/baml-runtime/src/internal/llm_client/primitive/openai/properties/openai.rs @@ -2,64 +2,38 @@ use std::collections::HashMap; use anyhow::{Context, Result}; -use crate::{internal::llm_client::AllowedMetadata, RuntimeContext}; +use crate::{ + internal::llm_client::{properties_hander::PropertiesHandler, AllowedMetadata}, + RuntimeContext, +}; use super::PostRequestProperties; pub fn resolve_properties( - mut properties: HashMap, + mut properties: PropertiesHandler, ctx: &RuntimeContext, ) -> Result { - let default_role = properties - .remove("default_role") - .and_then(|v| v.as_str().map(|s| s.to_string())) - .unwrap_or_else(|| "system".to_string()); + let default_role = properties.pull_default_role("system")?; let base_url = properties - .remove("base_url") - .and_then(|v| v.as_str().map(|s| s.to_string())) + .pull_base_url()? .unwrap_or_else(|| "https://api.openai.com/v1".to_string()); let api_key = properties - .remove("api_key") - .and_then(|v| v.as_str().map(|s| s.to_string())) + .pull_api_key()? .or_else(|| ctx.env.get("OPENAI_API_KEY").map(|s| s.to_string())); - let allowed_metadata = match properties.remove("allowed_role_metadata") { - Some(allowed_metadata) => serde_json::from_value(allowed_metadata).context( - "allowed_role_metadata must be an array of keys. For example: ['key1', 'key2']", - )?, - None => AllowedMetadata::None, - }; - - let headers = properties.remove("headers").map(|v| { - if let Some(v) = v.as_object() { - v.iter() - .map(|(k, v)| { - Ok(( - k.to_string(), - match v { - serde_json::Value::String(s) => s.to_string(), - _ => anyhow::bail!("Header '{k}' must be a string"), - }, - )) - }) - .collect::>>() - } else { - Ok(Default::default()) - } - }); - let headers = match headers { - Some(h) => h?, - None => Default::default(), - }; + let allowed_metadata = properties.pull_allowed_role_metadata()?; + let finish_reason = properties.pull_finish_reason_options()?; + let headers = properties.pull_headers()?; Ok(PostRequestProperties { default_role, base_url, api_key, headers, - properties, + properties: properties.finalize(), allowed_metadata, + finish_reason, // Replace proxy_url with code below to disable proxying // proxy_url: None, proxy_url: ctx diff --git a/engine/baml-runtime/src/internal/llm_client/primitive/vertex/vertex_client.rs b/engine/baml-runtime/src/internal/llm_client/primitive/vertex/vertex_client.rs index 24045f104..835e6d8a5 100644 --- a/engine/baml-runtime/src/internal/llm_client/primitive/vertex/vertex_client.rs +++ b/engine/baml-runtime/src/internal/llm_client/primitive/vertex/vertex_client.rs @@ -1,4 +1,5 @@ use crate::client_registry::ClientProperty; +use crate::internal::llm_client::properties_hander::{FinishReasonOptions, PropertiesHandler}; use crate::internal::llm_client::traits::{ ToProviderMessage, ToProviderMessageExt, WithClientProperties, }; @@ -62,6 +63,7 @@ struct PostRequestProperties { model_id: Option, location: Option, allowed_metadata: AllowedMetadata, + finish_reason: Option, } pub struct VertexClient { @@ -89,107 +91,86 @@ struct ServiceAccount { } fn resolve_properties( - mut properties: HashMap, + mut properties: PropertiesHandler, ctx: &RuntimeContext, ) -> Result { - let default_role = properties - .remove("default_role") - .and_then(|v| v.as_str().map(|s| s.to_string())) - .unwrap_or_else(|| "user".to_string()); - - let base_url = properties - .remove("base_url") - .and_then(|v| v.as_str().map(|s| s.to_string())) - .unwrap_or("".to_string()); - let allowed_metadata = match properties.remove("allowed_role_metadata") { - Some(allowed_metadata) => serde_json::from_value(allowed_metadata).context( - "allowed_role_metadata must be an array of keys. For example: ['key1', 'key2']", - )?, - None => AllowedMetadata::None, - }; + let default_role = properties.pull_default_role("user")?; + + let base_url = properties.pull_base_url()?; + let allowed_metadata = properties.pull_allowed_role_metadata()?; + let service_account_details = { - let authz = properties.remove("authorization"); - let creds = properties.remove("credentials"); - let creds_content = properties.remove("credentials_content"); - - match (authz, creds, creds_content) { - (Some(authz), _, _) => match authz { - serde_json::Value::String(s) => ServiceAccountDetails::RawAuthorizationHeader(s), - _ => anyhow::bail!("authorization must be a string"), - }, - (_, Some(creds), _) => match creds { + let authz = properties.remove_str("authorization")?; + let creds = properties.remove("credentials")?; + let creds_content = properties.remove_str("credentials_content")?; + + // Ensure that at most one of authz, creds, and creds_content is provided + if [authz.is_some(), creds.is_some(), creds_content.is_some()] + .iter() + .filter(|&&b| b) + .count() + > 1 + { + anyhow::bail!( + "Only one of authorization, credentials, and credentials_content can be provided" + ); + } + + if let Some(authz) = authz { + ServiceAccountDetails::RawAuthorizationHeader(authz) + } else if let Some(creds) = creds { + match creds { serde_json::Value::String(s) => match serde_json::from_str(&s) { Ok(service_account) => ServiceAccountDetails::Json(service_account), Err(_) => ServiceAccountDetails::FilePath(s), }, serde_json::Value::Object(o) => ServiceAccountDetails::Json(o), _ => anyhow::bail!("credentials must be a string or JSON object"), - }, - (_, _, Some(creds_content)) => match creds_content { - serde_json::Value::String(s) => ServiceAccountDetails::Json( - serde_json::from_str(&s) - .context("Failed to parse credentials_content as a JSON object")?, - ), - _ => anyhow::bail!("credentials_content must be a string"), - }, - (None, None, None) => match ( - ctx.env.get("GOOGLE_APPLICATION_CREDENTIALS"), - ctx.env.get("GOOGLE_APPLICATION_CREDENTIALS_CONTENT"), - ) { - (Some(path), _) => ServiceAccountDetails::FilePath(path.to_string()), - (_, Some(creds_content)) => ServiceAccountDetails::Json( - serde_json::from_str(&creds_content) - .context("Failed to parse credentials_content as a JSON object")?, - ), - _ => ServiceAccountDetails::None, - }, + } + } else if let Some(creds_content) = creds_content { + ServiceAccountDetails::Json( + serde_json::from_str(&creds_content) + .context("Failed to parse credentials_content as a JSON object")?, + ) + } else if let Some(path) = ctx.env.get("GOOGLE_APPLICATION_CREDENTIALS") { + ServiceAccountDetails::FilePath(path.to_string()) + } else if let Some(creds_content) = ctx.env.get("GOOGLE_APPLICATION_CREDENTIALS_CONTENT") { + ServiceAccountDetails::Json( + serde_json::from_str(&creds_content) + .context("Failed to parse credentials_content as a JSON object")?, + ) + } else { + ServiceAccountDetails::None } }; + let headers = properties.pull_headers()?; + let finish_reason = properties.pull_finish_reason_options()?; - let project_id = properties - .remove("project_id") - .and_then(|v| v.as_str().map(|s| s.to_string())) - .unwrap_or("".to_string()); - - let model_id = properties - .remove("model") - .and_then(|v| v.as_str().map(|s| s.to_string())) - .unwrap_or("".to_string()); - - let location = properties - .remove("location") - .and_then(|v| v.as_str().map(|s| s.to_string())) - .unwrap_or("".to_string()); - - let headers = properties.remove("headers").map(|v| { - if let Some(v) = v.as_object() { - v.iter() - .map(|(k, v)| { - Ok(( - k.to_string(), - match v { - serde_json::Value::String(s) => s.to_string(), - _ => anyhow::bail!("Header '{k}' must be a string"), - }, - )) - }) - .collect::>>() - } else { - Ok(Default::default()) - } - }); + let project_id = properties.remove_str("project_id")?; + let model_id = properties.remove_str("model")?; + let location = properties.remove_str("location")?; - let headers = match headers { - Some(h) => h?, - None => Default::default(), + // Ensure that project_id, model_id, and location are provided + let project_id = match project_id { + Some(project_id) => project_id, + None => anyhow::bail!("project_id must be provided"), + }; + let model_id = match model_id { + Some(model_id) => model_id, + None => anyhow::bail!("model must be provided"), + }; + let location = match location { + Some(location) => location, + None => anyhow::bail!("location must be provided"), }; Ok(PostRequestProperties { default_role, - base_url: Some(base_url), + base_url, service_account_details, headers, - properties, + properties: properties.finalize(), + finish_reason, project_id: Some(project_id), model_id: Some(model_id), location: Some(location), @@ -211,6 +192,9 @@ impl WithClientProperties for VertexClient { fn allowed_metadata(&self) -> &crate::internal::llm_client::AllowedMetadata { &self.properties.allowed_metadata } + fn finish_reason_handling(&self) -> Option<&FinishReasonOptions> { + self.properties.finish_reason.as_ref() + } } impl WithClient for VertexClient { @@ -361,14 +345,7 @@ impl VertexClient { } pub fn dynamic_new(client: &ClientProperty, ctx: &RuntimeContext) -> Result { - let properties = resolve_properties( - client - .options - .iter() - .map(|(k, v)| Ok((k.clone(), json!(v)))) - .collect::>>()?, - ctx, - )?; + let properties = resolve_properties(client.property_handler()?, ctx)?; let default_role = properties.default_role.clone(); Ok(Self { diff --git a/engine/baml-runtime/src/internal/llm_client/properties_hander.rs b/engine/baml-runtime/src/internal/llm_client/properties_hander.rs new file mode 100644 index 000000000..2125ac39c --- /dev/null +++ b/engine/baml-runtime/src/internal/llm_client/properties_hander.rs @@ -0,0 +1,193 @@ +use anyhow::{Context, Result}; +use std::collections::HashMap; + +use super::AllowedMetadata; + +pub enum FinishReasonOptions { + WhiteListed(Vec), + BlackListed(Vec), +} + +impl FinishReasonOptions { + pub fn is_allowed(&self, finish_reason: &str) -> bool { + if finish_reason.is_empty() { + return true; + } + match self { + FinishReasonOptions::WhiteListed(allow_list) => allow_list + .iter() + .any(|allowed| allowed.eq_ignore_ascii_case(finish_reason)), + FinishReasonOptions::BlackListed(deny_list) => !deny_list + .iter() + .any(|denied| denied.eq_ignore_ascii_case(finish_reason)), + } + } +} + +pub(super) struct PropertiesHandler { + properties: HashMap, +} + +impl PropertiesHandler { + pub fn new(properties: HashMap) -> Self { + Self { properties } + } + + pub fn finalize(self) -> HashMap { + self.properties + } + + fn get(&mut self, key: &str) -> Result> { + Ok(self.properties.remove(key)) + } + + pub fn remove(&mut self, key: &str) -> Result> { + // Ban certain keys + match key { + "finish_reason_whitelist" + | "finish_reason_blacklist" + | "allowed_role_metadata" + | "base_url" + | "api_key" + | "headers" + | "default_role" => { + anyhow::bail!("{} is a reserved key in options", key) + } + _ => Ok(self.properties.remove(key)), + } + } + + pub fn remove_str(&mut self, key: &str) -> Result> { + // Ban certain keys + match self.remove(key)? { + Some(value) => match value.as_str() { + Some(s) => Ok(Some(s.to_string())), + None => anyhow::bail!("{} must be a string", key), + }, + None => Ok(None), + } + } + + pub fn pull_finish_reason_options(&mut self) -> Result> { + let whitelist = match self.get("finish_reason_whitelist")? { + Some(value) => match value.as_array() { + Some(array) => array + .iter() + .filter_map(|v| v.as_str().map(|s| s.to_string())) + .collect::>(), + None => anyhow::bail!("finish_reason_whitelist must be an array of strings"), + }, + None => vec![], + }; + + let blacklist = match self.get("finish_reason_blacklist")? { + Some(value) => match value.as_array() { + Some(array) => array + .iter() + .filter_map(|v| v.as_str().map(|s| s.to_string())) + .collect::>(), + None => anyhow::bail!("finish_reason_blacklist must be an array of strings"), + }, + None => vec![], + }; + + Ok(match (whitelist.is_empty(), blacklist.is_empty()) { + (false, true) => Some(FinishReasonOptions::WhiteListed(whitelist)), + (true, false) => Some(FinishReasonOptions::BlackListed(blacklist)), + (false, false) => anyhow::bail!( + "Only one of finish_reason_whitelist or finish_reason_blacklist can be specified" + ), + (true, true) => None, + }) + } + + pub fn pull_headers(&mut self) -> Result> { + let headers = self.get("headers")?.map(|v| { + if let Some(v) = v.as_object() { + v.iter() + .map(|(k, v)| { + Ok(( + k.to_string(), + match v { + serde_json::Value::String(s) => s.to_string(), + _ => anyhow::bail!("Header '{k}' must be a string"), + }, + )) + }) + .collect::>>() + } else { + Ok(Default::default()) + } + }); + let headers = match headers { + Some(h) => h?, + None => Default::default(), + }; + + Ok(headers) + } + + pub fn pull_allowed_role_metadata(&mut self) -> Result { + let allowed_metadata = match self.get("allowed_role_metadata")? { + Some(allowed_metadata) => serde_json::from_value(allowed_metadata).context( + "allowed_role_metadata must be an array of keys. For example: ['key1', 'key2']", + )?, + None => AllowedMetadata::None, + }; + + Ok(allowed_metadata) + } + + pub fn pull_base_url(&mut self) -> Result> { + self.get("base_url")?.map_or(Ok(None), |v| { + match v + .as_str() + .map(|s| Some(s)) + .ok_or_else(|| anyhow::anyhow!("base_url must be a string"))? + { + Some(s) if s.is_empty() => { + anyhow::bail!("base_url must be a non-empty string") + } + Some(s) => Ok(Some(s.to_string())), + None => Ok(None), + } + }) + } + + pub fn pull_default_role(&mut self, default: &str) -> Result { + let default_role = self.get("default_role")?.map(|v| { + v.as_str() + .map(|s| s.to_string()) + .ok_or_else(|| anyhow::anyhow!("default_role must be a string")) + }); + match default_role { + Some(Ok(role)) => Ok(role), + Some(Err(e)) => Err(e), + None => Ok(default.to_string()), + } + } + + pub fn pull_api_key(&mut self) -> Result> { + let api_key = self.get("api_key")?.map(|v| { + v.as_str() + .map(|s| s.to_string()) + .ok_or_else(|| anyhow::anyhow!("api_key must be a string")) + }); + match api_key { + Some(Ok(key)) => Ok(Some(key)), + Some(Err(e)) => Err(e), + None => Ok(None), + } + } +} + +impl crate::client_registry::ClientProperty { + pub(super) fn property_handler(&self) -> Result { + Ok(PropertiesHandler::new( + self.options + .iter() + .map(|(k, v)| Ok((k.clone(), serde_json::json!(v)))) + .collect::>>()?, + )) + } +} diff --git a/engine/baml-runtime/src/internal/llm_client/strategy/fallback.rs b/engine/baml-runtime/src/internal/llm_client/strategy/fallback.rs index feac2cc43..6309bda73 100644 --- a/engine/baml-runtime/src/internal/llm_client/strategy/fallback.rs +++ b/engine/baml-runtime/src/internal/llm_client/strategy/fallback.rs @@ -6,8 +6,9 @@ use internal_baml_core::ir::{repr::ClientSpec, ClientWalker}; use crate::{ client_registry::ClientProperty, - internal::llm_client::orchestrator::{ - ExecutionScope, IterOrchestrator, OrchestrationScope, OrchestrationState, + internal::llm_client::{ + orchestrator::{ExecutionScope, IterOrchestrator, OrchestrationScope, OrchestrationState}, + properties_hander::PropertiesHandler, }, runtime_interface::InternalClientLookup, RuntimeContext, @@ -21,11 +22,11 @@ pub struct FallbackStrategy { } fn resolve_strategy( - mut properties: HashMap, + mut properties: PropertiesHandler, _ctx: &RuntimeContext, ) -> Result> { let strategy = properties - .remove("strategy") + .remove("strategy")? .map(|v| serde_json::from_value::>(v)) .transpose() .context("Failed to resolve strategy into string[]")?; @@ -39,6 +40,7 @@ fn resolve_strategy( anyhow::bail!("Missing a strategy field"); }; + let properties = properties.finalize(); if !properties.is_empty() { let supported_keys = ["strategy"]; let unknown_keys = properties.keys().map(String::from).collect::>(); @@ -58,14 +60,7 @@ impl TryFrom<(&ClientProperty, &RuntimeContext)> for FallbackStrategy { fn try_from( (client, ctx): (&ClientProperty, &RuntimeContext), ) -> std::result::Result { - let strategy = resolve_strategy( - client - .options - .iter() - .map(|(k, v)| Ok((k.clone(), serde_json::json!(v)))) - .collect::>>()?, - ctx, - )?; + let strategy = resolve_strategy(client.property_handler()?, ctx)?; Ok(Self { name: client.name.clone(), retry_policy: client.retry_policy.clone(), diff --git a/engine/baml-runtime/src/internal/llm_client/strategy/roundrobin.rs b/engine/baml-runtime/src/internal/llm_client/strategy/roundrobin.rs index 6c3356bdb..92c726464 100644 --- a/engine/baml-runtime/src/internal/llm_client/strategy/roundrobin.rs +++ b/engine/baml-runtime/src/internal/llm_client/strategy/roundrobin.rs @@ -11,9 +11,12 @@ use internal_baml_core::ir::{repr::ClientSpec, ClientWalker}; use crate::{ client_registry::ClientProperty, - internal::llm_client::orchestrator::{ - ExecutionScope, IterOrchestrator, OrchestrationScope, OrchestrationState, - OrchestratorNodeIterator, + internal::llm_client::{ + orchestrator::{ + ExecutionScope, IterOrchestrator, OrchestrationScope, OrchestrationState, + OrchestratorNodeIterator, + }, + properties_hander::PropertiesHandler, }, runtime_interface::InternalClientLookup, RuntimeContext, @@ -51,11 +54,11 @@ impl RoundRobinStrategy { } fn resolve_strategy( - mut properties: HashMap, + mut properties: PropertiesHandler, _ctx: &RuntimeContext, ) -> Result<(Vec, usize)> { let strategy = properties - .remove("strategy") + .remove("strategy")? .map(|v| serde_json::from_value::>(v)) .transpose() .context("Failed to resolve strategy into string[]")?; @@ -70,11 +73,12 @@ fn resolve_strategy( }; let start = properties - .remove("start") + .remove("start")? .map(|v| serde_json::from_value::(v)) .transpose() .context("Invalid start index (not a number)")?; + let properties = properties.finalize(); if !properties.is_empty() { let supported_keys = ["strategy", "start"]; let unknown_keys = properties.keys().map(String::from).collect::>(); @@ -114,14 +118,7 @@ impl TryFrom<(&ClientProperty, &RuntimeContext)> for RoundRobinStrategy { fn try_from( (client, ctx): (&ClientProperty, &RuntimeContext), ) -> std::result::Result { - let (strategy, start) = resolve_strategy( - client - .options - .iter() - .map(|(k, v)| Ok((k.clone(), serde_json::json!(v)))) - .collect::>>()?, - ctx, - )?; + let (strategy, start) = resolve_strategy(client.property_handler()?, ctx)?; Ok(RoundRobinStrategy { name: client.name.clone(), diff --git a/engine/baml-runtime/src/internal/llm_client/traits/mod.rs b/engine/baml-runtime/src/internal/llm_client/traits/mod.rs index 0dfe7601e..3ff52a5f0 100644 --- a/engine/baml-runtime/src/internal/llm_client/traits/mod.rs +++ b/engine/baml-runtime/src/internal/llm_client/traits/mod.rs @@ -10,7 +10,10 @@ pub use self::{ chat::{WithChat, WithStreamChat}, completion::{WithCompletion, WithNoCompletion, WithStreamCompletion}, }; -use super::{primitive::request::RequestBuilder, LLMResponse, ModelFeatures}; +use super::{ + primitive::request::RequestBuilder, properties_hander::FinishReasonOptions, LLMResponse, + ModelFeatures, +}; use crate::{internal::llm_client::ResolveMediaUrls, RenderCurlSettings}; use crate::{internal::prompt_renderer::PromptRenderer, RuntimeContext}; use baml_types::{BamlMedia, BamlMediaContent, BamlMediaType, BamlValue, MediaBase64, MediaUrl}; @@ -35,6 +38,7 @@ pub trait WithRetryPolicy { pub trait WithClientProperties { fn client_properties(&self) -> &HashMap; fn allowed_metadata(&self) -> &super::AllowedMetadata; + fn finish_reason_handling(&self) -> Option<&FinishReasonOptions>; } pub trait WithSingleCallable { diff --git a/engine/language_client_codegen/src/python/templates/async_client.py.j2 b/engine/language_client_codegen/src/python/templates/async_client.py.j2 index 01990b44b..f6ef307c9 100644 --- a/engine/language_client_codegen/src/python/templates/async_client.py.j2 +++ b/engine/language_client_codegen/src/python/templates/async_client.py.j2 @@ -53,7 +53,7 @@ class BamlAsyncClient: ) -> {{fn.return_type}}: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -92,7 +92,7 @@ class BamlStreamClient: ) -> baml_py.BamlStream[{{ fn.partial_return_type }}, {{ fn.return_type }}]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) diff --git a/engine/language_client_codegen/src/python/templates/sync_client.py.j2 b/engine/language_client_codegen/src/python/templates/sync_client.py.j2 index 744b9c6f0..7d5e386b6 100644 --- a/engine/language_client_codegen/src/python/templates/sync_client.py.j2 +++ b/engine/language_client_codegen/src/python/templates/sync_client.py.j2 @@ -51,7 +51,7 @@ class BamlSyncClient: ) -> {{fn.return_type}}: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -91,7 +91,7 @@ class BamlStreamClient: ) -> baml_py.BamlSyncStream[{{ fn.partial_return_type }}, {{ fn.return_type }}]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) diff --git a/engine/language_client_codegen/src/python/templates/type_builder.py.j2 b/engine/language_client_codegen/src/python/templates/type_builder.py.j2 index 1fe5cadc5..aa885801c 100644 --- a/engine/language_client_codegen/src/python/templates/type_builder.py.j2 +++ b/engine/language_client_codegen/src/python/templates/type_builder.py.j2 @@ -1,5 +1,6 @@ import typing -from baml_py.type_builder import FieldType, TypeBuilder as _TypeBuilder, ClassPropertyBuilder, EnumValueBuilder, EnumBuilder, ClassBuilder +from baml_py.baml_py import FieldType, EnumValueBuilder, EnumBuilder, ClassBuilder +from baml_py.type_builder import TypeBuilder as _TypeBuilder, ClassPropertyBuilder class TypeBuilder(_TypeBuilder): def __init__(self): @@ -10,11 +11,11 @@ class TypeBuilder(_TypeBuilder): )) {% for cls in classes %}{% if cls.dynamic %} - - @property {# BUG: this resets the class properties list on each access #} + @property def {{cls.name}}(self) -> "{{cls.name}}Builder": return {{cls.name}}Builder(self) + {% endif %}{% endfor %} {% for enum in enums %}{% if enum.dynamic %} @@ -28,8 +29,9 @@ class TypeBuilder(_TypeBuilder): class {{cls.name}}Builder: def __init__(self, tb: _TypeBuilder): - self.__bldr = tb._tb.class_("{{cls.name}}") - self.__properties = set([{% for (name, _) in cls.fields %} "{{name}}", {% endfor %}]) + _tb = tb._tb # type: ignore (we know how to use this private attribute) + self.__bldr = _tb.class_("{{cls.name}}") + self.__properties: typing.Set[str] = set([{% for (name, _) in cls.fields %} "{{name}}", {% endfor %}]) self.__props = {{cls.name}}Properties(self.__bldr, self.__properties) def type(self) -> FieldType: @@ -40,7 +42,7 @@ class {{cls.name}}Builder: return self.__props def list_properties(self) -> typing.List[typing.Tuple[str, ClassPropertyBuilder]]: - return [(name, self.__bldr.property(name)) for name in self.__properties] + return [(name, ClassPropertyBuilder(self.__bldr.property(name))) for name in self.__properties] def add_property(self, name: str, type: FieldType) -> ClassPropertyBuilder: if name in self.__properties: @@ -56,20 +58,22 @@ class {{cls.name}}Properties: @property def {{name}}(self) -> ClassPropertyBuilder: - return self.__bldr.property("{{name}}") + return ClassPropertyBuilder(self.__bldr.property("{{name}}")) {%- endfor %} def __getattr__(self, name: str) -> ClassPropertyBuilder: if name not in self.__properties: raise AttributeError(f"Property {name} not found.") return ClassPropertyBuilder(self.__bldr.property(name)) + {% endif %}{% endfor %} {% for enum in enums %}{% if enum.dynamic %} class {{enum.name}}Builder: def __init__(self, tb: _TypeBuilder): - self.__bldr = tb._tb.enum("{{enum.name}}") - self.__values = set([{% for value in enum.values %} "{{value}}", {% endfor %}]) + _tb = tb._tb # type: ignore (we know how to use this private attribute) + self.__bldr = _tb.enum("{{enum.name}}") + self.__values: typing.Set[str] = set([{% for value in enum.values %} "{{value}}", {% endfor %}]) self.__vals = {{enum.name}}Values(self.__bldr, self.__values) def type(self) -> FieldType: diff --git a/engine/language_client_python/python_src/baml_py/errors.py b/engine/language_client_python/python_src/baml_py/errors.py index c7f3c87e6..62eb2089f 100644 --- a/engine/language_client_python/python_src/baml_py/errors.py +++ b/engine/language_client_python/python_src/baml_py/errors.py @@ -3,10 +3,11 @@ BamlClientError, BamlClientHttpError, BamlInvalidArgumentError, + BamlValidationError, ) # hack to get the BamlValidationError class which is a custom error -from .baml_py.errors import BamlValidationError +# from .baml_py.errors import BamlValidationError __all__ = [ diff --git a/engine/language_client_python/src/errors.rs b/engine/language_client_python/src/errors.rs index a178631d8..a5a303f46 100644 --- a/engine/language_client_python/src/errors.rs +++ b/engine/language_client_python/src/errors.rs @@ -144,6 +144,7 @@ impl BamlError { )) } baml_runtime::internal::llm_client::ErrorCode::Other(_) + | baml_runtime::internal::llm_client::ErrorCode::BadRequest | baml_runtime::internal::llm_client::ErrorCode::InvalidAuthentication | baml_runtime::internal::llm_client::ErrorCode::NotSupported | baml_runtime::internal::llm_client::ErrorCode::RateLimited diff --git a/engine/language_client_typescript/src/errors.rs b/engine/language_client_typescript/src/errors.rs index 02234607a..a9ca81cbf 100644 --- a/engine/language_client_typescript/src/errors.rs +++ b/engine/language_client_typescript/src/errors.rs @@ -38,6 +38,7 @@ pub fn from_anyhow_error(err: anyhow::Error) -> napi::Error { ), ), baml_runtime::internal::llm_client::ErrorCode::Other(_) + | baml_runtime::internal::llm_client::ErrorCode::BadRequest | baml_runtime::internal::llm_client::ErrorCode::InvalidAuthentication | baml_runtime::internal::llm_client::ErrorCode::NotSupported | baml_runtime::internal::llm_client::ErrorCode::RateLimited diff --git a/integ-tests/python/baml_client/async_client.py b/integ-tests/python/baml_client/async_client.py index 615706ce7..d585f8149 100644 --- a/integ-tests/python/baml_client/async_client.py +++ b/integ-tests/python/baml_client/async_client.py @@ -66,7 +66,7 @@ async def AaaSamOutputFormat( ) -> types.Recipe: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -90,7 +90,7 @@ async def AudioInput( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -114,7 +114,7 @@ async def ClassifyDynEnumTwo( ) -> Union[types.DynEnumTwo, str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -138,7 +138,7 @@ async def ClassifyMessage( ) -> types.Category: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -162,7 +162,7 @@ async def ClassifyMessage2( ) -> types.Category: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -186,7 +186,7 @@ async def ClassifyMessage3( ) -> types.Category: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -210,7 +210,7 @@ async def CustomTask( ) -> Union[types.BookOrder, types.FlightConfirmation, types.GroceryReceipt]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -234,7 +234,7 @@ async def DescribeImage( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -258,7 +258,7 @@ async def DescribeImage2( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -282,7 +282,7 @@ async def DescribeImage3( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -306,7 +306,7 @@ async def DescribeImage4( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -330,7 +330,7 @@ async def DummyOutputFunction( ) -> types.DummyOutput: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -354,7 +354,7 @@ async def DynamicFunc( ) -> types.DynamicClassTwo: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -378,7 +378,7 @@ async def DynamicInputOutput( ) -> types.DynInputOutput: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -402,7 +402,7 @@ async def DynamicListInputOutput( ) -> List[types.DynInputOutput]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -426,7 +426,7 @@ async def ExpectFailure( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -450,7 +450,7 @@ async def ExtractNames( ) -> List[str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -474,7 +474,7 @@ async def ExtractPeople( ) -> List[types.Person]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -498,7 +498,7 @@ async def ExtractReceiptInfo( ) -> types.ReceiptInfo: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -522,7 +522,7 @@ async def ExtractResume( ) -> types.Resume: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -546,7 +546,7 @@ async def ExtractResume2( ) -> types.Resume: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -570,7 +570,7 @@ async def FnClassOptionalOutput( ) -> Optional[types.ClassOptionalOutput]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -594,7 +594,7 @@ async def FnClassOptionalOutput2( ) -> Optional[types.ClassOptionalOutput2]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -618,7 +618,7 @@ async def FnEnumListOutput( ) -> List[types.EnumOutput]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -642,7 +642,7 @@ async def FnEnumOutput( ) -> types.EnumOutput: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -666,7 +666,7 @@ async def FnNamedArgsSingleStringOptional( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -690,7 +690,7 @@ async def FnOutputBool( ) -> bool: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -714,7 +714,7 @@ async def FnOutputClass( ) -> types.TestOutputClass: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -738,7 +738,7 @@ async def FnOutputClassList( ) -> List[types.TestOutputClass]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -762,7 +762,7 @@ async def FnOutputClassNested( ) -> types.TestClassNested: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -786,7 +786,7 @@ async def FnOutputClassWithEnum( ) -> types.TestClassWithEnum: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -810,7 +810,7 @@ async def FnOutputStringList( ) -> List[str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -834,7 +834,7 @@ async def FnTestAliasedEnumOutput( ) -> types.TestEnum: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -858,7 +858,7 @@ async def FnTestClassAlias( ) -> types.TestClassAlias: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -882,7 +882,7 @@ async def FnTestNamedArgsSingleEnum( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -906,7 +906,7 @@ async def GetDataType( ) -> types.RaysData: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -930,7 +930,7 @@ async def GetOrderInfo( ) -> types.OrderInfo: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -954,7 +954,7 @@ async def GetQuery( ) -> types.SearchParams: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -978,7 +978,7 @@ async def MyFunc( ) -> types.DynamicOutput: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1002,7 +1002,7 @@ async def OptionalTest_Function( ) -> List[Optional[types.OptionalTest_ReturnType]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1026,7 +1026,7 @@ async def PromptTestClaude( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1050,7 +1050,7 @@ async def PromptTestClaudeChat( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1074,7 +1074,7 @@ async def PromptTestClaudeChatNoSystem( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1098,7 +1098,7 @@ async def PromptTestOpenAI( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1122,7 +1122,7 @@ async def PromptTestOpenAIChat( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1146,7 +1146,7 @@ async def PromptTestOpenAIChatNoSystem( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1170,7 +1170,7 @@ async def PromptTestStreaming( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1194,7 +1194,7 @@ async def SchemaDescriptions( ) -> types.Schema: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1218,7 +1218,7 @@ async def TestAnthropic( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1242,7 +1242,7 @@ async def TestAnthropicShorthand( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1266,7 +1266,7 @@ async def TestAws( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1290,7 +1290,7 @@ async def TestAzure( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1314,7 +1314,7 @@ async def TestCaching( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1338,7 +1338,7 @@ async def TestFallbackClient( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1362,7 +1362,7 @@ async def TestFallbackToShorthand( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1386,7 +1386,7 @@ async def TestFnNamedArgsSingleBool( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1410,7 +1410,7 @@ async def TestFnNamedArgsSingleClass( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1434,7 +1434,7 @@ async def TestFnNamedArgsSingleEnumList( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1458,7 +1458,7 @@ async def TestFnNamedArgsSingleFloat( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1482,7 +1482,7 @@ async def TestFnNamedArgsSingleInt( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1506,7 +1506,7 @@ async def TestFnNamedArgsSingleMapStringToClass( ) -> Dict[str, types.StringToClassEntry]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1530,7 +1530,7 @@ async def TestFnNamedArgsSingleMapStringToMap( ) -> Dict[str, Dict[str, str]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1554,7 +1554,7 @@ async def TestFnNamedArgsSingleMapStringToString( ) -> Dict[str, str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1578,7 +1578,7 @@ async def TestFnNamedArgsSingleString( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1602,7 +1602,7 @@ async def TestFnNamedArgsSingleStringArray( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1626,7 +1626,7 @@ async def TestFnNamedArgsSingleStringList( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1650,7 +1650,7 @@ async def TestGemini( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1674,7 +1674,7 @@ async def TestImageInput( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1698,7 +1698,7 @@ async def TestImageInputAnthropic( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1722,7 +1722,7 @@ async def TestImageListInput( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1746,7 +1746,7 @@ async def TestMulticlassNamedArgs( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1770,7 +1770,7 @@ async def TestOllama( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1794,7 +1794,7 @@ async def TestOpenAILegacyProvider( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1818,7 +1818,7 @@ async def TestOpenAIShorthand( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1842,7 +1842,7 @@ async def TestRetryConstant( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1866,7 +1866,7 @@ async def TestRetryExponential( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1890,7 +1890,7 @@ async def TestVertex( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1914,7 +1914,7 @@ async def UnionTest_Function( ) -> types.UnionTest_ReturnType: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1949,7 +1949,7 @@ def AaaSamOutputFormat( ) -> baml_py.BamlStream[partial_types.Recipe, types.Recipe]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1982,7 +1982,7 @@ def AudioInput( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2015,7 +2015,7 @@ def ClassifyDynEnumTwo( ) -> baml_py.BamlStream[Optional[Union[types.DynEnumTwo, str]], Union[types.DynEnumTwo, str]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2048,7 +2048,7 @@ def ClassifyMessage( ) -> baml_py.BamlStream[Optional[types.Category], types.Category]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2081,7 +2081,7 @@ def ClassifyMessage2( ) -> baml_py.BamlStream[Optional[types.Category], types.Category]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2114,7 +2114,7 @@ def ClassifyMessage3( ) -> baml_py.BamlStream[Optional[types.Category], types.Category]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2147,7 +2147,7 @@ def CustomTask( ) -> baml_py.BamlStream[Optional[Union[partial_types.BookOrder, partial_types.FlightConfirmation, partial_types.GroceryReceipt]], Union[types.BookOrder, types.FlightConfirmation, types.GroceryReceipt]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2180,7 +2180,7 @@ def DescribeImage( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2213,7 +2213,7 @@ def DescribeImage2( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2247,7 +2247,7 @@ def DescribeImage3( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2281,7 +2281,7 @@ def DescribeImage4( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2315,7 +2315,7 @@ def DummyOutputFunction( ) -> baml_py.BamlStream[partial_types.DummyOutput, types.DummyOutput]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2348,7 +2348,7 @@ def DynamicFunc( ) -> baml_py.BamlStream[partial_types.DynamicClassTwo, types.DynamicClassTwo]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2381,7 +2381,7 @@ def DynamicInputOutput( ) -> baml_py.BamlStream[partial_types.DynInputOutput, types.DynInputOutput]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2414,7 +2414,7 @@ def DynamicListInputOutput( ) -> baml_py.BamlStream[List[partial_types.DynInputOutput], List[types.DynInputOutput]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2447,7 +2447,7 @@ def ExpectFailure( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2479,7 +2479,7 @@ def ExtractNames( ) -> baml_py.BamlStream[List[Optional[str]], List[str]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2512,7 +2512,7 @@ def ExtractPeople( ) -> baml_py.BamlStream[List[partial_types.Person], List[types.Person]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2545,7 +2545,7 @@ def ExtractReceiptInfo( ) -> baml_py.BamlStream[partial_types.ReceiptInfo, types.ReceiptInfo]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2578,7 +2578,7 @@ def ExtractResume( ) -> baml_py.BamlStream[partial_types.Resume, types.Resume]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2612,7 +2612,7 @@ def ExtractResume2( ) -> baml_py.BamlStream[partial_types.Resume, types.Resume]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2645,7 +2645,7 @@ def FnClassOptionalOutput( ) -> baml_py.BamlStream[partial_types.ClassOptionalOutput, Optional[types.ClassOptionalOutput]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2678,7 +2678,7 @@ def FnClassOptionalOutput2( ) -> baml_py.BamlStream[partial_types.ClassOptionalOutput2, Optional[types.ClassOptionalOutput2]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2711,7 +2711,7 @@ def FnEnumListOutput( ) -> baml_py.BamlStream[List[Optional[types.EnumOutput]], List[types.EnumOutput]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2744,7 +2744,7 @@ def FnEnumOutput( ) -> baml_py.BamlStream[Optional[types.EnumOutput], types.EnumOutput]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2777,7 +2777,7 @@ def FnNamedArgsSingleStringOptional( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2810,7 +2810,7 @@ def FnOutputBool( ) -> baml_py.BamlStream[Optional[bool], bool]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2843,7 +2843,7 @@ def FnOutputClass( ) -> baml_py.BamlStream[partial_types.TestOutputClass, types.TestOutputClass]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2876,7 +2876,7 @@ def FnOutputClassList( ) -> baml_py.BamlStream[List[partial_types.TestOutputClass], List[types.TestOutputClass]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2909,7 +2909,7 @@ def FnOutputClassNested( ) -> baml_py.BamlStream[partial_types.TestClassNested, types.TestClassNested]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2942,7 +2942,7 @@ def FnOutputClassWithEnum( ) -> baml_py.BamlStream[partial_types.TestClassWithEnum, types.TestClassWithEnum]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2975,7 +2975,7 @@ def FnOutputStringList( ) -> baml_py.BamlStream[List[Optional[str]], List[str]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3008,7 +3008,7 @@ def FnTestAliasedEnumOutput( ) -> baml_py.BamlStream[Optional[types.TestEnum], types.TestEnum]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3041,7 +3041,7 @@ def FnTestClassAlias( ) -> baml_py.BamlStream[partial_types.TestClassAlias, types.TestClassAlias]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3074,7 +3074,7 @@ def FnTestNamedArgsSingleEnum( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3107,7 +3107,7 @@ def GetDataType( ) -> baml_py.BamlStream[partial_types.RaysData, types.RaysData]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3140,7 +3140,7 @@ def GetOrderInfo( ) -> baml_py.BamlStream[partial_types.OrderInfo, types.OrderInfo]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3173,7 +3173,7 @@ def GetQuery( ) -> baml_py.BamlStream[partial_types.SearchParams, types.SearchParams]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3206,7 +3206,7 @@ def MyFunc( ) -> baml_py.BamlStream[partial_types.DynamicOutput, types.DynamicOutput]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3239,7 +3239,7 @@ def OptionalTest_Function( ) -> baml_py.BamlStream[List[partial_types.OptionalTest_ReturnType], List[Optional[types.OptionalTest_ReturnType]]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3272,7 +3272,7 @@ def PromptTestClaude( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3305,7 +3305,7 @@ def PromptTestClaudeChat( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3338,7 +3338,7 @@ def PromptTestClaudeChatNoSystem( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3371,7 +3371,7 @@ def PromptTestOpenAI( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3404,7 +3404,7 @@ def PromptTestOpenAIChat( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3437,7 +3437,7 @@ def PromptTestOpenAIChatNoSystem( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3470,7 +3470,7 @@ def PromptTestStreaming( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3503,7 +3503,7 @@ def SchemaDescriptions( ) -> baml_py.BamlStream[partial_types.Schema, types.Schema]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3536,7 +3536,7 @@ def TestAnthropic( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3569,7 +3569,7 @@ def TestAnthropicShorthand( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3602,7 +3602,7 @@ def TestAws( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3635,7 +3635,7 @@ def TestAzure( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3668,7 +3668,7 @@ def TestCaching( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3701,7 +3701,7 @@ def TestFallbackClient( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3733,7 +3733,7 @@ def TestFallbackToShorthand( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3766,7 +3766,7 @@ def TestFnNamedArgsSingleBool( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3799,7 +3799,7 @@ def TestFnNamedArgsSingleClass( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3832,7 +3832,7 @@ def TestFnNamedArgsSingleEnumList( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3865,7 +3865,7 @@ def TestFnNamedArgsSingleFloat( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3898,7 +3898,7 @@ def TestFnNamedArgsSingleInt( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3931,7 +3931,7 @@ def TestFnNamedArgsSingleMapStringToClass( ) -> baml_py.BamlStream[Dict[str, partial_types.StringToClassEntry], Dict[str, types.StringToClassEntry]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3964,7 +3964,7 @@ def TestFnNamedArgsSingleMapStringToMap( ) -> baml_py.BamlStream[Dict[str, Dict[str, Optional[str]]], Dict[str, Dict[str, str]]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3997,7 +3997,7 @@ def TestFnNamedArgsSingleMapStringToString( ) -> baml_py.BamlStream[Dict[str, Optional[str]], Dict[str, str]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4030,7 +4030,7 @@ def TestFnNamedArgsSingleString( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4063,7 +4063,7 @@ def TestFnNamedArgsSingleStringArray( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4096,7 +4096,7 @@ def TestFnNamedArgsSingleStringList( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4129,7 +4129,7 @@ def TestGemini( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4162,7 +4162,7 @@ def TestImageInput( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4195,7 +4195,7 @@ def TestImageInputAnthropic( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4228,7 +4228,7 @@ def TestImageListInput( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4261,7 +4261,7 @@ def TestMulticlassNamedArgs( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4295,7 +4295,7 @@ def TestOllama( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4328,7 +4328,7 @@ def TestOpenAILegacyProvider( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4361,7 +4361,7 @@ def TestOpenAIShorthand( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4394,7 +4394,7 @@ def TestRetryConstant( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4426,7 +4426,7 @@ def TestRetryExponential( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4458,7 +4458,7 @@ def TestVertex( ) -> baml_py.BamlStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4491,7 +4491,7 @@ def UnionTest_Function( ) -> baml_py.BamlStream[partial_types.UnionTest_ReturnType, types.UnionTest_ReturnType]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) diff --git a/integ-tests/python/baml_client/sync_client.py b/integ-tests/python/baml_client/sync_client.py index a5b2056f2..a4924ce28 100644 --- a/integ-tests/python/baml_client/sync_client.py +++ b/integ-tests/python/baml_client/sync_client.py @@ -64,7 +64,7 @@ def AaaSamOutputFormat( ) -> types.Recipe: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -88,7 +88,7 @@ def AudioInput( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -112,7 +112,7 @@ def ClassifyDynEnumTwo( ) -> Union[types.DynEnumTwo, str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -136,7 +136,7 @@ def ClassifyMessage( ) -> types.Category: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -160,7 +160,7 @@ def ClassifyMessage2( ) -> types.Category: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -184,7 +184,7 @@ def ClassifyMessage3( ) -> types.Category: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -208,7 +208,7 @@ def CustomTask( ) -> Union[types.BookOrder, types.FlightConfirmation, types.GroceryReceipt]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -232,7 +232,7 @@ def DescribeImage( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -256,7 +256,7 @@ def DescribeImage2( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -280,7 +280,7 @@ def DescribeImage3( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -304,7 +304,7 @@ def DescribeImage4( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -328,7 +328,7 @@ def DummyOutputFunction( ) -> types.DummyOutput: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -352,7 +352,7 @@ def DynamicFunc( ) -> types.DynamicClassTwo: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -376,7 +376,7 @@ def DynamicInputOutput( ) -> types.DynInputOutput: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -400,7 +400,7 @@ def DynamicListInputOutput( ) -> List[types.DynInputOutput]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -424,7 +424,7 @@ def ExpectFailure( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -448,7 +448,7 @@ def ExtractNames( ) -> List[str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -472,7 +472,7 @@ def ExtractPeople( ) -> List[types.Person]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -496,7 +496,7 @@ def ExtractReceiptInfo( ) -> types.ReceiptInfo: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -520,7 +520,7 @@ def ExtractResume( ) -> types.Resume: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -544,7 +544,7 @@ def ExtractResume2( ) -> types.Resume: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -568,7 +568,7 @@ def FnClassOptionalOutput( ) -> Optional[types.ClassOptionalOutput]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -592,7 +592,7 @@ def FnClassOptionalOutput2( ) -> Optional[types.ClassOptionalOutput2]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -616,7 +616,7 @@ def FnEnumListOutput( ) -> List[types.EnumOutput]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -640,7 +640,7 @@ def FnEnumOutput( ) -> types.EnumOutput: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -664,7 +664,7 @@ def FnNamedArgsSingleStringOptional( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -688,7 +688,7 @@ def FnOutputBool( ) -> bool: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -712,7 +712,7 @@ def FnOutputClass( ) -> types.TestOutputClass: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -736,7 +736,7 @@ def FnOutputClassList( ) -> List[types.TestOutputClass]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -760,7 +760,7 @@ def FnOutputClassNested( ) -> types.TestClassNested: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -784,7 +784,7 @@ def FnOutputClassWithEnum( ) -> types.TestClassWithEnum: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -808,7 +808,7 @@ def FnOutputStringList( ) -> List[str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -832,7 +832,7 @@ def FnTestAliasedEnumOutput( ) -> types.TestEnum: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -856,7 +856,7 @@ def FnTestClassAlias( ) -> types.TestClassAlias: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -880,7 +880,7 @@ def FnTestNamedArgsSingleEnum( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -904,7 +904,7 @@ def GetDataType( ) -> types.RaysData: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -928,7 +928,7 @@ def GetOrderInfo( ) -> types.OrderInfo: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -952,7 +952,7 @@ def GetQuery( ) -> types.SearchParams: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -976,7 +976,7 @@ def MyFunc( ) -> types.DynamicOutput: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1000,7 +1000,7 @@ def OptionalTest_Function( ) -> List[Optional[types.OptionalTest_ReturnType]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1024,7 +1024,7 @@ def PromptTestClaude( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1048,7 +1048,7 @@ def PromptTestClaudeChat( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1072,7 +1072,7 @@ def PromptTestClaudeChatNoSystem( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1096,7 +1096,7 @@ def PromptTestOpenAI( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1120,7 +1120,7 @@ def PromptTestOpenAIChat( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1144,7 +1144,7 @@ def PromptTestOpenAIChatNoSystem( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1168,7 +1168,7 @@ def PromptTestStreaming( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1192,7 +1192,7 @@ def SchemaDescriptions( ) -> types.Schema: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1216,7 +1216,7 @@ def TestAnthropic( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1240,7 +1240,7 @@ def TestAnthropicShorthand( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1264,7 +1264,7 @@ def TestAws( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1288,7 +1288,7 @@ def TestAzure( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1312,7 +1312,7 @@ def TestCaching( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1336,7 +1336,7 @@ def TestFallbackClient( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1360,7 +1360,7 @@ def TestFallbackToShorthand( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1384,7 +1384,7 @@ def TestFnNamedArgsSingleBool( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1408,7 +1408,7 @@ def TestFnNamedArgsSingleClass( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1432,7 +1432,7 @@ def TestFnNamedArgsSingleEnumList( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1456,7 +1456,7 @@ def TestFnNamedArgsSingleFloat( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1480,7 +1480,7 @@ def TestFnNamedArgsSingleInt( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1504,7 +1504,7 @@ def TestFnNamedArgsSingleMapStringToClass( ) -> Dict[str, types.StringToClassEntry]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1528,7 +1528,7 @@ def TestFnNamedArgsSingleMapStringToMap( ) -> Dict[str, Dict[str, str]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1552,7 +1552,7 @@ def TestFnNamedArgsSingleMapStringToString( ) -> Dict[str, str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1576,7 +1576,7 @@ def TestFnNamedArgsSingleString( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1600,7 +1600,7 @@ def TestFnNamedArgsSingleStringArray( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1624,7 +1624,7 @@ def TestFnNamedArgsSingleStringList( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1648,7 +1648,7 @@ def TestGemini( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1672,7 +1672,7 @@ def TestImageInput( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1696,7 +1696,7 @@ def TestImageInputAnthropic( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1720,7 +1720,7 @@ def TestImageListInput( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1744,7 +1744,7 @@ def TestMulticlassNamedArgs( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1768,7 +1768,7 @@ def TestOllama( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1792,7 +1792,7 @@ def TestOpenAILegacyProvider( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1816,7 +1816,7 @@ def TestOpenAIShorthand( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1840,7 +1840,7 @@ def TestRetryConstant( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1864,7 +1864,7 @@ def TestRetryExponential( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1888,7 +1888,7 @@ def TestVertex( ) -> str: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1912,7 +1912,7 @@ def UnionTest_Function( ) -> types.UnionTest_ReturnType: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1948,7 +1948,7 @@ def AaaSamOutputFormat( ) -> baml_py.BamlSyncStream[partial_types.Recipe, types.Recipe]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -1981,7 +1981,7 @@ def AudioInput( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2014,7 +2014,7 @@ def ClassifyDynEnumTwo( ) -> baml_py.BamlSyncStream[Optional[Union[types.DynEnumTwo, str]], Union[types.DynEnumTwo, str]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2047,7 +2047,7 @@ def ClassifyMessage( ) -> baml_py.BamlSyncStream[Optional[types.Category], types.Category]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2080,7 +2080,7 @@ def ClassifyMessage2( ) -> baml_py.BamlSyncStream[Optional[types.Category], types.Category]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2113,7 +2113,7 @@ def ClassifyMessage3( ) -> baml_py.BamlSyncStream[Optional[types.Category], types.Category]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2146,7 +2146,7 @@ def CustomTask( ) -> baml_py.BamlSyncStream[Optional[Union[partial_types.BookOrder, partial_types.FlightConfirmation, partial_types.GroceryReceipt]], Union[types.BookOrder, types.FlightConfirmation, types.GroceryReceipt]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2179,7 +2179,7 @@ def DescribeImage( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2212,7 +2212,7 @@ def DescribeImage2( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2246,7 +2246,7 @@ def DescribeImage3( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2280,7 +2280,7 @@ def DescribeImage4( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2314,7 +2314,7 @@ def DummyOutputFunction( ) -> baml_py.BamlSyncStream[partial_types.DummyOutput, types.DummyOutput]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2347,7 +2347,7 @@ def DynamicFunc( ) -> baml_py.BamlSyncStream[partial_types.DynamicClassTwo, types.DynamicClassTwo]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2380,7 +2380,7 @@ def DynamicInputOutput( ) -> baml_py.BamlSyncStream[partial_types.DynInputOutput, types.DynInputOutput]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2413,7 +2413,7 @@ def DynamicListInputOutput( ) -> baml_py.BamlSyncStream[List[partial_types.DynInputOutput], List[types.DynInputOutput]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2446,7 +2446,7 @@ def ExpectFailure( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2478,7 +2478,7 @@ def ExtractNames( ) -> baml_py.BamlSyncStream[List[Optional[str]], List[str]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2511,7 +2511,7 @@ def ExtractPeople( ) -> baml_py.BamlSyncStream[List[partial_types.Person], List[types.Person]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2544,7 +2544,7 @@ def ExtractReceiptInfo( ) -> baml_py.BamlSyncStream[partial_types.ReceiptInfo, types.ReceiptInfo]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2577,7 +2577,7 @@ def ExtractResume( ) -> baml_py.BamlSyncStream[partial_types.Resume, types.Resume]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2611,7 +2611,7 @@ def ExtractResume2( ) -> baml_py.BamlSyncStream[partial_types.Resume, types.Resume]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2644,7 +2644,7 @@ def FnClassOptionalOutput( ) -> baml_py.BamlSyncStream[partial_types.ClassOptionalOutput, Optional[types.ClassOptionalOutput]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2677,7 +2677,7 @@ def FnClassOptionalOutput2( ) -> baml_py.BamlSyncStream[partial_types.ClassOptionalOutput2, Optional[types.ClassOptionalOutput2]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2710,7 +2710,7 @@ def FnEnumListOutput( ) -> baml_py.BamlSyncStream[List[Optional[types.EnumOutput]], List[types.EnumOutput]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2743,7 +2743,7 @@ def FnEnumOutput( ) -> baml_py.BamlSyncStream[Optional[types.EnumOutput], types.EnumOutput]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2776,7 +2776,7 @@ def FnNamedArgsSingleStringOptional( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2809,7 +2809,7 @@ def FnOutputBool( ) -> baml_py.BamlSyncStream[Optional[bool], bool]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2842,7 +2842,7 @@ def FnOutputClass( ) -> baml_py.BamlSyncStream[partial_types.TestOutputClass, types.TestOutputClass]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2875,7 +2875,7 @@ def FnOutputClassList( ) -> baml_py.BamlSyncStream[List[partial_types.TestOutputClass], List[types.TestOutputClass]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2908,7 +2908,7 @@ def FnOutputClassNested( ) -> baml_py.BamlSyncStream[partial_types.TestClassNested, types.TestClassNested]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2941,7 +2941,7 @@ def FnOutputClassWithEnum( ) -> baml_py.BamlSyncStream[partial_types.TestClassWithEnum, types.TestClassWithEnum]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -2974,7 +2974,7 @@ def FnOutputStringList( ) -> baml_py.BamlSyncStream[List[Optional[str]], List[str]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3007,7 +3007,7 @@ def FnTestAliasedEnumOutput( ) -> baml_py.BamlSyncStream[Optional[types.TestEnum], types.TestEnum]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3040,7 +3040,7 @@ def FnTestClassAlias( ) -> baml_py.BamlSyncStream[partial_types.TestClassAlias, types.TestClassAlias]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3073,7 +3073,7 @@ def FnTestNamedArgsSingleEnum( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3106,7 +3106,7 @@ def GetDataType( ) -> baml_py.BamlSyncStream[partial_types.RaysData, types.RaysData]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3139,7 +3139,7 @@ def GetOrderInfo( ) -> baml_py.BamlSyncStream[partial_types.OrderInfo, types.OrderInfo]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3172,7 +3172,7 @@ def GetQuery( ) -> baml_py.BamlSyncStream[partial_types.SearchParams, types.SearchParams]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3205,7 +3205,7 @@ def MyFunc( ) -> baml_py.BamlSyncStream[partial_types.DynamicOutput, types.DynamicOutput]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3238,7 +3238,7 @@ def OptionalTest_Function( ) -> baml_py.BamlSyncStream[List[partial_types.OptionalTest_ReturnType], List[Optional[types.OptionalTest_ReturnType]]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3271,7 +3271,7 @@ def PromptTestClaude( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3304,7 +3304,7 @@ def PromptTestClaudeChat( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3337,7 +3337,7 @@ def PromptTestClaudeChatNoSystem( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3370,7 +3370,7 @@ def PromptTestOpenAI( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3403,7 +3403,7 @@ def PromptTestOpenAIChat( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3436,7 +3436,7 @@ def PromptTestOpenAIChatNoSystem( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3469,7 +3469,7 @@ def PromptTestStreaming( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3502,7 +3502,7 @@ def SchemaDescriptions( ) -> baml_py.BamlSyncStream[partial_types.Schema, types.Schema]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3535,7 +3535,7 @@ def TestAnthropic( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3568,7 +3568,7 @@ def TestAnthropicShorthand( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3601,7 +3601,7 @@ def TestAws( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3634,7 +3634,7 @@ def TestAzure( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3667,7 +3667,7 @@ def TestCaching( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3700,7 +3700,7 @@ def TestFallbackClient( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3732,7 +3732,7 @@ def TestFallbackToShorthand( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3765,7 +3765,7 @@ def TestFnNamedArgsSingleBool( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3798,7 +3798,7 @@ def TestFnNamedArgsSingleClass( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3831,7 +3831,7 @@ def TestFnNamedArgsSingleEnumList( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3864,7 +3864,7 @@ def TestFnNamedArgsSingleFloat( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3897,7 +3897,7 @@ def TestFnNamedArgsSingleInt( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3930,7 +3930,7 @@ def TestFnNamedArgsSingleMapStringToClass( ) -> baml_py.BamlSyncStream[Dict[str, partial_types.StringToClassEntry], Dict[str, types.StringToClassEntry]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3963,7 +3963,7 @@ def TestFnNamedArgsSingleMapStringToMap( ) -> baml_py.BamlSyncStream[Dict[str, Dict[str, Optional[str]]], Dict[str, Dict[str, str]]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -3996,7 +3996,7 @@ def TestFnNamedArgsSingleMapStringToString( ) -> baml_py.BamlSyncStream[Dict[str, Optional[str]], Dict[str, str]]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4029,7 +4029,7 @@ def TestFnNamedArgsSingleString( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4062,7 +4062,7 @@ def TestFnNamedArgsSingleStringArray( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4095,7 +4095,7 @@ def TestFnNamedArgsSingleStringList( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4128,7 +4128,7 @@ def TestGemini( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4161,7 +4161,7 @@ def TestImageInput( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4194,7 +4194,7 @@ def TestImageInputAnthropic( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4227,7 +4227,7 @@ def TestImageListInput( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4260,7 +4260,7 @@ def TestMulticlassNamedArgs( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4294,7 +4294,7 @@ def TestOllama( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4327,7 +4327,7 @@ def TestOpenAILegacyProvider( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4360,7 +4360,7 @@ def TestOpenAIShorthand( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4393,7 +4393,7 @@ def TestRetryConstant( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4425,7 +4425,7 @@ def TestRetryExponential( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4457,7 +4457,7 @@ def TestVertex( ) -> baml_py.BamlSyncStream[Optional[str], str]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) @@ -4490,7 +4490,7 @@ def UnionTest_Function( ) -> baml_py.BamlSyncStream[partial_types.UnionTest_ReturnType, types.UnionTest_ReturnType]: __tb__ = baml_options.get("tb", None) if __tb__ is not None: - tb = __tb__._tb + tb = __tb__._tb # type: ignore (we know how to use this private attribute) else: tb = None __cr__ = baml_options.get("client_registry", None) diff --git a/integ-tests/python/baml_client/type_builder.py b/integ-tests/python/baml_client/type_builder.py index 7a021d389..7b8d37a90 100644 --- a/integ-tests/python/baml_client/type_builder.py +++ b/integ-tests/python/baml_client/type_builder.py @@ -14,7 +14,8 @@ # pylint: disable=unused-import,line-too-long # fmt: off import typing -from baml_py.type_builder import FieldType, TypeBuilder as _TypeBuilder, ClassPropertyBuilder, EnumValueBuilder, EnumBuilder, ClassBuilder +from baml_py.baml_py import FieldType, EnumValueBuilder, EnumBuilder, ClassBuilder +from baml_py.type_builder import TypeBuilder as _TypeBuilder, ClassPropertyBuilder class TypeBuilder(_TypeBuilder): def __init__(self): @@ -25,51 +26,51 @@ def __init__(self): )) - - @property + @property def DummyOutput(self) -> "DummyOutputBuilder": return DummyOutputBuilder(self) - @property + @property def DynInputOutput(self) -> "DynInputOutputBuilder": return DynInputOutputBuilder(self) - @property + @property def DynamicClassOne(self) -> "DynamicClassOneBuilder": return DynamicClassOneBuilder(self) - @property + @property def DynamicClassTwo(self) -> "DynamicClassTwoBuilder": return DynamicClassTwoBuilder(self) - @property + @property def DynamicOutput(self) -> "DynamicOutputBuilder": return DynamicOutputBuilder(self) - @property + @property def Person(self) -> "PersonBuilder": return PersonBuilder(self) - @property + @property def SomeClassNestedDynamic(self) -> "SomeClassNestedDynamicBuilder": return SomeClassNestedDynamicBuilder(self) + @property def Color(self) -> "ColorBuilder": return ColorBuilder(self) @@ -92,8 +93,9 @@ def Hobby(self) -> "HobbyBuilder": class DummyOutputBuilder: def __init__(self, tb: _TypeBuilder): - self.__bldr = tb._tb.class_("DummyOutput") - self.__properties = set([ "nonce", "nonce2", ]) + _tb = tb._tb # type: ignore (we know how to use this private attribute) + self.__bldr = _tb.class_("DummyOutput") + self.__properties: typing.Set[str] = set([ "nonce", "nonce2", ]) self.__props = DummyOutputProperties(self.__bldr, self.__properties) def type(self) -> FieldType: @@ -104,7 +106,7 @@ def props(self) -> "DummyOutputProperties": return self.__props def list_properties(self) -> typing.List[typing.Tuple[str, ClassPropertyBuilder]]: - return [(name, self.__bldr.property(name)) for name in self.__properties] + return [(name, ClassPropertyBuilder(self.__bldr.property(name))) for name in self.__properties] def add_property(self, name: str, type: FieldType) -> ClassPropertyBuilder: if name in self.__properties: @@ -120,20 +122,22 @@ def __init__(self, cls_bldr: ClassBuilder, properties: typing.Set[str]): @property def nonce(self) -> ClassPropertyBuilder: - return self.__bldr.property("nonce") + return ClassPropertyBuilder(self.__bldr.property("nonce")) @property def nonce2(self) -> ClassPropertyBuilder: - return self.__bldr.property("nonce2") + return ClassPropertyBuilder(self.__bldr.property("nonce2")) def __getattr__(self, name: str) -> ClassPropertyBuilder: if name not in self.__properties: raise AttributeError(f"Property {name} not found.") return ClassPropertyBuilder(self.__bldr.property(name)) + class DynInputOutputBuilder: def __init__(self, tb: _TypeBuilder): - self.__bldr = tb._tb.class_("DynInputOutput") - self.__properties = set([ "testKey", ]) + _tb = tb._tb # type: ignore (we know how to use this private attribute) + self.__bldr = _tb.class_("DynInputOutput") + self.__properties: typing.Set[str] = set([ "testKey", ]) self.__props = DynInputOutputProperties(self.__bldr, self.__properties) def type(self) -> FieldType: @@ -144,7 +148,7 @@ def props(self) -> "DynInputOutputProperties": return self.__props def list_properties(self) -> typing.List[typing.Tuple[str, ClassPropertyBuilder]]: - return [(name, self.__bldr.property(name)) for name in self.__properties] + return [(name, ClassPropertyBuilder(self.__bldr.property(name))) for name in self.__properties] def add_property(self, name: str, type: FieldType) -> ClassPropertyBuilder: if name in self.__properties: @@ -160,16 +164,18 @@ def __init__(self, cls_bldr: ClassBuilder, properties: typing.Set[str]): @property def testKey(self) -> ClassPropertyBuilder: - return self.__bldr.property("testKey") + return ClassPropertyBuilder(self.__bldr.property("testKey")) def __getattr__(self, name: str) -> ClassPropertyBuilder: if name not in self.__properties: raise AttributeError(f"Property {name} not found.") return ClassPropertyBuilder(self.__bldr.property(name)) + class DynamicClassOneBuilder: def __init__(self, tb: _TypeBuilder): - self.__bldr = tb._tb.class_("DynamicClassOne") - self.__properties = set([]) + _tb = tb._tb # type: ignore (we know how to use this private attribute) + self.__bldr = _tb.class_("DynamicClassOne") + self.__properties: typing.Set[str] = set([]) self.__props = DynamicClassOneProperties(self.__bldr, self.__properties) def type(self) -> FieldType: @@ -180,7 +186,7 @@ def props(self) -> "DynamicClassOneProperties": return self.__props def list_properties(self) -> typing.List[typing.Tuple[str, ClassPropertyBuilder]]: - return [(name, self.__bldr.property(name)) for name in self.__properties] + return [(name, ClassPropertyBuilder(self.__bldr.property(name))) for name in self.__properties] def add_property(self, name: str, type: FieldType) -> ClassPropertyBuilder: if name in self.__properties: @@ -198,10 +204,12 @@ def __getattr__(self, name: str) -> ClassPropertyBuilder: if name not in self.__properties: raise AttributeError(f"Property {name} not found.") return ClassPropertyBuilder(self.__bldr.property(name)) + class DynamicClassTwoBuilder: def __init__(self, tb: _TypeBuilder): - self.__bldr = tb._tb.class_("DynamicClassTwo") - self.__properties = set([ "hi", "some_class", "status", ]) + _tb = tb._tb # type: ignore (we know how to use this private attribute) + self.__bldr = _tb.class_("DynamicClassTwo") + self.__properties: typing.Set[str] = set([ "hi", "some_class", "status", ]) self.__props = DynamicClassTwoProperties(self.__bldr, self.__properties) def type(self) -> FieldType: @@ -212,7 +220,7 @@ def props(self) -> "DynamicClassTwoProperties": return self.__props def list_properties(self) -> typing.List[typing.Tuple[str, ClassPropertyBuilder]]: - return [(name, self.__bldr.property(name)) for name in self.__properties] + return [(name, ClassPropertyBuilder(self.__bldr.property(name))) for name in self.__properties] def add_property(self, name: str, type: FieldType) -> ClassPropertyBuilder: if name in self.__properties: @@ -228,24 +236,26 @@ def __init__(self, cls_bldr: ClassBuilder, properties: typing.Set[str]): @property def hi(self) -> ClassPropertyBuilder: - return self.__bldr.property("hi") + return ClassPropertyBuilder(self.__bldr.property("hi")) @property def some_class(self) -> ClassPropertyBuilder: - return self.__bldr.property("some_class") + return ClassPropertyBuilder(self.__bldr.property("some_class")) @property def status(self) -> ClassPropertyBuilder: - return self.__bldr.property("status") + return ClassPropertyBuilder(self.__bldr.property("status")) def __getattr__(self, name: str) -> ClassPropertyBuilder: if name not in self.__properties: raise AttributeError(f"Property {name} not found.") return ClassPropertyBuilder(self.__bldr.property(name)) + class DynamicOutputBuilder: def __init__(self, tb: _TypeBuilder): - self.__bldr = tb._tb.class_("DynamicOutput") - self.__properties = set([]) + _tb = tb._tb # type: ignore (we know how to use this private attribute) + self.__bldr = _tb.class_("DynamicOutput") + self.__properties: typing.Set[str] = set([]) self.__props = DynamicOutputProperties(self.__bldr, self.__properties) def type(self) -> FieldType: @@ -256,7 +266,7 @@ def props(self) -> "DynamicOutputProperties": return self.__props def list_properties(self) -> typing.List[typing.Tuple[str, ClassPropertyBuilder]]: - return [(name, self.__bldr.property(name)) for name in self.__properties] + return [(name, ClassPropertyBuilder(self.__bldr.property(name))) for name in self.__properties] def add_property(self, name: str, type: FieldType) -> ClassPropertyBuilder: if name in self.__properties: @@ -274,10 +284,12 @@ def __getattr__(self, name: str) -> ClassPropertyBuilder: if name not in self.__properties: raise AttributeError(f"Property {name} not found.") return ClassPropertyBuilder(self.__bldr.property(name)) + class PersonBuilder: def __init__(self, tb: _TypeBuilder): - self.__bldr = tb._tb.class_("Person") - self.__properties = set([ "name", "hair_color", ]) + _tb = tb._tb # type: ignore (we know how to use this private attribute) + self.__bldr = _tb.class_("Person") + self.__properties: typing.Set[str] = set([ "name", "hair_color", ]) self.__props = PersonProperties(self.__bldr, self.__properties) def type(self) -> FieldType: @@ -288,7 +300,7 @@ def props(self) -> "PersonProperties": return self.__props def list_properties(self) -> typing.List[typing.Tuple[str, ClassPropertyBuilder]]: - return [(name, self.__bldr.property(name)) for name in self.__properties] + return [(name, ClassPropertyBuilder(self.__bldr.property(name))) for name in self.__properties] def add_property(self, name: str, type: FieldType) -> ClassPropertyBuilder: if name in self.__properties: @@ -304,20 +316,22 @@ def __init__(self, cls_bldr: ClassBuilder, properties: typing.Set[str]): @property def name(self) -> ClassPropertyBuilder: - return self.__bldr.property("name") + return ClassPropertyBuilder(self.__bldr.property("name")) @property def hair_color(self) -> ClassPropertyBuilder: - return self.__bldr.property("hair_color") + return ClassPropertyBuilder(self.__bldr.property("hair_color")) def __getattr__(self, name: str) -> ClassPropertyBuilder: if name not in self.__properties: raise AttributeError(f"Property {name} not found.") return ClassPropertyBuilder(self.__bldr.property(name)) + class SomeClassNestedDynamicBuilder: def __init__(self, tb: _TypeBuilder): - self.__bldr = tb._tb.class_("SomeClassNestedDynamic") - self.__properties = set([ "hi", ]) + _tb = tb._tb # type: ignore (we know how to use this private attribute) + self.__bldr = _tb.class_("SomeClassNestedDynamic") + self.__properties: typing.Set[str] = set([ "hi", ]) self.__props = SomeClassNestedDynamicProperties(self.__bldr, self.__properties) def type(self) -> FieldType: @@ -328,7 +342,7 @@ def props(self) -> "SomeClassNestedDynamicProperties": return self.__props def list_properties(self) -> typing.List[typing.Tuple[str, ClassPropertyBuilder]]: - return [(name, self.__bldr.property(name)) for name in self.__properties] + return [(name, ClassPropertyBuilder(self.__bldr.property(name))) for name in self.__properties] def add_property(self, name: str, type: FieldType) -> ClassPropertyBuilder: if name in self.__properties: @@ -344,7 +358,7 @@ def __init__(self, cls_bldr: ClassBuilder, properties: typing.Set[str]): @property def hi(self) -> ClassPropertyBuilder: - return self.__bldr.property("hi") + return ClassPropertyBuilder(self.__bldr.property("hi")) def __getattr__(self, name: str) -> ClassPropertyBuilder: if name not in self.__properties: @@ -353,10 +367,12 @@ def __getattr__(self, name: str) -> ClassPropertyBuilder: + class ColorBuilder: def __init__(self, tb: _TypeBuilder): - self.__bldr = tb._tb.enum("Color") - self.__values = set([ "RED", "BLUE", "GREEN", "YELLOW", "BLACK", "WHITE", ]) + _tb = tb._tb # type: ignore (we know how to use this private attribute) + self.__bldr = _tb.enum("Color") + self.__values: typing.Set[str] = set([ "RED", "BLUE", "GREEN", "YELLOW", "BLACK", "WHITE", ]) self.__vals = ColorValues(self.__bldr, self.__values) def type(self) -> FieldType: @@ -419,8 +435,9 @@ def __getattr__(self, name: str) -> EnumValueBuilder: class DynEnumOneBuilder: def __init__(self, tb: _TypeBuilder): - self.__bldr = tb._tb.enum("DynEnumOne") - self.__values = set([]) + _tb = tb._tb # type: ignore (we know how to use this private attribute) + self.__bldr = _tb.enum("DynEnumOne") + self.__values: typing.Set[str] = set([]) self.__vals = DynEnumOneValues(self.__bldr, self.__values) def type(self) -> FieldType: @@ -453,8 +470,9 @@ def __getattr__(self, name: str) -> EnumValueBuilder: class DynEnumTwoBuilder: def __init__(self, tb: _TypeBuilder): - self.__bldr = tb._tb.enum("DynEnumTwo") - self.__values = set([]) + _tb = tb._tb # type: ignore (we know how to use this private attribute) + self.__bldr = _tb.enum("DynEnumTwo") + self.__values: typing.Set[str] = set([]) self.__vals = DynEnumTwoValues(self.__bldr, self.__values) def type(self) -> FieldType: @@ -487,8 +505,9 @@ def __getattr__(self, name: str) -> EnumValueBuilder: class HobbyBuilder: def __init__(self, tb: _TypeBuilder): - self.__bldr = tb._tb.enum("Hobby") - self.__values = set([ "SPORTS", "MUSIC", "READING", ]) + _tb = tb._tb # type: ignore (we know how to use this private attribute) + self.__bldr = _tb.enum("Hobby") + self.__values: typing.Set[str] = set([ "SPORTS", "MUSIC", "READING", ]) self.__vals = HobbyValues(self.__bldr, self.__values) def type(self) -> FieldType: diff --git a/integ-tests/python/tests/test_functions.py b/integ-tests/python/tests/test_functions.py index 5447de542..8628a5af7 100644 --- a/integ-tests/python/tests/test_functions.py +++ b/integ-tests/python/tests/test_functions.py @@ -12,7 +12,6 @@ from baml_py import errors # also test importing the error from the baml_py submodules -from baml_py.errors import BamlValidationError, BamlClientError from ..baml_client import b from ..baml_client.sync_client import b as sync_b from ..baml_client.globals import ( @@ -617,7 +616,7 @@ async def test_dynamic_class_output(): baml_options={"tb": tb}, ) print(output.model_dump_json()) - assert output.hair_color == "black" + assert output.hair_color == "black" # type: ignore (dynamic property) @pytest.mark.asyncio @@ -703,7 +702,7 @@ async def test_stream_dynamic_class_output(): print("final ", final) print("final ", final.model_dump()) print("final ", final.model_dump_json()) - assert final.hair_color == "black" + assert final.hair_color == "black" # type: ignore (dynamic property) @pytest.mark.asyncio @@ -737,12 +736,12 @@ async def test_dynamic_inputs_list2(): ], {"tb": tb}, ) - assert res[0].new_key == "hi1" + assert res[0].new_key == "hi1" # type: ignore (dynamic property) assert res[0].testKey == "myTest" - assert res[0].blah["nestedKey1"] == "nestedVal" - assert res[1].new_key == "hi" + assert res[0].blah["nestedKey1"] == "nestedVal" # type: ignore (dynamic property) + assert res[1].new_key == "hi" # type: ignore (dynamic property) assert res[1].testKey == "myTest" - assert res[1].blah["nestedKey1"] == "nestedVal" + assert res[1].blah["nestedKey1"] == "nestedVal" # type: ignore (dynamic property) @pytest.mark.asyncio @@ -776,12 +775,12 @@ async def test_dynamic_inputs_list(): ], {"tb": tb}, ) - assert res[0].new_key == "hi" + assert res[0].new_key == "hi" # type: ignore (dynamic property) assert res[0].testKey == "myTest" - assert res[0].blah["nestedKey1"] == "nestedVal" - assert res[1].new_key == "hi" + assert res[0].blah["nestedKey1"] == "nestedVal" # type: ignore (dynamic property) + assert res[1].new_key == "hi" # type: ignore (dynamic property) assert res[1].testKey == "myTest" - assert res[1].blah["nestedKey1"] == "nestedVal" + assert res[1].blah["nestedKey1"] == "nestedVal" # type: ignore (dynamic property) @pytest.mark.asyncio @@ -803,9 +802,9 @@ async def test_dynamic_output_map(): print("final ", res) print("final ", res.model_dump()) print("final ", res.model_dump_json()) - assert res.hair_color == "black" - assert res.attributes["eye_color"] == "blue" - assert res.attributes["facial_hair"] == "beard" + assert res.hair_color == "black" # type: ignore (dynamic property) + assert res.attributes["eye_color"] == "blue" # type: ignore (dynamic property) + assert res.attributes["facial_hair"] == "beard" # type: ignore (dynamic property) @pytest.mark.asyncio @@ -837,10 +836,10 @@ async def test_dynamic_output_union(): print("final ", res) print("final ", res.model_dump()) print("final ", res.model_dump_json()) - assert res.hair_color == "black" - assert res.attributes["eye_color"] == "blue" - assert res.attributes["facial_hair"] == "beard" - assert res.height["feet"] == 6 + assert res.hair_color == "black" # type: ignore (dynamic property) + assert res.attributes["eye_color"] == "blue" # type: ignore (dynamic property) + assert res.attributes["facial_hair"] == "beard" # type: ignore (dynamic property) + assert res.height["feet"] == 6 # type: ignore (dynamic property) res = await b.MyFunc( input="My name is Harrison. My hair is black and I'm 1.8 meters tall. I have blue eyes and a beard. I am 30 years old.", @@ -850,10 +849,10 @@ async def test_dynamic_output_union(): print("final ", res) print("final ", res.model_dump()) print("final ", res.model_dump_json()) - assert res.hair_color == "black" - assert res.attributes["eye_color"] == "blue" - assert res.attributes["facial_hair"] == "beard" - assert res.height["meters"] == 1.8 + assert res.hair_color == "black" # type: ignore (dynamic property) + assert res.attributes["eye_color"] == "blue" # type: ignore (dynamic property) + assert res.attributes["facial_hair"] == "beard" # type: ignore (dynamic property) + assert res.height["meters"] == 1.8 # type: ignore (dynamic property) @pytest.mark.asyncio @@ -1008,6 +1007,7 @@ async def test_descriptions(): ) # Assuming this returns a Pydantic model # Check Nested2 values + assert not isinstance(res.prop2, str) assert res.prop2.prop20.prop11 == "three" assert res.prop2.prop20.prop12 == "four" @@ -1037,11 +1037,11 @@ async def test_caching(): rand = random.randint(0, 26) story_idea += " " + rand * "a" start = time.time() - res = await b.TestCaching(story_idea) + _ = await b.TestCaching(story_idea) duration = time.time() - start start = time.time() - res2 = await b.TestCaching(story_idea) + _ = await b.TestCaching(story_idea) duration2 = time.time() - start print("Duration no caching: ", duration) @@ -1059,8 +1059,8 @@ async def test_arg_exceptions(): with pytest.raises(errors.BamlInvalidArgumentError): _ = await b.TestCaching( - 111 - ) # ldintentionally passing an int instead of a string + 111 # type: ignore (intentionally passing an int instead of a string) + ) with pytest.raises(errors.BamlClientError): cr = baml_py.ClientRegistry() @@ -1092,12 +1092,8 @@ async def test_arg_exceptions(): async def test_map_as_param(): with pytest.raises(errors.BamlInvalidArgumentError): _ = await b.TestFnNamedArgsSingleMapStringToMap( - {"a": "b"} - ) # intentionally passing the wrong type - - -import os - + {"a": "b"} # type: ignore (intentionally passing the wrong type) + ) @pytest.mark.asyncio async def test_env_vars_reset(): @@ -1150,3 +1146,34 @@ async def test_baml_validation_error_format(): raise e assert "Failed to parse" in str(excinfo) + +@pytest.mark.asyncio +async def test_baml_finish_reason(): + cr = baml_py.ClientRegistry() + cr.add_llm_client("MyClient", "openai", {"model": "gpt-4o-mini", "max_tokens": 1, "finish_reason_whitelist": ["stop"]}) + cr.set_primary("MyClient") + + with pytest.raises(errors.BamlValidationError) as excinfo: + _ = await b.TestCaching("Tell me a story about food!", { + "client_registry": cr + }) + print("Exception message: ", excinfo) + assert "Non-terminal finish reason" in str(excinfo) + +@pytest.mark.asyncio +async def test_baml_finish_reason_streaming(): + cr = baml_py.ClientRegistry() + cr.add_llm_client("MyClient", "openai", {"model": "gpt-4o-mini", "max_tokens": 1, "finish_reason_whitelist": ["stop"]}) + cr.set_primary("MyClient") + + with pytest.raises(errors.BamlValidationError) as excinfo: + stream = b.stream.TestCaching("Tell me a story about food!", { + "client_registry": cr + }) + async for msg in stream: + print("streamed ", msg) + + _ = await stream.get_final_response() + + print("Exception message: ", excinfo) + assert "Non-terminal finish reason" in str(excinfo) \ No newline at end of file diff --git a/integ-tests/typescript/tests/integ-tests.test.ts b/integ-tests/typescript/tests/integ-tests.test.ts index 5c9aba440..d8e9c0393 100644 --- a/integ-tests/typescript/tests/integ-tests.test.ts +++ b/integ-tests/typescript/tests/integ-tests.test.ts @@ -641,6 +641,50 @@ describe('Integ tests', () => { ) expect(people.length).toBeGreaterThan(0) }) + + it('should handle non-terminal finish reason', async () => { + const cr = new ClientRegistry() + cr.addLlmClient('MyClient', 'openai', { model: 'gpt-4o-mini', max_tokens: 1, finish_reason_whitelist: ['stop'] }) + cr.setPrimary('MyClient') + + try { + await b.TestCaching('Tell me a story about food!', { + clientRegistry: cr, + }) + fail('Expected BamlValidationError to be thrown') + } catch (error: any) { + if (error instanceof BamlValidationError) { + console.log('Exception message:', error) + expect(error.message).toContain('Non-terminal finish reason') + } else { + fail('Expected error to be an instance of BamlValidationError') + } + } + }) + + it('should handle non-terminal finish reason in streaming', async () => { + const cr = new ClientRegistry() + cr.addLlmClient('MyClient', 'openai', { model: 'gpt-4o-mini', max_tokens: 1, finish_reason_whitelist: ['stop'] }) + cr.setPrimary('MyClient') + + try { + const stream = b.stream.TestCaching('Tell me a story about food!', { + clientRegistry: cr, + }) + for await (const msg of stream) { + console.log('streamed', msg) + } + await stream.getFinalResponse() + fail('Expected BamlValidationError to be thrown') + } catch (error: any) { + if (error instanceof BamlValidationError) { + console.log('Exception message:', error) + expect(error.message).toContain('Non-terminal finish reason') + } else { + fail('Expected error to be an instance of BamlValidationError') + } + } + }) }) interface MyInterface { From 535156c34137507573ca101b8ec4ef70a0ee985c Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Thu, 10 Oct 2024 21:45:01 -0700 Subject: [PATCH 2/2] rename --- docs/snippets/finish-reason.mdx | 6 ++-- .../internal/llm_client/properties_hander.rs | 28 +++++++++---------- integ-tests/python/tests/test_functions.py | 4 +-- .../typescript/tests/integ-tests.test.ts | 4 +-- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/docs/snippets/finish-reason.mdx b/docs/snippets/finish-reason.mdx index 4035a41da..2cb71540f 100644 --- a/docs/snippets/finish-reason.mdx +++ b/docs/snippets/finish-reason.mdx @@ -1,12 +1,14 @@ - + A list of finish reasons to allow. If set, any response with a finish reason not in this list will be rejected. Empty finish reasons are always allowed. + All others will be rejected. **Default: `[]`** - + A list of finish reasons to reject. If set, any response with a finish reason in this list will be rejected. + All others will be allowed. Empty finish reasons are always allowed. **Default: `[]`** diff --git a/engine/baml-runtime/src/internal/llm_client/properties_hander.rs b/engine/baml-runtime/src/internal/llm_client/properties_hander.rs index 2125ac39c..540948fa1 100644 --- a/engine/baml-runtime/src/internal/llm_client/properties_hander.rs +++ b/engine/baml-runtime/src/internal/llm_client/properties_hander.rs @@ -4,8 +4,8 @@ use std::collections::HashMap; use super::AllowedMetadata; pub enum FinishReasonOptions { - WhiteListed(Vec), - BlackListed(Vec), + AllowList(Vec), + DenyList(Vec), } impl FinishReasonOptions { @@ -14,10 +14,10 @@ impl FinishReasonOptions { return true; } match self { - FinishReasonOptions::WhiteListed(allow_list) => allow_list + FinishReasonOptions::AllowList(allowlist) => allowlist .iter() .any(|allowed| allowed.eq_ignore_ascii_case(finish_reason)), - FinishReasonOptions::BlackListed(deny_list) => !deny_list + FinishReasonOptions::DenyList(deny_list) => !deny_list .iter() .any(|denied| denied.eq_ignore_ascii_case(finish_reason)), } @@ -44,8 +44,8 @@ impl PropertiesHandler { pub fn remove(&mut self, key: &str) -> Result> { // Ban certain keys match key { - "finish_reason_whitelist" - | "finish_reason_blacklist" + "finish_reason_allowlist" + | "finish_reason_denylist" | "allowed_role_metadata" | "base_url" | "api_key" @@ -69,33 +69,33 @@ impl PropertiesHandler { } pub fn pull_finish_reason_options(&mut self) -> Result> { - let whitelist = match self.get("finish_reason_whitelist")? { + let allowlist = match self.get("finish_reason_allowlist")? { Some(value) => match value.as_array() { Some(array) => array .iter() .filter_map(|v| v.as_str().map(|s| s.to_string())) .collect::>(), - None => anyhow::bail!("finish_reason_whitelist must be an array of strings"), + None => anyhow::bail!("finish_reason_allowlist must be an array of strings"), }, None => vec![], }; - let blacklist = match self.get("finish_reason_blacklist")? { + let denylist = match self.get("finish_reason_denylist")? { Some(value) => match value.as_array() { Some(array) => array .iter() .filter_map(|v| v.as_str().map(|s| s.to_string())) .collect::>(), - None => anyhow::bail!("finish_reason_blacklist must be an array of strings"), + None => anyhow::bail!("finish_reason_denylist must be an array of strings"), }, None => vec![], }; - Ok(match (whitelist.is_empty(), blacklist.is_empty()) { - (false, true) => Some(FinishReasonOptions::WhiteListed(whitelist)), - (true, false) => Some(FinishReasonOptions::BlackListed(blacklist)), + Ok(match (allowlist.is_empty(), denylist.is_empty()) { + (false, true) => Some(FinishReasonOptions::AllowList(allowlist)), + (true, false) => Some(FinishReasonOptions::DenyList(denylist)), (false, false) => anyhow::bail!( - "Only one of finish_reason_whitelist or finish_reason_blacklist can be specified" + "Only one of finish_reason_allowlist or finish_reason_denylist can be specified" ), (true, true) => None, }) diff --git a/integ-tests/python/tests/test_functions.py b/integ-tests/python/tests/test_functions.py index 8628a5af7..32765de21 100644 --- a/integ-tests/python/tests/test_functions.py +++ b/integ-tests/python/tests/test_functions.py @@ -1150,7 +1150,7 @@ async def test_baml_validation_error_format(): @pytest.mark.asyncio async def test_baml_finish_reason(): cr = baml_py.ClientRegistry() - cr.add_llm_client("MyClient", "openai", {"model": "gpt-4o-mini", "max_tokens": 1, "finish_reason_whitelist": ["stop"]}) + cr.add_llm_client("MyClient", "openai", {"model": "gpt-4o-mini", "max_tokens": 1, "finish_reason_allowlist": ["stop"]}) cr.set_primary("MyClient") with pytest.raises(errors.BamlValidationError) as excinfo: @@ -1163,7 +1163,7 @@ async def test_baml_finish_reason(): @pytest.mark.asyncio async def test_baml_finish_reason_streaming(): cr = baml_py.ClientRegistry() - cr.add_llm_client("MyClient", "openai", {"model": "gpt-4o-mini", "max_tokens": 1, "finish_reason_whitelist": ["stop"]}) + cr.add_llm_client("MyClient", "openai", {"model": "gpt-4o-mini", "max_tokens": 1, "finish_reason_allowlist": ["stop"]}) cr.set_primary("MyClient") with pytest.raises(errors.BamlValidationError) as excinfo: diff --git a/integ-tests/typescript/tests/integ-tests.test.ts b/integ-tests/typescript/tests/integ-tests.test.ts index d8e9c0393..3c1bc1511 100644 --- a/integ-tests/typescript/tests/integ-tests.test.ts +++ b/integ-tests/typescript/tests/integ-tests.test.ts @@ -644,7 +644,7 @@ describe('Integ tests', () => { it('should handle non-terminal finish reason', async () => { const cr = new ClientRegistry() - cr.addLlmClient('MyClient', 'openai', { model: 'gpt-4o-mini', max_tokens: 1, finish_reason_whitelist: ['stop'] }) + cr.addLlmClient('MyClient', 'openai', { model: 'gpt-4o-mini', max_tokens: 1, finish_reason_allowlist: ['stop'] }) cr.setPrimary('MyClient') try { @@ -664,7 +664,7 @@ describe('Integ tests', () => { it('should handle non-terminal finish reason in streaming', async () => { const cr = new ClientRegistry() - cr.addLlmClient('MyClient', 'openai', { model: 'gpt-4o-mini', max_tokens: 1, finish_reason_whitelist: ['stop'] }) + cr.addLlmClient('MyClient', 'openai', { model: 'gpt-4o-mini', max_tokens: 1, finish_reason_allowlist: ['stop'] }) cr.setPrimary('MyClient') try {