fix(fastapi): issues when using google genai as client

This commit is contained in:
sauravniraula 2025-07-16 21:08:23 +05:45
parent ca42467bcf
commit c9aa3b07b0
No known key found for this signature in database
GPG key ID: 60FCC1B5A5E83326
3 changed files with 28 additions and 180 deletions

View file

@ -10,7 +10,7 @@ from models.presentation_layout import PresentationLayoutModel
from models.presentation_structure_model import PresentationStructureModel
from models.presentation_with_slides import PresentationWithSlides
from models.sql.slide import SlideModel
from models.sse_response import SSECompleteResponse, SSEResponse
from models.sse_response import SSECompleteResponse, SSEResponse, SSEStatusResponse
from services import TEMP_FILE_SERVICE
from services.database import get_sql_session
from services.documents_loader import DocumentsLoader
@ -140,6 +140,7 @@ async def stream_presentation(presentation_id: str):
slide_content = await get_slide_content_from_type_and_outline(
slide_layout, outline.slides[i]
)
print(slide_content)
slide = SlideModel(
presentation=presentation_id,
layout=slide_layout.id,
@ -150,6 +151,7 @@ async def stream_presentation(presentation_id: str):
event="response",
data=json.dumps({"type": "chunk", "chunk": slide.model_dump_json()}),
).to_string()
yield SSEResponse(
event="response",
data=json.dumps({"type": "chunk", "chunk": " ] }"}),

View file

@ -16,54 +16,43 @@ class ContactInfoModel(BaseModel):
# First Slide Layout
class FirstSlideModel(BaseModel):
title: str = Field(
"Welcome to Our Presentation",
min_length=3,
max_length=100,
description="Main title of the presentation",
)
subtitle: Optional[str] = Field(
None, min_length=10, max_length=200, description="Optional subtitle or tagline"
min_length=10, max_length=200, description="Optional subtitle or tagline"
)
author: Optional[str] = Field(
"John Doe",
min_length=2,
max_length=100,
description="Author or presenter name",
)
date: Optional[str] = Field(None, description="Presentation date")
date: Optional[str] = Field(description="Presentation date")
company: Optional[str] = Field(
"Company Name",
min_length=2,
max_length=100,
description="Company or organization name",
)
backgroundImage: Optional[HttpUrl] = Field(
None, description="URL to background image for the slide"
description="URL to background image for the slide"
)
# Bullet Point Slide Layout
class BulletPointSlideModel(BaseModel):
title: str = Field(
"Key Points",
min_length=3,
max_length=100,
description="Title of the slide",
)
subtitle: Optional[str] = Field(
None,
min_length=3,
max_length=150,
description="Optional subtitle or description",
)
icon: Optional[str] = Field(None, description="Icon to display in the slide")
icon: Optional[str] = Field(description="Icon to display in the slide")
bulletPoints: List[str] = Field(
[
"First key point that highlights important information",
"Second bullet point with valuable insights",
"Third point demonstrating clear benefits",
"Fourth item showcasing key features",
],
min_length=2,
max_length=8,
description="List of bullet points (2-8 items)",
@ -73,35 +62,30 @@ class BulletPointSlideModel(BaseModel):
# Image Slide Layout
class ImageSlideModel(BaseModel):
title: str = Field(
"Image Showcase",
min_length=3,
max_length=100,
description="Title of the slide",
)
subtitle: Optional[str] = Field(
"Subtitle for the slide",
min_length=3,
max_length=150,
description="Optional subtitle or description",
)
image: HttpUrl = Field(
"https://images.unsplash.com/photo-1460925895917-afdab827c52f?w=800&h=600&fit=crop",
description="Main image URL",
)
imageCaption: Optional[str] = Field(
"Image caption",
min_length=5,
max_length=200,
description="Optional image caption or description",
)
content: Optional[str] = Field(
None,
min_length=10,
max_length=600,
description="Optional supporting content text",
)
backgroundImage: Optional[HttpUrl] = Field(
None, description="URL to background image for the slide"
description="URL to background image for the slide"
)
@ -116,10 +100,9 @@ class StatisticItemModel(BaseModel):
min_length=3, max_length=100, description="Description of the statistic"
)
trend: Optional[str] = Field(
None, description="Trend direction indicator", pattern="^(up|down|neutral)$"
description="Trend direction indicator", pattern="^(up|down|neutral)$"
)
context: Optional[str] = Field(
None,
min_length=5,
max_length=200,
description="Additional context or time period",
@ -128,88 +111,56 @@ class StatisticItemModel(BaseModel):
class StatisticsSlideModel(BaseModel):
title: str = Field(
"Key Statistics",
min_length=3,
max_length=100,
description="Title of the slide",
)
subtitle: Optional[str] = Field(
None,
min_length=3,
max_length=150,
description="Optional subtitle or description",
)
statistics: List[StatisticItemModel] = Field(
[
StatisticItemModel(
value="250%",
label="Revenue Growth",
trend="up",
context="Year over year increase",
),
StatisticItemModel(
value="50M+",
label="Active Users",
trend="up",
context="Global user base",
),
StatisticItemModel(
value="99.9%",
label="Uptime",
trend="neutral",
context="Service reliability",
),
StatisticItemModel(
value="24/7",
label="Support",
trend="neutral",
context="Customer service",
),
],
min_length=2,
max_length=6,
description="List of statistics (2-6 items)",
)
backgroundImage: Optional[HttpUrl] = Field(
None, description="URL to background image for the slide"
description="URL to background image for the slide"
)
# Quote Slide Layout
class QuoteSlideModel(BaseModel):
title: str = Field(
"Testimonials",
min_length=3,
max_length=100,
description="Title of the slide",
)
subtitle: Optional[str] = Field(
None,
min_length=3,
max_length=150,
description="Optional subtitle or description",
)
quote: str = Field(
"This solution has transformed our business operations and exceeded all expectations.",
min_length=10,
max_length=500,
description="The main quote or testimonial",
)
author: str = Field(
"John Smith",
min_length=2,
max_length=100,
description="Quote author name",
)
authorTitle: Optional[str] = Field(
None, min_length=2, max_length=100, description="Author job title or position"
min_length=2, max_length=100, description="Author job title or position"
)
company: Optional[str] = Field(
None, min_length=2, max_length=100, description="Author company or organization"
min_length=2, max_length=100, description="Author company or organization"
)
authorImage: Optional[HttpUrl] = Field(None, description="URL to author photo")
authorImage: Optional[HttpUrl] = Field(description="URL to author photo")
backgroundImage: Optional[HttpUrl] = Field(
None, description="URL to background image for the slide"
description="URL to background image for the slide"
)
@ -223,7 +174,6 @@ class TimelineItemModel(BaseModel):
min_length=10, max_length=300, description="Event description"
)
status: str = Field(
"upcoming",
description="Timeline item status",
pattern="^(completed|current|upcoming)$",
)
@ -231,50 +181,22 @@ class TimelineItemModel(BaseModel):
class TimelineSlideModel(BaseModel):
title: str = Field(
"Project Timeline",
min_length=3,
max_length=100,
description="Title of the slide",
)
subtitle: Optional[str] = Field(
None,
min_length=3,
max_length=150,
description="Optional subtitle or description",
)
timelineItems: List[TimelineItemModel] = Field(
[
TimelineItemModel(
date="Q1 2024",
title="Project Initiation",
description="Project planning, team assembly, and initial requirements gathering",
status="completed",
),
TimelineItemModel(
date="Q2 2024",
title="Development Phase",
description="Core development work, prototype creation, and testing implementation",
status="current",
),
TimelineItemModel(
date="Q3 2024",
title="Testing & QA",
description="Comprehensive testing, quality assurance, and user acceptance testing",
status="upcoming",
),
TimelineItemModel(
date="Q4 2024",
title="Launch & Deployment",
description="Final deployment, go-live activities, and post-launch monitoring",
status="upcoming",
),
],
min_length=2,
max_length=6,
description="Timeline events (2-6 items)",
)
backgroundImage: Optional[HttpUrl] = Field(
None, description="URL to background image for the slide"
description="URL to background image for the slide"
)
@ -282,63 +204,34 @@ class TimelineSlideModel(BaseModel):
class TeamMemberModel(BaseModel):
name: str = Field(min_length=2, max_length=100, description="Team member name")
title: str = Field(min_length=2, max_length=100, description="Job title or role")
image: Optional[HttpUrl] = Field(None, description="URL to team member photo")
image: Optional[HttpUrl] = Field(description="URL to team member photo")
bio: Optional[str] = Field(
None,
min_length=10,
max_length=300,
description="Brief biography or description",
)
email: Optional[EmailStr] = Field(None, description="Contact email")
linkedin: Optional[HttpUrl] = Field(None, description="LinkedIn profile URL")
email: Optional[EmailStr] = Field(description="Contact email")
linkedin: Optional[HttpUrl] = Field(description="LinkedIn profile URL")
class TeamSlideModel(BaseModel):
title: str = Field(
"Meet Our Team",
min_length=3,
max_length=100,
description="Title of the slide",
)
subtitle: Optional[str] = Field(
None,
min_length=3,
max_length=150,
description="Optional subtitle or team description",
)
teamMembers: List[TeamMemberModel] = Field(
[
TeamMemberModel(
name="Sarah Johnson",
title="Chief Executive Officer",
image="https://images.unsplash.com/photo-1494790108755-2616b612b786?w=300&h=300&fit=crop&crop=face",
bio="Strategic leader with 15+ years experience driving innovation and growth in technology companies.",
email="sarah@company.com",
linkedin="https://linkedin.com/in/sarahjohnson",
),
TeamMemberModel(
name="Michael Chen",
title="Chief Technology Officer",
image="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=300&h=300&fit=crop&crop=face",
bio="Technology visionary specializing in scalable architecture and emerging technologies.",
email="michael@company.com",
linkedin="https://linkedin.com/in/michaelchen",
),
TeamMemberModel(
name="Emma Rodriguez",
title="Head of Design",
image="https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=300&h=300&fit=crop&crop=face",
bio="Creative director passionate about user-centered design and innovative digital experiences.",
email="emma@company.com",
linkedin="https://linkedin.com/in/emmarodriguez",
),
],
min_length=1,
max_length=6,
description="Team members (1-6 people)",
)
backgroundImage: Optional[HttpUrl] = Field(
None, description="URL to background image for the slide"
description="URL to background image for the slide"
)
@ -353,46 +246,22 @@ class ProcessStepModel(BaseModel):
class ProcessSlideModel(BaseModel):
title: str = Field(
"Our Process",
min_length=3,
max_length=100,
description="Title of the slide",
)
subtitle: Optional[str] = Field(
None,
min_length=3,
max_length=150,
description="Optional subtitle or description",
)
processSteps: List[ProcessStepModel] = Field(
[
ProcessStepModel(
step=1,
title="Discovery",
description="Understanding requirements and gathering initial insights",
),
ProcessStepModel(
step=2,
title="Planning",
description="Strategic planning and roadmap development",
),
ProcessStepModel(
step=3,
title="Implementation",
description="Executing the plan with precision and quality",
),
ProcessStepModel(
step=4,
title="Delivery",
description="Final delivery and ongoing support",
),
],
min_length=2,
max_length=6,
description="Process steps (2-6 items)",
)
backgroundImage: Optional[HttpUrl] = Field(
None, description="URL to background image for the slide"
description="URL to background image for the slide"
)
@ -404,97 +273,75 @@ class ColumnContentModel(BaseModel):
class TwoColumnSlideModel(BaseModel):
title: str = Field(
"Two Column Layout",
min_length=3,
max_length=100,
description="Title of the slide",
)
subtitle: Optional[str] = Field(
None,
min_length=3,
max_length=150,
description="Optional subtitle or description",
)
leftColumn: ColumnContentModel = Field(
ColumnContentModel(
title="Left Column",
content="Content for the left column goes here. This can include detailed information, explanations, or supporting details.",
),
description="Left column content",
)
rightColumn: ColumnContentModel = Field(
ColumnContentModel(
title="Right Column",
content="Content for the right column goes here. This can include additional information, comparisons, or contrasting details.",
),
description="Right column content",
)
backgroundImage: Optional[HttpUrl] = Field(
None, description="URL to background image for the slide"
description="URL to background image for the slide"
)
# Conclusion Slide Layout
class ConclusionSlideModel(BaseModel):
title: str = Field(
"Conclusion",
min_length=3,
max_length=100,
description="Title of the slide",
)
subtitle: Optional[str] = Field(
None,
min_length=3,
max_length=150,
description="Optional subtitle or description",
)
keyTakeaways: List[str] = Field(
[
"Successfully achieved our primary objectives",
"Demonstrated significant value and impact",
"Established clear next steps for continued success",
"Built strong foundation for future growth",
],
min_length=2,
max_length=6,
description="Key takeaways or summary points (2-6 items)",
)
callToAction: Optional[str] = Field(
None,
min_length=5,
max_length=150,
description="Optional call to action or next steps",
)
contactInfo: Optional[ContactInfoModel] = Field(
None, description="Optional contact information"
description="Optional contact information"
)
backgroundImage: Optional[HttpUrl] = Field(
None, description="URL to background image for the slide"
description="URL to background image for the slide"
)
# Content Slide Layout
class ContentSlideModel(BaseModel):
title: str = Field(
"Slide Title",
min_length=3,
max_length=100,
description="Title of the slide",
)
subtitle: Optional[str] = Field(
None,
min_length=3,
max_length=150,
description="Optional subtitle or description",
)
content: str = Field(
"Your slide content goes here. This is where you can add detailed information, explanations, or any other text content that supports your presentation.",
min_length=10,
max_length=1000,
description="Main content text",
)
backgroundImage: Optional[HttpUrl] = Field(
None, description="URL to background image for the slide"
description="URL to background image for the slide"
)
@ -560,6 +407,6 @@ presentation_layout = PresentationLayoutModel(
],
)
# print(presentation_layout.model_dump_json())
print(presentation_layout.model_dump_json())
print(PresentationOutlineModel.model_json_schema())
# print(PresentationOutlineModel.model_json_schema())

View file

@ -72,15 +72,14 @@ async def get_slide_content_from_type_and_outline(
return json.loads(response.choices[0].message.content)
else:
client = get_google_llm_client()
user_prompt = get_user_prompt(outline.title, outline.body)
response = await asyncio.to_thread(
client.models.generate_content,
model=model,
contents=[user_prompt],
contents=[get_user_prompt(outline.title, outline.body)],
config=GenerateContentConfig(
system_instruction=system_prompt,
response_mime_type="application/json",
response_json_schema=slide_layout.json_schema,
),
)
return response.model_dump(mode="json")
return response.text