454 lines
23 KiB
Python
454 lines
23 KiB
Python
"""
|
|
LinkedIn Content Generation Models for ALwrity
|
|
|
|
This module defines the data models for LinkedIn content generation endpoints.
|
|
Enhanced to support grounding capabilities with source integration and quality metrics.
|
|
"""
|
|
|
|
from pydantic import BaseModel, Field, validator
|
|
from typing import List, Optional, Dict, Any, Literal
|
|
from datetime import datetime
|
|
from enum import Enum
|
|
|
|
|
|
class LinkedInPostType(str, Enum):
|
|
"""Types of LinkedIn posts."""
|
|
PROFESSIONAL = "professional"
|
|
THOUGHT_LEADERSHIP = "thought_leadership"
|
|
INDUSTRY_NEWS = "industry_news"
|
|
PERSONAL_STORY = "personal_story"
|
|
COMPANY_UPDATE = "company_update"
|
|
POLL = "poll"
|
|
|
|
|
|
class LinkedInTone(str, Enum):
|
|
"""LinkedIn content tone options."""
|
|
PROFESSIONAL = "professional"
|
|
CONVERSATIONAL = "conversational"
|
|
AUTHORITATIVE = "authoritative"
|
|
INSPIRATIONAL = "inspirational"
|
|
EDUCATIONAL = "educational"
|
|
FRIENDLY = "friendly"
|
|
|
|
|
|
class SearchEngine(str, Enum):
|
|
"""Available search engines for research."""
|
|
METAPHOR = "metaphor"
|
|
GOOGLE = "google"
|
|
TAVILY = "tavily"
|
|
|
|
|
|
class GroundingLevel(str, Enum):
|
|
"""Levels of content grounding."""
|
|
NONE = "none"
|
|
BASIC = "basic"
|
|
ENHANCED = "enhanced"
|
|
ENTERPRISE = "enterprise"
|
|
|
|
|
|
class LinkedInPostRequest(BaseModel):
|
|
"""Request model for LinkedIn post generation."""
|
|
topic: str = Field(..., description="Main topic for the post", min_length=3, max_length=200)
|
|
industry: str = Field(..., description="Target industry context", min_length=2, max_length=100)
|
|
post_type: LinkedInPostType = Field(default=LinkedInPostType.PROFESSIONAL, description="Type of LinkedIn post")
|
|
tone: LinkedInTone = Field(default=LinkedInTone.PROFESSIONAL, description="Tone of the post")
|
|
target_audience: Optional[str] = Field(None, description="Specific target audience", max_length=200)
|
|
key_points: Optional[List[str]] = Field(None, description="Key points to include", max_items=10)
|
|
include_hashtags: bool = Field(default=True, description="Whether to include hashtags")
|
|
include_call_to_action: bool = Field(default=True, description="Whether to include call to action")
|
|
research_enabled: bool = Field(default=True, description="Whether to include research-backed content")
|
|
search_engine: SearchEngine = Field(default=SearchEngine.GOOGLE, description="Search engine for research")
|
|
max_length: int = Field(default=3000, description="Maximum character count", ge=100, le=3000)
|
|
grounding_level: GroundingLevel = Field(default=GroundingLevel.ENHANCED, description="Level of content grounding")
|
|
include_citations: bool = Field(default=True, description="Whether to include inline citations")
|
|
user_id: Optional[int] = Field(default=1, description="User id for persona lookup")
|
|
persona_override: Optional[Dict[str, Any]] = Field(default=None, description="Session-only persona overrides to apply without saving")
|
|
|
|
class Config:
|
|
json_schema_extra = {
|
|
"example": {
|
|
"topic": "AI in healthcare transformation",
|
|
"industry": "Healthcare",
|
|
"post_type": "thought_leadership",
|
|
"tone": "professional",
|
|
"target_audience": "Healthcare executives and professionals",
|
|
"key_points": ["AI diagnostics", "Patient outcomes", "Cost reduction"],
|
|
"include_hashtags": True,
|
|
"include_call_to_action": True,
|
|
"research_enabled": True,
|
|
"search_engine": "google",
|
|
"max_length": 2000,
|
|
"grounding_level": "enhanced",
|
|
"include_citations": True
|
|
}
|
|
}
|
|
|
|
|
|
class LinkedInArticleRequest(BaseModel):
|
|
"""Request model for LinkedIn article generation."""
|
|
topic: str = Field(..., description="Main topic for the article", min_length=3, max_length=200)
|
|
industry: str = Field(..., description="Target industry context", min_length=2, max_length=100)
|
|
tone: LinkedInTone = Field(default=LinkedInTone.PROFESSIONAL, description="Tone of the article")
|
|
target_audience: Optional[str] = Field(None, description="Specific target audience", max_length=200)
|
|
key_sections: Optional[List[str]] = Field(None, description="Key sections to include", max_items=10)
|
|
include_images: bool = Field(default=True, description="Whether to generate image suggestions")
|
|
seo_optimization: bool = Field(default=True, description="Whether to include SEO optimization")
|
|
research_enabled: bool = Field(default=True, description="Whether to include research-backed content")
|
|
search_engine: SearchEngine = Field(default=SearchEngine.GOOGLE, description="Search engine for research")
|
|
word_count: int = Field(default=1500, description="Target word count", ge=500, le=5000)
|
|
grounding_level: GroundingLevel = Field(default=GroundingLevel.ENHANCED, description="Level of content grounding")
|
|
include_citations: bool = Field(default=True, description="Whether to include inline citations")
|
|
user_id: Optional[int] = Field(default=1, description="User id for persona lookup")
|
|
persona_override: Optional[Dict[str, Any]] = Field(default=None, description="Session-only persona overrides to apply without saving")
|
|
|
|
class Config:
|
|
json_schema_extra = {
|
|
"example": {
|
|
"topic": "Digital transformation in manufacturing",
|
|
"industry": "Manufacturing",
|
|
"tone": "professional",
|
|
"target_audience": "Manufacturing leaders and technology professionals",
|
|
"key_sections": ["Current challenges", "Technology solutions", "Implementation strategies"],
|
|
"include_images": True,
|
|
"seo_optimization": True,
|
|
"research_enabled": True,
|
|
"search_engine": "google",
|
|
"word_count": 2000,
|
|
"grounding_level": "enhanced",
|
|
"include_citations": True
|
|
}
|
|
}
|
|
|
|
|
|
class LinkedInCarouselRequest(BaseModel):
|
|
"""Request model for LinkedIn carousel generation."""
|
|
topic: str = Field(..., description="Main topic for the carousel", min_length=3, max_length=200)
|
|
industry: str = Field(..., description="Target industry context", min_length=2, max_length=100)
|
|
tone: LinkedInTone = Field(default=LinkedInTone.PROFESSIONAL, description="Tone of the carousel")
|
|
target_audience: Optional[str] = Field(None, description="Specific target audience", max_length=200)
|
|
number_of_slides: int = Field(default=5, description="Number of slides", ge=3, le=10)
|
|
include_cover_slide: bool = Field(default=True, description="Whether to include a cover slide")
|
|
include_cta_slide: bool = Field(default=True, description="Whether to include a call-to-action slide")
|
|
research_enabled: bool = Field(default=True, description="Whether to include research-backed content")
|
|
search_engine: SearchEngine = Field(default=SearchEngine.GOOGLE, description="Search engine for research")
|
|
grounding_level: GroundingLevel = Field(default=GroundingLevel.ENHANCED, description="Level of content grounding")
|
|
include_citations: bool = Field(default=True, description="Whether to include inline citations")
|
|
|
|
class Config:
|
|
json_schema_extra = {
|
|
"example": {
|
|
"topic": "Future of remote work",
|
|
"industry": "Technology",
|
|
"tone": "professional",
|
|
"target_audience": "HR professionals and business leaders",
|
|
"number_of_slides": 6,
|
|
"include_cover_slide": True,
|
|
"include_cta_slide": True,
|
|
"research_enabled": True,
|
|
"search_engine": "google",
|
|
"grounding_level": "enhanced",
|
|
"include_citations": True
|
|
}
|
|
}
|
|
|
|
|
|
class LinkedInVideoScriptRequest(BaseModel):
|
|
"""Request model for LinkedIn video script generation."""
|
|
topic: str = Field(..., description="Main topic for the video script", min_length=3, max_length=200)
|
|
industry: str = Field(..., description="Target industry context", min_length=2, max_length=100)
|
|
tone: LinkedInTone = Field(default=LinkedInTone.PROFESSIONAL, description="Tone of the video script")
|
|
target_audience: Optional[str] = Field(None, description="Specific target audience", max_length=200)
|
|
video_duration: int = Field(default=60, description="Target video duration in seconds", ge=30, le=300)
|
|
include_captions: bool = Field(default=True, description="Whether to include captions")
|
|
include_thumbnail_suggestions: bool = Field(default=True, description="Whether to include thumbnail suggestions")
|
|
research_enabled: bool = Field(default=True, description="Whether to include research-backed content")
|
|
search_engine: SearchEngine = Field(default=SearchEngine.GOOGLE, description="Search engine for research")
|
|
grounding_level: GroundingLevel = Field(default=GroundingLevel.ENHANCED, description="Level of content grounding")
|
|
include_citations: bool = Field(default=True, description="Whether to include inline citations")
|
|
|
|
class Config:
|
|
json_schema_extra = {
|
|
"example": {
|
|
"topic": "Cybersecurity best practices",
|
|
"industry": "Technology",
|
|
"tone": "educational",
|
|
"target_audience": "IT professionals and business leaders",
|
|
"video_duration": 90,
|
|
"include_captions": True,
|
|
"include_thumbnail_suggestions": True,
|
|
"research_enabled": True,
|
|
"search_engine": "google",
|
|
"grounding_level": "enhanced",
|
|
"include_citations": True
|
|
}
|
|
}
|
|
|
|
|
|
class LinkedInCommentResponseRequest(BaseModel):
|
|
"""Request model for LinkedIn comment response generation."""
|
|
original_comment: str = Field(..., description="Original comment to respond to", min_length=10, max_length=1000)
|
|
post_context: str = Field(..., description="Context of the post being commented on", min_length=10, max_length=500)
|
|
industry: str = Field(..., description="Industry context", min_length=2, max_length=100)
|
|
tone: LinkedInTone = Field(default=LinkedInTone.FRIENDLY, description="Tone of the response")
|
|
response_length: str = Field(default="medium", description="Length of response: short, medium, long")
|
|
include_questions: bool = Field(default=True, description="Whether to include engaging questions")
|
|
research_enabled: bool = Field(default=False, description="Whether to include research-backed content")
|
|
search_engine: SearchEngine = Field(default=SearchEngine.GOOGLE, description="Search engine for research")
|
|
grounding_level: GroundingLevel = Field(default=GroundingLevel.BASIC, description="Level of content grounding")
|
|
|
|
class Config:
|
|
json_schema_extra = {
|
|
"example": {
|
|
"original_comment": "Great insights on AI implementation!",
|
|
"post_context": "Post about AI transformation in healthcare",
|
|
"industry": "Healthcare",
|
|
"tone": "friendly",
|
|
"response_length": "medium",
|
|
"include_questions": True,
|
|
"research_enabled": False,
|
|
"search_engine": "google",
|
|
"grounding_level": "basic"
|
|
}
|
|
}
|
|
|
|
|
|
# Enhanced Research Source Model
|
|
class ResearchSource(BaseModel):
|
|
"""Enhanced model for research source information with grounding capabilities."""
|
|
title: str
|
|
url: str
|
|
content: str
|
|
relevance_score: Optional[float] = Field(None, description="Relevance score (0.0-1.0)")
|
|
credibility_score: Optional[float] = Field(None, description="Credibility score (0.0-1.0)")
|
|
domain_authority: Optional[float] = Field(None, description="Domain authority score (0.0-1.0)")
|
|
source_type: Optional[str] = Field(None, description="Type of source (academic, business_news, etc.)")
|
|
publication_date: Optional[str] = Field(None, description="Publication date if available")
|
|
raw_result: Optional[Dict[str, Any]] = Field(None, description="Raw search result data")
|
|
|
|
|
|
# Enhanced Hashtag Suggestion Model
|
|
class HashtagSuggestion(BaseModel):
|
|
"""Enhanced model for hashtag suggestions."""
|
|
hashtag: str
|
|
category: str
|
|
popularity_score: Optional[float] = Field(None, description="Popularity score (0.0-1.0)")
|
|
relevance_score: Optional[float] = Field(None, description="Relevance to topic (0.0-1.0)")
|
|
industry_alignment: Optional[float] = Field(None, description="Industry alignment score (0.0-1.0)")
|
|
|
|
|
|
# Enhanced Image Suggestion Model
|
|
class ImageSuggestion(BaseModel):
|
|
"""Enhanced model for image suggestions."""
|
|
description: str
|
|
alt_text: str
|
|
style: Optional[str] = Field(None, description="Visual style description")
|
|
placement: Optional[str] = Field(None, description="Suggested placement in content")
|
|
relevance_score: Optional[float] = Field(None, description="Relevance to content (0.0-1.0)")
|
|
|
|
|
|
# New Quality Metrics Model
|
|
class ContentQualityMetrics(BaseModel):
|
|
"""Model for content quality assessment metrics."""
|
|
overall_score: float = Field(..., description="Overall quality score (0.0-1.0)")
|
|
factual_accuracy: float = Field(..., description="Factual accuracy score (0.0-1.0)")
|
|
source_verification: float = Field(..., description="Source verification score (0.0-1.0)")
|
|
professional_tone: float = Field(..., description="Professional tone score (0.0-1.0)")
|
|
industry_relevance: float = Field(..., description="Industry relevance score (0.0-1.0)")
|
|
citation_coverage: float = Field(..., description="Citation coverage score (0.0-1.0)")
|
|
content_length: int = Field(..., description="Content length in characters")
|
|
word_count: int = Field(..., description="Word count")
|
|
analysis_timestamp: str = Field(..., description="Timestamp of quality analysis")
|
|
recommendations: Optional[List[str]] = Field(default_factory=list, description="List of improvement recommendations")
|
|
|
|
|
|
# New Citation Model
|
|
class Citation(BaseModel):
|
|
"""Model for inline citations in content."""
|
|
type: str = Field(..., description="Type of citation (inline, footnote, etc.)")
|
|
reference: str = Field(..., description="Citation reference (e.g., 'Source 1')")
|
|
position: Optional[int] = Field(None, description="Position in content")
|
|
source_index: Optional[int] = Field(None, description="Index of source in research_sources")
|
|
|
|
|
|
# Enhanced Post Content Model
|
|
class PostContent(BaseModel):
|
|
"""Enhanced model for generated post content with grounding capabilities."""
|
|
content: str
|
|
character_count: int
|
|
hashtags: List[HashtagSuggestion]
|
|
call_to_action: Optional[str] = None
|
|
engagement_prediction: Optional[Dict[str, Any]] = None
|
|
citations: List[Citation] = Field(default_factory=list, description="Inline citations")
|
|
source_list: Optional[str] = Field(None, description="Formatted source list")
|
|
quality_metrics: Optional[ContentQualityMetrics] = Field(None, description="Content quality metrics")
|
|
grounding_enabled: bool = Field(default=False, description="Whether grounding was used")
|
|
search_queries: Optional[List[str]] = Field(default_factory=list, description="Search queries used for research")
|
|
|
|
|
|
# Enhanced Article Content Model
|
|
class ArticleContent(BaseModel):
|
|
"""Enhanced model for generated article content with grounding capabilities."""
|
|
title: str
|
|
content: str
|
|
word_count: int
|
|
sections: List[Dict[str, str]]
|
|
seo_metadata: Optional[Dict[str, Any]] = None
|
|
image_suggestions: List[ImageSuggestion]
|
|
reading_time: Optional[int] = None
|
|
citations: List[Citation] = Field(default_factory=list, description="Inline citations")
|
|
source_list: Optional[str] = Field(None, description="Formatted source list")
|
|
quality_metrics: Optional[ContentQualityMetrics] = Field(None, description="Content quality metrics")
|
|
grounding_enabled: bool = Field(default=False, description="Whether grounding was used")
|
|
search_queries: Optional[List[str]] = Field(default_factory=list, description="Search queries used for research")
|
|
|
|
|
|
# Enhanced Carousel Slide Model
|
|
class CarouselSlide(BaseModel):
|
|
"""Enhanced model for carousel slide content."""
|
|
slide_number: int
|
|
title: str
|
|
content: str
|
|
visual_elements: List[str]
|
|
design_notes: Optional[str] = None
|
|
citations: List[Citation] = Field(default_factory=list, description="Inline citations for this slide")
|
|
|
|
|
|
# Enhanced Carousel Content Model
|
|
class CarouselContent(BaseModel):
|
|
"""Enhanced model for generated carousel content with grounding capabilities."""
|
|
title: str
|
|
slides: List[CarouselSlide]
|
|
cover_slide: Optional[CarouselSlide] = None
|
|
cta_slide: Optional[CarouselSlide] = None
|
|
design_guidelines: Dict[str, str]
|
|
citations: List[Citation] = Field(default_factory=list, description="Overall citations")
|
|
source_list: Optional[str] = Field(None, description="Formatted source list")
|
|
quality_metrics: Optional[ContentQualityMetrics] = Field(None, description="Content quality metrics")
|
|
grounding_enabled: bool = Field(default=False, description="Whether grounding was used")
|
|
|
|
|
|
# Enhanced Video Script Model
|
|
class VideoScript(BaseModel):
|
|
"""Enhanced model for video script content with grounding capabilities."""
|
|
hook: str
|
|
main_content: List[Dict[str, str]] # scene_number, content, duration, visual_notes
|
|
conclusion: str
|
|
captions: Optional[List[str]] = None
|
|
thumbnail_suggestions: List[str]
|
|
video_description: str
|
|
citations: List[Citation] = Field(default_factory=list, description="Inline citations")
|
|
source_list: Optional[str] = Field(None, description="Formatted source list")
|
|
quality_metrics: Optional[ContentQualityMetrics] = Field(None, description="Content quality metrics")
|
|
grounding_enabled: bool = Field(default=False, description="Whether grounding was used")
|
|
|
|
|
|
# Enhanced LinkedIn Post Response Model
|
|
class LinkedInPostResponse(BaseModel):
|
|
"""Enhanced response model for LinkedIn post generation with grounding capabilities."""
|
|
success: bool = True
|
|
data: Optional[PostContent] = None
|
|
research_sources: List[ResearchSource] = []
|
|
generation_metadata: Dict[str, Any] = {}
|
|
error: Optional[str] = None
|
|
grounding_status: Optional[Dict[str, Any]] = Field(None, description="Grounding operation status")
|
|
|
|
class Config:
|
|
json_schema_extra = {
|
|
"example": {
|
|
"success": True,
|
|
"data": {
|
|
"content": "🚀 AI is revolutionizing healthcare...",
|
|
"character_count": 1250,
|
|
"hashtags": [
|
|
{"hashtag": "#AIinHealthcare", "category": "industry", "popularity_score": 0.9},
|
|
{"hashtag": "#DigitalTransformation", "category": "general", "popularity_score": 0.8}
|
|
],
|
|
"call_to_action": "What's your experience with AI in healthcare? Share in the comments!",
|
|
"engagement_prediction": {"estimated_likes": 120, "estimated_comments": 15},
|
|
"citations": [
|
|
{"type": "inline", "reference": "Source 1", "position": 45}
|
|
],
|
|
"source_list": "**Sources:**\n1. **AI in Healthcare: Current Trends**\n - URL: [https://example.com/ai-healthcare](https://example.com/ai-healthcare)",
|
|
"quality_metrics": {
|
|
"overall_score": 0.85,
|
|
"factual_accuracy": 0.9,
|
|
"source_verification": 0.8,
|
|
"professional_tone": 0.9,
|
|
"industry_relevance": 0.85,
|
|
"citation_coverage": 0.8,
|
|
"content_length": 1250,
|
|
"word_count": 180,
|
|
"analysis_timestamp": "2025-01-15T10:30:00Z"
|
|
},
|
|
"grounding_enabled": True
|
|
},
|
|
"research_sources": [
|
|
{
|
|
"title": "AI in Healthcare: Current Trends",
|
|
"url": "https://example.com/ai-healthcare",
|
|
"content": "Summary of AI healthcare trends...",
|
|
"relevance_score": 0.95,
|
|
"credibility_score": 0.85,
|
|
"domain_authority": 0.9,
|
|
"source_type": "business_news"
|
|
}
|
|
],
|
|
"generation_metadata": {
|
|
"model_used": "gemini-2.0-flash-001",
|
|
"generation_time": 3.2,
|
|
"research_time": 5.1,
|
|
"grounding_enabled": True
|
|
},
|
|
"grounding_status": {
|
|
"status": "success",
|
|
"sources_used": 3,
|
|
"citation_coverage": 0.8,
|
|
"quality_score": 0.85
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
# Enhanced LinkedIn Article Response Model
|
|
class LinkedInArticleResponse(BaseModel):
|
|
"""Enhanced response model for LinkedIn article generation with grounding capabilities."""
|
|
success: bool = True
|
|
data: Optional[ArticleContent] = None
|
|
research_sources: List[ResearchSource] = []
|
|
generation_metadata: Dict[str, Any] = {}
|
|
error: Optional[str] = None
|
|
grounding_status: Optional[Dict[str, Any]] = Field(None, description="Grounding operation status")
|
|
|
|
|
|
# Enhanced LinkedIn Carousel Response Model
|
|
class LinkedInCarouselResponse(BaseModel):
|
|
"""Enhanced response model for LinkedIn carousel generation with grounding capabilities."""
|
|
success: bool = True
|
|
data: Optional[CarouselContent] = None
|
|
research_sources: List[ResearchSource] = []
|
|
generation_metadata: Dict[str, Any] = {}
|
|
error: Optional[str] = None
|
|
grounding_status: Optional[Dict[str, Any]] = Field(None, description="Grounding operation status")
|
|
|
|
|
|
# Enhanced LinkedIn Video Script Response Model
|
|
class LinkedInVideoScriptResponse(BaseModel):
|
|
"""Enhanced response model for LinkedIn video script generation with grounding capabilities."""
|
|
success: bool = True
|
|
data: Optional[VideoScript] = None
|
|
research_sources: List[ResearchSource] = []
|
|
generation_metadata: Dict[str, Any] = {}
|
|
error: Optional[str] = None
|
|
grounding_status: Optional[Dict[str, Any]] = Field(None, description="Grounding operation status")
|
|
|
|
|
|
# Enhanced LinkedIn Comment Response Result Model
|
|
class LinkedInCommentResponseResult(BaseModel):
|
|
"""Enhanced response model for LinkedIn comment response generation with grounding capabilities."""
|
|
success: bool = True
|
|
response: Optional[str] = None
|
|
alternative_responses: List[str] = []
|
|
tone_analysis: Optional[Dict[str, Any]] = None
|
|
generation_metadata: Dict[str, Any] = {}
|
|
error: Optional[str] = None
|
|
grounding_status: Optional[Dict[str, Any]] = Field(None, description="Grounding operation status") |