Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 0 additions & 41 deletions baml_language/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 0 additions & 12 deletions baml_language/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,6 @@ bex_cache = { path = "crates/bex_cache", default-features = false }
bex_project = { path = "crates/bex_project", default-features = false }
bex_engine = { path = "crates/bex_engine", default-features = false }
sys_glob = { path = "crates/sys_glob" }
sys_jinja = { path = "crates/sys_jinja" }
sys_jinja_types = { path = "crates/sys_jinja_types" }
sys_llm = { path = "crates/sys_llm", default-features = false }
sys_ops = { path = "crates/sys_ops", default-features = false }
sys_types = { path = "crates/sys_types" }
Expand Down Expand Up @@ -135,16 +133,6 @@ bex_resource_types = { path = "crates/bex_resource_types" }
darwin-kperf = "0.1.0"
darwin-kperf-events = "0.1.0"

# External dependency for sys_llm jinja module
minijinja = { git = "https://github.com/boundaryml/minijinja.git", branch = "value-cmp", default-features = false, features = [
"macros",
"builtins",
"debug",
"preserve_order",
"serde",
"unstable_machinery",
] }
minijinja-contrib = { git = "https://github.com/boundaryml/minijinja.git", branch = "value-cmp", features = [ "pycompat" ] }
baml_workspace = { path = "crates/baml_workspace" }

# External dependencies
Expand Down
3,533 changes: 1,809 additions & 1,724 deletions baml_language/architecture/architecture.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 4 additions & 11 deletions baml_language/crates/baml_base/src/dedent.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
//! Template-string dedenting.
//! Backtick-string dedenting.
//!
//! Shared with `sys_llm::jinja::render::preprocess_template`; both implement the
//! same algorithm and should remain in lockstep until that callsite migrates to
//! this one.
//!
//! Algorithm (BEP-049 §12, Kotlin `trimIndent` rule):
//! Algorithm (BEP-049 section 12, Kotlin `trimIndent` rule):
//! 1. Compute the longest common leading-whitespace *prefix* across all non-blank
//! lines, compared character-by-character. Tabs and spaces don't mix: a
//! tab-indented line and a space-indented line share no common prefix, so the
//! strip column drops to zero (§12 Rule 2).
//! strip column drops to zero (section 12, rule 2).
//! 2. Strip that common prefix from every line that has it; otherwise keep the
//! line as-is (its content is whitespace-only).
//! 3. Trim leading/trailing whitespace from the overall result.
//!
//! Used by BEP-049 backtick string literals (multi-line auto-dedent, §12). The
//! legacy Jinja prompt pipeline (`sys_llm::preprocess_template`) keeps the older
//! byte-count-min variant until that path is removed (M6) — they intentionally
//! diverge on mixed tab/space indentation, which only the new backtick form specs.
//! Used by BEP-049 backtick string literals for multi-line auto-dedent.
// Walk leading whitespace by *char* so we never split a multi-byte
// Unicode whitespace codepoint (NBSP U+00A0 = 2 bytes, LINE SEPARATOR
// U+2028 = 3 bytes, etc.). A naive `line.len() - line.trim_start().len()`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,13 +320,6 @@ testset:

Every leaf gets a canonical ID beginning with `root` (or `root.<namespace>`) and using `::` for testset nesting. For example, the first test above is `root::math suite::adds`. Run `baml test --list` to discover IDs and `baml test --help` for selectors and profiles.

template_string:
summary: "Defines a reusable prompt template with Jinja2 syntax."
syntax: |
template_string Greeting(name: string) #"
Hello, {{ name }}! How can I help you?
"#

retry_policy:
summary: "Configures automatic retry behavior for LLM calls."
syntax: |
Expand Down
10 changes: 0 additions & 10 deletions baml_language/crates/baml_compiler2_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1623,7 +1623,6 @@ pub enum BuiltinKind {
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LlmBodyDef {
pub client: Option<Name>,
pub prompt: Option<RawPrompt>,
/// Pre-lowered companion bodies keyed by target name. The single-path
/// world stashes exactly one: `"spec"` — the `<Fn>$spec` body, built in
/// `lower_cst` while the CST backtick is still in hand (the AST must stay
Expand All @@ -1645,15 +1644,6 @@ pub struct LlmBodyDef {
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RawPrompt {
pub text: std::string::String,
/// Interpolation locations within the template.
pub interpolations: Vec<Interpolation>,
pub span: TextRange,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Interpolation {
pub content: std::string::String,
/// Span of the full interpolation, including delimiters.
pub span: TextRange,
}

Expand Down
17 changes: 17 additions & 0 deletions baml_language/crates/baml_compiler2_ast/src/companions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,22 @@ fn own_params(parent: &FunctionDef) -> Vec<Param> {
.collect()
}

fn generic_type_args(parent: &FunctionDef) -> Vec<crate::ast::TypeExpr> {
parent
.generic_params
.iter()
.map(|param| {
TypeExprKind::Path {
segments: vec![param.name.clone()],
generic_args: vec![],
associated_type_bindings: vec![],
attrs: vec![],
}
.at(parent.span)
})
.collect()
}

fn companion_def(
parent: &FunctionDef,
name: Name,
Expand Down Expand Up @@ -126,6 +142,7 @@ fn llm_render_prompt(parent: &FunctionDef) -> Option<FunctionDef> {
let body = lower_expr_body::synthesize_spec_render_prompt_body(
parent.name.as_str(),
&param_names,
generic_type_args(parent),
Some(out),
parent.span,
);
Expand Down
71 changes: 22 additions & 49 deletions baml_language/crates/baml_compiler2_ast/src/lower_cst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ use crate::{
ast::{
AssociatedTypeBindingDef, AssociatedTypeDef, BuiltinKind, CallArg, EnumDef, Expr, ExprId,
FieldDef, FunctionBodyDef, FunctionDef, FunctionDefaults, ImplementsBlockDef,
ImplementsForDef, InterfaceDef, InterfaceFieldLinkDef, Interpolation, Item, LambdaDef,
LambdaKind, LlmBodyDef, MethodSigDef, Param, RawAttribute, RawAttributeArg, RawPrompt,
ImplementsForDef, InterfaceDef, InterfaceFieldLinkDef, Item, LambdaDef, LambdaKind,
LlmBodyDef, MethodSigDef, Param, RawAttribute, RawAttributeArg, RawPrompt,
TemplateStringDef, TestArgValue, TestDef, TypeAliasDef, TypeExpr, TypeExprKind, VariantDef,
},
companions::expand_companions,
Expand Down Expand Up @@ -156,6 +156,9 @@ pub fn lower_file_with_path_and_test_owner(
diags.push(lower_generator_deprecation(&child));
}
baml_compiler_syntax::SyntaxKind::TEMPLATE_STRING_DEF => {
diags.push(LoweringDiagnostic::TemplateStringRemoved {
span: child.span_range(),
});
if let Some(ts) = lower_template_string(&child, &mut diags) {
items.push(Item::TemplateString(ts));
}
Expand Down Expand Up @@ -343,10 +346,9 @@ fn lower_function(

// Jinja prompts are removed: the single-path world renders prompts as
// plain backtick templates through the spec.
if llm.prompt_field().and_then(|pf| pf.raw_string()).is_some() {
if let Some(raw_prompt) = llm.prompt_field().and_then(|pf| pf.raw_string()) {
diags.push(LoweringDiagnostic::LlmJinjaPromptRemoved {
function_name: name.as_str().to_string(),
span: llm_body_def.span,
span: raw_prompt.syntax().span_range(),
});
}

Expand Down Expand Up @@ -397,9 +399,22 @@ fn lower_function(
.iter()
.any(|(t, _)| t == "spec")
{
let spec_type_args = generic_params
.iter()
.map(|param| {
crate::ast::TypeExprKind::Path {
segments: vec![param.name.clone()],
generic_args: vec![],
associated_type_bindings: vec![],
attrs: vec![],
}
.at(llm_body_def.span)
})
.collect();
let (expr_body, source_map) = lower_expr_body::synthesize_spec_agent_run_body(
name.as_str(),
&param_names,
spec_type_args,
return_type.clone(),
llm_body_def.span,
);
Expand Down Expand Up @@ -693,14 +708,8 @@ fn lower_llm_body(llm_body: &ast::LlmFunctionBody) -> LlmBodyDef {
.and_then(|cf| cf.value())
.map(|name| Name::new(&name));

let prompt = llm_body
.prompt_field()
.and_then(|pf| pf.raw_string())
.map(|raw_str| lower_raw_prompt(&raw_str));

LlmBodyDef {
client,
prompt,
// Filled in by the LLM-function branch once param names are known.
companion_bodies: Vec::new(),
has_tools: llm_tools_present(llm_body),
Expand Down Expand Up @@ -828,46 +837,10 @@ fn tools_value_element(
}

fn lower_raw_prompt(raw_string: &ast::RawStringLiteral) -> RawPrompt {
use baml_compiler_syntax::{
SyntaxKind,
ast::{JinjaExpression, JinjaStatement, PromptText},
};

let mut text = String::new();
let mut interpolations = Vec::new();
let prompt_span = raw_string.syntax().span_range();

for child in raw_string.syntax().children() {
match child.kind() {
SyntaxKind::PROMPT_TEXT => {
if let Some(prompt_text) = PromptText::cast(child.clone()) {
text.push_str(&prompt_text.text());
}
}
SyntaxKind::TEMPLATE_INTERPOLATION => {
if let Some(jinja_expr) = JinjaExpression::cast(child.clone()) {
let inner = jinja_expr.inner_text();
let full = jinja_expr.full_text();
let span = child.span_range();
interpolations.push(Interpolation {
content: inner,
span,
});
text.push_str(&full);
}
}
SyntaxKind::TEMPLATE_CONTROL => {
if let Some(jinja_stmt) = JinjaStatement::cast(child.clone()) {
text.push_str(&jinja_stmt.full_text());
}
}
_ => {}
}
}

RawPrompt {
text,
interpolations,
text: crate::parse_string_attr_value(&raw_string.syntax().text().to_string())
.unwrap_or_default(),
span: prompt_span,
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,7 @@ pub(crate) fn synthesize_llm_spec_body(
pub(crate) fn synthesize_spec_render_prompt_body(
function_name: &str,
param_names: &[Name],
spec_type_args: Vec<crate::ast::TypeExpr>,
out_type: Option<crate::ast::TypeExpr>,
span: TextRange,
) -> (ExprBody, AstSourceMap) {
Expand All @@ -636,7 +637,7 @@ pub(crate) fn synthesize_spec_render_prompt_body(
let spec_call = ctx.alloc_expr(
Expr::Call {
callee: spec_callee,
type_args: vec![],
type_args: spec_type_args,
args: spec_args,
},
span,
Expand Down Expand Up @@ -733,6 +734,7 @@ pub(crate) fn synthesize_spec_parse_body(
pub(crate) fn synthesize_spec_agent_run_body(
function_name: &str,
param_names: &[Name],
spec_type_args: Vec<crate::ast::TypeExpr>,
out_type: Option<crate::ast::TypeExpr>,
span: TextRange,
) -> (ExprBody, AstSourceMap) {
Expand All @@ -755,7 +757,7 @@ pub(crate) fn synthesize_spec_agent_run_body(
let spec_call = ctx.alloc_expr(
Expr::Call {
callee: spec_callee,
type_args: vec![],
type_args: spec_type_args,
args: spec_args,
},
span,
Expand Down Expand Up @@ -825,6 +827,7 @@ pub(crate) fn synthesize_spec_agent_run_body(
pub fn synthesize_spec_stream_body(
function_name: &str,
param_names: &[Name],
spec_type_args: Vec<crate::ast::TypeExpr>,
type_args: Vec<crate::ast::TypeExpr>,
span: TextRange,
) -> (ExprBody, AstSourceMap) {
Expand All @@ -847,7 +850,7 @@ pub fn synthesize_spec_stream_body(
let spec_call = ctx.alloc_expr(
Expr::Call {
callee: spec_callee,
type_args: vec![],
type_args: spec_type_args,
args: spec_args,
},
span,
Expand Down
Loading
Loading