DuckDB Extension¶
openaivec.duckdb_ext ¶
DuckDB integration for openaivec.
Provides helpers that bridge openaivec's batched AI capabilities with DuckDB:
- UDF registration – register
responses,embeddingsandtaskfunctions directly as DuckDB scalar UDFs so SQL queries can invoke the OpenAI API transparently. - Persistent caching – pass
DuckDBCacheBackendas the_cachefield ofBatchCachefor cross-session cache persistence. - Vector similarity –
similarity_searchperforms top-k cosine similarity queries against an embedding table using DuckDB's built-inlist_cosine_similarity. - Schema → DDL –
pydantic_to_duckdb_ddlconverts a Pydantic model to aCREATE TABLEstatement for immediate SQL analysis of structured-output results.
Quick Start¶
import duckdb
from openaivec.duckdb_ext import register_responses_udf, register_embeddings_udf
conn = duckdb.connect()
register_responses_udf(conn, "translate", instructions="Translate to French")
register_embeddings_udf(conn, "embed")
conn.sql("SELECT translate(review) FROM products")
conn.sql("SELECT text, embed(text) FROM documents")
Classes¶
Functions¶
register_responses_udf ¶
register_responses_udf(
conn: DuckDBPyConnection,
name: str,
*,
instructions: str,
response_format: type = str,
model_name: str | None = None,
batch_size: int = 64,
max_concurrency: int = 8,
**api_kwargs: Any,
) -> None
Register a DuckDB Arrow-based UDF that calls the OpenAI Responses API.
The UDF processes rows in vectorized batches via AsyncBatchResponses,
leveraging deduplication and concurrency for throughput.
When response_format is a Pydantic BaseModel, the UDF returns a
DuckDB STRUCT whose fields match the model, allowing direct field
access in SQL (e.g. SELECT udf(text).sentiment FROM ...).
When response_format is str, the UDF returns VARCHAR.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
conn
|
DuckDBPyConnection
|
An open DuckDB connection. |
required |
name
|
str
|
UDF name visible in SQL. |
required |
instructions
|
str
|
System prompt for the model. |
required |
response_format
|
type
|
|
str
|
model_name
|
str | None
|
Model or deployment name. Defaults to the
container-registered |
None
|
batch_size
|
int
|
Rows per API batch. Defaults to 64. |
64
|
max_concurrency
|
int
|
Maximum concurrent API requests. Defaults to 8. |
8
|
**api_kwargs
|
Any
|
Extra parameters forwarded to the OpenAI API. |
{}
|
Example
import duckdb from pydantic import BaseModel from openaivec.duckdb_ext import register_responses_udf class Sentiment(BaseModel): ... label: str ... score: float conn = duckdb.connect() register_responses_udf(conn, "sentiment", instructions="Analyze sentiment", response_format=Sentiment)
conn.sql("SELECT sentiment(text).label, sentiment(text).score FROM docs")¶
Source code in src/openaivec/duckdb_ext.py
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | |
register_embeddings_udf ¶
register_embeddings_udf(
conn: DuckDBPyConnection,
name: str,
*,
model_name: str | None = None,
batch_size: int = 128,
max_concurrency: int = 8,
**api_kwargs: Any,
) -> None
Register a DuckDB Arrow-based UDF that returns embedding vectors.
The UDF processes rows in vectorized batches via AsyncBatchEmbeddings,
leveraging deduplication and concurrency for throughput.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
conn
|
DuckDBPyConnection
|
An open DuckDB connection. |
required |
name
|
str
|
UDF name visible in SQL. |
required |
model_name
|
str | None
|
Embeddings model or deployment name. |
None
|
batch_size
|
int
|
Rows per API batch. Defaults to 128. |
128
|
max_concurrency
|
int
|
Maximum concurrent API requests. Defaults to 8. |
8
|
**api_kwargs
|
Any
|
Extra parameters forwarded to the OpenAI API. |
{}
|
Example
import duckdb from openaivec.duckdb_ext import register_embeddings_udf conn = duckdb.connect() register_embeddings_udf(conn, "embed")
conn.sql("SELECT embed(text) FROM docs")¶
Source code in src/openaivec/duckdb_ext.py
register_task_udf ¶
register_task_udf(
conn: DuckDBPyConnection,
name: str,
*,
task: PreparedTask[ResponseFormat],
model_name: str | None = None,
batch_size: int = 64,
max_concurrency: int = 8,
**api_kwargs: Any,
) -> None
Register a DuckDB UDF backed by a PreparedTask.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
conn
|
DuckDBPyConnection
|
An open DuckDB connection. |
required |
name
|
str
|
UDF name visible in SQL. |
required |
task
|
PreparedTask
|
Pre-configured task with instructions and response format. |
required |
model_name
|
str | None
|
Model or deployment name. |
None
|
batch_size
|
int
|
Rows per API batch. Defaults to 64. |
64
|
max_concurrency
|
int
|
Maximum concurrent API requests. Defaults to 8. |
8
|
**api_kwargs
|
Any
|
Extra parameters forwarded to the OpenAI API. |
{}
|
Source code in src/openaivec/duckdb_ext.py
similarity_search ¶
similarity_search(
conn: DuckDBPyConnection,
target_table: str,
query_table: str,
*,
target_column: str = "embedding",
query_column: str = "embedding",
target_text_column: str = "text",
query_text_column: str = "text",
top_k: int = 10,
) -> duckdb.DuckDBPyRelation
Perform top-k cosine similarity search between two DuckDB tables.
Uses DuckDB's built-in list_cosine_similarity for efficient
vector comparison without leaving SQL.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
conn
|
DuckDBPyConnection
|
An open DuckDB connection. |
required |
target_table
|
str
|
Table containing candidate embeddings. |
required |
query_table
|
str
|
Table containing query embeddings. |
required |
target_column
|
str
|
Embedding column in target_table. |
'embedding'
|
query_column
|
str
|
Embedding column in query_table. |
'embedding'
|
target_text_column
|
str
|
Text identifier column in target_table. |
'text'
|
query_text_column
|
str
|
Text identifier column in query_table. |
'text'
|
top_k
|
int
|
Number of results per query. |
10
|
Returns:
| Type | Description |
|---|---|
DuckDBPyRelation
|
duckdb.DuckDBPyRelation: A DuckDB relation with columns |
DuckDBPyRelation
|
|
Example
import duckdb from openaivec.duckdb_ext import similarity_search conn = duckdb.connect()
(after populating docs and queries tables with embeddings)¶
results = similarity_search(conn, "docs", "queries", top_k=5) results.df()
Source code in src/openaivec/duckdb_ext.py
pydantic_to_duckdb_ddl ¶
Generate a CREATE TABLE DDL statement from a Pydantic model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
type[BaseModel]
|
The Pydantic model class. |
required |
table_name
|
str
|
Name for the DuckDB table. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
A |
Example
from pydantic import BaseModel from openaivec.duckdb_ext import pydantic_to_duckdb_ddl class Review(BaseModel): ... sentiment: str ... rating: int ... tags: list[str] print(pydantic_to_duckdb_ddl(Review, "reviews")) CREATE TABLE IF NOT EXISTS reviews ( sentiment VARCHAR, rating INTEGER, tags VARCHAR[] )