Skip to main content

Semantic layer for analytical databases

Project description

SemaFlow

A lightweight, async semantic layer for applications, APIs, and AI agents

SemaFlow is a semantic layer you integrate as a library — not a platform you operate. Built for developers first.

Think: dbt metrics, but as a Python library you import. Or: Cube, without the infrastructure.


Table of Contents


What is SemaFlow?

SemaFlow is a lightweight semantic layer written in Rust with Python bindings.

Define your semantic layer:

  • Dimensions — attributes to group by
  • Measures — aggregations and formulas
  • Joins — relationships between tables
  • Time grains — temporal hierarchies

Then serve semantic queries from:

  • REST APIs
  • Microservices
  • Dashboards
  • AI / LLM agents

All with async execution, backpressure, and predictable scalability.


Why SemaFlow?

Most semantic layers today are:

  • BI-first, synchronous, heavy platforms
  • Hard to embed in applications
  • Unsafe under bursty traffic
  • Not designed for AI or agent workloads

SemaFlow is built for a different world:

  • Real-time APIs and microservices
  • Agentic systems with concurrent requests
  • Horizontal scaling with bounded concurrency

Positioning

                         Heavy Platform
                             ▲
                             │
                 dbt SL      │         Cube
        Looker               │
                  Metriql    │
BI / Analytics               │
 ────────────────────────────┼────────────────────────────→ App / Infra
                             │
                             │        ★ SemaFlow
                             │    (lightweight library)
         BSL                 │
(Boring semantic layer)      │
                             ▼
                       Library / SDK

Key Differentiators

Feature Description
📦 Lightweight No control plane, no external dependencies, minimal config
⚡ Async by design Rust async runtime with backpressure
🔌 Library-first Import and integrate — deploy however you want
🤖 AI-friendly Safe for agents, MCP, and LLM tools
📈 Predictable scaling Bounded concurrency, connection pooling

Features

  • Multi-backend support: DuckDB, PostgreSQL, BigQuery
  • Semantic modeling: Define dimensions, measures, and flows in YAML or Python
  • DataFrame registration: Query pandas/polars DataFrames via in-memory DuckDB (zero-copy Arrow)
  • Automatic optimization: Join pruning, pre-aggregation CTEs, fanout detection
  • Type-safe SQL generation: AST-based SQL building with dialect-aware rendering
  • Async execution: Non-blocking queries with connection pooling
  • Built-in API: FastAPI integration for instant REST endpoints
  • Cursor pagination: Efficient page-by-page results (native BigQuery job pagination)
  • Formula expressions: Complex measures with inline aggregations (formula: "sum(a) / count(b)")

Installation

pip install semaflow

# With Arrow support (for register_dataframe with pandas/polars)
pip install "semaflow[arrow]"

# With FastAPI support
pip install "semaflow[api]"

# All extras
pip install "semaflow[all]"

Quick Start

From YAML Files

from semaflow import DataSource, FlowHandle

# Connect to your database
ds = DataSource.duckdb("analytics.duckdb", name="warehouse")
# Or: DataSource.postgres("postgresql://user:pass@host/db", schema="public", name="warehouse")
# Or: DataSource.bigquery(project_id="my-project", dataset="analytics", name="warehouse")

# Load semantic definitions
handle = FlowHandle.from_dir("flows/", [ds])

# Execute queries
result = await handle.execute({
    "flow": "sales",
    "dimensions": ["c.country"],
    "measures": ["o.order_total", "o.order_count"],
    "filters": [{"field": "c.country", "op": "==", "value": "US"}],
    "order": [{"column": "o.order_total", "direction": "desc"}],
    "limit": 100
})

From Python Objects

from semaflow import (
    DataSource, SemanticTable, SemanticFlow,
    Dimension, Measure, FlowJoin, JoinKey, build_flow_handles
)

ds = DataSource.duckdb("sales.duckdb", name="warehouse")

orders = SemanticTable(
    name="orders",
    data_source=ds,
    table="fct_orders",
    primary_key="order_id",
    dimensions={"status": Dimension("status")},
    measures={"total": Measure("amount", "sum")}
)

customers = SemanticTable(
    name="customers",
    data_source=ds,
    table="dim_customers",
    primary_key="customer_id",
    dimensions={"country": Dimension("country")},
    measures={"count": Measure("customer_id", "count")}
)

flow = SemanticFlow(
    name="sales",
    base_table=orders,
    base_table_alias="o",
    joins=[FlowJoin(customers, "c", "o", [JoinKey("customer_id", "customer_id")])]
)

handle = build_flow_handles({"sales": flow})

From In-Memory DataFrames

Query pandas or polars DataFrames through SemaFlow's semantic layer:

import pyarrow as pa
import pandas as pd
from semaflow import DataSource, SemanticTable, SemanticFlow, FlowHandle, Dimension, Measure

# Create in-memory DuckDB
ds = DataSource.duckdb(":memory:", name="test")

# Register a DataFrame (zero-copy via Arrow)
df = pd.DataFrame({"id": [1, 2, 3], "amount": [100.0, 200.0, 150.0], "status": ["a", "b", "a"]})
ds.register_dataframe("orders", pa.Table.from_pandas(df).to_reader())

# Define semantic layer and query
orders = SemanticTable(name="orders", data_source=ds, table="orders", primary_key="id",
                       dimensions={"status": Dimension("status")},
                       measures={"total": Measure("amount", "sum")})
flow = SemanticFlow(name="test", base_table=orders, base_table_alias="o")
handle = FlowHandle.from_parts([orders], [flow], [ds])

result = await handle.execute({"flow": "test", "dimensions": ["o.status"], "measures": ["o.total"]})

REST API

from semaflow import FlowHandle
from semaflow.api import create_app

handle = FlowHandle.from_dir("flows/", [ds])
app = create_app(handle)

# Endpoints:
# GET  /flows              - List available flows
# GET  /flows/{name}       - Get flow schema
# POST /flows/{name}/query - Execute query

YAML Schema

Semantic Table (tables/orders.yaml)

name: orders
data_source: warehouse
table: fct_orders
primary_key: order_id
time_dimension: order_date

dimensions:
  order_status:
    expr: status
    description: Order status

measures:
  # Simple measure
  order_total:
    expr: total_amount
    agg: sum
    description: Total order amount

  order_count:
    expr: order_id
    agg: count

  # Complex measure with formula
  avg_order_amount:
    formula: "order_total / order_count"
    description: Average order amount

Semantic Flow (flows/sales.yaml)

name: sales
base_table:
  semantic_table: orders
  alias: o
joins:
  customers:
    semantic_table: customers
    alias: c
    to_table: o
    join_type: left
    join_keys:
      - left: customer_id
        right: customer_id

Documentation

Guide Description
Core Concepts Data sources, tables, flows, queries
Expressions Filter syntax, simple & complex measures
Python API Full Python API reference
Dialects DuckDB, PostgreSQL, BigQuery specifics
Configuration TOML configuration reference
Join Semantics Join types, cardinality, NULL behavior
Architecture System design and components
Contributing Development setup, PR guidelines

Examples

See the examples/ directory for complete working examples.

# DuckDB demo
cd examples/duckdb && uv run python demo.py

# PostgreSQL demo (requires Docker)
cd examples/postgres && docker compose up -d && uv run python demo.py

# FastAPI server
uv run python examples/semantic_api.py
# Then: curl http://localhost:8080/flows/sales

Development

# Build Python bindings
uv run maturin develop

# Run Rust tests
cargo test --features all-backends

# Run Python tests
uv run pytest tests/

# Fast Rust iteration (no backends)
cargo check --no-default-features

Roadmap

  • Snowflake backend
  • Trino backend
  • Result caching layer
  • Time-series helpers (period-over-period, rolling windows)
  • TypeScript bindings
  • WASM support

Who is SemaFlow For?

  • Backend / platform engineers building data APIs
  • SaaS teams exposing metrics to customers
  • AI engineers building agent tools and MCP servers
  • Data platform teams building custom analytics UIs

What SemaFlow Is Not

  • ❌ Not a BI tool or dashboard platform
  • ❌ Not a dbt replacement
  • ❌ Not a metrics governance UI
  • ❌ Not a heavy analytics gateway

License

MIT

Project details


Download files

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

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

semaflow-0.1.2-cp312-cp312-win_amd64.whl (15.4 MB view details)

Uploaded CPython 3.12Windows x86-64

semaflow-0.1.2-cp312-cp312-macosx_11_0_arm64.whl (17.2 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

semaflow-0.1.2-cp312-cp312-macosx_10_12_x86_64.whl (18.7 MB view details)

Uploaded CPython 3.12macOS 10.12+ x86-64

File details

Details for the file semaflow-0.1.2-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: semaflow-0.1.2-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 15.4 MB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for semaflow-0.1.2-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 8768fd4cbcf24a5740a244aee001d68fa331ff70d68d1a9ff4071d66d4d4695d
MD5 fb5bdbfd2d051c5943deee8f8e967dea
BLAKE2b-256 b0309b4ce01c3bddfe971b98752fe55b985340c80ecc4e4e819f79a1b5f58ead

See more details on using hashes here.

File details

Details for the file semaflow-0.1.2-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for semaflow-0.1.2-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e3615b990169e699b22d4362f17879da40e71cf5b8a457a5f47cd275d2590533
MD5 9867abc20b7acc3bb7eb1224724133c8
BLAKE2b-256 f88d54ce98efa939acb999015ae50b47a861d972f28d048da932e19ceaba826f

See more details on using hashes here.

File details

Details for the file semaflow-0.1.2-cp312-cp312-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for semaflow-0.1.2-cp312-cp312-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 52361e20954454def9928361ad2add70835aa806d656bb64c485dcb554fde193
MD5 2e6826f8ab44671019fb069f09ffa4d3
BLAKE2b-256 082c28c1f73d50c39b5b04224b45ede6cfea5390a486cf6f2c3de8d1cb099e18

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