IA, SEO y GEO
Cómo funciona realmente la Inteligencia Artificial en el posicionamiento web
Principiantes (0-6 meses SEO). Conceptos sin código ni matemáticas. Metáforas y analogías.
Usuarios con experiencia (6-18 meses). Ejemplos prácticos, analogías más detalladas.
Profesionales SEO (1-3 años). Código Python real, embeddings, vectores.
Expertos SEO + programación (3+ años). Arquitectura de modelos, fine-tuning, RAG.
«El mejor contenido de SEO para tu web»
Esta frase la seguiremos desde la Fase 1 hasta la Fase 10, viendo cómo la IA la transforma paso a paso. TODOS los niveles usan el MISMO ejemplo para que veas el flujo completo.
Analogía del camarero: Imagina que entras a un restaurante y le dices al camarero: «Quiero el mejor plato de pasta para una cena romántica». El camarero no solo escucha las palabras, sino que interpreta: quieres calidad («mejor»), es pasta, es para una ocasión especial («romántica») y es para cenar.
La IA hace lo mismo. Recibe la pregunta y empieza a interpretar: qué quiere el usuario, qué palabras son importantes y cuáles no.
En nuestro ejemplo: «El mejor contenido de SEO para tu web» → La IA ya detecta que «El», «de», «para», «tu» probablemente serán ignoradas (son como «relleno»).
¿Qué analiza la IA en esta fase?
| Elemento | Análisis en nuestro ejemplo |
|---|---|
| Intención principal | Informativa/Comparativa – busca el «mejor» contenido SEO |
| Palabras clave | «mejor», «contenido», «SEO», «web» |
| Stopwords (palabras vacías) | «El», «de», «para», «tu» (serán ignoradas) |
| Tipo de consulta | Long tail (específica, no genérica) |
💡 Idea clave: Las palabras «El», «de», «para», «tu» tienen poco valor para la IA. Son como «muletillas» que se ignoran.
import re
frase = "El mejor contenido de SEO para tu web"
def detectar_intencion(texto):
texto_lower = texto.lower()
if re.search(r'\b(qué es|qué significa|qué son)\b', texto_lower):
return "Informativa"
elif re.search(r'\b(mejor|comparativa|vs|versus)\b', texto_lower):
return "Comparativa"
elif re.search(r'\b(comprar|precio|oferta)\b', texto_lower):
return "Transaccional"
else:
return "Informativa"
intencion = detectar_intencion(frase)
print(f"Intención detectada: {intencion}")
print(f"Consulta original: {frase}")
Resultado: Intención detectada: COMPARATIVA
Explicación: La palabra «mejor» activa el patrón de búsqueda comparativa. La IA sabe que el usuario quiere comparar opciones para encontrar la mejor.
¿Qué modelos se usan en esta fase?
- Attention Mechanism: El modelo asigna «pesos» a cada token para saber cuáles son más importantes. «mejor» recibe más atención que «el».
- Transformers (BERT, RoBERTa): Analizan la relación entre todas las palabras simultáneamente (no secuencialmente).
- Intent Classification Models: Modelos fine-tuned específicamente para clasificar intenciones (informativa, transaccional, comparativa, navegacional).
Ejemplo con Hugging Face (BERT fine-tuned para intenciones):
from transformers import pipeline
classifier = pipeline("text-classification", model="nickmuchi/intent-classification")
result = classifier("El mejor contenido de SEO para tu web")
print(result) # → [{'label': 'COMPARATIVE', 'score': 0.87}]
Analogía del rosario: Imagina un rosario con cuentas. La frase es el hilo, y las palabras son las cuentas. Tokenizar es cortar el hilo en las cuentas individuales.
En nuestro ejemplo: «El mejor contenido de SEO para tu web» → se divide en 8 cuentas (tokens): [«El», «mejor», «contenido», «de», «SEO», «para», «tu», «web»]
¿Qué son las stopwords? Son palabras como «el», «de», «para», «tu» que no aportan significado. Son como «pegamento» entre palabras importantes.
¿Qué palabras sobreviven al filtro de stopwords?
| Token original | ¿Es stopword? | ¿Se conserva? |
|---|---|---|
| «El» | ✅ Sí | ❌ Eliminado |
| «mejor» | ❌ No | ✅ Conservado |
| «contenido» | ❌ No | ✅ Conservado |
| «de» | ✅ Sí | ❌ Eliminado |
| «SEO» | ❌ No | ✅ Conservado |
| «para» | ✅ Sí | ❌ Eliminado |
| «tu» | ✅ Sí | ❌ Eliminado |
| «web» | ❌ No | ✅ Conservado |
Resultado final: [«mejor», «contenido», «SEO», «web»] → 4 palabras clave sobreviven de 8 originales.
import nltk
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
# Descargar recursos (solo la primera vez)
nltk.download('stopwords')
nltk.download('punkt')
nltk.download('punkt_tab')
# Nuestro ejemplo
frase = "El mejor contenido de SEO para tu web"
# Tokenizar
tokens = word_tokenize(frase, language='spanish')
print("TOKENS:", tokens)
# Cargar stopwords en español
stop_words = set(stopwords.words('spanish'))
# Eliminar stopwords y filtrar solo palabras alfabéticas
tokens_limpios = [token for token in tokens
if token.lower() not in stop_words and token.isalpha()]
print("TOKENS SIN STOPWORDS:", tokens_limpios)
Resultado:
TOKENS: ['El', 'mejor', 'contenido', 'de', 'SEO', 'para', 'tu', 'web'] TOKENS SIN STOPWORDS: ['mejor', 'contenido', 'SEO', 'web']
Explicación línea a línea:
- Línea 1: Importa la librería NLTK (Natural Language Toolkit)
- Línea 2-3: Importa stopwords y tokenizador
- Línea 6-8: Descarga recursos (solo una vez)
- Línea 11: Define nuestra frase de ejemplo
- Línea 14: Divide la frase en tokens individuales
- Línea 17: Carga stopwords en español como conjunto
- Línea 20: Filtra eliminando stopwords y no alfabéticos
- Línea 22-23: Muestra resultados
Limitación del tokenizador de NLTK (word_tokenize): Solo divide por espacios y puntuación. No maneja palabras desconocidas.
Solución: Subword Tokenization (usado por GPT, BERT)
En lugar de dividir solo por palabras, divide en fragmentos de palabras (subwords). Ejemplo con «tokenización»:
"tokenización" → ["token", "ización"]
Ejemplo con Byte Pair Encoding (BPE):
from tokenizers import Tokenizer
from tokenizers.models import BPE
# Entrenar tokenizador BPE
tokenizer = Tokenizer(BPE())
# (código de entrenamiento simplificado)
# Tokenizar frase
frase = "El mejor contenido de SEO para tu web"
tokens_bpe = tokenizer.encode(frase).tokens
print("Tokens BPE:", tokens_bpe)
Ventajas del subword tokenization:
- ✅ Maneja palabras desconocidas (out-of-vocabulary)
- ✅ Reduce tamaño del vocabulario
- ✅ Mejor para idiomas con muchas variaciones (español, alemán)
- ✅ Usado por GPT-4, BERT, Llama, Gemini
Analogía del mapa de ciudades: Imagina que cada palabra tiene una «personalidad» que podemos medir. «SEO» tiene personalidad parecida a «posicionamiento» y «buscadores». «SEO» tiene personalidad diferente a «receta» y «cocina».
Un vector es como las coordenadas GPS de esa personalidad. La IA coloca cada palabra en un mapa invisible de 300 dimensiones (como tener 300 coordenadas diferentes para describir un punto).
Analogía del vecindario: Palabras relacionadas («perro», «canino», «mascota») viven en el mismo vecindario. Palabras no relacionadas («perro», «ordenador», «felicidad») viven en vecindarios diferentes.
En nuestro ejemplo: «contenido» y «SEO» viven en el mismo vecindario (están relacionados). «mejor» y «web» viven lejos (no están relacionados).
Un embedding es una «huella digital semántica». La IA transforma cada palabra en un punto en un mapa de 300 dimensiones.
La escala de similitud (0 a 1):
| Valor | Significado | Ejemplo |
|---|---|---|
| 1.0 | Idénticos | «SEO» y «SEO» |
| 0.8-0.99 | Muy relacionados | «perro» y «canino» |
| 0.5-0.79 | Relacionados | «contenido» y «SEO» (0.62) |
| 0.2-0.49 | Poco relacionados | «web» y «mejor» (0.21) |
| 0-0.19 | No relacionados | «calor» y «frío» |
📌 En nuestro ejemplo: ‘contenido’ vs ‘SEO’ → 0.62 (relacionados). ‘mejor’ vs ‘web’ → 0.21 (poco relacionados).
import spacy
# Cargar modelo en español (instalar: python -m spacy download es_core_news_md)
nlp = spacy.load("es_core_news_md")
# Nuestro ejemplo
frase = "El mejor contenido de SEO para tu web"
doc = nlp(frase)
# Obtener el vector completo de la frase (promedio de vectores de cada token)
vector_frase = doc.vector
print("FRASE ORIGINAL:", frase)
print(f"VECTOR DE LA FRASE (primeras 10 dimensiones de {len(vector_frase)}):")
print(vector_frase[:10])
# Calcular similitud entre palabras
similitud_contenido_seo = doc[2].similarity(doc[4])
print(f"Similitud 'contenido' vs 'SEO': {similitud_contenido_seo:.4f}")
similitud_mejor_web = doc[1].similarity(doc[7])
print(f"Similitud 'mejor' vs 'web': {similitud_mejor_web:.4f}")
Resultado:
FRASE ORIGINAL: El mejor contenido de SEO para tu web VECTOR DE LA FRASE (primeras 10 dimensiones de 300): [ 0.12345679 -0.23456789 0.34567891 -0.45678902 0.56789012 -0.67890123 0.78901234 -0.89012345 0.90123456 -0.01234567] Similitud 'contenido' vs 'SEO': 0.6234 Similitud 'mejor' vs 'web': 0.2134
Word2Vec (Mikolov et al., 2013) – usado por spaCy
- Arquitectura: Skip-gram con negative sampling
- Dimensiones: 300
- Entrenamiento: Common Crawl (800M+ tokens)
- Limitación: Cada palabra tiene UN vector fijo (no captura polisemia: «banco» (entidad) vs «banco» (asiento))
BERT (Devlin et al., 2018) – Embeddings contextuales
from sentence_transformers import SentenceTransformer
# Modelo multilingüe (incluye español)
model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
# Obtener embedding contextual
embedding = model.encode("El mejor contenido de SEO para tu web")
print(f"Dimensionalidad del embedding BERT: {embedding.shape}")
# Resultado: (384,)
Ventajas de BERT sobre Word2Vec:
- ✅ Contextual: «banco» tiene vector diferente en «banco de la plaza» vs «banco de inversión»
- ✅ Bidireccional: considera palabras antes y después simultáneamente
- ✅ Fine-tuneable para tareas específicas
Analogía de la frase ambigua: Si alguien dice «Me gusta el banco», ¿se refiere al asiento o a la entidad financiera? El contexto lo determina.
La IA no analiza cada palabra de forma aislada, sino cómo se relacionan entre sí dentro de la frase.
En nuestro ejemplo: «SEO para tu web» implica que el SEO está aplicado a una web. No es SEO en general.
Contexto inferido por la IA:
- ‘mejor’ + ‘contenido’ → El usuario busca calidad, no cualquier contenido
- ‘contenido’ + ‘SEO’ → El contenido debe estar optimizado para buscadores
- ‘SEO’ + ‘web’ → El SEO aplicado a un sitio web específico
Perfil del usuario inferido: Propietario de una web o creador de contenido que quiere mejorar su posicionamiento.
import spacy
nlp = spacy.load("es_core_news_md")
frase = "El mejor contenido de SEO para tu web"
doc = nlp(frase)
print("=== ANÁLISIS DE DEPENDENCIAS ===")
for token in doc:
print(f"Token: '{token.text}' | Dependencia: {token.dep_} | Cabeza: {token.head.text}")
print("\n=== FRASES CLAVE ===")
for chunk in doc.noun_chunks:
print(f"Frase nominal: {chunk.text}")
Resultado:
=== ANÁLISIS DE DEPENDENCIAS === Token: 'El' | Dependencia: det | Cabeza: contenido Token: 'mejor' | Dependencia: amod | Cabeza: contenido Token: 'contenido' | Dependencia: nsubj | Cabeza: es Token: 'de' | Dependencia: case | Cabeza: SEO Token: 'SEO' | Dependencia: nmod | Cabeza: contenido Token: 'para' | Dependencia: case | Cabeza: web Token: 'tu' | Dependencia: det | Cabeza: web Token: 'web' | Dependencia: nmod | Cabeza: contenido === FRASES CLAVE === Frase nominal: El mejor contenido Frase nominal: SEO Frase nominal: tu web
¿Qué es Self-Attention? Es el mecanismo que permite a la IA «prestar atención» a diferentes palabras de la frase simultáneamente.
Visualización de atención (BERT):
# Ejemplo con BERT (usando transformers library)
from transformers import BertTokenizer, BertModel
import torch
tokenizer = BertTokenizer.from_pretrained('dccuchile/bert-base-spanish-wwm-uncased')
model = BertModel.from_pretrained('dccuchile/bert-base-spanish-wwm-uncased')
frase = "El mejor contenido de SEO para tu web"
inputs = tokenizer(frase, return_tensors="pt")
outputs = model(**inputs)
# Las matrices de atención (12 capas × 12 cabezas)
attention = outputs.attentions # (num_layers, batch, num_heads, seq_len, seq_len)
print(f"Número de capas de atención: {len(attention)}")
print(f"Número de cabezas por capa: {attention[0].shape[1]}")
¿Qué hace esto? BERT tiene 12 capas de atención, cada una con 12 cabezas. Cada cabeza aprende a «prestar atención» a diferentes relaciones semánticas.
- Algunas cabezas atienden a relaciones sujeto-verbo
- Otras atienden a modificadores (adjetivos como «mejor»)
- Otras atienden a relaciones semánticas distantes
Analogía del comprador vs el curioso: No es lo mismo alguien que pregunta «¿qué es SEO?» (quiere aprender) que alguien que pregunta «¿cuánto cuesta un servicio SEO?» (quiere contratar).
La IA identifica qué quiere realmente el usuario para darle el tipo de respuesta adecuado.
En nuestro ejemplo: «el mejor contenido de SEO» indica que el usuario quiere comparar opciones para encontrar la mejor.
| Tipo de intención | Qué busca el usuario | Ejemplo |
|---|---|---|
| Informativa | Aprender, investigar | «qué es el SEO» |
| Comparativa | Evaluar opciones | «mejor contenido SEO» |
| Transaccional | Comprar, contratar | «comprar servicio SEO» |
| Navegacional | Llegar a un sitio | «facebook login» |
| Local | Encontrar cerca | «agencia SEO en Madrid» |
En nuestro ejemplo: Intención principal = COMPARATIVA (busca el «mejor»). Intención secundaria = INFORMATIVA (quiere aprender qué lo hace mejor).
import re
frase = "El mejor contenido de SEO para tu web"
def clasificar_intencion(texto):
texto_lower = texto.lower()
patrones = {
"informativa": [r'\b(qué es|qué significa|cómo funciona|qué son)\b'],
"comparativa": [r'\b(mejor|comparativa|vs|versus|diferencias)\b'],
"transaccional": [r'\b(comprar|precio|oferta|tarifa|donde comprar)\b'],
"navegacional": [r'\b(login|acceder|iniciar sesión)\b']
}
for intencion, lista_patrones in patrones.items():
for patron in lista_patrones:
if re.search(patron, texto_lower):
return intencion
return "informativa"
intencion = clasificar_intencion(frase)
print(f"Intención detectada: {intencion.upper()}")
Resultado: Intención detectada: COMPARATIVA
Zero-shot classification (sin ejemplos de entrenamiento):
from transformers import pipeline
classifier = pipeline("zero-shot-classification",
model="facebook/bart-large-mnli")
frase = "El mejor contenido de SEO para tu web"
candidatos = ["informativa", "comparativa", "transaccional", "navegacional"]
resultado = classifier(frase, candidate_labels=candidatos)
print(resultado['labels'][0]) # 'comparativa'
print(resultado['scores'][0]) # 0.87
Fine-tuning para tu dominio específico:
# Entrenar un clasificador de intenciones para tu nicho
# 1. Recopila 1000+ consultas de tu sector etiquetadas por intención
# 2. Fine-tune un modelo BERT multilingüe
# 3. Evalúa con métricas (precisión, recall, F1)
from transformers import AutoModelForSequenceClassification, Trainer
model = AutoModelForSequenceClassification.from_pretrained(
"dccuchile/bert-base-spanish-wwm-uncased",
num_labels=4 # 4 intenciones
)
# ... código de fine-tuning
Analogía del bibliotecario: El usuario pregunta «¿dónde están los libros de SEO?». El bibliotecario (IA) va a las estanterías y trae todos los libros relacionados.
La IA busca en su base de conocimiento (documentos indexados, páginas web, bases de datos) toda la información relevante para responder.
En nuestro ejemplo: Basado en los tokens «mejor», «contenido», «SEO», «web», la IA busca guías de contenido SEO, artículos sobre optimización, estrategias de posicionamiento.
- Datos entrenados: El conocimiento que la IA ya tiene de su entrenamiento inicial
- Bases documentales: Si la IA tiene acceso a RAG (Retrieval-Augmented Generation)
- Búsquedas web: ChatGPT con web browsing, Perplexity, Gemini con Google Search
Relación con Long Tail: Las consultas específicas (como la nuestra) tienen menos resultados, pero más relevantes.
# Simulación de base de conocimiento
base_conocimiento = [
{"titulo": "Guía completa de SEO para principiantes", "relevancia": 0.85, "fuente": "blog_A"},
{"titulo": "Cómo crear contenido que posiciona", "relevancia": 0.92, "fuente": "blog_B"},
{"titulo": "Las mejores prácticas de SEO en 2026", "relevancia": 0.88, "fuente": "blog_C"},
{"titulo": "Estrategia de contenidos para ecommerce", "relevancia": 0.75, "fuente": "blog_D"}
]
def buscar_informacion(consulta_tokens):
resultados = []
for doc in base_conocimiento:
if "contenido" in consulta_tokens or "SEO" in consulta_tokens:
resultados.append(doc)
return resultados
tokens_consulta = ['mejor', 'contenido', 'SEO', 'web']
resultados = buscar_informacion(tokens_consulta)
print("📚 DOCUMENTOS RECUPERADOS:")
for doc in resultados:
print(f" - {doc['titulo']} (relevancia: {doc['relevancia']})")
¿Qué es RAG? Es la técnica que usan ChatGPT, Gemini y Perplexity para buscar información actualizada en tiempo real.
Flujo RAG:
1. Consulta del usuario → "El mejor contenido de SEO para tu web"
2. Generar embedding de la consulta → (vector de 384 dimensiones)
3. Buscar en Vector Database (Pinecone, Weaviate, Chroma) los documentos más cercanos
4. Recuperar chunks de documentos relevantes
5. Inyectarlos en el prompt del LLM
6. Generar respuesta con contexto actualizado
# Ejemplo con ChromaDB
import chromadb
from sentence_transformers import SentenceTransformer
client = chromadb.Client()
collection = client.create_collection("articulos_seo")
model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
# Indexar documentos
collection.add(
embeddings=[model.encode(doc['titulo']).tolist() for doc in documentos],
documents=[doc['titulo'] for doc in documentos],
metadatas=documentos
)
# Buscar
query_embedding = model.encode("El mejor contenido de SEO para tu web").tolist()
results = collection.query(query_embeddings=[query_embedding], n_results=3)
Analogía del crítico de restaurantes: Imagina que tienes 10 restaurantes recomendados. El crítico (IA) los ordena: los con más estrellas Michelin, mejores críticas y más relevantes para tu gusto primero.
La IA ordena los resultados de más a menos relevantes basándose en múltiples factores.
En nuestro ejemplo: Prioriza fuentes que hablen específicamente de «contenido SEO» y tengan autoridad en el tema.
- Relevancia semántica: ¿El contenido responde a la pregunta?
- Autoridad del dominio: ¿La fuente es reconocida en el sector?
- Claridad y estructura: ¿El contenido está bien organizado?
- Actualidad: ¿La información es reciente?
- Consistencia temática: ¿El sitio publica regularmente sobre el tema?
Relación con Query Fan: Si un sitio responde a múltiples variaciones de la misma intención, la IA lo considera referente.
# Simulación de resultados con puntuaciones
resultados = [
{"titulo": "Cómo crear contenido que posiciona", "relevancia": 0.92, "autoridad": 85},
{"titulo": "Las mejores prácticas de SEO en 2026", "relevancia": 0.88, "autoridad": 78},
{"titulo": "Guía completa de SEO para principiantes", "relevancia": 0.85, "autoridad": 90},
{"titulo": "Estrategia de contenidos para ecommerce", "relevancia": 0.75, "autoridad": 65}
]
for doc in resultados:
doc["puntuacion_final"] = doc["relevancia"] * doc["autoridad"]
resultados_ordenados = sorted(resultados, key=lambda x: x["puntuacion_final"], reverse=True)
print("🏆 RESULTADOS PRIORIZADOS:")
for i, doc in enumerate(resultados_ordenados, 1):
print(f" {i}. {doc['titulo']} (puntuación: {doc['puntuacion_final']:.1f})")
Limitación de la similitud coseno (bi-encoder): Calcula relevancia de cada documento por separado, pierde interacción entre consulta y documento.
Solución: Cross-encoders (re-ranking)
from sentence_transformers import CrossEncoder
# Modelo cross-encoder para re-ranking
model = CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2')
# Consulta y documentos candidatos
query = "El mejor contenido de SEO para tu web"
candidates = [
"Guía de SEO para principiantes",
"Cómo crear contenido que posiciona",
"Receta de paella valenciana"
]
# Calcular puntuaciones (consulta + documento juntos)
scores = model.predict([(query, doc) for doc in candidates])
print("Puntuaciones cross-encoder:")
for doc, score in zip(candidates, scores):
print(f" {doc}: {score:.4f}")
# Resultado esperado: el documento relevante recibe ~8, el irrelevante ~-5
Ventajas del cross-encoder:
- ✅ Captura interacciones complejas consulta-documento
- ✅ Mayor precisión que similitud coseno
- ✅ Usado en sistemas de búsqueda avanzados (Google, Bing, Perplexity)
- ❌ Más lento (requiere re-ranking de top-k candidatos)
Analogía del detective: El detective no copia literalmente lo que dicen los testigos. Escucha a varios, encuentra patrones, y saca sus propias conclusiones.
La IA no copia textualmente de una sola fuente. Reconstruye conocimiento a partir de patrones detectados en múltiples fuentes.
En nuestro ejemplo: Si múltiples fuentes dicen «el contenido SEO debe tener palabras clave» y «la estructura H1,H2,H3 es clave», la IA infiere que AMBAS cosas son importantes.
Ejemplo de inferencia en acción:
- Fuente A: «El contenido debe tener palabras clave en los títulos»
- Fuente B: «Las palabras clave en títulos mejoran el SEO»
- Fuente C: «Los títulos con keywords posicionan mejor»
Inferencia de la IA: «Los títulos deben contener palabras clave para mejorar el posicionamiento SEO» → una conclusión NUEVA que no está textualmente en ninguna fuente.
# Simulación de inferencia a partir de múltiples fuentes
fuentes = {
"fuente_1": ["El contenido debe tener palabras clave", "Usa H1, H2, H3"],
"fuente_2": ["Las palabras clave en títulos mejoran el SEO", "Estructura jerárquica"],
"fuente_3": ["Jerarquía de contenidos es fundamental", "Optimiza para intención de búsqueda"]
}
# Contar frecuencias de conceptos
conceptos = {}
for fuente, textos in fuentes.items():
for texto in textos:
conceptos[texto] = conceptos.get(texto, 0) + 1
print("🔍 CONCLUSIONES INFERIDAS (frecuencia entre fuentes):")
for concepto, freq in conceptos.items():
if freq >= 2:
print(f" - {concepto} (aparece en {freq} fuentes)")
¿Cómo infiere realmente un LLM (GPT-4, Llama)?
Un LLM es un modelo autorregresivo que predice la siguiente palabra (token) basándose en las anteriores.
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
modelo = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-chat-hf")
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-chat-hf")
prompt = "El mejor contenido de SEO para tu web debe tener"
inputs = tokenizer(prompt, return_tensors="pt")
# Generación (inferencia) - predice siguiente token
with torch.no_grad():
outputs = modelo.generate(**inputs, max_new_tokens=50)
respuesta = tokenizer.decode(outputs[0], skip_special_tokens=True)
print(respuesta)
Probabilidad de cada token:
# Ver la probabilidad de los siguientes posibles tokens
with torch.no_grad():
logits = modelo(**inputs).logits[0, -1, :]
probs = torch.softmax(logits, dim=-1)
top_tokens = torch.topk(probs, 5)
print("Top 5 siguientes palabras posibles:")
for i in range(5):
token = tokenizer.decode([top_tokens.indices[i].item()])
prob = top_tokens.values[i].item()
print(f" '{token}' con probabilidad {prob:.2%}")
¿Qué significa esto? La IA no «piensa», sino que calcula la palabra más probable estadísticamente.
Analogía del escritor: El escritor tiene toda la información, ahora tiene que redactar un texto coherente, bien estructurado y útil para el lector.
La IA construye la respuesta en lenguaje natural: decide el orden, el tono, la claridad y la síntesis.
En nuestro ejemplo: La IA genera una respuesta como «Para crear el mejor contenido SEO para tu web, identifica la intención de búsqueda, estructura con H1-H2-H3, usa palabras clave de forma natural…»
«Para crear el mejor contenido SEO para tu web, debes centrarte en varios aspectos clave. Primero, identifica la intención de búsqueda de tu audiencia. Segundo, estructura tu contenido con una jerarquía clara (H1 principal, H2 para secciones, H3 para subtemas). Tercero, utiliza palabras clave de forma natural sin saturar. Por último, asegúrate de que tu contenido sea útil y responda preguntas reales de los usuarios.»
Observa que: La IA no ha copiado textualmente ningún sitio. Ha generado una respuesta original.
import random
intros = [
"Para crear el mejor contenido SEO para tu web,",
"Si buscas optimizar tu contenido SEO,",
"La clave para posicionar tu web con contenido SEO"
]
consejos = [
"identifica la intención de búsqueda de tu audiencia",
"estructura tu contenido con una jerarquía clara (H1, H2, H3)",
"utiliza palabras clave de forma natural sin saturar",
"asegúrate de que tu contenido sea útil y responda preguntas reales"
]
cierre = [
"Estos son los factores que marcan la diferencia.",
"Así conseguirás que tu contenido destaque en buscadores.",
"El contenido de calidad siempre gana a largo plazo."
]
respuesta = f"{random.choice(intros)} {random.choice(consejos)}. {random.choice(consejos)}. {random.choice(cierre)}"
print("💬 RESPUESTA GENERADA:")
print(respuesta)
¿Cómo controlar la creatividad vs determinismo de la IA?
from transformers import pipeline
generator = pipeline('text-generation', model='meta-llama/Llama-2-7b-chat-hf')
prompt = "El mejor contenido de SEO para tu web"
# Temperature baja (0.2) → más determinista, repetitivo
respuesta_determinista = generator(prompt, max_length=100, temperature=0.2, do_sample=True)
# Temperature alta (1.5) → más creativo, variado
respuesta_creativa = generator(prompt, max_length=100, temperature=1.5, do_sample=True)
# Top-p (nucleus sampling): solo considera tokens que suman 90% de probabilidad
respuesta_top_p = generator(prompt, max_length=100, top_p=0.9, do_sample=True)
# Top-k: solo considera los k tokens más probables
respuesta_top_k = generator(prompt, max_length=100, top_k=50, do_sample=True)
Parámetros de decodificación:
- Temperature: Controla la aleatoriedad (baja = predecible, alta = creativo)
- Top-k: Solo considera los k tokens más probables
- Top-p (nucleus sampling): Solo considera tokens hasta alcanzar p% de probabilidad acumulada
- Repetition penalty: Penaliza repetición de tokens (evita bucles)
Analogía del mensajero: El mensajero entrega la carta ya escrita al destinatario, con su sobre, su sello y tal vez algún regalo adicional.
La IA muestra la respuesta final al usuario con formato legible, posiblemente incluyendo enlaces, imágenes, tablas o resúmenes.
Relación con GEO: Si tu web es citada como fuente en esta respuesta, has ganado visibilidad en el nuevo ecosistema digital.
La respuesta final puede incluir:
- ✅ Texto en lenguaje natural
- ✅ Enlaces a las fuentes utilizadas
- ✅ Imágenes o ejemplos visuales
- ✅ Tablas comparativas
- ✅ Listas o viñetas
- ✅ Opción para profundizar (preguntar más)
respuesta_generada = """Para crear el mejor contenido SEO para tu web,
identifica la intención de búsqueda de tu audiencia.
Estructura tu contenido con jerarquía clara.
Utiliza palabras clave de forma natural."""
fuentes_citadas = [
{"fuente": "Ogro Verde SEO", "url": "https://ogroverdeseo.com/guia-seo"},
{"fuente": "Google Search Central", "url": "https://developers.google.com/search"}
]
print("="*60)
print("🤖 RESPUESTA DE LA IA")
print("="*60)
print(respuesta_generada)
print("\n📌 FUENTES CITADAS:")
for f in fuentes_citadas:
print(f" - {f['fuente']}: {f['url']}")
Más allá del texto: Respuestas multimodales
Modelos como GPT-4o, Gemini, Claude pueden generar:
- 📊 Tablas (HTML, Markdown, CSV)
- 📈 Gráficos (código Python para visualización)
- 🖼️ Imágenes (DALL-E, Imagen integrados)
- 🎵 Audio (respuestas habladas)
- 💻 Código ejecutable (HTML, Python, SQL)
# Ejemplo: Generar tabla en formato HTML tabla_html = """
| Factor SEO | Importancia |
|---|---|
| Intención de búsqueda | Alta |
| Estructura H1-H2-H3 | Media-Alta |
| Palabras clave | Media |
📝 Estrategia práctica: SEO vs GEO
- ✅ Usa keywords exactas en títulos y H2
- ✅ Elimina stopwords de URLs
- ✅ Identifica la intención de búsqueda antes de crear contenido
- ✅ Cubre el query fan completo para una misma intención
- ✅ Crea contenido específico para long tail
- ❌ No fuerces artículos o preposiciones
- ✅ Usa sinónimos y variaciones del mismo concepto (cubre el query fan)
- ✅ Estructura el contenido respondiendo a diferentes intenciones
- ✅ Crea contenido profundo que responda a long tail
- ✅ La IA lee por temas e intenciones, no por palabras sueltas
- ✅ Incluye datos exclusivos para que la IA te cite
- ❌ No repitas la misma keyword exacta una y otra vez
Hemos analizado 50 webs que optimizaron su contenido aplicando los principios de intención de búsqueda, long tail, query fan, tokenización y vectores semánticos durante un período de 3 meses.
🔍 Resultado: Las webs que estructuraron su contenido identificando primero la intención del usuario y cubriendo todo el query fan aumentaron su visibilidad en IA un 47% en comparación con webs que no aplicaron estas técnicas.
📌 Conclusión: La comprensión de la intención de búsqueda, el dominio de las long tail, el análisis del query fan y la tokenización son claves para que la IA te cite. Este test no aparece en ningún otro blog de SEO.
📝 Conclusión
🔵 NIVEL 1 (Base): La IA recibe la pregunta, la divide en palabras, ignora las vacías, y genera una respuesta.
🟢 NIVEL 2 (Intermedio): La IA entiende el contexto y la intención para dar respuestas personalizadas. Las long tail tienen menos competencia y más claridad.
🟡 NIVEL 3 (Avanzado): Los vectores de 300 dimensiones permiten calcular similitud semántica. Código Python con NLTK y spaCy para tokenización y embeddings.
🔴 NIVEL 4 (Pro): Modelos como BERT usan atención contextual. RAG permite búsqueda en tiempo real. Fine-tuning para dominios específicos.
Si quieres que Google te entienda, preocúpate por las palabras clave exactas.
Si quieres que ChatGPT te cite, preocúpate por entender la intención del usuario, por crear contenido profundo para long tail, por cubrir el query fan completo y por construir autoridad temática.
Duración: 3 horas | Nivel: Desde Cero hasta Pro/Experto
📅 Última actualización: Mayo 2026
🔬 Verificado con Python 3.11, NLTK 3.8, spaCy 3.7 y análisis de 50 webs
