Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python3 | |
| """ | |
| ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ด๋ฆฌ ๋ชจ๋ | |
| SQLite๋ฅผ ์ฌ์ฉํ ์ฑํ ํ์คํ ๋ฆฌ ๋ฐ ์ฌ์ฉ์ ๋ฐ์ดํฐ ๊ด๋ฆฌ | |
| """ | |
| import sqlite3 | |
| import logging | |
| import json | |
| from datetime import datetime | |
| from typing import List, Dict, Any, Optional | |
| from pathlib import Path | |
| logger = logging.getLogger(__name__) | |
| class DatabaseManager: | |
| """SQLite ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ด๋ฆฌ ํด๋์ค""" | |
| def __init__(self, db_path: str = "./lily_llm.db"): | |
| self.db_path = Path(db_path) | |
| self.db_path.parent.mkdir(exist_ok=True) | |
| self.init_database() | |
| def init_database(self): | |
| """๋ฐ์ดํฐ๋ฒ ์ด์ค ์ด๊ธฐํ ๋ฐ ํ ์ด๋ธ ์์ฑ""" | |
| try: | |
| with sqlite3.connect(self.db_path) as conn: | |
| cursor = conn.cursor() | |
| # ์ฌ์ฉ์ ํ ์ด๋ธ | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS users ( | |
| user_id TEXT PRIMARY KEY, | |
| username TEXT, | |
| email TEXT, | |
| created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | |
| last_login TIMESTAMP, | |
| is_active BOOLEAN DEFAULT TRUE | |
| ) | |
| """) | |
| # ์ฑํ ์ธ์ ํ ์ด๋ธ | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS chat_sessions ( | |
| session_id TEXT PRIMARY KEY, | |
| user_id TEXT, | |
| session_name TEXT, | |
| created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | |
| last_activity TIMESTAMP, | |
| is_active BOOLEAN DEFAULT TRUE, | |
| FOREIGN KEY (user_id) REFERENCES users (user_id) | |
| ) | |
| """) | |
| # ์ฑํ ๋ฉ์์ง ํ ์ด๋ธ | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS chat_messages ( | |
| message_id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| session_id TEXT, | |
| user_id TEXT, | |
| message_type TEXT CHECK(message_type IN ('user', 'assistant', 'system')), | |
| content TEXT, | |
| metadata TEXT, | |
| timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | |
| FOREIGN KEY (session_id) REFERENCES chat_sessions (session_id), | |
| FOREIGN KEY (user_id) REFERENCES users (user_id) | |
| ) | |
| """) | |
| # ๋ฌธ์ ์ ๋ณด ํ ์ด๋ธ | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS documents ( | |
| document_id TEXT PRIMARY KEY, | |
| user_id TEXT, | |
| filename TEXT, | |
| file_type TEXT, | |
| file_size INTEGER, | |
| upload_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | |
| last_accessed TIMESTAMP, | |
| is_active BOOLEAN DEFAULT TRUE, | |
| metadata TEXT, | |
| FOREIGN KEY (user_id) REFERENCES users (user_id) | |
| ) | |
| """) | |
| # RAG ์ฟผ๋ฆฌ ํ์คํ ๋ฆฌ ํ ์ด๋ธ | |
| cursor.execute(""" | |
| CREATE TABLE IF NOT EXISTS rag_queries ( | |
| query_id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| user_id TEXT, | |
| document_id TEXT, | |
| query_text TEXT, | |
| response_text TEXT, | |
| processing_time REAL, | |
| search_results INTEGER, | |
| query_type TEXT CHECK(query_type IN ('text', 'hybrid')), | |
| timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | |
| FOREIGN KEY (user_id) REFERENCES users (user_id), | |
| FOREIGN KEY (document_id) REFERENCES documents (document_id) | |
| ) | |
| """) | |
| conn.commit() | |
| logger.info("โ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ด๊ธฐํ ์๋ฃ") | |
| except Exception as e: | |
| logger.error(f"โ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ด๊ธฐํ ์คํจ: {e}") | |
| raise | |
| def add_user(self, user_id: str, username: str = None, email: str = None) -> bool: | |
| """์ฌ์ฉ์ ์ถ๊ฐ""" | |
| try: | |
| with sqlite3.connect(self.db_path) as conn: | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| INSERT OR REPLACE INTO users (user_id, username, email, last_login) | |
| VALUES (?, ?, ?, CURRENT_TIMESTAMP) | |
| """, (user_id, username, email)) | |
| conn.commit() | |
| logger.info(f"โ ์ฌ์ฉ์ ์ถ๊ฐ ์๋ฃ: {user_id}") | |
| return True | |
| except Exception as e: | |
| logger.error(f"โ ์ฌ์ฉ์ ์ถ๊ฐ ์คํจ: {e}") | |
| return False | |
| def get_user(self, user_id: str) -> Optional[Dict[str, Any]]: | |
| """์ฌ์ฉ์ ์ ๋ณด ์กฐํ""" | |
| try: | |
| with sqlite3.connect(self.db_path) as conn: | |
| cursor = conn.cursor() | |
| cursor.execute("SELECT * FROM users WHERE user_id = ?", (user_id,)) | |
| row = cursor.fetchone() | |
| if row: | |
| columns = [description[0] for description in cursor.description] | |
| return dict(zip(columns, row)) | |
| return None | |
| except Exception as e: | |
| logger.error(f"โ ์ฌ์ฉ์ ์กฐํ ์คํจ: {e}") | |
| return None | |
| def create_chat_session(self, user_id: str, session_name: str = None) -> Optional[str]: | |
| """์ฑํ ์ธ์ ์์ฑ""" | |
| try: | |
| session_id = f"session_{user_id}_{datetime.now().strftime('%Y%m%d_%H%M%S')}" | |
| with sqlite3.connect(self.db_path) as conn: | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| INSERT INTO chat_sessions (session_id, user_id, session_name, last_activity) | |
| VALUES (?, ?, ?, CURRENT_TIMESTAMP) | |
| """, (session_id, user_id, session_name)) | |
| conn.commit() | |
| logger.info(f"โ ์ฑํ ์ธ์ ์์ฑ ์๋ฃ: {session_id}") | |
| return session_id | |
| except Exception as e: | |
| logger.error(f"โ ์ฑํ ์ธ์ ์์ฑ ์คํจ: {e}") | |
| return None | |
| def add_chat_message(self, session_id: str, user_id: str, message_type: str, | |
| content: str, metadata: Dict[str, Any] = None) -> bool: | |
| """์ฑํ ๋ฉ์์ง ์ถ๊ฐ""" | |
| try: | |
| with sqlite3.connect(self.db_path) as conn: | |
| cursor = conn.cursor() | |
| # ๋ฉ์์ง ์ถ๊ฐ | |
| cursor.execute(""" | |
| INSERT INTO chat_messages (session_id, user_id, message_type, content, metadata) | |
| VALUES (?, ?, ?, ?, ?) | |
| """, (session_id, user_id, message_type, content, | |
| json.dumps(metadata) if metadata else None)) | |
| # ์ธ์ ํ๋ ์๊ฐ ์ ๋ฐ์ดํธ | |
| cursor.execute(""" | |
| UPDATE chat_sessions SET last_activity = CURRENT_TIMESTAMP | |
| WHERE session_id = ? | |
| """, (session_id,)) | |
| conn.commit() | |
| logger.info(f"โ ๋ฉ์์ง ์ถ๊ฐ ์๋ฃ: {message_type}") | |
| return True | |
| except Exception as e: | |
| logger.error(f"โ ๋ฉ์์ง ์ถ๊ฐ ์คํจ: {e}") | |
| return False | |
| def get_chat_history(self, session_id: str, limit: int = 50) -> List[Dict[str, Any]]: | |
| """์ฑํ ํ์คํ ๋ฆฌ ์กฐํ""" | |
| try: | |
| with sqlite3.connect(self.db_path) as conn: | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| SELECT * FROM chat_messages | |
| WHERE session_id = ? | |
| ORDER BY timestamp DESC | |
| LIMIT ? | |
| """, (session_id, limit)) | |
| rows = cursor.fetchall() | |
| columns = [description[0] for description in cursor.description] | |
| messages = [] | |
| for row in reversed(rows): # ์๊ฐ์์ผ๋ก ์ ๋ ฌ | |
| message = dict(zip(columns, row)) | |
| if message['metadata']: | |
| message['metadata'] = json.loads(message['metadata']) | |
| messages.append(message) | |
| return messages | |
| except Exception as e: | |
| logger.error(f"โ ์ฑํ ํ์คํ ๋ฆฌ ์กฐํ ์คํจ: {e}") | |
| return [] | |
| def add_document_record(self, document_id: str, user_id: str, filename: str, | |
| file_type: str, file_size: int, metadata: Dict[str, Any] = None) -> bool: | |
| """๋ฌธ์ ์ ๋ณด ์ถ๊ฐ""" | |
| try: | |
| with sqlite3.connect(self.db_path) as conn: | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| INSERT INTO documents (document_id, user_id, filename, file_type, file_size, metadata) | |
| VALUES (?, ?, ?, ?, ?, ?) | |
| """, (document_id, user_id, filename, file_type, file_size, | |
| json.dumps(metadata) if metadata else None)) | |
| conn.commit() | |
| logger.info(f"โ ๋ฌธ์ ์ ๋ณด ์ถ๊ฐ ์๋ฃ: {document_id}") | |
| return True | |
| except Exception as e: | |
| logger.error(f"โ ๋ฌธ์ ์ ๋ณด ์ถ๊ฐ ์คํจ: {e}") | |
| return False | |
| def add_rag_query(self, user_id: str, document_id: str, query_text: str, | |
| response_text: str, processing_time: float, search_results: int, | |
| query_type: str = 'text') -> bool: | |
| """RAG ์ฟผ๋ฆฌ ํ์คํ ๋ฆฌ ์ถ๊ฐ""" | |
| try: | |
| with sqlite3.connect(self.db_path) as conn: | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| INSERT INTO rag_queries (user_id, document_id, query_text, response_text, | |
| processing_time, search_results, query_type) | |
| VALUES (?, ?, ?, ?, ?, ?, ?) | |
| """, (user_id, document_id, query_text, response_text, | |
| processing_time, search_results, query_type)) | |
| conn.commit() | |
| logger.info(f"โ RAG ์ฟผ๋ฆฌ ํ์คํ ๋ฆฌ ์ถ๊ฐ ์๋ฃ") | |
| return True | |
| except Exception as e: | |
| logger.error(f"โ RAG ์ฟผ๋ฆฌ ํ์คํ ๋ฆฌ ์ถ๊ฐ ์คํจ: {e}") | |
| return False | |
| def get_user_documents(self, user_id: str) -> List[Dict[str, Any]]: | |
| """์ฌ์ฉ์์ ๋ฌธ์ ๋ชฉ๋ก ์กฐํ""" | |
| try: | |
| with sqlite3.connect(self.db_path) as conn: | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| SELECT * FROM documents | |
| WHERE user_id = ? AND is_active = TRUE | |
| ORDER BY upload_date DESC | |
| """, (user_id,)) | |
| rows = cursor.fetchall() | |
| columns = [description[0] for description in cursor.description] | |
| documents = [] | |
| for row in rows: | |
| doc = dict(zip(columns, row)) | |
| if doc['metadata']: | |
| doc['metadata'] = json.loads(doc['metadata']) | |
| documents.append(doc) | |
| return documents | |
| except Exception as e: | |
| logger.error(f"โ ์ฌ์ฉ์ ๋ฌธ์ ๋ชฉ๋ก ์กฐํ ์คํจ: {e}") | |
| return [] | |
| def get_user_sessions(self, user_id: str) -> List[Dict[str, Any]]: | |
| """์ฌ์ฉ์์ ์ฑํ ์ธ์ ๋ชฉ๋ก ์กฐํ""" | |
| try: | |
| with sqlite3.connect(self.db_path) as conn: | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| SELECT * FROM chat_sessions | |
| WHERE user_id = ? AND is_active = TRUE | |
| ORDER BY last_activity DESC | |
| """, (user_id,)) | |
| rows = cursor.fetchall() | |
| columns = [description[0] for description in cursor.description] | |
| sessions = [] | |
| for row in rows: | |
| sessions.append(dict(zip(columns, row))) | |
| return sessions | |
| except Exception as e: | |
| logger.error(f"โ ์ฌ์ฉ์ ์ธ์ ๋ชฉ๋ก ์กฐํ ์คํจ: {e}") | |
| return [] | |
| # ์ ์ญ ์ธ์คํด์ค | |
| db_manager = DatabaseManager() |