Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -1503,7 +1503,15 @@ Provide specific solutions for each issue."""
|
|
1503 |
)
|
1504 |
|
1505 |
if response.status_code != 200:
|
1506 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1507 |
return
|
1508 |
|
1509 |
buffer = ""
|
@@ -1516,32 +1524,49 @@ Provide specific solutions for each issue."""
|
|
1516 |
if not line_str.startswith("data: "):
|
1517 |
continue
|
1518 |
|
1519 |
-
data_str = line_str[6:]
|
1520 |
if data_str == "[DONE]":
|
1521 |
break
|
1522 |
|
1523 |
-
|
1524 |
-
|
1525 |
-
|
1526 |
-
|
1527 |
-
|
1528 |
-
|
1529 |
-
|
1530 |
-
|
1531 |
-
|
1532 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1533 |
|
1534 |
except Exception as e:
|
1535 |
-
logger.error(f"Chunk processing error: {str(e)}")
|
1536 |
continue
|
1537 |
|
|
|
1538 |
if buffer:
|
1539 |
yield buffer
|
1540 |
|
|
|
|
|
|
|
1541 |
except Exception as e:
|
1542 |
logger.error(f"Streaming error: {type(e).__name__}: {str(e)}")
|
1543 |
yield f"โ Error occurred: {str(e)}"
|
1544 |
|
|
|
|
|
1545 |
def get_system_prompts(self, language: str) -> Dict[str, str]:
|
1546 |
"""Role-specific system prompts"""
|
1547 |
|
@@ -1903,22 +1928,29 @@ You provide feedback that's critical yet encouraging."""
|
|
1903 |
|
1904 |
# --- Utility functions ---
|
1905 |
def generate_random_screenplay_theme(screenplay_type: str, genre: str, language: str) -> str:
|
1906 |
-
|
1907 |
-
|
1908 |
-
|
1909 |
-
|
1910 |
-
|
1911 |
-
|
1912 |
-
|
1913 |
-
|
1914 |
-
|
1915 |
-
|
1916 |
-
|
1917 |
-
|
1918 |
-
|
1919 |
-
|
1920 |
-
|
1921 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1922 |
|
1923 |
์ํฉ: {situation}
|
1924 |
์ฃผ์ธ๊ณต: {protagonist}
|
@@ -1934,8 +1966,8 @@ def generate_random_screenplay_theme(screenplay_type: str, genre: str, language:
|
|
1934 |
**์ปจ์
:** [์ฃผ์ธ๊ณต]์ด(๊ฐ) [์ํฉ]์์ [๊ฐ๋ฑ]์ ๊ฒช์ผ๋ฉฐ [๋ชฉํ]๋ฅผ ์ถ๊ตฌํ๋ ์ด์ผ๊ธฐ.
|
1935 |
|
1936 |
**๋
ํนํ ์์:** [์ด ์ด์ผ๊ธฐ๋ง์ ํน๋ณํ ์ ]"""
|
1937 |
-
|
1938 |
-
|
1939 |
|
1940 |
Situation: {situation}
|
1941 |
Protagonist: {protagonist}
|
@@ -1952,28 +1984,61 @@ Format as:
|
|
1952 |
|
1953 |
**Unique Element:** [What makes this story special]"""
|
1954 |
|
1955 |
-
|
1956 |
-
|
1957 |
-
|
1958 |
-
|
1959 |
-
|
1960 |
-
|
1961 |
-
|
1962 |
-
|
1963 |
-
|
1964 |
-
|
1965 |
-
|
1966 |
-
|
1967 |
-
|
1968 |
-
|
1969 |
-
|
1970 |
-
|
1971 |
-
|
1972 |
-
|
1973 |
-
|
1974 |
-
|
1975 |
-
|
1976 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1977 |
|
1978 |
def load_screenplay_themes_data() -> Dict:
|
1979 |
"""Load screenplay themes data"""
|
|
|
1503 |
)
|
1504 |
|
1505 |
if response.status_code != 200:
|
1506 |
+
error_msg = f"API Error (Status Code: {response.status_code})"
|
1507 |
+
try:
|
1508 |
+
error_data = response.json()
|
1509 |
+
if isinstance(error_data, dict) and 'error' in error_data:
|
1510 |
+
error_msg += f" - {error_data['error']}"
|
1511 |
+
except:
|
1512 |
+
error_msg += f" - {response.text}"
|
1513 |
+
logger.error(error_msg)
|
1514 |
+
yield f"โ {error_msg}"
|
1515 |
return
|
1516 |
|
1517 |
buffer = ""
|
|
|
1524 |
if not line_str.startswith("data: "):
|
1525 |
continue
|
1526 |
|
1527 |
+
data_str = line_str[6:] # Remove "data: " prefix
|
1528 |
if data_str == "[DONE]":
|
1529 |
break
|
1530 |
|
1531 |
+
# Parse JSON data
|
1532 |
+
try:
|
1533 |
+
data = json.loads(data_str)
|
1534 |
+
except json.JSONDecodeError as e:
|
1535 |
+
logger.warning(f"JSON decode error: {e}, data: {data_str}")
|
1536 |
+
continue
|
1537 |
+
|
1538 |
+
# Safely check for content
|
1539 |
+
if data and isinstance(data, dict):
|
1540 |
+
choices = data.get("choices", [])
|
1541 |
+
if choices and len(choices) > 0:
|
1542 |
+
delta = choices[0].get("delta", {})
|
1543 |
+
if delta and isinstance(delta, dict):
|
1544 |
+
content = delta.get("content", "")
|
1545 |
+
if content:
|
1546 |
+
buffer += content
|
1547 |
+
|
1548 |
+
if len(buffer) >= 50 or '\n' in buffer:
|
1549 |
+
yield buffer
|
1550 |
+
buffer = ""
|
1551 |
+
time.sleep(0.01)
|
1552 |
|
1553 |
except Exception as e:
|
1554 |
+
logger.error(f"Chunk processing error: {str(e)}, line: {line_str[:100]}")
|
1555 |
continue
|
1556 |
|
1557 |
+
# Yield any remaining buffer content
|
1558 |
if buffer:
|
1559 |
yield buffer
|
1560 |
|
1561 |
+
except requests.exceptions.RequestException as e:
|
1562 |
+
logger.error(f"Request error: {type(e).__name__}: {str(e)}")
|
1563 |
+
yield f"โ Network error: {str(e)}"
|
1564 |
except Exception as e:
|
1565 |
logger.error(f"Streaming error: {type(e).__name__}: {str(e)}")
|
1566 |
yield f"โ Error occurred: {str(e)}"
|
1567 |
|
1568 |
+
|
1569 |
+
|
1570 |
def get_system_prompts(self, language: str) -> Dict[str, str]:
|
1571 |
"""Role-specific system prompts"""
|
1572 |
|
|
|
1928 |
|
1929 |
# --- Utility functions ---
|
1930 |
def generate_random_screenplay_theme(screenplay_type: str, genre: str, language: str) -> str:
|
1931 |
+
"""Generate random screenplay theme"""
|
1932 |
+
try:
|
1933 |
+
# Load themes data
|
1934 |
+
themes_data = load_screenplay_themes_data()
|
1935 |
+
|
1936 |
+
# Select random elements
|
1937 |
+
import secrets
|
1938 |
+
situations = themes_data['situations'].get(genre, themes_data['situations']['drama'])
|
1939 |
+
protagonists = themes_data['protagonists'].get(genre, themes_data['protagonists']['drama'])
|
1940 |
+
conflicts = themes_data['conflicts'].get(genre, themes_data['conflicts']['drama'])
|
1941 |
+
|
1942 |
+
if not situations or not protagonists or not conflicts:
|
1943 |
+
return f"Error: No theme data available for genre {genre}"
|
1944 |
+
|
1945 |
+
situation = secrets.choice(situations)
|
1946 |
+
protagonist = secrets.choice(protagonists)
|
1947 |
+
conflict = secrets.choice(conflicts)
|
1948 |
+
|
1949 |
+
# Generate theme using LLM
|
1950 |
+
system = ScreenplayGenerationSystem()
|
1951 |
+
|
1952 |
+
if language == "Korean":
|
1953 |
+
prompt = f"""๋ค์ ์์๋ค๋ก {screenplay_type}์ฉ ๋งค๋ ฅ์ ์ธ ์ปจ์
์ ์์ฑํ์ธ์:
|
1954 |
|
1955 |
์ํฉ: {situation}
|
1956 |
์ฃผ์ธ๊ณต: {protagonist}
|
|
|
1966 |
**์ปจ์
:** [์ฃผ์ธ๊ณต]์ด(๊ฐ) [์ํฉ]์์ [๊ฐ๋ฑ]์ ๊ฒช์ผ๋ฉฐ [๋ชฉํ]๋ฅผ ์ถ๊ตฌํ๋ ์ด์ผ๊ธฐ.
|
1967 |
|
1968 |
**๋
ํนํ ์์:** [์ด ์ด์ผ๊ธฐ๋ง์ ํน๋ณํ ์ ]"""
|
1969 |
+
else:
|
1970 |
+
prompt = f"""Generate an attractive concept for {screenplay_type} using these elements:
|
1971 |
|
1972 |
Situation: {situation}
|
1973 |
Protagonist: {protagonist}
|
|
|
1984 |
|
1985 |
**Unique Element:** [What makes this story special]"""
|
1986 |
|
1987 |
+
messages = [{"role": "user", "content": prompt}]
|
1988 |
+
|
1989 |
+
# Call LLM with error handling
|
1990 |
+
try:
|
1991 |
+
generated_theme = system.call_llm_sync(messages, "producer", language)
|
1992 |
+
|
1993 |
+
# Check if we got an error response
|
1994 |
+
if generated_theme.startswith("โ"):
|
1995 |
+
logger.error(f"LLM error: {generated_theme}")
|
1996 |
+
# Return a fallback theme
|
1997 |
+
return get_fallback_theme(screenplay_type, genre, language, situation, protagonist, conflict)
|
1998 |
+
|
1999 |
+
# Extract metadata
|
2000 |
+
metadata = {
|
2001 |
+
'title': extract_title_from_theme(generated_theme),
|
2002 |
+
'logline': extract_logline_from_theme(generated_theme),
|
2003 |
+
'protagonist': protagonist,
|
2004 |
+
'conflict': conflict,
|
2005 |
+
'tags': [genre, screenplay_type]
|
2006 |
+
}
|
2007 |
+
|
2008 |
+
# Save to database
|
2009 |
+
theme_id = ScreenplayDatabase.save_random_theme(
|
2010 |
+
generated_theme, screenplay_type, genre, language, metadata
|
2011 |
+
)
|
2012 |
+
|
2013 |
+
return generated_theme
|
2014 |
+
|
2015 |
+
except Exception as e:
|
2016 |
+
logger.error(f"LLM call failed: {e}")
|
2017 |
+
return get_fallback_theme(screenplay_type, genre, language, situation, protagonist, conflict)
|
2018 |
+
|
2019 |
+
except Exception as e:
|
2020 |
+
logger.error(f"Theme generation error: {str(e)}")
|
2021 |
+
return f"Error generating theme: {str(e)}"
|
2022 |
+
|
2023 |
+
def get_fallback_theme(screenplay_type: str, genre: str, language: str,
|
2024 |
+
situation: str, protagonist: str, conflict: str) -> str:
|
2025 |
+
"""Generate fallback theme without LLM"""
|
2026 |
+
if language == "Korean":
|
2027 |
+
return f"""**์ ๋ชฉ:** {protagonist}์ ์ ํ
|
2028 |
+
|
2029 |
+
**๋ก๊ทธ๋ผ์ธ:** {situation}์ ๊ฐํ {protagonist}๊ฐ {conflict}์ ๋ง์๋ฉฐ ์์กด์ ์ํด ์ธ์ด๋ค.
|
2030 |
+
|
2031 |
+
**์ปจ์
:** {protagonist}๊ฐ {situation}์์ {conflict}์ ๊ฒช์ผ๋ฉฐ ์์ ์ ํ๊ณ๋ฅผ ๊ทน๋ณตํ๋ ์ด์ผ๊ธฐ.
|
2032 |
+
|
2033 |
+
**๋
ํนํ ์์:** {genre} ์ฅ๋ฅด์ ์ ํต์ ์์๋ฅผ ํ๋์ ์ผ๋ก ์ฌํด์ํ ์ํ."""
|
2034 |
+
else:
|
2035 |
+
return f"""**Title:** The {protagonist.title()}'s Choice
|
2036 |
+
|
2037 |
+
**Logline:** When trapped in {situation}, a {protagonist} must face {conflict} to survive.
|
2038 |
+
|
2039 |
+
**Concept:** A story about a {protagonist} who faces {conflict} in {situation} while discovering their true strength.
|
2040 |
+
|
2041 |
+
**Unique Element:** A fresh take on {genre} genre conventions with contemporary relevance."""
|
2042 |
|
2043 |
def load_screenplay_themes_data() -> Dict:
|
2044 |
"""Load screenplay themes data"""
|