Skip to contents

artopenai 0.12.1

Patch — R CMD check hygiene

  • tests/testthat/fixtures/ is now shipped with the package tarball (removed from .Rbuildignore). The 0.11-era exclusion broke R CMD check offline: under devtools::check() the tarball was extracted without fixtures, httptest2 fell back to capture mode, and every mocked test attempted a real API call.
  • is_artwork() tests reinstated as capture/replay (with_mock_dir) for consistency with the rest of the suite. Fixtures live under tests/testthat/fixtures/is-artwork/ and is-artwork-portrait/.
  • Vignette (vignettes/artopenai.qmd) now falls back to a placeholder ART_OPENAI_KEY when the env var isn’t set. The key is never used — httptest2 replays from vignettes/artopenai/ fixtures — but .get_openai_cfg() requires a non-empty key to build the request.
  • Shortened fixtures/openai-chat/conversation/.../multi/ to keep final fixture paths under the 100-byte portable-name threshold.

With these, devtools::check() passes clean: 0 errors, 0 warnings, 0 notes.


artopenai 0.12.0

New Feature — is_artwork() Image Classifier

  • is_artwork(img_path) — exported predicate that asks OpenAI whether an image depicts artwork (digital artwork or professional flat digitization). Returns a list with is_artwork (boolean), confidence (0–1), reason, model, and usage.

    res <- is_artwork("path/to/thumbnail.jpg")
    if (res$is_artwork && res$confidence > 0.8) { ... }
  • Thumbnail-input contract. The function enforces file.info(img_path)$size <= max_bytes (default 2 MB) and errors with an actionable message otherwise. Callers are expected to pre-resize during ingestion; the function performs no magick work.

  • Hardcoded efficiency choices:

    • Model: gpt-5.4-nano (smallest vision-capable GPT-5 tier).
    • reasoning = list(effort = "none") — no chain-of-thought tokens.
    • detail = "low" on the image — 85-token tile regardless of resolution.
    • Raw-byte read + magic-byte mime detection (PNG / JPEG / WebP / GIF).
    • Strict JSON schema output.

    End-to-end latency on a 512x512 thumbnail: ~1.1 s median (inference-bound).

API Additions

Reliability

  • artopenai_health_check() now reads its URL from .get_openai_cfg(), so ART_OPENAI_BASE_URL is honored (previously hardcoded).

  • Retry logic replaced with httr2::req_retry(max_tries = 3); the hand-rolled regex-based retry helper is gone. Transient 429s and 5xx are now retried with proper Retry-After header support.

Dependencies

  • Dropped data.table from Imports (unused after artwork-analysis functions moved to artcurator in 0.10.0).
  • Bumped ellmer minimum to >= 0.4.0 — required by credentials = in openai_chat().

Internal

  • Removed stray magick::magick_set_seed(42) at package load (magick was never in Imports; the call was a non-functional artifact of a prior httptest2 fixture-stability workaround).
  • Removed dead data.table NSE @importFrom block and globalVariables() list left over from removed 0.10.0 functions.
  • Renamed internal ..api_openai_key() to .api_openai_key() to match R convention.
  • inst/httptest2/redact.R retabbed to 2-space indentation.

artopenai 0.11.0

New Feature - Interactive Chat with Streaming

  • New openai_chat() function - Creates reusable chat objects for interactive, multi-turn conversations with streaming support. Built on {ellmer} for robust provider integration.

    # Create chat object
    chat <- openai_chat(sys_prompt = "You are an art expert.")
    
    # Multi-turn conversation
    chat$chat("What is Baroque art?")
    chat$chat("How does it differ from Renaissance?")
    
    # Streaming for real-time UI
    stream <- chat$stream("Tell me about Impressionism.")
    coro::loop(for (chunk in stream) cat(chunk))
    
    # Structured output
    schema <- ellmer::type_object(
      style = ellmer::type_string("Art style"),
      period = ellmer::type_string("Time period")
    )
    chat$chat_structured("Describe Cubism", type = schema)
  • ellmer Chat object methods:

    • $chat(...) - Send message(s), receive text response
    • $stream(...) - Stream response chunks for real-time display
    • $chat_structured(prompt, type) - Extract structured data with type validation
    • $register_tool(tool) - Add tools for function calling
  • Image and file input via ellmer content helpers:

    chat$chat(ellmer::content_image_file("artwork.png"), "Describe this.")
    chat$chat(ellmer::content_image_url("https://..."), "What style?")

Use Case Guidance

Use Case Function Why
Interactive chat openai_chat() Multi-turn, streaming, session state
Pipeline/structured openai_responses() Single-turn, JSON schemas, batch
Manual conversation openai_continue() Fine-grained control

Dependencies

  • Added to Imports: ellmer (>= 0.2.0) - Provides Chat object abstraction with streaming

Integration with artcurator

This release enables artcurator to provide unified chat interfaces across providers:

# artcurator can now offer:
curator_chat_new(artist_uuid, provider = "openai")
# Returns ellmer Chat with artist context as system prompt

artopenai 0.10.0

Breaking Changes - API Consolidation

  • Artwork analysis functions deprecated - The following functions are deprecated and will be removed in a future release:

    • art_about_ai() → Use artcurator::art_about_ai() instead
    • art_style_ai() → Use artcurator::art_style_ai() instead
    • classify_styles_ai() → Use artcurator::classify_styles_ai() instead
    • art_profile_ai() → Use artcurator::art_profile_ai() instead
    • art_profile_full_ai() → Use artcurator::art_profile_full_ai() instead

    Rationale: artcurator now provides a unified interface for artwork analysis with provider abstraction (switch between Gemini/OpenAI). All artwork-specific prompts and high-level functions have been consolidated there.

  • Removed internal utilities (now provided by artcore):

    • Removed b64EncodeImage() from R/internal-utils.R → Use artcore::b64EncodeImage()
    • Removed %||% operator definition → Imported from artcore
    • Removed duplicate utility functions from R/internal-utils.R

New Exports - Low-Level API

  • Exported openai_responses() - Previously internal .openai_responses() is now exported for use by artcurator and other packages
    • Provides low-level access to OpenAI Responses API
    • Supports full parameter control: msgs, temp, json_schema, tools, store, prev_response_id, etc.
    • Use for custom prompts and advanced workflows
  • b64EncodeImage() now provided by artcore

Dependencies

  • Added to Imports: artcore (>= 1.4.0) - Provides shared HTTP, config, and image utilities
  • Removed from Imports: base64enc, magick - Now provided by artcore dependency
  • Dependencies alphabetized for consistency

Tests

  • Removed legacy artwork httptest2-based tests that depended on b64EncodeImage() in this package
    • Test files removed: test-artwork-ai.R, test-artwork-plus-ai.R
    • Artwork analysis testing is now handled in the artcurator package alongside the consolidated API

Migration Guide

For artpipelines and Other Consumers

Replace direct artopenai function calls with artcurator:

# Before
artopenai::art_about_ai(img_path)
artopenai::art_style_ai(img_path)

# After
artcurator::art_about_ai(img_path, provider = "openai")
artcurator::art_style_ai(img_path, provider = "openai")

See vignette("artpipelines-integration", package = "artcurator") for complete migration guide.

Low-Level API Remains Available

For custom prompts and advanced use cases, use the exported low-level functions:

# Low-level API (NOT deprecated)
artopenai::openai_responses()
artopenai::openai_with_tools()
artopenai::openai_continue()
artopenai::tool_*()

artopenai 0.9.4

Documentation

  • Clarified README as the source of truth for ART_OPENAI_* environment variables and added examples including ART_OPENAI_MAX_OUTPUT_TOKENS.
  • Updated vignettes to reference ART_OPENAI_MAX_OUTPUT_TOKENS for long/structured outputs.

artopenai 0.9.3

Reliability

  • Added ART_OPENAI_MAX_OUTPUT_TOKENS (default: 4096) to control the default max_output_tokens sent to the OpenAI Responses API.
  • Improved error handling for truncated Responses API outputs (status = "incomplete", incomplete_details.reason = "max_output_tokens") with a clear, actionable message.

artopenai 0.9.2

Documentation Quality Improvements

  • @param Documentation: Enhanced all exported function parameters to meet quality gate:

    • Added Type + Format + Source + Purpose for all parameters
    • Updated openai-api.R: internal API functions with comprehensive parameter docs
    • Updated artwork-ai.R: art_about_ai(), art_style_ai() with full context
  • @description WHY: All function descriptions now explain WHY/WHEN to use each function, not just WHAT it does

  • README Enhancements:

    • Added package description paragraph
    • Added “Quick Example” section with realistic code snippets
    • Added “Package Hierarchy” section showing ecosystem position
    • Added “Documentation” section with links to docs.artalytics.dev
    • Added “Development” section with AGENTS.md reference
  • Vignette Conversion: Converted artopenai.Rmd to artopenai.qmd for Quarto-native format consistency with other Artalytics packages


artopenai 0.9.1

Testing & Tooling

  • Added httptest2-based fixtures for all OpenAI calls (continue, tools, style, full profile, health check) so tests replay offline. See tests/testthat/test-openai-continue.R, test-openai-tools.R, test-artwork-ai.R, test-artwork-plus-ai.R, test-health-check.R, and fixture dirs under tests/testthat/fixtures/.
  • Restored prompts/utils tests; suite now runs offline (except ImageMagick data URI skip) using recorded fixtures.

Maintenance