mod anthropic;
mod azure_openai;
mod google;
mod ollama;
mod open_ai;
mod prompt;
pub use anthropic::AnthropicConverter;
pub use azure_openai::AzureOpenAiConverter;
pub use google::GoogleConverter;
pub use ollama::OllamaConverter;
pub use open_ai::OpenAiConverter;
pub use prompt::{inject_recipe, COOKLANG_CONVERTER_PROMPT};
use async_trait::async_trait;
use serde::Serialize;
use std::error::Error;
#[derive(Debug, Clone, Default, Serialize)]
pub struct TokenUsage {
pub input_tokens: Option<u32>,
pub output_tokens: Option<u32>,
}
#[derive(Debug, Clone, Default, Serialize)]
pub struct ConversionMetadata {
pub model_version: Option<String>,
pub tokens_used: TokenUsage,
pub latency_ms: u64,
}
#[derive(Debug, Clone)]
pub struct ConversionResult {
pub content: String,
pub metadata: ConversionMetadata,
}
#[async_trait]
pub trait Converter: Send + Sync {
fn name(&self) -> &str;
async fn convert(
&self,
ingredients_and_instructions: &str,
) -> Result<ConversionResult, Box<dyn Error + Send + Sync>>;
}
pub fn create_converter(
name: &str,
config: &crate::config::ProviderConfig,
) -> Option<Box<dyn Converter>> {
match name {
"open_ai" => OpenAiConverter::new(config)
.ok()
.map(|c| Box::new(c) as Box<dyn Converter>),
"anthropic" => AnthropicConverter::new(config)
.ok()
.map(|c| Box::new(c) as Box<dyn Converter>),
"azure_openai" => AzureOpenAiConverter::new(config)
.ok()
.map(|c| Box::new(c) as Box<dyn Converter>),
"google" => GoogleConverter::new(config)
.ok()
.map(|c| Box::new(c) as Box<dyn Converter>),
"ollama" => OllamaConverter::new(config)
.ok()
.map(|c| Box::new(c) as Box<dyn Converter>),
_ => None,
}
}