MODULE 08: CAPSTONE FULL DOCS

Connect Local AI to Enterprise Databases

Complete step-by-step guide to building an AI-powered data summarization endpoint using DreamFactory, stored procedures, and a local or cloud LLM.

~20 min read
Intermediate
Hands-on Tutorial

🎯 Overview

In this tutorial, you'll build a complete AI-powered API endpoint that retrieves data from your enterprise database, sends it to an LLM for processing, and returns an AI-generated summary, all through DreamFactory's secure API layer.

What You'll Build

By the end of this guide, you'll have a working endpoint that:

  • Accepts a record identifier (customer ID, ticket number, order ID, etc.)
  • Retrieves relevant data via a secure stored procedure
  • Sends that data to your AI model with a structured prompt
  • Returns an AI-generated summary in a clean JSON response

Workflow Overview

📥
API Request
Client calls endpoint
🗄️
Stored Procedure
Fetch scoped data
🤖
LLM Processing
Generate summary
📤
JSON Response
Return to client

Real-World Performance

Enterprise teams running this pattern in production report:

Configuration Response Time Notes
GPT-4o mini (cloud) 4-16 seconds Fastest option, requires internet
Llama 3.1 14B (local) ~25-32 seconds On NVIDIA DGX, fully air-gapped
Llama 3.1 120B (local) ~45-60 seconds Higher quality, slower inference
💡

Smaller Models Can Outperform Larger Ones

One enterprise team discovered their 14B parameter model actually produced better summaries than their 120B model. The smaller model focused on language and context without "overthinking." Always benchmark your specific use case.

📋 Prerequisites

Required

DreamFactory 7.x: Self-hosted or cloud instance with admin access
Database: SQL Server, PostgreSQL, MySQL, or any DreamFactory-supported database
AI Model Access: Either a local LLM (Ollama, vLLM, etc.) or cloud API (OpenAI, Anthropic)
Database permissions: Ability to create stored procedures

Recommended Knowledge

  • Basic SQL and stored procedure concepts
  • REST API fundamentals
  • Python basics (for scripted service)
  • JSON structure and manipulation

Time Estimate

Step Time
Database service setup5 min
Create stored procedure10 min
HTTP service for AI5 min
Scripted service (orchestration)15 min
Testing & debugging10 min
Total~45 min
DreamFactory dashboard home page showing API generation options
The DreamFactory dashboard. Click Connect to Database to begin creating your SQL Server API.

🏗️ Architecture

This integration uses three DreamFactory services working together:

Service Overview

Service Type Purpose Example Name
Database Service Connects to your enterprise database and exposes stored procedures MainDatabase
HTTP Service Connects to your AI model's API endpoint LocalAI
Scripted Service Python script that orchestrates the flow between database and AI AISummary

Data Flow Diagram

Architecture Overview
🧑‍💻 Client App 🔐 DreamFactory API 🗄️ Stored Procedure 🤖 Local AI (Ollama) 📄 AI Response

All traffic stays within your network, so no data leaves to external AI providers

Figure 1: High-level architecture showing the data flow from client request to AI-generated response

ℹ️

Why Three Services?

Separating concerns into distinct services provides flexibility. You can swap AI providers, change databases, or modify the orchestration logic independently without affecting other components.

Step 1 Configure Database Service

First, we'll connect DreamFactory to your database. If you already have a database service configured, skip to Step 2.

1.1

Create New Database Service

⏱️ ~3 min
  1. Log into your DreamFactory admin panel
  2. Navigate to ServicesCreate
  3. Select Database → Choose your database type (e.g., SQL Server, PostgreSQL)
  4. Fill in the connection details:
DreamFactory Admin: Create Database Service
① Service Type ② Service Details ③ Service Options ④ Security

Select your database type to get started:

PostgreSQL MySQL ✓ SQL Server Oracle Snowflake MongoDB SQLite

💡 DreamFactory supports 20+ database types. Select yours and click Next

Field Value Notes
Service Name MainDatabase Use a descriptive name
Host your-db-server.local Internal hostname or IP
Port 1433 (SQL Server) Default port for your DB type
Database YourDatabase Target database name
Username df_service_account Service account with proc execute rights
SQL Server service configuration in DreamFactory showing connection details
Example SQL Server connection configuration in DreamFactory showing host, port, database, and active status.
1.2

Test the Connection

⏱️ ~1 min
  1. Click Test Connection to verify connectivity
  2. If successful, click Save
  3. Navigate to API Docs tab to verify the service is accessible
⚠️

Connection Timeout?

If the connection times out, verify: (1) The database server is accessible from the DreamFactory host, (2) Firewall rules allow the connection, (3) The service account has appropriate permissions.

Step 2 Create Stored Procedure

The stored procedure acts as a security contract that defines exactly what data the AI can access. This is critical for compliance and prevents prompt injection attacks from accessing unauthorized data.

2.1

Design the Procedure

⏱️ ~5 min

Before writing SQL, determine:

  • Input parameters: What identifies the record? (ID, username, date range)
  • Output fields: What data does the AI need to generate a useful summary?
  • Security filters: How do you scope data to the requesting user?
🚫

Never Expose Sensitive PII

Do not include SSNs, full credit card numbers, passwords, or other sensitive data in the procedure output. The AI doesn't need this data, and exposing it creates compliance risk.

2.2

Create the Procedure

⏱️ ~5 min

Here's a template stored procedure. Adapt it to your schema:

SQL GetRecordSummaryData.sql
-- Stored Procedure: GetRecordSummaryData
-- Purpose: Retrieve data for AI summarization
-- Security: Returns only approved fields, user-scoped

CREATE PROCEDURE [dbo].[GetRecordSummaryData]
    @RecordId INT,
    @RequestingUser NVARCHAR(100)
AS
BEGIN
    SET NOCOUNT ON;

    -- Verify user has access to this record
    IF NOT EXISTS (
        SELECT 1 FROM Records r
        INNER JOIN UserAccess ua ON r.DepartmentId = ua.DepartmentId
        WHERE r.Id = @RecordId
        AND ua.Username = @RequestingUser
    )
    BEGIN
        RAISERROR('Access denied', 16, 1);
        RETURN;
    END

    -- Return only the fields needed for AI summary
    SELECT
        r.Id,
        r.Title,
        r.Description,
        r.Category,
        r.Status,
        r.CreatedDate,
        r.LastModified,
        -- Aggregate related data
        (
            SELECT COUNT(*)
            FROM Comments c
            WHERE c.RecordId = r.Id
        ) AS CommentCount,
        -- Include recent activity summary
        (
            SELECT TOP 5
                a.ActionType + ': ' + a.Description
            FROM ActivityLog a
            WHERE a.RecordId = r.Id
            ORDER BY a.Timestamp DESC
            FOR JSON PATH
        ) AS RecentActivity
    FROM
        Records r
    WHERE
        r.Id = @RecordId
        AND r.Status != 'Draft'  -- Don't expose drafts
END
2.3

Test via DreamFactory

⏱️ ~2 min
  1. Navigate to API DocsMainDatabase
  2. Find _proc/GetRecordSummaryData
  3. Click Try It Out
  4. Enter test parameters and execute
DreamFactory API Docs: Stored Procedure Test
sqlsrv 2.0 OAS3 ● API status: Healthy
GET/_procList stored procedures
POST/_proc/{procedure_name}Call stored procedure
GET/_tableRetrieve table records
GET/_schemaRetrieve schema resources

💡 Click any endpoint → Try It Out → Enter parameters → Execute to test live

Schema browser showing available tables from the bitcontrol SQL Server database
Once connected, the Schema browser shows all available tables from your SQL Server database.

Step 3 Configure HTTP Service for AI

Next, we'll create an HTTP service that connects to your AI model. This works with local models (Ollama, vLLM, Text Generation WebUI) or cloud APIs (OpenAI, Anthropic).

3.1

Create HTTP Service

⏱️ ~3 min
  1. Navigate to ServicesCreate
  2. Select HTTP Service
  3. Configure based on your AI provider:

For Local LLM (Ollama, vLLM, Web UI):

Field Value
Service Name LocalAI
Base URL http://your-ai-server:11434 (Ollama default)
Headers Content-Type: application/json

For OpenAI:

Field Value
Service Name OpenAI
Base URL https://api.openai.com/v1
Headers Authorization: Bearer {your-api-key}
Content-Type: application/json
⚠️

Critical: Set Timeout to 300 Seconds

LLM inference can take 30-180 seconds depending on model size and prompt length. The default 30-second timeout will cause failures. Set your HTTP service timeout to 300 seconds (5 minutes).

3.2

Test the AI Connection

⏱️ ~2 min

Verify connectivity with a simple test request:

JSON test-ai-request.json
{
  "model": "llama3.1:14b",
  "messages": [
    {
      "role": "user",
      "content": "Say 'Hello from DreamFactory' and nothing else."
    }
  ],
  "max_tokens": 50
}

Send this to /api/v2/LocalAI/chat/completions (or your service name). You should receive a response within 5-10 seconds for this simple prompt.

Step 4 Create Scripted Service (Orchestration)

The scripted service is the "brain" that ties everything together. It receives the client request, calls the stored procedure, formats the data for the AI, and returns the final response.

4.1

Create the Service

⏱️ ~2 min
  1. Navigate to ServicesCreate
  2. Select ScriptPython3
  3. Name it AISummary
  4. Leave default settings and click Save
4.2

Write the Orchestration Script

⏱️ ~10 min

Navigate to the service's Scripts tab and add this code:

Python AISummary.script.py
# AISummary Scripted Service
# Orchestrates data retrieval and AI summarization

import json
import urllib.request
import urllib.error

# ─── CONFIGURATION ──────────────────────────────────
BASE_URL = "http://localhost"  # Internal DF URL
API_KEY = event.request.headers.get("X-DreamFactory-Api-Key", "")
AI_MODEL = "llama3.1:14b"  # Or "gpt-4o-mini" for OpenAI

# ─── HELPER FUNCTION ────────────────────────────────
def internal_request(method, url, payload=None, timeout=300):
    """Make internal DreamFactory API call"""
    headers = {
        "X-DreamFactory-Api-Key": API_KEY,
        "Content-Type": "application/json"
    }

    data = json.dumps(payload).encode('utf-8') if payload else None
    req = urllib.request.Request(url, data=data, headers=headers, method=method)

    try:
        with urllib.request.urlopen(req, timeout=timeout) as response:
            return json.loads(response.read().decode('utf-8'))
    except urllib.error.HTTPError as e:
        return {"error": f"HTTP {e.code}: {e.reason}"}
    except Exception as e:
        return {"error": str(e)}

# ─── MAIN LOGIC ─────────────────────────────────────

# 1. Extract request parameters
record_id = event.request.parameters.get("record_id")
requesting_user = event.request.parameters.get("user", "anonymous")

if not record_id:
    raise ValueError("Missing required parameter: record_id")

# 2. Call stored procedure to get data
proc_url = f"{BASE_URL}/api/v2/MainDatabase/_proc/GetRecordSummaryData"
proc_payload = {
    "params": [
        {"name": "RecordId", "value": record_id},
        {"name": "RequestingUser", "value": requesting_user}
    ]
}

proc_result = internal_request("POST", proc_url, proc_payload, timeout=30)

if "error" in proc_result:
    raise Exception(f"Database error: {proc_result['error']}")

if not proc_result or not proc_result.get("resource"):
    raise ValueError("No data found for the specified record")

record_data = proc_result["resource"][0]

# 3. Format prompt for AI
system_prompt = """You are a professional analyst. Summarize the provided data
concisely and highlight key insights. Use bullet points for clarity.
Keep the summary under 200 words."""

user_prompt = f"""Please summarize the following record:

Title: {record_data.get('Title', 'N/A')}
Category: {record_data.get('Category', 'N/A')}
Status: {record_data.get('Status', 'N/A')}
Created: {record_data.get('CreatedDate', 'N/A')}
Description: {record_data.get('Description', 'N/A')}
Comment Count: {record_data.get('CommentCount', 0)}
Recent Activity: {record_data.get('RecentActivity', 'None')}

Provide a concise summary with key insights."""

# 4. Call AI model
ai_url = f"{BASE_URL}/api/v2/LocalAI/chat/completions"
ai_payload = {
    "model": AI_MODEL,
    "messages": [
        {"role": "system", "content": system_prompt},
        {"role": "user", "content": user_prompt}
    ],
    "max_tokens": 500,
    "temperature": 0.3  # Lower = more deterministic
}

ai_result = internal_request("POST", ai_url, ai_payload, timeout=300)

if "error" in ai_result:
    raise Exception(f"AI error: {ai_result['error']}")

# 5. Extract and return summary
summary = ai_result.get("choices", [{}])[0].get("message", {}).get("content", "")

return {
    "record_id": record_id,
    "title": record_data.get("Title"),
    "summary": summary.strip(),
    "model_used": AI_MODEL,
    "generated_at": __import__("datetime").datetime.utcnow().isoformat() + "Z"
}
ℹ️

Why urllib instead of requests?

DreamFactory's Python scripting environment includes urllib by default. Using it with explicit timeouts avoids worker pool deadlock issues that can occur when calling other DF endpoints internally.

Step 5 Testing Your Integration

5.1

Test via API Docs

⏱️ ~5 min
  1. Navigate to API DocsAISummary
  2. Find the GET endpoint
  3. Add parameters: record_id=123 and user=testuser
  4. Click Execute

Expected response (after 15-30 seconds):

JSON successful-response.json
{
  "record_id": "123",
  "title": "Q4 Sales Report",
  "summary": "**Key Insights:**\n• Record is currently Active with 12 comments\n• Created in Q4 2024, last modified recently\n• High engagement indicated by comment volume\n• Recent activity shows review and approval workflow\n\n**Recommendation:** This record appears to be progressing through standard approval process with healthy stakeholder engagement.",
  "model_used": "llama3.1:14b",
  "generated_at": "2026-02-05T14:32:18Z"
}
5.2

Test via cURL

⏱️ ~2 min
Bash
curl -X GET \
  "https://your-dreamfactory.com/api/v2/AISummary?record_id=123&user=testuser" \
  -H "X-DreamFactory-Api-Key: YOUR_API_KEY" \
  -H "Accept: application/json"

🔧 Troubleshooting

Common Issues and Solutions

504 Gateway Timeout

Cause: AI inference took longer than the configured timeout.

Fix: Increase HTTP service timeout to 300 seconds. Also check if your AI model is properly loaded in memory.

500 Internal Server Error on Script

Cause: Python script error, often JSON parsing or missing fields.

Fix: Check DreamFactory logs at /opt/dreamfactory/storage/logs/. Add try/except blocks around each step to isolate the issue.

400 Bad Request: Unknown Parameter

Cause: Parameter name mismatch between local and cloud AI providers.

Fix: Don't include business parameters (like username) in the AI payload. Keep AI requests clean, with only model, messages, max_tokens, etc.

Empty AI Response

Cause: Model not loaded, or response parsing issue.

Fix: Test the AI endpoint directly first. Verify the response structure matches what your script expects (choices[0].message.content).

Performance Optimization

Response Time Targets

Component Target If Slower, Check...
Stored Procedure < 500ms Missing indexes, complex joins
AI Inference (14B local) 15-30s GPU memory, model loading
AI Inference (cloud) 10-20s Network latency, rate limits
Total End-to-End 20-45s All of the above

Optimization Strategies

  • Reduce prompt size: Only include essential data in the AI prompt
  • Use smaller models: 14B often outperforms 120B for summarization tasks
  • Pre-warm models: Keep frequently used models loaded in GPU memory
  • Cache common queries: Consider caching AI responses for frequently accessed records
  • Batch processing: For bulk operations, process records in parallel

🔒 Security Considerations

Key Security Principles

Stored procedures as security contracts: AI can only access pre-defined, audited queries
User-scoped data access: Always filter data by the requesting user's permissions
No raw SQL from AI: Never let LLMs generate or execute SQL directly
Audit trail: DreamFactory logs all API calls for compliance
Local AI for sensitive data: Keep confidential data on-premise with local LLMs

Compliance Ready

This pattern supports HIPAA, GDPR, FedRAMP, and SOC 2 requirements because: exact queries are reviewed before deployment, complete audit trails exist, AI cannot access unauthorized data, and data minimization is enforced by design.