openfree commited on
Commit
01933ce
ยท
verified ยท
1 Parent(s): 077e0d8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +233 -165
app.py CHANGED
@@ -2098,200 +2098,268 @@ def translate_to_korean(text, category=None):
2098
  return translations.get(text, text)
2099
 
2100
  def generate_random_theme(language="English"):
2101
- """Generate an interesting random novel theme with smart compatibility"""
2102
  try:
2103
- # JSON ํŒŒ์ผ ๊ฒฝ๋กœ ํ™•์ธ
2104
  json_path = Path("novel_themes.json")
2105
-
2106
- # JSON ํŒŒ์ผ์ด ์—†์œผ๋ฉด ๋‚ด์žฅ ๋ฐ์ดํ„ฐ ์‚ฌ์šฉ
2107
  if not json_path.exists():
2108
  print("[WARNING] novel_themes.json not found, using built-in data")
2109
- # ์—ฌ๊ธฐ์— ์ง์ ‘ ํ…Œ๋งˆ ๋ฐ์ดํ„ฐ ์ •์˜
2110
- themes = [
2111
- "digital_extinction", "sensory_revolution", "temporal_paradox",
2112
- "emotional_economy", "linguistic_apocalypse", "algorithmic_mysticism",
2113
- "biological_nostalgia", "social_physics", "reality_bureaucracy",
2114
- "dream_industrialization", "genetic_copyright", "atmospheric_capitalism"
2115
- ]
2116
-
2117
- characters = [
2118
- "last person who dreams without ads",
2119
- "excavator of deleted conversations",
2120
- "black market memory dealer",
2121
- "guerrilla flavor bomber",
2122
- "temporal audit specialist",
2123
- "organic emotion cultivator",
2124
- "binary meditation teacher",
2125
- "extinct plant memory keeper",
2126
- "social distance calibrator",
2127
- "subconscious strip miner"
2128
- ]
2129
-
2130
- hooks = [
2131
- "discovers their memories belong to a corporate subscription service",
2132
- "realizes they're the only person not running on autopilot",
2133
- "finds out their personality is a discontinued model",
2134
- "learns their emotions are being crowdsourced",
2135
- "discovers they're allergic to their own digital footprint",
2136
- "causes the first spontaneous laughter in a decade",
2137
- "accidentally introduces randomness into a perfect system",
2138
- "finds the last handwritten letter in existence"
2139
- ]
2140
-
2141
- openings = [
2142
- "The notification read: 'Your humanity subscription expires in 24 hours.'",
2143
- "I was the only one at the funeral who couldn't stream my grief.",
2144
- "The day empathy became downloadable was the day I became obsolete.",
2145
- "My daughter asked me what dreams were, and I realized I'd forgotten.",
2146
- "The silence lasted twelve secondsโ€”a new world record.",
2147
- "The happiness mandate made funerals unbearably cheerful.",
2148
- "My genetic audit revealed I was 3% copyrighted material.",
2149
- "They repossessed my childhood memories this morning."
2150
- ]
2151
-
2152
- questions = [
2153
- "What remains human when humanity is optional?",
2154
- "Is consciousness a bug or a feature?",
2155
- "Can nostalgia exist without mortality?",
2156
- "Who owns the right to forget?",
2157
- "Is numbness a form of control?",
2158
- "What happens when words lose meaning?",
2159
- "Do algorithms dream of digital souls?",
2160
- "Are we variables in God's code?"
2161
- ]
2162
-
2163
  else:
2164
- # JSON ํŒŒ์ผ ๋กœ๋“œ
2165
  with open(json_path, 'r', encoding='utf-8') as f:
2166
  data = json.load(f)
 
 
 
 
 
 
2167
 
2168
- themes = list(data['core_themes'].keys())
2169
- characters = []
2170
- for char_data in data['characters'].values():
2171
- characters.extend(char_data.get('variations', []))
2172
-
2173
- hooks = []
2174
- for hook_list in data['narrative_hooks'].values():
2175
- hooks.extend(hook_list)
2176
-
2177
- openings = []
2178
- for opening_list in data['opening_sentences'].values():
2179
- openings.extend(opening_list)
2180
-
2181
- questions = []
2182
- for phil_data in data['philosophies'].values():
2183
- questions.extend(phil_data.get('core_questions', []))
2184
-
2185
- # ์ง„์งœ ๋žœ๋ค ์„ ํƒ์„ ์œ„ํ•ด ์ธ๋ฑ์Šค ๊ธฐ๋ฐ˜ ์„ ํƒ
2186
- import os
2187
-
2188
- # OS์˜ ์ง„์งœ ๋žœ๋ค ์‚ฌ์šฉ
2189
- theme = themes[int.from_bytes(os.urandom(1), 'big') % len(themes)]
2190
- character = characters[int.from_bytes(os.urandom(1), 'big') % len(characters)]
2191
- hook = hooks[int.from_bytes(os.urandom(1), 'big') % len(hooks)]
2192
- opening = openings[int.from_bytes(os.urandom(1), 'big') % len(openings)]
2193
- question = questions[int.from_bytes(os.urandom(1), 'big') % len(questions)]
2194
-
2195
- # ๋žœ๋ค ๋ฉ”์‹œ์ง€
2196
- messages = [
2197
- 'resistance is creation',
2198
- 'memory is rebellion',
2199
- 'imperfection is sacred',
2200
- 'connection transcends system',
2201
- 'humanity is a choice not a default'
2202
- ]
2203
- message = messages[int.from_bytes(os.urandom(1), 'big') % len(messages)]
2204
-
2205
- # ํ•œ๊ตญ์–ด ๋ฒˆ์—ญ
2206
  if language == "Korean":
2207
- # ๋ฒˆ์—ญ ๋กœ์ง
2208
- character = translate_to_korean(character)
2209
- question = translate_to_korean(question)
2210
- hook = translate_to_korean(hook)
2211
- opening = translate_to_korean(opening)
2212
- theme_kr = translate_to_korean(theme)
2213
-
2214
- message_kr = {
2215
- 'resistance is creation': '์ €ํ•ญ์ด ๊ณง ์ฐฝ์กฐ์ธ์ง€',
2216
- 'memory is rebellion': '๊ธฐ์–ต์ด ๊ณง ๋ฐ˜๋ž€์ธ์ง€',
2217
- 'imperfection is sacred': '๋ถˆ์™„์ „ํ•จ์ด ์‹ ์„ฑํ•œ์ง€',
2218
- 'connection transcends system': '์—ฐ๊ฒฐ์ด ์‹œ์Šคํ…œ์„ ์ดˆ์›”ํ•˜๋Š”์ง€',
2219
- 'humanity is a choice not a default': '์ธ๊ฐ„์„ฑ์€ ๊ธฐ๋ณธ๊ฐ’์ด ์•„๋‹Œ ์„ ํƒ์ธ์ง€'
2220
- }
2221
- message = message_kr.get(message, message)
2222
-
2223
- return f"""**์ œ๋ชฉ ์ปจ์…‰:** '{character.split()[0]}์˜ {theme_kr}'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2224
 
2225
- **์ฒซ ๋ฌธ์žฅ:** "{opening}"
 
 
 
2226
 
2227
- **์ค‘์‹ฌ ์ธ๋ฌผ:** {hook}ํ•˜๋Š” {character}.
 
 
 
 
2228
 
2229
- **ํ•ต์‹ฌ ์ฒ ํ•™์  ์งˆ๋ฌธ:** {question}
 
 
 
2230
 
2231
- **์„œ์‚ฌ ๊ตฌ์กฐ:**
2232
- - ํŒŒํŠธ 1-2: ๊ท ์—ด๋œ ํ˜„์‹ค์˜ ๋ฐœ๊ฒฌ
2233
- - ํŒŒํŠธ 3-4: ์ค‘์‹ฌ ๊ฐˆ๋“ฑ์˜ ์‹ฌํ™”
2234
- - ํŒŒํŠธ 5-6: ์ˆจ๊ฒจ์ง„ ์ง„์‹ค์˜ ๋ฐœ๊ฒฌ
2235
- - ํŒŒํŠธ 7-8: ๊ถ๊ทน์  ์„ ํƒ์˜ ์ง๋ฉด
2236
- - ํŒŒํŠธ 9-10: ์ž์•„์™€ ์„ธ๊ณ„์˜ ๋ณ€ํ™”
 
 
 
 
 
 
2237
 
2238
- **์ฃผ์ œ์  ํ•ต์‹ฌ:** ์ด ์ด์•ผ๊ธฐ๋Š” {theme_kr}๊ฐ€ ๊ทผ๋ณธ์ ์œผ๋กœ ์ธ๊ฐ„ ์กด์žฌ๋ฅผ ๋ณ€ํ™”์‹œํ‚จ ์„ธ๊ณ„์—์„œ {character}์˜ ์—ฌ์ •์„ ํ†ตํ•ด {question.lower().rstrip('?')}๋ฅผ ํƒ๊ตฌํ•ฉ๋‹ˆ๋‹ค.
2239
 
2240
- **ํ†ค:** ์–ด๋‘ก์ง€๋งŒ ์œ ๋จธ๋Ÿฌ์Šคํ•˜๊ณ  ์‹ฌ์˜คํ•œ - ์นดํ”„์นด, ๋ณด๋ฅดํ—ค์Šค, ํ•œ๊ฐ•์ด ๊ทธ๋“ค์˜ ๊ฐ€์žฅ ์–ด๋‘์šด ๋น„์ „์„ ๋„˜์–ด์„  ์„ธ๊ณ„๋ฅผ ์œ„ํ•ด ๊ธ€์„ ์“ด๋‹ค๊ณ  ์ƒ์ƒํ•ด๋ณด์„ธ์š”.
2241
 
2242
- **๋ฉ”์‹œ์ง€:** {theme_kr}๋ฅผ ํƒ๊ตฌํ•˜๋ฉด์„œ, ์ด ์ด์•ผ๊ธฐ๋Š” {message} ๋ฌป์Šต๋‹ˆ๋‹ค."""
2243
-
2244
- else:
2245
- return f"""**Title Concept:** 'The {character.split()[0].title()}'s {theme.replace('_', ' ').title()}'
 
2246
 
2247
- **Opening Sentence:** "{opening}"
2248
 
2249
- **Central Character:** A {character} who {hook}.
2250
 
2251
- **Core Philosophical Question:** {question}
2252
 
2253
- **Narrative Arc:**
2254
- - Parts 1-2: Discovery of fractured reality
2255
- - Parts 3-4: Deepening central conflict
2256
- - Parts 5-6: Uncovering hidden truths
2257
- - Parts 7-8: Confronting ultimate choice
2258
- - Parts 9-10: Transformation of self and world
2259
 
2260
- **Thematic Core:** This story explores {question.lower()} through the journey of {character} in a world where {theme.replace('_', ' ')} has fundamentally altered human existence.
 
 
 
 
 
 
 
 
2261
 
2262
- **Tone:** Darkly humorous yet profound - imagine Kafka, Borges, or Atwood writing for a world that has surpassed their darkest visions.
2263
 
2264
- **Message:** In exploring {theme.replace('_', ' ')}, the story asks whether {message}."""
 
 
 
 
 
 
2265
 
 
 
 
 
 
 
 
 
 
 
 
2266
  except Exception as e:
2267
- print(f"[CRITICAL ERROR] {str(e)}")
2268
- # ์ง„์งœ ๊ฐ„๋‹จํ•œ ๋žœ๋ค ์ƒ์„ฑ
2269
- import hashlib
2270
- import datetime
2271
-
2272
- # ํ˜„์žฌ ์‹œ๊ฐ„์˜ ํ•ด์‹œ๊ฐ’์œผ๋กœ ์ธ๋ฑ์Šค ์ƒ์„ฑ
2273
- time_hash = hashlib.md5(str(datetime.datetime.now()).encode()).hexdigest()
2274
- idx = int(time_hash[:8], 16)
2275
-
2276
- simple_themes = [
2277
- ("๊ธฐ์–ต ๊ฑฐ๋ž˜์ƒ", "Memory Trader"),
2278
- ("์‹œ๊ฐ„ ๋„๋‘‘", "Time Thief"),
2279
- ("๊ฐ์ • ๋†๋ถ€", "Emotion Farmer"),
2280
- ("๊ฟˆ ๊ด‘๋ถ€", "Dream Miner"),
2281
- ("์นจ๋ฌต ์ˆ˜์ง‘๊ฐ€", "Silence Collector")
2282
- ]
2283
 
2284
- theme = simple_themes[idx % len(simple_themes)]
 
 
 
 
2285
 
 
 
 
 
 
2286
  if language == "Korean":
2287
- return f"""**์ œ๋ชฉ:** '{theme[0]}์˜ ๊ณ ๋ฐฑ'
2288
- **์ฒซ ๋ฌธ์žฅ:** "์˜ค๋Š˜๋„ ๋‚˜๋Š” ๋‚จ๋“ค์ด ๋ฒ„๋ฆฐ ๊ฒƒ์„ ์ฃผ์› ๋‹ค."
2289
- **์ค‘์‹ฌ ๊ฐˆ๋“ฑ:** ์ธ๊ฐ„์˜ ๋ณธ์งˆ์  ๊ฐ€์น˜๊ฐ€ ๊ฑฐ๋ž˜๋˜๋Š” ์„ธ๊ณ„์—์„œ์˜ ์ƒ์กด"""
2290
  else:
2291
- return f"""**Title:** 'Confessions of a {theme[1]}'
2292
- **Opening:** "Today again, I collected what others discarded."
2293
- **Central Conflict:** Survival in a world where human essence is traded"""
2294
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2295
 
2296
  # Create Gradio interface
2297
  def create_interface():
 
2098
  return translations.get(text, text)
2099
 
2100
  def generate_random_theme(language="English"):
2101
+ """Generate a coherent and natural novel theme using LLM"""
2102
  try:
2103
+ # JSON ํŒŒ์ผ ๋กœ๋“œ
2104
  json_path = Path("novel_themes.json")
 
 
2105
  if not json_path.exists():
2106
  print("[WARNING] novel_themes.json not found, using built-in data")
2107
+ # ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ ์ •์˜
2108
+ themes_data = {
2109
+ "themes": ["digital extinction", "sensory revolution", "temporal paradox"],
2110
+ "characters": ["memory trader", "time thief", "emotion farmer"],
2111
+ "hooks": ["discovering hidden truth", "facing impossible choice", "breaking the system"],
2112
+ "questions": ["What makes us human?", "Can memory define identity?", "Is free will an illusion?"]
2113
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2114
  else:
 
2115
  with open(json_path, 'r', encoding='utf-8') as f:
2116
  data = json.load(f)
2117
+ themes_data = {
2118
+ "themes": list(data.get('core_themes', {}).keys()),
2119
+ "characters": [],
2120
+ "hooks": [],
2121
+ "questions": []
2122
+ }
2123
 
2124
+ # Extract data from JSON
2125
+ for char_data in data.get('characters', {}).values():
2126
+ themes_data["characters"].extend(char_data.get('variations', []))
2127
+ for hook_list in data.get('narrative_hooks', {}).values():
2128
+ themes_data["hooks"].extend(hook_list)
2129
+ for phil_data in data.get('philosophies', {}).values():
2130
+ themes_data["questions"].extend(phil_data.get('core_questions', []))
2131
+
2132
+ # Random selection with better randomization
2133
+ import secrets
2134
+ theme = secrets.choice(themes_data["themes"])
2135
+ character = secrets.choice(themes_data["characters"])
2136
+ hook = secrets.choice(themes_data["hooks"])
2137
+ question = secrets.choice(themes_data["questions"])
2138
+
2139
+ # Create a natural prompt for LLM to generate coherent theme
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2140
  if language == "Korean":
2141
+ prompt = f"""๋‹ค์Œ ์š”์†Œ๋“ค์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž์—ฐ์Šค๋Ÿฝ๊ณ  ํฅ๋ฏธ๋กœ์šด ์†Œ์„ค ์ฃผ์ œ๋ฅผ ์ƒ์„ฑํ•˜์„ธ์š”:
2142
+
2143
+ ์ฃผ์ œ: {theme}
2144
+ ์บ๋ฆญํ„ฐ: {character}
2145
+ ์‚ฌ๊ฑด: {hook}
2146
+ ์ฒ ํ•™์  ์งˆ๋ฌธ: {question}
2147
+
2148
+ ์š”๊ตฌ์‚ฌํ•ญ:
2149
+ 1. ๋ชจ๋“  ์š”์†Œ๊ฐ€ ์œ ๊ธฐ์ ์œผ๋กœ ์—ฐ๊ฒฐ๋œ ํ•˜๋‚˜์˜ ํ†ตํ•ฉ๋œ ์ฃผ์ œ
2150
+ 2. ๊ตฌ์ฒด์ ์ด๊ณ  ๋…์ฐฝ์ ์ธ ์„ค์ •
2151
+ 3. ๋ช…ํ™•ํ•œ ๊ฐˆ๋“ฑ๊ณผ ๊ธด์žฅ๊ฐ
2152
+ 4. ํ˜„๋Œ€์  ๊ด€๋ จ์„ฑ
2153
+ 5. ๋ฌธํ•™์  ๊นŠ์ด
2154
+
2155
+ ๋‹ค์Œ ํ˜•์‹์œผ๋กœ ์ž‘์„ฑํ•˜์„ธ์š”:
2156
+ - ์ œ๋ชฉ: [๋งค๋ ฅ์ ์ด๊ณ  ์•”์‹œ์ ์ธ ์ œ๋ชฉ]
2157
+ - ์ฒซ ๋ฌธ์žฅ: [๋…์ž๋ฅผ ์ฆ‰์‹œ ์‚ฌ๋กœ์žก๋Š” ๊ฐ•๋ ฌํ•œ ์ฒซ ๋ฌธ์žฅ]
2158
+ - ์ฃผ์ธ๊ณต: [๊ตฌ์ฒด์ ์ธ ์ƒํ™ฉ๊ณผ ํŠน์„ฑ์„ ๊ฐ€์ง„ ์ธ๋ฌผ]
2159
+ - ์ค‘์‹ฌ ๊ฐˆ๋“ฑ: [๋‚ด์  ๊ฐˆ๋“ฑ๊ณผ ์™ธ์  ๊ฐˆ๋“ฑ์˜ ๊ฒฐํ•ฉ]
2160
+ - ํƒ๊ตฌ ์ฃผ์ œ: [์ฒ ํ•™์  ๊นŠ์ด๋ฅผ ๊ฐ€์ง„ ํ•ต์‹ฌ ์งˆ๋ฌธ]"""
2161
+ else:
2162
+ prompt = f"""Generate a natural and compelling novel theme using these elements:
2163
+
2164
+ Theme: {theme}
2165
+ Character: {character}
2166
+ Event: {hook}
2167
+ Philosophical Question: {question}
2168
+
2169
+ Requirements:
2170
+ 1. All elements organically connected into one unified theme
2171
+ 2. Specific and original setting
2172
+ 3. Clear conflict and tension
2173
+ 4. Contemporary relevance
2174
+ 5. Literary depth
2175
+
2176
+ Format as:
2177
+ - Title: [Compelling and evocative title]
2178
+ - Opening: [Powerful first sentence that immediately hooks readers]
2179
+ - Protagonist: [Character with specific situation and traits]
2180
+ - Central Conflict: [Combination of internal and external conflict]
2181
+ - Core Exploration: [Philosophically deep central question]"""
2182
+
2183
+ # Use the UnifiedLiterarySystem's LLM to generate coherent theme
2184
+ system = UnifiedLiterarySystem()
2185
+
2186
+ # Call LLM synchronously for theme generation
2187
+ messages = [{"role": "user", "content": prompt}]
2188
+ generated_theme = system.call_llm_sync(messages, "director", language)
2189
+
2190
+ # Add narrative structure (simplified and natural)
2191
+ if language == "Korean":
2192
+ generated_theme += f"""
2193
 
2194
+ **์„œ์‚ฌ ๊ตฌ์กฐ:**
2195
+ ์ด ์ด์•ผ๊ธฐ๋Š” {character}๊ฐ€ {hook.lower()}๋Š” ์ถฉ๊ฒฉ์  ์‚ฌ๊ฑด์œผ๋กœ ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค.
2196
+ ์ ์ฐจ ์‹ฌํ™”๋˜๋Š” ๊ฐˆ๋“ฑ์„ ํ†ตํ•ด {question.lower().rstrip('?')}๋ผ๋Š” ๊ทผ๋ณธ์  ์งˆ๋ฌธ๊ณผ ๋Œ€๋ฉดํ•˜๊ฒŒ ๋˜๋ฉฐ,
2197
+ ๊ถ๊ทน์ ์œผ๋กœ {theme.replace('_', ' ')}์˜ ์‹œ๋Œ€๋ฅผ ์‚ด์•„๊ฐ€๋Š” ํ˜„๋Œ€์ธ์˜ ์‹ค์กด์  ์„ ํƒ์„ ๊ทธ๋ฆฝ๋‹ˆ๋‹ค.
2198
 
2199
+ **ํ†ค๊ณผ ์Šคํƒ€์ผ:**
2200
+ ํ˜„๋Œ€ ๋ฌธํ•™์˜ ๏ฟฝ๏ฟฝ๏ฟฝ๋ฆฌ์  ๊นŠ์ด์™€ ์ฒ ํ•™์  ํ†ต์ฐฐ์„ ๊ฒฐํ•ฉํ•˜์—ฌ, ๋…์ž๋กœ ํ•˜์—ฌ๊ธˆ
2201
+ ์ž์‹ ์˜ ์‚ถ์„ ๋Œ์•„๋ณด๊ฒŒ ๋งŒ๋“œ๋Š” ์„ฑ์ฐฐ์  ์„œ์‚ฌ๋ฅผ ์ง€ํ–ฅํ•ฉ๋‹ˆ๋‹ค."""
2202
+ else:
2203
+ generated_theme += f"""
2204
 
2205
+ **Narrative Arc:**
2206
+ The story begins with {character} who {hook}, a shocking event that sets everything in motion.
2207
+ Through deepening conflicts, they confront the fundamental question of {question.lower()}
2208
+ ultimately portraying the existential choices of modern humans living in an era of {theme.replace('_', ' ')}.
2209
 
2210
+ **Tone and Style:**
2211
+ Combining the psychological depth and philosophical insights of contemporary literature,
2212
+ aiming for a reflective narrative that makes readers examine their own lives."""
2213
+
2214
+ return generated_theme
2215
+
2216
+ except Exception as e:
2217
+ logger.error(f"Theme generation error: {str(e)}")
2218
+ # Fallback to simple pre-defined themes
2219
+ fallback_themes = {
2220
+ "Korean": [
2221
+ """**์ œ๋ชฉ:** ๋งˆ์ง€๋ง‰ ์•„๋‚ ๋กœ๊ทธ ์ธ๊ฐ„
2222
 
2223
+ **์ฒซ ๋ฌธ์žฅ:** "๋‚ด๊ฐ€ ๋งˆ์ง€๋ง‰์œผ๋กœ ์ข…์ด์— ๊ธ€์„ ์“ด ์‚ฌ๋žŒ์ด ๋œ ๋‚ , ์„ธ์ƒ์€ ์นจ๋ฌตํ–ˆ๋‹ค."
2224
 
2225
+ **์ฃผ์ธ๊ณต:** ๋””์ง€ํ„ธํ™”๋ฅผ ๊ฑฐ๋ถ€ํ•˜๊ณ  ์ˆ˜๊ธฐ๋กœ๋งŒ ์†Œํ†ตํ•˜๋Š” ๋…ธ๋…„์˜ ์ž‘๊ฐ€
2226
 
2227
+ **์ค‘์‹ฌ ๊ฐˆ๋“ฑ:** ํšจ์œจ์„ฑ๊ณผ ์ธ๊ฐ„์„ฑ ์‚ฌ์ด์—์„œ ์„ ํƒํ•ด์•ผ ํ•˜๋Š” ์‹ค์กด์  ๋”œ๋ ˆ๋งˆ
2228
+
2229
+ **ํƒ๊ตฌ ์ฃผ์ œ:** ๊ธฐ์ˆ  ๋ฐœ์ „ ์†์—์„œ ์ธ๊ฐ„ ๊ณ ์œ ์˜ ๊ฐ€์น˜๋Š” ๋ฌด์—‡์ธ๊ฐ€?""",
2230
+
2231
+ """**์ œ๋ชฉ:** ๊ธฐ์–ต ๊ฑฐ๋ž˜์†Œ
2232
 
2233
+ **์ฒซ ๋ฌธ์žฅ:** "์˜ค๋Š˜ ์•„์นจ, ๋‚˜๋Š” ์ฒซ์‚ฌ๋ž‘์˜ ๊ธฐ์–ต์„ ํŒ”๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ๋‹ค."
2234
 
2235
+ **์ฃผ์ธ๊ณต:** ์ƒ๊ณ„๋ฅผ ์œ„ํ•ด ์†Œ์ค‘ํ•œ ๊ธฐ์–ต์„ ํŒŒ๋Š” ์ Š์€ ์˜ˆ์ˆ ๊ฐ€
2236
 
2237
+ **์ค‘์‹ฌ ๊ฐˆ๋“ฑ:** ์ƒ์กด๊ณผ ์ •์ฒด์„ฑ ๋ณด์กด ์‚ฌ์ด์˜ ์„ ํƒ
2238
 
2239
+ **ํƒ๊ตฌ ์ฃผ์ œ:** ๊ธฐ์–ต์ด ๊ฑฐ๋ž˜๋˜๋Š” ์‹œ๋Œ€, ์šฐ๋ฆฌ๋Š” ๋ฌด์—‡์œผ๋กœ ์ž์‹ ์„ ์ •์˜ํ•˜๋Š”๊ฐ€?"""
2240
+ ],
2241
+ "English": [
2242
+ """**Title:** The Last Analog Human
 
 
2243
 
2244
+ **Opening:** "The day I became the last person to write on paper, the world fell silent."
2245
+
2246
+ **Protagonist:** An elderly writer who refuses digitalization and communicates only through handwriting
2247
+
2248
+ **Central Conflict:** Existential dilemma between efficiency and humanity
2249
+
2250
+ **Core Exploration:** What is uniquely human in the age of technological advancement?""",
2251
+
2252
+ """**Title:** The Memory Exchange
2253
 
2254
+ **Opening:** "This morning, I decided to sell my first love's memory."
2255
 
2256
+ **Protagonist:** A young artist selling precious memories for survival
2257
+
2258
+ **Central Conflict:** Choice between survival and preserving identity
2259
+
2260
+ **Core Exploration:** In an era where memories are traded, what defines who we are?"""
2261
+ ]
2262
+ }
2263
 
2264
+ import secrets
2265
+ return secrets.choice(fallback_themes.get(language, fallback_themes["English"]))
2266
+
2267
+ # Update the handle_random_theme function in create_interface
2268
+ def handle_random_theme(language):
2269
+ """Handle random theme generation with improved feedback"""
2270
+ try:
2271
+ # Generate theme using LLM for natural output
2272
+ theme = generate_random_theme(language)
2273
+ logger.info(f"Generated theme successfully")
2274
+ return theme
2275
  except Exception as e:
2276
+ logger.error(f"Random theme generation failed: {str(e)}")
2277
+ # Return a simple fallback theme
2278
+ if language == "Korean":
2279
+ return "๊ธฐ์–ต์„ ์žƒ์–ด๊ฐ€๋Š” ๋…ธ์ธ๊ณผ AI ๊ฐ„๋ณ‘์ธ์˜ ํŠน๋ณ„ํ•œ ์šฐ์ •"
2280
+ else:
2281
+ return "An unlikely friendship between an elderly person losing memories and their AI caregiver"
2282
+
2283
+ # Update the augment_query method to better handle generated themes
2284
+ def augment_query(self, user_query: str, language: str) -> str:
2285
+ """Augment and clean user query"""
2286
+ # Remove any formatting artifacts from random generation
2287
+ if "**" in user_query or "##" in user_query:
2288
+ # This is likely a generated theme with formatting
2289
+ # Extract the essence without formatting
2290
+ lines = user_query.split('\n')
2291
+ cleaned_parts = []
2292
 
2293
+ for line in lines:
2294
+ # Remove markdown formatting
2295
+ line = line.replace('**', '').replace('##', '').strip()
2296
+ if line and not line.startswith(('-', 'โ€ข', '*')) and ':' not in line[:20]:
2297
+ cleaned_parts.append(line)
2298
 
2299
+ if cleaned_parts:
2300
+ user_query = ' '.join(cleaned_parts[:3]) # Use first few meaningful lines
2301
+
2302
+ # If query is too short, enhance it
2303
+ if len(user_query.split()) < 15:
2304
  if language == "Korean":
2305
+ return f"{user_query}\n\n์ด ์ฃผ์ œ๋ฅผ ํ˜„๋Œ€์  ๊ด€์ ์—์„œ ์žฌํ•ด์„ํ•˜์—ฌ ์ธ๊ฐ„ ์กด์žฌ์˜ ๋ณธ์งˆ๊ณผ ๊ธฐ์ˆ  ์‹œ๋Œ€์˜ ๋”œ๋ ˆ๋งˆ๋ฅผ ํƒ๊ตฌํ•˜๋Š” 8,000๋‹จ์–ด ๋ถ„๋Ÿ‰์˜ ์ฒ ํ•™์  ์ค‘ํŽธ์†Œ์„ค์„ ์ž‘์„ฑํ•˜์„ธ์š”."
 
 
2306
  else:
2307
+ return f"{user_query}\n\nReinterpret this theme from a contemporary perspective to explore the essence of human existence and dilemmas of the technological age in an 8,000-word philosophical novella."
2308
+
2309
+ return user_query
2310
+
2311
+ # Add method to UnifiedLiterarySystem class for better theme processing
2312
+ def process_generated_theme(self, theme_text: str, language: str) -> str:
2313
+ """Process generated theme for novel writing"""
2314
+ # Extract key elements from generated theme
2315
+ theme_elements = {
2316
+ "title": "",
2317
+ "opening": "",
2318
+ "protagonist": "",
2319
+ "conflict": "",
2320
+ "exploration": ""
2321
+ }
2322
+
2323
+ lines = theme_text.split('\n')
2324
+ current_key = None
2325
+
2326
+ for line in lines:
2327
+ line = line.strip()
2328
+ if not line:
2329
+ continue
2330
+
2331
+ # Detect sections
2332
+ if any(marker in line.lower() for marker in ['title:', 'opening:', 'protagonist:', 'conflict:', 'exploration:', '์ œ๋ชฉ:', '์ฒซ ๋ฌธ์žฅ:', '์ฃผ์ธ๊ณต:', '๊ฐˆ๋“ฑ:', 'ํƒ๊ตฌ']):
2333
+ for key in theme_elements:
2334
+ if key in line.lower() or (language == "Korean" and key in translate_to_korean(line.lower())):
2335
+ current_key = key
2336
+ # Extract content after colon
2337
+ if ':' in line:
2338
+ content = line.split(':', 1)[1].strip()
2339
+ if content:
2340
+ theme_elements[current_key] = content
2341
+ break
2342
+ elif current_key and line:
2343
+ # Continue adding to current element
2344
+ theme_elements[current_key] = (theme_elements[current_key] + " " + line).strip()
2345
+
2346
+ # Construct a coherent theme summary
2347
+ if language == "Korean":
2348
+ summary = f"{theme_elements.get('title', '๋ฌด์ œ')}. "
2349
+ if theme_elements.get('opening'):
2350
+ summary += f"'{theme_elements['opening']}' "
2351
+ summary += f"{theme_elements.get('protagonist', '์ฃผ์ธ๊ณต')}์˜ ์ด์•ผ๊ธฐ. "
2352
+ summary += f"{theme_elements.get('conflict', '')} "
2353
+ summary += f"{theme_elements.get('exploration', '')}"
2354
+ else:
2355
+ summary = f"{theme_elements.get('title', 'Untitled')}. "
2356
+ if theme_elements.get('opening'):
2357
+ summary += f"'{theme_elements['opening']}' "
2358
+ summary += f"The story of {theme_elements.get('protagonist', 'a protagonist')}. "
2359
+ summary += f"{theme_elements.get('conflict', '')} "
2360
+ summary += f"{theme_elements.get('exploration', '')}"
2361
+
2362
+ return summary.strip()
2363
 
2364
  # Create Gradio interface
2365
  def create_interface():