LLM UDF extension for DuckDB (Python interface)
Project description
DuckDB LLM UDF
Query your database in plain English—no SQL required. DuckDB LLM UDF translates natural language to SQL using large language models like OpenAI GPT-4 and Anthropic Claude.
✨ Overview
DuckDB LLM UDF bridges the gap between natural language and database queries. It's perfect for:
- Data analysts who need quick answers without writing complex SQL
- Application developers looking to add natural language query capabilities
- SQL learners who want to see how their questions translate to SQL
- DuckDB users who want to leverage the power of modern LLMs
This Python-based extension creates User-Defined Functions (UDFs) that let you query your database in plain English:
- 📚 Schema Analysis: Automatically extracts your database schema metadata
- 🤖 LLM Integration: Sends properly formatted prompts to OpenAI or Anthropic
- 🔍 SQL Generation: Converts natural language to accurate SQL
- ✅ Safety First: Asks for confirmation before executing any generated SQL
- 📊 Results Delivery: Returns query results in standard DuckDB format
🚀 Demo
Here's a screenshot of DuckDB LLM UDF in action:
🚀 Installation
Core features only:
pip install duckdb-llm-udf
With OpenAI support:
pip install duckdb-llm-udf[openai]
With Anthropic support:
pip install duckdb-llm-udf[anthropic]
With all providers:
pip install duckdb-llm-udf[all]
Or install from source:
git clone https://github.com/SQLxAI/duckdb-llm-udf.git
cd duckdb_llm_udf
pip install -e .
Dependencies
The package will automatically install the required dependencies:
- DuckDB ≥ 0.8.0
- python-dotenv ≥ 0.19.0 (for .env file support)
- numpy ≥ 1.21.0 (required for DuckDB UDFs)
Optional dependencies (installed with extras):
- OpenAI: for GPT model integration
- Anthropic: for Claude model integration
To use OpenAI or Anthropic, install the corresponding extra as shown above.
🔍 Usage
Python API
import os
from dotenv import load_dotenv
import duckdb
from duckdb_llm_udf import register_llm_functions
# Sample database creation for demonstration
def create_sample_database(conn):
...
# Usage example
if __name__ == "__main__":
# Load .env file from current working directory
load_dotenv()
conn = duckdb.connect()
register_llm_functions(conn)
create_sample_database(conn)
# Set API key in DuckDB (required for LLM queries)
api_key = os.environ.get('OPENAI_API_KEY', '')
if not api_key:
print("Warning: No OpenAI API key found. Please set the OPENAI_API_KEY environment variable.")
print("Alternatively, you can set it with: conn.execute(\"SELECT llm_configure('api_key', 'your-api-key')\")")
else:
conn.execute(f"SELECT llm_configure('api_key', '{api_key}')")
# Ask a question in natural language
query = "Show me the top 5 customers by total order amount"
# Option 1: Generate SQL without executing (for review)
sql = conn.execute(f"SELECT ask_llm('{query}', 'execute', 'false')").fetchone()[0]
print(f"Generated SQL:\n{sql}")
# Option 2: Execute directly with user confirmation
result = conn.execute(f"SELECT ask_llm('{query}')").fetchall()
print(result)
# Direct Python function usage
from duckdb_llm_udf.llm_udf import ask_llm
result = conn.execute(f"SELECT ask_llm('{query}')").fetchall()
print(result)
# Direct Python function usage
from duckdb_llm_udf.llm_udf import ask_llm
# Generate SQL without executing
sql = ask_llm(query, conn, execute=False)
print(f"Generated SQL:\n{sql}")
# Execute with confirmation
results = ask_llm(query, conn)
print(results)
⚙️ Configuration
You can configure DuckDB LLM UDF in three ways:
1. Environment Variables
# API Keys (required for corresponding provider)
OPENAI_API_KEY=sk-your-openai-key-here
ANTHROPIC_API_KEY=sk-ant-your-anthropic-key-here
# Configuration (all optional)
LLM_PROVIDER=openai # Default: "openai", Alternatives: "anthropic"
LLM_MODEL=gpt-4o # Default: "gpt-3.5-turbo" or "claude-3-sonnet-20240229"
LLM_TEMPERATURE=0.7 # Controls randomness (0.0-1.0)
LLM_MAX_TOKENS=4096 # Maximum tokens for LLM response
2. .env File (recommended for security)
Create a .env file in your project with the same variables as above:
# API Keys
OPENAI_API_KEY=sk-your-openai-key-here
# Configuration
LLM_PROVIDER=openai
LLM_MODEL=gpt-4o
LLM_TEMPERATURE=0.3
Variables will automatically load when the package is imported. See examples/.env.example for a template.
3. Runtime Configuration
Python interface:
conn.execute("SELECT llm_configure('api_key', 'your-api-key')")
conn.execute("SELECT llm_configure('model', 'gpt-4-turbo')")
🧪 Examples
The examples/ directory contains ready-to-use examples:
basic_usage.py- Core functionality demonstrationdotenv_usage.py- Using environment variables with a .env filetest_extraction.py- Test schema extraction without LLM API calls
Example Questions
Here are some example questions you can ask your database:
- "Show me the top 5 customers by total order amount"
- "How many orders were placed in each month of 2023?"
- "What's the average order value by product category?"
- "Find customers who haven't made a purchase in the last 30 days"
- "What product has generated the most revenue?"
🔧 How It Works
Security & Safety
- Use
execute=Falseto preview generated SQL before running it. - Always validate output SQL in production contexts to prevent malformed or dangerous queries.
- LLM prompts are sent to the providers you configure (OpenAI/Anthropic).
-
Schema Analysis: When you call
ask_llm(), the function extracts your database schema metadata (tables, columns, types, foreign keys, etc.) -
Prompt Engineering: Your natural language question is combined with the schema into a carefully crafted prompt that helps the LLM understand the context
-
LLM Query: The prompt is sent to the configured LLM (OpenAI or Anthropic) with instructions to generate valid SQL
-
SQL Generation: The LLM produces SQL based on your schema and question
-
Safety Check: The generated SQL is presented to you for review and confirmation
-
Execution: If approved, the SQL is executed and the results are returned in standard DuckDB format
📝 License
This project is licensed under the MIT License - see the LICENSE file for details.
👥 Contributing
Contributions are welcome and appreciated! Here's how you can help:
- 🐛 Report bugs by opening an issue
- 💡 Suggest features or improvements
- 🧪 Improve tests or add new test cases
- 📚 Improve documentation to make it clearer or more complete
- 🧑💻 Submit pull requests with bug fixes or new features
Please see CONTRIBUTING.md for more details.
🙏 Credits
This project was built with:
- DuckDB - The in-process SQL OLAP database management system
- OpenAI API - For GPT model integration
- Anthropic API - For Claude model integration
📨 Contact
If you have any questions or need help, please open an issue on GitHub.
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file duckdb_llm_udf-0.1.3.tar.gz.
File metadata
- Download URL: duckdb_llm_udf-0.1.3.tar.gz
- Upload date:
- Size: 19.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
47938068d47f1ac702ac1aae5a13a580e69f85580e75ba9d9cb601291d0d789c
|
|
| MD5 |
b3fabbd34866f6bca79da80ac10e66f6
|
|
| BLAKE2b-256 |
7df65954c29ea800314634cce37d1b507fd0c52e769faf4ff4d973215018df24
|
File details
Details for the file duckdb_llm_udf-0.1.3-py3-none-any.whl.
File metadata
- Download URL: duckdb_llm_udf-0.1.3-py3-none-any.whl
- Upload date:
- Size: 10.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
667ac9e22e91b336a7c2d9e06e5aa852035a273c2fb349d0d79dde7acc4355c9
|
|
| MD5 |
4b413f68f1609b53c4bf136b818eebd6
|
|
| BLAKE2b-256 |
431d92ae7a6031cf16c09213bd82dd79aefe50081a355515cf7657e9140857a4
|