Lotus.AI (Lotus v0.16.4)

Copy Markdown View Source

AI-powered query generation for Lotus.

Configuration

Configure AI in your application config:

config :lotus,
  ai: [
    enabled: true,
    model: "anthropic:claude-opus-4",
    api_key: {:system, "ANTHROPIC_API_KEY"}
  ]

The model key accepts any model string supported by ReqLLM, e.g.:

  • "openai:gpt-4o" (default)
  • "anthropic:claude-opus-4"
  • "google:gemini-2.0-flash"
  • "groq:llama-3.3-70b-versatile"
  • Any other provider supported by ReqLLM

Usage

{:ok, result} = Lotus.AI.generate_query(
  prompt: "Show me all users who signed up last month",
  data_source: "postgres"
)

# Returns:
# %{
#   sql: "SELECT * FROM users WHERE created_at >= ...",
#   variables: [],
#   model: "openai:gpt-4o",
#   usage: %{total_tokens: 150}
# }

Error Handling

The generate_query/1 function returns structured error tuples that clients can pattern match on for custom handling and internationalization (i18n):

  • {:ok, result} - Successfully generated SQL query
  • {:error, :not_configured} - AI features not enabled in config
  • {:error, :api_key_not_configured} - API key missing or invalid
  • {:error, {:unable_to_generate, reason}} - LLM refused (non-SQL question)
  • {:error, term} - Other errors (API failures, network issues, etc.)

Summary

Functions

Check if AI features are enabled and configured.

Get an AI-powered plain-language explanation of a SQL query.

Generate SQL query from natural language prompt.

Generate SQL query from natural language prompt with conversation context.

Get the configured AI model string.

Get AI-powered optimization suggestions for a SQL query.

Functions

enabled?()

@spec enabled?() :: boolean()

Check if AI features are enabled and configured.

Returns true if AI is properly configured, false otherwise.

Examples

Lotus.AI.enabled?()
# => true

explain_query(opts)

@spec explain_query(keyword()) :: {:ok, map()} | {:error, term()}

Get an AI-powered plain-language explanation of a SQL query.

Supports explaining a full query or a selected fragment. When a fragment is provided, the full query is sent as context so the AI can explain even isolated terms accurately.

Options

  • :sql (required) - The full SQL query
  • :fragment (optional) - A selected portion of the query to explain
  • :data_source (required) - Name of the data source to resolve schema context

Returns

  • {:ok, result} - Map with :explanation, :model, and :usage
  • {:error, term} - Structured error tuple

Examples

# Explain a full query
{:ok, result} = Lotus.AI.explain_query(
  sql: "SELECT d.name, COUNT(o.id) FROM departments d LEFT JOIN orders o ...",
  data_source: "postgres"
)

result.explanation
# => "This query shows departments ranked by total order count..."

# Explain a selected fragment
{:ok, result} = Lotus.AI.explain_query(
  sql: "SELECT d.name FROM departments d LEFT JOIN employees e ON e.department_id = d.id",
  fragment: "LEFT JOIN employees e ON e.department_id = d.id",
  data_source: "postgres"
)

generate_query(opts)

@spec generate_query(keyword()) :: {:ok, map()} | {:error, term()}

Generate SQL query from natural language prompt.

Uses the globally configured AI provider from application config.

Options

  • :prompt (required) - Natural language description of desired query
  • :data_source (required) - Name of the data source to query against
  • :read_only (optional) - When true (default), the AI only generates read-only queries. Set to false to allow the AI to generate write queries.

Returns

  • {:ok, result} - Successfully generated SQL with metadata
  • {:error, term} - Structured error tuple (see module docs for error types)

Examples

{:ok, result} = Lotus.AI.generate_query(
  prompt: "Count active users by signup month",
  data_source: "postgres"
)

result.sql
# => "SELECT DATE_TRUNC('month', created_at) as month, COUNT(*) FROM users WHERE status = 'active' GROUP BY month"

result.model
# => "openai:gpt-4o"

result.usage
# => %{prompt_tokens: 150, completion_tokens: 50, total_tokens: 200}

# Error handling with pattern matching
{:error, :not_configured} = Lotus.AI.generate_query(
  prompt: "some query",
  data_source: "postgres"
)

generate_query_with_context(opts)

@spec generate_query_with_context(keyword()) :: {:ok, map()} | {:error, term()}

Generate SQL query from natural language prompt with conversation context.

Enables multi-turn conversations by accepting conversation history. The AI can refine queries, fix errors, and provide iterative improvements.

Options

  • :prompt (required) - Natural language description of desired query
  • :data_source (required) - Name of the data source to query against
  • :conversation (optional) - Conversation struct with message history
  • :read_only (optional) - When true (default), the AI only generates read-only queries. Set to false to allow the AI to generate write queries.

Returns

  • {:ok, result} - Successfully generated SQL with metadata
  • {:error, term} - Structured error tuple (see module docs for error types)

Examples

# Simple single-turn (same as generate_query/1)
{:ok, result} = Lotus.AI.generate_query_with_context(
  prompt: "Show active users",
  data_source: "postgres"
)

# Multi-turn with conversation history
conversation = Conversation.new()
conversation = Conversation.add_user_message(conversation, "Show active users")

{:ok, result} = Lotus.AI.generate_query_with_context(
  prompt: "Show active users",
  data_source: "postgres",
  conversation: conversation
)

# If query fails, add error to conversation
conversation = Conversation.add_query_result(conversation, {:error, "column 'status' not found"})

# AI can now fix the error with full context
{:ok, fixed_result} = Lotus.AI.generate_query_with_context(
  prompt: "Fix the error",
  data_source: "postgres",
  conversation: conversation
)

model()

@spec model() :: {:ok, String.t()} | {:error, :not_configured}

Get the configured AI model string.

Returns the full model string (e.g. "openai:gpt-4o") if configured.

Examples

Lotus.AI.model()
# => {:ok, "openai:gpt-4o"}

suggest_optimizations(opts)

@spec suggest_optimizations(keyword()) :: {:ok, map()} | {:error, term()}

Get AI-powered optimization suggestions for a SQL query.

Runs EXPLAIN on the query to get the execution plan, then uses AI to analyze both the SQL and plan for potential improvements.

Options

  • :sql (required) - The SQL query to optimize
  • :data_source (required) - Name of the data source to run against
  • :params (optional) - Query parameters (default: [])
  • :search_path (optional) - PostgreSQL search path

Returns

  • {:ok, result} - Map with suggestions list, model, and usage info
  • {:error, term} - Structured error tuple

Examples

{:ok, result} = Lotus.AI.suggest_optimizations(
  sql: "SELECT * FROM orders WHERE created_at > '2024-01-01'",
  data_source: "postgres"
)

result.suggestions
# => [
#   %{
#     "type" => "index",
#     "impact" => "high",
#     "title" => "Add index on orders.created_at",
#     "suggestion" => "..."
#   }
# ]