openfree commited on
Commit
06baaa1
ยท
verified ยท
1 Parent(s): 596c9c5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +166 -50
app.py CHANGED
@@ -540,7 +540,7 @@ Present the revised final plan including:
540
  Create a final masterplan that all 16 writers can clearly understand."""
541
 
542
  def create_writer_prompt(self, writer_number: int, director_plan: str, previous_content: str, language: str = "English") -> str:
543
- """Individual writer prompt - 3ํŽ˜์ด์ง€, 1500-1800๋‹จ์–ด"""
544
  pages_start = (writer_number - 1) * 3 + 1
545
  pages_end = writer_number * 3
546
 
@@ -553,24 +553,32 @@ Create a final masterplan that all 16 writers can clearly understand."""
553
  {'์ด์ „๊นŒ์ง€์˜ ๋‚ด์šฉ:' if previous_content else '๋‹น์‹ ์ด ์ฒซ ๋ฒˆ์งธ ์ž‘์„ฑ์ž์ž…๋‹ˆ๋‹ค.'}
554
  {previous_content[-2000:] if previous_content else ''}
555
 
556
- ๋‹ค์Œ ์ง€์นจ์— ๋”ฐ๋ผ ์ž‘์„ฑํ•˜์„ธ์š”:
557
 
558
- 1. **๋ถ„๋Ÿ‰**: ์ •ํ™•ํžˆ 3ํŽ˜์ด์ง€ (ํŽ˜์ด์ง€๋‹น ์•ฝ 500-600๋‹จ์–ด, ์ด 1500-1800๋‹จ์–ด)
559
- 2. **์—ฐ์†์„ฑ**: ์ด์ „ ๋‚ด์šฉ๊ณผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ด์–ด์ง€๋„๋ก
560
- 3. **์ผ๊ด€์„ฑ**:
561
- - ๋“ฑ์žฅ์ธ๋ฌผ์˜ ์„ฑ๊ฒฉ๊ณผ ๋งํˆฌ ์œ ์ง€
 
 
 
 
 
 
 
 
 
 
 
562
  - ์‹œ๊ฐ„์„ ๊ณผ ๊ณต๊ฐ„ ์„ค์ • ์ค€์ˆ˜
563
- - ์ด๋ฏธ ์ œ์‹œ๋œ ์‚ฌ์‹ค๋“ค๊ณผ ๋ชจ์ˆœ ์—†์ด
564
- 4. **๋ฐœ์ „**:
565
- - ํ”Œ๋กฏ์„ ์ „์ง„์‹œํ‚ค๊ธฐ
566
- - ์ธ๋ฌผ์˜ ์„ฑ์žฅ์ด๋‚˜ ๋ณ€ํ™” ํ‘œํ˜„
567
- - ๊ธด์žฅ๊ฐ ์กฐ์ ˆ
568
- 5. **๋ฌธ์ฒด**:
569
- - ์ „์ฒด์ ์ธ ํ†ค๊ณผ ๋ถ„์œ„๊ธฐ ์œ ์ง€
570
- - ๋…์ž์˜ ๋ชฐ์ž…์„ ํ•ด์น˜์ง€ ์•Š๊ธฐ
571
-
572
- ์ค‘์š”: ํŽ˜์ด์ง€ ๊ตฌ๋ถ„ ํ‘œ์‹œ๋ฅผ ์ ˆ๋Œ€ ํ•˜์ง€ ๋งˆ์„ธ์š”. ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ด์–ด์ง€๋Š” ์„œ์‚ฌ๋กœ ์ž‘์„ฑํ•˜์„ธ์š”.
573
- ๋ฐ˜๋“œ์‹œ 1500-1800๋‹จ์–ด ๋ถ„๋Ÿ‰์„ ์ฑ„์›Œ์ฃผ์„ธ์š”."""
574
  else:
575
  return f"""You are Writer #{writer_number}. Write pages {pages_start}-{pages_end} (3 pages) of the 48-page novella.
576
 
@@ -580,24 +588,32 @@ Director's Masterplan:
580
  {'Previous content:' if previous_content else 'You are the first writer.'}
581
  {previous_content[-2000:] if previous_content else ''}
582
 
583
- Write according to these guidelines:
584
 
585
- 1. **Length**: Exactly 3 pages (about 500-600 words per page, total 1500-1800 words)
586
- 2. **Continuity**: Flow naturally from previous content
587
- 3. **Consistency**:
 
 
 
 
 
 
 
 
 
 
 
588
  - Maintain character personalities and speech
589
  - Follow timeline and spatial settings
590
- - No contradictions with established facts
591
- 4. **Development**:
592
- - Advance the plot
593
- - Show character growth or change
594
- - Control tension
595
- 5. **Style**:
596
- - Maintain overall tone and atmosphere
597
- - Keep reader immersion
598
-
599
- Important: DO NOT use any page markers. Write as continuous narrative.
600
- You MUST write 1500-1800 words."""
601
 
602
  def create_critic_writer_prompt(self, writer_number: int, writer_content: str, director_plan: str, all_previous_content: str, language: str = "English") -> str:
603
  """Critic's review of individual writer's work"""
@@ -942,7 +958,7 @@ Present a complete 48-page novel integrating all writers' contributions."""
942
  time.sleep(0.02)
943
 
944
  def call_llm_streaming(self, messages: List[Dict[str, str]], role: str, language: str = "English") -> Generator[str, None, None]:
945
- """Streaming LLM API call with adjusted token limits"""
946
 
947
  if self.test_mode:
948
  logger.info(f"Test mode streaming - Role: {role}, Language: {language}")
@@ -954,37 +970,50 @@ Present a complete 48-page novel integrating all writers' contributions."""
954
  try:
955
  system_prompts = self.get_system_prompts(language)
956
 
 
 
 
 
 
 
 
957
  full_messages = [
958
  {"role": "system", "content": system_prompts.get(role, "")},
959
  *messages
960
  ]
961
 
962
- # ์ž‘์„ฑ์ž๋“ค์—๊ฒŒ๋Š” ์ ์ ˆํ•œ ํ† ํฐ ํ• ๋‹น (3ํŽ˜์ด์ง€ = 1500-1800๋‹จ์–ด = ์•ฝ 7500-9000ํ† ํฐ)
963
  if role.startswith("writer"):
964
- max_tokens = 10240 # ์ถฉ๋ถ„ํ•œ ์—ฌ์œ 
965
- elif role == "director" and "์ตœ์ข…" in str(messages) or "final" in str(messages):
966
- max_tokens = 32768 # ์ตœ์ข… ๊ฐ๋…์€ ๋ชจ๋“  ๋‚ด์šฉ์„ ํ†ตํ•ฉ
 
 
 
 
967
  else:
968
- max_tokens = 8192
 
 
969
 
970
  payload = {
971
  "model": self.model_id,
972
  "messages": full_messages,
973
  "max_tokens": max_tokens,
974
- "temperature": 0.7 if role.startswith("writer") else 0.6,
975
- "top_p": 0.9,
976
  "stream": True,
977
  "stream_options": {"include_usage": True}
978
  }
979
 
980
- logger.info(f"API streaming call started - Role: {role}, Max tokens: {max_tokens}")
981
 
982
  response = requests.post(
983
  self.api_url,
984
  headers=self.create_headers(),
985
  json=payload,
986
  stream=True,
987
- timeout=30
988
  )
989
 
990
  if response.status_code != 200:
@@ -1003,7 +1032,7 @@ Present a complete 48-page novel integrating all writers' contributions."""
1003
  if data == "[DONE]":
1004
  if buffer:
1005
  yield buffer
1006
- logger.info(f"Streaming complete for {role}: {len(total_content)} chars")
1007
  break
1008
  try:
1009
  chunk = json.loads(data)
@@ -1014,7 +1043,7 @@ Present a complete 48-page novel integrating all writers' contributions."""
1014
  total_content += content
1015
 
1016
  # ์ž‘๊ฐ€๋Š” ๋” ํฐ ๋ฒ„ํผ ์‚ฌ์šฉ
1017
- buffer_size = 300 if role.startswith("writer") else 150
1018
 
1019
  if len(buffer) > buffer_size or '\n\n' in buffer:
1020
  yield buffer
@@ -1025,11 +1054,61 @@ Present a complete 48-page novel integrating all writers' contributions."""
1025
  if buffer:
1026
  yield buffer
1027
 
1028
- # ์ž‘๊ฐ€์˜ ๊ฒฝ์šฐ ๋‚ด์šฉ ๊ธธ์ด ํ™•์ธ
1029
  if role.startswith("writer"):
1030
  word_count = len(total_content.split())
1031
  if word_count < 1400:
1032
- logger.warning(f"Writer {role} produced only {word_count} words!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1033
 
1034
  except requests.exceptions.Timeout:
1035
  yield "โฑ๏ธ API call timed out. Please try again."
@@ -1040,7 +1119,7 @@ Present a complete 48-page novel integrating all writers' contributions."""
1040
  yield f"โŒ Error occurred: {str(e)}"
1041
 
1042
  def get_system_prompts(self, language: str) -> Dict[str, str]:
1043
- """Get system prompts for all 16 writers"""
1044
  if language == "Korean":
1045
  prompts = {
1046
  "director": "๋‹น์‹ ์€ 48ํŽ˜์ด์ง€ ์ค‘ํŽธ ์†Œ์„ค์„ ๊ธฐํšํ•˜๊ณ  ๊ฐ๋…ํ•˜๋Š” ๋ฌธํ•™ ๊ฐ๋…์ž์ž…๋‹ˆ๋‹ค. ์ฒด๊ณ„์ ์ด๊ณ  ์ฐฝ์˜์ ์ธ ์Šคํ† ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค์–ด๋ƒ…๋‹ˆ๋‹ค.",
@@ -1068,7 +1147,7 @@ Present a complete 48-page novel integrating all writers' contributions."""
1068
  ]
1069
 
1070
  for i, role_desc in enumerate(writer_roles, 1):
1071
- prompts[f"writer{i}"] = f"๋‹น์‹ ์€ {role_desc} ๋ฐ˜๋“œ์‹œ 1500-1800๋‹จ์–ด๋ฅผ ์ž‘์„ฑํ•˜์„ธ์š”."
1072
 
1073
  return prompts
1074
  else:
@@ -1098,7 +1177,7 @@ Present a complete 48-page novel integrating all writers' contributions."""
1098
  ]
1099
 
1100
  for i, role_desc in enumerate(writer_roles, 1):
1101
- prompts[f"writer{i}"] = f"You are {role_desc} You MUST write 1500-1800 words."
1102
 
1103
  return prompts
1104
 
@@ -1859,8 +1938,39 @@ def create_interface():
1859
 
1860
  return interface
1861
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1862
  # Main execution
1863
  if __name__ == "__main__":
 
 
1864
  logger.info("Starting SOMA Novel Writing System...")
1865
 
1866
  # Check environment
@@ -1874,7 +1984,13 @@ if __name__ == "__main__":
1874
  NovelDatabase.init_db()
1875
  logger.info("Database initialized successfully.")
1876
 
1877
- interface = create_interface()
 
 
 
 
 
 
1878
 
1879
  interface.launch(
1880
  server_name="0.0.0.0",
 
540
  Create a final masterplan that all 16 writers can clearly understand."""
541
 
542
  def create_writer_prompt(self, writer_number: int, director_plan: str, previous_content: str, language: str = "English") -> str:
543
+ """Individual writer prompt - ๊ฐ•ํ™”๋œ ๊ธธ์ด ์š”๊ตฌ์‚ฌํ•ญ"""
544
  pages_start = (writer_number - 1) * 3 + 1
545
  pages_end = writer_number * 3
546
 
 
553
  {'์ด์ „๊นŒ์ง€์˜ ๋‚ด์šฉ:' if previous_content else '๋‹น์‹ ์ด ์ฒซ ๋ฒˆ์งธ ์ž‘์„ฑ์ž์ž…๋‹ˆ๋‹ค.'}
554
  {previous_content[-2000:] if previous_content else ''}
555
 
556
+ **์ค‘์š” ์ง€์นจ:**
557
 
558
+ 1. **ํ•„์ˆ˜ ๋ถ„๋Ÿ‰**:
559
+ - ์ตœ์†Œ 1500๋‹จ์–ด, ์ตœ๋Œ€ 1800๋‹จ์–ด
560
+ - ๋Œ€๋žต 7500-9000์ž (๊ณต๋ฐฑ ํฌํ•จ)
561
+ - 3ํŽ˜์ด์ง€ ๋ถ„๋Ÿ‰์„ ๋ฐ˜๋“œ์‹œ ์ฑ„์›Œ์•ผ ํ•ฉ๋‹ˆ๋‹ค
562
+
563
+ 2. **๋ถ„๋Ÿ‰ ํ™•๋ณด ์ „๋žต**:
564
+ - ์ƒ์„ธํ•œ ์žฅ๋ฉด ๋ฌ˜์‚ฌ ํฌํ•จ
565
+ - ์ธ๋ฌผ์˜ ๋‚ด๋ฉด ์‹ฌ๋ฆฌ ๊นŠ์ด ์žˆ๊ฒŒ ํƒ๊ตฌ
566
+ - ๋Œ€ํ™”์™€ ํ–‰๋™์„ ๊ตฌ์ฒด์ ์œผ๋กœ ํ‘œํ˜„
567
+ - ๋ฐฐ๊ฒฝ๊ณผ ๋ถ„์œ„๊ธฐ๋ฅผ ์ƒ์ƒํ•˜๊ฒŒ ๊ทธ๋ ค๋‚ด๊ธฐ
568
+ - ๊ฐ๊ฐ์  ์„ธ๋ถ€์‚ฌํ•ญ(์‹œ๊ฐ, ์ฒญ๊ฐ, ์ด‰๊ฐ ๋“ฑ) ํ™œ์šฉ
569
+
570
+ 3. **์—ฐ์†์„ฑ๊ณผ ์ผ๊ด€์„ฑ**:
571
+ - ์ด์ „ ๋‚ด์šฉ๊ณผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์—ฐ๊ฒฐ
572
+ - ์ธ๋ฌผ ์„ฑ๊ฒฉ๊ณผ ๋งํˆฌ ์œ ์ง€
573
  - ์‹œ๊ฐ„์„ ๊ณผ ๊ณต๊ฐ„ ์„ค์ • ์ค€์ˆ˜
574
+
575
+ 4. **์„œ์‚ฌ ๋ฐœ์ „**:
576
+ - ํ”Œ๋กฏ์„ ์˜๋ฏธ ์žˆ๊ฒŒ ์ „์ง„์‹œํ‚ค๊ธฐ
577
+ - ๊ธด์žฅ๊ฐ ์ ์ ˆํžˆ ์กฐ์ ˆ
578
+ - ๋…์ž์˜ ๊ด€์‹ฌ ์œ ์ง€
579
+
580
+ **์ž‘์„ฑ ์‹œ์ž‘:**
581
+ ์ด์ œ 1500-1800๋‹จ์–ด ๋ถ„๋Ÿ‰์˜ ์†Œ์„ค์„ ์ž‘์„ฑํ•˜์„ธ์š”. ํŽ˜์ด์ง€ ๊ตฌ๋ถ„ ํ‘œ์‹œ๋Š” ํ•˜์ง€ ๋งˆ์„ธ์š”."""
 
 
 
582
  else:
583
  return f"""You are Writer #{writer_number}. Write pages {pages_start}-{pages_end} (3 pages) of the 48-page novella.
584
 
 
588
  {'Previous content:' if previous_content else 'You are the first writer.'}
589
  {previous_content[-2000:] if previous_content else ''}
590
 
591
+ **CRITICAL INSTRUCTIONS:**
592
 
593
+ 1. **MANDATORY LENGTH**:
594
+ - Minimum 1500 words, Maximum 1800 words
595
+ - Approximately 7500-9000 characters
596
+ - You MUST fill 3 full pages
597
+
598
+ 2. **LENGTH STRATEGIES**:
599
+ - Include detailed scene descriptions
600
+ - Explore character's inner psychology deeply
601
+ - Express dialogue and actions concretely
602
+ - Paint backgrounds and atmosphere vividly
603
+ - Use sensory details (visual, auditory, tactile, etc.)
604
+
605
+ 3. **CONTINUITY & CONSISTENCY**:
606
+ - Flow naturally from previous content
607
  - Maintain character personalities and speech
608
  - Follow timeline and spatial settings
609
+
610
+ 4. **NARRATIVE DEVELOPMENT**:
611
+ - Advance the plot meaningfully
612
+ - Control tension appropriately
613
+ - Maintain reader interest
614
+
615
+ **BEGIN WRITING:**
616
+ Now write your 1500-1800 word section. Do not use any page markers."""
 
 
 
617
 
618
  def create_critic_writer_prompt(self, writer_number: int, writer_content: str, director_plan: str, all_previous_content: str, language: str = "English") -> str:
619
  """Critic's review of individual writer's work"""
 
958
  time.sleep(0.02)
959
 
960
  def call_llm_streaming(self, messages: List[Dict[str, str]], role: str, language: str = "English") -> Generator[str, None, None]:
961
+ """Streaming LLM API call with improved prompting"""
962
 
963
  if self.test_mode:
964
  logger.info(f"Test mode streaming - Role: {role}, Language: {language}")
 
970
  try:
971
  system_prompts = self.get_system_prompts(language)
972
 
973
+ # ์ž‘๊ฐ€์—๊ฒŒ ๋” ๊ฐ•ํ•œ ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ ์ถ”๊ฐ€
974
+ if role.startswith("writer"):
975
+ if language == "Korean":
976
+ system_prompts[role] += "\n\n**์ ˆ๋Œ€์  ์š”๊ตฌ์‚ฌํ•ญ**: ๋‹น์‹ ์€ ๋ฐ˜๋“œ์‹œ 1500-1800๋‹จ์–ด๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ํ˜‘์ƒ ๋ถˆ๊ฐ€๋Šฅํ•œ ์š”๊ตฌ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. ์งง์€ ์‘๋‹ต์€ ํ—ˆ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."
977
+ else:
978
+ system_prompts[role] += "\n\n**ABSOLUTE REQUIREMENT**: You MUST write 1500-1800 words. This is non-negotiable. Short responses are not acceptable."
979
+
980
  full_messages = [
981
  {"role": "system", "content": system_prompts.get(role, "")},
982
  *messages
983
  ]
984
 
985
+ # ์ž‘์„ฑ์ž๋“ค์—๊ฒŒ๋Š” ๋” ๋งŽ์€ ํ† ํฐ ํ• ๋‹น
986
  if role.startswith("writer"):
987
+ max_tokens = 12000 # ์ฆ๊ฐ€
988
+ temperature = 0.8 # ์•ฝ๊ฐ„ ์ฆ๊ฐ€
989
+ top_p = 0.95 # ์•ฝ๊ฐ„ ์ฆ๊ฐ€
990
+ elif role == "director" and ("์ตœ์ข…" in str(messages) or "final" in str(messages)):
991
+ max_tokens = 40000 # ์ฆ๊ฐ€
992
+ temperature = 0.6
993
+ top_p = 0.9
994
  else:
995
+ max_tokens = 10000
996
+ temperature = 0.6
997
+ top_p = 0.9
998
 
999
  payload = {
1000
  "model": self.model_id,
1001
  "messages": full_messages,
1002
  "max_tokens": max_tokens,
1003
+ "temperature": temperature,
1004
+ "top_p": top_p,
1005
  "stream": True,
1006
  "stream_options": {"include_usage": True}
1007
  }
1008
 
1009
+ logger.info(f"API streaming call started - Role: {role}, Max tokens: {max_tokens}, Temperature: {temperature}")
1010
 
1011
  response = requests.post(
1012
  self.api_url,
1013
  headers=self.create_headers(),
1014
  json=payload,
1015
  stream=True,
1016
+ timeout=60 # ํƒ€์ž„์•„์›ƒ ์ฆ๊ฐ€
1017
  )
1018
 
1019
  if response.status_code != 200:
 
1032
  if data == "[DONE]":
1033
  if buffer:
1034
  yield buffer
1035
+ logger.info(f"Streaming complete for {role}: {len(total_content)} chars, {len(total_content.split())} words")
1036
  break
1037
  try:
1038
  chunk = json.loads(data)
 
1043
  total_content += content
1044
 
1045
  # ์ž‘๊ฐ€๋Š” ๋” ํฐ ๋ฒ„ํผ ์‚ฌ์šฉ
1046
+ buffer_size = 500 if role.startswith("writer") else 200
1047
 
1048
  if len(buffer) > buffer_size or '\n\n' in buffer:
1049
  yield buffer
 
1054
  if buffer:
1055
  yield buffer
1056
 
1057
+ # ์ž‘๊ฐ€์˜ ๊ฒฝ์šฐ ๋‚ด์šฉ ๊ธธ์ด ํ™•์ธ ๋ฐ ์žฌ์‹œ๋„
1058
  if role.startswith("writer"):
1059
  word_count = len(total_content.split())
1060
  if word_count < 1400:
1061
+ logger.warning(f"Writer {role} produced only {word_count} words! Requesting continuation...")
1062
+
1063
+ # ์ถ”๊ฐ€ ์š”์ฒญ
1064
+ continuation_prompt = f"Continue writing to reach the required 1500-1800 words. You have written {word_count} words so far. Write {1500 - word_count} more words to complete your section."
1065
+
1066
+ if language == "Korean":
1067
+ continuation_prompt = f"ํ•„์ˆ˜ ๋ถ„๋Ÿ‰ 1500-1800๋‹จ์–ด๋ฅผ ์ฑ„์šฐ๊ธฐ ์œ„ํ•ด ๊ณ„์† ์ž‘์„ฑํ•˜์„ธ์š”. ์ง€๊ธˆ๊นŒ์ง€ {word_count}๋‹จ์–ด๋ฅผ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค. {1500 - word_count}๋‹จ์–ด๋ฅผ ๋” ์ž‘์„ฑํ•˜์—ฌ ์„น์…˜์„ ๏ฟฝ๏ฟฝ์„ฑํ•˜์„ธ์š”."
1068
+
1069
+ full_messages.append({"role": "assistant", "content": total_content})
1070
+ full_messages.append({"role": "user", "content": continuation_prompt})
1071
+
1072
+ # ์ถ”๊ฐ€ ์ƒ์„ฑ ์š”์ฒญ
1073
+ continuation_payload = {
1074
+ "model": self.model_id,
1075
+ "messages": full_messages,
1076
+ "max_tokens": 6000,
1077
+ "temperature": temperature,
1078
+ "top_p": top_p,
1079
+ "stream": True
1080
+ }
1081
+
1082
+ logger.info(f"Requesting continuation for {role}...")
1083
+
1084
+ continuation_response = requests.post(
1085
+ self.api_url,
1086
+ headers=self.create_headers(),
1087
+ json=continuation_payload,
1088
+ stream=True,
1089
+ timeout=60
1090
+ )
1091
+
1092
+ if continuation_response.status_code == 200:
1093
+ for line in continuation_response.iter_lines():
1094
+ if line:
1095
+ line = line.decode('utf-8')
1096
+ if line.startswith("data: "):
1097
+ data = line[6:]
1098
+ if data == "[DONE]":
1099
+ break
1100
+ try:
1101
+ chunk = json.loads(data)
1102
+ if "choices" in chunk and chunk["choices"]:
1103
+ content = chunk["choices"][0].get("delta", {}).get("content", "")
1104
+ if content:
1105
+ yield content
1106
+ total_content += content
1107
+ except json.JSONDecodeError:
1108
+ continue
1109
+
1110
+ final_word_count = len(total_content.split())
1111
+ logger.info(f"Final word count for {role}: {final_word_count}")
1112
 
1113
  except requests.exceptions.Timeout:
1114
  yield "โฑ๏ธ API call timed out. Please try again."
 
1119
  yield f"โŒ Error occurred: {str(e)}"
1120
 
1121
  def get_system_prompts(self, language: str) -> Dict[str, str]:
1122
+ """Get system prompts for all 16 writers with enhanced length requirements"""
1123
  if language == "Korean":
1124
  prompts = {
1125
  "director": "๋‹น์‹ ์€ 48ํŽ˜์ด์ง€ ์ค‘ํŽธ ์†Œ์„ค์„ ๊ธฐํšํ•˜๊ณ  ๊ฐ๋…ํ•˜๋Š” ๋ฌธํ•™ ๊ฐ๋…์ž์ž…๋‹ˆ๋‹ค. ์ฒด๊ณ„์ ์ด๊ณ  ์ฐฝ์˜์ ์ธ ์Šคํ† ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค์–ด๋ƒ…๋‹ˆ๋‹ค.",
 
1147
  ]
1148
 
1149
  for i, role_desc in enumerate(writer_roles, 1):
1150
+ prompts[f"writer{i}"] = f"๋‹น์‹ ์€ {role_desc} ๋ฐ˜๋“œ์‹œ 1500-1800๋‹จ์–ด๋ฅผ ์ž‘์„ฑํ•˜์„ธ์š”. ์ด๋Š” ์ ˆ๋Œ€์ ์ธ ์š”๊ตฌ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค."
1151
 
1152
  return prompts
1153
  else:
 
1177
  ]
1178
 
1179
  for i, role_desc in enumerate(writer_roles, 1):
1180
+ prompts[f"writer{i}"] = f"You are {role_desc} You MUST write 1500-1800 words. This is an absolute requirement."
1181
 
1182
  return prompts
1183
 
 
1938
 
1939
  return interface
1940
 
1941
+ # ๋น ๋ฅธ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ์ถ•์†Œ ๋ฒ„์ „ ์ถ”๊ฐ€
1942
+ def create_quick_test_interface():
1943
+ """๋น ๋ฅธ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ๊ฐ„๋‹จํ•œ ์ธํ„ฐํŽ˜์ด์Šค"""
1944
+ with gr.Blocks(title="Novel Writing System - Quick Test") as interface:
1945
+ gr.Markdown("# ๐Ÿš€ Quick Test Mode - 3 Writers Only")
1946
+
1947
+ with gr.Row():
1948
+ query_input = gr.Textbox(label="Novel Theme", placeholder="Enter theme...")
1949
+ language = gr.Radio(["English", "Korean"], value="English", label="Language")
1950
+ submit_btn = gr.Button("Start Quick Test")
1951
+
1952
+ output = gr.Textbox(label="Output", lines=20)
1953
+
1954
+ def quick_test(query, lang):
1955
+ system = NovelWritingSystem()
1956
+ # 3๋ช…์˜ ์ž‘๊ฐ€๋งŒ ํ…Œ์ŠคํŠธ
1957
+ stages = ["Director Plan", "Writer 1", "Writer 2", "Writer 3", "Final"]
1958
+ result = f"Testing with theme: {query}\n\n"
1959
+
1960
+ for stage in stages:
1961
+ result += f"Processing {stage}...\n"
1962
+ time.sleep(1) # ์‹œ๋ฎฌ๋ ˆ์ด์…˜
1963
+
1964
+ return result + "\nQuick test complete!"
1965
+
1966
+ submit_btn.click(quick_test, inputs=[query_input, language], outputs=output)
1967
+
1968
+ return interface
1969
+
1970
  # Main execution
1971
  if __name__ == "__main__":
1972
+ import sys
1973
+
1974
  logger.info("Starting SOMA Novel Writing System...")
1975
 
1976
  # Check environment
 
1984
  NovelDatabase.init_db()
1985
  logger.info("Database initialized successfully.")
1986
 
1987
+ # ๋น ๋ฅธ ํ…Œ์ŠคํŠธ ๋ชจ๋“œ ์˜ต์…˜
1988
+ if "--quick-test" in sys.argv:
1989
+ logger.info("Running in QUICK TEST mode")
1990
+ interface = create_quick_test_interface()
1991
+ else:
1992
+ logger.info("Running in FULL mode")
1993
+ interface = create_interface()
1994
 
1995
  interface.launch(
1996
  server_name="0.0.0.0",