LARS - AI That Speaks SQL
Your team knows SQL. Why learn Python for AI?
Add AI operators directly to your SQL queries — from your existing SQL client, on your existing databases.
SELECT * FROM support_tickets
WHERE description MEANS 'urgent customer issue';
That's it. No notebooks. No orchestration code. No vector database to provision. Just SQL with semantic understanding (and a declarative workflow engine underneath). Express intent, not patterns — especially when you don't know what you're looking for.
- Use your existing SQL client: PostgreSQL wire protocol (
lars serve sql) - Your data never moves: DuckDB federation across Postgres/MySQL/BigQuery/Snowflake/S3/files
- Cached + cost-attributed: query LLM calls via
all_data/sql_query_log - Optional Studio UI: inspect runs, takes, costs, and "what the model saw" (not required)
One line. That's all it takes.
Before: Regex, LIKE patterns, and brittle keyword matching.
SELECT * FROM tickets
WHERE description LIKE '%urgent%'
OR description LIKE '%critical%'
OR description LIKE '%asap%'
-- still misses "need this fixed immediately"
After: One line that understands meaning.
SELECT * FROM tickets
WHERE description MEANS 'urgent customer issue'
What Can You Do?
-- Filter by meaning, not keywords
SELECT * FROM products
WHERE description MEANS 'eco-friendly'
-- Score relevance (0.0 to 1.0)
SELECT title, description ABOUT 'sustainability' AS relevance
FROM reports
ORDER BY relevance DESC
-- Semantic deduplication
SELECT SEMANTIC DISTINCT company_name FROM leads
-- Find contradictions (compliance, fact-checking)
SELECT * FROM disclosures
WHERE statement CONTRADICTS 'no material changes'
-- Summarize groups
SELECT category, SUMMARIZE(reviews) AS summary
FROM feedback
GROUP BY category
-- Group by auto-discovered topics
SELECT TOPICS(title, 5) AS topic, COUNT(*) AS count
FROM articles
GROUP BY topic
-- Vector similarity search
SELECT * FROM docs
WHERE title SIMILAR_TO 'quarterly earnings report'
LIMIT 10
-- Ask arbitrary questions
SELECT
product_name,
ASK('Is this suitable for children? yes/no', description) AS kid_friendly
FROM products
-- plus lots more...
100+ built-in operators for filtering, logic, transformation, aggregation, data quality, parsing, and more.
Quick Start
# install
pip install larsql
# set your LLM API key (OpenRouter, or see docs site for others)
export OPENROUTER_API_KEY=sk-or-v1-...
# set up clickhouse (docker or existing DB)
docker run -d \
--name lars-clickhouse \
--ulimit nofile=262144:262144 \
-p 8123:8123 \
-p 9000:9000 \
-p 9009:9009 \
-v clickhouse-data:/var/lib/clickhouse \
-v clickhouse-logs:/var/log/clickhouse-server \
-e CLICKHOUSE_USER=lars \
-e CLICKHOUSE_PASSWORD=lars \
clickhouse/clickhouse-server:25.11
# create & populate a project directory for the starter files
lars init my_lars_project ; cd my_lars_project
# init the database and refresh the metadata
lars db init
# start the SQL server (PostgreSQL wire protocol)
lars serve sql --port 15432
# connect with any SQL client (default is lars/lars - proper auth coming soon)
psql postgresql://localhost:15432/default
# optional - start the web UI admin / studio tool
lars serve studio
# runs at http://localhost:5050
That's it. Run semantic queries from DBeaver, DataGrip, psql, Tableau, or any PostgreSQL client. For a full end-to-end setup (ClickHouse + sample data + Studio UI), see the Quickstart Guide.
How It Works
LARS uses query rewriting - your semantic SQL is transformed into standard SQL with UDF calls that execute LLM operations. Your database stays untouched.
WHERE description MEANS 'urgent'
↓
WHERE semantic_matches('urgent', description)
↓
UDF runs LLM → returns true/false
Results are cached - same query on same data costs zero after the first run.
Every semantic UDF call is also logged (model, tokens, cost, duration) into queryable "magic tables":
SELECT session_id, cell_name, model, cost, duration_ms
FROM all_data
WHERE is_sql_udf = true
ORDER BY timestamp DESC
LIMIT 20;
Every semantic operator is backed by a cascade file under cascades/semantic_sql/ - edit YAML to change behavior or create your own operator.
If you want a visual view of the same execution data, Studio is a UI over these logs (optional).
Wait, it gets weirder.
Semantic SQL is just the beginning. Under the hood, LARS is a declarative agent framework for building sophisticated LLM workflows.
The Problem It Solves
Every LLM project eventually becomes this:
for attempt in range(max_retries):
try:
result = llm.call(prompt)
if validate(result):
return result
prompt += f"\nError: {validation.error}. Try again."
except JSONDecodeError as e:
prompt += f"\nFailed to parse: {e}"
# 47 lines later... still doesn't work reliably
The LARS Solution
Run multiple attempts in parallel. Filter errors naturally. Pick the best.
- name: generate_analysis
instructions: "Analyze the sales data..."
takes:
factor: 3 # Run 3 times in parallel
evaluator_instructions: "Pick the most thorough analysis"
Instead of serial retries hoping one succeeds, run N attempts simultaneously and select the winner. Same cost, faster execution, higher quality output.
Declarative Workflows (Cascades)
Define multi-step agent workflows in YAML:
cascade_id: analyze_data
cells:
- name: query_data
tool: sql_data
tool_inputs:
query: "SELECT * FROM sales WHERE date > '2024-01-01'"
- name: analyze
instructions: |
Analyze this sales data: {{ outputs.query_data }}
Create visualizations and summarize key trends.
skills:
- create_chart
- smart_sql_run
takes:
factor: 3
evaluator_instructions: "Pick the most insightful analysis"
handoffs: [review]
- name: review
instructions: "Summarize the findings"
context:
from: [analyze]
Key Concepts
| Concept | What It Does |
|---|---|
| Cascades | Declarative YAML workflows |
| Cells | Execution stages (LLM, deterministic, or human-in-the-loop) |
| Takes | Parallel execution → filter errors → pick best |
| Reforge | Iterative refinement of winning output |
| Wards | Validation barriers (blocking, retry, advisory) |
| Skills | Tools available to agents (are also FULL multi-cell cascades!) |
Database Support
LARS connects to your existing databases:
- DuckDB (default, in-memory or file)
- PostgreSQL, MySQL, ClickHouse
- BigQuery, Snowflake
- S3, Azure, GCS (Parquet, CSV, JSON)
Your data stays where it is. LARS queries it federated-style. Join across DB boundaries.
LLM Providers
Works with any LLM via LiteLLM:
- OpenRouter (default) - access to 200+ models, excellently granular cost tracking
- OpenAI, Anthropic, Google
- Ollama (local & remote models, zero cost)
- Azure OpenAI, AWS Bedrock, Vertex AI
Installation Options
# Basic
pip install larsql
# With browser automation (Playwright)
pip install larsql[browser]
# With local models (HuggingFace)
pip install larsql[local-models]
# Everything
pip install larsql[all]
Running Cascades
# Run a workflow
lars run cascades/example.yaml --input '{"task": "analyze sales data"}'
# With model override
lars run cascades/example.yaml --model "anthropic/claude-sonnet-4"
Studio Web UI (Optional)
# Launch the visual interface
lars serve studio
# Access at http://localhost:5050
# - SQL IDE with semantic operators
# - Cascade runner (incl. takes + winners)
# - Context inspector ("what the model saw")
# - Cost explorer (by query/cascade/model)
Documentation
Full documentation at larsql.com
-
Docs hub - Full reference
-
Quickstart Guide - Get running in 10 minutes
-
Studio Web UI - Optional UI for debugging cost/context/takes
-
Semantic SQL - Query rewriting, caching, annotations, observability
-
Built-in Operators - All 100+ operators
-
Vector Search & Embedding - SIMILAR_TO, LARS EMBED, hybrid search
-
Cascade DSL - Workflow configuration
-
Takes & Evaluation - Parallel execution patterns
-
SQL Connections - Connect 18+ data sources via DuckDB
-
AI Providers - OpenRouter, Vertex AI, Bedrock, Azure, Ollama
-
Tools Reference - Available skills & integrations
Example: Create Your Own Operator
Any cascade can become a SQL operator. No Python required.
# cascades/semantic_sql/sentiment_score.cascade.yaml
cascade_id: sentiment_score
sql_function:
name: SENTIMENT_SCORE
operators:
- "SENTIMENT_SCORE({{ text }})"
returns: DOUBLE
shape: SCALAR
cells:
- name: score
model: google/gemini-2.5-flash-lite
instructions: |
Rate the sentiment of this text from -1.0 to 1.0.
TEXT: {{ input.text }}
Return only the number.
Worried about the output? Me too. Run validations or multiple takes (on multiple models), all within a SQL call.
Now use it:
SELECT product_id, AVG(SENTIMENT_SCORE(review)) AS sentiment
FROM reviews
GROUP BY product_id
HAVING sentiment < -0.3
Contributing
Issues welcome at github.com/ryrobes/larsql
License
O'SASSY License (basically MIT)
Metadata
Release files for larsql 3.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| larsql-3.2.2.tar.gz | 80.3 MB | With provenance | Details for larsql-3.2.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| larsql-3.2.2-py3-none-any.whl | Python 3 | none | any | Details for larsql-3.2.2-py3-none-any.whl |
Total release size: 161.6 MB
Release files / larsql-3.2.2.tar.gz
| Download URL | larsql-3.2.2.tar.gz |
|---|---|
| Size | 80.3 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
79e999f41366e604678afbe5e372027a8118fd59c9dd05dea9f0bc5abaabfd0e
|
|
BLAKE2b-256 checksum How to use checksums |
e4e1879bf9b247b8e30dcc57092330efab0f59e9e2a3b9d870f5f344e6af6287
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 20, 2026.
Transparency logRelease files / larsql-3.2.2-py3-none-any.whl
| Download URL | larsql-3.2.2-py3-none-any.whl |
|---|---|
| Size | 81.3 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
11b6b7df2a849d21e4cbd539533f8fa8b06a52a1000e4a11eb8c80bd05df8505
|
|
BLAKE2b-256 checksum How to use checksums |
5991d662d4d7175cf377bcff1f3f23acacbf788b7a38e9d9ef9f032c63264c8b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 20, 2026.
Transparency logSecurity for larsql 3.2.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for larsql-3.2.2.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 20, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.