gbrabbit's picture
Fresh start for HF Spaces deployment
526927a
#!/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()