
Respuestas del foro creadas
-
Angel Sánchez
Miembro21 mayo, 2025 en 3:16 pm en respuesta a: Corregir error de Google Sheets OAuth2 API de Formularios con IA.json compartidoHola Alberto Ordaz,
Te comparto la información para crear tus credenciales y poder usar Google Sheets en n8n.
En la página donde se muestran los créditos, debes ingresar a Google Cloud Console. En la parte superior izquierda verás una opción que dice “Selecciona un proyecto”. Da clic ahí y luego selecciona la opción de “Crear proyecto”. Te recomiendo nombrarlo como “Proyecto N8N”. Adjunto una imagen de ejemplo.
Después de eso, regresa a tu flujo de trabajo en n8n, da doble clic en el nodo de Google Sheets, y en donde dice “Credential to connect with”, selecciona la opción “Create new credential”. Verás una ventana emergente. Donde dice “OAuth Redirect URL”, copia esa URL y pégala en un bloc de notas, ya que la usaremos más adelante. Esa URL debe contener algo como “localhost”. También anexo una imagen de ejemplo.
Ahora regresa a Google Cloud Console y sigue los pasos del siguiente video:
👉 https://www.youtube.com/watch?v=gZ6N2H3_vys-
En el segundo 00:33, es donde debes pegar la URL que copiaste previamente.
-
En el minuto 01:03, verás cómo se genera el Client ID y el Client Secret. Esos datos debes ingresarlos en el nodo de Google Sheets. También te anexo una imagen indicando dónde colocarlos.
-
En el minuto 01:43, verás cómo habilitar el acceso a Google Sheets. Una vez habilitado, regresa al nodo en n8n.
En el nodo de Google Sheets, ahora te aparecerá una opción que dice “Sign in with Google” (iniciar sesión con Google). Da clic ahí. Se abrirá una ventana emergente donde se te pedirá seleccionar tu cuenta de Google. Haz clic en tu cuenta.
Importante: Aparecerá una advertencia indicando que “Google no ha verificado esta aplicación”. En esa página, haz clic en “Configuración avanzada” y luego en “Ir a TUURL (no seguro)”. Después, se te informará que esa URL tendrá acceso a tu cuenta de Google. Haz clic en Aceptar.
Si todo sale bien, verás una página de confirmación indicando que el proceso se ha completado correctamente. También te anexo imágenes de referencia.
Me avisas si llegas hasta aquí con todo bien, ya que después de eso, tienes que crear la hoja de cálculo en tu drive y conectarla en el nodo.
-
-
Angel Sánchez
Miembro6 mayo, 2025 en 4:15 pm en respuesta a: Cómo configurar Session Key en Simple Memory en n8nHola Alejandro,
La Session Key sirve para identificar cada conversación. Cuando utilizas el disparador “When chat message received” con Simple Memory, se recomienda dejar la opción “Session ID” configurada como “Connected Chat Trigger Node”, para que en “Session Key From Previous Node” se utilice la variable {{ $json.sessionId }}.
Esto significa que cada vez que un usuario inicia el chat, se generará un identificador único que se utilizará durante toda la conversación. Si un nuevo usuario comienza otra conversación, se generará un nuevo ID. La variable que contiene estos identificadores es: {{ $json.sessionId }}. Adjunto una imagen como referencia.
En tu caso, si vas a utilizar WhatsApp, te recomiendo usar el número de teléfono como identificador de la sesión de chat. Este dato lo proporciona el nodo de WhatsApp, y te sugiero utilizar el valor que aparece en “from”. También adjunto una imagen para ilustrarlo.
-
Angel Sánchez
Miembro5 mayo, 2025 en 9:47 pm en respuesta a: Agente AI para convertir leads en clientes potenciales con WhatsApp APIProblemas en la configuración actual:
-
Mensaje del usuario no capturado:
En el campo “Prompt (User Message)” debe ir el mensaje del usuario. Como no lo habías colocado, el sistema no sabía qué contenido debía procesar. -
Ubicación del mensaje del sistema:
Lo que tenías antes en “Prompt (User Message)” en realidad debe ir en “System Message”. Te adjunto una imagen para que veas cómo debería estar estructurado este punto junto con el anterior. -
Uso de WhatsApp – Session Key:
Si vas a usar WhatsApp, te recomiendo usar el número del usuario como valor en “Session Key From Previous Node”. Actualmente lo tienes en “1”, pero ese ID es el que define la sesión de cada conversación. Si no lo cambias, todas las conversaciones se guardarán como si fueran de una sola persona. -
Context Window Length:
Este parámetro determina cuántos mensajes anteriores se mantienen en memoria. Te recomiendo establecerlo en alrededor de 50 para mantener un contexto útil sin sobrecargar la conversación. También adjunto imagen para este punto. -
Modelo de lenguaje:
El modelo que estás utilizando es bastante costoso. Te recomiendo cambiarlo a “gpt-4o-mini”, que ofrece una excelente calidad a un costo mucho más accesible.
Observaciones sobre el prompt:
La estructura actual del prompt no está optimizada para mantener una conversación en fases, y además hace referencia a elementos que no están disponibles o que requieren configuración adicional. A continuación te comparto algunos puntos específicos:
-
Inicio repetitivo:
Iniciar siempre la conversación con “Hola, soy Rafa Motte” puede hacer que las interacciones se sientan forzadas o poco naturales. Se puede plantear un inicio más flexible. -
Identificación del usuario (género y país):
Aunque es posible identificar estos datos mediante preguntas, si no los estás almacenando en alguna parte, no podrás usarlos posteriormente. Será necesario conectar una herramienta para guardar esta información (lo veremos más adelante). -
Invitación a sesiones por Zoom:
Si no tienes una herramienta automatizada para gestionar estas invitaciones, el asistente no podrá generarlas solo. Lo mejor sería dejar el enlace fijo dentro del prompt en caso de que aplique. También lo revisaremos más adelante. -
Archivos adjuntos:
Actualmente, si colocas PDFs dentro del prompt, el modelo no podrá leerlos directamente. Una mejor opción sería alojar los documentos en Google Docs o similar, y que el modelo acceda al contenido desde allí. -
Origen de la conversación (Meta, WhatsApp, etc.):
El modelo no tiene forma de saber desde dónde se originó la conversación, a menos que tú proporciones esa información. Por ahora, no tiene sentido dejar esa instrucción si no hay datos disponibles que lo respalden. -
Aprendizaje progresivo del modelo:
Lamentablemente, los modelos no aprenden automáticamente de cada conversación. Nosotros nos conectamos a modelos que ya están entrenados, y no tienen la capacidad de incorporar nuevos aprendizajes tras cada interacción (más allá del contexto de la conversación activa).
Entiendo bien lo que estás intentando hacer. Sin embargo, hay varios puntos importantes que necesitan corregirse y otros que requieren más conocimientos técnicos. Por eso, mi recomendación es que sigas el proceso que tenemos planeado en las clases y cursos. A medida que avancemos, te será mucho más fácil implementar todo esto correctamente.
-
Angel Sánchez
Miembro5 mayo, 2025 en 9:48 pm en respuesta a: Agente AI para convertir leads en clientes potenciales con WhatsApp APITe adjunto un archivo .json con los ajustes para que puedas hacer pruebas.
-
-
Angel Sánchez
Miembro5 mayo, 2025 en 8:37 pm en respuesta a: Agente AI para convertir leads en clientes potenciales con WhatsApp APIHola Alejandro,
¿Podrías compartir tu flujo de trabajo para que podamos revisarlo? También sería útil una captura de pantalla que muestre el resultado que mencionas.
Te adjunto una imagen con los pasos para exportar tu flujo en n8n. Esto generará un archivo .json que puedes subir aquí. Si la plataforma no te permite subirlo directamente, por favor comprímelo en un .rar y súbelo así.
¡Muchas gracias!
-
Claro. Lo que pasa es que al principio puede parecer innecesario hacer un atributo privado (__tematica) si de todos modos vas a crear métodos para acceder y modificar su valor. Pero el punto real no es simplemente ocultarlo, sino tener control sobre cómo se accede o modifica.
En tu ejemplo, se usa property() para que puedas usar navidad.tematica como si fuera un atributo normal, pero internamente está pasando por los métodos _get_tematica y _set_tematica. Esto te permite, por ejemplo, más adelante poner validaciones, imprimir logs, calcular un valor en tiempo real, etc., sin cambiar la forma en que se usa desde fuera.
Te doy un ejemplo simple con validación, que muestra por qué esto es útil:
class GalletaConTematica:
def __init__(self, tematica):
self.__tematica = tematica
def get_tematica(self):
return self.__tematica
def set_tematica(self, value):
if value in ["Navidad", "Pascua", "Halloween"]:
self.__tematica = value
else:
print("Temática no válida")
tematica = property(get_tematica, set_tematica)
galleta = GalletaConTematica("Navidad")
print(galleta.tematica)
galleta.tematica = "Cumpleaños" # Este cambio no se permite
print(galleta.tematica)
Sin los métodos, no podrías evitar que alguien pusiera un valor que no tiene sentido para tu lógica. En resumen: sí, en este primer ejemplo no se ve tan necesario, pero cuando tu código crece, tener ese control se vuelve muy útil. Y usar property() te deja tener ese control sin cambiar la forma en que accedes a los datos desde fuera.
-
Angel Sánchez
Miembro10 marzo, 2025 en 12:55 am en respuesta a: ¿Por qué los datos en JSON no coinciden con los de un archivo .pickle?Hola 😀
El problema es bastante común cuando trabajamos con diferentes formatos de almacenamiento de datos en Python.
JSON y pickle funcionan de manera diferente:
- JSON solo puede guardar tipos básicos (diccionarios, listas, textos, números), pero no sabe qué es una “clase” de Python.
- Pickle es específico de Python y guarda toda la información de los objetos, incluyendo a qué clase pertenecen.
Cuando guardas objetos de tu clase Patient en JSON, pierden su identidad como instancias de Patient y se convierten en simples diccionarios. Por eso, al compararlos con los objetos guardados en pickle, aparecen como diferentes.
La solución es crear un sistema para que JSON pueda recordar que esos datos pertenecían a la clase Patient:
# Cuando guardas en JSON, añade información sobre la clase
def convertir_patient_a_json(obj):
if isinstance(obj, Patient):
return {
"__class__": "Patient", # Marcador que indica la clase
"id": obj.id,
"name": obj.name,
"surname": obj.surname,
"age": obj.age,
"diabetic": obj.diabetic
}
raise TypeError(f"No puedo convertir {type(obj)} a JSON")
# Cuando lees del JSON, reconstruye los objetos Patient
def reconstruir_patient_desde_json(obj):
if "__class__" in obj and obj["__class__"] == "Patient":
return Patient(
id=obj["id"],
name=obj["name"],
surname=obj["surname"],
age=obj["age"],
diabetic=obj["diabetic"]
)
return obj
Al usar estas funciones con json.dump() y json.load(), podrás mantener la información de clase al guardar y recuperar datos en formato JSON, haciendo que sean más comparables con los datos guardados en pickle.
Dime si todo quedó claro o puedo ayudarte en algo más 😀
-
Angel Sánchez
Miembro28 febrero, 2025 en 3:55 pm en respuesta a: Error al instalar Scrapy: Falta Microsoft Visual C++ 14.0 en WindowsVeo que estás intentando instalar Scrapy en Windows 64 bits, pero estás encontrando un error con las dependencias. El error principal indica que necesitas Microsoft Visual C++ 14.0 o superior para compilar algunas de las dependencias de Scrapy.
El mensaje de error específico es:
distutils.errors.DistutilsPlatformError: Microsoft Visual C++ 14.0 or greater is required. Get it with "Microsoft C++ Build Tools": https://visualstudio.microsoft.com/visual-cpp-build-tools/
Para resolver este problema, necesitas seguir estos pasos:
-
Instala las herramientas de compilación de Microsoft C++:
- Descarga e instala Microsoft C++ Build Tools desde: https://visualstudio.microsoft.com/visual-cpp-build-tools/
- Durante la instalación, asegúrate de seleccionar “Herramientas de compilación de C++” o “Desktop development with C++”
-
Después de instalar Microsoft C++ Build Tools, intenta nuevamente instalar Scrapy:
pip install scrapy
-
Alternativa: Si prefieres no instalar las herramientas de compilación, puedes intentar usar wheels precompilados:
pip install wheel pip install scrapy
-
Otra alternativa: Usar Anaconda/Miniconda, que maneja mejor las dependencias en Windows (No recomendable ya que no se ve en los cursos):
- Instala Anaconda o Miniconda
- Crea un entorno:
conda create -n scraping python=3.9
- Activa el entorno:
conda activate scraping
- Instala Scrapy:
conda install -c conda-forge scrapy
¿Has intentado alguna de estas opciones anteriormente? ¿O necesitas más detalles sobre alguno de estos pasos?
-
-
Puedes validar si ya todo está solucionado, por favor 😀
-
Estoy resolviendo eso, Carlos. En un momento te confirmaré cuando todo esté listo.
-
Angel Sánchez
Miembro6 mayo, 2025 en 8:00 pm en respuesta a: Cómo configurar Session Key en Simple Memory en n8nGenial 👏
-
Angel Sánchez
Miembro10 marzo, 2025 en 5:22 pm en respuesta a: ¿Por qué los datos en JSON no coinciden con los de un archivo .pickle?Hola 😀
-
En la Imagen 1 (JSON) tienes un formato donde cada paciente es una lista con valores ordenados:
"1": [1, "Juan", "Perez", 42, "S1"]
-
En la Imagen 2 (objetos originales) tienes instancias de la clase Patient:
Patient(id=1, name=Juan, surname=Perez, age=42, diabetic=S1)
El problema es que tu JSON no está guardando los nombres de los atributos, solo los valores en una lista. Esto hace que cuando lo cargas, no puedas reconstruir automáticamente los objetos Patient.
Aquí hay una solución que debería funcionar mejor:
import json import pickle from collections import namedtuple # Definición de la clase (similar a lo que muestras) Patient = namedtuple('_Patient', ['id', 'name', 'surname', 'age', 'diabetic']) # Función para convertir Patient a un formato que JSON entienda mejor def patient_encoder(obj): if isinstance(obj, Patient): # Convertimos a diccionario con nombres de atributos return { "__class__": "Patient", "id": obj.id, "name": obj.name, "surname": obj.surname, "age": obj.age, "diabetic": obj.diabetic } # Si es un diccionario con pacientes elif isinstance(obj, dict) and all(isinstance(k, str) for k in obj.keys()): result = {} for key, value in obj.items(): if isinstance(value, Patient): result[key] = patient_encoder(value) else: result[key] = value return result raise TypeError(f"No se puede serializar objeto de tipo {type(obj)}") # Para guardar en JSON con formato adecuado with open("patients.json", "w") as f: json.dump(patients_dict, f, default=patient_encoder, indent=2) # Para reconstruir los objetos Patient al leer def patient_decoder(obj): if "__class__" in obj and obj["__class__"] == "Patient": return Patient( id=obj["id"], name=obj["name"], surname=obj["surname"], age=obj["age"], diabetic=obj["diabetic"] ) return obj # Para cargar desde JSON recuperando los objetos Patient with open("patients.json", "r") as f: patients_from_json = json.load(f, object_hook=patient_decoder)
La clave está en cambiar el formato JSON para que guarde cada paciente como un objeto con atributos nombrados, en lugar de una lista. Con esto, al cargar el JSON podrás reconstruir los objetos Patient exactamente igual que los originales.
Un último consejo: para comprobar si los datos cargados desde JSON y pickle son iguales, puedes usar una comparación así:
# Comparar si son iguales (una vez cargados ambos) are_equal = all(patients_from_json[key] == patients_from_pickle[key] for key in patients_from_json) print(f"¿Son iguales? {are_equal}")
-
-
Angel Sánchez
Miembro4 marzo, 2025 en 8:52 am en respuesta a: Error al instalar Scrapy: Falta Microsoft Visual C++ 14.0 en WindowsOtra cosa, puedes subir directo las imágenes al foro sin problemas, en vez de un documento 😀
-
Angel Sánchez
Miembro4 marzo, 2025 en 8:51 am en respuesta a: Error al instalar Scrapy: Falta Microsoft Visual C++ 14.0 en WindowsEl error sugiere que hay un problema con la compilación de algunas dependencias, específicamente relacionadas con la librería lxml.
Aquí hay algunos pasos que puede intentar:
- Actualizar pip y setuptools:
python -m pip install --upgrade pip setuptools wheel
- Instalar lxml por separado antes de Scrapy:
pip install lxml
- Si lo anterior no funciona, pruebe instalar Scrapy usando una rueda (wheel) precompilada:
pip install scrapy --only-binary=:all:
Si ninguno de estos métodos funciona, por favor comparte:
- Tu versión de Python
- Tu versión de Windows
- El error completo
Me avisas si funciona 😀
-
Angel Sánchez
Miembro20 noviembre, 2024 en 6:55 pm en respuesta a: Error al definir una funcion en VSC¿Al final lograste resolver tu problema?
Redes sociales.