Skip to content

krishkumar/SwiftDBAI

Repository files navigation

SwiftDBAI

A Swift package that adds a natural language query interface to any SQLite database in your iOS, macOS, or visionOS app. Works with GRDB, Core Data, SwiftData, or raw SQLite -- any .sqlite file on the device.

Swift 6.1+ Platforms License

Real-World Demo: NetNewsWire

SwiftDBAI added to NetNewsWire (the open source RSS reader) in one commit. The LLM queries the article database directly -- unread counts, feed rankings, article search. Running Ollama locally, no backend.

iPhone iPad
iPhone iPad

Quick Start

Point it at your database, give it an LLM:

import SwiftDBAI
import AnyLanguageModel

DataChatView(
    databasePath: documentsURL.appendingPathComponent("app.db").path,
    model: OllamaLanguageModel(model: "qwen3-coder")
)

Or pass an existing GRDB connection:

DataChatView(
    database: myDatabasePool,
    model: OpenAILanguageModel(apiKey: key, model: "gpt-4o"),
    allowlist: .readOnly,
    additionalContext: "E-commerce app with orders, products, and customers."
)

Schema introspection is automatic. No annotations, no mapping files. Read-only by default.

Tool Calling

If your app already talks to an LLM, use DatabaseTool to register SwiftDBAI as a tool it can call. Your existing LLM generates SQL, SwiftDBAI validates and executes it.

let tool = try await DatabaseTool(databasePath: myDB)

// Add schema to your system prompt
let systemPrompt = "You are a helpful assistant.\n\n" + tool.systemPromptSnippet

// Register with your LLM
let functionDef = tool.openAIFunctionDefinition

// When the LLM calls the tool
let result = try tool.execute(sql: "SELECT * FROM users WHERE active = 1")
result.jsonString     // return to LLM as tool response
result.markdownTable  // display to user

SQL is validated against a read-only allowlist before execution. INSERT, UPDATE, DELETE, and DROP are rejected.

DatabaseTool API

Headless / Programmatic Use

Use ChatEngine directly when you don't need a UI:

let pool = try DatabasePool(path: myDB)
let engine = ChatEngine(
    database: pool,
    model: OpenAILanguageModel(apiKey: key, model: "gpt-4o")
)

let response = try await engine.send("How many users signed up this week?")
print(response.summary)   // "There were 42 new signups this week."
print(response.sql)        // Optional("SELECT COUNT(*) FROM users WHERE ...")

Installation

dependencies: [
    .package(url: "https://github.com/krishkumar/SwiftDBAI.git", from: "1.0.0"),
]

Presentation

Works in every context: sheets, full-screen covers, navigation pushes, UIKit modals.

Custom theme Sheet presentation
Custom theme Sheet presentation
// Sheet with nav bar and Done button
.dataChatSheet(isPresented: $showChat, databasePath: path, model: myLLM)

// Full-screen cover
.dataChatFullScreen(isPresented: $showChat, databasePath: path, model: myLLM)

// UIKit
let vc = DataChatViewController(databasePath: path, model: myLLM)
present(vc, animated: true)

See THEMING.md for customization -- colors, fonts, dark mode, compact mode, assistant avatars.

Features

  • Drop-in SwiftUI chat view (DataChatView) or headless ChatEngine
  • LLM-agnostic via AnyLanguageModel -- OpenAI, Anthropic, Gemini, Ollama, llama.cpp, or any OpenAI-compatible endpoint
  • DatabaseTool for integrating into your existing LLM tool calling setup
  • Automatic schema introspection -- no manual annotations
  • Safety-first: read-only by default, operation allowlists, table-level mutation policies
  • Auto-generated bar charts, pie charts, and data tables
  • Structured output via @Generable for models that support it
  • 448 tests

Choosing a Provider

// Cloud
ProviderConfiguration.openAI(apiKey: "sk-...", model: "gpt-4o")
ProviderConfiguration.anthropic(apiKey: "sk-ant-...", model: "claude-sonnet-4-20250514")

// Local -- data stays on device
ProviderConfiguration.ollama(model: "llama3.2")
ProviderConfiguration.llamaCpp(model: "default")

// Any OpenAI-compatible endpoint
ProviderConfiguration.openAICompatible(apiKey: "key", model: "llama-3.1-70b", baseURL: url)

Safety

Preset Allowed
.readOnly (default) SELECT
.standard SELECT, INSERT, UPDATE
.unrestricted SELECT, INSERT, UPDATE, DELETE

Per-table control via MutationPolicy. Destructive operations require confirmation through ToolExecutionDelegate.

Architecture

User Question
    |
    v
ChatEngine
    |-- SchemaIntrospector   (auto-discovers tables, columns, keys, indexes)
    |-- PromptBuilder        (builds LLM system prompt with schema context)
    |-- LanguageModel        (generates SQL via AnyLanguageModel)
    |-- SQLQueryParser       (parses and validates against allowlist/policy)
    |-- GRDB                 (executes SQL against SQLite)
    |-- TextSummaryRenderer  (summarizes results via LLM)
    v
ChatResponse { summary, sql, queryResult }

Demo App

The demo app is at Example/SwiftDBAIDemo/. It includes a showcase of all themes and presentation modes. Generate the Xcode project with xcodegen:

cd Example/SwiftDBAIDemo && xcodegen generate

Requirements

  • iOS 17.0+ / macOS 14.0+ / visionOS 1.0+
  • Swift 6.1+
  • Xcode 16+

License

MIT. See LICENSE for details.

About

Add natural language database queries to any iOS app. One SwiftUI view, any LLM, any SQLite database.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages