Update app.py
Browse files
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
|
| 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 |
-
|
| 2111 |
-
"
|
| 2112 |
-
"
|
| 2113 |
-
"
|
| 2114 |
-
"
|
| 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 |
-
|
| 2169 |
-
|
| 2170 |
-
|
| 2171 |
-
|
| 2172 |
-
|
| 2173 |
-
|
| 2174 |
-
|
| 2175 |
-
|
| 2176 |
-
|
| 2177 |
-
|
| 2178 |
-
|
| 2179 |
-
|
| 2180 |
-
|
| 2181 |
-
|
| 2182 |
-
|
| 2183 |
-
|
| 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 |
-
|
| 2209 |
-
|
| 2210 |
-
|
| 2211 |
-
|
| 2212 |
-
|
| 2213 |
-
|
| 2214 |
-
|
| 2215 |
-
|
| 2216 |
-
|
| 2217 |
-
|
| 2218 |
-
|
| 2219 |
-
|
| 2220 |
-
|
| 2221 |
-
|
| 2222 |
-
|
| 2223 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2224 |
|
| 2225 |
-
|
|
|
|
|
|
|
|
|
|
| 2226 |
|
| 2227 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2228 |
|
| 2229 |
-
|
|
|
|
|
|
|
|
|
|
| 2230 |
|
| 2231 |
-
|
| 2232 |
-
|
| 2233 |
-
|
| 2234 |
-
|
| 2235 |
-
|
| 2236 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2237 |
|
| 2238 |
-
|
| 2239 |
|
| 2240 |
-
|
| 2241 |
|
| 2242 |
-
|
| 2243 |
-
|
| 2244 |
-
|
| 2245 |
-
|
|
|
|
| 2246 |
|
| 2247 |
-
|
| 2248 |
|
| 2249 |
-
|
| 2250 |
|
| 2251 |
-
|
| 2252 |
|
| 2253 |
-
|
| 2254 |
-
|
| 2255 |
-
|
| 2256 |
-
|
| 2257 |
-
- Parts 7-8: Confronting ultimate choice
|
| 2258 |
-
- Parts 9-10: Transformation of self and world
|
| 2259 |
|
| 2260 |
-
**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2261 |
|
| 2262 |
-
**
|
| 2263 |
|
| 2264 |
-
**
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2265 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2266 |
except Exception as e:
|
| 2267 |
-
|
| 2268 |
-
#
|
| 2269 |
-
|
| 2270 |
-
|
| 2271 |
-
|
| 2272 |
-
|
| 2273 |
-
|
| 2274 |
-
|
| 2275 |
-
|
| 2276 |
-
|
| 2277 |
-
|
| 2278 |
-
|
| 2279 |
-
|
| 2280 |
-
|
| 2281 |
-
|
| 2282 |
-
]
|
| 2283 |
|
| 2284 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2285 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2286 |
if language == "Korean":
|
| 2287 |
-
return f"
|
| 2288 |
-
**์ฒซ ๋ฌธ์ฅ:** "์ค๋๋ ๋๋ ๋จ๋ค์ด ๋ฒ๋ฆฐ ๊ฒ์ ์ฃผ์ ๋ค."
|
| 2289 |
-
**์ค์ฌ ๊ฐ๋ฑ:** ์ธ๊ฐ์ ๋ณธ์ง์ ๊ฐ์น๊ฐ ๊ฑฐ๋๋๋ ์ธ๊ณ์์์ ์์กด"""
|
| 2290 |
else:
|
| 2291 |
-
return f"
|
| 2292 |
-
|
| 2293 |
-
|
| 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():
|