Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -115,22 +115,38 @@ GENRE_TEMPLATES = {
|
|
115 |
}
|
116 |
|
117 |
# Screenplay stages definition
|
|
|
118 |
SCREENPLAY_STAGES = [
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
132 |
]
|
133 |
|
|
|
134 |
# Save the Cat Beat Sheet
|
135 |
SAVE_THE_CAT_BEATS = {
|
136 |
1: "Opening Image (0-1%)",
|
@@ -382,13 +398,53 @@ class ScreenplayDatabase:
|
|
382 |
conn.commit()
|
383 |
return session_id
|
384 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
385 |
@staticmethod
|
386 |
def save_stage(session_id: str, stage_number: int, stage_name: str,
|
387 |
role: str, content: str, status: str = 'complete'):
|
388 |
page_count = 0
|
389 |
if role == "screenwriter" and content:
|
390 |
-
#
|
391 |
-
|
|
|
392 |
|
393 |
with ScreenplayDatabase.get_db() as conn:
|
394 |
cursor = conn.cursor()
|
@@ -401,14 +457,24 @@ class ScreenplayDatabase:
|
|
401 |
''', (session_id, stage_number, stage_name, role, content, page_count, status,
|
402 |
content, page_count, status))
|
403 |
|
404 |
-
# Update session
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
410 |
|
411 |
conn.commit()
|
|
|
|
|
412 |
|
413 |
@staticmethod
|
414 |
def save_screenplay_bible(session_id: str, bible: ScreenplayBible):
|
@@ -450,19 +516,33 @@ class ScreenplayDatabase:
|
|
450 |
)
|
451 |
conn.commit()
|
452 |
|
|
|
453 |
@staticmethod
|
454 |
def get_screenplay_content(session_id: str) -> str:
|
455 |
-
"""Get complete screenplay content"""
|
456 |
with ScreenplayDatabase.get_db() as conn:
|
|
|
457 |
rows = conn.cursor().execute('''
|
458 |
SELECT content FROM screenplay_stages
|
459 |
-
WHERE session_id = ?
|
|
|
|
|
460 |
ORDER BY stage_number
|
461 |
''', (session_id,)).fetchall()
|
462 |
|
463 |
if rows:
|
464 |
return '\n\n'.join(row['content'] for row in rows if row['content'])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
465 |
return ""
|
|
|
|
|
466 |
|
467 |
@staticmethod
|
468 |
def update_final_screenplay(session_id: str, final_screenplay: str, title: str, logline: str):
|
@@ -1060,17 +1140,22 @@ Plan each scene to advance story and develop character."""
|
|
1060 |
def create_screenwriter_prompt(self, act: str, scene_breakdown: str,
|
1061 |
characters: str, previous_acts: str,
|
1062 |
screenplay_type: str, genre: str, language: str) -> str:
|
1063 |
-
"""
|
1064 |
|
1065 |
act_pages = int(SCREENPLAY_LENGTHS[screenplay_type]['pages'] * 0.25)
|
|
|
|
|
|
|
|
|
1066 |
|
1067 |
lang_prompts = {
|
1068 |
"Korean": f"""๋น์ ์ ํ๋ก ์๋๋ฆฌ์ค ์๊ฐ์
๋๋ค. {act}์ ํ์ค ์๋๋ฆฌ์ค ํฌ๋งท์ผ๋ก ์์ฑํ์ธ์.
|
1069 |
-
|
1070 |
-
|
|
|
1071 |
|
1072 |
**์ฌ ๋ธ๋ ์ดํฌ๋ค์ด:**
|
1073 |
-
{
|
1074 |
|
1075 |
**์บ๋ฆญํฐ ์ ๋ณด:**
|
1076 |
{characters}
|
@@ -1078,46 +1163,51 @@ Plan each scene to advance story and develop character."""
|
|
1078 |
**์ด์ ๋ด์ฉ:**
|
1079 |
{previous_acts if previous_acts else "์ฒซ ๋ง์
๋๋ค."}
|
1080 |
|
1081 |
-
|
1082 |
-
|
1083 |
-
1.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1084 |
INT. ์ฅ์ - ์๊ฐ
|
1085 |
-
|
1086 |
-
|
1087 |
-
|
1088 |
-
|
1089 |
-
- ์๊ฐ์ ์ผ๋ก ๋ณด์ด๋ ๊ฒ๋ง ๋ฌ์ฌ
|
1090 |
-
- 4์ค ์ดํ๋ก ์ ์ง
|
1091 |
-
- ๊ฐ์ ์ ํ๋์ผ๋ก ํํ
|
1092 |
-
|
1093 |
-
3. **์บ๋ฆญํฐ ์๊ฐ**
|
1094 |
-
์ฒซ ๋ฑ์ฅ์: ์ด๋ฆ๊ณผ ๊ฐ๋จํ ๋ฌ์ฌ
|
1095 |
-
|
1096 |
-
4. **๋ํ**
|
1097 |
์บ๋ฆญํฐ๋ช
|
1098 |
(์ง๋ฌธ)
|
1099 |
๋์ฌ
|
1100 |
|
1101 |
-
|
1102 |
-
- Show, don't tell
|
1103 |
-
- ์๋ธํ
์คํธ ํ์ฉ
|
1104 |
-
- ์์ฐ์ค๋ฌ์ด ๋ํ
|
1105 |
-
- ์๊ฐ์ ์คํ ๋ฆฌํ
๋ง
|
1106 |
-
- ํ์ด์ง๋น 1๋ถ ๊ท์น
|
1107 |
-
|
1108 |
-
**{genre} ์ฅ๋ฅด ํน์ฑ:**
|
1109 |
-
- ๋ํ ๋น์จ: {GENRE_TEMPLATES[genre]['dialogue_ratio']*100}%
|
1110 |
-
- ์ฌ ๊ธธ์ด: {GENRE_TEMPLATES[genre]['scene_length']}
|
1111 |
-
- ํต์ฌ ์์: {', '.join(GENRE_TEMPLATES[genre]['key_elements'][:2])}
|
1112 |
|
1113 |
-
|
1114 |
|
1115 |
-
|
1116 |
-
|
1117 |
-
**Target Length:** {act_pages} pages
|
1118 |
|
1119 |
**Scene Breakdown:**
|
1120 |
-
{
|
1121 |
|
1122 |
**Character Info:**
|
1123 |
{characters}
|
@@ -1125,43 +1215,49 @@ Plan each scene to advance story and develop character."""
|
|
1125 |
**Previous Content:**
|
1126 |
{previous_acts if previous_acts else "This is the first act."}
|
1127 |
|
1128 |
-
**
|
1129 |
-
|
1130 |
-
1. **
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1131 |
INT. LOCATION - TIME
|
1132 |
-
|
1133 |
-
|
1134 |
-
|
1135 |
-
|
1136 |
-
- Only what's visually seen
|
1137 |
-
- Keep under 4 lines
|
1138 |
-
- Emotions through actions
|
1139 |
-
|
1140 |
-
3. **Character Intros**
|
1141 |
-
First appearance: NAME with brief description
|
1142 |
-
|
1143 |
-
4. **Dialogue**
|
1144 |
CHARACTER NAME
|
1145 |
(parenthetical)
|
1146 |
Dialogue
|
1147 |
|
1148 |
-
|
1149 |
-
- Show, don't tell
|
1150 |
-
- Use subtext
|
1151 |
-
- Natural dialogue
|
1152 |
-
- Visual storytelling
|
1153 |
-
- One page = one minute
|
1154 |
-
|
1155 |
-
**{genre} Genre Characteristics:**
|
1156 |
-
- Dialogue Ratio: {GENRE_TEMPLATES[genre]['dialogue_ratio']*100}%
|
1157 |
-
- Scene Length: {GENRE_TEMPLATES[genre]['scene_length']}
|
1158 |
-
- Key Elements: {', '.join(GENRE_TEMPLATES[genre]['key_elements'][:2])}
|
1159 |
-
|
1160 |
-
Write with proper format and engaging storytelling."""
|
1161 |
}
|
1162 |
-
|
1163 |
return lang_prompts.get(language, lang_prompts["English"])
|
1164 |
|
|
|
|
|
1165 |
def create_script_doctor_prompt(self, act_content: str, act: str,
|
1166 |
genre: str, language: str) -> str:
|
1167 |
"""Script doctor review and polish"""
|
@@ -1487,14 +1583,14 @@ Provide specific solutions for each issue."""
|
|
1487 |
*messages
|
1488 |
]
|
1489 |
|
1490 |
-
max_tokens =
|
1491 |
|
1492 |
payload = {
|
1493 |
"model": self.model_id,
|
1494 |
"messages": full_messages,
|
1495 |
"max_tokens": max_tokens,
|
1496 |
-
"temperature": 0.
|
1497 |
-
"top_p": 0.
|
1498 |
"presence_penalty": 0.3,
|
1499 |
"frequency_penalty": 0.3,
|
1500 |
"stream": True
|
@@ -1804,7 +1900,9 @@ You provide feedback that's critical yet encouraging."""
|
|
1804 |
def get_stage_prompt(self, stage_idx: int, role: str, query: str,
|
1805 |
screenplay_type: str, genre: str, language: str,
|
1806 |
stages: List[Dict]) -> str:
|
1807 |
-
"""Generate stage-specific prompt"""
|
|
|
|
|
1808 |
if stage_idx == 0: # Producer
|
1809 |
return self.create_producer_prompt(query, screenplay_type, genre, language)
|
1810 |
|
@@ -1828,26 +1926,44 @@ You provide feedback that's critical yet encouraging."""
|
|
1828 |
stages[1]["content"], stages[2]["content"], screenplay_type, genre, language
|
1829 |
)
|
1830 |
|
1831 |
-
#
|
1832 |
-
|
1833 |
-
|
1834 |
-
|
1835 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1836 |
previous_acts = self._get_previous_acts(stages, stage_idx)
|
1837 |
return self.create_screenwriter_prompt(
|
1838 |
act, stages[4]["content"], stages[2]["content"],
|
1839 |
previous_acts, screenplay_type, genre, language
|
1840 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1841 |
|
1842 |
-
#
|
1843 |
-
if role == "script_doctor":
|
1844 |
-
act_mapping = {6: "Act 1", 8: "Act 2A", 10: "Act 2B"}
|
1845 |
-
if stage_idx in act_mapping:
|
1846 |
-
act = act_mapping[stage_idx]
|
1847 |
-
act_content = stages[stage_idx-1]["content"]
|
1848 |
-
return self.create_script_doctor_prompt(act_content, act, genre, language)
|
1849 |
-
|
1850 |
-
# Final reviewer
|
1851 |
if role == "final_reviewer":
|
1852 |
complete_screenplay = ScreenplayDatabase.get_screenplay_content(self.current_session_id)
|
1853 |
return self.create_final_reviewer_prompt(
|
@@ -1855,6 +1971,8 @@ You provide feedback that's critical yet encouraging."""
|
|
1855 |
)
|
1856 |
|
1857 |
return ""
|
|
|
|
|
1858 |
|
1859 |
def _get_previous_acts(self, stages: List[Dict], current_idx: int) -> str:
|
1860 |
"""Get previous acts content"""
|
|
|
115 |
}
|
116 |
|
117 |
# Screenplay stages definition
|
118 |
+
# Screenplay stages definition - Enhanced with expansion stages
|
119 |
SCREENPLAY_STAGES = [
|
120 |
+
("producer", "๐ฌ Producer: Concept Development & Market Analysis"),
|
121 |
+
("story_developer", "๐ Story Developer: Synopsis & Three-Act Structure"),
|
122 |
+
("character_designer", "๐ฅ Character Designer: Cast & Relationships"),
|
123 |
+
("critic_structure", "๐ Structure Critic: Story & Character Review"),
|
124 |
+
("scene_planner", "๐ฏ Scene Planner: Detailed Scene Breakdown"),
|
125 |
+
|
126 |
+
# Act 1 - 3 stages: Draft -> Review -> Expansion
|
127 |
+
("screenwriter", "โ๏ธ Screenwriter: Act 1 - Setup (25%) - First Draft"),
|
128 |
+
("script_doctor", "๐ง Script Doctor: Act 1 Review & Expansion Notes"),
|
129 |
+
("screenwriter", "โ๏ธ Screenwriter: Act 1 - Expanded Final Version"),
|
130 |
+
|
131 |
+
# Act 2A - 3 stages
|
132 |
+
("screenwriter", "โ๏ธ Screenwriter: Act 2A - Rising Action (25%) - First Draft"),
|
133 |
+
("script_doctor", "๐ง Script Doctor: Act 2A Review & Expansion Notes"),
|
134 |
+
("screenwriter", "โ๏ธ Screenwriter: Act 2A - Expanded Final Version"),
|
135 |
+
|
136 |
+
# Act 2B - 3 stages
|
137 |
+
("screenwriter", "โ๏ธ Screenwriter: Act 2B - Complications (25%) - First Draft"),
|
138 |
+
("script_doctor", "๐ง Script Doctor: Act 2B Review & Expansion Notes"),
|
139 |
+
("screenwriter", "โ๏ธ Screenwriter: Act 2B - Expanded Final Version"),
|
140 |
+
|
141 |
+
# Act 3 - 3 stages
|
142 |
+
("screenwriter", "โ๏ธ Screenwriter: Act 3 - Resolution (25%) - First Draft"),
|
143 |
+
("script_doctor", "๐ง Script Doctor: Act 3 Review & Expansion Notes"),
|
144 |
+
("screenwriter", "โ๏ธ Screenwriter: Act 3 - Expanded Final Version"),
|
145 |
+
|
146 |
+
("final_reviewer", "๐ญ Final Review: Complete Screenplay Analysis"),
|
147 |
]
|
148 |
|
149 |
+
|
150 |
# Save the Cat Beat Sheet
|
151 |
SAVE_THE_CAT_BEATS = {
|
152 |
1: "Opening Image (0-1%)",
|
|
|
398 |
conn.commit()
|
399 |
return session_id
|
400 |
|
401 |
+
# In ScreenplayDatabase.save_stage method, add page count tracking
|
402 |
+
@staticmethod
|
403 |
+
def save_stage(session_id: str, stage_number: int, stage_name: str,
|
404 |
+
role: str, content: str, status: str = 'complete'):
|
405 |
+
page_count = 0
|
406 |
+
if role == "screenwriter" and content:
|
407 |
+
# Use the accurate page calculation
|
408 |
+
system = ScreenplayGenerationSystem()
|
409 |
+
page_count = system.calculate_screenplay_pages(content)
|
410 |
+
|
411 |
+
with ScreenplayDatabase.get_db() as conn:
|
412 |
+
cursor = conn.cursor()
|
413 |
+
cursor.execute('''
|
414 |
+
INSERT INTO screenplay_stages
|
415 |
+
(session_id, stage_number, stage_name, role, content, page_count, status)
|
416 |
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
417 |
+
ON CONFLICT(session_id, stage_number)
|
418 |
+
DO UPDATE SET content=?, page_count=?, status=?, updated_at=datetime('now')
|
419 |
+
''', (session_id, stage_number, stage_name, role, content, page_count, status,
|
420 |
+
content, page_count, status))
|
421 |
+
|
422 |
+
# Update total pages in session
|
423 |
+
if role == "screenwriter" and "Expanded" in stage_name:
|
424 |
+
cursor.execute('''
|
425 |
+
UPDATE screenplay_sessions
|
426 |
+
SET total_pages = (
|
427 |
+
SELECT SUM(page_count)
|
428 |
+
FROM screenplay_stages
|
429 |
+
WHERE session_id = ?
|
430 |
+
AND role = 'screenwriter'
|
431 |
+
AND stage_name LIKE '%Expanded%'
|
432 |
+
),
|
433 |
+
updated_at = datetime('now')
|
434 |
+
WHERE session_id = ?
|
435 |
+
''', (session_id, session_id))
|
436 |
+
|
437 |
+
conn.commit()# In ScreenplayDatabase.save_stage method, add page count tracking
|
438 |
+
|
439 |
+
|
440 |
@staticmethod
|
441 |
def save_stage(session_id: str, stage_number: int, stage_name: str,
|
442 |
role: str, content: str, status: str = 'complete'):
|
443 |
page_count = 0
|
444 |
if role == "screenwriter" and content:
|
445 |
+
# Use the accurate page calculation
|
446 |
+
system = ScreenplayGenerationSystem()
|
447 |
+
page_count = system.calculate_screenplay_pages(content)
|
448 |
|
449 |
with ScreenplayDatabase.get_db() as conn:
|
450 |
cursor = conn.cursor()
|
|
|
457 |
''', (session_id, stage_number, stage_name, role, content, page_count, status,
|
458 |
content, page_count, status))
|
459 |
|
460 |
+
# Update total pages in session
|
461 |
+
if role == "screenwriter" and "Expanded" in stage_name:
|
462 |
+
cursor.execute('''
|
463 |
+
UPDATE screenplay_sessions
|
464 |
+
SET total_pages = (
|
465 |
+
SELECT SUM(page_count)
|
466 |
+
FROM screenplay_stages
|
467 |
+
WHERE session_id = ?
|
468 |
+
AND role = 'screenwriter'
|
469 |
+
AND stage_name LIKE '%Expanded%'
|
470 |
+
),
|
471 |
+
updated_at = datetime('now')
|
472 |
+
WHERE session_id = ?
|
473 |
+
''', (session_id, session_id))
|
474 |
|
475 |
conn.commit()
|
476 |
+
|
477 |
+
|
478 |
|
479 |
@staticmethod
|
480 |
def save_screenplay_bible(session_id: str, bible: ScreenplayBible):
|
|
|
516 |
)
|
517 |
conn.commit()
|
518 |
|
519 |
+
|
520 |
@staticmethod
|
521 |
def get_screenplay_content(session_id: str) -> str:
|
522 |
+
"""Get complete screenplay content - only expanded versions"""
|
523 |
with ScreenplayDatabase.get_db() as conn:
|
524 |
+
# Get only the expanded final versions
|
525 |
rows = conn.cursor().execute('''
|
526 |
SELECT content FROM screenplay_stages
|
527 |
+
WHERE session_id = ?
|
528 |
+
AND role = 'screenwriter'
|
529 |
+
AND stage_name LIKE '%Expanded Final Version%'
|
530 |
ORDER BY stage_number
|
531 |
''', (session_id,)).fetchall()
|
532 |
|
533 |
if rows:
|
534 |
return '\n\n'.join(row['content'] for row in rows if row['content'])
|
535 |
+
else:
|
536 |
+
# Fallback to any writer content
|
537 |
+
rows = conn.cursor().execute('''
|
538 |
+
SELECT content FROM screenplay_stages
|
539 |
+
WHERE session_id = ? AND role = 'screenwriter'
|
540 |
+
ORDER BY stage_number
|
541 |
+
''', (session_id,)).fetchall()
|
542 |
+
return '\n\n'.join(row['content'] for row in rows if row['content'])
|
543 |
return ""
|
544 |
+
|
545 |
+
|
546 |
|
547 |
@staticmethod
|
548 |
def update_final_screenplay(session_id: str, final_screenplay: str, title: str, logline: str):
|
|
|
1140 |
def create_screenwriter_prompt(self, act: str, scene_breakdown: str,
|
1141 |
characters: str, previous_acts: str,
|
1142 |
screenplay_type: str, genre: str, language: str) -> str:
|
1143 |
+
"""Enhanced screenwriter prompt with strict length requirements"""
|
1144 |
|
1145 |
act_pages = int(SCREENPLAY_LENGTHS[screenplay_type]['pages'] * 0.25)
|
1146 |
+
min_lines = act_pages * 55 # 1 page = ~55 lines
|
1147 |
+
|
1148 |
+
# Extract detailed scene information for this act
|
1149 |
+
act_scenes = self._extract_act_scenes(scene_breakdown, act)
|
1150 |
|
1151 |
lang_prompts = {
|
1152 |
"Korean": f"""๋น์ ์ ํ๋ก ์๋๋ฆฌ์ค ์๊ฐ์
๋๋ค. {act}์ ํ์ค ์๋๋ฆฌ์ค ํฌ๋งท์ผ๋ก ์์ฑํ์ธ์.
|
1153 |
+
|
1154 |
+
**๋ชฉํ ๋ถ๋:** {act_pages}ํ์ด์ง (์ต์ {min_lines}์ค ํ์)
|
1155 |
+
**์ ๋ ๊ท์น: {min_lines}์ค ๋ฏธ๋ง ์์ฑ์ ์คํจ๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.**
|
1156 |
|
1157 |
**์ฌ ๋ธ๋ ์ดํฌ๋ค์ด:**
|
1158 |
+
{act_scenes}
|
1159 |
|
1160 |
**์บ๋ฆญํฐ ์ ๋ณด:**
|
1161 |
{characters}
|
|
|
1163 |
**์ด์ ๋ด์ฉ:**
|
1164 |
{previous_acts if previous_acts else "์ฒซ ๋ง์
๋๋ค."}
|
1165 |
|
1166 |
+
**ํ์ ์์ฑ ์๊ตฌ์ฌํญ:**
|
1167 |
+
|
1168 |
+
1. **๋ถ๋ ๋ฌ์ฑ ์ ๋ต**
|
1169 |
+
- ๊ฐ ์ฌ๋ง๋ค ์ต์ 3-5ํ์ด์ง ํ ๋น
|
1170 |
+
- ๋ํ: ์บ๋ฆญํฐ๊ฐ ์ถฉ๋ถํ ๊ตํ (๊ฐ ๋ํ ์ํ์ค 10-15์ค)
|
1171 |
+
- ์ก์
: ์์ธํ ์๊ฐ์ ๋ฌ์ฌ (๊ฐ ์ก์
๋นํธ 3-5์ค)
|
1172 |
+
- ์ ํ: ์ฌ ์ฌ์ด ์ถฉ๋ถํ ๋ธ๋ฆฟ์ง ์ฅ๋ฉด
|
1173 |
+
|
1174 |
+
2. **๋ํ ์์ฑ ์ง์นจ**
|
1175 |
+
- ์๋ธํ
์คํธ๊ฐ ํ๋ถํ ๋ํ
|
1176 |
+
- ๊ฐ๋ฑ์ด ์ ์ง์ ์ผ๋ก ๊ณ ์กฐ
|
1177 |
+
- ์บ๋ฆญํฐ๋ณ ๊ณ ์ ํ ๋งํฌ์ ๋ฆฌ๋ฌ
|
1178 |
+
- ์นจ๋ฌต๊ณผ ๋ฐ์์ ์ ์ ํ ํ์ฉ
|
1179 |
+
- ์ค์ํ ์ ๋ณด๋ ๋ํ๋ก ์์ฐ์ค๋ฝ๊ฒ
|
1180 |
+
|
1181 |
+
3. **์ก์
๋ผ์ธ ์์ธํ**
|
1182 |
+
- ์ฅ์์ ๊ตฌ์ฒด์ ์ด๊ณ ๋ถ์๊ธฐ ์๋ ๋ฌ์ฌ
|
1183 |
+
- ์บ๋ฆญํฐ์ ๋ฏธ์ธํ ๋์๊ณผ ํ์ ํฌ์ฐฉ
|
1184 |
+
- ์๊ฐ๋์ ๋ ์จ, ์กฐ๋ช
๋ฑ ํ๊ฒฝ ๋ฌ์ฌ
|
1185 |
+
- ์ํ๊ณผ ์์ ๋ฑ ์๊ฐ์ ๋ํ
์ผ
|
1186 |
+
|
1187 |
+
4. **{genre} ์ฅ๋ฅด ํนํ ์์**
|
1188 |
+
- ํ์ด์ฑ: {GENRE_TEMPLATES[genre]['pacing']}
|
1189 |
+
- ์ฌ ๊ธธ์ด: {GENRE_TEMPLATES[genre]['scene_length']}
|
1190 |
+
- ํต์ฌ ์์: {', '.join(GENRE_TEMPLATES[genre]['key_elements'])}
|
1191 |
+
|
1192 |
+
5. **์๋๋ฆฌ์ค ํฌ๋งท ๊ท์น**
|
1193 |
INT. ์ฅ์ - ์๊ฐ
|
1194 |
+
|
1195 |
+
์ก์
๋ผ์ธ์ ํ์ฌ ์์ ๋ก ์์ฑ.
|
1196 |
+
์๊ฐ์ ์ผ๋ก ๋ณด์ด๋ ๊ฒ๋ง ๋ฌ์ฌ.
|
1197 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1198 |
์บ๋ฆญํฐ๋ช
|
1199 |
(์ง๋ฌธ)
|
1200 |
๋์ฌ
|
1201 |
|
1202 |
+
**๋ฐ๋์ {min_lines}์ค ์ด์ ์์ฑํ์ธ์. ๊ฐ ์ฌ์ ์ถฉ๋ถํ ์ ๊ฐํ๊ณ ๋ํ
์ผ์ ์ด๋ ค์ฃผ์ธ์.**""",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1203 |
|
1204 |
+
"English": f"""You are a professional screenwriter. Write {act} in standard screenplay format.
|
1205 |
|
1206 |
+
**Target Length:** {act_pages} pages (MINIMUM {min_lines} lines required)
|
1207 |
+
**ABSOLUTE RULE: Writing less than {min_lines} lines is considered failure.**
|
|
|
1208 |
|
1209 |
**Scene Breakdown:**
|
1210 |
+
{act_scenes}
|
1211 |
|
1212 |
**Character Info:**
|
1213 |
{characters}
|
|
|
1215 |
**Previous Content:**
|
1216 |
{previous_acts if previous_acts else "This is the first act."}
|
1217 |
|
1218 |
+
**Required Writing Elements:**
|
1219 |
+
|
1220 |
+
1. **Volume Achievement Strategy**
|
1221 |
+
- Allocate minimum 3-5 pages per scene
|
1222 |
+
- Dialogue: Sufficient exchanges (10-15 lines per sequence)
|
1223 |
+
- Action: Detailed visual descriptions (3-5 lines per beat)
|
1224 |
+
- Transitions: Adequate bridge scenes between
|
1225 |
+
|
1226 |
+
2. **Dialogue Guidelines**
|
1227 |
+
- Rich subtext in conversations
|
1228 |
+
- Gradually escalating conflict
|
1229 |
+
- Unique voice and rhythm per character
|
1230 |
+
- Appropriate use of pauses and reactions
|
1231 |
+
- Important information through natural dialogue
|
1232 |
+
|
1233 |
+
3. **Action Line Details**
|
1234 |
+
- Specific atmospheric location descriptions
|
1235 |
+
- Subtle character movements and expressions
|
1236 |
+
- Time, weather, lighting environment
|
1237 |
+
- Props and costume visual details
|
1238 |
+
|
1239 |
+
4. **{genre} Genre Elements**
|
1240 |
+
- Pacing: {GENRE_TEMPLATES[genre]['pacing']}
|
1241 |
+
- Scene Length: {GENRE_TEMPLATES[genre]['scene_length']}
|
1242 |
+
- Key Elements: {', '.join(GENRE_TEMPLATES[genre]['key_elements'])}
|
1243 |
+
|
1244 |
+
5. **Screenplay Format Rules**
|
1245 |
INT. LOCATION - TIME
|
1246 |
+
|
1247 |
+
Action lines in present tense.
|
1248 |
+
Only what's visually seen.
|
1249 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1250 |
CHARACTER NAME
|
1251 |
(parenthetical)
|
1252 |
Dialogue
|
1253 |
|
1254 |
+
**MUST write {min_lines}+ lines. Fully develop each scene with rich details.**"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1255 |
}
|
1256 |
+
|
1257 |
return lang_prompts.get(language, lang_prompts["English"])
|
1258 |
|
1259 |
+
|
1260 |
+
|
1261 |
def create_script_doctor_prompt(self, act_content: str, act: str,
|
1262 |
genre: str, language: str) -> str:
|
1263 |
"""Script doctor review and polish"""
|
|
|
1583 |
*messages
|
1584 |
]
|
1585 |
|
1586 |
+
max_tokens = 25000 if role == "screenwriter" else 15000
|
1587 |
|
1588 |
payload = {
|
1589 |
"model": self.model_id,
|
1590 |
"messages": full_messages,
|
1591 |
"max_tokens": max_tokens,
|
1592 |
+
"temperature": 0.8 if role in ["screenwriter", "script_doctor"] else 0.7,
|
1593 |
+
"top_p": 0.95,
|
1594 |
"presence_penalty": 0.3,
|
1595 |
"frequency_penalty": 0.3,
|
1596 |
"stream": True
|
|
|
1900 |
def get_stage_prompt(self, stage_idx: int, role: str, query: str,
|
1901 |
screenplay_type: str, genre: str, language: str,
|
1902 |
stages: List[Dict]) -> str:
|
1903 |
+
"""Generate stage-specific prompt - Enhanced for expansion stages"""
|
1904 |
+
|
1905 |
+
# Initial stages (0-4)
|
1906 |
if stage_idx == 0: # Producer
|
1907 |
return self.create_producer_prompt(query, screenplay_type, genre, language)
|
1908 |
|
|
|
1926 |
stages[1]["content"], stages[2]["content"], screenplay_type, genre, language
|
1927 |
)
|
1928 |
|
1929 |
+
# Act writing stages (5-16)
|
1930 |
+
# Act 1: stages 5-7, Act 2A: 8-10, Act 2B: 11-13, Act 3: 14-16
|
1931 |
+
|
1932 |
+
# Determine which act and phase
|
1933 |
+
act_stages = {
|
1934 |
+
5: ("Act 1", "draft"), 6: ("Act 1", "review"), 7: ("Act 1", "expand"),
|
1935 |
+
8: ("Act 2A", "draft"), 9: ("Act 2A", "review"), 10: ("Act 2A", "expand"),
|
1936 |
+
11: ("Act 2B", "draft"), 12: ("Act 2B", "review"), 13: ("Act 2B", "expand"),
|
1937 |
+
14: ("Act 3", "draft"), 15: ("Act 3", "review"), 16: ("Act 3", "expand"),
|
1938 |
+
}
|
1939 |
+
|
1940 |
+
if stage_idx in act_stages:
|
1941 |
+
act, phase = act_stages[stage_idx]
|
1942 |
+
|
1943 |
+
if phase == "draft":
|
1944 |
+
# First draft writing
|
1945 |
previous_acts = self._get_previous_acts(stages, stage_idx)
|
1946 |
return self.create_screenwriter_prompt(
|
1947 |
act, stages[4]["content"], stages[2]["content"],
|
1948 |
previous_acts, screenplay_type, genre, language
|
1949 |
)
|
1950 |
+
|
1951 |
+
elif phase == "review":
|
1952 |
+
# Script doctor review for expansion
|
1953 |
+
draft_content = stages[stage_idx-1]["content"]
|
1954 |
+
return self.create_script_doctor_expansion_prompt(
|
1955 |
+
draft_content, act, screenplay_type, genre, language
|
1956 |
+
)
|
1957 |
+
|
1958 |
+
elif phase == "expand":
|
1959 |
+
# Expanded rewrite
|
1960 |
+
original_content = stages[stage_idx-2]["content"] # Original draft
|
1961 |
+
expansion_notes = stages[stage_idx-1]["content"] # Review notes
|
1962 |
+
return self.create_expansion_writer_prompt(
|
1963 |
+
act, original_content, expansion_notes, screenplay_type, language
|
1964 |
+
)
|
1965 |
|
1966 |
+
# Final reviewer (stage 17)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1967 |
if role == "final_reviewer":
|
1968 |
complete_screenplay = ScreenplayDatabase.get_screenplay_content(self.current_session_id)
|
1969 |
return self.create_final_reviewer_prompt(
|
|
|
1971 |
)
|
1972 |
|
1973 |
return ""
|
1974 |
+
|
1975 |
+
|
1976 |
|
1977 |
def _get_previous_acts(self, stages: List[Dict], current_idx: int) -> str:
|
1978 |
"""Get previous acts content"""
|