Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/slidedeckai/agents/content_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,10 @@ def generate_subtitle(self, slide_title: str, purpose: str,
return "Analysis"

def generate_bullets(self, slide_title: str, purpose: str,
search_facts: List[str], max_bullets: int = 5) -> List[str]:
search_facts: List[str], max_bullets: int = 5,
max_words_per_bullet: int = 15) -> List[str]:
"""
Generate bullet points from search facts
Generate bullet points from search facts with strict length control
"""

facts_text = "\n".join(search_facts) if search_facts else "No data available"
Expand All @@ -78,7 +79,7 @@ def generate_bullets(self, slide_title: str, purpose: str,

Requirements:
- Generate EXACTLY {max_bullets} bullet points
- Each bullet: 10-20 words
- Each bullet MUST be under {max_words_per_bullet} words to fit layout
- Include QUANTITATIVE data (numbers, percentages)
- Professional, executive-level tone
- NO preamble, ONLY bullet points
Expand Down
34 changes: 31 additions & 3 deletions src/slidedeckai/agents/execution_orchestrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,11 +278,18 @@ def _gen_for_ph(ph_id, ph_info):
)
return (ph_id, {'type': 'kpi', 'kpi_data': kpi})
else:
max_bullets = self._calculate_max_bullets(ph_info.get('area', 5))
max_words = self._calculate_word_limit(
ph_info.get('width', 5),
ph_info.get('height', 5),
max_bullets
)
bullets = self.content_generator.generate_bullets(
section.section_title,
section.section_purpose,
relevant_facts,
max_bullets=self._calculate_max_bullets(ph_info.get('area', 5))
max_bullets=max_bullets,
max_words_per_bullet=max_words
)
return (ph_id, {'type': 'bullets', 'bullets': bullets})
except Exception as e:
Expand Down Expand Up @@ -1037,13 +1044,19 @@ def _fill_content(self, placeholder, ph_id: int, ph_info: Dict,
if query.query in search_results:
relevant_facts.extend(search_results[query.query])

max_bullets = self._calculate_max_bullets(ph_info['area'])
max_bullets = self._calculate_max_bullets(ph_info.get('area', 5))
max_words = self._calculate_word_limit(
ph_info.get('width', 0),
ph_info.get('height', 0),
max_bullets
)

bullets = self.content_generator.generate_bullets(
section.section_title,
section.section_purpose,
relevant_facts,
max_bullets=max_bullets
max_bullets=max_bullets,
max_words_per_bullet=max_words
)

text_frame = placeholder.text_frame
Expand Down Expand Up @@ -1089,6 +1102,21 @@ def _calculate_max_bullets(self, area: float) -> int:
else:
return 10

def _calculate_word_limit(self, width: float, height: float, max_bullets: int) -> int:
"""Calculate max words per bullet to fit in placeholder"""
if height <= 0 or width <= 0 or max_bullets <= 0:
return 15

# Estimate based on standard 18pt font (~0.3 inch line height)
lines_available = height / 0.3
lines_per_bullet = lines_available / max_bullets

# Estimate words per line (width * 8 chars/inch / 6 chars/word)
words_per_line = (width * 8) / 6

limit = int(lines_per_bullet * words_per_line)
return max(5, min(limit, 40)) # Clamp between 5 and 40

def _calculate_font_size_from_area(self, area: float, size_type: str) -> int:
"""FIX #4: Calculate from template base size"""
from pptx.util import Pt
Expand Down