diff --git a/engine/baml-lib/baml-core/src/ir/ir_helpers/to_baml_arg.rs b/engine/baml-lib/baml-core/src/ir/ir_helpers/to_baml_arg.rs index b50abb113..694af9910 100644 --- a/engine/baml-lib/baml-core/src/ir/ir_helpers/to_baml_arg.rs +++ b/engine/baml-lib/baml-core/src/ir/ir_helpers/to_baml_arg.rs @@ -27,7 +27,7 @@ impl ParameterError { pub fn validate_arg( ir: &IntermediateRepr, field_type: &FieldType, - value: &BamlValue, + value: &BamlValue, // original value passed in by user scope: &mut ScopeStack, allow_implicit_cast_to_string: bool, ) -> Option { @@ -158,6 +158,7 @@ pub fn validate_arg( BamlValue::Class(_, obj) | BamlValue::Map(obj) => match ir.find_class(name) { Ok(c) => { let mut fields = BamlMap::new(); + for f in c.walk_fields() { if let Some(v) = obj.get(f.name()) { if let Some(v) = validate_arg( @@ -177,6 +178,28 @@ pub fn validate_arg( )); } } + let is_dynamic = c.item.attributes.get("dynamic_type").is_some(); + if is_dynamic { + for (key, value) in obj { + if !fields.contains_key(key) { + fields.insert(key.clone(), value.clone()); + } + } + } else { + // throw an error if there are remaining fields + // instead of dropping them silently + // TODO, these extra dynamic fields should also be validated according to the runtime overrides. + // and we should also render the key by its alias. + for key in obj.keys() { + if !fields.contains_key(key) { + scope.push_error(format!( + "Unexpected field `{}` for class {}. Mark the class as @@dynamic if you want to allow additional fields.", + key, name + )); + } + } + } + Some(BamlValue::Class(name.to_string(), fields)) } Err(_) => { diff --git a/engine/baml-lib/jsonish/src/jsonish/parser/fixing_parser/json_collection.rs b/engine/baml-lib/jsonish/src/jsonish/parser/fixing_parser/json_collection.rs index 9faa75076..098cf205e 100644 --- a/engine/baml-lib/jsonish/src/jsonish/parser/fixing_parser/json_collection.rs +++ b/engine/baml-lib/jsonish/src/jsonish/parser/fixing_parser/json_collection.rs @@ -36,7 +36,7 @@ impl From for Option { Some(match collection { JsonCollection::TrailingComment(_) | JsonCollection::BlockComment(_) => return None, JsonCollection::Object(keys, values) => { - log::info!("keys: {:?}", keys); + // log::debug!("keys: {:?}", keys); let mut object = BamlMap::new(); for (key, value) in keys.into_iter().zip(values.into_iter()) { object.insert(key, value); 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 6a7eab701..b1b77eba9 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 @@ -391,7 +391,7 @@ impl RequestBuilder for AnthropicClient { if stream { body_obj.insert("stream".into(), true.into()); } - log::info!("Request body: {:#?}", body); + log::debug!("Request body: {:#?}", body); req.json(&body) } diff --git a/engine/baml-runtime/src/tracing/wasm_tracer.rs b/engine/baml-runtime/src/tracing/wasm_tracer.rs index 8046d5d88..3f7c25904 100644 --- a/engine/baml-runtime/src/tracing/wasm_tracer.rs +++ b/engine/baml-runtime/src/tracing/wasm_tracer.rs @@ -4,15 +4,10 @@ use super::api_wrapper::{core_types::LogSchema, APIWrapper, BoundaryAPI}; pub(super) struct NonThreadedTracer { options: APIWrapper, - log_event_callback: Option Result<()> + Send>>, } impl NonThreadedTracer { - pub fn new( - api_config: &APIWrapper, - _max_batch_size: usize, - log_event_callback: Option Result<()> + Send>>, - ) -> Self { + pub fn new(api_config: &APIWrapper, _max_batch_size: usize) -> Self { Self { options: api_config.clone(), } diff --git a/engine/language_client_typescript/src/types/runtime.rs b/engine/language_client_typescript/src/types/runtime.rs index 590830a2b..bf312566e 100644 --- a/engine/language_client_typescript/src/types/runtime.rs +++ b/engine/language_client_typescript/src/types/runtime.rs @@ -84,6 +84,7 @@ impl BamlRuntime { tb: Option<&TypeBuilder>, ) -> napi::Result { let args = parse_ts_types::js_object_to_baml_value(env, args)?; + if !args.is_map() { return Err(napi::Error::new( napi::Status::GenericFailure, diff --git a/integ-tests/baml_src/clients.baml b/integ-tests/baml_src/clients.baml index 8a21b61a3..bba97e3ab 100644 --- a/integ-tests/baml_src/clients.baml +++ b/integ-tests/baml_src/clients.baml @@ -16,7 +16,7 @@ retry_policy Foo { client GPT4 { provider baml-openai-chat options { - model gpt-4 + model gpt-4o api_key env.OPENAI_API_KEY } } diff --git a/integ-tests/baml_src/test-files/dynamic/dynamic.baml b/integ-tests/baml_src/test-files/dynamic/dynamic.baml index f2fa932d5..36ad77b5e 100644 --- a/integ-tests/baml_src/test-files/dynamic/dynamic.baml +++ b/integ-tests/baml_src/test-files/dynamic/dynamic.baml @@ -33,12 +33,45 @@ function DynamicFunc(input: DynamicClassOne) -> DynamicClassTwo { "# } +class DynInputOutput { + testKey string + @@dynamic +} + +function DynamicInputOutput(input: DynInputOutput) -> DynInputOutput { + client GPT35 + prompt #" + Here is some input data: + ---- + {{ input }} + ---- + + Extract the information. + {{ ctx.output_format }} + "# +} + +function DynamicListInputOutput(input: DynInputOutput[]) -> DynInputOutput[] { + client GPT35 + prompt #" + Here is some input data: + ---- + {{ input }} + ---- + + Extract the information. + {{ ctx.output_format }} + "# +} + + + class DynamicOutput { @@dynamic } function MyFunc(input: string) -> DynamicOutput { - client GPT4 + client GPT35 prompt #" Given a string, extract info using the schema: @@ -46,4 +79,5 @@ function MyFunc(input: string) -> DynamicOutput { {{ ctx.output_format }} "# -} \ No newline at end of file +} + diff --git a/integ-tests/baml_src/test-files/functions/input/named-args/single/named-image.baml b/integ-tests/baml_src/test-files/functions/input/named-args/single/named-image.baml index 464262b74..624525a2b 100644 --- a/integ-tests/baml_src/test-files/functions/input/named-args/single/named-image.baml +++ b/integ-tests/baml_src/test-files/functions/input/named-args/single/named-image.baml @@ -3,7 +3,7 @@ function TestImageInput(img: image) -> string{ prompt #" {{ _.role("user") }} - Describe this in 4 words {{img}} + Describe this in 4 words. One word must be the color {{img}} "# } diff --git a/integ-tests/python/baml_client/client.py b/integ-tests/python/baml_client/client.py index 665a1453e..722cd15ba 100644 --- a/integ-tests/python/baml_client/client.py +++ b/integ-tests/python/baml_client/client.py @@ -253,6 +253,50 @@ async def DynamicFunc( mdl = create_model("DynamicFuncReturnType", inner=(types.DynamicClassTwo, ...)) return coerce(mdl, raw.parsed()) + async def DynamicInputOutput( + self, + input: types.DynInputOutput, + baml_options: BamlCallOptions = {}, + ) -> types.DynInputOutput: + __tb__ = baml_options.get("tb", None) + if __tb__ is not None: + tb = __tb__._tb + else: + tb = None + + raw = await self.__runtime.call_function( + "DynamicInputOutput", + { + "input": input, + }, + self.__ctx_manager.get(), + tb, + ) + mdl = create_model("DynamicInputOutputReturnType", inner=(types.DynInputOutput, ...)) + return coerce(mdl, raw.parsed()) + + async def DynamicListInputOutput( + self, + input: List[types.DynInputOutput], + baml_options: BamlCallOptions = {}, + ) -> List[types.DynInputOutput]: + __tb__ = baml_options.get("tb", None) + if __tb__ is not None: + tb = __tb__._tb + else: + tb = None + + raw = await self.__runtime.call_function( + "DynamicListInputOutput", + { + "input": input, + }, + self.__ctx_manager.get(), + tb, + ) + mdl = create_model("DynamicListInputOutputReturnType", inner=(List[types.DynInputOutput], ...)) + return coerce(mdl, raw.parsed()) + async def ExtractNames( self, input: str, @@ -1610,6 +1654,70 @@ def DynamicFunc( tb, ) + def DynamicInputOutput( + self, + input: types.DynInputOutput, + baml_options: BamlCallOptions = {}, + ) -> baml_py.BamlStream[partial_types.DynInputOutput, types.DynInputOutput]: + __tb__ = baml_options.get("tb", None) + if __tb__ is not None: + tb = __tb__._tb + else: + tb = None + + raw = self.__runtime.stream_function( + "DynamicInputOutput", + { + "input": input, + }, + None, + self.__ctx_manager.get(), + tb, + ) + + mdl = create_model("DynamicInputOutputReturnType", inner=(types.DynInputOutput, ...)) + partial_mdl = create_model("DynamicInputOutputPartialReturnType", inner=(partial_types.DynInputOutput, ...)) + + return baml_py.BamlStream[partial_types.DynInputOutput, types.DynInputOutput]( + raw, + lambda x: coerce(partial_mdl, x), + lambda x: coerce(mdl, x), + self.__ctx_manager.get(), + tb, + ) + + def DynamicListInputOutput( + self, + input: List[types.DynInputOutput], + baml_options: BamlCallOptions = {}, + ) -> baml_py.BamlStream[List[partial_types.DynInputOutput], List[types.DynInputOutput]]: + __tb__ = baml_options.get("tb", None) + if __tb__ is not None: + tb = __tb__._tb + else: + tb = None + + raw = self.__runtime.stream_function( + "DynamicListInputOutput", + { + "input": input, + }, + None, + self.__ctx_manager.get(), + tb, + ) + + mdl = create_model("DynamicListInputOutputReturnType", inner=(List[types.DynInputOutput], ...)) + partial_mdl = create_model("DynamicListInputOutputPartialReturnType", inner=(List[partial_types.DynInputOutput], ...)) + + return baml_py.BamlStream[List[partial_types.DynInputOutput], List[types.DynInputOutput]]( + raw, + lambda x: coerce(partial_mdl, x), + lambda x: coerce(mdl, x), + self.__ctx_manager.get(), + tb, + ) + def ExtractNames( self, input: str, diff --git a/integ-tests/python/baml_client/inlinedbaml.py b/integ-tests/python/baml_client/inlinedbaml.py index c4ffe039d..e14aa9fab 100644 --- a/integ-tests/python/baml_client/inlinedbaml.py +++ b/integ-tests/python/baml_client/inlinedbaml.py @@ -16,7 +16,7 @@ file_map = { - "clients.baml": "retry_policy Bar {\n max_retries 3\n strategy {\n type exponential_backoff\n }\n}\n\nretry_policy Foo {\n max_retries 3\n strategy {\n type constant_delay\n delay_ms 100\n }\n}\n\nclient GPT4 {\n provider baml-openai-chat\n options {\n model gpt-4\n api_key env.OPENAI_API_KEY\n }\n} \n\n\nclient GPT4o {\n provider baml-openai-chat\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n} \n\n\nclient GPT4Turbo {\n retry_policy Bar\n provider baml-openai-chat\n options {\n model gpt-4-turbo\n api_key env.OPENAI_API_KEY\n }\n} \n\nclient GPT35 {\n provider baml-openai-chat\n options {\n model \"gpt-3.5-turbo\"\n api_key env.OPENAI_API_KEY\n }\n}\n\nclient Ollama {\n provider ollama\n options {\n model llama2\n }\n}\n\nclient GPT35Azure {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n // base_url \"https://west-us-azure-baml.openai.azure.com/openai/deployments/gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\nclient Gemini {\n provider google-ai\n options{\n model \"gemini-1.5-pro-001\"\n api_key env.GOOGLE_API_KEY\n }\n}\n\n\nclient Claude {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 1000\n }\n}\n\nclient Resilient_SimpleSyntax {\n retry_policy Foo\n provider baml-fallback\n options {\n strategy [\n GPT4Turbo\n GPT35\n Lottery_SimpleSyntax\n ]\n }\n} \n \nclient Lottery_SimpleSyntax {\n provider baml-round-robin\n options {\n start 0\n strategy [\n GPT35\n Claude\n ]\n }\n}\n", + "clients.baml": "retry_policy Bar {\n max_retries 3\n strategy {\n type exponential_backoff\n }\n}\n\nretry_policy Foo {\n max_retries 3\n strategy {\n type constant_delay\n delay_ms 100\n }\n}\n\nclient GPT4 {\n provider baml-openai-chat\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n} \n\n\nclient GPT4o {\n provider baml-openai-chat\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n} \n\n\nclient GPT4Turbo {\n retry_policy Bar\n provider baml-openai-chat\n options {\n model gpt-4-turbo\n api_key env.OPENAI_API_KEY\n }\n} \n\nclient GPT35 {\n provider baml-openai-chat\n options {\n model \"gpt-3.5-turbo\"\n api_key env.OPENAI_API_KEY\n }\n}\n\nclient Ollama {\n provider ollama\n options {\n model llama2\n }\n}\n\nclient GPT35Azure {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n // base_url \"https://west-us-azure-baml.openai.azure.com/openai/deployments/gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\nclient Gemini {\n provider google-ai\n options{\n model \"gemini-1.5-pro-001\"\n api_key env.GOOGLE_API_KEY\n }\n}\n\n\nclient Claude {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 1000\n }\n}\n\nclient Resilient_SimpleSyntax {\n retry_policy Foo\n provider baml-fallback\n options {\n strategy [\n GPT4Turbo\n GPT35\n Lottery_SimpleSyntax\n ]\n }\n} \n \nclient Lottery_SimpleSyntax {\n provider baml-round-robin\n options {\n start 0\n strategy [\n GPT35\n Claude\n ]\n }\n}\n", "fiddle-examples/chain-of-thought.baml": "class Email {\n subject string\n body string\n from_address string\n}\n\nenum OrderStatus {\n ORDERED\n SHIPPED\n DELIVERED\n CANCELLED\n}\n\nclass OrderInfo {\n order_status OrderStatus\n tracking_number string?\n estimated_arrival_date string?\n}\n\nfunction GetOrderInfo(email: Email) -> OrderInfo {\n client GPT4\n prompt #\"\n Given the email below:\n\n ```\n from: {{email.from_address}}\n Email Subject: {{email.subject}}\n Email Body: {{email.body}}\n ```\n\n Extract this info from the email in JSON format:\n {{ ctx.output_format }}\n\n Before you output the JSON, please explain your\n reasoning step-by-step. Here is an example on how to do this:\n 'If we think step by step we can see that ...\n therefore the output JSON is:\n {\n ... the json schema ...\n }'\n \"#\n}", "fiddle-examples/chat-roles.baml": "// This will be available as an enum in your Python and Typescript code.\nenum Category2 {\n Refund\n CancelOrder\n TechnicalSupport\n AccountIssue\n Question\n}\n\nfunction ClassifyMessage2(input: string) -> Category {\n client GPT4\n\n prompt #\"\n {{ _.role(\"system\") }}\n // You can use _.role(\"system\") to indicate that this text should be a system message\n\n Classify the following INPUT into ONE\n of the following categories:\n\n {{ ctx.output_format }}\n\n {{ _.role(\"user\") }}\n // And _.role(\"user\") to indicate that this text should be a user message\n\n INPUT: {{ input }}\n\n Response:\n \"#\n}", "fiddle-examples/classify-message.baml": "// This will be available as an enum in your Python and Typescript code.\nenum Category {\n Refund\n CancelOrder\n TechnicalSupport\n AccountIssue\n Question\n}\n\nfunction ClassifyMessage(input: string) -> Category {\n client GPT4\n\n prompt #\"\n Classify the following INPUT into ONE\n of the following categories:\n\n INPUT: {{ input }}\n\n {{ ctx.output_format }}\n\n Response:\n \"#\n}", @@ -27,7 +27,7 @@ "test-files/aliases/classes.baml": "class TestClassAlias {\n key string @alias(\"key-dash\") @description(#\"\n This is a description for key\n af asdf\n \"#)\n key2 string @alias(\"key21\")\n key3 string @alias(\"key with space\")\n key4 string //unaliased\n key5 string @alias(\"key.with.punctuation/123\")\n}\n\nfunction FnTestClassAlias(input: string) -> TestClassAlias {\n client GPT35\n prompt #\"\n {{ctx.output_format}}\n \"#\n}\n\ntest FnTestClassAlias {\n functions [FnTestClassAlias]\n args {\n input \"example input\"\n }\n}\n", "test-files/aliases/enums.baml": "enum TestEnum {\n A @alias(\"k1\") @description(#\"\n User is angry\n \"#)\n B @alias(\"k22\") @description(#\"\n User is happy\n \"#)\n // tests whether k1 doesnt incorrectly get matched with k11\n C @alias(\"k11\") @description(#\"\n User is sad\n \"#)\n D @alias(\"k44\") @description(\n User is confused\n )\n E @description(\n User is excited\n )\n F @alias(\"k5\") // only alias\n \n G @alias(\"k6\") @description(#\"\n User is bored\n With a long description\n \"#)\n \n @@alias(\"Category\")\n}\n\nfunction FnTestAliasedEnumOutput(input: string) -> TestEnum {\n client GPT35\n prompt #\"\n Classify the user input into the following category\n \n {{ ctx.output_format }}\n\n {{ _.role('user') }}\n {{input}}\n\n {{ _.role('assistant') }}\n Category ID:\n \"#\n}\n\ntest FnTestAliasedEnumOutput {\n functions [FnTestAliasedEnumOutput]\n args {\n input \"mehhhhh\"\n }\n}", "test-files/comments/comments.baml": "// add some functions, classes, enums etc with comments all over.", - "test-files/dynamic/dynamic.baml": "class DynamicClassOne {\n @@dynamic\n}\n\nenum DynEnumOne {\n @@dynamic\n}\n\nenum DynEnumTwo {\n @@dynamic\n}\n\nclass SomeClassNestedDynamic {\n hi string\n @@dynamic\n\n}\n\nclass DynamicClassTwo {\n hi string\n some_class SomeClassNestedDynamic\n status DynEnumOne\n @@dynamic\n}\n\nfunction DynamicFunc(input: DynamicClassOne) -> DynamicClassTwo {\n client GPT35\n prompt #\"\n Please extract the schema from \n {{ input }}\n\n {{ ctx.output_format }}\n \"#\n}\n\nclass DynamicOutput {\n @@dynamic\n}\n \nfunction MyFunc(input: string) -> DynamicOutput {\n client GPT4\n prompt #\"\n Given a string, extract info using the schema:\n\n {{ input}}\n\n {{ ctx.output_format }}\n \"#\n}", + "test-files/dynamic/dynamic.baml": "class DynamicClassOne {\n @@dynamic\n}\n\nenum DynEnumOne {\n @@dynamic\n}\n\nenum DynEnumTwo {\n @@dynamic\n}\n\nclass SomeClassNestedDynamic {\n hi string\n @@dynamic\n\n}\n\nclass DynamicClassTwo {\n hi string\n some_class SomeClassNestedDynamic\n status DynEnumOne\n @@dynamic\n}\n\nfunction DynamicFunc(input: DynamicClassOne) -> DynamicClassTwo {\n client GPT35\n prompt #\"\n Please extract the schema from \n {{ input }}\n\n {{ ctx.output_format }}\n \"#\n}\n\nclass DynInputOutput {\n testKey string\n @@dynamic\n}\n\nfunction DynamicInputOutput(input: DynInputOutput) -> DynInputOutput {\n client GPT35\n prompt #\"\n Here is some input data:\n ----\n {{ input }}\n ----\n\n Extract the information.\n {{ ctx.output_format }}\n \"#\n}\n\nfunction DynamicListInputOutput(input: DynInputOutput[]) -> DynInputOutput[] {\n client GPT35\n prompt #\"\n Here is some input data:\n ----\n {{ input }}\n ----\n\n Extract the information.\n {{ ctx.output_format }}\n \"#\n}\n\n\n\nclass DynamicOutput {\n @@dynamic\n}\n \nfunction MyFunc(input: string) -> DynamicOutput {\n client GPT35\n prompt #\"\n Given a string, extract info using the schema:\n\n {{ input}}\n\n {{ ctx.output_format }}\n \"#\n}\n\n", "test-files/functions/input/named-args/single/named-audio.baml": "function AudioInput(aud: audio) -> string{\n client Gemini\n prompt #\"\n {{ _.role(\"user\") }}\n\n Does this sound like a roar? Yes or no? One word no other characters.\n \n {{ aud }}\n \"#\n}\n\n\ntest TestURLAudioInput{\n functions [AudioInput]\n args {\n aud{ \n url https://actions.google.com/sounds/v1/emergency/beeper_emergency_call.ogg\n }\n } \n}\n\n\n", "test-files/functions/input/named-args/single/named-boolean.baml": "\n\nfunction TestFnNamedArgsSingleBool(myBool: bool) -> string{\n client GPT35\n prompt #\"\n Return this value back to me: {{myBool}}\n \"#\n}\n\ntest TestFnNamedArgsSingleBool {\n functions [TestFnNamedArgsSingleBool]\n args {\n myBool true\n }\n}", "test-files/functions/input/named-args/single/named-class-list.baml": "\n\n\nfunction TestFnNamedArgsSingleStringList(myArg: string[]) -> string{\n client GPT35\n prompt #\"\n Return this value back to me: {{myArg}}\n \"#\n}\n\ntest TestFnNamedArgsSingleStringList {\n functions [TestFnNamedArgsSingleStringList]\n args {\n myArg [\"hello\", \"world\"]\n }\n}", @@ -35,7 +35,7 @@ "test-files/functions/input/named-args/single/named-enum-list.baml": "enum NamedArgsSingleEnumList {\n ONE\n TWO\n}\n\nfunction TestFnNamedArgsSingleEnumList(myArg: NamedArgsSingleEnumList[]) -> string {\n client GPT35\n prompt #\"\n Print these values back to me:\n {{myArg}}\n \"#\n}\n\ntest TestFnNamedArgsSingleEnumList {\n functions [TestFnNamedArgsSingleEnumList]\n args {\n myArg [ONE, TWO]\n }\n}", "test-files/functions/input/named-args/single/named-enum.baml": "enum NamedArgsSingleEnum {\n ONE\n TWO\n}\n\nfunction FnTestNamedArgsSingleEnum(myArg: NamedArgsSingleEnum) -> string {\n client GPT35\n prompt #\"\n Print these values back to me:\n {{myArg}}\n \"#\n}\n\ntest FnTestNamedArgsSingleEnum {\n functions [FnTestNamedArgsSingleEnum]\n args {\n myArg ONE\n }\n}", "test-files/functions/input/named-args/single/named-float.baml": "function TestFnNamedArgsSingleFloat(myFloat: float) -> string {\n client GPT35\n prompt #\"\n Return this value back to me: {{myFloat}}\n \"#\n}\n\ntest TestFnNamedArgsSingleFloat {\n functions [TestFnNamedArgsSingleFloat]\n args {\n myFloat 3.14\n }\n}\n", - "test-files/functions/input/named-args/single/named-image.baml": "function TestImageInput(img: image) -> string{\n client Claude\n prompt #\"\n {{ _.role(\"user\") }}\n\n Describe this in 4 words {{img}}\n \"#\n}\n\ntest TestImageInput {\n functions [TestImageInput]\n args {\n img {\n url \"https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png\"\n }\n }\n}\n\ntest shrek {\n functions [TestImageInput]\n args {\n img {\n url \"https://upload.wikimedia.org/wikipedia/en/4/4d/Shrek_%28character%29.png\"\n }\n }\n}\n\n\n\n// double check this before adding it. Probably n ot right.\n// function TestImageInputAnthropic(img: image) -> string{\n// client GPT4o\n// prompt #\"\n// {{ _.role(\"user\") }}\n\n// Describe this in 4 words {{img}}\n// \"#\n// }\n\n// test TestImageInputAnthropic {\n// functions [TestImageInputAnthropic]\n// args {\n// img {\n// base64 iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=\n// media_type \"image/png\"\n// }\n// }\n// }", + "test-files/functions/input/named-args/single/named-image.baml": "function TestImageInput(img: image) -> string{\n client Claude\n prompt #\"\n {{ _.role(\"user\") }}\n\n Describe this in 4 words. One word must be the color {{img}}\n \"#\n}\n\ntest TestImageInput {\n functions [TestImageInput]\n args {\n img {\n url \"https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png\"\n }\n }\n}\n\ntest shrek {\n functions [TestImageInput]\n args {\n img {\n url \"https://upload.wikimedia.org/wikipedia/en/4/4d/Shrek_%28character%29.png\"\n }\n }\n}\n\n\n\n// double check this before adding it. Probably n ot right.\n// function TestImageInputAnthropic(img: image) -> string{\n// client GPT4o\n// prompt #\"\n// {{ _.role(\"user\") }}\n\n// Describe this in 4 words {{img}}\n// \"#\n// }\n\n// test TestImageInputAnthropic {\n// functions [TestImageInputAnthropic]\n// args {\n// img {\n// base64 iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=\n// media_type \"image/png\"\n// }\n// }\n// }", "test-files/functions/input/named-args/single/named-int.baml": "// test for int\nfunction TestFnNamedArgsSingleInt(myInt: int) -> string {\n client GPT35\n prompt #\"\n Return this value back to me: {{myInt}}\n \"#\n}\n\ntest TestFnNamedArgsSingleInt {\n functions [TestFnNamedArgsSingleInt]\n args {\n myInt 42\n }\n}\n", "test-files/functions/input/named-args/single/named-string-list.baml": "// string[]\nfunction TestFnNamedArgsSingleStringArray(myStringArray: string[]) -> string {\n client GPT35\n prompt #\"\n Return this value back to me: {{myStringArray}}\n \"#\n}\n\ntest TestFnNamedArgsSingleStringArray {\n functions [TestFnNamedArgsSingleStringArray]\n args {\n myStringArray [\"example1\", \"example2\", \"example3\"]\n }\n}\n", "test-files/functions/input/named-args/single/named-string-optional.baml": "\n\n // string[]\nfunction FnNamedArgsSingleStringOptional(myString: string?) -> string {\n client GPT35\n prompt #\"\n Return this value back to me: {{myString}}\n \"#\n}\n\ntest FnNamedArgsSingleStringOptional {\n functions [FnNamedArgsSingleStringOptional]\n args {\n myString \"example string\"\n }\n}\n\ntest FnNamedArgsSingleStringOptional2 {\n functions [FnNamedArgsSingleStringOptional]\n args {\n \n }\n}\n", diff --git a/integ-tests/python/baml_client/partial_types.py b/integ-tests/python/baml_client/partial_types.py index b6f12e325..88cb27341 100644 --- a/integ-tests/python/baml_client/partial_types.py +++ b/integ-tests/python/baml_client/partial_types.py @@ -53,6 +53,12 @@ class ClassWithImage(BaseModel): param2: Optional[str] = None fake_image: Optional["FakeImage"] = None +class DynInputOutput(BaseModel): + + model_config = ConfigDict(extra='allow') + + testKey: Optional[str] = None + class DynamicClassOne(BaseModel): model_config = ConfigDict(extra='allow') diff --git a/integ-tests/python/baml_client/type_builder.py b/integ-tests/python/baml_client/type_builder.py index 189265dda..a617a8e77 100644 --- a/integ-tests/python/baml_client/type_builder.py +++ b/integ-tests/python/baml_client/type_builder.py @@ -19,13 +19,18 @@ class TypeBuilder(_TypeBuilder): def __init__(self): super().__init__(classes=set( - ["Blah","ClassOptionalOutput","ClassOptionalOutput2","ClassWithImage","DynamicClassOne","DynamicClassTwo","DynamicOutput","Education","Email","Event","FakeImage","InnerClass","InnerClass2","NamedArgsSingleClass","OptionalTest_Prop1","OptionalTest_ReturnType","OrderInfo","Person","RaysData","Resume","SearchParams","SomeClassNestedDynamic","TestClassAlias","TestClassNested","TestClassWithEnum","TestOutputClass","UnionTest_ReturnType","WithReasoning",] + ["Blah","ClassOptionalOutput","ClassOptionalOutput2","ClassWithImage","DynInputOutput","DynamicClassOne","DynamicClassTwo","DynamicOutput","Education","Email","Event","FakeImage","InnerClass","InnerClass2","NamedArgsSingleClass","OptionalTest_Prop1","OptionalTest_ReturnType","OrderInfo","Person","RaysData","Resume","SearchParams","SomeClassNestedDynamic","TestClassAlias","TestClassNested","TestClassWithEnum","TestOutputClass","UnionTest_ReturnType","WithReasoning",] ), enums=set( ["Category","Category2","Category3","Color","DataType","DynEnumOne","DynEnumTwo","EnumInClass","EnumOutput","Hobby","NamedArgsSingleEnum","NamedArgsSingleEnumList","OptionalTest_CategoryType","OrderStatus","Tag","TestEnum",] )) + @property + def DynInputOutput(self) -> "DynInputOutputBuilder": + return DynInputOutputBuilder(self) + + @property def DynamicClassOne(self) -> "DynamicClassOneBuilder": return DynamicClassOneBuilder(self) @@ -73,6 +78,42 @@ def Hobby(self) -> "HobbyBuilder": return HobbyBuilder(self) +class DynInputOutputBuilder: + def __init__(self, tb: _TypeBuilder): + self.__bldr = tb._tb.class_("DynInputOutput") + self.__properties = set([ "testKey", ]) + self.__props = DynInputOutputProperties(self.__bldr, self.__properties) + + def type(self) -> FieldType: + return self.__bldr.field() + + @property + 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] + + def add_property(self, name: str, type: FieldType) -> ClassPropertyBuilder: + if name in self.__properties: + raise ValueError(f"Property {name} already exists.") + return ClassPropertyBuilder(self.__bldr.property(name).type(type)) + +class DynInputOutputProperties: + def __init__(self, cls_bldr: ClassBuilder, properties: typing.Set[str]): + self.__bldr = cls_bldr + self.__properties = properties + + + + @property + def testKey(self) -> ClassPropertyBuilder: + return 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") diff --git a/integ-tests/python/baml_client/types.py b/integ-tests/python/baml_client/types.py index 00bdc6fec..d738d8ed1 100644 --- a/integ-tests/python/baml_client/types.py +++ b/integ-tests/python/baml_client/types.py @@ -144,6 +144,12 @@ class ClassWithImage(BaseModel): param2: str fake_image: "FakeImage" +class DynInputOutput(BaseModel): + + model_config = ConfigDict(extra='allow') + + testKey: str + class DynamicClassOne(BaseModel): model_config = ConfigDict(extra='allow') diff --git a/integ-tests/ruby/baml_client/client.rb b/integ-tests/ruby/baml_client/client.rb index ab539367a..d3c578b42 100644 --- a/integ-tests/ruby/baml_client/client.rb +++ b/integ-tests/ruby/baml_client/client.rb @@ -229,6 +229,46 @@ def DynamicFunc( (raw.parsed_using_types(Baml::Types)) end + sig { + + params( + input: Baml::Types::DynInputOutput, + ).returns(Baml::Types::DynInputOutput) + + } + def DynamicInputOutput( + input: + ) + raw = @runtime.call_function( + "DynamicInputOutput", + { + "input" => input, + }, + @ctx_manager, + ) + (raw.parsed_using_types(Baml::Types)) + end + + sig { + + params( + input: T::Array[Baml::Types::DynInputOutput], + ).returns(T::Array[Baml::Types::DynInputOutput]) + + } + def DynamicListInputOutput( + input: + ) + raw = @runtime.call_function( + "DynamicListInputOutput", + { + "input" => input, + }, + @ctx_manager, + ) + (raw.parsed_using_types(Baml::Types)) + end + sig { params( @@ -1385,6 +1425,48 @@ def DynamicFunc( ) end + sig { + params( + input: Baml::Types::DynInputOutput, + ).returns(Baml::BamlStream[Baml::Types::DynInputOutput]) + } + def DynamicInputOutput( + input: + ) + raw = @runtime.stream_function( + "DynamicInputOutput", + { + "input" => input, + }, + @ctx_manager, + ) + Baml::BamlStream[Baml::PartialTypes::DynInputOutput, Baml::Types::DynInputOutput].new( + ffi_stream: raw, + ctx_manager: @ctx_manager + ) + end + + sig { + params( + input: T::Array[Baml::Types::DynInputOutput], + ).returns(Baml::BamlStream[T::Array[Baml::Types::DynInputOutput]]) + } + def DynamicListInputOutput( + input: + ) + raw = @runtime.stream_function( + "DynamicListInputOutput", + { + "input" => input, + }, + @ctx_manager, + ) + Baml::BamlStream[T::Array[Baml::PartialTypes::DynInputOutput], T::Array[Baml::Types::DynInputOutput]].new( + ffi_stream: raw, + ctx_manager: @ctx_manager + ) + end + sig { params( input: String, diff --git a/integ-tests/ruby/baml_client/inlined.rb b/integ-tests/ruby/baml_client/inlined.rb index 032b985f6..5957b6cf6 100644 --- a/integ-tests/ruby/baml_client/inlined.rb +++ b/integ-tests/ruby/baml_client/inlined.rb @@ -16,7 +16,7 @@ module Baml module Inlined FILE_MAP = { - "clients.baml" => "retry_policy Bar {\n max_retries 3\n strategy {\n type exponential_backoff\n }\n}\n\nretry_policy Foo {\n max_retries 3\n strategy {\n type constant_delay\n delay_ms 100\n }\n}\n\nclient GPT4 {\n provider baml-openai-chat\n options {\n model gpt-4\n api_key env.OPENAI_API_KEY\n }\n} \n\n\nclient GPT4o {\n provider baml-openai-chat\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n} \n\n\nclient GPT4Turbo {\n retry_policy Bar\n provider baml-openai-chat\n options {\n model gpt-4-turbo\n api_key env.OPENAI_API_KEY\n }\n} \n\nclient GPT35 {\n provider baml-openai-chat\n options {\n model \"gpt-3.5-turbo\"\n api_key env.OPENAI_API_KEY\n }\n}\n\nclient Ollama {\n provider ollama\n options {\n model llama2\n }\n}\n\nclient GPT35Azure {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n // base_url \"https://west-us-azure-baml.openai.azure.com/openai/deployments/gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\nclient Gemini {\n provider google-ai\n options{\n model \"gemini-1.5-pro-001\"\n api_key env.GOOGLE_API_KEY\n }\n}\n\n\nclient Claude {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 1000\n }\n}\n\nclient Resilient_SimpleSyntax {\n retry_policy Foo\n provider baml-fallback\n options {\n strategy [\n GPT4Turbo\n GPT35\n Lottery_SimpleSyntax\n ]\n }\n} \n \nclient Lottery_SimpleSyntax {\n provider baml-round-robin\n options {\n start 0\n strategy [\n GPT35\n Claude\n ]\n }\n}\n", + "clients.baml" => "retry_policy Bar {\n max_retries 3\n strategy {\n type exponential_backoff\n }\n}\n\nretry_policy Foo {\n max_retries 3\n strategy {\n type constant_delay\n delay_ms 100\n }\n}\n\nclient GPT4 {\n provider baml-openai-chat\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n} \n\n\nclient GPT4o {\n provider baml-openai-chat\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n} \n\n\nclient GPT4Turbo {\n retry_policy Bar\n provider baml-openai-chat\n options {\n model gpt-4-turbo\n api_key env.OPENAI_API_KEY\n }\n} \n\nclient GPT35 {\n provider baml-openai-chat\n options {\n model \"gpt-3.5-turbo\"\n api_key env.OPENAI_API_KEY\n }\n}\n\nclient Ollama {\n provider ollama\n options {\n model llama2\n }\n}\n\nclient GPT35Azure {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n // base_url \"https://west-us-azure-baml.openai.azure.com/openai/deployments/gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\nclient Gemini {\n provider google-ai\n options{\n model \"gemini-1.5-pro-001\"\n api_key env.GOOGLE_API_KEY\n }\n}\n\n\nclient Claude {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 1000\n }\n}\n\nclient Resilient_SimpleSyntax {\n retry_policy Foo\n provider baml-fallback\n options {\n strategy [\n GPT4Turbo\n GPT35\n Lottery_SimpleSyntax\n ]\n }\n} \n \nclient Lottery_SimpleSyntax {\n provider baml-round-robin\n options {\n start 0\n strategy [\n GPT35\n Claude\n ]\n }\n}\n", "fiddle-examples/chain-of-thought.baml" => "class Email {\n subject string\n body string\n from_address string\n}\n\nenum OrderStatus {\n ORDERED\n SHIPPED\n DELIVERED\n CANCELLED\n}\n\nclass OrderInfo {\n order_status OrderStatus\n tracking_number string?\n estimated_arrival_date string?\n}\n\nfunction GetOrderInfo(email: Email) -> OrderInfo {\n client GPT4\n prompt #\"\n Given the email below:\n\n ```\n from: {{email.from_address}}\n Email Subject: {{email.subject}}\n Email Body: {{email.body}}\n ```\n\n Extract this info from the email in JSON format:\n {{ ctx.output_format }}\n\n Before you output the JSON, please explain your\n reasoning step-by-step. Here is an example on how to do this:\n 'If we think step by step we can see that ...\n therefore the output JSON is:\n {\n ... the json schema ...\n }'\n \"#\n}", "fiddle-examples/chat-roles.baml" => "// This will be available as an enum in your Python and Typescript code.\nenum Category2 {\n Refund\n CancelOrder\n TechnicalSupport\n AccountIssue\n Question\n}\n\nfunction ClassifyMessage2(input: string) -> Category {\n client GPT4\n\n prompt #\"\n {{ _.role(\"system\") }}\n // You can use _.role(\"system\") to indicate that this text should be a system message\n\n Classify the following INPUT into ONE\n of the following categories:\n\n {{ ctx.output_format }}\n\n {{ _.role(\"user\") }}\n // And _.role(\"user\") to indicate that this text should be a user message\n\n INPUT: {{ input }}\n\n Response:\n \"#\n}", "fiddle-examples/classify-message.baml" => "// This will be available as an enum in your Python and Typescript code.\nenum Category {\n Refund\n CancelOrder\n TechnicalSupport\n AccountIssue\n Question\n}\n\nfunction ClassifyMessage(input: string) -> Category {\n client GPT4\n\n prompt #\"\n Classify the following INPUT into ONE\n of the following categories:\n\n INPUT: {{ input }}\n\n {{ ctx.output_format }}\n\n Response:\n \"#\n}", @@ -27,7 +27,7 @@ module Inlined "test-files/aliases/classes.baml" => "class TestClassAlias {\n key string @alias(\"key-dash\") @description(#\"\n This is a description for key\n af asdf\n \"#)\n key2 string @alias(\"key21\")\n key3 string @alias(\"key with space\")\n key4 string //unaliased\n key5 string @alias(\"key.with.punctuation/123\")\n}\n\nfunction FnTestClassAlias(input: string) -> TestClassAlias {\n client GPT35\n prompt #\"\n {{ctx.output_format}}\n \"#\n}\n\ntest FnTestClassAlias {\n functions [FnTestClassAlias]\n args {\n input \"example input\"\n }\n}\n", "test-files/aliases/enums.baml" => "enum TestEnum {\n A @alias(\"k1\") @description(#\"\n User is angry\n \"#)\n B @alias(\"k22\") @description(#\"\n User is happy\n \"#)\n // tests whether k1 doesnt incorrectly get matched with k11\n C @alias(\"k11\") @description(#\"\n User is sad\n \"#)\n D @alias(\"k44\") @description(\n User is confused\n )\n E @description(\n User is excited\n )\n F @alias(\"k5\") // only alias\n \n G @alias(\"k6\") @description(#\"\n User is bored\n With a long description\n \"#)\n \n @@alias(\"Category\")\n}\n\nfunction FnTestAliasedEnumOutput(input: string) -> TestEnum {\n client GPT35\n prompt #\"\n Classify the user input into the following category\n \n {{ ctx.output_format }}\n\n {{ _.role('user') }}\n {{input}}\n\n {{ _.role('assistant') }}\n Category ID:\n \"#\n}\n\ntest FnTestAliasedEnumOutput {\n functions [FnTestAliasedEnumOutput]\n args {\n input \"mehhhhh\"\n }\n}", "test-files/comments/comments.baml" => "// add some functions, classes, enums etc with comments all over.", - "test-files/dynamic/dynamic.baml" => "class DynamicClassOne {\n @@dynamic\n}\n\nenum DynEnumOne {\n @@dynamic\n}\n\nenum DynEnumTwo {\n @@dynamic\n}\n\nclass SomeClassNestedDynamic {\n hi string\n @@dynamic\n\n}\n\nclass DynamicClassTwo {\n hi string\n some_class SomeClassNestedDynamic\n status DynEnumOne\n @@dynamic\n}\n\nfunction DynamicFunc(input: DynamicClassOne) -> DynamicClassTwo {\n client GPT35\n prompt #\"\n Please extract the schema from \n {{ input }}\n\n {{ ctx.output_format }}\n \"#\n}\n\nclass DynamicOutput {\n @@dynamic\n}\n \nfunction MyFunc(input: string) -> DynamicOutput {\n client GPT4\n prompt #\"\n Given a string, extract info using the schema:\n\n {{ input}}\n\n {{ ctx.output_format }}\n \"#\n}", + "test-files/dynamic/dynamic.baml" => "class DynamicClassOne {\n @@dynamic\n}\n\nenum DynEnumOne {\n @@dynamic\n}\n\nenum DynEnumTwo {\n @@dynamic\n}\n\nclass SomeClassNestedDynamic {\n hi string\n @@dynamic\n\n}\n\nclass DynamicClassTwo {\n hi string\n some_class SomeClassNestedDynamic\n status DynEnumOne\n @@dynamic\n}\n\nfunction DynamicFunc(input: DynamicClassOne) -> DynamicClassTwo {\n client GPT35\n prompt #\"\n Please extract the schema from \n {{ input }}\n\n {{ ctx.output_format }}\n \"#\n}\n\nclass DynInputOutput {\n testKey string\n @@dynamic\n}\n\nfunction DynamicInputOutput(input: DynInputOutput) -> DynInputOutput {\n client GPT35\n prompt #\"\n Here is some input data:\n ----\n {{ input }}\n ----\n\n Extract the information.\n {{ ctx.output_format }}\n \"#\n}\n\nfunction DynamicListInputOutput(input: DynInputOutput[]) -> DynInputOutput[] {\n client GPT35\n prompt #\"\n Here is some input data:\n ----\n {{ input }}\n ----\n\n Extract the information.\n {{ ctx.output_format }}\n \"#\n}\n\n\n\nclass DynamicOutput {\n @@dynamic\n}\n \nfunction MyFunc(input: string) -> DynamicOutput {\n client GPT35\n prompt #\"\n Given a string, extract info using the schema:\n\n {{ input}}\n\n {{ ctx.output_format }}\n \"#\n}\n\n", "test-files/functions/input/named-args/single/named-audio.baml" => "function AudioInput(aud: audio) -> string{\n client Gemini\n prompt #\"\n {{ _.role(\"user\") }}\n\n Does this sound like a roar? Yes or no? One word no other characters.\n \n {{ aud }}\n \"#\n}\n\n\ntest TestURLAudioInput{\n functions [AudioInput]\n args {\n aud{ \n url https://actions.google.com/sounds/v1/emergency/beeper_emergency_call.ogg\n }\n } \n}\n\n\n", "test-files/functions/input/named-args/single/named-boolean.baml" => "\n\nfunction TestFnNamedArgsSingleBool(myBool: bool) -> string{\n client GPT35\n prompt #\"\n Return this value back to me: {{myBool}}\n \"#\n}\n\ntest TestFnNamedArgsSingleBool {\n functions [TestFnNamedArgsSingleBool]\n args {\n myBool true\n }\n}", "test-files/functions/input/named-args/single/named-class-list.baml" => "\n\n\nfunction TestFnNamedArgsSingleStringList(myArg: string[]) -> string{\n client GPT35\n prompt #\"\n Return this value back to me: {{myArg}}\n \"#\n}\n\ntest TestFnNamedArgsSingleStringList {\n functions [TestFnNamedArgsSingleStringList]\n args {\n myArg [\"hello\", \"world\"]\n }\n}", @@ -35,7 +35,7 @@ module Inlined "test-files/functions/input/named-args/single/named-enum-list.baml" => "enum NamedArgsSingleEnumList {\n ONE\n TWO\n}\n\nfunction TestFnNamedArgsSingleEnumList(myArg: NamedArgsSingleEnumList[]) -> string {\n client GPT35\n prompt #\"\n Print these values back to me:\n {{myArg}}\n \"#\n}\n\ntest TestFnNamedArgsSingleEnumList {\n functions [TestFnNamedArgsSingleEnumList]\n args {\n myArg [ONE, TWO]\n }\n}", "test-files/functions/input/named-args/single/named-enum.baml" => "enum NamedArgsSingleEnum {\n ONE\n TWO\n}\n\nfunction FnTestNamedArgsSingleEnum(myArg: NamedArgsSingleEnum) -> string {\n client GPT35\n prompt #\"\n Print these values back to me:\n {{myArg}}\n \"#\n}\n\ntest FnTestNamedArgsSingleEnum {\n functions [FnTestNamedArgsSingleEnum]\n args {\n myArg ONE\n }\n}", "test-files/functions/input/named-args/single/named-float.baml" => "function TestFnNamedArgsSingleFloat(myFloat: float) -> string {\n client GPT35\n prompt #\"\n Return this value back to me: {{myFloat}}\n \"#\n}\n\ntest TestFnNamedArgsSingleFloat {\n functions [TestFnNamedArgsSingleFloat]\n args {\n myFloat 3.14\n }\n}\n", - "test-files/functions/input/named-args/single/named-image.baml" => "function TestImageInput(img: image) -> string{\n client Claude\n prompt #\"\n {{ _.role(\"user\") }}\n\n Describe this in 4 words {{img}}\n \"#\n}\n\ntest TestImageInput {\n functions [TestImageInput]\n args {\n img {\n url \"https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png\"\n }\n }\n}\n\ntest shrek {\n functions [TestImageInput]\n args {\n img {\n url \"https://upload.wikimedia.org/wikipedia/en/4/4d/Shrek_%28character%29.png\"\n }\n }\n}\n\n\n\n// double check this before adding it. Probably n ot right.\n// function TestImageInputAnthropic(img: image) -> string{\n// client GPT4o\n// prompt #\"\n// {{ _.role(\"user\") }}\n\n// Describe this in 4 words {{img}}\n// \"#\n// }\n\n// test TestImageInputAnthropic {\n// functions [TestImageInputAnthropic]\n// args {\n// img {\n// base64 iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=\n// media_type \"image/png\"\n// }\n// }\n// }", + "test-files/functions/input/named-args/single/named-image.baml" => "function TestImageInput(img: image) -> string{\n client Claude\n prompt #\"\n {{ _.role(\"user\") }}\n\n Describe this in 4 words. One word must be the color {{img}}\n \"#\n}\n\ntest TestImageInput {\n functions [TestImageInput]\n args {\n img {\n url \"https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png\"\n }\n }\n}\n\ntest shrek {\n functions [TestImageInput]\n args {\n img {\n url \"https://upload.wikimedia.org/wikipedia/en/4/4d/Shrek_%28character%29.png\"\n }\n }\n}\n\n\n\n// double check this before adding it. Probably n ot right.\n// function TestImageInputAnthropic(img: image) -> string{\n// client GPT4o\n// prompt #\"\n// {{ _.role(\"user\") }}\n\n// Describe this in 4 words {{img}}\n// \"#\n// }\n\n// test TestImageInputAnthropic {\n// functions [TestImageInputAnthropic]\n// args {\n// img {\n// base64 iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=\n// media_type \"image/png\"\n// }\n// }\n// }", "test-files/functions/input/named-args/single/named-int.baml" => "// test for int\nfunction TestFnNamedArgsSingleInt(myInt: int) -> string {\n client GPT35\n prompt #\"\n Return this value back to me: {{myInt}}\n \"#\n}\n\ntest TestFnNamedArgsSingleInt {\n functions [TestFnNamedArgsSingleInt]\n args {\n myInt 42\n }\n}\n", "test-files/functions/input/named-args/single/named-string-list.baml" => "// string[]\nfunction TestFnNamedArgsSingleStringArray(myStringArray: string[]) -> string {\n client GPT35\n prompt #\"\n Return this value back to me: {{myStringArray}}\n \"#\n}\n\ntest TestFnNamedArgsSingleStringArray {\n functions [TestFnNamedArgsSingleStringArray]\n args {\n myStringArray [\"example1\", \"example2\", \"example3\"]\n }\n}\n", "test-files/functions/input/named-args/single/named-string-optional.baml" => "\n\n // string[]\nfunction FnNamedArgsSingleStringOptional(myString: string?) -> string {\n client GPT35\n prompt #\"\n Return this value back to me: {{myString}}\n \"#\n}\n\ntest FnNamedArgsSingleStringOptional {\n functions [FnNamedArgsSingleStringOptional]\n args {\n myString \"example string\"\n }\n}\n\ntest FnNamedArgsSingleStringOptional2 {\n functions [FnNamedArgsSingleStringOptional]\n args {\n \n }\n}\n", diff --git a/integ-tests/ruby/baml_client/partial-types.rb b/integ-tests/ruby/baml_client/partial-types.rb index 1697d7c55..5198d1b94 100644 --- a/integ-tests/ruby/baml_client/partial-types.rb +++ b/integ-tests/ruby/baml_client/partial-types.rb @@ -25,6 +25,7 @@ class Blah < T::Struct; end class ClassOptionalOutput < T::Struct; end class ClassOptionalOutput2 < T::Struct; end class ClassWithImage < T::Struct; end + class DynInputOutput < T::Struct; end class DynamicClassOne < T::Struct; end class DynamicClassTwo < T::Struct; end class DynamicOutput < T::Struct; end @@ -70,6 +71,10 @@ class ClassWithImage < T::Struct const :param2, T.nilable(String) const :fake_image, Baml::PartialTypes::FakeImage end + class DynInputOutput < T::Struct + include T::Struct::ActsAsComparable + const :testKey, T.nilable(String) + end class DynamicClassOne < T::Struct include T::Struct::ActsAsComparable end diff --git a/integ-tests/ruby/baml_client/types.rb b/integ-tests/ruby/baml_client/types.rb index 5b299b8ef..a6810d3c0 100644 --- a/integ-tests/ruby/baml_client/types.rb +++ b/integ-tests/ruby/baml_client/types.rb @@ -135,6 +135,7 @@ class Blah < T::Struct; end class ClassOptionalOutput < T::Struct; end class ClassOptionalOutput2 < T::Struct; end class ClassWithImage < T::Struct; end + class DynInputOutput < T::Struct; end class DynamicClassOne < T::Struct; end class DynamicClassTwo < T::Struct; end class DynamicOutput < T::Struct; end @@ -180,6 +181,10 @@ class ClassWithImage < T::Struct const :param2, String const :fake_image, Baml::Types::FakeImage end + class DynInputOutput < T::Struct + include T::Struct::ActsAsComparable + const :testKey, String + end class DynamicClassOne < T::Struct include T::Struct::ActsAsComparable end diff --git a/integ-tests/typescript/baml_client/client.ts b/integ-tests/typescript/baml_client/client.ts index 2cb8026ae..aca736544 100644 --- a/integ-tests/typescript/baml_client/client.ts +++ b/integ-tests/typescript/baml_client/client.ts @@ -16,7 +16,7 @@ $ pnpm add @boundaryml/baml // biome-ignore format: autogenerated code /* eslint-disable */ import { BamlRuntime, FunctionResult, BamlCtxManager, BamlStream, Image } from "@boundaryml/baml" -import {Blah, ClassOptionalOutput, ClassOptionalOutput2, ClassWithImage, DynamicClassOne, DynamicClassTwo, DynamicOutput, Education, Email, Event, FakeImage, InnerClass, InnerClass2, NamedArgsSingleClass, OptionalTest_Prop1, OptionalTest_ReturnType, OrderInfo, Person, RaysData, Resume, SearchParams, SomeClassNestedDynamic, TestClassAlias, TestClassNested, TestClassWithEnum, TestOutputClass, UnionTest_ReturnType, WithReasoning, Category, Category2, Category3, Color, DataType, DynEnumOne, DynEnumTwo, EnumInClass, EnumOutput, Hobby, NamedArgsSingleEnum, NamedArgsSingleEnumList, OptionalTest_CategoryType, OrderStatus, Tag, TestEnum} from "./types" +import {Blah, ClassOptionalOutput, ClassOptionalOutput2, ClassWithImage, DynInputOutput, DynamicClassOne, DynamicClassTwo, DynamicOutput, Education, Email, Event, FakeImage, InnerClass, InnerClass2, NamedArgsSingleClass, OptionalTest_Prop1, OptionalTest_ReturnType, OrderInfo, Person, RaysData, Resume, SearchParams, SomeClassNestedDynamic, TestClassAlias, TestClassNested, TestClassWithEnum, TestOutputClass, UnionTest_ReturnType, WithReasoning, Category, Category2, Category3, Color, DataType, DynEnumOne, DynEnumTwo, EnumInClass, EnumOutput, Hobby, NamedArgsSingleEnum, NamedArgsSingleEnumList, OptionalTest_CategoryType, OrderStatus, Tag, TestEnum} from "./types" import TypeBuilder from "./type_builder" export type RecursivePartialNull = T extends object @@ -172,6 +172,36 @@ export class BamlClient { return raw.parsed() as DynamicClassTwo } + async DynamicInputOutput( + input: DynInputOutput, + __baml_options__?: { tb?: TypeBuilder } + ): Promise { + const raw = await this.runtime.callFunction( + "DynamicInputOutput", + { + "input": input + }, + this.ctx_manager.get(), + __baml_options__?.tb?.__tb(), + ) + return raw.parsed() as DynInputOutput + } + + async DynamicListInputOutput( + input: DynInputOutput[], + __baml_options__?: { tb?: TypeBuilder } + ): Promise { + const raw = await this.runtime.callFunction( + "DynamicListInputOutput", + { + "input": input + }, + this.ctx_manager.get(), + __baml_options__?.tb?.__tb(), + ) + return raw.parsed() as DynInputOutput[] + } + async ExtractNames( input: string, __baml_options__?: { tb?: TypeBuilder } @@ -1096,6 +1126,50 @@ class BamlStreamClient { ) } + DynamicInputOutput( + input: DynInputOutput, + __baml_options__?: { tb?: TypeBuilder } + ): BamlStream, DynInputOutput> { + const raw = this.runtime.streamFunction( + "DynamicInputOutput", + { + "input": input + }, + undefined, + this.ctx_manager.get(), + __baml_options__?.tb?.__tb(), + ) + return new BamlStream, DynInputOutput>( + raw, + (a): a is RecursivePartialNull => a, + (a): a is DynInputOutput => a, + this.ctx_manager.get(), + __baml_options__?.tb?.__tb(), + ) + } + + DynamicListInputOutput( + input: DynInputOutput[], + __baml_options__?: { tb?: TypeBuilder } + ): BamlStream, DynInputOutput[]> { + const raw = this.runtime.streamFunction( + "DynamicListInputOutput", + { + "input": input + }, + undefined, + this.ctx_manager.get(), + __baml_options__?.tb?.__tb(), + ) + return new BamlStream, DynInputOutput[]>( + raw, + (a): a is RecursivePartialNull => a, + (a): a is DynInputOutput[] => a, + this.ctx_manager.get(), + __baml_options__?.tb?.__tb(), + ) + } + ExtractNames( input: string, __baml_options__?: { tb?: TypeBuilder } diff --git a/integ-tests/typescript/baml_client/inlinedbaml.ts b/integ-tests/typescript/baml_client/inlinedbaml.ts index f70184518..6db5229dd 100644 --- a/integ-tests/typescript/baml_client/inlinedbaml.ts +++ b/integ-tests/typescript/baml_client/inlinedbaml.ts @@ -17,7 +17,7 @@ $ pnpm add @boundaryml/baml /* eslint-disable */ const fileMap = { - "clients.baml": "retry_policy Bar {\n max_retries 3\n strategy {\n type exponential_backoff\n }\n}\n\nretry_policy Foo {\n max_retries 3\n strategy {\n type constant_delay\n delay_ms 100\n }\n}\n\nclient GPT4 {\n provider baml-openai-chat\n options {\n model gpt-4\n api_key env.OPENAI_API_KEY\n }\n} \n\n\nclient GPT4o {\n provider baml-openai-chat\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n} \n\n\nclient GPT4Turbo {\n retry_policy Bar\n provider baml-openai-chat\n options {\n model gpt-4-turbo\n api_key env.OPENAI_API_KEY\n }\n} \n\nclient GPT35 {\n provider baml-openai-chat\n options {\n model \"gpt-3.5-turbo\"\n api_key env.OPENAI_API_KEY\n }\n}\n\nclient Ollama {\n provider ollama\n options {\n model llama2\n }\n}\n\nclient GPT35Azure {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n // base_url \"https://west-us-azure-baml.openai.azure.com/openai/deployments/gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\nclient Gemini {\n provider google-ai\n options{\n model \"gemini-1.5-pro-001\"\n api_key env.GOOGLE_API_KEY\n }\n}\n\n\nclient Claude {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 1000\n }\n}\n\nclient Resilient_SimpleSyntax {\n retry_policy Foo\n provider baml-fallback\n options {\n strategy [\n GPT4Turbo\n GPT35\n Lottery_SimpleSyntax\n ]\n }\n} \n \nclient Lottery_SimpleSyntax {\n provider baml-round-robin\n options {\n start 0\n strategy [\n GPT35\n Claude\n ]\n }\n}\n", + "clients.baml": "retry_policy Bar {\n max_retries 3\n strategy {\n type exponential_backoff\n }\n}\n\nretry_policy Foo {\n max_retries 3\n strategy {\n type constant_delay\n delay_ms 100\n }\n}\n\nclient GPT4 {\n provider baml-openai-chat\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n} \n\n\nclient GPT4o {\n provider baml-openai-chat\n options {\n model gpt-4o\n api_key env.OPENAI_API_KEY\n }\n} \n\n\nclient GPT4Turbo {\n retry_policy Bar\n provider baml-openai-chat\n options {\n model gpt-4-turbo\n api_key env.OPENAI_API_KEY\n }\n} \n\nclient GPT35 {\n provider baml-openai-chat\n options {\n model \"gpt-3.5-turbo\"\n api_key env.OPENAI_API_KEY\n }\n}\n\nclient Ollama {\n provider ollama\n options {\n model llama2\n }\n}\n\nclient GPT35Azure {\n provider azure-openai\n options {\n resource_name \"west-us-azure-baml\"\n deployment_id \"gpt-35-turbo-default\"\n // base_url \"https://west-us-azure-baml.openai.azure.com/openai/deployments/gpt-35-turbo-default\"\n api_version \"2024-02-01\"\n api_key env.AZURE_OPENAI_API_KEY\n }\n}\n\nclient Gemini {\n provider google-ai\n options{\n model \"gemini-1.5-pro-001\"\n api_key env.GOOGLE_API_KEY\n }\n}\n\n\nclient Claude {\n provider anthropic\n options {\n model claude-3-haiku-20240307\n api_key env.ANTHROPIC_API_KEY\n max_tokens 1000\n }\n}\n\nclient Resilient_SimpleSyntax {\n retry_policy Foo\n provider baml-fallback\n options {\n strategy [\n GPT4Turbo\n GPT35\n Lottery_SimpleSyntax\n ]\n }\n} \n \nclient Lottery_SimpleSyntax {\n provider baml-round-robin\n options {\n start 0\n strategy [\n GPT35\n Claude\n ]\n }\n}\n", "fiddle-examples/chain-of-thought.baml": "class Email {\n subject string\n body string\n from_address string\n}\n\nenum OrderStatus {\n ORDERED\n SHIPPED\n DELIVERED\n CANCELLED\n}\n\nclass OrderInfo {\n order_status OrderStatus\n tracking_number string?\n estimated_arrival_date string?\n}\n\nfunction GetOrderInfo(email: Email) -> OrderInfo {\n client GPT4\n prompt #\"\n Given the email below:\n\n ```\n from: {{email.from_address}}\n Email Subject: {{email.subject}}\n Email Body: {{email.body}}\n ```\n\n Extract this info from the email in JSON format:\n {{ ctx.output_format }}\n\n Before you output the JSON, please explain your\n reasoning step-by-step. Here is an example on how to do this:\n 'If we think step by step we can see that ...\n therefore the output JSON is:\n {\n ... the json schema ...\n }'\n \"#\n}", "fiddle-examples/chat-roles.baml": "// This will be available as an enum in your Python and Typescript code.\nenum Category2 {\n Refund\n CancelOrder\n TechnicalSupport\n AccountIssue\n Question\n}\n\nfunction ClassifyMessage2(input: string) -> Category {\n client GPT4\n\n prompt #\"\n {{ _.role(\"system\") }}\n // You can use _.role(\"system\") to indicate that this text should be a system message\n\n Classify the following INPUT into ONE\n of the following categories:\n\n {{ ctx.output_format }}\n\n {{ _.role(\"user\") }}\n // And _.role(\"user\") to indicate that this text should be a user message\n\n INPUT: {{ input }}\n\n Response:\n \"#\n}", "fiddle-examples/classify-message.baml": "// This will be available as an enum in your Python and Typescript code.\nenum Category {\n Refund\n CancelOrder\n TechnicalSupport\n AccountIssue\n Question\n}\n\nfunction ClassifyMessage(input: string) -> Category {\n client GPT4\n\n prompt #\"\n Classify the following INPUT into ONE\n of the following categories:\n\n INPUT: {{ input }}\n\n {{ ctx.output_format }}\n\n Response:\n \"#\n}", @@ -28,7 +28,7 @@ const fileMap = { "test-files/aliases/classes.baml": "class TestClassAlias {\n key string @alias(\"key-dash\") @description(#\"\n This is a description for key\n af asdf\n \"#)\n key2 string @alias(\"key21\")\n key3 string @alias(\"key with space\")\n key4 string //unaliased\n key5 string @alias(\"key.with.punctuation/123\")\n}\n\nfunction FnTestClassAlias(input: string) -> TestClassAlias {\n client GPT35\n prompt #\"\n {{ctx.output_format}}\n \"#\n}\n\ntest FnTestClassAlias {\n functions [FnTestClassAlias]\n args {\n input \"example input\"\n }\n}\n", "test-files/aliases/enums.baml": "enum TestEnum {\n A @alias(\"k1\") @description(#\"\n User is angry\n \"#)\n B @alias(\"k22\") @description(#\"\n User is happy\n \"#)\n // tests whether k1 doesnt incorrectly get matched with k11\n C @alias(\"k11\") @description(#\"\n User is sad\n \"#)\n D @alias(\"k44\") @description(\n User is confused\n )\n E @description(\n User is excited\n )\n F @alias(\"k5\") // only alias\n \n G @alias(\"k6\") @description(#\"\n User is bored\n With a long description\n \"#)\n \n @@alias(\"Category\")\n}\n\nfunction FnTestAliasedEnumOutput(input: string) -> TestEnum {\n client GPT35\n prompt #\"\n Classify the user input into the following category\n \n {{ ctx.output_format }}\n\n {{ _.role('user') }}\n {{input}}\n\n {{ _.role('assistant') }}\n Category ID:\n \"#\n}\n\ntest FnTestAliasedEnumOutput {\n functions [FnTestAliasedEnumOutput]\n args {\n input \"mehhhhh\"\n }\n}", "test-files/comments/comments.baml": "// add some functions, classes, enums etc with comments all over.", - "test-files/dynamic/dynamic.baml": "class DynamicClassOne {\n @@dynamic\n}\n\nenum DynEnumOne {\n @@dynamic\n}\n\nenum DynEnumTwo {\n @@dynamic\n}\n\nclass SomeClassNestedDynamic {\n hi string\n @@dynamic\n\n}\n\nclass DynamicClassTwo {\n hi string\n some_class SomeClassNestedDynamic\n status DynEnumOne\n @@dynamic\n}\n\nfunction DynamicFunc(input: DynamicClassOne) -> DynamicClassTwo {\n client GPT35\n prompt #\"\n Please extract the schema from \n {{ input }}\n\n {{ ctx.output_format }}\n \"#\n}\n\nclass DynamicOutput {\n @@dynamic\n}\n \nfunction MyFunc(input: string) -> DynamicOutput {\n client GPT4\n prompt #\"\n Given a string, extract info using the schema:\n\n {{ input}}\n\n {{ ctx.output_format }}\n \"#\n}", + "test-files/dynamic/dynamic.baml": "class DynamicClassOne {\n @@dynamic\n}\n\nenum DynEnumOne {\n @@dynamic\n}\n\nenum DynEnumTwo {\n @@dynamic\n}\n\nclass SomeClassNestedDynamic {\n hi string\n @@dynamic\n\n}\n\nclass DynamicClassTwo {\n hi string\n some_class SomeClassNestedDynamic\n status DynEnumOne\n @@dynamic\n}\n\nfunction DynamicFunc(input: DynamicClassOne) -> DynamicClassTwo {\n client GPT35\n prompt #\"\n Please extract the schema from \n {{ input }}\n\n {{ ctx.output_format }}\n \"#\n}\n\nclass DynInputOutput {\n testKey string\n @@dynamic\n}\n\nfunction DynamicInputOutput(input: DynInputOutput) -> DynInputOutput {\n client GPT35\n prompt #\"\n Here is some input data:\n ----\n {{ input }}\n ----\n\n Extract the information.\n {{ ctx.output_format }}\n \"#\n}\n\nfunction DynamicListInputOutput(input: DynInputOutput[]) -> DynInputOutput[] {\n client GPT35\n prompt #\"\n Here is some input data:\n ----\n {{ input }}\n ----\n\n Extract the information.\n {{ ctx.output_format }}\n \"#\n}\n\n\n\nclass DynamicOutput {\n @@dynamic\n}\n \nfunction MyFunc(input: string) -> DynamicOutput {\n client GPT35\n prompt #\"\n Given a string, extract info using the schema:\n\n {{ input}}\n\n {{ ctx.output_format }}\n \"#\n}\n\n", "test-files/functions/input/named-args/single/named-audio.baml": "function AudioInput(aud: audio) -> string{\n client Gemini\n prompt #\"\n {{ _.role(\"user\") }}\n\n Does this sound like a roar? Yes or no? One word no other characters.\n \n {{ aud }}\n \"#\n}\n\n\ntest TestURLAudioInput{\n functions [AudioInput]\n args {\n aud{ \n url https://actions.google.com/sounds/v1/emergency/beeper_emergency_call.ogg\n }\n } \n}\n\n\n", "test-files/functions/input/named-args/single/named-boolean.baml": "\n\nfunction TestFnNamedArgsSingleBool(myBool: bool) -> string{\n client GPT35\n prompt #\"\n Return this value back to me: {{myBool}}\n \"#\n}\n\ntest TestFnNamedArgsSingleBool {\n functions [TestFnNamedArgsSingleBool]\n args {\n myBool true\n }\n}", "test-files/functions/input/named-args/single/named-class-list.baml": "\n\n\nfunction TestFnNamedArgsSingleStringList(myArg: string[]) -> string{\n client GPT35\n prompt #\"\n Return this value back to me: {{myArg}}\n \"#\n}\n\ntest TestFnNamedArgsSingleStringList {\n functions [TestFnNamedArgsSingleStringList]\n args {\n myArg [\"hello\", \"world\"]\n }\n}", @@ -36,7 +36,7 @@ const fileMap = { "test-files/functions/input/named-args/single/named-enum-list.baml": "enum NamedArgsSingleEnumList {\n ONE\n TWO\n}\n\nfunction TestFnNamedArgsSingleEnumList(myArg: NamedArgsSingleEnumList[]) -> string {\n client GPT35\n prompt #\"\n Print these values back to me:\n {{myArg}}\n \"#\n}\n\ntest TestFnNamedArgsSingleEnumList {\n functions [TestFnNamedArgsSingleEnumList]\n args {\n myArg [ONE, TWO]\n }\n}", "test-files/functions/input/named-args/single/named-enum.baml": "enum NamedArgsSingleEnum {\n ONE\n TWO\n}\n\nfunction FnTestNamedArgsSingleEnum(myArg: NamedArgsSingleEnum) -> string {\n client GPT35\n prompt #\"\n Print these values back to me:\n {{myArg}}\n \"#\n}\n\ntest FnTestNamedArgsSingleEnum {\n functions [FnTestNamedArgsSingleEnum]\n args {\n myArg ONE\n }\n}", "test-files/functions/input/named-args/single/named-float.baml": "function TestFnNamedArgsSingleFloat(myFloat: float) -> string {\n client GPT35\n prompt #\"\n Return this value back to me: {{myFloat}}\n \"#\n}\n\ntest TestFnNamedArgsSingleFloat {\n functions [TestFnNamedArgsSingleFloat]\n args {\n myFloat 3.14\n }\n}\n", - "test-files/functions/input/named-args/single/named-image.baml": "function TestImageInput(img: image) -> string{\n client Claude\n prompt #\"\n {{ _.role(\"user\") }}\n\n Describe this in 4 words {{img}}\n \"#\n}\n\ntest TestImageInput {\n functions [TestImageInput]\n args {\n img {\n url \"https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png\"\n }\n }\n}\n\ntest shrek {\n functions [TestImageInput]\n args {\n img {\n url \"https://upload.wikimedia.org/wikipedia/en/4/4d/Shrek_%28character%29.png\"\n }\n }\n}\n\n\n\n// double check this before adding it. Probably n ot right.\n// function TestImageInputAnthropic(img: image) -> string{\n// client GPT4o\n// prompt #\"\n// {{ _.role(\"user\") }}\n\n// Describe this in 4 words {{img}}\n// \"#\n// }\n\n// test TestImageInputAnthropic {\n// functions [TestImageInputAnthropic]\n// args {\n// img {\n// base64 iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=\n// media_type \"image/png\"\n// }\n// }\n// }", + "test-files/functions/input/named-args/single/named-image.baml": "function TestImageInput(img: image) -> string{\n client Claude\n prompt #\"\n {{ _.role(\"user\") }}\n\n Describe this in 4 words. One word must be the color {{img}}\n \"#\n}\n\ntest TestImageInput {\n functions [TestImageInput]\n args {\n img {\n url \"https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png\"\n }\n }\n}\n\ntest shrek {\n functions [TestImageInput]\n args {\n img {\n url \"https://upload.wikimedia.org/wikipedia/en/4/4d/Shrek_%28character%29.png\"\n }\n }\n}\n\n\n\n// double check this before adding it. Probably n ot right.\n// function TestImageInputAnthropic(img: image) -> string{\n// client GPT4o\n// prompt #\"\n// {{ _.role(\"user\") }}\n\n// Describe this in 4 words {{img}}\n// \"#\n// }\n\n// test TestImageInputAnthropic {\n// functions [TestImageInputAnthropic]\n// args {\n// img {\n// base64 iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=\n// media_type \"image/png\"\n// }\n// }\n// }", "test-files/functions/input/named-args/single/named-int.baml": "// test for int\nfunction TestFnNamedArgsSingleInt(myInt: int) -> string {\n client GPT35\n prompt #\"\n Return this value back to me: {{myInt}}\n \"#\n}\n\ntest TestFnNamedArgsSingleInt {\n functions [TestFnNamedArgsSingleInt]\n args {\n myInt 42\n }\n}\n", "test-files/functions/input/named-args/single/named-string-list.baml": "// string[]\nfunction TestFnNamedArgsSingleStringArray(myStringArray: string[]) -> string {\n client GPT35\n prompt #\"\n Return this value back to me: {{myStringArray}}\n \"#\n}\n\ntest TestFnNamedArgsSingleStringArray {\n functions [TestFnNamedArgsSingleStringArray]\n args {\n myStringArray [\"example1\", \"example2\", \"example3\"]\n }\n}\n", "test-files/functions/input/named-args/single/named-string-optional.baml": "\n\n // string[]\nfunction FnNamedArgsSingleStringOptional(myString: string?) -> string {\n client GPT35\n prompt #\"\n Return this value back to me: {{myString}}\n \"#\n}\n\ntest FnNamedArgsSingleStringOptional {\n functions [FnNamedArgsSingleStringOptional]\n args {\n myString \"example string\"\n }\n}\n\ntest FnNamedArgsSingleStringOptional2 {\n functions [FnNamedArgsSingleStringOptional]\n args {\n \n }\n}\n", diff --git a/integ-tests/typescript/baml_client/type_builder.ts b/integ-tests/typescript/baml_client/type_builder.ts index ff4473cf8..36ed1d713 100644 --- a/integ-tests/typescript/baml_client/type_builder.ts +++ b/integ-tests/typescript/baml_client/type_builder.ts @@ -21,6 +21,8 @@ import { TypeBuilder as _TypeBuilder, EnumBuilder, ClassBuilder } from '@boundar export default class TypeBuilder { private tb: _TypeBuilder; + DynInputOutput: ClassBuilder<'DynInputOutput', "testKey">; + DynamicClassOne: ClassBuilder<'DynamicClassOne'>; DynamicClassTwo: ClassBuilder<'DynamicClassTwo', "hi" | "some_class" | "status">; @@ -44,13 +46,17 @@ export default class TypeBuilder { constructor() { this.tb = new _TypeBuilder({ classes: new Set([ - "Blah","ClassOptionalOutput","ClassOptionalOutput2","ClassWithImage","DynamicClassOne","DynamicClassTwo","DynamicOutput","Education","Email","Event","FakeImage","InnerClass","InnerClass2","NamedArgsSingleClass","OptionalTest_Prop1","OptionalTest_ReturnType","OrderInfo","Person","RaysData","Resume","SearchParams","SomeClassNestedDynamic","TestClassAlias","TestClassNested","TestClassWithEnum","TestOutputClass","UnionTest_ReturnType","WithReasoning", + "Blah","ClassOptionalOutput","ClassOptionalOutput2","ClassWithImage","DynInputOutput","DynamicClassOne","DynamicClassTwo","DynamicOutput","Education","Email","Event","FakeImage","InnerClass","InnerClass2","NamedArgsSingleClass","OptionalTest_Prop1","OptionalTest_ReturnType","OrderInfo","Person","RaysData","Resume","SearchParams","SomeClassNestedDynamic","TestClassAlias","TestClassNested","TestClassWithEnum","TestOutputClass","UnionTest_ReturnType","WithReasoning", ]), enums: new Set([ "Category","Category2","Category3","Color","DataType","DynEnumOne","DynEnumTwo","EnumInClass","EnumOutput","Hobby","NamedArgsSingleEnum","NamedArgsSingleEnumList","OptionalTest_CategoryType","OrderStatus","Tag","TestEnum", ]) }); + this.DynInputOutput = this.tb.classBuilder("DynInputOutput", [ + "testKey", + ]); + this.DynamicClassOne = this.tb.classBuilder("DynamicClassOne", [ ]); diff --git a/integ-tests/typescript/baml_client/types.ts b/integ-tests/typescript/baml_client/types.ts index fa7f03d01..4f0675ab4 100644 --- a/integ-tests/typescript/baml_client/types.ts +++ b/integ-tests/typescript/baml_client/types.ts @@ -141,6 +141,12 @@ export interface ClassWithImage { } +export interface DynInputOutput { + testKey: string + + [key: string]: any; +} + export interface DynamicClassOne { [key: string]: any; diff --git a/integ-tests/typescript/tests/integ-tests.test.ts b/integ-tests/typescript/tests/integ-tests.test.ts index 3e17d644f..e511fb71a 100644 --- a/integ-tests/typescript/tests/integ-tests.test.ts +++ b/integ-tests/typescript/tests/integ-tests.test.ts @@ -237,7 +237,7 @@ describe('Integ tests', () => { })('hi', 10) }) - it('should work with dynamics', async () => { + it('should work with dynamic types', async () => { let tb = new TypeBuilder() tb.Person.addProperty('last_name', tb.string().optional()) tb.Person.addProperty('height', tb.float().optional()).description('Height in meters') @@ -255,6 +255,28 @@ describe('Integ tests', () => { console.log(res) }) + + it('should work with dynamic inputs class', async () => { + let tb = new TypeBuilder() + tb.DynInputOutput.addProperty('new-key', tb.string().optional()) + + const res = await b.DynamicInputOutput({ 'new-key': 'hi', testKey: "myTest" }, { tb }) + expect(res["new-key"]).toEqual('hi') + expect(res["testKey"]).toEqual('myTest') + }) + + it('should work with dynamic inputs list', async () => { + let tb = new TypeBuilder() + tb.DynInputOutput.addProperty('new-key', tb.string().optional()) + + const res = await b.DynamicListInputOutput([{ 'new-key': 'hi', testKey: "myTest" }], { tb }) + expect(res[0]["new-key"]).toEqual('hi') + expect(res[0]["testKey"]).toEqual('myTest') + }) + + // test with extra list, boolean in the input as well. + + it('should work with nested classes', async () => { let stream = b.stream.FnOutputClassNested('hi!') let msgs: RecursivePartialNull = [] diff --git a/typescript/vscode-ext/packages/vscode/src/plugins/language-server/index.ts b/typescript/vscode-ext/packages/vscode/src/plugins/language-server/index.ts index 2f10e59d6..7addda20d 100644 --- a/typescript/vscode-ext/packages/vscode/src/plugins/language-server/index.ts +++ b/typescript/vscode-ext/packages/vscode/src/plugins/language-server/index.ts @@ -231,7 +231,7 @@ const activateClient = ( // need to append line for the show to work for some reason. // dont delete this. client.outputChannel.appendLine('baml/showLanguageServerOutput') - client.outputChannel.show() + //client.outputChannel.show() }) client.onNotification('baml/message', (message: BAMLMessage) => { client.outputChannel.appendLine('baml/message' + JSON.stringify(message, null, 2))