use whatlang::detect;
pub const COOKLANG_CONVERTER_PROMPT: &str = include_str!("prompt.txt");
fn detect_language(text: &str) -> String {
detect(text)
.map(|info| info.lang().eng_name().to_string())
.unwrap_or_else(|| "the original language".to_string())
}
pub fn inject_recipe(recipe_content: &str) -> String {
let language = detect_language(recipe_content);
COOKLANG_CONVERTER_PROMPT
.replace("{{RECIPE}}", recipe_content)
.replace("{{LANGUAGE}}", &language)
}
pub const FINETUNED_CONVERTER_PREFIX: &str = "Convert recipe to Cooklang:\n\n";
pub fn prompt_for_model(model: &str, recipe_content: &str) -> String {
if model.starts_with("ft:") {
format!("{}{}", FINETUNED_CONVERTER_PREFIX, recipe_content)
} else {
inject_recipe(recipe_content)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_prompt_is_embedded() {
assert!(!COOKLANG_CONVERTER_PROMPT.is_empty());
assert!(COOKLANG_CONVERTER_PROMPT.contains("Cooklang"));
assert!(COOKLANG_CONVERTER_PROMPT.contains("@ symbol"));
assert!(COOKLANG_CONVERTER_PROMPT.contains("# symbol"));
assert!(COOKLANG_CONVERTER_PROMPT.contains("timer"));
}
#[test]
fn test_prompt_for_model_finetuned_uses_short_prompt() {
let p = prompt_for_model(
"ft:gpt-4.1-mini-2025-04-14:personal::abc",
"2 eggs\n\nBoil.",
);
assert_eq!(p, "Convert recipe to Cooklang:\n\n2 eggs\n\nBoil.");
}
#[test]
fn test_prompt_for_model_base_uses_full_prompt() {
let p = prompt_for_model("gpt-4.1-mini", "2 eggs\n\nBoil.");
assert!(p.contains("Cooklang syntax rules"));
assert!(p.contains("2 eggs\n\nBoil."));
}
#[test]
fn test_prompt_contains_examples() {
assert!(COOKLANG_CONVERTER_PROMPT.contains("Example:"));
assert!(COOKLANG_CONVERTER_PROMPT.contains("@salt"));
assert!(COOKLANG_CONVERTER_PROMPT.contains("@potato{2}"));
assert!(COOKLANG_CONVERTER_PROMPT.contains("#pot"));
}
}