Contenido del curso
Interfaces de la API y streaming
Function calling y salidas estructuradas
Reducción de costos con caching y batch
Ingeniería de producción y control de calidad
Proyecto final de consultas sobre documentos
Generar contenido por canal
Resumen
Generar contenido por canal con OpenAI significa crear piezas listas para publicar que respetan las particularidades de LinkedIn, Twitter (hoy X) o Instagram, partiendo de una sola idea. Si construyes flujos de contenido automatizado con Python, aquí verás cómo encadenar un brief estructurado con una función que produce el post final, adaptado al tono y la audiencia de cada plataforma.
El punto clave es que el formato de publicación cambia drásticamente entre canales, y en lugar de escribir prompts sueltos, usamos un brief estructurado como base para que la salida sea coherente y detallada.
Por qué el formato de contenido cambia entre LinkedIn, Twitter e Instagram
Un reel de Instagram no se escribe igual que un post de LinkedIn ni que un texto en X. Cada canal tiene su ritmo, su tono y su audiencia, y por eso la clase parte de una idea central: aprovechar el brief estructurado que ya teníamos y adaptarlo a cada plataforma [00:12].
La ventaja de este enfoque es que no partes de cero cada vez. Tomas una idea sencilla, la conviertes en un brief técnico y de ahí generas la pieza final. Todo con dos funciones encadenadas.
¿Qué es un brief estructurado en generación de contenido? Es un formato de datos que organiza título, tono y audiencia de una idea antes de escribir el post. Sirve como base intermedia para que la pieza final sea más rica y detallada.
Cómo definir el modelo ContentPiece con clases en Python
Lo primero es crear un tipo de dato para la pieza de contenido. Se define una clase llamada ContentPiece que recibe cuatro campos, todos de tipo string [00:38]:
- channel: el canal donde se va a publicar.
- title: el título de la pieza.
- body: el cuerpo o descripción del contenido.
- call_to_action: la invitación final para el lector.
Este modelo se guarda en el archivo de models, junto al CampaignBrief que ya existía, para importarlo donde haga falta [00:54]. Tener el modelo definido te da estructura garantizada en la respuesta.
Cómo crear la función generateContentPiece en el cliente de OpenAI
Dentro del archivo del OpenAI Client agregamos la función generateContentPiece [01:10]. Esta recibe un brief del tipo CampaignBrief y el canal como string, y devuelve un ContentPiece.
Dentro se usa un response llamado clientResponsesParse con el mismo modelo que se venía trabajando. La instrucción es directa: genera una pieza de contenido lista para publicar, respeta el brief, el canal, el tono y la audiencia, y responde siempre en español [01:34].
El input combina el brief usando model dump, una funcionalidad que entrega Pydantic para volcar los datos del modelo, más el canal que llega por parámetro [01:50]. El text format es el propio ContentPiece, y se retorna el output parse para que la respuesta llegue ya con el formato especificado.
¿Para qué sirve model dump en Pydantic? Convierte los datos de un modelo en un formato que puedes pasar como input al prompt. Así el brief completo viaja limpio hacia la función que genera el contenido.
Un detalle importante: hay que importar ContentPiece arriba junto al CampaignBrief para que el retorno y el text format aparezcan reconocidos como tipo [02:20].
Cómo crear el endpoint /content que encadena brief y pieza
En el archivo de server agregamos un nuevo endpoint debajo de brief, llamado /content, con la función content [02:36]. Recibe dos parámetros que vienen desde un formulario: una idea y un canal.
Aquí ocurren dos pasos encadenados que son el corazón del flujo [02:56]:
- Se define un brief pasando la idea por la función de generar brief estructurado de la clase anterior.
- Se crea la variable piece, que llama a generateContentPiece con ese brief y el channel recibido.
Finalmente el endpoint retorna un HTML con el título del piece, el canal, el cuerpo renderizado y el call to action antes del botón de volver [03:26]. Ambas funciones, generateStructuredBrief y generateContentPiece, deben importarse arriba para que queden reconocidas [03:40].
Cómo agregar el formulario de contenido por canal en la interfaz
En el home, dentro del slash, ya existían dos formularios: el básico de Operations Studio y el de convertir una idea en brief. Se agrega un tercero para generar contenido por canal [04:10].
Ese formulario usa método post con acción hacia /content. Incluye un text area para la idea y un selector con tres canales: Twitter, LinkedIn e Instagram, más el botón de generar contenido [04:30].
Qué demuestra el resultado sobre no alucinar datos
Al probar en el navegador con la idea "un contenido para un evento de AI en Springfield" y el canal LinkedIn, la respuesta llega con título, canal y descripción completa [05:20].
El título generado fue: "Springfield se prepara para su gran cita con la inteligencia artificial", y el call to action pedía seguir la página y comentar "quiero asistir" para recibir novedades [05:44].
Y aquí viene lo interesante. En la idea original nunca se mencionó fecha, lugar, agenda ni speakers. En vez de inventar esos datos, el modelo escribió que "muy pronto compartiremos más detalles sobre fecha, sede, agenda, speakers invitados" [06:24]. Es decir, evitó la pregunta obvia del lector sin alucinar información que no tenía.
Ese comportamiento es clave: el contenido usa exactamente la información que le diste, y cuando falta un dato, lo maneja en vez de inventarlo.
Cómo funciona el flujo completo de idea a pieza publicable
Recapitulando el proceso en orden [06:50]:
- Pasas una idea sencilla en el input, por ejemplo "haz un post para anunciar un evento de AI en X ciudad".
- Esa idea entra a generar brief estructurado, que responde con título y todo el formato de datos definido.
- Ese brief nunca lo ves en la interfaz ni en la terminal: va directo a la función que genera la pieza de contenido.
- La pieza es la que produce el render final con título, descripción y call to action.
El paso intermedio del brief es lo que hace que el texto salga mucho más enriquecido y detallado, en vez de un post plano generado desde una sola línea.
Si tu approach es diferente pero funciona, puedes compararlo con la rama final de cada clase en el repositorio. ¿Para qué otros canales generarías contenido específico con este flujo? Cuéntamelo en los comentarios.