You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
3.7 KiB
121 lines
3.7 KiB
use ai_core::ai::Params;
|
|
use gloo_net::http::Request;
|
|
use leptos::{
|
|
html::{Input, Option_, Select, Textarea},
|
|
*,
|
|
};
|
|
use serde_json::{json, Value};
|
|
|
|
#[component]
|
|
pub fn GenerationUI(cx: Scope) -> impl IntoView {
|
|
let input: NodeRef<Textarea> = create_node_ref(cx);
|
|
let output: NodeRef<Textarea> = create_node_ref(cx);
|
|
|
|
let ai_selector: NodeRef<Select> = create_node_ref(cx);
|
|
let temp: NodeRef<Input> = create_node_ref(cx);
|
|
let max_tokens: NodeRef<Input> = create_node_ref(cx);
|
|
|
|
let generate_action = create_action(cx, move |_: &()| async move {
|
|
// these unwraps should never fail as the elements will always exist at this point
|
|
let prompt = input.get().unwrap().value();
|
|
let output = output.get().unwrap();
|
|
|
|
let temperature = temp.get().unwrap().value_as_number();
|
|
let max_tokens = max_tokens.get().unwrap().value_as_number();
|
|
|
|
let ai_selector = ai_selector.get().unwrap().value();
|
|
|
|
output.set_value("Generating...");
|
|
|
|
let res = Request::post("/api/generate")
|
|
.json(&json!({
|
|
"ai": ai_selector,
|
|
"params": Params {
|
|
prompt,
|
|
max_tokens: max_tokens as _,
|
|
temperature: temperature as _
|
|
}
|
|
}))
|
|
.unwrap()
|
|
.send()
|
|
.await;
|
|
|
|
match res {
|
|
Ok(res) => {
|
|
if res.status() != 200 {
|
|
output.set_value("Failed to generate!");
|
|
tracing::error!("Status code not 200");
|
|
|
|
return;
|
|
}
|
|
|
|
let res = res.text().await.unwrap(); // should be safe to unwrap here?
|
|
|
|
output.set_value(&res);
|
|
}
|
|
Err(err) => {
|
|
output.set_value("Failed to generate!");
|
|
tracing::error!("{}", err);
|
|
}
|
|
}
|
|
});
|
|
|
|
_ = create_resource(cx, || (), move |_| async move {
|
|
let res = Request::get("/api/ais").send().await;
|
|
|
|
match res {
|
|
Ok(res) => {
|
|
if res.status() != 200 {
|
|
tracing::error!("Status code not 200 for AI selector fetch");
|
|
|
|
return;
|
|
}
|
|
|
|
// these should never fail in theory
|
|
let res: Value = res.json().await.unwrap();
|
|
let res = res.as_array().unwrap().to_vec();
|
|
|
|
for ai in res {
|
|
let ai = ai.as_str().unwrap(); // should never fail
|
|
let option = &Option_::default();
|
|
|
|
option.set_value(ai);
|
|
option.set_label(ai);
|
|
|
|
ai_selector.get().unwrap().append_child(&option).unwrap();
|
|
}
|
|
}
|
|
Err(err) => {
|
|
tracing::error!("Failed to get AIs for selector! {}", err);
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
view! { cx,
|
|
<main>
|
|
<div class="bar">
|
|
<button on:click=move |_| {
|
|
generate_action.dispatch(());
|
|
}>
|
|
"Generate"
|
|
</button>
|
|
|
|
<h5>"AI"</h5>
|
|
<select node_ref=ai_selector />
|
|
|
|
<h5>"Temperature"</h5>
|
|
<input type="number" min="0" max="2" step="0.1" value="1" node_ref=temp />
|
|
|
|
<h5>"Max Tokens"</h5>
|
|
<input type="number" min="0" max="2000" step="10" value="1000" node_ref=max_tokens />
|
|
</div>
|
|
|
|
<div class="io">
|
|
<textarea node_ref=input />
|
|
<textarea readonly="true" node_ref=output />
|
|
</div>
|
|
</main>
|
|
}
|
|
}
|