# Cyber-MySQL-OpenAI

**Intelligent natural language to SQL translator for Node.js**

[![npm version](https://img.shields.io/npm/v/cyber-mysql-openai.svg?style=flat-square)](https://www.npmjs.com/package/cyber-mysql-openai)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](https://opensource.org/licenses/MIT)
[![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg?style=flat-square)](https://www.typescriptlang.org/)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/dannyusca/cyber-mysql-openai)

<br />

<div align="center">
  <p>Si esta librería te ahorró horas de desarrollo, considera invitarme un café:</p>
  <a href="https://buymeacoffee.com/dannyusca" target="_blank">
    <img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 50px !important;width: 217px !important;" >
  </a>
</div>

<br />

Cyber-MySQL-OpenAI is a powerful Node.js library that translates natural language queries into valid SQL, executes them against MySQL databases, and returns results accompanied by human-readable explanations — all powered by OpenAI.

[Spanish documentation / Documentación en español](README.es.md)

---

## <img src="https://api.iconify.design/mdi:format-list-bulleted.svg" width="28" height="28" style="vertical-align: middle; margin-right: 8px;" /> Table of Contents

- [Features](#features)
- [Installation](#installation)
- [System Requirements](#system-requirements)
- [Basic Usage](#basic-usage)
- [Intelligence Features (v0.3.0)](#intelligence-features-v030)
- [Token Optimization (v0.3.2)](#token-optimization-v032)
- [Streaming & Agentic Mode (v0.3.4)](#streaming--agentic-mode-v034)
- [Configuration Options](#configuration-options)
- [Cache System](#cache-system)
- [Multi-Language Support](#multi-language-support)
- [API Reference](#api-reference)
- [Troubleshooting](#troubleshooting)
- [Project Status](#project-status)
- [License](#license)

---

## <img src="https://api.iconify.design/mdi:lightning-bolt.svg" width="28" height="28" style="vertical-align: middle; margin-right: 8px;" /> Features

- **Natural language to SQL translation** — Converts plain-text questions into valid SQL queries
- **Automatic execution** — Runs generated queries directly against your MySQL database
- **Self-correcting error handling** — Detects and autonomously corrects failed queries (up to 3 reflection attempts)
- **Natural language explanations** — Translates technical query results into user-friendly responses
- **Structured output with function calling** — Uses OpenAI function calling for predictable JSON responses with automatic text fallback
- **Business context awareness** — Enrich the AI with domain-specific knowledge about your tables and columns
- **Foreign key relationship detection** — Automatically discovers and uses FK relationships for accurate JOINs
- **Few-shot examples** — Provide reference question/SQL pairs to guide the model
- **Confidence scoring** — Each query includes a confidence score indicating how well it answers the question
- **Multi-language support** — English and Spanish with dynamic runtime switching
- **In-memory cache** — Optional high-performance caching layer with variable TTL and automatic cleanup
- **Full TypeScript support** — Complete type definitions for a seamless developer experience
- **Highly configurable** — Adjust logging, caching, language, and model settings to fit your needs
- **Enhanced Intelligence (v0.3.0)** — Improved prompts with SQL optimization rules, aliases, and better disambiguation
- **Custom Instructions** — Inject your own business rules and response styles into the AI
- **Query Validation Layer** — Automatically checks generated SQL for safety, table existence, and cartesian products
- **Schema Caching** — Configurable TTL to reduce database load and improve latency
- **Token Usage Tracking** — Detailed token counts and estimated cost per query
- **Query History** — In-memory log of executed queries with performance statistics
- **Advanced logging** — Structured logging system with token usage tracking and prompt/response audit trails
- **Token Optimization (v0.3.2)** — Compressed schema format, `lightModel` for subtasks, and filtered schema in reflections — **50–70% fewer tokens per request**

---

## <img src="https://api.iconify.design/mdi:download.svg" width="28" height="28" style="vertical-align: middle; margin-right: 8px;" /> Installation

```bash
npm install cyber-mysql-openai
```

---

## <img src="https://api.iconify.design/mdi:cog.svg" width="28" height="28" style="vertical-align: middle; margin-right: 8px;" /> System Requirements

| Requirement  | Details                                              |
| ------------ | ---------------------------------------------------- |
| **Node.js**  | v16.x or higher (developed and tested with v22.15.0) |
| **Database** | MySQL or MariaDB                                     |
| **API Key**  | A valid OpenAI API key                               |

---

## <img src="https://api.iconify.design/mdi:lightbulb-on.svg" width="28" height="28" style="vertical-align: middle; margin-right: 8px;" /> Basic Usage

```typescript
import { CyberMySQLOpenAI } from "cyber-mysql-openai";
import "dotenv/config";

const translator = new CyberMySQLOpenAI({
  database: {
    host: process.env.DB_HOST || "localhost",
    port: 3306,
    user: process.env.DB_USER || "",
    password: process.env.DB_PASSWORD || "",
    database: process.env.DB_DATABASE || "",
    ssl: false,
  },
  openai: {
    apiKey: process.env.OPENAI_API_KEY || "",
    model: "gpt-4",
  },
  language: "en",
});

async function main() {
  try {
    const result = await translator.query(
      "What was the best-selling product last month?",
    );

    console.log("Generated SQL:", result.sql);
    console.log("Results:", result.results);
    console.log("Explanation:", result.naturalResponse);

    await translator.close();
  } catch (error) {
    console.error("Error:", error);
  }
}

main();
```

---

## Intelligence Features

> New in v0.2.0

Cyber-MySQL-OpenAI can be configured with business context to dramatically improve the accuracy and relevance of generated SQL queries.

### Business Context

Provide the AI with domain-specific knowledge about your database:

````typescript
import { CyberMySQLOpenAI, SchemaContext } from "cyber-mysql-openai";

const context: SchemaContext = {
  businessDescription:
    "E-commerce platform for electronic products with orders, customers, and inventory",
  tables: {
    orders: {
      description: "Customer purchase orders with status tracking",
      columns: {
        status: "Order status: 'pending', 'shipped', 'delivered', 'cancelled'",
        total_amount: "Total in USD including taxes and shipping",
      },
    },
    products: {
      description: "Product catalog with pricing and stock levels",
      columns: {
        sku: "Unique product identifier used in warehouse systems",
        price: "Current retail price in USD (before discounts)",
      },
    },
  },
};

const translator = new CyberMySQLOpenAI({
  database: {
    /* ... */
  },
  openai: {
    /* ... */
  },
  context,
});
```

---

## <img src="https://api.iconify.design/mdi:lightbulb.svg" width="28" height="28" style="vertical-align: middle; margin-right: 8px;" /> Intelligence Features (v0.3.0)

### 1. Custom Instructions & Response Style

You can now inject specific business rules and control the personality of the AI:

```typescript
const translator = new CyberMySQLOpenAI({
  // ...
  context: {
    businessDescription: "E-commerce platform",
    // v0.3.0: Custom rules
    customInstructions: [
      "Always exclude soft-deleted records (deleted_at IS NOT NULL)",
      "When asked for 'revenue', use the sum of total_amount from orders table",
    ],
    // v0.3.0: Response style ('concise', 'detailed', 'technical')
    responseStyle: "concise",
  },
});
````

### 2. Query Validation

Every generated query is automatically validated before execution. The system checks for:

- **Dangerous operations**: Only `SELECT` statements are allowed; `UPDATE`, `DROP`, etc., are blocked.
- **Schema validation**: Checks for non-existent tables or columns (best-effort).
- **Cartesian products**: Warns about potential cartesian products due to missing JOIN conditions.
- **Performance checks**: Identifies missing `LIMIT` clauses on potentially large result sets.

### 3. Schema Caching

Reduce latency and database load by caching schema definitions:

```typescript
const translator = new CyberMySQLOpenAI({
  // ...
  schemaTTL: 600000, // Cache schema for 10 minutes (default: 5 min)
});

// Force refresh if schema changes
translator.refreshSchema();
```

### 4. Query History & Stats

Track performance and usage during the session:

```typescript
const stats = translator.getQueryStats();
console.log(stats);
// {
//   totalQueries: 10,
//   successfulQueries: 9,
//   averageExecutionTime: 450ms,
//   totalTokensUsed: 5200
// }

// Get last 5 queries
const history = translator.getQueryHistory(5);
```

### 5. Token Usage & Cost Estimation

Each result now includes detailed token usage and estimated cost:

```typescript
const result = await translator.query("Sales count?");
console.log(result.tokenUsage);
// {
//   promptTokens: 500,
//   completionTokens: 50,
//   totalTokens: 550,
//   estimatedCost: 0.0015 // USD (based on current model pricing)
// }
```

---

### Few-Shot Examples

Guide the model with reference question/SQL pairs specific to your domain:

```typescript
const context: SchemaContext = {
  businessDescription: "E-commerce platform",
  tables: {
    /* ... */
  },
  examples: [
    {
      question: "What are this month's total sales?",
      sql: "SELECT SUM(total_amount) as total_sales FROM orders WHERE MONTH(created_at) = MONTH(CURRENT_DATE()) AND YEAR(created_at) = YEAR(CURRENT_DATE())",
    },
    {
      question: "Which products are low on stock?",
      sql: "SELECT name, stock FROM products WHERE stock < 10 ORDER BY stock ASC",
    },
  ],
};
```

### Foreign Key Relationships

The library automatically detects FK relationships from your database's `information_schema` and includes them in the AI prompt. This enables the model to construct accurate JOINs without you having to describe table relationships manually.

### Function Calling with Fallback

The library uses OpenAI's function calling feature for structured, predictable responses:

- **Primary mode (function calling):** Returns `{ sql, confidence, reasoning }` as structured JSON
- **Fallback mode (text):** If the model does not support function calling, the library automatically falls back to text parsing with `sqlCleaner`

This dual-mode approach ensures compatibility across all OpenAI models (GPT-3.5, GPT-4, GPT-4o, etc.).

### Confidence Score

Every query result includes an optional `confidence` field (0–1) when function calling is available:

```typescript
const result = await translator.query(
  "What are the top 5 products by revenue?",
);

console.log(result.confidence); // 0.95
console.log(result.sql); // SELECT ...
```

Use `confidence` to implement logic like warning users when the model is unsure, or triggering a manual review for low-confidence queries.

---

## <img src="https://api.iconify.design/mdi:flash.svg" width="28" height="28" style="vertical-align: middle; margin-right: 8px;" /> Token Optimization (v0.3.2)

Three built-in optimizations reduce token consumption by 50–70% with zero behavioral changes.

### 1. Compressed Schema Format

The schema sent to OpenAI is now ultra-compact (~20 tokens/table vs ~60 before):

```
# Before
Tabla orders (Customer purchases): id (int, PRIMARY KEY), status (varchar), total_amount (decimal)...

# After
orders: id* status total_amount→customers
```

`*` = PRIMARY KEY, `→table` = FK reference. Business descriptions still appear when configured.

### 2. `lightModel` for Subtasks

Use a cheaper model for reflection and natural language formatting while keeping your main model for SQL generation:

```typescript
const translator = new CyberMySQLOpenAI({
  openai: {
    apiKey: "...",
    model: "gpt-4o", // SQL generation (needs intelligence)
    lightModel: "gpt-4o-mini", // Reflection & formatting (20x cheaper, same quality) (v0.3.2)
  },
});
```

Or via environment variable: `OPENAI_LIGHT_MODEL=gpt-4o-mini`

> **Cost impact**: `gpt-4o-mini` is ~20x cheaper than `gpt-4o`. Since ~40% of calls are subtasks, this alone reduces total cost by ~40–85%.

### 3. Filtered Schema in Reflections

When a query fails and needs correction, only the schema of the **tables used in the failed SQL** is sent to the LLM — not the entire database schema. In a 30-table database, this can reduce the reflection prompt by ~80%.

---

## <img src="https://api.iconify.design/mdi:connection.svg" width="28" height="28" style="vertical-align: middle; margin-right: 8px;" /> Streaming & Agentic Mode (v0.3.4)

This version introduces **real-time response streaming** to reduce perceived user latency to zero, and a **Multi-Step Agentic Mode** designed for complex or massive enterprise databases.

### 1. Response Streaming (Callbacks & Async Generators)

Instead of waiting for the full natural language explanation to be generated, you can consume it chunk-by-chunk.

#### Option A: Streaming Callback (onChunk) - Backward-Compatible
Pass an `onChunk` callback to the options parameter of `query()`:

```typescript
const result = await translator.query(
  "What is the most expensive product?",
  {
    onChunk: (chunk) => {
      process.stdout.write(chunk);
    }
  }
);
```

#### Option B: Async Generator (queryStream)
Use `queryStream()` to get full control over step-by-step agent lifecycle events:

```typescript
const stream = translator.queryStream("List our 5 latest orders");

for await (const chunk of stream) {
  if (chunk.type === "sql") {
    console.log("SQL Generated:", chunk.sql);
  } else if (chunk.type === "results") {
    console.log("Database Results:", chunk.results);
  } else if (chunk.type === "chunk" && chunk.content) {
    process.stdout.write(chunk.content); // Explaining results in real-time
  } else if (chunk.type === "done" && chunk.metadata) {
    console.log("\nFinished execution in", chunk.metadata.executionTime + "ms");
  }
}
```

### 2. Multi-Step Agentic Mode (MCP style)

For large database schemas that exceed model context windows, enable `mode: "agentic"`. Instead of injecting the entire schema at start (One-Shot), the agent uses database inspection tools dynamically:

```typescript
const agent = new CyberMySQLOpenAI({
  database: { ... },
  openai: { apiKey: "..." },
  mode: "agentic" // "direct" (One-Shot) or "agentic" (Multi-Step tool exploration)
});
```

* **Tool Exploration**: The agent sequentially invokes tools (`list_tables`, `describe_table`, `execute_sql_query`) to explore tables and schemas dynamically, then executes queries and explains them.

### 3. Reflection Loop Optimizations

* **Parallel Candidate Testing**: On a SQL execution failure, the reflection loop generates up to 3 candidate SQL statements in a single prompt and executes them in parallel on the database. The first one that runs successfully is chosen, resolving reflection errors in a single LLM roundtrip.
* **Levenshtein Hints**: The library automatically calculates Levenshtein distances on table/column misspellings and injects recommendations (e.g. *"Did you mean 'created_at'?"*) into the error prompt, helping the model correct itself on the first retry.

---

## <img src="https://api.iconify.design/mdi:tune.svg" width="28" height="28" style="vertical-align: middle; margin-right: 8px;" /> Configuration Options

```typescript
const translator = new CyberMySQLOpenAI({
  // Database connection
  database: {
    host: "localhost",
    port: 3306,
    user: "username",
    password: "password",
    database: "my_database",
    ssl: false,
    socketPath: "/path/to/mysql.sock", // Optional
  },

  // OpenAI settings
  openai: {
    apiKey: "your_api_key",
    model: "gpt-4o", // Main model for SQL generation
    lightModel: "gpt-4o-mini", // Optional: cheaper model for reflection & formatting (v0.3.2)
  },

  // Cache settings (optional)
  cache: {
    enabled: true, // Enable/disable cache
    maxSize: 1000, // Maximum number of cache entries
    defaultTTL: 300000, // Default TTL in milliseconds (5 min)
    cleanupInterval: 300000, // Cleanup interval in milliseconds
  },

  // General settings
  maxReflections: 3, // Max correction attempts on SQL errors
  logLevel: "info", // 'error' | 'warn' | 'info' | 'debug' | 'none'
  logDirectory: "./logs", // Directory for log files
  logEnabled: true, // Set to false to disable all logging
  language: "en", // 'en' (English) or 'es' (Spanish)
});
```

---

## <img src="https://api.iconify.design/mdi:database.svg" width="28" height="28" style="vertical-align: middle; margin-right: 8px;" /> Cache System

Cyber-MySQL-OpenAI includes an optional in-memory cache that significantly improves response times for repeated or similar queries.

### How It Works

- **Query normalization** — Queries are normalized before cache lookup to maximize hit rates
- **Variable TTL** — Time-to-live is determined dynamically based on query type:
  - Schema/metadata queries: 1 hour
  - Aggregate queries (COUNT, SUM, AVG, GROUP BY): 15 minutes
  - Simple queries: 5 minutes
- **Automatic cleanup** — Expired entries are periodically removed
- **Performance metrics** — Real-time statistics including hit rate and memory usage

### Basic Cache Usage

```typescript
const translator = new CyberMySQLOpenAI({
  // ... database and OpenAI config
  cache: {
    enabled: true,
    maxSize: 1000,
    defaultTTL: 300000,
    cleanupInterval: 300000,
  },
});

const result1 = await translator.query("Show me all users"); // Hits the database
const result2 = await translator.query("Show me all users"); // Returns from cache

console.log("From cache:", result2.fromCache); // true
console.log("Execution time:", result2.executionTime); // Significantly faster
```

### Cache Management

```typescript
// Retrieve cache performance statistics
const stats = translator.getCacheStats();
console.log("Hit rate:", stats.hitRate);
console.log("Entries:", stats.totalEntries);

// Clear all cached entries
translator.clearCache();

// Toggle cache at runtime
translator.disableCache();
translator.enableCache();
console.log("Cache active:", translator.isCacheEnabled());
```

### Best Practices for API Integration

Use a shared global instance to maximize cache effectiveness across requests:

```typescript
// api-instance.ts
import { CyberMySQLOpenAI } from "cyber-mysql-openai";

export const translator = new CyberMySQLOpenAI({
  // ... configuration
  cache: { enabled: true, maxSize: 2000 },
});

// api-routes.ts
import { translator } from "./api-instance";

app.get("/query", async (req, res) => {
  const result = await translator.query(req.body.question);
  res.json({
    ...result,
    cached: result.fromCache,
    responseTime: result.executionTime,
  });
});
```

> **Note:** The cache is shared across all requests and users. For user-specific data, implement appropriate cache invalidation strategies.

For additional examples, see [docs/cache-examples.md](docs/cache-examples.md).

---

## <img src="https://api.iconify.design/mdi:translate.svg" width="28" height="28" style="vertical-align: middle; margin-right: 8px;" /> Multi-Language Support

The library supports English and Spanish for all responses, error messages, and OpenAI prompts. The language can be configured at initialization or changed dynamically at runtime.

### Configuration

```typescript
// Set during initialization
const translator = new CyberMySQLOpenAI({
  // ... other configuration
  language: "en", // 'en' for English, 'es' for Spanish
});

// Change at runtime
translator.setLanguage("es");
console.log("Current language:", translator.getLanguage());
```

### What Gets Localized

- Error messages
- Prompts sent to OpenAI
- Natural language explanations
- Interface labels and status text

### Example: Dynamic Switching

```typescript
translator.setLanguage("en");
const english = await translator.query("What are the top 5 products?");
console.log(english.naturalResponse); // Response in English

translator.setLanguage("es");
const spanish = await translator.query(
  "¿Cuáles son los 5 productos principales?",
);
console.log(spanish.naturalResponse); // Response in Spanish
```

---

## <img src="https://api.iconify.design/mdi:book-open.svg" width="28" height="28" style="vertical-align: middle; margin-right: 8px;" /> API Reference

### CyberMySQLOpenAI

| Method                      | Description                                                                      |
| --------------------------- | -------------------------------------------------------------------------------- |
| `constructor(config)`       | Creates a new instance with the provided configuration                           |
| `query(prompt, options?)`   | Translates a natural language prompt to SQL, executes it, and returns the result |
| `executeSQL(sql, options?)` | Executes a raw SQL query directly (no translation)                               |
| `close()`                   | Closes all database connections                                                  |
| `setLanguage(lang)`         | Sets the response language (`'en'` or `'es'`)                                    |
| `getLanguage()`             | Returns the current language setting                                             |

### Cache Methods

| Method                              | Description                                                    |
| ----------------------------------- | -------------------------------------------------------------- |
| `getCacheStats()`                   | Returns cache statistics (hit rate, memory usage, entry count) |
| `clearCache()`                      | Removes all cached entries                                     |
| `enableCache()`                     | Enables the cache system                                       |
| `disableCache()`                    | Disables the cache system                                      |
| `isCacheEnabled()`                  | Returns whether the cache is currently active                  |
| `invalidateCacheByTable(tableName)` | Removes cached entries related to a specific table             |

### Query Options

```typescript
const result = await translator.query(
  "What was the month with highest sales?",
  {
    detailed: true, // Request a detailed analytical response
    bypassCache: true, // Skip cache and force a fresh query
  },
);

console.log("Simple response:", result.naturalResponse);
console.log("Detailed response:", result.detailedResponse);
```

### Response Types

**TranslationResult** (returned by `query`):

| Field              | Type           | Description                                                   |
| ------------------ | -------------- | ------------------------------------------------------------- |
| `sql`              | `string`       | The generated SQL query                                       |
| `results`          | `any[]`        | Query results from the database                               |
| `reflections`      | `Reflection[]` | Error correction history (if any)                             |
| `attempts`         | `number`       | Total execution attempts                                      |
| `success`          | `boolean`      | Whether the query succeeded                                   |
| `confidence`       | `number?`      | Confidence score (0–1), available when using function calling |
| `naturalResponse`  | `string`       | Human-readable explanation                                    |
| `detailedResponse` | `string`       | Detailed analysis (when `detailed: true`)                     |
| `executionTime`    | `number`       | Total execution time in milliseconds                          |
| `fromCache`        | `boolean`      | Whether the result was served from cache                      |

---

## <img src="https://api.iconify.design/mdi:comment-question.svg" width="28" height="28" style="vertical-align: middle; margin-right: 8px;" /> Troubleshooting

### Nodemon Restarts

If Nodemon restarts constantly due to log file generation, add this to your `package.json` or `nodemon.json`:

```json
{
  "nodemonConfig": {
    "ignore": ["*.log", "tmp/*", "logs/*"]
  }
}
```

### Detailed Response Issues

1. Update to the latest version: `npm update cyber-mysql-openai`
2. Verify your OpenAI API key has sufficient credits
3. Reduce log verbosity with `logLevel: 'warn'` or `logLevel: 'error'`

### Log Configuration

```typescript
// Disable all logging
const translator = new CyberMySQLOpenAI({
  logEnabled: false,
});

// Log only errors
const translator = new CyberMySQLOpenAI({
  logLevel: "error",
});
```

---

## <img src="https://api.iconify.design/mdi:information.svg" width="28" height="28" style="vertical-align: middle; margin-right: 8px;" /> Project Status

This project is in **stable release** and under active development. Contributions and feedback are welcome.

### Current Limitations

- Very complex queries may require multiple correction iterations
- Some advanced SQL constructs may not be interpreted correctly
- Performance depends on database schema complexity and OpenAI model latency

### Roadmap

- ~~Business context and schema metadata~~ (shipped in v0.2.0)
- ~~Foreign key relationship detection~~ (shipped in v0.2.0)
- ~~Function calling with structured output~~ (shipped in v0.2.0)
- ~~Few-shot example support~~ (shipped in v0.2.0)
- ~~Custom instructions and response styles~~ (shipped in v0.3.0)
- ~~Query validation layer~~ (shipped in v0.3.0)
- ~~Schema caching with configurable TTL~~ (shipped in v0.3.0)
- ~~Token usage tracking and cost estimation~~ (shipped in v0.3.0)
- ~~Query history and performance stats~~ (shipped in v0.3.0)
- ~~Reflection context injection bugfix~~ (shipped in v0.3.1)
- ~~Compressed schema format (66% fewer tokens)~~ (shipped in v0.3.2)
- ~~`lightModel` for subtasks (85% cheaper reflections)~~ (shipped in v0.3.2)
- ~~Filtered schema in reflections~~ (shipped in v0.3.2)
- Support for additional SQL dialects
- Streaming responses
- Expanded documentation and usage examples

---

## <img src="https://api.iconify.design/mdi:certificate.svg" width="28" height="28" style="vertical-align: middle; margin-right: 8px;" /> License

MIT
