Super fast natural language data visualization and analysis for pandas DataFrames
Project description
QueryFrame
Super fast natural language data visualization and analysis for pandas DataFrames.
QueryFrame lets you ask questions about your data in plain English and get instant answers, charts, and insights. It's the faster, safer, more flexible alternative to PandasAI.
import pandas as pd
import queryframe as qf
df = pd.read_csv("sales.csv")
# Ask anything
result = qf.ask(df, "what is the average revenue by region?")
print(result.data)
# Visualize instantly
result = df.qf.ask("show me a bar chart of sales by product")
result.show()
# Chain queries
result = qf.ask(df, "top 5 customers by spend").save("top_customers.html")
Why QueryFrame over PandasAI?
| Feature | QueryFrame | PandasAI |
|---|---|---|
| Speed | Smart caching, minimal prompts | Sends full schema every query |
| Safety | AST-validated sandbox | Raw exec() |
| Local models | First-class Ollama + LM Studio | Limited support |
| Visualizations | Auto-selects Plotly/Matplotlib/Altair | Mostly matplotlib |
| Follow-ups | Conversation memory | Stateless |
| Token usage | Compressed schemas, 3 sample rows | Verbose, 5 sample rows |
Installation
# Core (no LLM provider included)
pip install queryframe
# With your preferred provider
pip install queryframe[openai] # OpenAI
pip install queryframe[anthropic] # Claude
pip install queryframe[gemini] # Google Gemini
pip install queryframe[ollama] # Ollama (local)
pip install queryframe[lmstudio] # LM Studio (local)
# With visualization libraries
pip install queryframe[plotly] # Interactive charts (recommended)
pip install queryframe[matplotlib] # Static charts (includes seaborn)
pip install queryframe[altair] # Declarative charts
# Everything
pip install queryframe[all]
Quick Start
1. Set your API key (cloud providers)
export OPENAI_API_KEY="sk-..."
# or
export ANTHROPIC_API_KEY="sk-ant-..."
# or
export GOOGLE_API_KEY="..."
2. Use it
import pandas as pd
import queryframe as qf
df = pd.DataFrame({
"product": ["Laptop", "Phone", "Tablet"],
"price": [999, 699, 449],
"units_sold": [150, 500, 200],
})
# Natural language queries
result = qf.ask(df, "which product generated the most revenue?")
print(result.data) # The answer
print(result.code) # Generated pandas code
print(result.explanation) # Human-readable explanation
# Visualizations
result = qf.ask(df, "bar chart of revenue by product")
result.show() # Display interactive chart
result.save("chart.html") # Export
Local Models (Ollama / LM Studio)
QueryFrame has first-class support for local models — no API keys, no data leaves your machine.
Ollama
# Start Ollama
ollama serve
# Pull a model
ollama pull llama3.1
import queryframe as qf
qf.configure(provider="ollama", model="llama3.1")
result = qf.ask(df, "average sales by region")
LM Studio
import queryframe as qf
# LM Studio runs at localhost:1234 by default
qf.configure(provider="lmstudio")
result = qf.ask(df, "show me the top 10 products")
All Providers
from queryframe import QueryEngine, QueryFrameConfig
# OpenAI
engine = QueryEngine(config=QueryFrameConfig(
provider="openai", model="gpt-4o-mini"
))
# Anthropic Claude
engine = QueryEngine(config=QueryFrameConfig(
provider="anthropic", model="claude-sonnet-4-20250514"
))
# Google Gemini
engine = QueryEngine(config=QueryFrameConfig(
provider="gemini", model="gemini-2.0-flash"
))
# Ollama
engine = QueryEngine(config=QueryFrameConfig(
provider="ollama", model="llama3.1"
))
# LM Studio
engine = QueryEngine(config=QueryFrameConfig(
provider="lmstudio"
))
# Auto-detect (checks env vars, then local servers)
engine = QueryEngine() # Just works
Visualization
QueryFrame auto-selects the best visualization library:
- Notebooks → Plotly (interactive)
- Scripts → Matplotlib (static)
- Override →
qf.ask(df, "...", viz="altair")
Supported chart types: bar, line, scatter, pie, histogram, heatmap, box, area, violin, treemap, funnel
# Auto-select
result = qf.ask(df, "show trend of sales over time") # → line chart
# Force specific library
result = qf.ask(df, "bar chart of revenue", viz="matplotlib")
# Re-render with different library
result = qf.ask(df, "sales by region").viz("altair")
# Save to file
result.save("chart.png") # static image
result.save("chart.html") # interactive HTML
Chainable API
# Chain operations
result = (
qf.ask(df, "total revenue by product")
.save("revenue.html")
)
# Follow-up queries (uses conversation memory)
r1 = qf.ask(df, "show me sales by region")
r2 = r1.ask("now filter to just Q4") # "it" = sales by region
r3 = r2.ask("which region had the highest?") # context preserved
Caching
Repeated queries are instant (< 5ms vs 2-5s for LLM calls):
# First call: hits the LLM (~2s)
result = qf.ask(df, "average sales")
print(result.cached) # False
# Same query: from cache (~1ms)
result = qf.ask(df, "average sales")
print(result.cached) # True
Configuration
import queryframe as qf
# Via configure()
qf.configure(
provider="openai",
model="gpt-4o",
cache_enabled=True,
viz_mode="plotly", # auto, plotly, matplotlib, altair
timeout=30, # seconds
max_retries=2,
)
# Via environment variables
# QF_PROVIDER=openai
# QF_MODEL=gpt-4o
# QF_VIZ=plotly
# QF_TIMEOUT=30
# QF_VERBOSE=true
# QF_LOG_LEVEL=DEBUG
Security
QueryFrame takes security seriously:
- AST Validation — All LLM-generated code is parsed and validated before execution. Dangerous operations (
import os,exec,eval,open, etc.) are rejected. - Restricted Builtins — Only safe builtins are available in the sandbox (no
__import__,getattr,globals, etc.) - Execution Timeout — Code that runs too long is killed (default: 30s)
- DataFrame Isolation — The LLM code operates on a copy of your DataFrame, never the original
- No Network Access — Sandboxed code cannot make network requests
Architecture
df.ask("show me sales by region")
│
▼
┌─────────────┐ ┌──────────┐ ┌────────────┐
│ Cache Check │────▸│ Schema │────▸│ Prompt │
│ (< 1ms) │ │ Extract │ │ Builder │
└─────────────┘ └──────────┘ └────────────┘
│
▼
┌─────────────┐ ┌──────────┐ ┌────────────┐
│ Viz Render │◂────│ Sandbox │◂────│ LLM │
│ (auto-pick) │ │ Execute │ │ Provider │
└─────────────┘ └──────────┘ └────────────┘
│
┌────────────┐
│ QueryResult│
│ .data │
│ .chart │
│ .code │
└────────────┘
Development
# Clone
git clone https://github.com/movar-group/queryframe.git
cd queryframe
# Install in dev mode
pip install -e ".[dev,all]"
# Run tests
pytest
# Lint
ruff check src/ tests/
ruff format src/ tests/
# Type check
mypy src/queryframe/
License
MIT License. See LICENSE for details.
Contributing
Contributions welcome! Please read CONTRIBUTING.md before submitting a PR.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file queryframe-0.1.0.tar.gz.
File metadata
- Download URL: queryframe-0.1.0.tar.gz
- Upload date:
- Size: 1.1 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7667e3d6fe1b743409591bd3dda259c0e3f6c096647440fcc98fc72337aa301e
|
|
| MD5 |
4767f2b2173f6287e4ff4105df88fafd
|
|
| BLAKE2b-256 |
a20c1dcec4d8092f1eb042673a220cfc4ee0110a76113b28379c1f90d2634f11
|
File details
Details for the file queryframe-0.1.0-py3-none-any.whl.
File metadata
- Download URL: queryframe-0.1.0-py3-none-any.whl
- Upload date:
- Size: 50.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6b52b9a382e273c6753e42b6cf183f62f5961b9a0ef84e362fc061aee2b89aec
|
|
| MD5 |
0162bfe2f82d9f7deda8b9cdfab81c99
|
|
| BLAKE2b-256 |
f34b7f3a1b567cc1cdb72cefeabafa5159dc972fd47e9faaee1be07d5a6435d4
|