|
1 2 3 4 5 6 7 8 |
SELECT u.nombre, CONTAR(o.identificación) CO total_de_pedidos DE `comercio`.Ventas.usuarios CO u ÚNETE `comercio`.Ventas.pedidos CO o Activado u.identificación = o.ID de usuario DÓNDE o.estado = “completado” Y DIF_FECHA_STR(AHORA_STR(), o.fecha_del_pedido, “día”) <= 30 GRUPO POR u.nombre PEDIDO POR total_de_pedidos DESC LÍMITE 5; |
La consulta anterior proporciona información valiosa de sus datos almacenados en Couchbase sobre sus cinco principales usuarios que generaron la mayor cantidad de pedidos completados en los últimos 30 días. Pero, ¿qué pasa si usted no es un desarrollador avanzado de SQL++ y necesita las respuestas antes de las 11 p. m. para un informe? Entonces tendrá que esperar a que un desarrollador escriba una consulta SQL++ y le proporcione las respuestas.
Alternativamente, considere un caso en el que necesite realizar alguna depuración ad hoc para abordar preguntas como:
- ¿Hay algún documento en el que falte la fecha en que se entregó el pedido?
- ¿Significa eso que se canceló el pedido? ¿O extraviamos el pedido y este nunca se entregó? ¿O estuvo todo bien, pero simplemente omitimos agregar el valor order_delivered en el campo?
En este caso, no solo necesitas buscar en el campo order_delivered, sino también revisar order_cancelled o investigar los comentarios para averiguar si se extravió, etc. Por lo tanto, la consulta que se debe escribir no es simple ni directa.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
SELECT o.ID de pedido, o.fechaDePedido, o.Pedido cancelado, o.pedido entregado, o.comentarios, CASO ¿CUÁNDO o.Pedido cancelado = VERDADERO ENTONCES “El pedido fue cancelado” ¿CUÁNDO CUALQUIER c ENTRADA o.comentarios SATISFACE BAJAR(c) Me gusta “%misplac%” O BAJAR(c) Me gusta “%lost%” ENTONCES “Es posible que el pedido se haya extraviado” ¿CUÁNDO CUALQUIER c ENTRADA o.comentarios SATISFACE BAJAR(c) Me gusta “%deliver%” ENTONCES “Entregado pero el campo no está actualizado” SINO “Razón desconocida — investigar” FIN CO razón DE `comercio`.`Ventas`.`pedidos` CO o DÓNDE o.pedido entregado ES DESAPARECIDO O o.pedido entregado ES NULO; |
En tales casos, sería de ayuda contar con un asistente confiable disponible las 24 horas, los 7 días de la semana para obtener todas estas respuestas. La UDF descrita en este blog es un asistente de ese tipo. Acepta tus preguntas de la manera más natural y devuelve los resultados en formato JSON. Tras bambalinas, se conecta a un modelo de tu elección, junto con tu clave de API, para convertir tus pensamientos en SQL++ y luego los ejecuta. Y todo lo que necesitas para invocar a este asistente es usar la UDF.
|
1 2 3 4 5 6 7 |
SELECT NL2SQL( [“`comercio`.`Ventas`.`pedidos`”], “¿Hay algún documento en el que falte la fecha order_delivered y, de ser así, por qué?”, “”, “https://api.openai.com/v1/chat/completions”, “gpt-4o-2024-05-13” ) ; |
Cómo funciona
1. Configurar la biblioteca.
Primero creas una biblioteca de JavaScript utilizada por la UDF.
Biblioteca
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
/* input: keyspaces: una matriz de cadenas, cada cadena representa un “bucket.scope.collection” de keyspaces con el escape adecuado utilizando comillas de acento grave siempre que sea necesario solicitud en lenguaje natural del usuario apikey: tu clave de api de openai modelo: cadena que representa el nombre del modelo; para más detalles, consulta https://platform.openai.com/docs/api-reference/completions/create#completions-create-model salida: respuesta de la API de chat-completions con la sentencia SQL generada */ función inferidor(k) { var infq = N1QL(“SELECT t.properties FROM(INFER “+k+ “) como t”) ; var res=[] para(constante doc. de infq) { res.empujar(doc.) } regresar res[0]; } función nl2sql(espacios de claves, indicación, clave de API, modelapi, modelo) { esquemaDeColección = {} para(constante k en espacios de claves) { c = inferidor(espacios de claves[k]) esquemaDeColección[espacios de claves[k]] = c } collectionSchemaStr = JSON.serializar(esquemaDeColección) contenidoDelPrompt = `Información:nCollection‘Esquema: ${collectionSchemaStr}nnMensaje de solicitud: “${prompt}”nnEl contexto de la consulta está definido.nnBasándote en la información anterior, escribe un código SQL++ válido y devuelve solo la instrucción, sin explicaciones. Para la recuperación, usa alias. Usa UNNEST en la cláusula FROM cuando sea apropiado. nnSi tú’re claro el Aviso lata‘No se puede usar para generar una consulta; primero di “#ERR:” y luego explica por qué no».` data = {“messages”:[{“role”:”system”,”content”:”Eres un experto en Couchbase Capella. Tu tarea es crear consultas válidas para recuperar o crear datos según la información proporcionada.nnAborda esta tarea paso a paso y tómate tu tiempo.”},{“role”:”user”,”content”:promptContent}], “modelo”: modelo, “temperatura”:0, “max_tokens”:1024, “stream”:false} var dataStr = JSON.stringify(data) .replace(/\/g, “\\”) // escape backslashes .replace(/”/g, ‘\“‘); // escapar comillas var completionsurl = modelapi var q= `SELECT CURL(“${URL de finalizaciones}“, { “solicitud“: “PUBLICACIÓN“, “encabezado“: [“Autorización: Portador ${clave de API}“,“Contenido–tipo: aplicación/json“], “datos“: “${cadenaDatos}“ }) AS result; var completionsq = N1QL(q); var res = [] for(const doc of completionsq) { res.push(doc); } try { contenido = res[0].result.choices[0].message.content } catch(e) { return res; } stmt = content.trim().substring(7, content.length-4) isSelect = (stmt.substring(0,6).toLowerCase())===”seleccionar“ if(isSelect === false){ devolver { “generado_declaración“: stmt } } var runq = N1QL(stmt); var rrun = [] for(const doc of runq) { rrun.push(doc) } devolver { “generado_declaración“: stmt, “resultados“: ejecutar } } |
2. Subir la biblioteca.
Ejecute el comando curl después de copiar el código de la biblioteca proporcionado en un archivo, es decir, usingailib.js.
|
1 2 |
curl –X PUBLICACIÓN https://localhost:9499/evaluator/v1/libraries/usingailib —datos–binario @usando ailib.JS –u Administrador:contraseña |
3. Crea la UDF.
Usa la siguiente declaración de función create para crear la UDF una vez que hayas creado la librería:
|
1 2 |
CREAR O REEMPLAZAR FUNCIÓN NL2SQL(espacios de claves, indicación, clave de API, modelapi, modelo) Idioma JavaScript CO “nl2sql” AT “utilizandoailib”; |
NL2SQL() ahora actúa como su traductor multilingüe entre el lenguaje humano y el motor de consultas de Couchbase. Simplemente le proporciona algo de contexto y una solicitud en lenguaje natural, y devuelve una respuesta.
Cómo piensa la UDF
Bajo el capó, utiliza tu modelo preferido al invocar la UDF para comprender tu intención y generar una consulta que Couchbase pueda ejecutar.
La ventaja de usar la API de chat completions significa que simplemente puedes conectar un modelo de otros proveedores que sea compatible con la misma especificación de API. Puedes usar tu propio LLM privado o los conocidos de OpenAI, Gemini, Claude, etc.
La UDF invocada requiere la siguiente información de usted:
- espacios de claves – Una matriz de cadenas, cada una representando un espacio de claves de Couchbase (bucket.scope.collection). Use acentos graves donde sea necesario para escapar nombres especiales (como
travel-sample.inventory.route). Esto le indica a la UDF dónde buscar sus datos. - indicación – Su solicitud en inglés sencillo (o cualquier otro idioma).
Muéstrame todos los usuarios que hicieron una compra en las últimas 24 horas.“ - clave de API – Your API key used for authenticating with the model endpoint.
- model endpoint – e.g., Open AI compliant chat completions URL.
- modelo – The name of the model you want to use from the provider.
e.g., “gpt-4o-2024-05-13”
There are also several available functions in the library:
inferencer()
Before generating a query, the UDF first tries to understand your data. The inferencer() helper function calls Couchbase’s INFER statement to retrieve a collection’s schema:
|
1 2 3 4 5 6 7 8 |
función inferidor(k) { var infq = N1QL(“SELECT t.properties FROM (INFER “ + k + “) AS t”); var res = []; para (constante doc. de infq) { res.empujar(doc.); } regresar res[0]; } |
This schema is used to help the AI understand what kind of data lives inside each collection.
The main function: nl2sql()
- Collects all schemas for the given keyspaces using the inferencer(). Constructs a prompt that includes: the inferred schema, your natural language query, and a Couchbase prompt to nudge the LLM.
- Sends it to the LLM.
- Extracts the generated SQL++ from the model’s response.
- Executes it directly if it’s a SELECT statement and returns both the generated SQL++ statement and the query results.
The reason for not executing non-select statements is that you don’t want this UDF to insert, update, or delete documents in a collection without you verifying it. So the SQL++ statement lets you execute it after it’s been verified.
Example use case:
|
1 2 3 4 5 6 |
SELECT default:NL2SQL( [“`travel-sample`.inventory.hotel”], “Give me hotels in San Francisco that have free parking and free breakfast and a rating of more than 3”, “”, “https://api.openai.com/v1/chat/completions”, “gpt-4o-2024-05-13” ); |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
Result: [{ “$1”: { “generated_statement”: “SELECT h.name, h.address, h.city, h.state, h.country, h.free_parking, h.free_breakfast, r.ratings.OverallnFROM `travel-sample`.inventory.hotel AS hnUNNEST h.reviews AS rnWHERE h.city = “San Francisco“n AND h.free_parking = truen AND h.free_breakfast = truen AND r.ratings.Overall > 3;”, “results”: [{ “Overall”: 4, “dirección”: “520 Church St”, “ciudad”: “San Francisco”, “país”: “United States”, “free_breakfast”: verdadero, “free_parking”: verdadero, “nombre”: “Parker House”, “state”: “California” }, { “Overall”: 4, “dirección”: “520 Church St”, “ciudad”: “San Francisco”, “país”: “United States”, “free_breakfast”: verdadero, “free_parking”: verdadero, “nombre”: “Parker House”, “state”: “California” }, { “Overall”: 5, “dirección”: “520 Church St”, “ciudad”: “San Francisco”, “país”: “United States”, “free_breakfast”: verdadero, “free_parking”: verdadero, “nombre”: “Parker House”, “state”: “California” }, { “Overall”: 4, “dirección”: “520 Church St”, “ciudad”: “San Francisco”, “país”: “United States”, “free_breakfast”: verdadero, “free_parking”: verdadero, “nombre”: “Parker House”, “state”: “California” }, { “Overall”: 5, “dirección”: “465 Grant Ave”, “ciudad”: “San Francisco”, “país”: “United States”, “free_breakfast”: verdadero, “free_parking”: verdadero, “nombre”: “Grant Plaza Hotel”, “state”: “California” }, { “Overall”: 5, “dirección”: “465 Grant Ave”, “ciudad”: “San Francisco”, “país”: “United States”, “free_breakfast”: verdadero, “free_parking”: verdadero, “nombre”: “Grant Plaza Hotel”, “state”: “California” }, ... |
Experimenting with models from other providers
The next example uses Gemini’s Open AI-compatible API. You simply change the model provider’s URL from the previous Open AI API to Gemini’s API. Also, be sure to change the model parameter to a model it recognizes. Of course, you need to also update the api-key from Open AI’s key to Gemini’s key.
|
1 2 3 4 5 6 7 |
SELECT NL2SQL( [“`travel-sample`.inventory.hotel”], “Show me hotels in France”, “”, “https://generativelanguage.googleapis.com/v1beta/openai/chat/completions”, “gemini-2.0-flash” )as p; |
The following illustrates the result:
0
Conclusión
This blog provides a glimpse into how you can leverage AI to interact with your data in Couchbase. With this UDF, natural language querying becomes a reality – no SQL++ expertise required. It is model-agnostic and safe for production queries.
And this is just the beginning. In the future, we hope to extend it to:
- Image → SQL++
- Voice → SQL++
- Agent-like pipelines
… all running inside Couchbase workflows.
Referencias
Capella IQ: https://docs.couchbase.com/cloud/get-started/capella-iq/get-started-with-iq.html
Chat completions APIs:
https://platform.openai.com/docs/api-reference/chat
https://ai.google.dev/gemini-api/docs/openai#rest

Deja un comentario
Lo siento, debes estar conectado para publicar un comentario.