google-ai-schema-derive

Crates.iogoogle-ai-schema-derive
lib.rsgoogle-ai-schema-derive
version0.1.2
created_at2025-05-07 20:16:18.127125+00
updated_at2025-08-11 11:30:21.553097+00
descriptionType-safe schema generation for Google AI API interactions
homepage
repositoryhttps://github.com/veecore/google-ai-rs
max_upload_size
id1664425
size121,152
Victor (veecore)

documentation

https://docs.rs/google-ai-schema-derive

README

crates.io Documentation CI Status

🧬 google-ai-schema-derive: Type-Safe Gemini Schemas in Rust

Generate bulletproof JSON schemas for Google AI with derive macros -
Because guessing games don't belong in production AI systems!

[dependencies]
google-ai-schema-derive = "0.1.2"

⚡️ 10-Second Schema Generation

#[derive(AsSchema, Deserialize)]
#[schema(description = "Social media post analysis")]
struct PostAnalysis {
    #[schema(description = "Sentiment score (-1 to 1)")]
    sentiment: f32,
    
    #[schema(rename = "topics", description = "Detected topics")]
    hashtags: Vec<String>,
}

// Automatically generates Gemini-compatible schema:
/*
{
  "type": "object",
  "description": "Social media post analysis",
  "properties": {
    "sentiment": {
      "type": "number",
      "format": "float",
      "description": "Sentiment score (-1 to 1)"
    },
    "topics": {
      "type": "array",
      "items": {"type": "string"},
      "description": "Detected topics"
    }
  },
  "required": ["sentiment", "topics"]
}
*/

🚀 Why Developers Love This

1. Type Safety Meets AI Magic

#[derive(AsSchema, Deserialize)]
struct FinancialReport {
    #[schema(description = "Year-over-year growth %")]
    yoy_growth: f64,
    
    #[schema(
        description = "Key performance indicators",
        min_items = 3,
        max_items = 5
    )]
    kpis: Vec<String>,
}

// Compile-time validation

2. Serde Superpowers

#[derive(AsSchema, Serialize)]
#[schema(rename_all = "camelCase")]
struct UserProfile {
    #[serde(rename = "fullName")] // Mirrored in schema!
    name: String,
    
    #[schema(skip)] // Hidden from schema, kept in Serde
    internal_id: Uuid,
}

3. Real-World AI Schemas Made Easy

News Article Analysis:

#[derive(AsSchema, Deserialize)]
#[schema(description = "News article metadata extraction")]
struct ArticleMeta {
    #[schema(description = "ISO language code")]
    language: String,
    
    #[schema(
        description = "People/organizations mentioned",
        min_items = 1
    )]
    entities: Vec<String>,
    
    #[schema(as_schema = "date_schema")]
    publish_date: i64,
}

fn date_schema() -> Schema {
    Schema {
        r#type: SchemaType::String as i32,
        ..Default::default()
    }
}

🛠️ Schema Crafting Toolkit

Core Attributes Cheat Sheet

Struct-Level Magic:

#[schema(
    description = "E-commerce product listing",
    rename_all = "snake_case",
    nullable   // Whole struct can be null
)]
struct Product {
    // ...
}

Field-Level Control:

#[schema(
    description = "Price in USD cents",
    r#type = "Integer",
    format = "int64",
    required  // Force include in required[]
)]
price: u64,

#[schema(
    as_schema = "custom_image_schema",  // Full override
    skip      // Exclude from schema
)]
hero_image: Vec<u8>

Enum Strategies

Simple Variants → String Enum:

#[derive(AsSchema)]
enum ContentRating {
    Safe,
    Mature,
    Explicit
}

// Generates: {"type": "string", "enum": ["Safe", "Mature", "Explicit"]}

Complex Variants → Tagged Union:

#[derive(AsSchema)]
enum APIResponse {
    Success { data: String },
    Error { code: u16, message: String }
}

/*
{
  "type": "object",
  "properties": {
    "Success": { /* data schema */ },
    "Error": { /* error schema */ }
  }
}
*/

🚨 Compliance First

Enforced Best Practices

#[derive(AsSchema)]
struct MedicalReport {
    diagnosis: String,
    
    #[schema(r#type = "string", format = "float")] // COMPILE ERROR: Type mismatch
    probability: f32
}

Gemini-Specific Rules

  • Type-format compatibility checked
  • No recursive types

📦 Perfect Pairing

Works seamlessly with google-ai-rs main crate:

use google_ai_rs::{AsSchema, TypedModel};

#[derive(AsSchema, Deserialize)]
struct LegalClause {
    #[schema(description = "Clause text in Markdown")]
    text: String,
    #[schema(description = "Applicable jurisdictions")]
    regions: Vec<String>,
}

let model = TypedModel::<LegalClause>::new(&client, "gemini-pro");
let clause = model.generate_content("Generate GDPR data processing clause").await?;
Commit count: 34

cargo fmt