prompt-to-query
v1.0.19
Published
High-performance SDK to convert natural language prompts to MongoDB queries using AI (OpenAI GPT or Anthropic Claude)
Maintainers
Readme
Prompt to Query - JavaScript/Node.js SDK
SDK de alto rendimiento para convertir lenguaje natural en queries de MongoDB usando IA (OpenAI GPT o Anthropic Claude).
Características
- Alto Rendimiento: Core nativo en Go para máxima velocidad
- Multiplataforma: Soporta Linux, macOS y Windows (AMD64 y ARM64)
- Múltiples LLMs: Compatible con OpenAI (GPT-4, GPT-3.5) y Anthropic (Claude)
- Type-Safe: Incluye definiciones TypeScript
- Conversión Automática de Fechas: Convierte automáticamente fechas Extended JSON a objetos Date nativos
- Detección de Columnas: Genera automáticamente títulos legibles para las columnas de resultados
- Sugerencias Inteligentes: Análisis de queries con recomendaciones basadas exclusivamente en tu esquema de base de datos
- Optimización de Prompts: Mejora tus consultas en lenguaje natural con sugerencias contextuales
- Fácil de Usar: API simple y consistente
Instalación
npm install prompt-to-query
# o
yarn add prompt-to-queryRequisitos
- Node.js >= 14.0.0 (recomendado >= 16.0.0)
- Una API key de OpenAI o Anthropic
- Las librerías nativas se incluyen para las siguientes plataformas:
- Linux (AMD64, ARM64) - glibc y musl (Alpine)
- macOS (AMD64/Intel, ARM64/Apple Silicon)
- Windows (AMD64, ARM64)
Nota técnica: Este paquete usa koffi para FFI (Foreign Function Interface), una librería moderna compatible con Node.js 14-22+.
Uso Rápido
JavaScript
const { PromptToQuery } = require('prompt-to-query');
async function main() {
// Inicializar el SDK
const ptq = new PromptToQuery({
llmProvider: 'openai', // o 'anthropic'
apiKey: process.env.OPENAI_API_KEY,
dbSchemaPath: './schema.json'
});
// Generar query desde lenguaje natural
const result = await ptq.generateQuery('Get all active users from last month');
console.log('Query:', result.query);
// Output: { operation: 'find', collection: 'users', filter: { ... } }
console.log('Column Titles:', result.columnTitles);
// Output: ['User Name', 'Email', 'Status', 'Registration Date']
// Obtener versión del SDK
console.log('SDK Version:', ptq.getVersion());
}
main().catch(console.error);TypeScript
import { PromptToQuery, PromptToQueryError } from 'prompt-to-query';
const ptq = new PromptToQuery({
llmProvider: 'openai',
apiKey: process.env.OPENAI_API_KEY!,
dbSchemaPath: './schema.json'
});
try {
const result = await ptq.generateQuery('Count orders from last week');
console.log('Query:', result.query);
console.log('Columns:', result.columnTitles);
} catch (error) {
if (error instanceof PromptToQueryError) {
console.error('SDK Error:', error.message);
}
}Configuración
Opciones del Constructor
new PromptToQuery({
llmProvider: string, // 'openai' o 'anthropic' (requerido)
apiKey: string, // Tu API key (requerido)
dbSchema?: object, // Esquema de DB como objeto (opcional)
dbSchemaPath?: string, // Path al archivo JSON del esquema (opcional)
model?: string, // Modelo específico a usar (opcional)
libPath?: string // Path personalizado a la librería nativa (opcional)
})Nota: Debes proporcionar o bien dbSchema o bien dbSchemaPath.
Esquema de Base de Datos
Formato Recomendado: TOON
⚠️ Recomendación importante: Para reducir significativamente los costos de tokenización al usar LLMs, te recomendamos usar el formato TOON (Token-Oriented Object Notation) en lugar de JSON para tu esquema de base de datos.
Ventajas del formato TOON:
- 30-60% menos tokens que JSON, lo que reduce directamente los costos de API
- Mantiene la legibilidad humana
- Especialmente eficiente para estructuras uniformes como esquemas de base de datos
- Elimina redundancia en la repetición de claves y puntuación innecesaria
Ejemplo de esquema en formato TOON (schema.toon):
collections[2]{name,fields}:
users,{name:string;email:string;status:string;created_at:date;last_login:date}
products,{name:string;price:number;category:string;stock:number}Comparación con JSON equivalente (schema.json):
{
"users": {
"fields": {
"name": "string",
"email": "string",
"status": "string",
"created_at": "date",
"last_login": "date"
}
},
"products": {
"fields": {
"name": "string",
"price": "number",
"category": "string",
"stock": "number"
}
}
}Ahorro: El formato TOON usa aproximadamente 42% menos tokens en este ejemplo.
Uso con formato TOON
Para usar el formato TOON, simplemente pasa el archivo .toon como string:
const fs = require('fs');
const schema = fs.readFileSync('./schema.toon', 'utf-8');
const ptq = new PromptToQuery({
llmProvider: 'openai',
apiKey: process.env.OPENAI_API_KEY,
dbSchema: schema // Pasa el contenido TOON como string
});También puedes seguir usando JSON si lo prefieres con dbSchemaPath:
const ptq = new PromptToQuery({
llmProvider: 'openai',
apiKey: process.env.OPENAI_API_KEY,
dbSchemaPath: './schema.json'
});API
new PromptToQuery(config)
Crea una nueva instancia del SDK.
Parámetros:
config(Object): Objeto de configuración (ver arriba)
Throws:
PromptToQueryError: Si la inicialización fallaError: Si la configuración es inválida
generateQuery(prompt): Promise<Object>
Genera una query de MongoDB desde un prompt en lenguaje natural.
Parámetros:
prompt(string): Descripción en lenguaje natural de la query deseada
Returns:
Promise<Object>: Objeto con las siguientes propiedades:query: Objeto de query de MongoDB con:operation: "find", "aggregate", o "count"collection: Nombre de la colecciónfilter: Filtro de query (para find/count)pipeline: Pipeline de agregación (para aggregate)projection,sort,limit,skip: Parámetros opcionales
columnTitles: Array de strings con títulos legibles para las columnas
Throws:
PromptToQueryError: Si la generación de query falla
explainQuery(query): Promise<Object>
Explica qué hace una query de MongoDB en lenguaje natural.
Parámetros:
query(Object): Objeto de query de MongoDB (del resultado degenerateQuery)
Returns:
Promise<Object>: Objeto con las siguientes propiedades:explanation(string): Explicación completa en lenguaje natural de lo que hace la queryoperation(string): Tipo de operación ("find", "aggregate", o "count")targetCollection(string): Colección que se está consultandodataReturned(Array): Campos/datos que serán devueltosfilters(Array): Descripciones de filtros en lenguaje naturalsorting(string): Descripción del ordenamiento (si aplica)limitations(string): Descripción de límites/paginación (si aplica)complexity(string): Complejidad de la query ("low", "medium", "high")estimatedDocuments(string): Estimación de documentos retornados ("1-10", "10-100", "100-1000", "1000+", "all")
Throws:
PromptToQueryError: Si la explicación falla
Ejemplo:
const result = await ptq.generateQuery('Get top 10 products by price');
const explanation = await ptq.explainQuery(result.query);
console.log(explanation.explanation);
// "Esta query recupera los 10 productos principales ordenados por precio en orden descendente"
console.log(explanation.operation); // "find"
console.log(explanation.complexity); // "low"
console.log(explanation.estimatedDocuments); // "1-10"suggestDatabaseImprovements(query): Promise<Object>
Obtiene sugerencias de optimización para la base de datos.
Parámetros:
query(Object): Objeto de query de MongoDB (del resultado degenerateQuery)
Returns:
Promise<Object>: Objeto con las siguientes propiedades:indexRecommendations(Array): Recomendaciones específicas de índices con comandos MongoDBcollection(string): Nombre de la colecciónfields(Array): Campos a indexartype(string): Tipo de índice ("single", "compound", "text", "geo")reason(string): Por qué se necesita este índiceimpact(string): Impacto esperado ("high", "medium", "low")createQuery(string): Comando MongoDB para crear el índice
performanceHints(Array): Sugerencias de optimización de rendimientoschemaOptimizations(Array): Sugerencias de diseño del esquemaqueryOptimization(string): Descripción de enfoques alternativosestimatedImprovement(string): Mejora de rendimiento esperadapriority(string): Nivel de prioridad ("high", "medium", "low")
Throws:
PromptToQueryError: Si el análisis falla
Ejemplo:
const result = await ptq.generateQuery('Get top 10 products by price');
const improvements = await ptq.suggestDatabaseImprovements(result.query);
console.log(improvements.indexRecommendations);
// [{
// collection: "products",
// fields: ["price"],
// type: "single",
// reason: "Query sorts by price field which is currently unindexed",
// impact: "high",
// createQuery: "db.products.createIndex({price: -1})"
// }]
console.log(improvements.estimatedImprovement);
// "10-100x faster for sort operations"
console.log(improvements.priority); // "high"improvePrompt(query, originalPrompt): Promise<Object>
Obtiene sugerencias para mejorar el prompt en lenguaje natural.
Parámetros:
query(Object): Objeto de query de MongoDB (del resultado degenerateQuery)originalPrompt(string): El prompt original en lenguaje natural
Returns:
Promise<Object>: Objeto con las siguientes propiedades:originalPrompt(string): El prompt original del usuarioimprovedPrompt(string): Versión mejorada sugerida del promptambiguities(Array): Ambigüedades detectadasmissingDetails(Array): Detalles que podrían agregarsesuggestions(Array): Sugerencias específicas de mejoraclarityScore(string): Evaluación de claridad ("excellent", "good", "fair", "poor")availableFields(Array): Campos relevantes del esquemaexamplePrompts(Array): Ejemplos de prompts bien escritos
Nota importante: Las sugerencias solo referencian campos que existen en tu esquema de base de datos.
Throws:
PromptToQueryError: Si el análisis falla
Ejemplo:
const result = await ptq.generateQuery('Get products');
const improvement = await ptq.improvePrompt(result.query, 'Get products');
console.log(improvement.improvedPrompt);
// "Get all active products sorted by price in descending order, limited to 10 results"
console.log(improvement.clarityScore); // "poor"
console.log(improvement.suggestions);
// ["Add status filter using 'status' field",
// "Specify time range using 'createdAt' field",
// "Add sort order", "Consider adding a limit"]
console.log(improvement.availableFields);
// ["name", "price", "category", "stock", "status", "createdAt"]getVersion(): string
Obtiene la versión del SDK.
Returns:
string: String de versión
Ejemplos
Ejemplo 1: Query Simple
const result = await ptq.generateQuery('Get all active users');
console.log(result.query);
// { operation: 'find', collection: 'users', filter: { status: 'active' } }
console.log(result.columnTitles);
// ['Name', 'Email', 'Status', 'Created At']Ejemplo 2: Query con Filtros Complejos
const result = await ptq.generateQuery(
'Find products with price greater than 100 dollars'
);
console.log(result.query);
// {
// operation: 'find',
// collection: 'products',
// filter: { price: { $gt: 100 } }
// }
console.log(result.columnTitles);
// ['Product Name', 'Price', 'Category']Ejemplo 3: Query de Agregación
const result = await ptq.generateQuery(
'Get top 10 products by sales with their categories'
);
console.log(result.query);
// {
// operation: 'aggregate',
// collection: 'products',
// pipeline: [
// { $sort: { sales: -1 } },
// { $limit: 10 },
// { $project: { name: 1, sales: 1, category: 1 } }
// ]
// }
console.log(result.columnTitles);
// ['Product Name', 'Sales', 'Category']Ejemplo 4: Query de Conteo
const result = await ptq.generateQuery('Count orders from last month');
console.log(result.query);
// {
// operation: 'count',
// collection: 'orders',
// filter: { created_at: { $gte: ISODate('...') } }
// }
console.log(result.columnTitles);
// ['Total Orders']Ejemplo 5: Explicar Query
const result = await ptq.generateQuery('Get top 10 products by price');
// Obtener explicación de qué hace la query
const explanation = await ptq.explainQuery(result.query);
console.log(explanation.explanation);
// "Esta query recupera los 10 productos principales ordenados por precio en orden descendente"
console.log(explanation.operation); // "find"
console.log(explanation.targetCollection); // "products"
console.log(explanation.complexity); // "low"
console.log(explanation.estimatedDocuments); // "1-10"Ejemplo 6: Optimizar Base de Datos
const result = await ptq.generateQuery('Get top 10 products by price');
// Obtener sugerencias de optimización de base de datos
const improvements = await ptq.suggestDatabaseImprovements(result.query);
console.log(improvements.indexRecommendations);
// [{
// collection: "products",
// fields: ["price"],
// type: "single",
// reason: "Query sorts by price field which is currently unindexed",
// impact: "high",
// createQuery: "db.products.createIndex({price: -1})"
// }]
console.log(improvements.performanceHints);
// ["Add index on price field for faster sorting",
// "Consider adding compound index if filtering by category"]
console.log(improvements.estimatedImprovement);
// "10-100x faster for sort operations"
console.log(improvements.priority); // "high"Ejemplo 7: Mejorar Prompts
const result = await ptq.generateQuery('Get products');
// Obtener sugerencias para mejorar el prompt
const improvement = await ptq.improvePrompt(result.query, 'Get products');
console.log(improvement.improvedPrompt);
// "Get all active products sorted by price in descending order, limited to 10 results"
console.log(improvement.clarityScore); // "poor"
console.log(improvement.ambiguities);
// ["No filter specified - will return all products",
// "No sort order specified",
// "No limit specified - could return too many results"]
console.log(improvement.suggestions);
// ["Add status filter using 'status' field",
// "Specify sort order and direction",
// "Consider adding a limit"]
console.log(improvement.availableFields);
// ["name", "price", "category", "stock", "status", "createdAt"]Ejemplo 8: Queries con Fechas
// El SDK convierte automáticamente fechas Extended JSON a objetos Date nativos
const result = await ptq.generateQuery('Get users created after January 1, 2024');
console.log(result.query);
// {
// operation: 'find',
// collection: 'users',
// filter: {
// created_at: {
// $gte: Date('2024-01-01T00:00:00.000Z') // ✅ Objeto Date nativo
// }
// }
// }
// Listo para usar directamente con MongoDB
const { MongoClient } = require('mongodb');
const client = new MongoClient(process.env.MONGODB_URI);
await client.connect();
const db = client.db('mydb');
// Las fechas ya están convertidas - no se necesita procesamiento adicional
const users = await db.collection(result.query.collection)
.find(result.query.filter)
.toArray();
console.log(`Found ${users.length} users`);💡 Nota: Las fechas se convierten automáticamente en find, aggregate y count queries. También funciona con Mongoose. Ver Manejo Automático de Fechas en ADVANCED.md para más detalles, uso con Mongoose, y función helper completa.
Ejemplo 9: Manejo de Errores
try {
const result = await ptq.generateQuery('invalid query');
console.log(result.query);
console.log(result.columnTitles);
} catch (error) {
if (error instanceof PromptToQueryError) {
console.error('Error del SDK:', error.message);
} else {
console.error('Error inesperado:', error);
}
}Documentación Adicional
Para casos de uso más avanzados, consulta la documentación especializada:
Guía de Docker
Documentación completa para usar el SDK con Docker:
- Configuración con Alpine Linux y Ubuntu/Debian
- Multi-stage builds para optimizar tamaño de imagen
- Docker Compose con MongoDB
- Kubernetes deployments
- CI/CD con GitHub Actions
- Seguridad y best practices
Características Avanzadas
Funcionalidades avanzadas y optimización:
- Detección automática de columnas
- Uso del esquema como objeto
- Configuración de librería nativa personalizada
- Benchmarking y optimización de rendimiento
- Manejo avanzado de errores (retry, circuit breaker)
- Integración con TypeScript
- Caché y patrones singleton
- Debugging y logging
Proveedores LLM
OpenAI
const ptq = new PromptToQuery({
llmProvider: 'openai',
apiKey: process.env.OPENAI_API_KEY,
model: 'gpt-4o', // opcional, por defecto: gpt-4-turbo-preview
dbSchemaPath: './schema.json'
});Modelos soportados:
gpt-4o(recomendado - más rápido y económico)gpt-4o-mini(más económico para tareas simples)gpt-4-turbo-preview(por defecto)gpt-4-turbogpt-4gpt-3.5-turbo
Anthropic Claude
const ptq = new PromptToQuery({
llmProvider: 'anthropic',
apiKey: process.env.ANTHROPIC_API_KEY,
model: 'claude-3-5-sonnet-20241022', // opcional, por defecto: claude-3-sonnet-20240229
dbSchemaPath: './schema.json'
});Modelos soportados:
claude-3-5-sonnet-20241022(recomendado - Claude 3.5 Sonnet más reciente)claude-3-5-sonnet-20240620(Claude 3.5 Sonnet primera versión)claude-3-opus-20240229(más potente pero más costoso)claude-3-sonnet-20240229(por defecto - buen balance)claude-3-haiku-20240307(más rápido y económico)
Solución de Problemas
Error: "Library not found"
Si ves este error, significa que la librería nativa no se encuentra. Soluciones:
- Verifica que tu plataforma sea compatible
- Reinstala el paquete:
npm install --force prompt-to-query - Especifica un path personalizado:
const ptq = new PromptToQuery({
llmProvider: 'openai',
apiKey: 'your-key',
dbSchemaPath: './schema.json',
libPath: '/path/to/libprompttoquery.so'
});Error: "Initialization failed"
Verifica:
- Que tu API key sea válida
- Que el archivo de esquema exista y sea JSON válido
- Que el provider sea 'openai' o 'anthropic'
Error de Compilación en Node.js 20+
Si experimentas errores de compilación con versiones anteriores que usaban ffi-napi, el paquete ahora usa koffi que es:
- Compatible con Node.js 14-22+
- No requiere compilación nativa compleja
- Más rápido y moderno
- Mejor mantenido
Error: "CMake does not seem to be available" (Docker/Alpine)
Solución: Instala las dependencias de compilación antes de npm install:
Alpine:
apk add --no-cache python3 make g++ cmake linux-headersUbuntu/Debian:
apt-get install -y python3 make g++ cmakemacOS:
brew install cmakeLuego reconstruye:
npm rebuild koffiCaracterísticas Avanzadas
Detección Automática de Columnas
El SDK incluye detección inteligente de columnas que genera títulos legibles para los resultados:
const result = await ptq.generateQuery('Show me user names and emails');
// La query incluye solo los campos necesarios
console.log(result.query);
// {
// operation: 'find',
// collection: 'users',
// projection: { name: 1, email: 1 }
// }
// Los títulos son legibles para humanos
console.log(result.columnTitles);
// ['User Name', 'Email']Esto es especialmente útil para:
- Generar tablas dinámicas en interfaces de usuario
- Exportar datos a CSV/Excel con headers apropiados
- Mostrar resultados en dashboards
Uso del Esquema como Objeto
En lugar de un archivo, puedes pasar el esquema directamente:
const schema = {
users: {
fields: {
name: 'string',
email: 'string',
age: 'number'
}
}
};
const ptq = new PromptToQuery({
llmProvider: 'openai',
apiKey: process.env.OPENAI_API_KEY,
dbSchema: schema // En lugar de dbSchemaPath
});Rendimiento
- Modo Nativo: Usa FFI para llamar directamente a la librería Go compilada (más rápido)
- Detección Alpine: Automática con fallback a diferentes versiones de libc
- Caché: El SDK mantiene el estado internamente para llamadas subsecuentes más rápidas
Seguridad
- Nunca incluyas API keys en el código o control de versiones
- Usa variables de entorno (
process.env) para credenciales - El SDK valida todas las queries generadas antes de retornarlas
- No ejecuta queries automáticamente - siempre tienes control
Plataformas Soportadas
| OS | AMD64 | ARM64 | Alpine (musl) | |----|-------|-------|---------------| | Linux | ✅ | ✅ | ✅ | | macOS | ✅ | ✅ | N/A | | Windows | ✅ | ✅ | N/A |
Licencia
MIT
Soporte
- Issues: GitHub Issues
- Documentación completa: GitHub
- Ejemplos: Ver directorio
examples/
Hecho con ❤️ usando Go + Node.js
