Consultar datos de Search Console usando un LLM local

Publicado por Lino Uruñuela el 19 de marzo de 2025

 

Los grandes modelos de lenguaje (LLMs) como los disponibles por OpenAI o Google se pueden ejecutar en tu propio ordenador sin apenas consumir recursos, ya que realmente se procesan en las máquinas de estos proveedores. Esto, en principio, no sería un impedimento para ejecutar LLMs en tu ordenador, pero son de pago y, para el volumen de datos con el que suelo trabajar, no me resulta rentable.

Aunque el precio por token de entrada/salida es aparentemente bajo, deja de serlo si tienes que solicitar decenas o cientos de millones... Por ejemplo, algunas propiedades de Search Console pueden tener millones de keywords únicas. Y no solo eso, si combinas ciertos datos como keyword, title y algo más en una página que tenga unas 100.000 URLs, el número de tokens que querrás procesar comienza a crecer rápidamente.

 

Cuando se trata de un funcionamiento en producción, puede tener mucho sentido usar los modelos de pago de los grandes proveedores, dependerá del problema que estés resolviendo y, sobre todo, del valor que aporte la solución. Si eres una empresa de seguros y un LLM bien ejecutado puede resolver un porcentaje de las consultas que hacen los usuarios, posiblemente puedas (y debas) considerar estos modelos.

Pero si eres alguien como yo, que está todo el día investigando con grandes volúmenes de datos para explorar nuevas utilidades o funcionalidades que solo voy a usar yo, o por ejemplo, para crear un buscador en tu sitio web o un buscador semántico en los contenidos de vídeos, posiblemente no te salga a cuenta.

 

 

Nuevo modelo de Mistral (mistral-small-2503)

Dicho esto, el otro día probé el nuevo modelo de Mistral y, sinceramente, me ha encantado. Funciona relativamente bien, al menos en el primer caso de uso que estoy creando, que es mostrar datos, por ejemplo de Search Console, haciéndole preguntas en lenguaje natural.

De momento, he creado un script básico que se ejecuta desde la línea de comandos. Odio los stacks y frameworks, etc., cuando voy a ser yo el único que lo ejecute y use. Soy un poco "hater" de los frameworks, sean de lo que sean, normalmente para mis casos de uso solo añaden complejidad.

 

Usando llm para ejecutar LLM en local

Para ejecutar los LLMs que mi ordenador es capaz de procesar uso llm (desarrollado por Simon Willison, si no le sigues, ¡deberías!), ya que es fácil, tiene actualizados todos los modelos y me ocupa mucho menos espacio que cuando instalo LLMs con Ollama, puede que por mi propio desconocimiento...

 

Por si quieres probarlo,aquí tienes las instrucciones, solo con 1 línea ya lo tendrás instalado y luego, por ejemplo, este sería el comando para descargar la lista de modelos de Mistral:

$ llm install llm-mistral

Ahora vamos al lío :), vamos a ejecutar el modelo 'mistral/mistral-small-2503', por ejemplo, le solicitamos la lista de modelos de Nike en la última década.
$ llm -m mistral/mistral-small-2503 "lista los modelos de zapatillas Nike en los últimos 10 años"

 

Lo que nos devuelve la lista de zapatillas Nike en formato Markdown

1. **Nike Air Max 270** (2018) - Conocida por su gran unidad Air Max para máxima amortiguación.
2. **Nike Air VaporMax** (2017) - Introduce una unidad Air completa sin soporte adicional, ofreciendo una sensación de flotación.
3. **Nike Air Zoom Pegasus 36** (2019) - Parte de la popular serie Pegasus, conocida por su comodidad y rendimiento.
4. **Nike Air Force 1** (Versiones actualizadas) - Un clásico que ha sido reimaginado con nuevas tecnologías y diseños.
5. **Nike Air Max 720** (2016) - Ofrece una unidad Air Max de 360 grados para una amortiguación completa.
[...recortado por extensión...]

 

Haciendo preguntas sobre Google Search Console a un script

Ya hemos visto cómo podemos ejecutar fácilmente este modelo de Mistral en nuestro ordenador. Ahora intentaremos ir un poco más allá y nos marcaremos como objetivo poder realizar consultas a Search Console usando lenguaje natural.


Yo proceso los datos de logs, Search Console, Analytics y otras fuentes diariamente. Cada día me descargo a mi BBDD los nuevos datos generados en GSC para todos los proyectos de mis clientes y los uso a menudo para diferentes tareas como análisis profundos, alertas, forecast, etc... Y sí, también porque me gusta, o tengo el síndrome de Diógenes con los datos :).


Vamos a usar la línea de comandos para ejecutar una consulta SQL a la base de datos, que está en mi ordenador. Se podría usar cualquier cliente de bases de datos típico como MySQL, PostgreSQL, DuckDB, ClickHouse, etc. Para este ejemplo, estoy usando ClickHouse.

En este caso, vamos a usar el cliente de ClickHouse para hacer una consulta de prueba:

clickhouse-client -u default --ask-password -q "select now()"

┏━━━━━━━━━━━━━━━━━━━━━┓
┃               now() ┃
┡━━━━━━━━━━━━━━━━━━━━━┩
│ 2025-03-19 11:27:46 │
└─────────────────────┘

 

Pero también podría hacer una consulta a la base de datos de GSC para contar cuántas filas hay en la tabla.

#A partir de aquí usaré 'sqlCH' en vez de 'clickhouse-client -u default --ask-password'para hacerlo más corto

sqlCH "select count() cnt from default.GSC_ https_MiDominio_dev FORMAT Pretty"

┏━━━━━━━━━━┓
┃      cnt ┃
┡━━━━━━━━━━┩
│ 10648667 │
└──────────┘

Algo crucial es comunicarle al modelo cómo se llaman las tablas, cuáles son las columnas y qué tipo de variables son. Esto lo hago con la SQL "DESCRIBE TABLE", cuyo resultado será intercalado en el prompt que pasaremos al LLM.

sqlCH "DESCRIBE Table default.GSC_ https_MiDominio_dev FORMAT Pretty"
    ┏━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┓
    ┃ name        ┃ type    ┃ default_type ┃ default_expression ┃ comment ┃ codec_expression ┃ ttl_expression ┃
    ┡━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━┩
 1. │ fecha       │ Date    │              │                    │         │                  │                │
    ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
 2. │ consulta    │ String  │              │                    │         │                  │                │
    ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
 3. │ landing     │ String  │              │                    │         │                  │                │
    ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
 4. │ clicks      │ UInt32  │              │                    │         │                  │                │
    ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
 5. │ impresiones │ UInt32  │              │                    │         │                  │                │
    ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
 6. │ posicion    │ Float32 │              │                    │         │                  │                │
    ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
 7. │ ctr         │ Float32 │ Float32 │              │                    │         │                  │                │
    ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
 8. │ dispositivo │ String  │              │                    │         │                  │                │
    ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
 9. │ pais        │ String  │              │                    │         │                  │                │
    ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
10. │ id_cliente  │ UInt32  │              │                    │         │                  │                │
    ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
11. │ propiedad   │ String  │              │                    │         │                  │                │
    └─────────────┴─────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘

 

Ahora podemos ir juntando/concatenando las diferentes piezas que tenemos para crear el prompt que enviaremos al modelo, indicándole el nombre de la tabla y luego el resultado de la SQL DESCRIBE. Al final, si os fijáis, añado la consulta que quiero hacer, en este caso: "Genera una SQL que sume el total de clicks en la tabla".

:~$ llm -m mistral/mistral-small-2503 "Este es el esquema de la tabla: \

┏━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┓
┃ name        ┃ type    ┃ default_type ┃ default_expression ┃ comment ┃ codec_expression ┃ ttl_expression ┃
┡━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━┩

│ fecha       │ Date    │              │                    │         │                  │                │
├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤

│ consulta    │ String  │              │                    │         │                  │                │
├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤

│ landing     │ String  │              │                    │         │                  │                │
├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤

│ clicks      │ UInt32  │              │                    │         │                  │                │
├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤

│ impresiones │ UInt32  │              │                    │         │                  │                │
├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤

│ posicion    │ Float32 │              │                    │         │                  │                │
├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤

│ ctr         │ Float32 │              │                    │         │                  │                │
├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤

│ dispositivo │ String  │              │                    │         │                  │                │
├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤

│ pais        │ String  │              │                    │         │                  │                │
├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤

│ id_cliente  │ UInt32  │              │                    │         │                  │                │
├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤

│ propiedad   │ String  │              │                    │         │                  │                │
└─────────────┴─────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘
 Genera una SQL que sume el total de clicks en la tabla"

Esto nos devuelve una SQL que podemos ejecutar en nuestra base de datos para obtener el dato que hemos solicitado.

sql
SELECT SUM(clicks) AS total_clicks
FROM .GSC_https_ MiDominio_dev;

Esta consulta selecciona la suma de la columna clicks y la etiqueta como total_clicks. La tabla .GSC_https_ MiDominio_dev es especificada en la cláusula FROM.

Si necesitas agregar alguna condición, como filtrar por un rango de fechas o algún otro criterio, puedes hacerlo utilizando la cláusula WHERE. Por ejemplo, si quieres sumar los clicks solo para un rango de fechas específico, podrías hacer algo como esto:

sql
SELECT SUM(clicks) AS total_clicks
FROM .GSC_https_ MiDominio_dev
WHERE fecha BETWEEN '2023-01-01' AND '2023-12-31';

Asegúrate de ajustar las fechas y cualquier otra condición según tus necesidades específicas.

 

Este tipo de consultas SQL las resuelve bastante bien, tampoco tiene mucha ciencia, pero podemos ir bastante más allá.

 

Para poder aprovechar la SQL que nos facilita Mistral, debemos hacer que el modelo se calle, y que únicamente devuelva la SQL, sin explicaciones ni consejos ni nada, solo la SQL para poder ejecutar la salida del modelo directamente contra la base de datos...

 

Aquí un consejo importante: utiliza un usuario de la base de datos que solo tenga permisos de lectura, porque nadie te puede asegurar que el LLM no genere accidentalmente un DROP DATABASE..... En serio, si ejecutas muchas SQL obtenidas de LLMs, será cuestión de estadística que algo así ocurra, o al menos esa es mi hipótesis.

 

Descripción del proceso

Como un esquema simple, podríamos decir que:

#De momento nuestro prompt está vacío

  1. Texto inicial del prompt: "Eres un asistente de SQL que..."

    #El contenido de nuestro prompt ahora es: Eres un asistente de SQL que...

    1. Ejecuto el cliente de la base de datos para obtener el resultado de "DESCRIBE TABLE nombreTabla".

    2. Concateno lo que me devuelve el comando para añadirlo al prompt.

      #El contenido de nuestro prompt ahora es:

      Eres un asistente de SQL que... . Este es el esquema de la tabla nombreTabla:
      
      ┏━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┓
      ┃ name        ┃ type    ┃ default_type ┃ default_expression ┃ comment ┃ codec_expression ┃ ttl_expression ┃
      ┡━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━┩
      
      │ fecha       │ Date    │              │                    │         │                  │                │
      ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
      
      │ consulta    │ String  │              │                    │         │                  │                │
      ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
      
      │ landing     │ String  │              │                    │         │                  │                │
      ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
      
      │ clicks      │ UInt32  │              │                    │         │                  │                │
      ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
      
      │ impresiones │ UInt32  │              │                    │         │                  │                │
      ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
      
      │ posicion    │ Float32 │              │                    │         │                  │                │
      ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
      
      │ ctr         │ Float32 │              │                    │         │                  │                │
      ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
      
      │ dispositivo │ String  │              │                    │         │                  │                │
      ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
      
      │ pais        │ String  │              │                    │         │                  │                │
      ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
      
      │ id_cliente  │ UInt32  │              │                    │         │                  │                │
      ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
      
      │ propiedad   │ String  │              │                    │         │                  │                │
      └─────────────┴─────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘
      



  2. Añadimos indicamos qué queremos obtener, por ejemplo: " Genera una SQL que sume el total de clicks".
    #Ahora nuestro prompt contiene:
    Eres un asistente de SQL que... . Este es el esquema de la tabla nombreTabla:
    
    ┏━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┓
    ┃ name        ┃ type    ┃ default_type ┃ default_expression ┃ comment ┃ codec_expression ┃ ttl_expression ┃
    ┡━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━┩
    
    │ fecha       │ Date    │              │                    │         │                  │                │
    ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
    
    │ consulta    │ String  │              │                    │         │                  │                │
    ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
    
    │ landing     │ String  │              │                    │         │                  │                │
    ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
    
    │ clicks      │ UInt32  │              │                    │         │                  │                │
    ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
    
    │ impresiones │ UInt32  │              │                    │         │                  │                │
    ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
    
    │ posicion    │ Float32 │              │                    │         │                  │                │
    ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
    
    │ ctr         │ Float32 │              │                    │         │                  │                │
    ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
    
    │ dispositivo │ String  │              │                    │         │                  │                │
    ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
    
    │ pais        │ String  │              │                    │         │                  │                │
    ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
    
    │ id_cliente  │ UInt32  │              │                    │         │                  │                │
    ├─────────────┼─────────┼──────────────┼────────────────────┼─────────┼──────────────────┼────────────────┤
    
    │ propiedad   │ String  │              │                    │         │                  │                │
    └─────────────┴─────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘
    
    Genera una SQL que sume el total de clicks. Devuelve únicamente la SQL completa, sin comentarios adicionales, en texto plano.
    

    Como he dicho antes, para que el modelo se centre en devolver solo lo que ejecutaremos posteriormente, he añadido el prompt: "*Devuelve únicamente la SQL completa, sin comentarios adicionales, en texto plano.*". Otros métodos, como definir el tipo de datos que sale en formato Json, serían más robustos, pero de momento funciona bastante bien.

Ya tenemos un prompt "completo", que se lo damos al LLM pasándole la información necesaria para comprender los datos y que genera la respuesta, en este caso una SQL que ejecutaremos en nuestra base de datos, en este caso concreto para obtener el número total de clicks.

 

Organizarlo todo en un script

Va siendo hora de organizar todo esto dentro de un script, porque además veremos cómo podemos ir mejorando/complicando esta pila de ejecución.

Al script que he creado le paso dos argumentos (bueno, tres, pero los últimos son para activar/desactivar determinadas funcionalidades):

  1. Como primer argumento, le paso el nombre de la base de datos y la tabla. En el script, se ejecuta la SQL "DESCRIBE TABLE..." y el resultado se añade a la variable del prompt.

  2. El segundo argumento es la pregunta en sí, en este caso sería: "Genera una SQL que sume el total de clicks. Devuelve únicamente la SQL completa, sin comentarios adicionales, en texto plano."

Con este simple prompt ya creado y guardado en una variable, ejecuto el LLM de Mistral, que me devuelve la SQL a ejecutar y que guardo en otra variable. El siguiente paso simplemente es ejecutar la SQL devuelta por el LLM, ¡y listo!

 

Pero las cosas no son tan sencillas, ni tan complicadas... Muchas veces falla, usa funciones SQL que no son compatibles con la base de datos que le indicas, o genera la SQL con errores de formato. Sin embargo, es posible corregirlo.

 

Cuándo la ejecución de la SQL falla podemos volver a pedir al LLM que genere una SQL, pero le añadiremos al prompt la SQL que acabamos de ejecutar y el mensaje de error que ha generado para indicar al LLM que pruebe con otra SQL diferente y teniendo en cuenta el error que había generado.

 

De esta forma, cuando falla, vuelve a intentarlo teniendo el contexto de los intentos anteriores. En consultas complejas se ve cómo va corrigiendo los errores, por ejemplo, si ha usado una función que ClickHouse no admite, se da cuenta y en el siguiente reintento lo corrige. Si el número de intentos al ejecutar la SQL supera un máximo que defino yo, se para y termina.

 

Este proceso podríamos repetirlo las veces que quisiéramos con la idea de que alguna acertará, pero la probabilidad de que la SQL genere un resultado correcto intuyo qye será inversamente proporcional al número de intentos...

 

Por último, si añado como parámetro al script '--explicaSQL=si' cuándo ejecute la SQL correctamente se creará un nuevo prompt con las instrucciones para que el LLM explique la SQL que ha generado resultados.

Aquí dejo una imagen en la que intento representar el flujo de instrucciones que sigue el script

 

Este script, aunque parezca complejo, es bastante simple, y funciona para muchísimas de las consultas que realizo. Para SQLs con cierto nivel de dificultad, por ejemplo regresiones logísticas o uso de datos de entrenamiento y validación en las propias SQL, si bien no lo hace mal del todo, no te puedes fiar completamente, ya que a veces no realiza bien la "teorización" del problema.

 

Y aquí dejo el código del script que implementa este proceso.

#!/bin/bash

if [ "$#" -lt 2 ]; then
  echo "Uso: $0  '' [--explicaSQL=si]"
  exit 1
fi

DB_TABLA="$1"
PROMPT="$2"
MUESTRA_EXPLICACION=0
if [ "$3" = "--explicaSQL=si" ]; then
  MUESTRA_EXPLICACION=1
fi

CLICKHOUSE_CLIENT="clickhouse-client -u default --password=MI_PASSWORD!"

intentos=0
max_intentos=15
errores_acumulados=""

mkdir -p logs
LOG_FILE="logs/sqlResultados_log.csv"

if [ ! -f "$LOG_FILE" ]; then
  echo "prompt;sql;estado_salida;respuesta;tabla" > "$LOG_FILE"
fi

tabla=$($CLICKHOUSE_CLIENT --query="DESCRIBE TABLE $DB_TABLA" | tr '\n' ' ')

while [ "$intentos" -lt "$max_intentos" ]; do
  sqlIA=$(llm -m mistral/mistral-small-2503 "Este es el esquema SQL de ClickHouse para la tabla $DB_TABLA: $tabla. $PROMPT ${errores_acumulados:+Ten en cuenta los siguientes errores generados anteriormente al ejecutar SQLs anteriores: $errores_acumulados} Devuelve únicamente la SQL completa, sin comentarios adicionales, en texto plano." | grep -v '
')

  salida=$($CLICKHOUSE_CLIENT -q "$sqlIA" 2>&1)
  resultado=$?

  if [ "$resultado" -eq 0 ]; then
    estado_salida="correcta"
    respuesta="$salida"
  else
    estado_salida="error"
    respuesta="$salida"
    errores_acumulados+=" | SQL: ${sqlIA//[$'\n'$'\t']/ } Error: ${salida//[$'\n'$'\t']/ }"
  fi

  echo "\"${PROMPT//\"/\"\"}\";\"${sqlIA//\"/\"\"}\";$estado_salida;\"${respuesta//\"/\"\"}\";$DB_TABLA" >> "$LOG_FILE"

  if [ "$resultado" -eq 0 ]; then
    echo " SQL ejecutada con éxito:\n$sqlIA\n Resultado:\n$salida"
    if [ "$MUESTRA_EXPLICACION" -eq 1 ]; then
      explicacion=$(llm -m mistral/mistral-small-2503 "Explica qué hace esta SQL: $sqlIA")
      echo -e " Explicación:\n$explicacion"
    fi
    exit 0
  else
    intentos=$((intentos+1))
    echo -e " Intento $intentos fallido:\n$respuesta"
    sleep 1
  fi

done

echo " Se han agotado los intentos, no se generó una SQL válida."
exit 1

Ejemplos de consultas realizadas a Search Console usando lLLM

Obtener las 10 KWs que más clicks tienen

sqlCHIA3.sh  "default.GSC_ https_MiDominio_dev" "Genera una consulta SQL válida para ClickHouse que liste las 10 consultas con más clicks totales desde tres meses antes de la última fecha disponible hasta dicha última fecha,  (NO DESDE HOY, TEN EN CUENTA QUE LA ÚLTIMA FECHA EN LA TABLA NO ES LA DE HOY). Las columnas serán exactamente: consulta,totalClicks. Limita los resultados únicamente a las 10 consultas con más clicks totales,  añadir al final de la consulta SQL 'FORMAT Markdown'. Usa funciones analíticas o agregadas propias de ClickHouse."

 

Obtener TOP países con más clicks

sqlCHIA3.sh  "default.GSC_ https_MiDominio_dev" "Genera una consulta SQL válida para ClickHouse que liste las 10 consultas con más clicks totales desde tres meses antes de la última fecha disponible hasta dicha última fecha,  (NO DESDE HOY, TEN EN CUENTA QUE LA ÚLTIMA FECHA EN LA TABLA NO ES LA DE HOY). Las columnas serán exactamente: consulta,totalClicks. Limita los resultados únicamente a las 10 consultas con más clicks totales,  añadir al final de la consulta SQL 'FORMAT Markdown'. Usa funciones analíticas o agregadas propias de ClickHouse."

 

URLs que más clcks pierden entre dos fechas con % acumulado

sqlCHIA3.sh \
  "WA.GSC_ MiDominio_dv" \
  "Genera una consulta SQL válida para que devuelva las URLs que más diferencia de clicks hay entre los periodos:
    - Periodo 1: desde 2025-02-03 al 2025-02-16
    - Periodo 2: desde 2025-01-13 al 2025-01-26

Devolver las columnas:
  - landing
  - clicks_Periodo_1
  - clicks_Periodo_2
  - diferencia_clicks_Periodo1_Periodo2
  - % de clicks perdidos (cuanto representa frente al total de clicks perdidos de todas las landings), con dos decimales
  - % de clicks perdidos acumulado (va sumando cada % de clicks perdidos), con dos decimales

Ordena las URLs en base al total de clicks perdidos (es decir, aquellas cuya diferencia: clicks en Periodo_1 menos clicks en Periodo_2, sea menor).

Limita el número de resultados a 100. Añadir al final de la consulta SQL: 'FORMAT Markdown'."

 


 




Lea otros artículos de Inteligencia Artificial para SEOs

Últimos posts

Últimos comentarios


augmentin 875 mg po bid
160 Gotland CLOPIDOGREL 75 mg GARMISCH Clopidogrel Caja x 15 tabs augmentin liquid
Post: Cómo influye el servidor y el dominio

Lino
@spamloco a tí r hacerme ver que no soy al único que le importa :p A ver si nos vemos!
Post: ¿Cómo decide Google que URL debe rastrear?

Alejandro
Gracias Lino, siempre investigando un poco más allá.
Post: ¿Cómo decide Google que URL debe rastrear?

Lino
3,2,1... Gracias a ti Pedro!! y sí, parece que los humanos somos expertos en haciendo ruido cuando intentamos que alguien nos escuche... :p
Post: ¿Cómo decide Google que URL debe rastrear?

Pedro
1,2...1,2... probando. Gracias por el artículo, verdaderamente interesante ver cómo no paramos de generar ruido :)
Post: ¿Cómo decide Google que URL debe rastrear?

Lino
Funcionan!! Ahora solo tengo que generar engagement :D A ver si quito lo de avisar por Twitter... no sé cuántos años llevará sin funcio
Post: ¿Cómo decide Google que URL debe rastrear?

Juanan Carapapa
Yo también vengo a probar los comentarios, probando probando xD
Post: ¿Cómo decide Google que URL debe rastrear?

Lino2
Hola @errioxa que tal
Post: ¿Cómo decide Google que URL debe rastrear?

Lino2
Hola
Post: ¿Cómo decide Google que URL debe rastrear?

Lino
Probando!
Post: ¿Cómo decide Google que URL debe rastrear?