RAG3 / rag_chain.py
jeongsoo's picture
deepseek_done
ac1b0e8
"""
직접 DeepSeek API ν˜ΈμΆœμ„ μœ„ν•œ ν΄λΌμ΄μ–ΈνŠΈ κ΅¬ν˜„
"""
import os
import time
import logging
import requests
import json
from typing import Dict, Any, Optional, List
# λ‘œκΉ… μ„€μ •
logger = logging.getLogger("DirectDeepSeek")
class DirectDeepSeekClient:
"""
DeepSeek APIλ₯Ό 직접 ν˜ΈμΆœν•˜λŠ” ν΄λΌμ΄μ–ΈνŠΈ
OpenAI ν΄λΌμ΄μ–ΈνŠΈλ₯Ό μš°νšŒν•˜κ³  직접 HTTP μš”μ²­ μ‚¬μš©
"""
def __init__(self, api_key: str, model_name: str = "deepseek-chat"):
"""
ν΄λΌμ΄μ–ΈνŠΈ μ΄ˆκΈ°ν™”
Args:
api_key: DeepSeek API ν‚€
model_name: μ‚¬μš©ν•  λͺ¨λΈ 이름 (κΈ°λ³Έκ°’: "deepseek-chat")
"""
self.api_key = api_key
self.model_name = model_name
self.endpoint = os.getenv("DEEPSEEK_ENDPOINT", "https://api.deepseek.com/v1/chat/completions")
logger.info(f"DirectDeepSeekClient μ΄ˆκΈ°ν™”: λͺ¨λΈ={model_name}, μ—”λ“œν¬μΈνŠΈ={self.endpoint}")
def generate(self,
prompt: str,
temperature: float = 0.3,
max_tokens: int = 1000,
max_retries: int = 3,
timeout: int = 60) -> Dict[str, Any]:
"""
ν…μŠ€νŠΈ 생성 μš”μ²­
Args:
prompt: μž…λ ₯ ν”„λ‘¬ν”„νŠΈ
temperature: 생성 μ˜¨λ„ (0.0 ~ 1.0)
max_tokens: μ΅œλŒ€ 생성 토큰 수
max_retries: μž¬μ‹œλ„ 횟수
timeout: μš”μ²­ νƒ€μž„μ•„μ›ƒ (초)
Returns:
생성 κ²°κ³Ό λ”•μ…”λ„ˆλ¦¬ (success, response, message λ“±)
"""
# λ©”μ‹œμ§€ ꡬ성 (단일 μ‚¬μš©μž λ©”μ‹œμ§€)
messages = [{"role": "user", "content": prompt}]
return self.chat(messages, temperature, max_tokens, max_retries, timeout)
def chat(self,
messages: List[Dict[str, str]],
temperature: float = 0.3,
max_tokens: int = 1000,
max_retries: int = 3,
timeout: int = 60) -> Dict[str, Any]:
"""
μ±„νŒ… API 호좜
Args:
messages: μ±„νŒ… λ©”μ‹œμ§€ 리슀트 (role, content ν‚€λ₯Ό κ°€μ§„ λ”•μ…”λ„ˆλ¦¬ 리슀트)
temperature: 생성 μ˜¨λ„ (0.0 ~ 1.0)
max_tokens: μ΅œλŒ€ 생성 토큰 수
max_retries: μž¬μ‹œλ„ 횟수
timeout: μš”μ²­ νƒ€μž„μ•„μ›ƒ (초)
Returns:
생성 κ²°κ³Ό λ”•μ…”λ„ˆλ¦¬ (success, response, message λ“±)
"""
# API μš”μ²­ 헀더 및 데이터
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {self.api_key}"
}
payload = {
"model": self.model_name,
"messages": messages,
"temperature": temperature,
"max_tokens": max_tokens
}
# μž¬μ‹œλ„ 둜직
retry_delay = 1.0
attempt = 0
while attempt < max_retries:
attempt += 1
try:
logger.info(f"DeepSeek API μš”μ²­ μ‹œλ„ ({attempt}/{max_retries})...")
# API μš”μ²­ 전솑
response = requests.post(
self.endpoint,
headers=headers,
json=payload,
timeout=timeout
)
# 응닡 확인
if response.status_code == 200:
result = response.json()
# 응닡 λ‚΄μš© μΆ”μΆœ
if "choices" in result and len(result["choices"]) > 0:
message_content = result["choices"][0].get("message", {}).get("content", "")
logger.info(f"DeepSeek API 응닡 성곡 (길이: {len(message_content)})")
return {
"success": True,
"response": message_content,
"status_code": response.status_code,
"raw_response": result
}
else:
logger.warning(f"DeepSeek API 응닡은 μ„±κ³΅ν–ˆμœΌλ‚˜ μ˜ˆμƒμΉ˜ λͺ»ν•œ 응닡 ν˜•μ‹: {result}")
return {
"success": False,
"message": "μ‘λ‹΅μ—μ„œ λ©”μ‹œμ§€λ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€",
"status_code": response.status_code,
"raw_response": result
}
else:
logger.error(f"DeepSeek API 였λ₯˜: μƒνƒœ μ½”λ“œ {response.status_code}")
# 였λ₯˜ λ©”μ‹œμ§€ μΆ”μΆœ
error_message = ""
try:
error_data = response.json()
error_message = error_data.get("error", {}).get("message", str(error_data))
except:
error_message = response.text
# μš”μ²­ ν•œλ„ μ΄ˆκ³Όμ‹œ 더 였래 λŒ€κΈ°
if response.status_code == 429:
retry_delay = min(retry_delay * 3, 15)
else:
retry_delay = min(retry_delay * 2, 10)
if attempt < max_retries:
logger.info(f"{retry_delay}초 ν›„ μž¬μ‹œλ„...")
time.sleep(retry_delay)
else:
# λͺ¨λ“  μ‹œλ„ μ‹€νŒ¨
return {
"success": False,
"message": f"API 였λ₯˜: {error_message}",
"status_code": response.status_code
}
except requests.exceptions.Timeout:
logger.error("DeepSeek API μš”μ²­ μ‹œκ°„ 초과")
if attempt < max_retries:
logger.info(f"{retry_delay}초 ν›„ μž¬μ‹œλ„...")
time.sleep(retry_delay)
retry_delay = min(retry_delay * 2, 10)
else:
return {
"success": False,
"message": "API μš”μ²­ μ‹œκ°„ 초과",
"status_code": None
}
except requests.exceptions.ConnectionError:
logger.error("DeepSeek API μ—°κ²° μ‹€νŒ¨")
if attempt < max_retries:
logger.info(f"{retry_delay}초 ν›„ μž¬μ‹œλ„...")
time.sleep(retry_delay)
retry_delay = min(retry_delay * 2, 10)
else:
return {
"success": False,
"message": "API μ„œλ²„ μ—°κ²° μ‹€νŒ¨",
"status_code": None
}
except Exception as e:
logger.error(f"DeepSeek API μš”μ²­ 쀑 μ˜ˆμƒμΉ˜ λͺ»ν•œ 였λ₯˜: {e}")
if attempt < max_retries:
logger.info(f"{retry_delay}초 ν›„ μž¬μ‹œλ„...")
time.sleep(retry_delay)
retry_delay = min(retry_delay * 2, 10)
else:
return {
"success": False,
"message": f"μ˜ˆμƒμΉ˜ λͺ»ν•œ 였λ₯˜: {str(e)}",
"status_code": None
}
# λͺ¨λ“  μ‹œλ„ μ‹€νŒ¨
return {
"success": False,
"message": "μ΅œλŒ€ μž¬μ‹œλ„ 횟수 초과",
"status_code": None
}
def system_prompt_chat(self,
system_prompt: str,
user_prompt: str,
temperature: float = 0.3,
max_tokens: int = 1000,
max_retries: int = 3,
timeout: int = 60) -> Dict[str, Any]:
"""
μ‹œμŠ€ν…œ ν”„λ‘¬ν”„νŠΈμ™€ μ‚¬μš©μž ν”„λ‘¬ν”„νŠΈλ₯Ό μ΄μš©ν•œ μ±„νŒ… API 호좜
Args:
system_prompt: μ‹œμŠ€ν…œ ν”„λ‘¬ν”„νŠΈ
user_prompt: μ‚¬μš©μž ν”„λ‘¬ν”„νŠΈ
temperature: 생성 μ˜¨λ„ (0.0 ~ 1.0)
max_tokens: μ΅œλŒ€ 생성 토큰 수
max_retries: μž¬μ‹œλ„ 횟수
timeout: μš”μ²­ νƒ€μž„μ•„μ›ƒ (초)
Returns:
생성 κ²°κ³Ό λ”•μ…”λ„ˆλ¦¬
"""
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt}
]
return self.chat(messages, temperature, max_tokens, max_retries, timeout)
# 단독 싀행을 μœ„ν•œ ν…ŒμŠ€νŠΈ μ½”λ“œ
if __name__ == "__main__":
# λ‘œκΉ… μ„€μ •
logging.basicConfig(level=logging.INFO)
# API ν‚€ 확인
api_key = os.environ.get("DEEPSEEK_API_KEY")
if not api_key:
print("ν™˜κ²½ λ³€μˆ˜ DEEPSEEK_API_KEYκ°€ μ„€μ •λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.")
exit(1)
# ν΄λΌμ΄μ–ΈνŠΈ 생성
client = DirectDeepSeekClient(api_key)
# κ°„λ‹¨ν•œ ν…ŒμŠ€νŠΈ
response = client.generate("Hello, what can you do?")
# κ²°κ³Ό 좜λ ₯
if response["success"]:
print("응닡 성곡!")
print(response["response"])
else:
print(f"응닡 μ‹€νŒ¨: {response['message']}")