"Be thorough, detailed, and written in the same didactic style as a "
"professional programming course text (not a summary/recap). "
"If is_break is True, skip all of this and just write a brief note "
"that this was a break (e.g. 'הפסקה — אין תוכן לימודי בקטע זה.')."
)
)
class ChunkOutline(BaseModel):
"""Lessons found within a single video chunk."""
lessons: list[Lesson] = Field(description="Ordered list of lessons in this chunk")
✏ העלאת הקבצים לגוגל
לגוגל יש Google File API שמאפשר לנו לשמור קבצים כדי שג'מיני יוכל לקרוא אותם. המנגנון מותאם לסוכנים ולא דורש מאתנו למחוק את הקבצים, גוגל ימחקו אותם אוטומטית אחרי כמה שעות. מנגנונים דומים קיימים גם ב Claude וגם ב OpenAI. הפונקציה הבאה מעלה קובץ ושומרת את המזהה שלו לצורך העברה לסוכן בהמשך התוכנית:
def upload_chunk(chunk_path: str, chunk_index: int) -> UploadedFile:
"""Upload a single chunk to Google File API."""
print(f" 📤 Uploading chunk {chunk_index} ({Path(chunk_path).name})...")
client = genai.Client()
t0 = time.time()
uploaded = client.files.upload(
file=chunk_path,
config={"display_name": Path(chunk_path).name},
)
elapsed = time.time() - t0
print(f" ↑ {elapsed:.0f}s, state={uploaded.state.name}")
while uploaded.state.name != "ACTIVE":
time.sleep(5)
uploaded = client.files.get(name=uploaded.name)
print(f" ✅ ACTIVE")
return UploadedFile(
file_id=uploaded.uri,
provider_name="google",
media_type=uploaded.mime_type or "video/mp4",
)
אחרי העלאה Google File API צריך זמן לעבד את הקובץ וזו הסיבה ללולאת ההמתנה שאנחנו רואים שמחכה שהקובץ יהיה מוכן.
✏ פיענוח השיעורים
החלק הבא הוא החלק המרכזי של התוכנית - מגדירים את הסוכן ומריצים אותו על Chunk שמכיל מספר שיעורים כדי להבין איזה שיעורים יש שם:
def build_agent() -> Agent:
"""Create the course-builder agent with Google Gemini."""
model = GoogleModel("gemini-3-flash-preview")
return Agent(
model,
output_type=ChunkOutline,
system_prompt=(
"You are an expert course builder and video content analyst. "
"You receive a SEGMENT (chunk) of a longer course recording and must "
"identify complete, self-contained lessons of 10-15 minutes each "
"within this segment.\n\n"
"CRITICAL RULES:\n"
"- Timestamps MUST be relative to THIS CHUNK (00:00:00 = chunk start)\n"
"- Only include lessons that are FULLY or MOSTLY contained in this chunk\n"
"- If a lesson is cut off at the start or end, do NOT include it — "
"the overlap with adjacent chunks will capture it\n"
"- Each lesson should be 10-15 minutes of coherent content\n"
"- Identify natural topic boundaries\n"
"- Create descriptive, URL-safe English slugs (lowercase, hyphens)\n"
"- Write comprehensive Hebrew markdown summaries including:\n"
" * Sub-topics covered\n"
" * ALL code snippets shown (in ``` code blocks)\n"
" * Links or references mentioned\n"
" * Key takeaways\n\n"
"BREAK-TIME DETECTION:\n"
"- Also detect BREAKS: segments with no teaching content, such as "
"coffee/lunch breaks, silence, students chatting among themselves, "
"the instructor stepping away, or any other non-lesson downtime.\n"
"- Treat a break exactly like a lesson entry — give it a start/end "
"timestamp — but set is_break=True and give it a short title such "
"as 'הפסקה'. The slug field is ignored for breaks, just put any "
"placeholder.\n"
"- For a break's summary_markdown_hebrew, just write a brief note "
"that this was a break (e.g. 'הפסקה — אין תוכן לימודי בקטע זה.'), "
"no need for a full lesson write-up.\n"