Skip to content

Commit

Permalink
Add ui elements for number, input, class
Browse files Browse the repository at this point in the history
  • Loading branch information
imalsogreg committed Dec 9, 2024
1 parent cd5dc4c commit 76cae4f
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 33 deletions.
112 changes: 79 additions & 33 deletions engine/baml-schema-wasm/src/runtime_wasm/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod generator;
pub mod runtime_prompt;
pub mod ui;
use crate::runtime_wasm::runtime_prompt::WasmPrompt;
use anyhow::Context;
use baml_runtime::internal::llm_client::orchestrator::OrchestrationScope;
Expand Down Expand Up @@ -480,6 +481,56 @@ impl WasmLLMResponse {
}
}

#[wasm_bindgen(getter_with_clone, inspectable)]
#[derive(Clone, Debug)]
pub struct WasmInputForm {
pub items: Vec<WasmInputItem>
}

#[wasm_bindgen(getter_with_clone, inspectable)]
#[derive(Clone, Debug)]
pub struct WasmInputParam {
pub name: String,
pub item: WasmInputItem
}

#[wasm_bindgen(getter_with_clone, inspectable)]
#[derive(Clone, Debug)]
pub struct WasmInputItem {
pub r#type: WasmInputItemType,
pub primitive: Option<WasmInputField>,
pub class: Option<WasmInputClass>,
}

#[wasm_bindgen(getter_with_clone, inspectable)]
#[derive(Clone, Debug)]
pub struct WasmInputPrimitive {
pub r#type: String,
pub default: Option<String>
}

#[wasm_bindgen(getter_with_clone, inspectable)]
#[derive(Clone, Debug)]
pub struct WasmInputClass {
pub class_name: String,
pub fields: Vec<WasmInputClassField>,
}

#[wasm_bindgen(getter_with_clone, inspectable)]
#[derive(Clone, Debug)]


#[wasm_bindgen(getter_with_clone, inspectable)]
#[derive(Clone, Debug)]
pub enum WasmInputItemType {
Primitive,
Class,
// Enum,
// List,
}



#[wasm_bindgen]
impl WasmFunctionResponse {
pub fn parsed_response(&self) -> Option<String> {
Expand Down Expand Up @@ -1597,39 +1648,7 @@ impl WasmFunction {
)
.create_ctx_with_default();

let params = rt
.runtime
.get_test_params(&self.name, &test_name, &ctx, false)
.map_err(|e| JsError::new(format!("{e:?}").as_str()))?;

let result = rt
.runtime
.internal()
.render_prompt(&self.name, &ctx, &params, wasm_call_context.node_index)
.await;

let final_prompt = match result {
Ok((prompt, _, _)) => match prompt {
RenderedPrompt::Chat(chat_messages) => chat_messages,
RenderedPrompt::Completion(_) => vec![], // or handle this case differently
},
Err(e) => return Err(wasm_bindgen::JsError::new(format!("{:?}", e).as_str())),
};

rt.runtime
.internal()
.render_raw_curl(
&self.name,
&ctx,
&final_prompt,
RenderCurlSettings {
stream,
as_shell_commands: !expand_images,
},
wasm_call_context.node_index,
)
.await
.map_err(|e| wasm_bindgen::JsError::new(format!("{e:?}").as_str()))
return Ok("Greg test".to_string());
}

#[wasm_bindgen]
Expand Down Expand Up @@ -1668,6 +1687,33 @@ impl WasmFunction {
})
}

#[wasm_bindgen]
pub async fn input_form(
&self,
rt: &mut WasmRuntime,
test_name: String,
get_baml_src_cb: js_sys::Function,
) -> Result<WasmInputForm, JsValue> {
let rt = &rt.runtime;
let ir = rt.internal().ir();
let function_name = self.name.clone();
let ctx_mgr = rt.create_ctx_manager(
BamlValue::String("wasm".to_string()),
js_fn_to_baml_src_reader(get_baml_src_cb),
);
let ctx = ctx_mgr.create_ctx(None, None).unwrap();
let param_types = &ir.find_function(&function_name)
.map_err(|e| JsValue::from_str(&format!("{:?}", e)))?
.item
.elem
.inputs
;
let test_params = rt.get_test_params(&function_name, &test_name, &ctx, false)
.map_err(|e| JsValue::from_str(&format!("{:?}", e)))?;
ui::form_from_input(ir, param_types, test_params)
.map_err(|e| JsValue::from_str(&format!("{:?}", e)))
}

pub fn orchestration_graph(&self, rt: &WasmRuntime) -> Result<Vec<WasmScope>, JsValue> {
let rt: &BamlRuntime = &rt.runtime;

Expand Down
77 changes: 77 additions & 0 deletions engine/baml-schema-wasm/src/runtime_wasm/ui.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use anyhow::Result;
use indexmap::IndexMap;
use itertools::join;

use baml_types::{BamlValueWithMeta, BamlValue, FieldType, TypeValue, Constraint};
use internal_baml_core::ir::repr::IntermediateRepr;
use internal_baml_core::ir::IRHelper;
use crate::runtime_wasm::{WasmInputForm, WasmInputField, WasmInputItem};

/// Derive an HTML form from
// TODO: Return UIInput, and let typescript handle the rendering
// into actual html.
pub fn form_from_input(ir: &IntermediateRepr, field_types: &Vec<(String, FieldType)>, arguments: IndexMap<String, BamlValue>) -> Result<WasmInputForm> {
let form_items = field_types.iter().map(|(arg_name, arg_type)| {
let argument = arguments.get(arg_name);
let item = form_item(ir, arg_name, arg_type, argument)?;
Ok( WasmInputFormArgument { arg_name, item })
}).collect::<Result<Vec<_>>>()?;
Ok(WasmInputForm {
items: form_items
})
}


// fn form_arg(
// ir: &IntermediateRepr,
// arg_name: &str,
// arg_type: &FieldType,
// argument: Option<&BamlValue>
// ) -> Result<WasmInputItem> {
//
// }

/// The html of a single argument.
/// `arg_name` is only present for top-level arguments. For arguments
/// that are fields of a class, the "arg_name" should be the class name.
fn form_item(
ir: &IntermediateRepr,
field_name: Option<&str>,
field_type: &FieldType,
argument: Option<&BamlValue>
) -> Result<WasmInputItem> {

let (r#type, constraints) = ir.distribute_constraints(arg_type);
let arg_str = argument.map(|baml_value| baml_value.to_string());
match r#type {
FieldType::Primitive(TypeValue::Int) => Ok(input_el(arg_name, "number", arg_str)),
FieldType::Primitive(TypeValue::String) => Ok(input_el(arg_name, "text", arg_str)),
FieldType::Primitive(TypeValue::Bool) => Ok(input_el(arg_name, "checkbox", arg_str)),
FieldType::Class(class_name) => {
let class_field_items = ir.find_class(name)?.walk_fields().map(|field| {
let field_arg = match argument {
Some(BamlValue::Class(_name, fields)) => fields.get(arg_name),
_ => None,
};
form_item(ir, field.name(), field.r#type(), field_arg)
}).collect::<Result<Vec<_>>>()?;
Ok(WasmInputItem {
r#type: WasmInputItemType::Class,
name: name.to_string(),
fields: class_field_items,
})
},
_ => todo!(),
}
}

fn input_el(name: &str, r#type: &str, default: Option<String>) -> WasmInputItem {
WasmInputItem {
name: name.to_string(),
field: Some( WasmInputField {
r#type: r#type.to_string(),
default: default,
}),
subform: Vec::new()
}
}

0 comments on commit 76cae4f

Please sign in to comment.