Skip to main content

Crate sqlrite_ask

Crate sqlrite_ask 

Source
Expand description

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

Phase 7g.2 made this crate pure — it no longer depends on sqlrite-engine. The canonical API takes a &str schema dump (built however you like — see sqlrite::ConnectionAskExt::ask for the engine-side helper that wraps it):

use sqlrite_ask::{ask_with_schema, AskConfig};

let schema = "\
CREATE TABLE users (\n  id INTEGER PRIMARY KEY,\n  name TEXT NOT NULL\n);\n";
let cfg  = AskConfig::from_env()?;          // reads SQLRITE_LLM_API_KEY etc.
let resp = ask_with_schema(schema, "How many users?", &cfg)?;
println!("{}", resp.sql);

For the engine-integrated form (conn.ask("...", &cfg)), enable the sqlrite-engine crate’s ask feature and bring its ConnectionAskExt trait into scope:

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

let conn = Connection::open("foo.sqlrite")?;
let cfg  = AskConfig::from_env()?;
let resp = conn.ask("How many users?", &cfg)?;

§Why the split (Phase 7g.2 retro)

Wiring the REPL’s .ask meta-command would have required the engine binary to depend on sqlrite-ask, but sqlrite-ask already depended on sqlrite-engine (for Connection, Database, Table). Cargo’s static cycle detection rejects that shape even with optional = true. Solution: keep this crate pure over &str inputs, move the engine integration (schema dump + ConnectionAskExt) into sqlrite-engine itself behind an ask feature. Now there’s one direction of dep flow: engine → sqlrite-ask, never the other way.

§What this crate is

  • Provider adapters (Anthropic now; OpenAI / Ollama later) that POST one HTTP request to a chat-completion endpoint per ask() call.
  • Prompt construction with a cache_control: ephemeral breakpoint on the schema block, so repeat calls against the same schema served from Anthropic’s prompt cache.
  • Output parsing tolerant to fenced JSON / leading prose / strict JSON (model output drifts even with strict instructions).
  • AskConfig (env vars + explicit overrides), AskResponse { sql, explanation, usage }, AskError.

§What this crate is NOT

  • Not an executor. The caller decides whether to run the generated SQL. SDK convenience wrappers (Python.Connection .ask_run, Node.db.askRun, etc.) layer that on top.
  • Not multi-turn. Stateless — every call is a fresh prompt.
  • Not engine-coupled. Schema introspection lives on the engine side as of v0.1.19 — see sqlrite::ConnectionAskExt.

§Configuration

AskConfig resolves in this priority order:

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

Re-exports§

pub use provider::anthropic::AnthropicProvider;
pub use provider::Provider;
pub use provider::Request;
pub use provider::Response;
pub use provider::Usage;

Modules§

prompt
Prompt construction — turn a schema dump + a natural-language question into the request shape Anthropic expects.
provider
LLM provider abstraction.

Structs§

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.

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.

Functions§

ask_with_schema
One-shot natural-language → SQL.
ask_with_schema_and_provider
Lower-level entry point — same flow as ask_with_schema, but you supply the provider directly.
parse_response
Pull sql and explanation out of the model’s reply.