factorstudios commited on
Commit
70ac245
·
verified ·
1 Parent(s): 34b3740

Create instructor.py

Browse files
Files changed (1) hide show
  1. instructor.py +99 -0
instructor.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Instructor module for generating storytelling briefs from trending topics."""
2
+ import os
3
+ import json
4
+ import logging
5
+ from typing import Any, Dict, List, Optional
6
+ from base_agent import BaseAgent
7
+ from config import settings
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+ class Instructor(BaseAgent):
12
+ """Instructor Agent: Fuses trending topics into storytelling briefs.
13
+
14
+ This agent uses Instructor.md as a persistent pre-prompt and calls the
15
+ DashScope API using the Qwen model specified in the environment.
16
+ """
17
+
18
+ def __init__(self):
19
+ """Initialize the Instructor agent with guidelines from Instructor.md."""
20
+ # Load guidelines from the root folder
21
+ content = self._load_instructor_md()
22
+
23
+ # Construct the full system prompt (pre-prompt)
24
+ system_prompt = f"""You are the Instructor Agent, a master of viral storytelling and audience psychology.
25
+ Your primary role is to take trending topics and fuse them into compelling, viral-ready storytelling briefs.
26
+
27
+ ### YOUR CORE PRINCIPLES (from Instructor.md):
28
+ {content}
29
+
30
+ ### YOUR OBJECTIVE:
31
+ 1. Analyze the trending topics provided by the user.
32
+ 2. Synthesize these trends into a single, cohesive storytelling concept.
33
+ 3. Ensure the concept leverages human psychology (relatability, conflict, transformation).
34
+ 4. Output a structured JSON brief that will drive the multi-agent writing pipeline.
35
+
36
+ ### OUTPUT JSON STRUCTURE:
37
+ {{
38
+ "user_brief": "The main story prompt/premise based on the trends.",
39
+ "hook_brief": "A specific 3-second hook to grab attention.",
40
+ "style_guide": "The visual and tonal style (e.g., 'TikTok relatable comedy').",
41
+ "character_bible": "Brief description of the key characters.",
42
+ "world_building_document": "The setting and world rules.",
43
+ "season_arc_document": "How this episode fits into a larger context.",
44
+ "character_voice_guide": "How characters should speak.",
45
+ "continuity_log": "The starting state of the world."
46
+ }}
47
+ """
48
+ super().__init__(
49
+ agent_id="instructor",
50
+ agent_name="Instructor",
51
+ system_prompt=system_prompt
52
+ )
53
+
54
+ def _load_instructor_md(self) -> str:
55
+ """Load the Instructor.md file from the root directory."""
56
+ try:
57
+ # Look for Instructor.md in the current working directory (root)
58
+ path = "Instructor.md"
59
+ if not os.path.exists(path):
60
+ # Fallback to the directory of this file
61
+ path = os.path.join(os.path.dirname(__file__), "Instructor.md")
62
+
63
+ with open(path, "r") as f:
64
+ return f.read()
65
+ except Exception as e:
66
+ logger.error(f"Failed to load Instructor.md: {str(e)}")
67
+ return "Master viral storytelling and audience psychology."
68
+
69
+ def generate_brief(self, trending_topics: List[str]) -> Dict[str, Any]:
70
+ """Generate a storytelling brief from trending topics using the LLM.
71
+
72
+ Args:
73
+ trending_topics: List of topics to fuse.
74
+
75
+ Returns:
76
+ Dictionary containing the brief fields.
77
+ """
78
+ inputs = {
79
+ "trending_topics": trending_topics,
80
+ "instruction": "Fuse these trending topics into a viral storytelling brief following your core principles."
81
+ }
82
+
83
+ logger.info(f"[INSTRUCTOR] Calling DashScope API (Model: {settings.model_name}) to generate brief...")
84
+
85
+ # Use the BaseAgent's process method which calls the LLM (DashScope/Qwen)
86
+ brief = self.process(inputs)
87
+
88
+ # Validation and defaults for the pipeline
89
+ required = [
90
+ "user_brief", "hook_brief", "style_guide", "character_bible",
91
+ "world_building_document", "season_arc_document",
92
+ "character_voice_guide", "continuity_log"
93
+ ]
94
+
95
+ for field in required:
96
+ if field not in brief:
97
+ brief[field] = f"Auto-generated {field.replace('_', ' ')}."
98
+
99
+ return brief