Skip to main content

Crate sqlrite_ask

Crate sqlrite_ask 

Source
Expand description

sqlrite-ask — natural-language → SQL adapter for SQLRite.

Phase 7g.1 (foundational). One sync call:

use sqlrite::Connection;
use sqlrite_ask::{ask, AskConfig};

let conn = Connection::open("foo.sqlrite")?;
let config = AskConfig::from_env()?;  // reads SQLRITE_LLM_API_KEY etc.
let response = ask(&conn, "How many users are over 30?", &config)?;
println!("Generated SQL: {}", response.sql);
println!("Why: {}", response.explanation);

§What this crate is

  • Reflects the schema of an open Connection into CREATE TABLE text the LLM can ground on.
  • Wraps that schema in a stable system prompt with an cache_control: ephemeral breakpoint so the schema dump is served from Anthropic’s prompt cache after the first call.
  • Sends one HTTP POST to the LLM provider per ask() call.
  • Parses the response into AskResponse { sql, explanation }.

§What this crate is NOT

  • Not an executor. The library deliberately does not run the generated SQL — the caller decides whether to execute it. SDK layers (Python.Connection.ask_run, Node.db.askRun, etc.) add a one-shot generate-and-execute helper for the common case, but the default API is “generate, return, let me decide”.
  • Not multi-turn. Stateless — every call is a fresh prompt.
  • Not multi-provider yet. Anthropic-first per Phase 7 plan Q4. OpenAI + Ollama follow-ups slot into [provider] without changing the public surface.

§Configuration

AskConfig resolves in this priority order:

  1. Explicit values you set on the struct (AskConfig { api_key: Some(...), .. })
  2. Environment variables (SQLRITE_LLM_*)
  3. Built-in defaults (model = claude-sonnet-4-6, max_tokens = 1024, cache TTL = 5 min)

Modules§

schema
Schema introspection — turn an open Connection into a textual schema dump the LLM can ground its SQL generation on.

Structs§

AnthropicProvider
Anthropic Messages API client. Stateless — one struct, many complete() calls. The agent (ureq client) is reused across calls so connection-pool / TLS-session-cache benefits accrue when the same AnthropicProvider makes repeat calls.
AskConfig
Knobs for an ask() call. Construct directly, or via AskConfig::from_env to pull defaults from the environment.
AskResponse
Result returned from a successful ask call.
Request
One LLM call’s worth of input. Mirrors the Anthropic Messages request shape because it’s the most expressive of the three providers we’ll support; OpenAI and Ollama adapters convert to their native shapes inside their own complete impls.
Response
What every provider returns. We keep this minimal — text is the raw string the model produced (the caller parses it), usage surfaces token counts so callers can verify cache hits.
Usage
Token-usage breakdown. Names match Anthropic’s API field names so the mapping stays obvious; OpenAI’s prompt_tokens / completion_tokens will fan into input_tokens / output_tokens when that adapter lands.

Enums§

AskError
Errors ask() can return. Includes every failure mode along the path: config / network / API / parsing.
CacheTtl
Cache-TTL knob exposed on AskConfig.
ProviderKind
Which LLM provider ask talks to. Anthropic-only in 7g.1; the enum is here so adding OpenAI/Ollama later doesn’t break the AskConfig shape.

Constants§

DEFAULT_MAX_TOKENS
Default max_tokens. SQL generation rarely needs more than ~500 output tokens (single-statement queries + a one-sentence explanation). 1024 leaves headroom; under the SDK timeout cap so we don’t have to stream.
DEFAULT_MODEL
Default model — Sonnet 4.6 hits the cost-quality sweet spot for NL→SQL. Override via AskConfig::model or the SQLRITE_LLM_MODEL env var. See docs/phase-7-plan.md for the model-choice rationale.

Traits§

ConnectionAskExt
Extension trait that adds ConnectionAskExt::ask to sqlrite::Connection. Lives here (not on the engine) to keep the engine free of HTTP / TLS / serde deps. Bring it into scope with use sqlrite_ask::ConnectionAskExt;.
Provider
A single one-shot call. Sync because every supported provider has a sync HTTPS entry point and ask() itself is sync (matches the engine’s surface — Connection::execute etc. are all sync).

Functions§

ask
One-shot natural-language → SQL.
ask_with_provider
Lower-level entry point — same flow, but you supply the provider.