Spaces:
Running
on
Zero
Running
on
Zero
Update app.py
Browse files
app.py
CHANGED
@@ -81,7 +81,7 @@ BRAVE_ENDPOINT = "https://api.search.brave.com/res/v1/web/search"
|
|
81 |
|
82 |
@dataclass
|
83 |
class ConversationConfig:
|
84 |
-
max_words: int =
|
85 |
prefix_url: str = "https://r.jina.ai/"
|
86 |
api_model_name: str = "meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo"
|
87 |
legacy_local_model_name: str = "NousResearch/Hermes-2-Pro-Llama-3-8B"
|
@@ -89,8 +89,8 @@ class ConversationConfig:
|
|
89 |
local_model_name: str = "Private-BitSix-Mistral-Small-3.1-24B-Instruct-2503.gguf"
|
90 |
local_model_repo: str = "ginigen/Private-BitSix-Mistral-Small-3.1-24B-Instruct-2503"
|
91 |
# ํ ํฐ ์ ์ฆ๊ฐ
|
92 |
-
max_tokens: int =
|
93 |
-
max_new_tokens: int =
|
94 |
|
95 |
|
96 |
def brave_search(query: str, count: int = 8, freshness_days: int | None = None):
|
@@ -120,41 +120,42 @@ def brave_search(query: str, count: int = 8, freshness_days: int | None = None):
|
|
120 |
return []
|
121 |
|
122 |
def format_search_results(query: str) -> str:
|
123 |
-
"""๊ฒ์ ๊ฒฐ๊ณผ๋ฅผ ํฌ๋งทํ
ํ์ฌ ๋ฐํ"""
|
124 |
-
rows = brave_search(query,
|
125 |
if not rows:
|
126 |
-
return
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
|
|
|
|
134 |
|
135 |
def extract_keywords_for_search(text: str, language: str = "English") -> List[str]:
|
136 |
-
"""ํ
์คํธ์์ ๊ฒ์ํ ํค์๋ ์ถ์ถ"""
|
137 |
-
#
|
138 |
-
|
139 |
-
text_sample = ' '.join(lines)
|
140 |
|
141 |
-
# ์ธ์ด๋ณ ์ค์ ํค์๋ ํจํด
|
142 |
if language == "Korean":
|
143 |
-
# ํ๊ตญ์ด ํค์๋ ํจํด (๋ช
์ฌํ ๋จ์ด๋ค)
|
144 |
import re
|
|
|
145 |
keywords = re.findall(r'[๊ฐ-ํฃ]{2,}', text_sample)
|
146 |
-
# ์ค๋ณต
|
147 |
-
unique_keywords = list(dict.fromkeys(keywords))
|
|
|
|
|
|
|
148 |
else:
|
149 |
-
#
|
150 |
words = text_sample.split()
|
151 |
-
# ๊ธธ์ด 3 ์ด์, ๋๋ฌธ์๋ก ์์ํ๋ ๋จ์ด๋ค ์ฐ์
|
152 |
keywords = [word.strip('.,!?;:') for word in words
|
153 |
-
if len(word) >
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
|
159 |
class UnifiedAudioConverter:
|
160 |
def __init__(self, config: ConversationConfig):
|
@@ -199,7 +200,7 @@ class UnifiedAudioConverter:
|
|
199 |
flash_attn=True,
|
200 |
n_gpu_layers=81 if torch.cuda.is_available() else 0,
|
201 |
n_batch=1024,
|
202 |
-
n_ctx=
|
203 |
)
|
204 |
self.local_llm_model = self.config.local_model_name
|
205 |
print(f"Local LLM initialized: {model_path_local}")
|
@@ -307,10 +308,15 @@ class UnifiedAudioConverter:
|
|
307 |
else:
|
308 |
return MessagesFormatterType.LLAMA_3
|
309 |
|
|
|
310 |
def _build_prompt(self, text: str, language: str = "English", search_context: str = "") -> str:
|
311 |
"""Build prompt for conversation generation with search context"""
|
|
|
|
|
|
|
|
|
|
|
312 |
if language == "Korean":
|
313 |
-
# ๊ฐํ๋ ํ๊ตญ์ด ํ๋กฌํํธ (์กด๋๋ง ๊ฐํ ๋ฐ ํ๊ตญ์ ํน์ฑ ๋ฐ์)
|
314 |
template = """
|
315 |
{
|
316 |
"conversation": [
|
@@ -322,36 +328,22 @@ class UnifiedAudioConverter:
|
|
322 |
}
|
323 |
"""
|
324 |
|
|
|
|
|
|
|
|
|
|
|
325 |
base_prompt = (
|
326 |
f"# ์๋ณธ ์ฝํ
์ธ :\n{text}\n\n"
|
327 |
-
f"
|
328 |
-
f"์
|
329 |
-
f"##
|
330 |
-
f"
|
331 |
-
f"-
|
332 |
-
f"-
|
333 |
-
f"
|
334 |
-
f"-
|
335 |
-
f"
|
336 |
-
f"- **์์ฐ์ค๋ฌ์ด ์กด๋๋ง**: ๋ฑ๋ฑํ์ง ์๊ณ ์น๊ทผํ ์กด๋๋ง ์ฌ์ฉ ('๊ทธ๋ ๊ตฐ์', '๋ง์ผ์ธ์', '๊ทธ๋ฐ๋ฐ์')\n"
|
337 |
-
f"- **๊ฐํ์ฌ ํ์ฉ**: '์~', '๊ทธ๋ ๊ตฌ๋์', '์~', '์ง์ง์?', '์ด๋จธ๋' ๋ฑ ์์ฐ์ค๋ฌ์ด ๋ฐ์\n\n"
|
338 |
-
f"### ๐ ๋ํ ๊ตฌ์ฑ:\n"
|
339 |
-
f"1. **ํ๊ตญ ๋ฌธํ ๋ง์ถค**: ํ๊ตญ์ธ์ ์ ์์ ์ผ์์ ๋ง๋ ๊ตฌ์ฒด์ ์์์ ๋น์ ์ฌ์ฉ\n"
|
340 |
-
f"2. **๊ณต๊ฐ๋ ํ์ฑ**: '์ฐ๋ฆฌ๋๋ผ์์๋', 'ํ๊ตญ ์ฌ๋๋ค์ด', '์์ฆ ์ฌ๋๋ค' ๋ฑ์ ํํ์ผ๋ก ์น๋ฐ๊ฐ ์กฐ์ฑ\n"
|
341 |
-
f"3. **์ถฉ๋ถํ ๋ถ๋**: ๊ฐ ๋ํ๋ ์ต์ 3-4๋ฌธ์ฅ ์ด์, ์ ์ฒด 10ํ ์ด์ ์ฃผ๊ณ ๋ฐ๊ธฐ\n"
|
342 |
-
f"4. **์ค์ฉ์ ์กฐ์ธ**: ์ฒญ์ทจ์๊ฐ ์ค์ ๋ก ์ ์ฉํ ์ ์๋ ๊ตฌ์ฒด์ ์ด๊ณ ์ ์ฉํ ์ ๋ณด ์ ๊ณต\n"
|
343 |
-
f"5. **์ต์ ์ ๋ณด ๋ฐ์**: ์ ๊ณต๋ ์ต์ ๊ด๋ จ ์ ๋ณด๋ฅผ ์์ฐ์ค๋ฝ๊ฒ ๋ํ์ ํฌํจ\n\n"
|
344 |
-
f"### ๐ฏ ํ์บ์คํธ ํ์ง:\n"
|
345 |
-
f"- **์คํ๋**: ๋ฐ๋ปํ ์ธ์ฌ์ ์ฃผ์ ์๊ฐ\n"
|
346 |
-
f"- **๋ฉ์ธ**: ํต์ฌ ๋ด์ฉ์ ์ฌ๋ฏธ์๊ณ ์ดํดํ๊ธฐ ์ฝ๊ฒ ์ ๋ฌ\n"
|
347 |
-
f"- **์ํธ์์ฉ**: '์ฒญ์ทจ์ ์ฌ๋ฌ๋ถ์ ์ด๋ป๊ฒ ์๊ฐํ์ธ์?' ๊ฐ์ ์ฐธ์ฌ ์ ๋\n"
|
348 |
-
f"- **ํด๋ก์ง**: ํต์ฌ ์์ฝ๊ณผ ์ค์ฉ์ ์กฐ์ธ์ผ๋ก ๋ง๋ฌด๋ฆฌ\n\n"
|
349 |
-
f"### ๐ก ํ๊ตญ์ด ํนํ ์์:\n"
|
350 |
-
f"- **ํธ์นญ**: '์ค์์จ', '๋ฏผํธ์จ' ๋ฑ ์ ์ ํ ํธ์นญ ์ฌ์ฉ\n"
|
351 |
-
f"- **๊ด์ฉ์ด๊ตฌ**: ์์ฐ์ค๋ฌ์ด ํ๊ตญ์ด ๊ด์ฉํํ ํ์ฉ\n"
|
352 |
-
f"- **์ ์์ ์ฐ๊ฒฐ**: ํ๊ตญ์ธ์ '์ ', '๋์น', '์ฒด๋ฉด' ๋ฑ์ ๋ฌธํ์ ์ฝ๋ ๋ฐ์\n"
|
353 |
-
f"- **๊ณ์ ๊ฐ**: ํ์ฌ ๊ณ์ ์ด๋ ์๊ธฐ์ ํน์ฑ ๋ฐ์\n\n"
|
354 |
-
f"๋ค์ JSON ํ์์ผ๋ก๋ง ๋ฐํํ์ธ์:\n{template}"
|
355 |
)
|
356 |
|
357 |
return base_prompt
|
@@ -368,26 +360,27 @@ class UnifiedAudioConverter:
|
|
368 |
}
|
369 |
"""
|
370 |
|
|
|
|
|
|
|
|
|
371 |
base_prompt = (
|
372 |
-
f"#
|
373 |
-
f"
|
374 |
-
f"
|
375 |
f"Guidelines:\n"
|
376 |
-
f"
|
377 |
-
f"
|
378 |
-
f"
|
379 |
-
f"
|
380 |
-
f"
|
381 |
-
f"
|
382 |
-
f"7. Address common questions and misconceptions\n"
|
383 |
-
f"8. Maintain an informative yet entertaining tone\n"
|
384 |
-
f"9. Incorporate the latest related information naturally into the conversation\n"
|
385 |
-
f"10. End with key takeaways and practical advice\n\n"
|
386 |
-
f"Return ONLY the JSON in this format:\n{template}"
|
387 |
)
|
388 |
|
389 |
return base_prompt
|
390 |
|
|
|
|
|
391 |
def _build_messages_for_local(self, text: str, language: str = "English", search_context: str = "") -> List[Dict]:
|
392 |
"""Build messages for local LLM with enhanced Korean guidelines"""
|
393 |
if language == "Korean":
|
|
|
81 |
|
82 |
@dataclass
|
83 |
class ConversationConfig:
|
84 |
+
max_words: int = 4000
|
85 |
prefix_url: str = "https://r.jina.ai/"
|
86 |
api_model_name: str = "meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo"
|
87 |
legacy_local_model_name: str = "NousResearch/Hermes-2-Pro-Llama-3-8B"
|
|
|
89 |
local_model_name: str = "Private-BitSix-Mistral-Small-3.1-24B-Instruct-2503.gguf"
|
90 |
local_model_repo: str = "ginigen/Private-BitSix-Mistral-Small-3.1-24B-Instruct-2503"
|
91 |
# ํ ํฐ ์ ์ฆ๊ฐ
|
92 |
+
max_tokens: int = 3000 # 2048์์ 6000์ผ๋ก ์ฆ๊ฐ
|
93 |
+
max_new_tokens: int = 6000 # 4000์์ 8000์ผ๋ก ์ฆ๊ฐ
|
94 |
|
95 |
|
96 |
def brave_search(query: str, count: int = 8, freshness_days: int | None = None):
|
|
|
120 |
return []
|
121 |
|
122 |
def format_search_results(query: str) -> str:
|
123 |
+
"""๊ฒ์ ๊ฒฐ๊ณผ๋ฅผ ํฌ๋งทํ
ํ์ฌ ๋ฐํ (๊ฐ๋ตํ๊ฒ)"""
|
124 |
+
rows = brave_search(query, 3, freshness_days=3) # 6๊ฐ์์ 3๊ฐ๋ก ์ค์
|
125 |
if not rows:
|
126 |
+
return "" # ๋น ๋ฌธ์์ด ๋ฐํ
|
127 |
+
|
128 |
+
# ๊ฒ์ ๊ฒฐ๊ณผ๋ฅผ ๋ ๊ฐ๋ตํ๊ฒ ์์ฝ
|
129 |
+
results = []
|
130 |
+
for r in rows[:2]: # ์ต๋ 2๊ฐ๋ง ์ฌ์ฉ
|
131 |
+
# ์ค๋ํซ์ 100์๋ก ์ ํ
|
132 |
+
snippet = r['snippet'][:100] + "..." if len(r['snippet']) > 100 else r['snippet']
|
133 |
+
results.append(f"- {r['title']}: {snippet}")
|
134 |
+
|
135 |
+
return "\n".join(results) + "\n"
|
136 |
|
137 |
def extract_keywords_for_search(text: str, language: str = "English") -> List[str]:
|
138 |
+
"""ํ
์คํธ์์ ๊ฒ์ํ ํค์๋ ์ถ์ถ (๊ฐ์ )"""
|
139 |
+
# ํ
์คํธ ์๋ถ๋ถ๋ง ์ฌ์ฉ (๋๋ฌด ๋ง์ ํ
์คํธ ์ฒ๋ฆฌ ๋ฐฉ์ง)
|
140 |
+
text_sample = text[:500]
|
|
|
141 |
|
|
|
142 |
if language == "Korean":
|
|
|
143 |
import re
|
144 |
+
# ํ๊ตญ์ด ๋ช
์ฌ ์ถ์ถ (2๊ธ์ ์ด์)
|
145 |
keywords = re.findall(r'[๊ฐ-ํฃ]{2,}', text_sample)
|
146 |
+
# ์ค๋ณต ์ ๊ฑฐํ๊ณ ๊ฐ์ฅ ๊ธด ๋จ์ด 1๊ฐ๋ง ์ ํ
|
147 |
+
unique_keywords = list(dict.fromkeys(keywords))
|
148 |
+
# ๊ธธ์ด ์์ผ๋ก ์ ๋ ฌํ๊ณ ๊ฐ์ฅ ์๋ฏธ์์ ๊ฒ ๊ฐ์ ๋จ์ด ์ ํ
|
149 |
+
unique_keywords.sort(key=len, reverse=True)
|
150 |
+
return unique_keywords[:1] # 1๊ฐ๋ง ๋ฐํ
|
151 |
else:
|
152 |
+
# ์์ด๋ ๋๋ฌธ์๋ก ์์ํ๋ ๋จ์ด ์ค ๊ฐ์ฅ ๊ธด ๊ฒ 1๊ฐ
|
153 |
words = text_sample.split()
|
|
|
154 |
keywords = [word.strip('.,!?;:') for word in words
|
155 |
+
if len(word) > 4 and word[0].isupper()]
|
156 |
+
if keywords:
|
157 |
+
return [max(keywords, key=len)] # ๊ฐ์ฅ ๊ธด ๋จ์ด 1๊ฐ
|
158 |
+
return []
|
|
|
159 |
|
160 |
class UnifiedAudioConverter:
|
161 |
def __init__(self, config: ConversationConfig):
|
|
|
200 |
flash_attn=True,
|
201 |
n_gpu_layers=81 if torch.cuda.is_available() else 0,
|
202 |
n_batch=1024,
|
203 |
+
n_ctx=16384,
|
204 |
)
|
205 |
self.local_llm_model = self.config.local_model_name
|
206 |
print(f"Local LLM initialized: {model_path_local}")
|
|
|
308 |
else:
|
309 |
return MessagesFormatterType.LLAMA_3
|
310 |
|
311 |
+
|
312 |
def _build_prompt(self, text: str, language: str = "English", search_context: str = "") -> str:
|
313 |
"""Build prompt for conversation generation with search context"""
|
314 |
+
# ํ
์คํธ ๊ธธ์ด ์ ํ์ ๋ ๊ฐํ๊ฒ ์ ์ฉ
|
315 |
+
max_text_length = 3000 if search_context else 4000
|
316 |
+
if len(text) > max_text_length:
|
317 |
+
text = text[:max_text_length] + "..."
|
318 |
+
|
319 |
if language == "Korean":
|
|
|
320 |
template = """
|
321 |
{
|
322 |
"conversation": [
|
|
|
328 |
}
|
329 |
"""
|
330 |
|
331 |
+
# ๊ฒ์ ์ปจํ
์คํธ๊ฐ ์์ ๋๋ง ํฌํจ
|
332 |
+
context_part = ""
|
333 |
+
if search_context:
|
334 |
+
context_part = f"# ์ต์ ๊ด๋ จ ์ ๋ณด:\n{search_context}\n"
|
335 |
+
|
336 |
base_prompt = (
|
337 |
f"# ์๋ณธ ์ฝํ
์ธ :\n{text}\n\n"
|
338 |
+
f"{context_part}"
|
339 |
+
f"์ ๋ด์ฉ์ผ๋ก ํ๊ตญ์ด ํ์บ์คํธ ๋ํ๋ฅผ ๋ง๋ค์ด์ฃผ์ธ์.\n\n"
|
340 |
+
f"## ํต์ฌ ์ง์นจ:\n"
|
341 |
+
f"- ์ค์(์งํ์)์ ๋ฏผํธ(์ ๋ฌธ๊ฐ) ๋ 30๋ ๋จ์ฑ์ ๋ํ\n"
|
342 |
+
f"- ์๋ก ์กด๋๋ง ์ฌ์ฉ ํ์ (๋ฐ๋ง ์ ๋ ๊ธ์ง)\n"
|
343 |
+
f"- ์์ฐ์ค๋ฌ์ด ํ๊ตญ์ด ํํ ์ฌ์ฉ\n"
|
344 |
+
f"- ๊ฐ ๋ํ 2-3๋ฌธ์ฅ, ์ ์ฒด 8-10ํ ์ฃผ๊ณ ๋ฐ๊ธฐ\n"
|
345 |
+
f"- ์ต์ ์ ๋ณด๊ฐ ์๋ค๋ฉด ์์ฐ์ค๋ฝ๊ฒ ํฌํจ\n\n"
|
346 |
+
f"JSON ํ์์ผ๋ก๋ง ๋ฐํ:\n{template}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
347 |
)
|
348 |
|
349 |
return base_prompt
|
|
|
360 |
}
|
361 |
"""
|
362 |
|
363 |
+
context_part = ""
|
364 |
+
if search_context:
|
365 |
+
context_part = f"# Latest Information:\n{search_context}\n"
|
366 |
+
|
367 |
base_prompt = (
|
368 |
+
f"# Content:\n{text}\n\n"
|
369 |
+
f"{context_part}"
|
370 |
+
f"Create a podcast conversation.\n\n"
|
371 |
f"Guidelines:\n"
|
372 |
+
f"- Alex (Host) and Jordan (Expert)\n"
|
373 |
+
f"- Natural conversational English\n"
|
374 |
+
f"- Each response 2-3 sentences\n"
|
375 |
+
f"- 8-10 exchanges total\n"
|
376 |
+
f"- Include latest info if available\n\n"
|
377 |
+
f"Return JSON only:\n{template}"
|
|
|
|
|
|
|
|
|
|
|
378 |
)
|
379 |
|
380 |
return base_prompt
|
381 |
|
382 |
+
|
383 |
+
|
384 |
def _build_messages_for_local(self, text: str, language: str = "English", search_context: str = "") -> List[Dict]:
|
385 |
"""Build messages for local LLM with enhanced Korean guidelines"""
|
386 |
if language == "Korean":
|