common.pyโข6.27 kB
from pydantic import BaseModel, Field
from typing import Dict, Any, List, Optional
import logging
import os
import sys
#from database import db_manager
#from ai_provider import ai_manager
#from config import config
logger = logging.getLogger(__name__)
# Pydantic ๋ชจ๋ธ๋ค
class SQLQueryRequest(BaseModel):
query: str
class NaturalLanguageRequest(BaseModel):
question: str
class TableSchemaRequest(BaseModel):
table_name: str
class AIProviderRequest(BaseModel):
provider: str = Field(..., description="AI Provider ์ด๋ฆ", pattern="^(groq|ollama|google)$")
class Response(BaseModel):
success: bool
data: Any = None
error: Optional[str] = None
def model_dump(self, **kwargs):
"""UTF-8 ์ธ์ฝ๋ฉ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ์ปค์คํ
model_dump"""
try:
return super().model_dump(**kwargs)
except UnicodeDecodeError as e:
# UTF-8 ์ธ์ฝ๋ฉ ์ค๋ฅ ๋ฐ์ ์ ๋ฐ์ดํฐ ์ ๋ฆฌ
logger.warning(f"UTF-8 ์ธ์ฝ๋ฉ ์ค๋ฅ ๋ฐ์, ๋ฐ์ดํฐ ์ ๋ฆฌ ์ค: {e}")
# ๋ฐ์ดํฐ ์ ๋ฆฌ
cleaned_data = self._clean_data(self.data)
cleaned_error = self._clean_string(self.error) if self.error else None
return {
"success": self.success,
"data": cleaned_data,
"error": cleaned_error
}
def _clean_data(self, data):
"""๋ฐ์ดํฐ์์ UTF-8 ๋ฌธ์ ๊ฐ ์๋ ๋ถ๋ถ์ ์ ๋ฆฌ"""
if isinstance(data, str):
return self._clean_string(data)
elif isinstance(data, dict):
return {k: self._clean_data(v) for k, v in data.items()}
elif isinstance(data, list):
return [self._clean_data(item) for item in data]
else:
return data
def _clean_string(self, text):
"""๋ฌธ์์ด์์ UTF-8 ๋ฌธ์ ๊ฐ ์๋ ๋ถ๋ถ์ ์ ๋ฆฌ"""
if not isinstance(text, str):
return str(text)
try:
# UTF-8๋ก ์ธ์ฝ๋ฉ/๋์ฝ๋ฉํ์ฌ ๋ฌธ์ ์๋ ๋ฌธ์ ์ ๊ฑฐ
return text.encode('utf-8', errors='ignore').decode('utf-8')
except Exception:
# ์ตํ์ ์๋จ: ASCII๋ก ๋ณํ
return text.encode('ascii', errors='ignore').decode('ascii')
def clear_screen():
"""ํ๋ฉด์ ์ง์ฐ๋ ํจ์"""
if os.name == 'nt':
# Windows ํ๊ฒฝ์ด์ง๋ง Git Bash ๋ฑ์์๋ 'clear'๋ฅผ ์ฌ์ฉํด์ผ ํจ
if 'MSYSTEM' in os.environ or 'MINGW64' in os.environ or 'MINGW32' in os.environ:
os.system('clear')
else:
os.system('cls')
else:
os.system('clear')
def init_environment(db_manager, ai_manager):
"""์ดํ๋ฆฌ์ผ์ด์
์คํ๋ ์ ์๋๋ก DB connection ์์ฑ ๋ฐ AI Provider ์์ฑ"""
try:
# ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ์ด๊ธฐํ
db_manager.constructor()
# AI Provider ์ด๊ธฐํ
ai_manager.constructor()
logger.info("ํ๊ฒฝ ์ด๊ธฐํ๊ฐ ์๋ฃ๋์์ต๋๋ค.")
except Exception as e:
logger.error(f"ํ๊ฒฝ ์ด๊ธฐํ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค: {e}")
raise
def convert_for_json_serialization(obj):
"""JSON ์ง๋ ฌํ๋ฅผ ์ํด ๋ชจ๋ ๋ฐ์ดํฐ ํ์
์ ๋ณํ"""
if obj is None:
return None
# ๋ ์ง/์๊ฐ ํ์
์ ๋ฌธ์์ด๋ก ๋ณํ
import datetime
if isinstance(obj, (datetime.date, datetime.datetime)):
return obj.isoformat()
# Decimal ํ์
์ float๋ก ๋ณํ
from decimal import Decimal
if isinstance(obj, Decimal):
return float(obj)
# ๋ฐ์ด๋๋ฆฌ ๋ฐ์ดํฐ๋ฅผ 16์ง์ ๋ฌธ์์ด๋ก ๋ณํ
if isinstance(obj, bytes):
return obj.hex()
# ๋์
๋๋ฆฌ์ ๋ฆฌ์คํธ๋ ์ฌ๊ท์ ์ผ๋ก ์ฒ๋ฆฌ
elif isinstance(obj, dict):
return {k: convert_for_json_serialization(v) for k, v in obj.items()}
elif isinstance(obj, list):
return [convert_for_json_serialization(item) for item in obj]
# ๋ค๋ฅธ ํ์
์ ๊ทธ๋๋ก ๋ฐํ
else:
return obj
def convert_decimal_in_result(obj):
"""๊ฒฐ๊ณผ ๋ฐ์ดํฐ์์ Decimal ํ์
์ float๋ก, date ํ์
์ ๋ฌธ์์ด๋ก ๋ณํ (๊ธฐ์กด ํธํ์ฑ ์ ์ง)"""
return convert_for_json_serialization(obj)
import datetime
if isinstance(obj, Decimal):
return float(obj)
elif isinstance(obj, (datetime.date, datetime.datetime)):
return obj.isoformat()
elif isinstance(obj, dict):
return {k: convert_decimal_in_result(v) for k, v in obj.items()}
elif isinstance(obj, list):
return [convert_decimal_in_result(item) for item in obj]
else:
return obj
def check_init_environment(db_manager, args, ai_manager, config):
# ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ํ์ธ
if not db_manager.is_connected():
logger.error("๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฐ๊ฒฐํ ์ ์์ต๋๋ค.")
logger.error("ํ๊ฒฝ ๋ณ์๋ฅผ ํ์ธํ๊ฑฐ๋ .env ํ์ผ์ ์ค์ ํด์ฃผ์ธ์.")
sys.exit(1)
logger.info("MySQL Hub Server๋ฅผ ์์ํฉ๋๋ค.")
logger.info(f"์คํ ๋ชจ๋: {args}")
logger.info(f"AI Provider: {ai_manager.get_current_provider()}")
logger.info(f"HTTP ์๋ฒ: http://{config.HTTP_SERVER_HOST}:{config.HTTP_SERVER_PORT}")
logger.info(f"log level : {config.LOG_LEVEL}")
# json์ ์
๋ ฅ๋ฐ์ json format์ ๋ง๊ฒ string์ผ๋ก ๋ณํํด์ ๋ฆฌํดํ๋ ํจ์
def json_to_pretty_string(data):
"""
json ๊ฐ์ฒด๋ฅผ ์์๊ฒ ํฌ๋งท๋ ๋ฌธ์์ด๋ก ๋ณํํ์ฌ ๋ฐํํฉ๋๋ค.
Args:
data (dict or list): JSON ๊ฐ์ฒด
Returns:
str: ์์๊ฒ ํฌ๋งท๋ JSON ๋ฌธ์์ด
"""
try:
import json
# Response ๊ฐ์ฒด์ธ ๊ฒฝ์ฐ model_dump() ์ฌ์ฉ
if hasattr(data, 'model_dump'):
data = data.model_dump()
# ๊ณตํต ๋ณํ ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ๋ ๋ฐ์ดํฐ ํ์
๋ณํ
converted_data = convert_for_json_serialization(data)
return json.dumps(converted_data, ensure_ascii=False, indent=2, sort_keys=True)
except Exception as e:
return f"JSON ๋ณํ ์ค๋ฅ: {e}"