Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -563,7 +563,7 @@ class NovelWritingSystem:
|
|
563 |
return full_content
|
564 |
|
565 |
def call_llm_streaming(self, messages: List[Dict[str, str]], role: str, language: str) -> Generator[str, None, None]:
|
566 |
-
"""LLM ์คํธ๋ฆฌ๋ฐ ํธ์ถ (
|
567 |
try:
|
568 |
system_prompts = self.get_system_prompts(language)
|
569 |
full_messages = [{"role": "system", "content": system_prompts.get(role, "You are a helpful assistant.")}, *messages]
|
@@ -578,32 +578,82 @@ class NovelWritingSystem:
|
|
578 |
"stream": True,
|
579 |
"stream_options": {"include_usage": True}
|
580 |
}
|
|
|
|
|
581 |
response = requests.post(self.api_url, headers=self.create_headers(), json=payload, stream=True, timeout=180)
|
582 |
response.raise_for_status()
|
|
|
583 |
buffer = ""
|
|
|
|
|
584 |
for line in response.iter_lines():
|
585 |
if line:
|
586 |
line_str = line.decode('utf-8')
|
587 |
if line_str.startswith("data: "):
|
588 |
data = line_str[6:]
|
589 |
-
if data == "[DONE]":
|
|
|
|
|
|
|
590 |
try:
|
591 |
chunk = json.loads(data)
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
599 |
continue
|
600 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
601 |
except requests.exceptions.RequestException as e:
|
602 |
-
logger.error(f"API
|
603 |
yield f"โ API ์ค๋ฅ: {e}"
|
604 |
except Exception as e:
|
605 |
-
logger.error(f"
|
606 |
yield f"โ ์ฒ๋ฆฌ ์ค๋ฅ: {e}"
|
|
|
|
|
|
|
607 |
|
608 |
def get_system_prompts(self, language: str) -> Dict[str, str]:
|
609 |
"""์ญํ ๋ณ ์์คํ
ํ๋กฌํํธ ์์ฑ"""
|
|
|
563 |
return full_content
|
564 |
|
565 |
def call_llm_streaming(self, messages: List[Dict[str, str]], role: str, language: str) -> Generator[str, None, None]:
|
566 |
+
"""LLM ์คํธ๋ฆฌ๋ฐ ํธ์ถ (์์ ํ ์๋ฌ ์ฒ๋ฆฌ)"""
|
567 |
try:
|
568 |
system_prompts = self.get_system_prompts(language)
|
569 |
full_messages = [{"role": "system", "content": system_prompts.get(role, "You are a helpful assistant.")}, *messages]
|
|
|
578 |
"stream": True,
|
579 |
"stream_options": {"include_usage": True}
|
580 |
}
|
581 |
+
|
582 |
+
logger.info(f"API ํธ์ถ ์์ - ์ญํ : {role}")
|
583 |
response = requests.post(self.api_url, headers=self.create_headers(), json=payload, stream=True, timeout=180)
|
584 |
response.raise_for_status()
|
585 |
+
|
586 |
buffer = ""
|
587 |
+
chunk_count = 0
|
588 |
+
|
589 |
for line in response.iter_lines():
|
590 |
if line:
|
591 |
line_str = line.decode('utf-8')
|
592 |
if line_str.startswith("data: "):
|
593 |
data = line_str[6:]
|
594 |
+
if data == "[DONE]":
|
595 |
+
logger.info(f"์คํธ๋ฆฌ๋ฐ ์๋ฃ - ์ด {chunk_count}๊ฐ ์ฒญํฌ ์ฒ๋ฆฌ")
|
596 |
+
break
|
597 |
+
|
598 |
try:
|
599 |
chunk = json.loads(data)
|
600 |
+
|
601 |
+
# ๋๋ฒ๊น
์ ์ํด ์ฒซ ๋ช ๊ฐ ์ฒญํฌ ๋ก๊น
|
602 |
+
if chunk_count < 3:
|
603 |
+
logger.debug(f"์ฒญํฌ {chunk_count}: {json.dumps(chunk, ensure_ascii=False)[:200]}")
|
604 |
+
|
605 |
+
# ์์ ํ content ์ถ์ถ
|
606 |
+
choices = chunk.get("choices", [])
|
607 |
+
if choices and len(choices) > 0:
|
608 |
+
delta = choices[0].get("delta", {})
|
609 |
+
content = delta.get("content", "")
|
610 |
+
|
611 |
+
if content:
|
612 |
+
buffer += content
|
613 |
+
chunk_count += 1
|
614 |
+
|
615 |
+
# ๋ฒํผ๊ฐ ์ถฉ๋ถํ ์ฐจ๊ฑฐ๋ ์ค๋ฐ๊ฟ์ด ์์ ๋ yield
|
616 |
+
if len(buffer) > 100 or "\n" in buffer:
|
617 |
+
yield buffer
|
618 |
+
buffer = ""
|
619 |
+
|
620 |
+
# ์๋ฌ ๋ฉ์์ง ์ฒดํฌ
|
621 |
+
elif chunk.get("error"):
|
622 |
+
error_msg = chunk.get("error", {}).get("message", "Unknown error")
|
623 |
+
logger.error(f"API ์๋ฌ ์๋ต: {error_msg}")
|
624 |
+
yield f"โ API ์ค๋ฅ: {error_msg}"
|
625 |
+
return
|
626 |
+
|
627 |
+
except json.JSONDecodeError as e:
|
628 |
+
logger.warning(f"JSON ํ์ฑ ์ค๋ฅ: {e}, ๋ฐ์ดํฐ: {data[:100]}")
|
629 |
continue
|
630 |
+
except Exception as e:
|
631 |
+
logger.error(f"์ฒญํฌ ์ฒ๋ฆฌ ์ค ์์ธ: {e}")
|
632 |
+
continue
|
633 |
+
|
634 |
+
# ๋จ์ ๋ฒํผ ๋ด์ฉ ์ถ๋ ฅ
|
635 |
+
if buffer:
|
636 |
+
yield buffer
|
637 |
+
|
638 |
+
# ์ฒญํฌ๊ฐ ํ๋๋ ์ฒ๋ฆฌ๋์ง ์์๋ค๋ฉด
|
639 |
+
if chunk_count == 0:
|
640 |
+
logger.error("์๋ต์์ ์ฝํ
์ธ ๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค.")
|
641 |
+
yield "โ API ์๋ต์ ์ฝํ
์ธ ๊ฐ ์์ต๋๋ค."
|
642 |
+
|
643 |
+
except requests.exceptions.HTTPError as e:
|
644 |
+
logger.error(f"HTTP ์ค๋ฅ: {e}")
|
645 |
+
logger.error(f"์๋ต ์ํ ์ฝ๋: {e.response.status_code if e.response else 'N/A'}")
|
646 |
+
logger.error(f"์๋ต ๋ด์ฉ: {e.response.text[:500] if e.response else 'N/A'}")
|
647 |
+
yield f"โ HTTP ์ค๋ฅ: {e}"
|
648 |
except requests.exceptions.RequestException as e:
|
649 |
+
logger.error(f"API ์์ฒญ ์ค๋ฅ: {e}")
|
650 |
yield f"โ API ์ค๋ฅ: {e}"
|
651 |
except Exception as e:
|
652 |
+
logger.error(f"์๊ธฐ์น ์์ ์ค๋ฅ: {e}", exc_info=True)
|
653 |
yield f"โ ์ฒ๋ฆฌ ์ค๋ฅ: {e}"
|
654 |
+
|
655 |
+
|
656 |
+
|
657 |
|
658 |
def get_system_prompts(self, language: str) -> Dict[str, str]:
|
659 |
"""์ญํ ๋ณ ์์คํ
ํ๋กฌํํธ ์์ฑ"""
|