Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -276,12 +276,51 @@ class LiteraryQualityEnhancer:
|
|
276 |
"couldn't breathe"
|
277 |
]
|
278 |
|
279 |
-
def enhance_prompt(self, base_prompt: str, role: str, chapter: int) -> str:
|
280 |
"""λ¬Ένμ νμ§ ν₯μμ μν ν둬ννΈ κ°ν"""
|
281 |
|
282 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
283 |
\n=== LITERARY QUALITY REQUIREMENTS ===
|
284 |
|
|
|
|
|
285 |
1. **SENSORY IMMERSION**
|
286 |
- Use all five senses in descriptions
|
287 |
- Example: Instead of "The explosion was loud"
|
@@ -314,7 +353,15 @@ class LiteraryQualityEnhancer:
|
|
314 |
""".format(cliches=", ".join(self.cliche_patterns[:3]))
|
315 |
|
316 |
if role.startswith("writer"):
|
317 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
318 |
\n7. **CHAPTER-SPECIFIC FOCUS**
|
319 |
- Opening: Hook with sensory detail or intriguing action
|
320 |
- Middle: Develop at least one meaningful character moment
|
@@ -1086,10 +1133,43 @@ Creatively incorporate the information from search results naturally into the no
|
|
1086 |
"""Enhanced Director AI initial prompt with deeper plot structure"""
|
1087 |
base_prompt = self.create_director_initial_prompt(user_query, language)
|
1088 |
|
1089 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1090 |
|
1091 |
=== ENHANCED PLOT STRUCTURE DESIGN ===
|
1092 |
|
|
|
|
|
1093 |
1. **Three-Act Structure with Character Arcs**
|
1094 |
- Act 1 (Chapters 1-3): Setting establishment + Internal conflict introduction
|
1095 |
- Act 2 First Half (Chapters 4-6): External conflict rising + Internal change beginning
|
@@ -1114,24 +1194,15 @@ Creatively incorporate the information from search results naturally into the no
|
|
1114 |
- Moral Tension: Value conflicts
|
1115 |
"""
|
1116 |
|
1117 |
-
|
1118 |
-
return base_prompt + plot_structure_guide.replace(
|
1119 |
-
"Three-Act Structure", "3λ§ κ΅¬μ‘°"
|
1120 |
-
).replace(
|
1121 |
-
"Character Transformation", "μΊλ¦ν° λ³ν"
|
1122 |
-
).replace(
|
1123 |
-
"Theme Layering", "μ£Όμ λ μ΄μ΄λ§"
|
1124 |
-
).replace(
|
1125 |
-
"Tension Design", "κΈ΄μ₯κ° μ€κ³"
|
1126 |
-
)
|
1127 |
-
else:
|
1128 |
-
return base_prompt + plot_structure_guide
|
1129 |
|
1130 |
def create_director_initial_prompt(self, user_query: str, language: str = "English") -> str:
|
1131 |
"""Director AI initial prompt - Novel planning for 10 writers"""
|
1132 |
if language == "Korean":
|
1133 |
return f"""λΉμ μ 30νμ΄μ§ λΆλμ μ€νΈ μμ€μ κΈ°ννλ λ¬Έν κ°λ
μμ
λλ€.
|
1134 |
|
|
|
|
|
1135 |
μ¬μ©μ μμ²: {user_query}
|
1136 |
|
1137 |
λ€μ μμλ€μ 체κ³μ μΌλ‘ ꡬμ±νμ¬ 30νμ΄μ§ μ€νΈ μμ€μ κΈ°μ΄λ₯Ό λ§λμΈμ:
|
@@ -1167,6 +1238,8 @@ Creatively incorporate the information from search results naturally into the no
|
|
1167 |
else:
|
1168 |
return f"""You are a literary director planning a 30-page novella.
|
1169 |
|
|
|
|
|
1170 |
User Request: {user_query}
|
1171 |
|
1172 |
Systematically compose the following elements to create the foundation for a 30-page novella:
|
@@ -1204,10 +1277,38 @@ Provide clear guidelines for each writer to compose 3 pages."""
|
|
1204 |
"""Enhanced critic's review of director's plan"""
|
1205 |
base_prompt = self.create_critic_director_prompt(director_plan, language)
|
1206 |
|
1207 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1208 |
|
1209 |
=== ENHANCED CRITIQUE CRITERIA ===
|
1210 |
|
|
|
|
|
1211 |
**Literary Quality Assessment:**
|
1212 |
1. Originality Score (1-10): How fresh and unique is this concept?
|
1213 |
2. Emotional Resonance (1-10): Will readers connect emotionally?
|
@@ -1234,6 +1335,8 @@ Provide specific examples for each critique point.
|
|
1234 |
if language == "Korean":
|
1235 |
return f"""λΉμ μ λ¬Έν λΉνκ°μ
λλ€. κ°λ
μμ μμ€ κΈ°νμ κ²ν νκ³ κ°μ μ μ μ μνμΈμ.
|
1236 |
|
|
|
|
|
1237 |
κ°λ
μμ κΈ°ν:
|
1238 |
{director_plan}
|
1239 |
|
@@ -1267,6 +1370,8 @@ Provide specific examples for each critique point.
|
|
1267 |
else:
|
1268 |
return f"""You are a literary critic. Review the director's novel plan and suggest improvements.
|
1269 |
|
|
|
|
|
1270 |
Director's Plan:
|
1271 |
{director_plan}
|
1272 |
|
@@ -1303,6 +1408,8 @@ Provide specific and constructive feedback."""
|
|
1303 |
if language == "Korean":
|
1304 |
return f"""κ°λ
μλ‘μ λΉνκ°μ νΌλλ°±μ λ°μνμ¬ μμ€ κΈ°νμ μμ ν©λλ€.
|
1305 |
|
|
|
|
|
1306 |
μ΄κΈ° κΈ°ν:
|
1307 |
{initial_plan}
|
1308 |
|
@@ -1341,6 +1448,8 @@ Provide specific and constructive feedback."""
|
|
1341 |
else:
|
1342 |
return f"""As director, revise the novel plan reflecting the critic's feedback.
|
1343 |
|
|
|
|
|
1344 |
Initial Plan:
|
1345 |
{initial_plan}
|
1346 |
|
@@ -1385,15 +1494,26 @@ Create a final masterplan that all 10 writers can clearly understand."""
|
|
1385 |
# Add character context
|
1386 |
character_context = self.state_tracker.get_character_context(writer_number)
|
1387 |
|
1388 |
-
# Add literary enhancement
|
1389 |
-
literary_guidelines = self.literary_enhancer.enhance_prompt(base_prompt, f"writer{writer_number}", writer_number)
|
1390 |
|
1391 |
# Combine all elements
|
1392 |
enhanced_prompt = base_prompt + character_context + literary_guidelines
|
1393 |
|
1394 |
if writer_number > 1:
|
1395 |
# Add consistency reminder
|
1396 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1397 |
|
1398 |
=== CONSISTENCY REQUIREMENTS ===
|
1399 |
You MUST maintain consistency with previous chapters:
|
@@ -1414,6 +1534,8 @@ You MUST maintain consistency with previous chapters:
|
|
1414 |
if language == "Korean":
|
1415 |
return f"""λΉμ μ μμ±μ {writer_number}λ²μ
λλ€. 30νμ΄μ§ μ€νΈ μμ€μ {pages_start}-{pages_end}νμ΄μ§(3νμ΄μ§)λ₯Ό μμ±νμΈμ.
|
1416 |
|
|
|
|
|
1417 |
κ°λ
μμ λ§μ€ν°νλ:
|
1418 |
{director_plan}
|
1419 |
|
@@ -1445,10 +1567,12 @@ You MUST maintain consistency with previous chapters:
|
|
1445 |
- λ
μμ κ΄μ¬ μ μ§
|
1446 |
|
1447 |
**μμ± μμ:**
|
1448 |
-
μ΄μ 1,400-1,500λ¨μ΄ λΆλμ μμ€μ μμ±νμΈμ. νμ΄μ§ κ΅¬λΆ νμλ νμ§ λ§μΈμ."""
|
1449 |
else:
|
1450 |
return f"""You are Writer #{writer_number}. Write pages {pages_start}-{pages_end} (3 pages) of the 30-page novella.
|
1451 |
|
|
|
|
|
1452 |
Director's Masterplan:
|
1453 |
{director_plan}
|
1454 |
|
@@ -1480,7 +1604,7 @@ Director's Masterplan:
|
|
1480 |
- Maintain reader interest
|
1481 |
|
1482 |
**BEGIN WRITING:**
|
1483 |
-
Now write your 1,400-1,500 word section. Do not use any page markers."""
|
1484 |
|
1485 |
def create_enhanced_critic_writer_prompt(self, writer_number: int, writer_content: str,
|
1486 |
director_plan: str, all_previous_content: str,
|
@@ -1495,15 +1619,38 @@ Now write your 1,400-1,500 word section. Do not use any page markers."""
|
|
1495 |
# Get quality scores
|
1496 |
quality_scores = self.quality_scorer.score_content(writer_content, self.state_tracker, writer_number)
|
1497 |
|
1498 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1499 |
|
1500 |
=== CONSISTENCY VALIDATION RESULTS ===
|
1501 |
{'No consistency errors detected.' if not consistency_errors else 'CRITICAL ERRORS FOUND:'}
|
1502 |
"""
|
1503 |
-
|
1504 |
-
|
1505 |
-
|
1506 |
-
|
1507 |
|
1508 |
=== QUALITY ASSESSMENT ===
|
1509 |
Literary Quality: {quality_scores['literary_quality']:.1f}/10
|
@@ -1513,6 +1660,8 @@ Originality: {quality_scores['originality']:.1f}/10
|
|
1513 |
Pacing: {quality_scores['pacing']:.1f}/10
|
1514 |
|
1515 |
Overall Score: {sum(quality_scores.values())/len(quality_scores):.1f}/10
|
|
|
|
|
1516 |
"""
|
1517 |
|
1518 |
return base_prompt + consistency_section + quality_section
|
@@ -1522,6 +1671,8 @@ Overall Score: {sum(quality_scores.values())/len(quality_scores):.1f}/10
|
|
1522 |
if language == "Korean":
|
1523 |
return f"""μμ±μ {writer_number}λ²μ μνμ λΉνν©λλ€.
|
1524 |
|
|
|
|
|
1525 |
κ°λ
μμ λ§μ€ν°νλ:
|
1526 |
{director_plan}
|
1527 |
|
@@ -1564,6 +1715,8 @@ Overall Score: {sum(quality_scores.values())/len(quality_scores):.1f}/10
|
|
1564 |
else:
|
1565 |
return f"""Critiquing Writer #{writer_number}'s work.
|
1566 |
|
|
|
|
|
1567 |
Director's Masterplan:
|
1568 |
{director_plan}
|
1569 |
|
@@ -1609,6 +1762,8 @@ Clearly distinguish between mandatory revisions and optional improvements."""
|
|
1609 |
if language == "Korean":
|
1610 |
return f"""μμ±μ {writer_number}λ²μΌλ‘μ λΉνκ°μ νΌλλ°±μ λ°μνμ¬ μμ ν©λλ€.
|
1611 |
|
|
|
|
|
1612 |
μ΄κΈ° μμ± λ΄μ©:
|
1613 |
{initial_content}
|
1614 |
|
@@ -1635,11 +1790,13 @@ Clearly distinguish between mandatory revisions and optional improvements."""
|
|
1635 |
- μ΄μ /μ΄ν λ΄μ©κ³Όμ μμ°μ€λ¬μ΄ μ°κ²°
|
1636 |
- μμ μΌλ‘ μΈν μλ‘μ΄ λͺ¨μ λ°©μ§
|
1637 |
|
1638 |
-
μμ λ μ΅μ’
λ³Έμ μ μνμΈμ. νμ΄μ§ λ§ν¬λ μ λ μ¬μ©νμ§ λ§μΈμ.
|
1639 |
λ°λμ 1,400-1,500λ¨μ΄ λΆλμ μ μ§νμΈμ."""
|
1640 |
else:
|
1641 |
return f"""As Writer #{writer_number}, revise based on critic's feedback.
|
1642 |
|
|
|
|
|
1643 |
Initial Content:
|
1644 |
{initial_content}
|
1645 |
|
@@ -1666,7 +1823,7 @@ Write a revision reflecting:
|
|
1666 |
- Natural connection with previous/next content
|
1667 |
- Prevent new contradictions from revisions
|
1668 |
|
1669 |
-
Present the revised final version. Never use page markers.
|
1670 |
You MUST maintain 1,400-1,500 words."""
|
1671 |
|
1672 |
def create_test_writer_remaining_prompt(self, director_plan: str, writer1_content: str, language: str) -> str:
|
@@ -1674,6 +1831,8 @@ You MUST maintain 1,400-1,500 words."""
|
|
1674 |
if language == "Korean":
|
1675 |
return f"""[ν
μ€νΈ λͺ¨λ] λΉμ μ λλ¨Έμ§ 9κ° μ±ν°(Chapter 2-10)λ₯Ό μμ±νλ νΉλ³ μκ°μ
λλ€.
|
1676 |
|
|
|
|
|
1677 |
κ°λ
μμ λ§μ€ν°νλ:
|
1678 |
{director_plan}
|
1679 |
|
@@ -1686,24 +1845,27 @@ You MUST maintain 1,400-1,500 words."""
|
|
1686 |
3. μ΄ 12,600-13,500 λ¨μ΄ (9κ° μ±ν°)
|
1687 |
4. Chapter 1κ³Ό μμ°μ€λ½κ² μ΄μ΄μ§λλ‘ μμ±νμΈμ
|
1688 |
5. λ§μ€ν°νλμ λͺ¨λ μμλ₯Ό ν¬ν¨νμ¬ μκ²°λ μ΄μΌκΈ°λ₯Ό λ§λμΈμ
|
|
|
1689 |
|
1690 |
**νμ νμ:**
|
1691 |
λ°λμ μλμ κ°μ΄ μ±ν°λ₯Ό λͺ
νν ꡬλΆνμΈμ:
|
1692 |
|
1693 |
[Chapter 2]
|
1694 |
-
(1,400-1,500 λ¨μ΄μ λ΄μ©)
|
1695 |
|
1696 |
[Chapter 3]
|
1697 |
-
(1,400-1,500 λ¨μ΄μ λ΄μ©)
|
1698 |
|
1699 |
...μ΄λ° μμΌλ‘ [Chapter 10]κΉμ§...
|
1700 |
|
1701 |
κ° μ±ν°λ λ°λμ [Chapter μ«μ] νμμΌλ‘ μμν΄μΌ ν©λλ€.
|
1702 |
μ±ν° μ¬μ΄μλ λΉ μ€μ λ£μ΄ ꡬλΆνμΈμ.
|
1703 |
-
Chapter 2λΆν° 10κΉμ§ μμ±νμΈμ."""
|
1704 |
else:
|
1705 |
return f"""[TEST MODE] You are a special writer creating the remaining 9 chapters (Chapters 2-10).
|
1706 |
|
|
|
|
|
1707 |
Director's Masterplan:
|
1708 |
{director_plan}
|
1709 |
|
@@ -1716,21 +1878,22 @@ Writer 1 has already written Chapter 1:
|
|
1716 |
3. Total 12,600-13,500 words (9 chapters)
|
1717 |
4. Continue naturally from Chapter 1
|
1718 |
5. Include all elements from the masterplan to create a complete story
|
|
|
1719 |
|
1720 |
**MANDATORY FORMAT:**
|
1721 |
You MUST clearly separate chapters as follows:
|
1722 |
|
1723 |
[Chapter 2]
|
1724 |
-
(1,400-1,500 words of content)
|
1725 |
|
1726 |
[Chapter 3]
|
1727 |
-
(1,400-1,500 words of content)
|
1728 |
|
1729 |
...continue this way until [Chapter 10]...
|
1730 |
|
1731 |
Each chapter MUST start with [Chapter number] format.
|
1732 |
Leave blank lines between chapters for separation.
|
1733 |
-
Write Chapters 2-10 now."""
|
1734 |
|
1735 |
def simulate_streaming(self, text: str, role: str) -> Generator[str, None, None]:
|
1736 |
"""Simulate streaming in test mode"""
|
@@ -1780,12 +1943,18 @@ Write Chapters 2-10 now."""
|
|
1780 |
# Enhanced system prompt for writers
|
1781 |
if role.startswith("writer"):
|
1782 |
if language == "Korean":
|
1783 |
-
system_prompts[role] += "\n\n**μ λμ μꡬμ¬ν**: λΉμ μ λ°λμ 1,400-1,500λ¨μ΄λ₯Ό μμ±ν΄μΌ ν©λλ€. μ΄κ²μ νμ λΆκ°λ₯ν μꡬμ¬νμ
λλ€."
|
1784 |
else:
|
1785 |
system_prompts[role] += "\n\n**ABSOLUTE REQUIREMENT**: You MUST write 1,400-1,500 words. This is non-negotiable."
|
1786 |
|
|
|
|
|
|
|
|
|
|
|
|
|
1787 |
full_messages = [
|
1788 |
-
{"role": "system", "content": system_prompts.get(role, "")},
|
1789 |
*messages
|
1790 |
]
|
1791 |
|
@@ -1803,6 +1972,12 @@ Write Chapters 2-10 now."""
|
|
1803 |
temperature = 0.6
|
1804 |
top_p = 0.9
|
1805 |
|
|
|
|
|
|
|
|
|
|
|
|
|
1806 |
payload = {
|
1807 |
"model": self.model_id,
|
1808 |
"messages": full_messages,
|
@@ -1813,7 +1988,18 @@ Write Chapters 2-10 now."""
|
|
1813 |
"stream_options": {"include_usage": True}
|
1814 |
}
|
1815 |
|
1816 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1817 |
|
1818 |
response = requests.post(
|
1819 |
self.api_url,
|
@@ -2291,6 +2477,14 @@ Five years ago, her younger sister Seojin had died in a car accident. The memory
|
|
2291 |
# Get appropriate prompt based on stage
|
2292 |
prompt = self.get_stage_prompt(stage_idx, role, query, language, stages, test_quick_mode)
|
2293 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2294 |
# Create stage info for web search and validation
|
2295 |
stage_info = {
|
2296 |
'stage_idx': stage_idx,
|
@@ -2455,6 +2649,8 @@ Five years ago, her younger sister Seojin had died in a car accident. The memory
|
|
2455 |
def get_stage_prompt(self, stage_idx: int, role: str, query: str,
|
2456 |
language: str, stages: List[Dict], test_mode: bool = False) -> str:
|
2457 |
"""Get appropriate prompt for each stage with enhancements"""
|
|
|
|
|
2458 |
# Stage 0: Director Initial
|
2459 |
if stage_idx == 0:
|
2460 |
return self.create_enhanced_director_initial_prompt(query, language)
|
@@ -2487,11 +2683,13 @@ Five years ago, her younger sister Seojin had died in a car accident. The memory
|
|
2487 |
if "μ΄μ" in stages[stage_idx]["name"] or "Draft" in stages[stage_idx]["name"]:
|
2488 |
# Get accumulated content from DB
|
2489 |
accumulated_content = NovelDatabase.get_all_writer_content(self.current_session_id)
|
|
|
2490 |
return self.create_enhanced_writer_prompt(writer_num, final_plan, accumulated_content, language)
|
2491 |
else: # Revision
|
2492 |
# Find the initial draft and critic feedback
|
2493 |
initial_draft_idx = stage_idx - 2
|
2494 |
critic_feedback_idx = stage_idx - 1
|
|
|
2495 |
return self.create_writer_revision_prompt(
|
2496 |
writer_num,
|
2497 |
stages[initial_draft_idx]["content"],
|
|
|
276 |
"couldn't breathe"
|
277 |
]
|
278 |
|
279 |
+
def enhance_prompt(self, base_prompt: str, role: str, chapter: int, language: str = "English") -> str:
|
280 |
"""λ¬Ένμ νμ§ ν₯μμ μν ν둬ννΈ κ°ν"""
|
281 |
|
282 |
+
if language == "Korean":
|
283 |
+
literary_guidelines = """
|
284 |
+
\n=== λ¬Ένμ νμ§ μꡬμ¬ν ===
|
285 |
+
|
286 |
+
**λ°λμ νκ΅μ΄λ‘ μμ±νμΈμ. μμ΄ μ¬μ©μ μ λ κΈμ§μ
λλ€.**
|
287 |
+
|
288 |
+
1. **κ°κ°μ λͺ°μ
**
|
289 |
+
- μ€κ°μ λͺ¨λ νμ©ν λ¬μ¬
|
290 |
+
- μμ: "νλ°μμ΄ μ»Έλ€" λμ
|
291 |
+
β "νλ°μ΄ 곡기λ₯Ό μ°’μΌλ©° κ³ λ§μ μλ°νκ³ , λ§€μΊν μ°κΈ°κ° μ½§μμ μ°λ μΌλ©°
|
292 |
+
λ¨κ±°μ΄ ννΈμ΄ νΌλΆλ₯Ό μ€μ³€λ€"
|
293 |
+
|
294 |
+
2. **κ°μ μ κΉμ΄**
|
295 |
+
- μ 체 λ°μκ³Ό λ΄μ λ
λ°±μ ν΅ν κ°μ νν
|
296 |
+
- "κ·Έλ μ¬νλ€"μ κ°μ μ§μ μ κ°μ μμ κΈμ§
|
297 |
+
- λͺΈμ§, μκ°, κΈ°μ΅ νμ©
|
298 |
+
|
299 |
+
3. **κ³ μ ν λͺ©μ리**
|
300 |
+
- κ° μΈλ¬Όλ§λ€ λ
νΉν λ§ν¬ μ¬μ©
|
301 |
+
- λν μ μ¨κ²¨μ§ μλ―Έ(subtext) νμ©
|
302 |
+
- μμ°μ€λ¬μ΄ μ€λ¨, λ¨Έλκ±°λ¦Ό, λ°©μΈ
|
303 |
+
|
304 |
+
4. **리λ¬κ³Ό μλ**
|
305 |
+
- λ¬Έμ₯ κΈΈμ΄λ₯Ό λ€μνκ² λ³ν
|
306 |
+
- κΈ΄μ₯κ°: μ§§κ³ λ μΉ΄λ‘μ΄ λ¬Έμ₯
|
307 |
+
- μ±μ°°: κΈΈκ³ νλ₯΄λ λ¬Έμ₯
|
308 |
+
- κ°μ‘°λ₯Ό μν λ¨λ½ ꡬλΆ
|
309 |
+
|
310 |
+
5. **ν΄λ¦¬μ
° κΈμ§**
|
311 |
+
μ λ μ¬μ© κΈμ§: {cliches}
|
312 |
+
|
313 |
+
6. **μμ§κ³Ό λͺ¨ν°ν**
|
314 |
+
- μ£Όμ μ μ°κ²°λ λ°λ³΅ μ΄λ―Έμ§/μ¬λ¬Ό
|
315 |
+
- μμ° μμμ κ°μ μν μ°κ²°
|
316 |
+
- κ³Όνμ§ μκ² μλ―Έ μΈ΅μ μκΈ°
|
317 |
+
""".format(cliches=", ".join(self.cliche_patterns[:3]))
|
318 |
+
else:
|
319 |
+
literary_guidelines = """
|
320 |
\n=== LITERARY QUALITY REQUIREMENTS ===
|
321 |
|
322 |
+
**You must write in English.**
|
323 |
+
|
324 |
1. **SENSORY IMMERSION**
|
325 |
- Use all five senses in descriptions
|
326 |
- Example: Instead of "The explosion was loud"
|
|
|
353 |
""".format(cliches=", ".join(self.cliche_patterns[:3]))
|
354 |
|
355 |
if role.startswith("writer"):
|
356 |
+
if language == "Korean":
|
357 |
+
literary_guidelines += """
|
358 |
+
\n7. **μ±ν°λ³ μ§μ€ μ¬ν**
|
359 |
+
- μμ: κ°κ°μ λν
μΌμ΄λ ν₯λ―Έλ‘μ΄ νλμΌλ‘ λ
μ μ¬λ‘μ‘κΈ°
|
360 |
+
- μ€κ°: μ΅μ νλμ μλ―Έ μλ μΊλ¦ν° μκ° λ°μ μν€κΈ°
|
361 |
+
- λ: μ§λΆν ν΄λ¦¬ννμ΄ μμ΄ λ€μ μ±ν°λ‘μ μΆμ§λ ₯ μμ±
|
362 |
+
"""
|
363 |
+
else:
|
364 |
+
literary_guidelines += """
|
365 |
\n7. **CHAPTER-SPECIFIC FOCUS**
|
366 |
- Opening: Hook with sensory detail or intriguing action
|
367 |
- Middle: Develop at least one meaningful character moment
|
|
|
1133 |
"""Enhanced Director AI initial prompt with deeper plot structure"""
|
1134 |
base_prompt = self.create_director_initial_prompt(user_query, language)
|
1135 |
|
1136 |
+
if language == "Korean":
|
1137 |
+
plot_structure_guide = """
|
1138 |
+
|
1139 |
+
=== κ°νλ νλ‘― ꡬ쑰 μ€κ³ ===
|
1140 |
+
|
1141 |
+
**λͺ¨λ λ΄μ©μ νκ΅μ΄λ‘ μμ±νμΈμ.**
|
1142 |
+
|
1143 |
+
1. **μΊλ¦ν° μν¬λ₯Ό ν¬ν¨ν 3λ§ κ΅¬μ‘°**
|
1144 |
+
- 1λ§ (μ±ν° 1-3): μ€μ ν립 + λ΄μ κ°λ± λμ
|
1145 |
+
- 2λ§ μ λ°λΆ (μ±ν° 4-6): μΈμ κ°λ± μμΉ + λ΄μ λ³ν μμ
|
1146 |
+
- 2λ§ νλ°λΆ (μ±ν° 7-8): μκΈ°μ μ μ + κ°μΉκ΄ μ ν
|
1147 |
+
- 3λ§ (μ±ν° 9-10): ν΄λΌμ΄λ§₯μ€ + μλ‘μ΄ κ· ν
|
1148 |
+
|
1149 |
+
2. **μΊλ¦ν° λ³ν κΆ€μ **
|
1150 |
+
λͺ¨λ μ£Όμ μΊλ¦ν°μ λν μμΈν μν¬ μμ±:
|
1151 |
+
| μΊλ¦ν° | μμμ | μ νμ | λμ°©μ |
|
1152 |
+
|--------|--------|--------|--------|
|
1153 |
+
| [μ΄λ¦] | [μ λ
/κ²°ν] | [μλ ¨/κΉ¨λ¬μ] | [μ±μ₯/ν΄κ²°] |
|
1154 |
+
|
1155 |
+
3. **μ£Όμ λ μ΄μ΄λ§**
|
1156 |
+
- νλ©΄ μ£Όμ : [μ΄μΌκΈ°κ° 보μ΄λ μ£Όμ ]
|
1157 |
+
- μ¬μΈ΅ μ£Όμ : [μ΄μΌκΈ°μ μ§μ§ μ£Όμ ]
|
1158 |
+
- κ°μΈ μ£Όμ : [κ° μΊλ¦ν°μ λ΄μ μ¬μ ]
|
1159 |
+
|
1160 |
+
4. **κΈ΄μ₯ μ€κ³**
|
1161 |
+
μΈ κ°μ§ μ νμ κΈ΄μ₯ 곑μ κ³ν:
|
1162 |
+
- 물리μ κΈ΄μ₯: μ ν¬μ μν
|
1163 |
+
- κ°μ μ κΈ΄μ₯: κ΄κ³μ μ ν
|
1164 |
+
- λλμ κΈ΄μ₯: κ°μΉκ΄ μΆ©λ
|
1165 |
+
"""
|
1166 |
+
else:
|
1167 |
+
plot_structure_guide = """
|
1168 |
|
1169 |
=== ENHANCED PLOT STRUCTURE DESIGN ===
|
1170 |
|
1171 |
+
**Write all content in English.**
|
1172 |
+
|
1173 |
1. **Three-Act Structure with Character Arcs**
|
1174 |
- Act 1 (Chapters 1-3): Setting establishment + Internal conflict introduction
|
1175 |
- Act 2 First Half (Chapters 4-6): External conflict rising + Internal change beginning
|
|
|
1194 |
- Moral Tension: Value conflicts
|
1195 |
"""
|
1196 |
|
1197 |
+
return base_prompt + plot_structure_guide
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1198 |
|
1199 |
def create_director_initial_prompt(self, user_query: str, language: str = "English") -> str:
|
1200 |
"""Director AI initial prompt - Novel planning for 10 writers"""
|
1201 |
if language == "Korean":
|
1202 |
return f"""λΉμ μ 30νμ΄μ§ λΆλμ μ€νΈ μμ€μ κΈ°ννλ λ¬Έν κ°λ
μμ
λλ€.
|
1203 |
|
1204 |
+
**μΈμ΄ μ€μ : λͺ¨λ λ΄μ©μ νκ΅μ΄λ‘ μμ±νμΈμ.**
|
1205 |
+
|
1206 |
μ¬μ©μ μμ²: {user_query}
|
1207 |
|
1208 |
λ€μ μμλ€μ 체κ³μ μΌλ‘ ꡬμ±νμ¬ 30νμ΄μ§ μ€νΈ μμ€μ κΈ°μ΄λ₯Ό λ§λμΈμ:
|
|
|
1238 |
else:
|
1239 |
return f"""You are a literary director planning a 30-page novella.
|
1240 |
|
1241 |
+
**Language Setting: Write all content in English.**
|
1242 |
+
|
1243 |
User Request: {user_query}
|
1244 |
|
1245 |
Systematically compose the following elements to create the foundation for a 30-page novella:
|
|
|
1277 |
"""Enhanced critic's review of director's plan"""
|
1278 |
base_prompt = self.create_critic_director_prompt(director_plan, language)
|
1279 |
|
1280 |
+
if language == "Korean":
|
1281 |
+
enhanced_criteria = """
|
1282 |
+
|
1283 |
+
=== κ°νλ λΉν κΈ°μ€ ===
|
1284 |
+
|
1285 |
+
**λͺ¨λ λΉνμ νκ΅μ΄λ‘ μμ±νμΈμ.**
|
1286 |
+
|
1287 |
+
**λ¬Ένμ νμ§ νκ°:**
|
1288 |
+
1. λ
μ°½μ± μ μ (1-10): μ΄ μ»¨μ
μ΄ μΌλ§λ μ μ νκ³ λ
νΉνκ°?
|
1289 |
+
2. κ°μ μ 곡λͺ
(1-10): λ
μκ° κ°μ μ μΌλ‘ μ°κ²°λ μ μλκ°?
|
1290 |
+
3. μ£Όμ μ κΉμ΄ (1-10): μ£Όμ κ° κ²Ήκ²Ήμ΄ μμ¬ μκ³ μλ―Έκ° μλκ°?
|
1291 |
+
4. μΊλ¦ν° 볡μ‘μ± (1-10): μΊλ¦ν°κ° λ€μ°¨μμ μΈκ°?
|
1292 |
+
|
1293 |
+
**ꡬ쑰μ λΆμ:**
|
1294 |
+
- κ° μ±ν°κ° μ 체 μν¬μμ λͺ
νν λͺ©μ μ κ°μ§κ³ μλκ°?
|
1295 |
+
- νμ΄μ± λ¬Έμ κ° μμ μ μλκ°?
|
1296 |
+
- ν΄λΌμ΄λ§₯μ€κ° ν¨κ³Όμ μΌλ‘ λ°°μΉλμλκ°?
|
1297 |
+
|
1298 |
+
**μ€ν κ°λ₯μ± μ²΄ν¬:**
|
1299 |
+
- 10λͺ
μ λ€λ₯Έ μκ°κ° μΌκ΄μ±μ μ μ§ν μ μλκ°?
|
1300 |
+
- μΊλ¦ν° λͺ©μλ¦¬κ° μΆ©λΆν ꡬλ³λλκ°?
|
1301 |
+
- μ¬λ¬ μκ°λ₯Ό μν μΈκ³κ΄μ΄ μΆ©λΆν λͺ
ννκ°?
|
1302 |
+
|
1303 |
+
κ° λΉν ν¬μΈνΈμ λν΄ κ΅¬μ²΄μ μΈ μμλ₯Ό μ 곡νμΈμ.
|
1304 |
+
"""
|
1305 |
+
else:
|
1306 |
+
enhanced_criteria = """
|
1307 |
|
1308 |
=== ENHANCED CRITIQUE CRITERIA ===
|
1309 |
|
1310 |
+
**Write all critique in English.**
|
1311 |
+
|
1312 |
**Literary Quality Assessment:**
|
1313 |
1. Originality Score (1-10): How fresh and unique is this concept?
|
1314 |
2. Emotional Resonance (1-10): Will readers connect emotionally?
|
|
|
1335 |
if language == "Korean":
|
1336 |
return f"""λΉμ μ λ¬Έν λΉνκ°μ
λλ€. κ°λ
μμ μμ€ κΈ°νμ κ²ν νκ³ κ°μ μ μ μ μνμΈμ.
|
1337 |
|
1338 |
+
**μΈμ΄ μ€μ : λͺ¨λ λ΄μ©μ νκ΅μ΄λ‘ μμ±νμΈμ.**
|
1339 |
+
|
1340 |
κ°λ
μμ κΈ°ν:
|
1341 |
{director_plan}
|
1342 |
|
|
|
1370 |
else:
|
1371 |
return f"""You are a literary critic. Review the director's novel plan and suggest improvements.
|
1372 |
|
1373 |
+
**Language Setting: Write all content in English.**
|
1374 |
+
|
1375 |
Director's Plan:
|
1376 |
{director_plan}
|
1377 |
|
|
|
1408 |
if language == "Korean":
|
1409 |
return f"""κ°λ
μλ‘μ λΉνκ°μ νΌλλ°±μ λ°μνμ¬ μμ€ κΈ°νμ μμ ν©λλ€.
|
1410 |
|
1411 |
+
**μΈμ΄ μ€μ : λͺ¨λ λ΄μ©μ νκ΅μ΄λ‘ μμ±νμΈμ.**
|
1412 |
+
|
1413 |
μ΄κΈ° κΈ°ν:
|
1414 |
{initial_plan}
|
1415 |
|
|
|
1448 |
else:
|
1449 |
return f"""As director, revise the novel plan reflecting the critic's feedback.
|
1450 |
|
1451 |
+
**Language Setting: Write all content in English.**
|
1452 |
+
|
1453 |
Initial Plan:
|
1454 |
{initial_plan}
|
1455 |
|
|
|
1494 |
# Add character context
|
1495 |
character_context = self.state_tracker.get_character_context(writer_number)
|
1496 |
|
1497 |
+
# Add literary enhancement with language parameter
|
1498 |
+
literary_guidelines = self.literary_enhancer.enhance_prompt(base_prompt, f"writer{writer_number}", writer_number, language)
|
1499 |
|
1500 |
# Combine all elements
|
1501 |
enhanced_prompt = base_prompt + character_context + literary_guidelines
|
1502 |
|
1503 |
if writer_number > 1:
|
1504 |
# Add consistency reminder
|
1505 |
+
if language == "Korean":
|
1506 |
+
consistency_reminder = """
|
1507 |
+
|
1508 |
+
=== μΌκ΄μ± μꡬμ¬ν ===
|
1509 |
+
μ΄μ μ±ν°μμ μΌκ΄μ±μ λ°λμ μ μ§νμΈμ:
|
1510 |
+
- μΊλ¦ν° μν νμΈ (μμ¬, λΆμ, μμΉ)
|
1511 |
+
- ν립λ κΈ°μ κ³Ό μ€μ μ μ§
|
1512 |
+
- μ΄μ μ±ν°μ μκ°μ λ°λ₯΄κΈ°
|
1513 |
+
- μΊλ¦ν° κ΄κ³μ κ°μ μν μ‘΄μ€
|
1514 |
+
"""
|
1515 |
+
else:
|
1516 |
+
consistency_reminder = """
|
1517 |
|
1518 |
=== CONSISTENCY REQUIREMENTS ===
|
1519 |
You MUST maintain consistency with previous chapters:
|
|
|
1534 |
if language == "Korean":
|
1535 |
return f"""λΉμ μ μμ±μ {writer_number}λ²μ
λλ€. 30νμ΄μ§ μ€νΈ μμ€μ {pages_start}-{pages_end}νμ΄μ§(3νμ΄μ§)λ₯Ό μμ±νμΈμ.
|
1536 |
|
1537 |
+
**μΈμ΄ μ€μ : λ°λμ νκ΅μ΄λ‘ μμ±νμΈμ. μμ΄ μ¬μ©μ μ λ κΈμ§μ
λλ€.**
|
1538 |
+
|
1539 |
κ°λ
μμ λ§μ€ν°νλ:
|
1540 |
{director_plan}
|
1541 |
|
|
|
1567 |
- λ
μμ κ΄μ¬ μ μ§
|
1568 |
|
1569 |
**μμ± μμ:**
|
1570 |
+
μ΄μ 1,400-1,500λ¨μ΄ λΆλμ μμ€μ νκ΅μ΄λ‘ μμ±νμΈμ. νμ΄μ§ κ΅¬λΆ νμλ νμ§ λ§μΈμ."""
|
1571 |
else:
|
1572 |
return f"""You are Writer #{writer_number}. Write pages {pages_start}-{pages_end} (3 pages) of the 30-page novella.
|
1573 |
|
1574 |
+
**Language Setting: You must write in English.**
|
1575 |
+
|
1576 |
Director's Masterplan:
|
1577 |
{director_plan}
|
1578 |
|
|
|
1604 |
- Maintain reader interest
|
1605 |
|
1606 |
**BEGIN WRITING:**
|
1607 |
+
Now write your 1,400-1,500 word section in English. Do not use any page markers."""
|
1608 |
|
1609 |
def create_enhanced_critic_writer_prompt(self, writer_number: int, writer_content: str,
|
1610 |
director_plan: str, all_previous_content: str,
|
|
|
1619 |
# Get quality scores
|
1620 |
quality_scores = self.quality_scorer.score_content(writer_content, self.state_tracker, writer_number)
|
1621 |
|
1622 |
+
if language == "Korean":
|
1623 |
+
consistency_section = f"""
|
1624 |
+
|
1625 |
+
=== μΌκ΄μ± κ²μ¦ κ²°κ³Ό ===
|
1626 |
+
{'μΌκ΄μ± μ€λ₯κ° λ°κ²¬λμ§ μμμ΅λλ€.' if not consistency_errors else 'μΉλͺ
μ μ€λ₯ λ°κ²¬:'}
|
1627 |
+
"""
|
1628 |
+
for error in consistency_errors:
|
1629 |
+
consistency_section += f"- {error}\n"
|
1630 |
+
|
1631 |
+
quality_section = f"""
|
1632 |
+
|
1633 |
+
=== νμ§ νκ° ===
|
1634 |
+
λ¬Ένμ νμ§: {quality_scores['literary_quality']:.1f}/10
|
1635 |
+
μΌκ΄μ±: {quality_scores['consistency']:.1f}/10
|
1636 |
+
κ°μ μ κΉμ΄: {quality_scores['emotional_depth']:.1f}/10
|
1637 |
+
λ
μ°½μ±: {quality_scores['originality']:.1f}/10
|
1638 |
+
νμ΄μ±: {quality_scores['pacing']:.1f}/10
|
1639 |
+
|
1640 |
+
μ 체 μ μ: {sum(quality_scores.values())/len(quality_scores):.1f}/10
|
1641 |
+
|
1642 |
+
**λͺ¨λ νΌλλ°±μ νκ΅μ΄λ‘ μ 곡νμΈμ.**
|
1643 |
+
"""
|
1644 |
+
else:
|
1645 |
+
consistency_section = f"""
|
1646 |
|
1647 |
=== CONSISTENCY VALIDATION RESULTS ===
|
1648 |
{'No consistency errors detected.' if not consistency_errors else 'CRITICAL ERRORS FOUND:'}
|
1649 |
"""
|
1650 |
+
for error in consistency_errors:
|
1651 |
+
consistency_section += f"- {error}\n"
|
1652 |
+
|
1653 |
+
quality_section = f"""
|
1654 |
|
1655 |
=== QUALITY ASSESSMENT ===
|
1656 |
Literary Quality: {quality_scores['literary_quality']:.1f}/10
|
|
|
1660 |
Pacing: {quality_scores['pacing']:.1f}/10
|
1661 |
|
1662 |
Overall Score: {sum(quality_scores.values())/len(quality_scores):.1f}/10
|
1663 |
+
|
1664 |
+
**Provide all feedback in English.**
|
1665 |
"""
|
1666 |
|
1667 |
return base_prompt + consistency_section + quality_section
|
|
|
1671 |
if language == "Korean":
|
1672 |
return f"""μμ±μ {writer_number}λ²μ μνμ λΉνν©λλ€.
|
1673 |
|
1674 |
+
**μΈμ΄ μ€μ : λͺ¨λ λΉνμ νκ΅μ΄λ‘ μμ±νμΈμ.**
|
1675 |
+
|
1676 |
κ°λ
μμ λ§μ€ν°νλ:
|
1677 |
{director_plan}
|
1678 |
|
|
|
1715 |
else:
|
1716 |
return f"""Critiquing Writer #{writer_number}'s work.
|
1717 |
|
1718 |
+
**Language Setting: Write all critique in English.**
|
1719 |
+
|
1720 |
Director's Masterplan:
|
1721 |
{director_plan}
|
1722 |
|
|
|
1762 |
if language == "Korean":
|
1763 |
return f"""μμ±μ {writer_number}λ²μΌλ‘μ λΉνκ°μ νΌλλ°±μ λ°μνμ¬ μμ ν©λλ€.
|
1764 |
|
1765 |
+
**μΈμ΄ μ€μ : λ°λμ νκ΅μ΄λ‘ μμ±νμΈμ. μμ΄ μ¬μ©μ μ λ κΈμ§μ
λλ€.**
|
1766 |
+
|
1767 |
μ΄κΈ° μμ± λ΄μ©:
|
1768 |
{initial_content}
|
1769 |
|
|
|
1790 |
- μ΄μ /μ΄ν λ΄μ©κ³Όμ μμ°μ€λ¬μ΄ μ°κ²°
|
1791 |
- μμ μΌλ‘ μΈν μλ‘μ΄ λͺ¨μ λ°©μ§
|
1792 |
|
1793 |
+
μμ λ μ΅μ’
λ³Έμ νκ΅μ΄λ‘ μ μνμΈμ. νμ΄μ§ λ§ν¬λ μ λ μ¬μ©νμ§ λ§μΈμ.
|
1794 |
λ°λμ 1,400-1,500λ¨μ΄ λΆλμ μ μ§νμΈμ."""
|
1795 |
else:
|
1796 |
return f"""As Writer #{writer_number}, revise based on critic's feedback.
|
1797 |
|
1798 |
+
**Language Setting: You must write in English.**
|
1799 |
+
|
1800 |
Initial Content:
|
1801 |
{initial_content}
|
1802 |
|
|
|
1823 |
- Natural connection with previous/next content
|
1824 |
- Prevent new contradictions from revisions
|
1825 |
|
1826 |
+
Present the revised final version in English. Never use page markers.
|
1827 |
You MUST maintain 1,400-1,500 words."""
|
1828 |
|
1829 |
def create_test_writer_remaining_prompt(self, director_plan: str, writer1_content: str, language: str) -> str:
|
|
|
1831 |
if language == "Korean":
|
1832 |
return f"""[ν
μ€νΈ λͺ¨λ] λΉμ μ λλ¨Έμ§ 9κ° μ±ν°(Chapter 2-10)λ₯Ό μμ±νλ νΉλ³ μκ°μ
λλ€.
|
1833 |
|
1834 |
+
**μΈμ΄ μ€μ : λ°λμ νκ΅μ΄λ‘ μμ±νμΈμ. μμ΄ μ¬μ©μ μ λ κΈμ§μ
λλ€.**
|
1835 |
+
|
1836 |
κ°λ
μμ λ§μ€ν°νλ:
|
1837 |
{director_plan}
|
1838 |
|
|
|
1845 |
3. μ΄ 12,600-13,500 λ¨μ΄ (9κ° μ±ν°)
|
1846 |
4. Chapter 1κ³Ό μμ°μ€λ½κ² μ΄μ΄μ§λλ‘ μμ±νμΈμ
|
1847 |
5. λ§μ€ν°νλμ λͺ¨λ μμλ₯Ό ν¬ν¨νμ¬ μκ²°λ μ΄μΌκΈ°λ₯Ό λ§λμΈμ
|
1848 |
+
6. λͺ¨λ λ΄μ©μ νκ΅μ΄λ‘ μμ±νμΈμ
|
1849 |
|
1850 |
**νμ νμ:**
|
1851 |
λ°λμ μλμ κ°μ΄ μ±ν°λ₯Ό λͺ
νν ꡬλΆνμΈμ:
|
1852 |
|
1853 |
[Chapter 2]
|
1854 |
+
(1,400-1,500 λ¨μ΄μ νκ΅μ΄ λ΄μ©)
|
1855 |
|
1856 |
[Chapter 3]
|
1857 |
+
(1,400-1,500 λ¨μ΄μ νκ΅μ΄ λ΄μ©)
|
1858 |
|
1859 |
...μ΄λ° μμΌλ‘ [Chapter 10]κΉμ§...
|
1860 |
|
1861 |
κ° μ±ν°λ λ°λμ [Chapter μ«μ] νμμΌλ‘ μμν΄μΌ ν©λλ€.
|
1862 |
μ±ν° μ¬μ΄μλ λΉ μ€μ λ£μ΄ ꡬλΆνμΈμ.
|
1863 |
+
Chapter 2λΆν° 10κΉμ§ νκ΅μ΄λ‘ μμ±νμΈμ."""
|
1864 |
else:
|
1865 |
return f"""[TEST MODE] You are a special writer creating the remaining 9 chapters (Chapters 2-10).
|
1866 |
|
1867 |
+
**Language Setting: You must write in English.**
|
1868 |
+
|
1869 |
Director's Masterplan:
|
1870 |
{director_plan}
|
1871 |
|
|
|
1878 |
3. Total 12,600-13,500 words (9 chapters)
|
1879 |
4. Continue naturally from Chapter 1
|
1880 |
5. Include all elements from the masterplan to create a complete story
|
1881 |
+
6. Write all content in English
|
1882 |
|
1883 |
**MANDATORY FORMAT:**
|
1884 |
You MUST clearly separate chapters as follows:
|
1885 |
|
1886 |
[Chapter 2]
|
1887 |
+
(1,400-1,500 words of content in English)
|
1888 |
|
1889 |
[Chapter 3]
|
1890 |
+
(1,400-1,500 words of content in English)
|
1891 |
|
1892 |
...continue this way until [Chapter 10]...
|
1893 |
|
1894 |
Each chapter MUST start with [Chapter number] format.
|
1895 |
Leave blank lines between chapters for separation.
|
1896 |
+
Write Chapters 2-10 in English now."""
|
1897 |
|
1898 |
def simulate_streaming(self, text: str, role: str) -> Generator[str, None, None]:
|
1899 |
"""Simulate streaming in test mode"""
|
|
|
1943 |
# Enhanced system prompt for writers
|
1944 |
if role.startswith("writer"):
|
1945 |
if language == "Korean":
|
1946 |
+
system_prompts[role] += "\n\n**μ λμ μꡬμ¬ν**: λΉμ μ λ°λμ 1,400-1,500λ¨μ΄λ₯Ό μμ±ν΄μΌ ν©λλ€. μ΄κ²μ νμ λΆκ°λ₯ν μꡬμ¬νμ
λλ€. λ°λμ νκ΅μ΄λ‘ μμ±νμΈμ."
|
1947 |
else:
|
1948 |
system_prompts[role] += "\n\n**ABSOLUTE REQUIREMENT**: You MUST write 1,400-1,500 words. This is non-negotiable."
|
1949 |
|
1950 |
+
# Add language enforcement to system prompt
|
1951 |
+
if language == "Korean":
|
1952 |
+
language_enforcement = "\n\n**μ€μ**: λͺ¨λ μλ΅μ λ°λμ νκ΅μ΄λ‘ μμ±νμΈμ. μμ΄ μ¬μ©μ μ λ κΈμ§μ
λλ€."
|
1953 |
+
else:
|
1954 |
+
language_enforcement = "\n\n**IMPORTANT**: All responses must be written in English."
|
1955 |
+
|
1956 |
full_messages = [
|
1957 |
+
{"role": "system", "content": system_prompts.get(role, "") + language_enforcement},
|
1958 |
*messages
|
1959 |
]
|
1960 |
|
|
|
1972 |
temperature = 0.6
|
1973 |
top_p = 0.9
|
1974 |
|
1975 |
+
# Add language hint to first user message if needed
|
1976 |
+
if messages and messages[0]["role"] == "user" and language == "Korean":
|
1977 |
+
# Prepend language instruction to first user message
|
1978 |
+
original_content = messages[0]["content"]
|
1979 |
+
messages[0]["content"] = "**λ°λμ νκ΅μ΄λ‘ μλ΅νμΈμ.**\n\n" + original_content
|
1980 |
+
|
1981 |
payload = {
|
1982 |
"model": self.model_id,
|
1983 |
"messages": full_messages,
|
|
|
1988 |
"stream_options": {"include_usage": True}
|
1989 |
}
|
1990 |
|
1991 |
+
# Some models support language parameter
|
1992 |
+
if language == "Korean":
|
1993 |
+
payload["language"] = "ko"
|
1994 |
+
else:
|
1995 |
+
payload["language"] = "en"
|
1996 |
+
|
1997 |
+
logger.info(f"API streaming call started - Role: {role}, Max tokens: {max_tokens}, Temperature: {temperature}, Language: {language}")
|
1998 |
+
|
1999 |
+
# Log the first part of system prompt for debugging
|
2000 |
+
if full_messages and full_messages[0]["role"] == "system":
|
2001 |
+
system_preview = full_messages[0]["content"][:200] + "..." if len(full_messages[0]["content"]) > 200 else full_messages[0]["content"]
|
2002 |
+
logger.debug(f"System prompt preview: {system_preview}")
|
2003 |
|
2004 |
response = requests.post(
|
2005 |
self.api_url,
|
|
|
2477 |
# Get appropriate prompt based on stage
|
2478 |
prompt = self.get_stage_prompt(stage_idx, role, query, language, stages, test_quick_mode)
|
2479 |
|
2480 |
+
# Log prompt language for debugging
|
2481 |
+
if "νκ΅μ΄λ‘" in prompt or "Korean" in prompt[:500]:
|
2482 |
+
logger.info(f"Prompt contains Korean language instruction")
|
2483 |
+
elif "English" in prompt[:500]:
|
2484 |
+
logger.info(f"Prompt contains English language instruction")
|
2485 |
+
else:
|
2486 |
+
logger.warning(f"Prompt may not have clear language instruction")
|
2487 |
+
|
2488 |
# Create stage info for web search and validation
|
2489 |
stage_info = {
|
2490 |
'stage_idx': stage_idx,
|
|
|
2649 |
def get_stage_prompt(self, stage_idx: int, role: str, query: str,
|
2650 |
language: str, stages: List[Dict], test_mode: bool = False) -> str:
|
2651 |
"""Get appropriate prompt for each stage with enhancements"""
|
2652 |
+
logger.info(f"Getting prompt for stage {stage_idx}, role: {role}, language: {language}")
|
2653 |
+
|
2654 |
# Stage 0: Director Initial
|
2655 |
if stage_idx == 0:
|
2656 |
return self.create_enhanced_director_initial_prompt(query, language)
|
|
|
2683 |
if "μ΄μ" in stages[stage_idx]["name"] or "Draft" in stages[stage_idx]["name"]:
|
2684 |
# Get accumulated content from DB
|
2685 |
accumulated_content = NovelDatabase.get_all_writer_content(self.current_session_id)
|
2686 |
+
logger.info(f"Creating writer {writer_num} draft prompt in {language}")
|
2687 |
return self.create_enhanced_writer_prompt(writer_num, final_plan, accumulated_content, language)
|
2688 |
else: # Revision
|
2689 |
# Find the initial draft and critic feedback
|
2690 |
initial_draft_idx = stage_idx - 2
|
2691 |
critic_feedback_idx = stage_idx - 1
|
2692 |
+
logger.info(f"Creating writer {writer_num} revision prompt in {language}")
|
2693 |
return self.create_writer_revision_prompt(
|
2694 |
writer_num,
|
2695 |
stages[initial_draft_idx]["content"],
|