Skip to main content

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)
  • Overrideqf.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:

  1. AST Validation — All LLM-generated code is parsed and validated before execution. Dangerous operations (import os, exec, eval, open, etc.) are rejected.
  2. Restricted Builtins — Only safe builtins are available in the sandbox (no __import__, getattr, globals, etc.)
  3. Execution Timeout — Code that runs too long is killed (default: 30s)
  4. DataFrame Isolation — The LLM code operates on a copy of your DataFrame, never the original
  5. 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

queryframe-0.1.0.tar.gz (1.1 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

queryframe-0.1.0-py3-none-any.whl (50.1 kB view details)

Uploaded Python 3

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

Hashes for queryframe-0.1.0.tar.gz
Algorithm Hash digest
SHA256 7667e3d6fe1b743409591bd3dda259c0e3f6c096647440fcc98fc72337aa301e
MD5 4767f2b2173f6287e4ff4105df88fafd
BLAKE2b-256 a20c1dcec4d8092f1eb042673a220cfc4ee0110a76113b28379c1f90d2634f11

See more details on using hashes here.

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

Hashes for queryframe-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6b52b9a382e273c6753e42b6cf183f62f5961b9a0ef84e362fc061aee2b89aec
MD5 0162bfe2f82d9f7deda8b9cdfab81c99
BLAKE2b-256 f34b7f3a1b567cc1cdb72cefeabafa5159dc972fd47e9faaee1be07d5a6435d4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page