Skip to contents

Status: Implementation Complete (Part 1 of 2) Branch: unify-interface Version: 0.0.2


Overview

artcurator now provides a unified interface for artwork analysis functions that abstracts over multiple AI providers (Google Gemini and OpenAI). Instead of calling provider-specific packages directly, use artcurator::art_about_ai() with a provider parameter to switch between backends.

Benefits

  • Provider agnostic: Write code once, switch providers with a parameter
  • Centralized prompts: All artwork analysis prompts managed in one location
  • Consistent API: Same function signatures across providers
  • Easy migration: Existing code continues to work during transition
  • Flexible configuration: Control provider via parameter, env var, or auto-detection

Unified Functions

All functions include a provider parameter for explicit provider selection:

1. art_about_ai(img_path, provider = NULL, ...)

Generate natural language artwork descriptions.

Returns: Character string with description

Example:

desc <- art_about_ai("artwork.png", provider = "gemini")

2. art_style_ai(img_path, provider = NULL, ...)

Extract 5-10 stylistic features as structured data.

Returns: data.table with columns tag, tag_norm, desc

Example:

styles <- art_style_ai("artwork.png", provider = "openai", temp = 0)

3. classify_styles_ai(tags, exist_cats = NULL, provider = NULL, ...)

Standardize free-form tags into consistent categories.

Returns: data.table with columns tag, category

Example:

tags <- c("Photorealistic", "Vibrant Colors")
classified <- classify_styles_ai(tags, provider = "gemini")

4. art_profile_ai(art_title, artist_name, drawing_hours, brush_strokes, img_path, provider = NULL, ...)

Generate concise artwork profile with category, style, methodology, color, details.

Returns: 1-row data.table

Example:

profile <- art_profile_ai(
    art_title = "Portrait",
    artist_name = "Artist Name",
    drawing_hours = 12,
    brush_strokes = 5000,
    img_path = "artwork.png",
    provider = "gemini"
)

5. art_profile_full_ai(story = NULL, artist_name, creation_time, art_title, img_path, provider = NULL, ...)

Generate comprehensive artwork profile with medium, description, inspiration, approach, impact.

Returns: 1-row data.table

Example:

profile <- art_profile_full_ai(
    story = "Background story...",
    artist_name = "Artist Name",
    creation_time = "10 hours",
    art_title = "Portrait",
    img_path = "artwork.png",
    provider = "openai"
)

Provider Selection

The provider parameter controls which AI backend to use:

art_about_ai("artwork.png", provider = "gemini")
art_about_ai("artwork.png", provider = "openai")

Method 2: Environment Variable

Sys.setenv(ARTCURATOR_PROVIDER = "openai")
art_about_ai("artwork.png")  # Uses OpenAI

Method 3: Auto-Detection

# No provider specified - auto-detects:
# 1. Prefers artgemini if installed
# 2. Falls back to artopenai if installed
# 3. Errors if neither is available
art_about_ai("artwork.png")

Provider-Specific Parameters

Use ... to pass provider-specific parameters:

Gemini-Specific

art_style_ai("artwork.png",
            provider = "gemini",
            ml = "gemini-3-pro-preview",  # Model selection
            temp = 0,                     # Temperature
            max_think = TRUE,             # Extended reasoning
            timeout = 60)                 # Request timeout

OpenAI-Specific

art_style_ai("artwork.png",
            provider = "openai",
            ml = "gpt-5.1",      # Model selection
            temp = 0,            # Temperature
            timeout = 60)        # Request timeout

Configuration

Environment Variables

Provider Selection: - ARTCURATOR_PROVIDER (optional) - Set to "gemini" or "openai" for default provider

Provider-Specific (passed through to underlying packages): - Gemini: ART_GEMINI_KEY, ART_GEMINI_MODEL, etc. - OpenAI: ART_OPENAI_KEY, ART_OPENAI_MODEL, etc.

See artgemini README and artopenai README for complete configuration.


Migration Path

Part 1: Unified Interface (Current - ✅ Complete)

Status: Implemented in artcurator v0.0.2+

  • ✅ Unified functions available in artcurator
  • ✅ Original functions remain in artgemini/artopenai
  • ✅ No breaking changes - both APIs work simultaneously
  • ✅ Prompts centralized in artcurator/inst/prompts/

Usage: Start migrating new code to use artcurator::art_*_ai():

# Old way (still works)
library(artgemini)
desc <- art_about_ai("artwork.png")

# New way (recommended)
library(artcurator)
desc <- art_about_ai("artwork.png", provider = "gemini")

Part 2: Deprecation (Future - ⏳ Planned)

Timeline: TBD based on adoption metrics

  • Add .Deprecated() warnings in artgemini/artopenai
  • Update dependent packages (modArtist, modGallery, etc.)
  • Remove artwork functions from artgemini/artopenai (major version bump)
  • artcurator becomes the sole source for artwork analysis

Technical Architecture

File Structure

artcurator/
├── R/
│   ├── artwork-ai.R              # Unified interface: art_about_ai, art_style_ai, classify_styles_ai
│   ├── artwork-plus-ai.R         # Unified interface: art_profile_ai, art_profile_full_ai
│   ├── internal-provider.R       # Provider routing: .resolve_provider, .dispatch_artwork_ai
│   ├── internal-prompts.R        # Prompt management: .render_prompt, read_prompt_file
│   └── internal-utils.R          # Shared utilities: b64EncodeImage, validators
├── inst/prompts/                 # Centralized prompt templates (10 files)
├── data-raw/schema-definitions.R # JSON schemas for validation
└── tests/testthat/
    ├── test-provider-routing.R   # Provider routing tests
    └── test-artwork-ai.R         # Integration tests

Dispatch Flow

User Call: artcurator::art_about_ai("img.png", provider="gemini", temp=0.7)
     ↓
.dispatch_artwork_ai("art_about_ai", "gemini", img_path="img.png", temp=0.7)
     ↓
.resolve_provider("gemini") → "gemini"
     ↓
do.call(getExportedValue("artgemini", "art_about_ai"),
        list(img_path="img.png", temp=0.7))
     ↓
artcurator::art_about_ai(img_path="img.png", provider="gemini", temp=0.7)
     ↓
Returns: Character string with description

Provider Resolution Order

  1. Explicit provider parameter (highest priority)
  2. ARTCURATOR_PROVIDER environment variable
  3. Auto-detection: artgemini if installed, else artopenai
  4. Error if no providers available

Testing

Test Coverage

  • Provider routing (test-provider-routing.R):
    • Explicit provider selection
    • Environment variable fallback
    • Auto-detection logic
    • Error handling for missing providers
  • Integration (test-artwork-ai.R):
    • Functions return correct types
    • Both providers work end-to-end
    • Provider-specific parameters pass through
    • Auto-detection functions correctly

Running Tests

# Run all tests
devtools::test()

# Run specific test file
devtools::test_file("tests/testthat/test-provider-routing.R")

# With coverage
covr::package_coverage()

Development Notes

Adding New Artwork Functions

To add a new unified artwork function:

  1. Ensure the function exists in both artgemini and artopenai with identical signatures
  2. Add the unified wrapper to appropriate R/ file in artcurator
  3. Use .dispatch_artwork_ai(fn_name, provider, ...) pattern
  4. Add roxygen documentation with @family tag
  5. Add tests to verify routing and both providers
  6. Run devtools::document() and devtools::check()

Prompt Management

Prompts are centralized in artcurator/inst/prompts/: - Each prompt file includes # PROMPT_VERSION: vX.Y header - Use .render_prompt(name, data) for templating with glue - Update prompts in artcurator (not source packages) - Provider packages will eventually reference artcurator prompts (Part 2)

Schema Management

JSON schemas defined in data-raw/schema-definitions.R: - Kept internal (not exported) - Used for validation only - Sourced from artgemini/artopenai common schemas - Generate R/sysdata.rda via usethis::use_data(..., internal=TRUE)


Troubleshooting

Provider Not Found Error

Error: No AI provider available. Install artgemini or artopenai.

Solution: Install at least one provider package:

pak::pkg_install("artalytics/artgemini")
# or
pak::pkg_install("artalytics/artopenai")

API Key Not Set

Error: ART_GEMINI_KEY Not Set
# or
Error: ART_OPENAI_KEY not set

Solution: Configure provider API keys:

Sys.setenv(ART_GEMINI_KEY = "your-key")
Sys.setenv(ART_OPENAI_KEY = "sk-your-key")

Provider Package Not Installed

Error: artgemini package required but not installed

Solution: Install the requested provider:

pak::pkg_install("artalytics/artgemini")

Future Enhancements

Part 2 Considerations

  • Deprecation warnings in source packages
  • Migration guide for dependent packages
  • Prompt version synchronization strategy
  • Performance benchmarking across providers
  • Provider-specific feature detection and warnings

Potential Extensions

  • Add health check: artcurator_health_check(provider)
  • Provider comparison utilities
  • Batch processing with provider switching
  • Cost tracking across providers
  • Response caching at curator level


Last Updated: 2025-12-23 Part 1 of 2: Unified Interface Implementation