Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -2872,31 +2872,32 @@ if __name__ == "__main__":
|
|
2872 |
return value.strip() if value else None
|
2873 |
return None
|
2874 |
|
|
|
2875 |
from typing import List
|
2876 |
|
2877 |
def _parse_character_profile(self, content: str, role: str) -> CharacterProfile:
|
2878 |
-
"""Parse character profile from content and return CharacterProfile
|
2879 |
# --- 1. ๋ก๊ทธ ---
|
2880 |
logger.debug(f"Parsing character profile for role: {role}")
|
2881 |
logger.debug(f"Content preview: {content[:200]}...")
|
2882 |
-
|
2883 |
# --- 2. ์ด๋ฆ ์ถ์ถ ---
|
2884 |
-
name = f"Character_{role}"
|
2885 |
name_patterns = [
|
2886 |
-
r'(?:์ด๋ฆ|Name)[:\s]*([^\n,(]+)',
|
2887 |
-
r'^\s*[-*โข]\s*([^\n,(]+)',
|
2888 |
-
r'^([^\n,(]+)'
|
2889 |
]
|
2890 |
for pat in name_patterns:
|
2891 |
m = re.search(pat, content, re.IGNORECASE | re.MULTILINE)
|
2892 |
if m and m.group(1).strip():
|
2893 |
extracted = m.group(1).strip()
|
2894 |
-
#
|
2895 |
extracted = re.sub(r'[\*:\s]+', '', extracted)
|
2896 |
if len(extracted) > 1:
|
2897 |
name = extracted
|
2898 |
break
|
2899 |
-
|
2900 |
# --- 3. ํ๋ ์ถ์ถ ํฌํผ ---
|
2901 |
def extract_clean_field(patterns) -> str:
|
2902 |
patterns = [patterns] if isinstance(patterns, str) else patterns
|
@@ -2910,8 +2911,8 @@ from typing import List
|
|
2910 |
val = re.sub(r'\s+', ' ', val)
|
2911 |
return val
|
2912 |
return ""
|
2913 |
-
|
2914 |
-
#
|
2915 |
profile = CharacterProfile(
|
2916 |
name=name,
|
2917 |
role=role,
|
@@ -2953,37 +2954,144 @@ from typing import List
|
|
2953 |
r"๋ณํ"
|
2954 |
])
|
2955 |
)
|
2956 |
-
|
2957 |
logger.debug(f"Parsed character: {profile.name}")
|
2958 |
return profile
|
2959 |
|
2960 |
def _extract_personality_traits(self, content: str) -> List[str]:
|
2961 |
-
"""Extract personality traits from content"""
|
2962 |
-
traits = []
|
2963 |
-
# Look for personality section with multiple pattern options
|
2964 |
personality_patterns = [
|
2965 |
r"(?:Personality|์ฑ๊ฒฉ ํน์ฑ|์ฑ๊ฒฉ)[:\s]*([^\n]+(?:\n(?![\w๊ฐ-ํฃ]+:)[^\n]+)*)",
|
2966 |
r"์ฑ๊ฒฉ[:\s]*(?:\n?[-โข*]\s*[^\n]+)+"
|
2967 |
]
|
2968 |
-
|
2969 |
for pattern in personality_patterns:
|
2970 |
match = re.search(pattern, content, re.IGNORECASE | re.DOTALL)
|
2971 |
if match and match.group(1):
|
2972 |
-
|
2973 |
-
|
2974 |
-
trait_lines = personality_section.split('\n')
|
2975 |
-
for line in trait_lines:
|
2976 |
line = line.strip()
|
2977 |
if line and not line.endswith(':'):
|
2978 |
-
#
|
2979 |
-
trait = re.sub(r'^\s*
|
2980 |
-
|
2981 |
-
if trait and len(trait) > 2: # Skip very short entries
|
2982 |
traits.append(trait)
|
2983 |
-
if traits:
|
2984 |
break
|
|
|
|
|
2985 |
|
2986 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2987 |
|
2988 |
def _process_character_content(self, content: str):
|
2989 |
"""Process character designer output with better error handling"""
|
|
|
2872 |
return value.strip() if value else None
|
2873 |
return None
|
2874 |
|
2875 |
+
import re
|
2876 |
from typing import List
|
2877 |
|
2878 |
def _parse_character_profile(self, content: str, role: str) -> CharacterProfile:
|
2879 |
+
"""Parse character profile from content and return a CharacterProfile object."""
|
2880 |
# --- 1. ๋ก๊ทธ ---
|
2881 |
logger.debug(f"Parsing character profile for role: {role}")
|
2882 |
logger.debug(f"Content preview: {content[:200]}...")
|
2883 |
+
|
2884 |
# --- 2. ์ด๋ฆ ์ถ์ถ ---
|
2885 |
+
name = f"Character_{role}" # fallback
|
2886 |
name_patterns = [
|
2887 |
+
r'(?:์ด๋ฆ|Name)[:\s]*([^\n,(]+)', # ์: "์ด๋ฆ: ํ๊ธธ๋"
|
2888 |
+
r'^\s*[-*โข]\s*([^\n,(]+)', # ์: "- ํ๊ธธ๋"
|
2889 |
+
r'^([^\n,(]+)' # ๋ฌธ๋จ ์ฒซ ๋จ์ด
|
2890 |
]
|
2891 |
for pat in name_patterns:
|
2892 |
m = re.search(pat, content, re.IGNORECASE | re.MULTILINE)
|
2893 |
if m and m.group(1).strip():
|
2894 |
extracted = m.group(1).strip()
|
2895 |
+
# ๋งํฌ๋ค์ดยทํน์ ๊ธฐํธ ์ ๊ฑฐ
|
2896 |
extracted = re.sub(r'[\*:\s]+', '', extracted)
|
2897 |
if len(extracted) > 1:
|
2898 |
name = extracted
|
2899 |
break
|
2900 |
+
|
2901 |
# --- 3. ํ๋ ์ถ์ถ ํฌํผ ---
|
2902 |
def extract_clean_field(patterns) -> str:
|
2903 |
patterns = [patterns] if isinstance(patterns, str) else patterns
|
|
|
2911 |
val = re.sub(r'\s+', ' ', val)
|
2912 |
return val
|
2913 |
return ""
|
2914 |
+
|
2915 |
+
# --- 4. Personality(์ฌ๋ฌ ์ค) ์ถ์ถ์ ๋ณ๋ ๋ฉ์๋ ์ฌ์ฉ ---
|
2916 |
profile = CharacterProfile(
|
2917 |
name=name,
|
2918 |
role=role,
|
|
|
2954 |
r"๋ณํ"
|
2955 |
])
|
2956 |
)
|
2957 |
+
|
2958 |
logger.debug(f"Parsed character: {profile.name}")
|
2959 |
return profile
|
2960 |
|
2961 |
def _extract_personality_traits(self, content: str) -> List[str]:
|
2962 |
+
"""Extract personality traits from content."""
|
2963 |
+
traits: List[str] = []
|
|
|
2964 |
personality_patterns = [
|
2965 |
r"(?:Personality|์ฑ๊ฒฉ ํน์ฑ|์ฑ๊ฒฉ)[:\s]*([^\n]+(?:\n(?![\w๊ฐ-ํฃ]+:)[^\n]+)*)",
|
2966 |
r"์ฑ๊ฒฉ[:\s]*(?:\n?[-โข*]\s*[^\n]+)+"
|
2967 |
]
|
2968 |
+
|
2969 |
for pattern in personality_patterns:
|
2970 |
match = re.search(pattern, content, re.IGNORECASE | re.DOTALL)
|
2971 |
if match and match.group(1):
|
2972 |
+
section = match.group(1)
|
2973 |
+
for line in section.split('\n'):
|
|
|
|
|
2974 |
line = line.strip()
|
2975 |
if line and not line.endswith(':'):
|
2976 |
+
trait = re.sub(r'^\s*[-โข*]\s*', '', line) # ๊ธ๋จธ๋ฆฌํ ์ ๊ฑฐ
|
2977 |
+
trait = re.sub(r'^\d+\.\s*', '', trait) # ๋ฒํธ ์ ๊ฑฐ
|
2978 |
+
if len(trait) > 2:
|
|
|
2979 |
traits.append(trait)
|
2980 |
+
if traits:
|
2981 |
break
|
2982 |
+
|
2983 |
+
return traits[:5] # ์ต๋ 5๊ฐ
|
2984 |
|
2985 |
+
import re
|
2986 |
+
from typing import List
|
2987 |
+
|
2988 |
+
def _parse_character_profile(self, content: str, role: str) -> CharacterProfile:
|
2989 |
+
"""Parse character profile from content and return a CharacterProfile object."""
|
2990 |
+
# --- 1. ๋ก๊ทธ ---
|
2991 |
+
logger.debug(f"Parsing character profile for role: {role}")
|
2992 |
+
logger.debug(f"Content preview: {content[:200]}...")
|
2993 |
+
|
2994 |
+
# --- 2. ์ด๋ฆ ์ถ์ถ ---
|
2995 |
+
name = f"Character_{role}" # fallback
|
2996 |
+
name_patterns = [
|
2997 |
+
r'(?:์ด๋ฆ|Name)[:\s]*([^\n,(]+)', # ์: "์ด๋ฆ: ํ๊ธธ๋"
|
2998 |
+
r'^\s*[-*โข]\s*([^\n,(]+)', # ์: "- ํ๊ธธ๋"
|
2999 |
+
r'^([^\n,(]+)' # ๋ฌธ๋จ ์ฒซ ๋จ์ด
|
3000 |
+
]
|
3001 |
+
for pat in name_patterns:
|
3002 |
+
m = re.search(pat, content, re.IGNORECASE | re.MULTILINE)
|
3003 |
+
if m and m.group(1).strip():
|
3004 |
+
extracted = m.group(1).strip()
|
3005 |
+
# ๋งํฌ๋ค์ดยทํน์ ๊ธฐํธ ์ ๊ฑฐ
|
3006 |
+
extracted = re.sub(r'[\*:\s]+', '', extracted)
|
3007 |
+
if len(extracted) > 1:
|
3008 |
+
name = extracted
|
3009 |
+
break
|
3010 |
+
|
3011 |
+
# --- 3. ํ๋ ์ถ์ถ ํฌํผ ---
|
3012 |
+
def extract_clean_field(patterns) -> str:
|
3013 |
+
patterns = [patterns] if isinstance(patterns, str) else patterns
|
3014 |
+
for p in patterns:
|
3015 |
+
m = re.search(rf'{p}[:\s]*([^\n*]+?)(?=\n|$)', content,
|
3016 |
+
re.IGNORECASE | re.DOTALL)
|
3017 |
+
if m and m.group(1).strip():
|
3018 |
+
val = m.group(1).strip()
|
3019 |
+
val = re.sub(r'^[-*โข:\s]+', '', val)
|
3020 |
+
val = re.sub(r'\*+', '', val)
|
3021 |
+
val = re.sub(r'\s+', ' ', val)
|
3022 |
+
return val
|
3023 |
+
return ""
|
3024 |
+
|
3025 |
+
# --- 4. Personality(์ฌ๋ฌ ์ค) ์ถ์ถ์ ๋ณ๋ ๋ฉ์๋ ์ฌ์ฉ ---
|
3026 |
+
profile = CharacterProfile(
|
3027 |
+
name=name,
|
3028 |
+
role=role,
|
3029 |
+
archetype=extract_clean_field([
|
3030 |
+
r"์บ๋ฆญํฐ ์ํฌํ์
",
|
3031 |
+
r"Character Archetype",
|
3032 |
+
r"Archetype",
|
3033 |
+
r"์ํฌํ์
"
|
3034 |
+
]),
|
3035 |
+
want=extract_clean_field([
|
3036 |
+
r"WANT\s*\(์ธ์ ๋ชฉํ\)",
|
3037 |
+
r"WANT",
|
3038 |
+
r"์ธ์ ๋ชฉํ",
|
3039 |
+
r"External Goal"
|
3040 |
+
]),
|
3041 |
+
need=extract_clean_field([
|
3042 |
+
r"NEED\s*\(๋ด์ ํ์\)",
|
3043 |
+
r"NEED",
|
3044 |
+
r"๋ด์ ํ์",
|
3045 |
+
r"Internal Need"
|
3046 |
+
]),
|
3047 |
+
backstory=extract_clean_field([
|
3048 |
+
r"๋ฐฑ์คํ ๋ฆฌ",
|
3049 |
+
r"Backstory",
|
3050 |
+
r"ํต์ฌ ์์ฒ",
|
3051 |
+
r"Core Wound"
|
3052 |
+
]),
|
3053 |
+
personality=self._extract_personality_traits(content),
|
3054 |
+
speech_pattern=extract_clean_field([
|
3055 |
+
r"๋งํฌ.*?ํจํด",
|
3056 |
+
r"Speech Pattern",
|
3057 |
+
r"์ธ์ด ํจํด",
|
3058 |
+
r"๋งํฌ"
|
3059 |
+
]),
|
3060 |
+
character_arc=extract_clean_field([
|
3061 |
+
r"์บ๋ฆญํฐ ์ํฌ",
|
3062 |
+
r"Character Arc",
|
3063 |
+
r"Arc",
|
3064 |
+
r"๋ณํ"
|
3065 |
+
])
|
3066 |
+
)
|
3067 |
+
|
3068 |
+
logger.debug(f"Parsed character: {profile.name}")
|
3069 |
+
return profile
|
3070 |
+
|
3071 |
+
def _extract_personality_traits(self, content: str) -> List[str]:
|
3072 |
+
"""Extract personality traits from content."""
|
3073 |
+
traits: List[str] = []
|
3074 |
+
personality_patterns = [
|
3075 |
+
r"(?:Personality|์ฑ๊ฒฉ ํน์ฑ|์ฑ๊ฒฉ)[:\s]*([^\n]+(?:\n(?![\w๊ฐ-ํฃ]+:)[^\n]+)*)",
|
3076 |
+
r"์ฑ๊ฒฉ[:\s]*(?:\n?[-โข*]\s*[^\n]+)+"
|
3077 |
+
]
|
3078 |
+
|
3079 |
+
for pattern in personality_patterns:
|
3080 |
+
match = re.search(pattern, content, re.IGNORECASE | re.DOTALL)
|
3081 |
+
if match and match.group(1):
|
3082 |
+
section = match.group(1)
|
3083 |
+
for line in section.split('\n'):
|
3084 |
+
line = line.strip()
|
3085 |
+
if line and not line.endswith(':'):
|
3086 |
+
trait = re.sub(r'^\s*[-โข*]\s*', '', line) # ๊ธ๋จธ๋ฆฌํ ์ ๊ฑฐ
|
3087 |
+
trait = re.sub(r'^\d+\.\s*', '', trait) # ๋ฒํธ ์ ๊ฑฐ
|
3088 |
+
if len(trait) > 2:
|
3089 |
+
traits.append(trait)
|
3090 |
+
if traits:
|
3091 |
+
break
|
3092 |
+
|
3093 |
+
return traits[:5] # ์ต๋ 5๊ฐ
|
3094 |
+
|
3095 |
|
3096 |
def _process_character_content(self, content: str):
|
3097 |
"""Process character designer output with better error handling"""
|