Spaces:
No application file
No application file
""" | |
RAG ๊ฒ์ ์ฑ๋ด ์น ์ ํ๋ฆฌ์ผ์ด์ (์ธ์ ์ค์ ์์ ์ ์ฉ ๋ฐ TypeError ํด๊ฒฐ) | |
""" | |
import os | |
import json | |
import logging | |
import tempfile | |
import threading | |
import datetime | |
import time # ์ถ๊ฐ | |
from flask import Flask, request, jsonify, render_template, send_from_directory, session, redirect, url_for | |
from werkzeug.utils import secure_filename | |
from dotenv import load_dotenv | |
from functools import wraps | |
# ๋ก๊ฑฐ ์ค์ | |
logging.basicConfig( | |
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', | |
level=logging.DEBUG | |
) | |
logger = logging.getLogger(__name__) | |
# ํ๊ฒฝ ๋ณ์ ๋ก๋ | |
load_dotenv() | |
# ํ๊ฒฝ ๋ณ์ ๋ก๋ ์ํ ํ์ธ ๋ฐ ๋ก๊น | |
ADMIN_USERNAME = os.getenv('ADMIN_USERNAME') | |
ADMIN_PASSWORD = os.getenv('ADMIN_PASSWORD') | |
DEVICE_SERVER_URL = os.getenv('DEVICE_SERVER_URL', '') | |
logger.info(f"==== ํ๊ฒฝ ๋ณ์ ๋ก๋ ์ํ ====") | |
logger.info(f"ADMIN_USERNAME ์ค์ ์ฌ๋ถ: {ADMIN_USERNAME is not None}") | |
logger.info(f"ADMIN_PASSWORD ์ค์ ์ฌ๋ถ: {ADMIN_PASSWORD is not None}") | |
logger.info(f"DEVICE_SERVER_URL: {DEVICE_SERVER_URL or '์ค์ ๋์ง ์์ (ํ๋ก ํธ์๋์์ ์๋ ์ค์ )'}") | |
# ํ๊ฒฝ ๋ณ์๊ฐ ์์ผ๋ฉด ๊ธฐ๋ณธ๊ฐ ์ค์ | |
if not ADMIN_USERNAME: | |
ADMIN_USERNAME = 'admin' | |
logger.warning("ADMIN_USERNAME ํ๊ฒฝ๋ณ์๊ฐ ์์ด ๊ธฐ๋ณธ๊ฐ 'admin'์ผ๋ก ์ค์ ํฉ๋๋ค.") | |
if not ADMIN_PASSWORD: | |
ADMIN_PASSWORD = 'rag12345' | |
logger.warning("ADMIN_PASSWORD ํ๊ฒฝ๋ณ์๊ฐ ์์ด ๊ธฐ๋ณธ๊ฐ 'rag12345'๋ก ์ค์ ํฉ๋๋ค.") | |
# --- ๋ก์ปฌ ๋ชจ๋ ์ํฌํธ --- | |
# MockComponent ์ ์ (์ํฌํธ ์คํจ ์ ๋์ฒด) | |
class MockComponent: | |
def __init__(self): | |
self.is_mock = True | |
def search(self, query, top_k=5, first_stage_k=None): | |
"""๋น ๊ฒ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํฉ๋๋ค.""" | |
logger.warning(f"MockComponent.search ํธ์ถ๋จ (์ฟผ๋ฆฌ: {query[:30]}...)") | |
return [] | |
def __getattr__(self, name): | |
# Mock ๊ฐ์ฒด์ ์ด๋ค ์์ฑ์ด๋ ๋ฉ์๋ ํธ์ถ ์ ๊ฒฝ๊ณ ๋ก๊ทธ ์ถ๋ ฅ ๋ฐ ๊ธฐ๋ณธ๊ฐ ๋ฐํ | |
logger.warning(f"MockComponent์์ '{name}' ์ ๊ทผ ์๋๋จ (์ค์ ๋ชจ๋ ๋ก๋ ์คํจ)") | |
# ๋ฉ์๋ ํธ์ถ ์์๋ ์๋ฌด๊ฒ๋ ์ ํ๋ ํจ์ ๋ฐํ | |
if name in ['add_documents', 'save', 'transcribe_audio', 'rag_generate', 'set_llm', 'get_current_llm_details', 'prepare_rag_context', 'csv_to_documents', 'text_to_documents', 'load_documents_from_directory']: | |
return lambda *args, **kwargs: logger.warning(f"Mocked method '{name}' called") or None | |
# ์์ฑ ์ ๊ทผ ์์๋ None ๋ฐํ | |
return None | |
try: | |
from utils.vito_stt import VitoSTT | |
from utils.llm_interface import LLMInterface | |
from utils.document_processor import DocumentProcessor | |
from retrieval.vector_retriever import VectorRetriever | |
from retrieval.reranker import ReRanker | |
from app.app_routes import register_routes | |
from app.app_device_routes import register_device_routes | |
MODULE_LOAD_SUCCESS = True | |
except ImportError as e: | |
logger.error(f"๋ก์ปฌ ๋ชจ๋ ์ํฌํธ ์คํจ: {e}. Mock ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํฉ๋๋ค.") | |
VitoSTT = LLMInterface = DocumentProcessor = VectorRetriever = ReRanker = MockComponent | |
# register_routes, register_device_routes๋ ์ํฌํธ ์คํจ ์ ์ ์๋์ง ์์ผ๋ฏ๋ก ์๋์์ ์ฒ๋ฆฌ | |
MODULE_LOAD_SUCCESS = False | |
# ์์๋ก ๋น ํจ์ ์ ์ (์ฑ ์คํ์ ๋๋๋ก) | |
def register_routes(*args, **kwargs): logger.error("register_routes ์ํฌํธ ์คํจ") | |
def register_device_routes(*args, **kwargs): logger.error("register_device_routes ์ํฌํธ ์คํจ") | |
# --- ๋ก์ปฌ ๋ชจ๋ ์ํฌํธ ๋ --- | |
# Flask ์ฑ ์ด๊ธฐํ | |
app = Flask(__name__) | |
# ์ธ์ ์ค์ | |
app.secret_key = os.getenv('FLASK_SECRET_KEY', 'rag_chatbot_fixed_secret_key_12345') | |
app.config['SESSION_COOKIE_SECURE'] = True | |
app.config['SESSION_COOKIE_HTTPONLY'] = True | |
app.config['SESSION_COOKIE_SAMESITE'] = 'None' | |
app.config['SESSION_COOKIE_DOMAIN'] = None | |
app.config['SESSION_COOKIE_PATH'] = '/' | |
app.config['PERMANENT_SESSION_LIFETIME'] = datetime.timedelta(days=1) | |
# ์ต๋ ํ์ผ ํฌ๊ธฐ ์ค์ (10MB) | |
app.config['MAX_CONTENT_LENGTH'] = 10 * 1024 * 1024 | |
# ์ ํ๋ฆฌ์ผ์ด์ ํ์ผ ๊ธฐ์ค ์๋ ๊ฒฝ๋ก ์ค์ | |
APP_ROOT = os.path.dirname(os.path.abspath(__file__)) | |
# static ํด๋ ๊ฒฝ๋ก ์์ (app ํด๋ ๋ด๋ถ์ static) | |
app.config['STATIC_FOLDER'] = os.path.join(APP_ROOT, 'static') | |
app.config['UPLOAD_FOLDER'] = os.path.join(APP_ROOT, 'uploads') | |
# data ๋ฐ index ๊ฒฝ๋ก๋ app ํด๋ ์ธ๋ถ๋ก ์ค์ (ํ๋ก์ ํธ ๋ฃจํธ ๊ธฐ์ค) | |
app.config['DATA_FOLDER'] = os.path.join(os.path.dirname(APP_ROOT), 'data') | |
app.config['INDEX_PATH'] = os.path.join(os.path.dirname(APP_ROOT), 'data', 'index') | |
# ํ์ํ ํด๋ ์์ฑ | |
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True) | |
os.makedirs(app.config['DATA_FOLDER'], exist_ok=True) | |
os.makedirs(app.config['INDEX_PATH'], exist_ok=True) | |
# ํ์ฉ๋๋ ์ค๋์ค/๋ฌธ์ ํ์ผ ํ์ฅ์ | |
ALLOWED_AUDIO_EXTENSIONS = {'mp3', 'wav', 'ogg', 'm4a'} | |
ALLOWED_DOC_EXTENSIONS = {'txt', 'md', 'pdf', 'docx', 'csv'} | |
# --- ์ ์ญ ๊ฐ์ฒด ์ด๊ธฐํ --- | |
llm_interface = None | |
stt_client = None | |
base_retriever = None | |
retriever = None | |
# app_ready ํ๋๊ทธ ๋์ threading.Event ์ฌ์ฉ | |
app_ready_event = threading.Event() # ์ด๊ธฐ ์ํ: False (set() ํธ์ถ ์ ๊น์ง) | |
# --- ์ ์ญ ๊ฐ์ฒด ์ด๊ธฐํ (try-except๋ก ๊ฐ์ธ๊ธฐ) --- | |
try: | |
if MODULE_LOAD_SUCCESS: # ๋ชจ๋ ๋ก๋ ์ฑ๊ณต ์์๋ง ์ค์ ์ด๊ธฐํ ์๋ | |
llm_interface = LLMInterface(default_llm="openai") | |
stt_client = VitoSTT() | |
else: # ์คํจ ์ Mock ๊ฐ์ฒด ์ฌ์ฉ | |
llm_interface = LLMInterface() # MockComponent | |
stt_client = VitoSTT() # MockComponent | |
except Exception as e: | |
logger.error(f"LLM ๋๋ STT ์ธํฐํ์ด์ค ์ด๊ธฐํ ์ค ์ค๋ฅ ๋ฐ์: {e}", exc_info=True) | |
llm_interface = MockComponent() # ์ค๋ฅ ์ Mock ๊ฐ์ฒด ํ ๋น | |
stt_client = MockComponent() # ์ค๋ฅ ์ Mock ๊ฐ์ฒด ํ ๋น | |
# --- ์ธ์ฆ ๋ฐ์ฝ๋ ์ดํฐ --- | |
def login_required(f): | |
def decorated_function(*args, **kwargs): | |
logger.info(f"----------- ์ธ์ฆ ํ์ ํ์ด์ง ์ ๊ทผ ์๋: {request.path} -----------") | |
logger.debug(f"ํ์ฌ ํ๋ผ์คํฌ ์ธ์ ๊ฐ์ฒด: {session}") # DEBUG ๋ ๋ฒจ๋ก ๋ณ๊ฒฝ | |
logger.info(f"ํ์ฌ ์ธ์ ์ํ: logged_in={session.get('logged_in', False)}, username={session.get('username', 'None')}") | |
logger.debug(f"์์ฒญ์ ์ธ์ ์ฟ ํค ๊ฐ: {request.cookies.get('session', 'None')}") # DEBUG ๋ ๋ฒจ๋ก ๋ณ๊ฒฝ | |
if not session.get('logged_in'): # .get() ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ์์ | |
logger.warning(f"์ธ์ ์ 'logged_in' ์์ ๋๋ False. ๋ก๊ทธ์ธ ํ์ด์ง๋ก ๋ฆฌ๋๋ ์ .") | |
return redirect(url_for('login', next=request.url)) | |
logger.info(f"์ธ์ฆ ์ฑ๊ณต: {session.get('username', 'unknown')} ์ฌ์ฉ์๊ฐ {request.path} ์ ๊ทผ") | |
return f(*args, **kwargs) | |
return decorated_function | |
# --- ์ธ์ฆ ๋ฐ์ฝ๋ ์ดํฐ ๋ --- | |
# --- ํฌํผ ํจ์ (app_routes.py์๋ ์์ง๋ง ์ฌ๊ธฐ์๋ ํ์ํ ์ ์์) --- | |
def allowed_audio_file(filename): | |
"""ํ์ผ์ด ํ์ฉ๋ ์ค๋์ค ํ์ฅ์๋ฅผ ๊ฐ์ง๋์ง ํ์ธ""" | |
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_AUDIO_EXTENSIONS | |
def allowed_doc_file(filename): | |
"""ํ์ผ์ด ํ์ฉ๋ ๋ฌธ์ ํ์ฅ์๋ฅผ ๊ฐ์ง๋์ง ํ์ธ""" | |
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_DOC_EXTENSIONS | |
# --- ํฌํผ ํจ์ ๋ --- | |
# --- ๊ฒ์๊ธฐ ์ด๊ธฐํ ๊ด๋ จ ํจ์ --- | |
def init_retriever(): | |
"""๊ฒ์๊ธฐ ๊ฐ์ฒด ์ด๊ธฐํ ๋๋ ๋ก๋""" | |
global base_retriever, retriever | |
# ๋ชจ๋ ๋ก๋ ์คํจ ์ Mock ๊ฐ์ฒด ๋ฐํ | |
if not MODULE_LOAD_SUCCESS: | |
logger.warning("ํ์ ๋ชจ๋ ๋ก๋ ์คํจ๋ก Mock ๊ฒ์๊ธฐ ๋ฐํ") | |
base_retriever = VectorRetriever() # MockComponent | |
retriever = ReRanker() # MockComponent | |
return retriever | |
index_path = app.config['INDEX_PATH'] | |
data_path = app.config['DATA_FOLDER'] | |
logger.info("--- init_retriever ์์ ---") | |
# 1. ๊ธฐ๋ณธ ๊ฒ์๊ธฐ ๋ก๋ ๋๋ ์ด๊ธฐํ | |
try: | |
if os.path.exists(os.path.join(index_path, "documents.json")): # ์ ์ฅ ๋ฐฉ์์ ๋ฐ๋ผ ํ์ธ ํ์ผ ๋ณ๊ฒฝ ํ์ | |
logger.info(f"์ธ๋ฑ์ค ๋ก๋ ์๋: {index_path}") | |
base_retriever = VectorRetriever.load(index_path) | |
logger.info(f"์ธ๋ฑ์ค ๋ก๋ ์ฑ๊ณต. ๋ฌธ์ {len(getattr(base_retriever, 'documents', []))}๊ฐ") | |
else: | |
logger.info("์ธ๋ฑ์ค ํ์ผ ์์. ์ VectorRetriever ์ด๊ธฐํ ์๋...") | |
base_retriever = VectorRetriever() | |
logger.info("์ VectorRetriever ์ด๊ธฐํ ์ฑ๊ณต.") | |
except Exception as e: | |
logger.error(f"๊ธฐ๋ณธ ๊ฒ์๊ธฐ ์ด๊ธฐํ/๋ก๋ ์คํจ: {e}", exc_info=True) | |
base_retriever = MockComponent() # ์คํจ ์ Mock ์ฌ์ฉ | |
retriever = MockComponent() | |
logger.info("Mock ๊ฒ์๊ธฐ๋ฅผ ๋์ฒด๋ก ์ฌ์ฉํฉ๋๋ค.") | |
return retriever # ์ด๊ธฐํ ์คํจํด๋ Mock ๊ฒ์๊ธฐ ๋ฐํ (None ๋์ ) | |
# 2. ๋ฐ์ดํฐ ํด๋ ๋ฌธ์ ๋ก๋ (๊ธฐ๋ณธ ๊ฒ์๊ธฐ๊ฐ ๋น์ด์์ ๋) | |
needs_loading = not hasattr(base_retriever, 'documents') or not getattr(base_retriever, 'documents', []) | |
if needs_loading and os.path.exists(data_path): | |
logger.info(f"๊ธฐ๋ณธ ๊ฒ์๊ธฐ๊ฐ ๋น์ด์์ด {data_path}์์ ๋ฌธ์ ๋ก๋ ์๋...") | |
try: | |
# DocumentProcessor.load_documents_from_directory ํธ์ถ ํ์ธ | |
if hasattr(DocumentProcessor, 'load_documents_from_directory'): | |
docs = DocumentProcessor.load_documents_from_directory( | |
directory=data_path, | |
extensions=[".txt", ".md", ".csv"], | |
recursive=True | |
) | |
logger.info(f"{len(docs)}๊ฐ ๋ฌธ์ ๋ก๋ ์ฑ๊ณต.") | |
if docs and hasattr(base_retriever, 'add_documents'): | |
logger.info("๊ฒ์๊ธฐ์ ๋ฌธ์ ์ถ๊ฐ ์๋...") | |
base_retriever.add_documents(docs) | |
logger.info("๋ฌธ์ ์ถ๊ฐ ์๋ฃ.") | |
if hasattr(base_retriever, 'save'): | |
logger.info(f"๊ฒ์๊ธฐ ์ํ ์ ์ฅ ์๋: {index_path}") | |
try: | |
base_retriever.save(index_path) | |
logger.info("์ธ๋ฑ์ค ์ ์ฅ ์๋ฃ.") | |
except Exception as e_save: | |
logger.error(f"์ธ๋ฑ์ค ์ ์ฅ ์คํจ: {e_save}", exc_info=True) | |
else: | |
logger.warning("DocumentProcessor์ load_documents_from_directory ๋ฉ์๋๊ฐ ์์ต๋๋ค.") | |
except Exception as e_load_add: | |
logger.error(f"DATA_FOLDER ๋ฌธ์ ๋ก๋/์ถ๊ฐ ์ค ์ค๋ฅ: {e_load_add}", exc_info=True) | |
# 3. ์ฌ์์ํ ๊ฒ์๊ธฐ ์ด๊ธฐํ | |
logger.info("์ฌ์์ํ ๊ฒ์๊ธฐ ์ด๊ธฐํ ์๋...") | |
try: | |
# custom_rerank_fn ์ ์ | |
def custom_rerank_fn(query, results): | |
# ์ด ํจ์๋ ์ค์ ์ฌ์์ํ ๋ก์ง์ ๋ง๊ฒ ๊ตฌํ ํ์ | |
# ์์: ๋จ์ํ score ๊ธฐ์ค์ผ๋ก ์ ๋ ฌ | |
results.sort(key=lambda x: x.get("score", 0) if isinstance(x, dict) else 0, reverse=True) | |
return results | |
# ReRanker ํด๋์ค ์ฌ์ฉ | |
retriever = ReRanker( | |
base_retriever=base_retriever, | |
rerank_fn=custom_rerank_fn, | |
rerank_field="text" # ์ฌ์์ํ์ ์ฌ์ฉํ ํ๋ (ํ์์) | |
) | |
logger.info("์ฌ์์ํ ๊ฒ์๊ธฐ ์ด๊ธฐํ ์๋ฃ.") | |
except Exception as e_rerank: | |
logger.error(f"์ฌ์์ํ ๊ฒ์๊ธฐ ์ด๊ธฐํ ์คํจ: {e_rerank}", exc_info=True) | |
logger.warning("์ฌ์์ํ ์คํจ, ๊ธฐ๋ณธ ๊ฒ์๊ธฐ๋ฅผ retriever๋ก ์ฌ์ฉํฉ๋๋ค.") | |
retriever = base_retriever # fallback | |
logger.info("--- init_retriever ์ข ๋ฃ ---") | |
return retriever | |
# --- ๋ฐฑ๊ทธ๋ผ์ด๋ ์ด๊ธฐํ --- | |
def background_init(): | |
"""๋ฐฑ๊ทธ๋ผ์ด๋์์ ๊ฒ์๊ธฐ ๋ฐ ๊ธฐํ ์ปดํฌ๋ํธ ์ด๊ธฐํ ์ํ""" | |
global retriever, base_retriever, llm_interface, stt_client, app_ready_event | |
logger.info("๋ฐฑ๊ทธ๋ผ์ด๋ ์ด๊ธฐํ ์์...") | |
start_init_time = time.time() | |
try: | |
# 1. LLM, STT ์ธํฐํ์ด์ค ์ฌํ์ธ (์ด๋ฏธ ์ด๊ธฐํ ์๋๋จ) | |
if llm_interface is None or isinstance(llm_interface, MockComponent): | |
logger.warning("LLM ์ธํฐํ์ด์ค๊ฐ ์ด๊ธฐํ๋์ง ์์๊ฑฐ๋ Mock ๊ฐ์ฒด์ ๋๋ค.") | |
# ํ์์ ์ฌ๊ธฐ์ ๋ค์ ์ด๊ธฐํ ์๋ ๊ฐ๋ฅ | |
if stt_client is None or isinstance(stt_client, MockComponent): | |
logger.warning("STT ํด๋ผ์ด์ธํธ๊ฐ ์ด๊ธฐํ๋์ง ์์๊ฑฐ๋ Mock ๊ฐ์ฒด์ ๋๋ค.") | |
# 2. ๊ฒ์๊ธฐ ์ด๊ธฐํ | |
logger.info("๊ฒ์๊ธฐ ์ด๊ธฐํ ์๋ (background)...") | |
retriever = init_retriever() # init_retriever๊ฐ base_retriever๋ ์ค์ | |
# ์ฑ๊ณต ์ฌ๋ถ ํ์ธ - retriever๊ฐ None์ด ์๋๋ฉด ์ฑ๊ณต์ผ๋ก ๊ฐ์ฃผ | |
if retriever is not None: | |
if not isinstance(retriever, MockComponent): | |
logger.info("๊ฒ์๊ธฐ ์ด๊ธฐํ ์ฑ๊ณต (background)") | |
else: | |
logger.warning("Mock ๊ฒ์๊ธฐ๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ผ๋ถ ๊ธฐ๋ฅ์ด ์ ํ๋ ์ ์์ต๋๋ค.") | |
# ์ค์: ๊ฒ์๊ธฐ๊ฐ Mock ๊ฐ์ฒด์ด๋๋ผ๋ app_ready_event.set()์ ํธ์ถํ์ฌ ๋ก๋ฉ ์ํ๋ฅผ ์ข ๋ฃํฉ๋๋ค. | |
app_ready_event.set() | |
logger.info("app_ready_event๊ฐ True๋ก ์ค์ ๋จ.") | |
else: | |
logger.error("๊ฒ์๊ธฐ ์ด๊ธฐํ ์คํจ (background)") | |
# ์ค์ ์์ : ์คํจ ์์๋ app_ready_event๋ฅผ ์ค์ ํ์ฌ ๋ก๋ฉ ํ์ด์ง์์ ๋ฒ์ด๋ ์ ์๋๋ก ํจ | |
# ์ด๋ ๊ฒ ํ๋ฉด ์ฑ ์์ฒด๋ ์คํ๋์ด ์ฌ์ฉ ๊ฐ๋ฅํ ์ํ๊ฐ ๋จ | |
app_ready_event.set() | |
logger.warning("๊ฒ์๊ธฐ ์ด๊ธฐํ ์คํจํ์ง๋ง app_ready_event๋ฅผ True๋ก ์ค์ ํ์ฌ ์ฑ์ ์ฌ์ฉ ๊ฐ๋ฅํ ์ํ๋ก ๋ง๋ญ๋๋ค.") | |
except Exception as e: | |
logger.error(f"๋ฐฑ๊ทธ๋ผ์ด๋ ์ด๊ธฐํ ์ค ์ฌ๊ฐํ ์ค๋ฅ ๋ฐ์: {e}", exc_info=True) | |
# ์ค๋ฅ ๋ฐ์ ์์๋ Mock ๊ฐ์ฒด ํ ๋น ๋ฐ ์ํ ์ค์ ๊ณ ๋ ค | |
if base_retriever is None: base_retriever = MockComponent() | |
if retriever is None: retriever = MockComponent() | |
# ์ค์ ์์ : ์ค๋ฅ ๋ฐ์ ์์๋ app_ready_event๋ฅผ ์ค์ ํ์ฌ ๋ก๋ฉ ํ์ด์ง์์ ๋ฒ์ด๋ ์ ์๋๋ก ํจ | |
app_ready_event.set() | |
logger.warning("์ด๊ธฐํ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ง๋ง app_ready_event๋ฅผ True๋ก ์ค์ ํ์ฌ ์ฑ์ ์ฌ์ฉ ๊ฐ๋ฅํ ์ํ๋ก ๋ง๋ญ๋๋ค.") | |
finally: | |
end_init_time = time.time() | |
logger.info(f"๋ฐฑ๊ทธ๋ผ์ด๋ ์ด๊ธฐํ ์๋ฃ. ์์ ์๊ฐ: {end_init_time - start_init_time:.2f}์ด") | |
logger.info(f"์ต์ข ์ฑ ์ค๋น ์ํ (app_ready_event.is_set()): {app_ready_event.is_set()}") | |
# ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋ ์์ | |
init_thread = threading.Thread(target=background_init) | |
init_thread.daemon = True | |
init_thread.start() | |
# --- ๋ผ์ฐํธ ๋ฑ๋ก --- | |
try: | |
# ๊ธฐ๋ณธ RAG ์ฑ๋ด ๋ผ์ฐํธ ๋ฑ๋ก | |
register_routes( | |
app=app, | |
login_required=login_required, | |
llm_interface=llm_interface, | |
retriever=retriever, | |
stt_client=stt_client, | |
DocumentProcessor=DocumentProcessor, | |
base_retriever=base_retriever, | |
app_ready_event=app_ready_event, | |
ADMIN_USERNAME=ADMIN_USERNAME, | |
ADMIN_PASSWORD=ADMIN_PASSWORD, | |
DEVICE_SERVER_URL=DEVICE_SERVER_URL | |
) | |
logger.info("๊ธฐ๋ณธ ์ฑ๋ด ๋ผ์ฐํธ ๋ฑ๋ก ์๋ฃ") | |
# ์ฅ์น ๊ด๋ฆฌ ๋ผ์ฐํธ ๋ฑ๋ก | |
register_device_routes( | |
app=app, | |
login_required=login_required, | |
DEVICE_SERVER_URL=DEVICE_SERVER_URL | |
) | |
logger.info("์ฅ์น ๊ด๋ฆฌ ๋ผ์ฐํธ ๋ฑ๋ก ์๋ฃ") | |
except Exception as e: | |
# ๋ผ์ฐํธ ๋ฑ๋ก ์คํจ๋ ์ฌ๊ฐํ ๋ฌธ์ ์ด๋ฏ๋ก Critical ๋ ๋ฒจ ์ฌ์ฉ ๊ณ ๋ ค | |
logger.critical(f"๋ผ์ฐํธ ๋ฑ๋ก ์ค ์น๋ช ์ ์ค๋ฅ ๋ฐ์: {e}", exc_info=True) | |
# ์ฑ ์คํ์ ์ค๋จํ๊ฑฐ๋ ์ต์ํ์ ์ค๋ฅ ํ์ด์ง๋ฅผ ์ ๊ณตํ๋ ๋ก์ง ์ถ๊ฐ ๊ฐ๋ฅ | |
# --- ์ ์ ํ์ผ ์๋น --- | |
# STATIC_FOLDER ์ค์ ์ ์ฌ์ฉํ์ฌ static ํด๋ ๊ฒฝ๋ก ์ง์ | |
def send_static(path): | |
static_folder = app.config.get('STATIC_FOLDER', 'static') # ์ค์ ๊ฐ ๋๋ ๊ธฐ๋ณธ๊ฐ ์ฌ์ฉ | |
# logger.debug(f"Serving static file: {path} from {static_folder}") # ๋๋ฒ๊น ์ ์ฃผ์ ํด์ | |
return send_from_directory(static_folder, path) | |
# --- ์์ฒญ ์ฒ๋ฆฌ ํ --- | |
def after_request_func(response): | |
"""๋ชจ๋ ์๋ต์ ๋ํด ํ์ฒ๋ฆฌ ์ํ (์: ๋ณด์ ํค๋ ์ถ๊ฐ)""" | |
# ์์: response.headers['X-Content-Type-Options'] = 'nosniff' | |
return response | |
# ์ฑ ์คํ (๋ก์ปฌ ํ ์คํธ์ฉ) | |
if __name__ == '__main__': | |
logger.info("Flask ์ฑ์ ์ง์ ์คํํฉ๋๋ค (๊ฐ๋ฐ์ฉ ์๋ฒ).") | |
# port ๋ฒํธ๋ ํ๊ฒฝ ๋ณ์ ๋๋ ๊ธฐ๋ณธ๊ฐ์ ์ฌ์ฉํฉ๋๋ค. | |
port = int(os.environ.get("PORT", 7860)) # ๊ธฐ๋ณธ ํฌํธ 7860 ์ฌ์ฉ | |
logger.info(f"์๋ฒ๋ฅผ http://0.0.0.0:{port} ์์ ์์ํฉ๋๋ค.") | |
# debug=True๋ ๊ฐ๋ฐ ์ค์๋ง ์ฌ์ฉํ๊ณ , ๋ฐฐํฌ ์์๋ False๋ก ๋ณ๊ฒฝํ๊ฑฐ๋ ์ ๊ฑฐ | |
# use_reloader=False ์ถ๊ฐํ์ฌ ์๋ ๋ฆฌ๋ก๋ ๋นํ์ฑํ (๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋ ๋ฌธ์ ๋ฐฉ์ง) | |
app.run(debug=False, host='0.0.0.0', port=port, use_reloader=False) | |