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"],
|