Skip to main content

rosetta_aisp_llm/
lib.rs

1//! Rosetta AISP LLM Fallback
2//!
3//! Provides LLM-powered fallback for AISP conversion when deterministic
4//! Rosetta mappings have low confidence. Uses Claude SDK for intelligent
5//! prose-to-symbol translation.
6//!
7//! # Example
8//!
9//! ```no_run
10//! use rosetta_aisp_llm::{convert_with_fallback, ConversionOptionsExt};
11//!
12//! # async fn example() {
13//! let prose = "Define a type User with valid credentials";
14//! let result = convert_with_fallback(prose, None).await;
15//! println!("Output: {}", result.output);
16//! println!("Used LLM: {}", result.used_fallback);
17//! # }
18//! ```
19
20mod claude;
21mod provider;
22
23pub use claude::ClaudeFallback;
24pub use provider::{LlmProvider, LlmResult};
25
26// Re-export rosetta-aisp types for convenience
27pub use rosetta_aisp::{
28    AispConverter, ConversionOptions, ConversionResult, ConversionTier, RosettaStone, TokenStats,
29};
30
31/// Extended conversion options with LLM fallback support
32#[derive(Debug, Clone, Default)]
33pub struct ConversionOptionsExt {
34    /// Force specific tier (auto-detect if None)
35    pub tier: Option<ConversionTier>,
36    /// Confidence threshold for LLM fallback (default: 0.8)
37    pub confidence_threshold: Option<f64>,
38    /// Enable LLM fallback
39    pub enable_llm_fallback: bool,
40    /// LLM model to use (default: sonnet)
41    pub llm_model: Option<String>,
42}
43
44/// Convert prose to AISP with optional LLM fallback
45///
46/// This function first attempts deterministic conversion using rosetta-aisp.
47/// If the confidence is below the threshold and LLM fallback is enabled,
48/// it uses Claude to improve the conversion.
49///
50/// # Arguments
51///
52/// * `prose` - The natural language text to convert
53/// * `options` - Optional configuration for conversion behavior
54///
55/// # Returns
56///
57/// A `ConversionResult` containing the AISP output and metadata
58pub async fn convert_with_fallback(
59    prose: &str,
60    options: Option<ConversionOptionsExt>,
61) -> ConversionResult {
62    let opts = options.unwrap_or_default();
63
64    // Convert using rosetta-aisp's ConversionOptions
65    let base_options = ConversionOptions {
66        tier: opts.tier,
67        confidence_threshold: opts.confidence_threshold,
68    };
69
70    let result = AispConverter::convert(prose, Some(base_options));
71    let threshold = opts.confidence_threshold.unwrap_or(0.8);
72
73    // Check if LLM fallback is needed
74    if opts.enable_llm_fallback && result.confidence < threshold {
75        let provider = if let Some(model) = &opts.llm_model {
76            ClaudeFallback::with_model(model)
77        } else {
78            ClaudeFallback::new()
79        };
80
81        if provider.is_available().await {
82            if let Ok(llm_result) = provider
83                .convert(prose, result.tier, &result.unmapped, Some(&result.output))
84                .await
85            {
86                return llm_result.to_conversion_result(result.tier, prose.len());
87            }
88        }
89    }
90
91    result
92}