memFrame
memFrame brings a pandas-like DataFrame API to DuckDB, PostgreSQL, and ClickHouse — async-first, with an optional AI agent for natural-language data work.
Features
- Database-backed DataFrame API across DuckDB, PostgreSQL, and ClickHouse.
- Compiles every pandas-style call to backend-native SQL (DuckDB / PostgreSQL / ClickHouse) and runs it in-engine — your data never leaves the database.
- Async-first surface with sync equivalents for every operation.
- Upload from CSV, Parquet, or pandas DataFrame.
- Pandas-style
mf.DataFrame(...)constructor for dicts, frames, or existing dataset contexts. - Database-native indexes: DuckDB ART, PostgreSQL B-tree/partial/covering, ClickHouse projection indexes (no full data copy) with explicit skipping-index types, plus a guarded ClickHouse
ORDER BYrebuild. - Sync pre-existing DuckDB, PostgreSQL, or ClickHouse tables as datasets — no re-upload.
- Two-level cache: lineage audit + replayable result tables.
- Optional AI agent layer (
memframe_ai) for chatting with your CSV. - Optional Logfire observability for the AI agent layer — traces every agent run, LLM call, and tool call, plus host metrics. Opt-in via
logfire_enabled(local console needs no token; bring-your-own-key for the cloud).
Installation
pip install memframe # core
uv add memframe # alt: uv
pip install "memframe[ai]" # + Pydantic AI agent layer
uv add "memframe[ai]" # alt: uv
pip install "memframe[logfire]" # + AI agent layer AND Logfire observability
pip install "memframe[ai,logfire]" # explicit equivalent of the above
Local development from this repository:
git clone https://github.com/Debojit95/memFrame.git
cd memFrame
uv sync --extra dev --extra ai
uv build
Quick Start
import asyncio
import memframe as mf
async def main():
await mf.aconnect(
connection_type="local",
connection_params={"db_path": "memFrame.duckdb"},
)
customers = await mf.aDataFrame(
{
"id": [101, 102, 103],
"name": ["Alice", "Bob", "Charlie"],
"score": [95.5, 82.0, None],
"active": [True, False, True],
},
filename="customers",
)
preview = await customers.ahead(n=5)
print(preview)
await mf.aclose()
asyncio.run(main())
memframe itself is the connection facade: mf.connect(...) / await mf.aconnect(...) configure one default connection, and every instance method
(upload_df, list_tables, set_active, mean, chat, …) is available
directly on the module. Each upload returns a dataset context; chain
inspection, selection, cleaning, arithmetic, statistics, and plotting on it.
Sync methods drop the a prefix (head, iloc, fillna, …).
Need more than one connection? Use the class directly:
from memframe import MemFrame
analytics = MemFrame(
connection_type="local",
connection_params={"db_path": "analytics.duckdb"},
)
analytics.connect()
Build a dataset from in-memory data with the pandas-style constructor:
dataset = mf.DataFrame({"name": ["Alice", "Bob"], "score": [95.5, 82.0]})
dataset = mf.DataFrame(existing_dataset) # snapshot into a new dataset
Already have tables in your database? Register them as datasets without
re-uploading (after mf.connect(...)):
registered = mf.register_tables()
# {'sales': [{'data_id': 'a1b2c3', 'table_name': 'orders', 'row_count': 100}, ...]}
Registered tables act like uploads — activate with set_active(data_id) and
query via memFrame(). Deleting one only removes memFrame's registry entry;
your real table is left untouched.
Architecture
Every pandas-style call compiles to backend-native SQL and runs in-engine — your
data never leaves the database. The call path is a four-layer stack (public API →
orchestrator → core SQL engine → backend adapter), with connection, ingestion,
and a two-level cache as cross-cutting subsystems, plus an optional
memframe_ai agent layer on top.
See the full Architecture page for the component diagram and a per-layer breakdown.
AI Agent
memframe_ai adds a Pydantic AI agent fleet on top of memFrame. After enabling
it on the MemFrame instance, any dataset context can run natural-language
queries that decompose into specialist tools and return typed response blocks.
import asyncio
import memframe as mf
async def main():
await mf.aconnect(
connection_type="local",
connection_params={"db_path": "memFrame.duckdb"},
)
await mf.aenable_agent(
provider="openai",
model="gpt-5.5",
api_key="sk-...",
)
ds = await mf.aDataFrame(
{
"name": ["Alice", "Bob", "Charlie"],
"score": [95.5, 82.0, None],
},
filename="customers",
)
result = await ds.achat("fill null scores with the mean")
print(result["answer"])
print(result["plots"]) # any charts the agent built (id, title, spec_preview)
await mf.aclose()
asyncio.run(main())
The agent supports OpenAI, Anthropic, Google, and Ollama. Pick a provider when you enable the agent:
await mf.aenable_agent(api_key="sk-...", provider="anthropic", model="claude-...")
Documentation
Full reference lives in docs/:
- Getting Started — connect, upload, first query.
- Connector & Connection — DuckDB / Postgres / ClickHouse wiring.
- Upload Manager — CSV / Parquet / DataFrame ingestion.
- Sync Existing Tables — register pre-existing DB tables as datasets.
- Dataset Operations — table and active-dataset management.
- Inspection · Selection · Filter · Clean
- Statistics · Arithmetic · Comparison · Cumulative
- Sorting · Index · Reshape · Merge · Transform
- Plotting · Caching
Serve locally:
mkdocs serve
Metadata
Release files for memframe 0.17.0
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 |
|---|---|---|---|---|
| memframe-0.17.0.tar.gz | 2.4 MB | Without provenance | Details for memframe-0.17.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| memframe-0.17.0-py3-none-any.whl | Python 3 | none | any | Details for memframe-0.17.0-py3-none-any.whl |
Total release size: 3.0 MB
Release files / memframe-0.17.0.tar.gz
| Download URL | memframe-0.17.0.tar.gz |
|---|---|
| Size | 2.4 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
90e57ce69cf0c38ff97d506342a945195bd4685cd412d19b23f1ba19ba67049f
|
|
BLAKE2b-256 checksum How to use checksums |
3c74ae2ec8a1adc39ebcc866c6faf006d5b6eefc7e3bde54949533afa924b348
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / memframe-0.17.0-py3-none-any.whl
| Download URL | memframe-0.17.0-py3-none-any.whl |
|---|---|
| Size | 508.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a0b4536c66698223cbebb4de35a3c334e85596f53205143447e30c7dab1eb84f
|
|
BLAKE2b-256 checksum How to use checksums |
5dcfd59c566fb895e31342f655b08450801edc7b455fbc938c4a24f3b5ca6b0b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.7 {"installer":{"name":"uv","version":"0.13.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for memframe 0.17.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A 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.