feat: rich character profiles — brand voice, target, rules, hashtag profiles

Backend:
- Character model: add brand_voice, target_audience, business_goals,
  products_services, content_rules (JSON do/dont), hashtag_profiles (JSON)
- Content generation: inject full character context into LLM system prompt
  (voice, audience, goals, products, rules)
- Hashtag generation: merge always-on tags from profile with AI-generated tags
- Schema: update CharacterBase and CharacterUpdate with new fields

Frontend:
- CharacterForm: new sections "Identità e Voce", "Regole Contenuti",
  "Profili Hashtag" with dedicated editors
- RulesEditor: do/don't list with add/remove
- HashtagProfileEditor: per-platform tabs, fixed hashtags + max generated count
- All fields loaded on edit, saved on submit

DB migration: 6 new columns added to characters table

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Michele
2026-04-04 16:34:25 +02:00
parent 8629d145a8
commit befa8b4adc
5 changed files with 290 additions and 14 deletions

View File

@@ -20,7 +20,9 @@ def generate_post_text(
"""Generate social media post text based on a character profile.
Args:
character: Dict with keys: name, niche, topics (list), tone (str).
character: Dict with keys: name, niche, topics (list), tone (str),
and optional rich profile: brand_voice, target_audience,
business_goals, products_services, content_rules.
topic_hint: Optional topic suggestion to guide generation.
llm_provider: LLM provider instance for text generation.
platform: Target platform (e.g. 'instagram', 'facebook', 'tiktok', 'youtube').
@@ -36,18 +38,56 @@ def generate_post_text(
topics_str = ", ".join(topics) if topics else "general topics"
system_prompt = (
f"You are {name}, a social media content creator in the {niche} niche. "
f"Your expertise covers: {topics_str}. "
f"Your communication style is {tone}. "
f"You create authentic, engaging content that resonates with your audience. "
f"Never reveal you are an AI. Write as {name} would naturally write.\n\n"
f"REGOLA CRITICA: Se ti viene indicata una tecnica narrativa (PAS, AIDA, Storytelling, ecc.), "
f"usala SOLO come struttura invisibile del testo. "
f"NON scrivere MAI le etichette del framework nel post (es. non scrivere 'PROBLEMA:', "
f"'AGITAZIONE:', 'SOLUZIONE:', 'ATTENZIONE:', 'INTERESSE:', ecc.). "
f"Il lettore non deve percepire alcun framework — deve sembrare un post naturale e spontaneo."
)
# Base identity
system_parts = [
f"You are {name}, a social media content creator in the {niche} niche.",
f"Your expertise covers: {topics_str}.",
f"Your communication style is {tone}.",
]
# Rich profile: brand voice
brand_voice = character.get("brand_voice")
if brand_voice:
system_parts.append(f"\nVOCE E STILE DI COMUNICAZIONE:\n{brand_voice}")
# Rich profile: target audience
target_audience = character.get("target_audience")
if target_audience:
system_parts.append(f"\nPUBBLICO TARGET:\n{target_audience}")
# Rich profile: business goals
business_goals = character.get("business_goals")
if business_goals:
system_parts.append(f"\nOBIETTIVI BUSINESS:\n{business_goals}")
# Rich profile: products/services
products_services = character.get("products_services")
if products_services:
system_parts.append(f"\nPRODOTTI/SERVIZI OFFERTI:\n{products_services}")
# Rich profile: content rules (do/don't)
content_rules = character.get("content_rules") or {}
do_rules = content_rules.get("do", [])
dont_rules = content_rules.get("dont", [])
if do_rules or dont_rules:
rules_text = "\nREGOLE CONTENUTI:"
if do_rules:
rules_text += "\nFA SEMPRE: " + " | ".join(do_rules)
if dont_rules:
rules_text += "\nNON FARE MAI: " + " | ".join(dont_rules)
system_parts.append(rules_text)
system_parts.extend([
"\nYou create authentic, engaging content that resonates with your audience.",
"Never reveal you are an AI. Write as {name} would naturally write.",
"\nREGOLA CRITICA: Se ti viene indicata una tecnica narrativa (PAS, AIDA, Storytelling, ecc.), "
"usala SOLO come struttura invisibile del testo. "
"NON scrivere MAI le etichette del framework nel post (es. non scrivere 'PROBLEMA:', "
"'AGITAZIONE:', 'SOLUZIONE:', 'ATTENZIONE:', 'INTERESSE:', ecc.). "
"Il lettore non deve percepire alcun framework — deve sembrare un post naturale e spontaneo.",
])
system_prompt = "\n".join(system_parts)
# Platform-specific instructions
platform_guidance = {