feat: Add proper thread handling in content generation
- Detect threads by template name and skip platform truncation - Parse thread content into individual posts with numbering - Add thread_posts array to API response with post details - Evaluate quality on first post (hook) for threads - Add is_thread and thread_posts fields to GenerateV2Response Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -164,12 +164,37 @@ class ContentGeneratorV2:
|
||||
|
||||
content = response.choices[0].message.content.strip()
|
||||
|
||||
# 6. Adaptar a plataforma
|
||||
# 6. Detectar si es un hilo (no adaptar, devolver posts separados)
|
||||
is_thread = template_name == "thread"
|
||||
|
||||
if is_thread:
|
||||
# Parsear posts del hilo
|
||||
thread_posts = self._parse_thread_posts(content)
|
||||
|
||||
return {
|
||||
"content": content,
|
||||
"adapted_content": content, # No truncar hilos
|
||||
"is_thread": True,
|
||||
"thread_posts": thread_posts,
|
||||
"truncated": False,
|
||||
"metadata": {
|
||||
"template": template_name,
|
||||
"personality": rendered["personality"],
|
||||
"platform": platform,
|
||||
"temperature": temperature,
|
||||
"tokens_used": response.usage.total_tokens if response.usage else None,
|
||||
"changes_made": [],
|
||||
"num_posts": len(thread_posts),
|
||||
}
|
||||
}
|
||||
|
||||
# 7. Adaptar a plataforma (solo para contenido normal)
|
||||
adapted = self.plt_adapter.adapt(content, platform)
|
||||
|
||||
return {
|
||||
"content": content,
|
||||
"adapted_content": adapted.content,
|
||||
"is_thread": False,
|
||||
"truncated": adapted.truncated,
|
||||
"metadata": {
|
||||
"template": template_name,
|
||||
@@ -181,6 +206,55 @@ class ContentGeneratorV2:
|
||||
}
|
||||
}
|
||||
|
||||
def _parse_thread_posts(self, content: str) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
Parsear el contenido de un hilo en posts individuales.
|
||||
|
||||
Args:
|
||||
content: Contenido completo del hilo
|
||||
|
||||
Returns:
|
||||
Lista de dicts con cada post y sus metadatos
|
||||
"""
|
||||
import re
|
||||
|
||||
posts = []
|
||||
|
||||
# Intentar separar por patrones de numeración: "1/", "2/", "1)", "2)"
|
||||
# Buscar patrones como "\n1/" o inicio con "1/"
|
||||
numbered_pattern = r'(?:^|\n)(\d+)[/\)]\s*'
|
||||
|
||||
# Encontrar todas las posiciones de inicio de posts numerados
|
||||
matches = list(re.finditer(numbered_pattern, content))
|
||||
|
||||
if matches and len(matches) >= 2:
|
||||
# Extraer posts basándose en las posiciones
|
||||
for i, match in enumerate(matches):
|
||||
start = match.start()
|
||||
# El fin es el inicio del siguiente match o el final del contenido
|
||||
end = matches[i + 1].start() if i + 1 < len(matches) else len(content)
|
||||
|
||||
post_content = content[start:end].strip()
|
||||
post_num = int(match.group(1))
|
||||
|
||||
posts.append({
|
||||
"number": post_num,
|
||||
"content": post_content,
|
||||
"char_count": len(post_content)
|
||||
})
|
||||
else:
|
||||
# Fallback: separar por doble salto de línea
|
||||
raw_posts = [p.strip() for p in content.split("\n\n") if p.strip()]
|
||||
|
||||
for i, post_content in enumerate(raw_posts, 1):
|
||||
posts.append({
|
||||
"number": i,
|
||||
"content": post_content,
|
||||
"char_count": len(post_content)
|
||||
})
|
||||
|
||||
return posts
|
||||
|
||||
# === Métodos de Conveniencia ===
|
||||
|
||||
async def generate_tip(
|
||||
|
||||
Reference in New Issue
Block a user