Skip to main content

semduck

Portable semantic view runtime for DuckDB, implemented in Python.

Full documentation lives in the GitHub Pages docs site for this repository. This README stays focused on the package-facing quickstart.

Supported baseline:

  • Python 3.11 to 3.13
  • DuckDB 1.4+
  • dbt-duckdb 1.9.x for the optional dbt plugin path

Install

pip install semduck

Install the dbt support extra only if you are registering the DuckDB plugin in a dbt-duckdb project:

pip install "semduck[dbt]"

Supported Patterns

  • Standalone Python package and CLI:
    • YAML semantic specs
    • semantic DDL
  • dbt interface through dbt-semduck:
    • inline semantic DDL only

YAML is supported for standalone Python and CLI usage. The dbt interface deliberately uses DDL instead of YAML-in-dbt so semduck stays dbt-agnostic.

Quickstart

Start by initializing a registry. This creates a semantic schema and several supporting tables in the duckdb database you provide.

semduck init --db demo.duckdb

Load a semantic definition from YAML:

semduck load --db demo.duckdb --file orders_semantic.yaml
semduck compile --db demo.duckdb --request "orders_semantic dimensions region metrics total_revenue"

Load a semantic definition from DDL:

semduck load --db demo.duckdb --format ddl --file path/to/orders_semantic.sql
semduck query --db demo.duckdb --request "orders_semantic dimensions region metrics total_revenue"

The CLI accepts --format auto|yaml|ddl for check and load. In auto mode it uses the file extension or the first non-empty line to infer the format.

Configure an Ollama-backed ask provider and run the ask CLI:

semduck ask \
  --db examples/dbt_example/jaffle_shop.duckdb \
  --config packages/semduck/examples/ask_ollama_config.yaml \
  --llm-log-dir .semduck/llm-logs \
  --question "What is total revenue by customer name?" \
  --sql --table

Configure an OpenAI-compatible local server and run the ask CLI:

semduck ask \
  --db examples/dbt_example/jaffle_shop.duckdb \
  --config packages/semduck/examples/ask_openai_compatible_config.yaml \
  --llm-log-dir .semduck/llm-logs \
  --question "What is total revenue by customer name?" \
  --sql --table

Set llm.log_dir in the config file to enable persistent trace logging by default, or use --llm-log-dir to override it per run. Pass --no-llm-log to disable logging even when the config file specifies a directory.

semduck ask uses a planner stage to build the semantic request and, when --summary is requested, a separate summary stage to explain the executed rows. Advanced users can configure different models for those jobs with llm.tasks.ask_plan and llm.tasks.ask_summary. If task-specific config is used, the summary task only needs to be configured when summary output is requested.

During semduck ask, the CLI now prints one-line stage updates such as planning, compile, execution, and summarization to stderr. Final results remain on stdout, so JSON output stays machine-readable.

Start the semduck MCP server over stdio:

semduck mcp --db examples/dbt_example/jaffle_shop.duckdb

Learn More

The docs site covers:

  • installation and quickstart
  • YAML vs DDL authoring
  • request language semantics
  • CLI command reference
  • Python API guidance
  • dbt interface
  • MCP server setup
  • ask provider configuration

Python API

The package exposes both YAML and DDL loaders:

import duckdb
from semduck import compile_request_sql, init_registry, load_semantic_ddl, load_semantic_yaml

conn = duckdb.connect("demo.duckdb")
init_registry(conn)

load_semantic_yaml(conn, """
name: sample
tables:
  - name: orders
    base_table:
      table: orders
    dimensions:
      - name: region
        expr: region
    metrics:
      - name: order_count
        expr: count(order_id)
""")

load_semantic_ddl(conn, """
create semantic view replacement_sample as
table main.orders as orders
  dimensions (
    region as region
  )
  metrics (
    count(order_id) as order_count
  );
""")

sql = compile_request_sql(conn, "replacement_sample dimensions region metrics order_count")
print(sql)

Relevant API entry points:

  • init_registry(conn)
  • load_semantic_yaml(conn, yaml_text)
  • load_semantic_ddl(conn, ddl_text)
  • load_semantic_yaml_file(conn, path)
  • load_semantic_ddl_file(conn, path)
  • compile_request_sql(conn, request)
  • execute_request(conn, request)

dbt Boundary

semduck keeps dbt-specific behavior in the dbt-semduck package.

  • Supported in dbt: inline semantic DDL compiled by dbt and then loaded into semduck
  • Not supported in dbt: YAML specs containing unresolved ref(...) or source(...)

The design note for that boundary lives in _project/decisions/remove_yaml_in_dbt_support.md.

Repo Examples

Development

uv sync
uv run --group dev python -m pytest
uv run tox

Metadata

Release files for semduck 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for semduck 0.1.1
File Size Uploaded
semduck-0.1.1.tar.gz 74.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for semduck 0.1.1
File Interpreter ABI Platform
semduck-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 144.5 kB

Release files / semduck-0.1.1.tar.gz

Download URL semduck-0.1.1.tar.gz
Size 74.0 kB
Tags Source
SHA-256 checksum
How to use checksums
2d8bc622b72ae82d6f4e253ebf61d8e85e401772229d475713c67d3044ceb7a8
BLAKE2b-256 checksum
How to use checksums
9927786cffe3f42d196c298ac3bc8f8f657a052ad3442b3ff1ee02bd73576abe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 May 6, 2026.

Transparency log

Release files / semduck-0.1.1-py3-none-any.whl

Download URL semduck-0.1.1-py3-none-any.whl
Size 70.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
66402ca64d8100757c23859ec662dda3f50f6691e021f0c010b1fa49ebbe34eb
BLAKE2b-256 checksum
How to use checksums
01d584f34d25362d7e0c509329f8e9804e10971e243d8598683656d40ce9f5a6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 May 6, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page