Phase 28: P3 — Pydantic Settings, dependency-injector IoC, tenacity retry
- config.py: dataclasses → pydantic-settings BaseSettings (flat AppConfig, env vars auto-loaded from .env, type-safe validation) - api_client.py: HTTPAPIClient takes AppConfig directly (APIConfig removed); tenacity retry on 5 methods (reset/ingest/list/delete/feedback) — retries on 5xx + TransportError, 3 attempts, exponential backoff 1-8s - container.py: manual DI → dependency_injector DeclarativeContainer with providers.Singleton; Container() needs no args - app.py: container.X → container.X() calls, remove AppConfig import - requirements.txt: add pydantic-settings, tenacity, dependency-injector Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -23,10 +23,9 @@ logging.basicConfig(
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
from config import AppConfig
|
||||
from container import Container
|
||||
|
||||
container = Container(AppConfig())
|
||||
container = Container()
|
||||
|
||||
USER_LABELS = ["아록", "근혜", "도율", "하율"]
|
||||
DEFAULT_USER = "아록"
|
||||
@@ -39,7 +38,7 @@ def _get_whisper():
|
||||
global _whisper_model
|
||||
if _whisper_model is None:
|
||||
import whisper
|
||||
_whisper_model = whisper.load_model(container.config.whisper_model_size)
|
||||
_whisper_model = whisper.load_model(container.config().whisper_model_size)
|
||||
return _whisper_model
|
||||
|
||||
|
||||
@@ -71,7 +70,7 @@ async def respond(message, history, show_thinking, user_id, use_tts, run_ids):
|
||||
thinking_finalized = False
|
||||
|
||||
try:
|
||||
async for token, run_id in container.chat_service.chat(message, user_id, show_thinking):
|
||||
async for token, run_id in container.chat_service().chat(message, user_id, show_thinking):
|
||||
if run_id is not None:
|
||||
collected_run_id = run_id
|
||||
break
|
||||
@@ -120,7 +119,7 @@ async def respond(message, history, show_thinking, user_id, use_tts, run_ids):
|
||||
run_ids.append(collected_run_id)
|
||||
|
||||
if use_tts:
|
||||
audio_path = await container.tts_service.speak(tts_text)
|
||||
audio_path = await container.tts_service().speak(tts_text)
|
||||
yield history, "", audio_path, run_ids, gr.update(), gr.update()
|
||||
else:
|
||||
yield history, "", None, run_ids, gr.update(), gr.update()
|
||||
@@ -142,7 +141,7 @@ async def handle_feedback(like_data: gr.LikeData, history, run_ids, user_id):
|
||||
rating = 1 if like_data.liked else -1
|
||||
|
||||
try:
|
||||
await container.chat_service.save_feedback(user_id, user_msg, asst_msg, rating, run_id)
|
||||
await container.chat_service().save_feedback(user_id, user_msg, asst_msg, rating, run_id)
|
||||
except Exception as e:
|
||||
logger.error("피드백 저장 실패: %s", e)
|
||||
|
||||
@@ -153,7 +152,7 @@ def switch_user(user_id):
|
||||
|
||||
async def reset_chat(user_id):
|
||||
try:
|
||||
await container.chat_service.reset(user_id)
|
||||
await container.chat_service().reset(user_id)
|
||||
except Exception as e:
|
||||
logger.error("대화 초기화 실패: %s", e)
|
||||
return [], []
|
||||
@@ -168,7 +167,7 @@ async def ingest_files(files):
|
||||
results = []
|
||||
for path in paths:
|
||||
try:
|
||||
result = await container.document_service.ingest(path)
|
||||
result = await container.document_service().ingest(path)
|
||||
name = os.path.basename(path)
|
||||
results.append(f"{name} → {result.get('chunks', '?')}개 청크")
|
||||
except Exception as e:
|
||||
@@ -178,7 +177,7 @@ async def ingest_files(files):
|
||||
|
||||
async def list_docs():
|
||||
try:
|
||||
sources = await container.document_service.list_documents()
|
||||
sources = await container.document_service().list_documents()
|
||||
return [[os.path.basename(s), s] for s in sources]
|
||||
except Exception as e:
|
||||
return [[f"오류: {e}", ""]]
|
||||
@@ -188,7 +187,7 @@ async def delete_doc(source):
|
||||
if not source.strip():
|
||||
return "삭제할 파일 경로를 입력하세요.", await list_docs()
|
||||
try:
|
||||
await container.document_service.delete_document(source.strip())
|
||||
await container.document_service().delete_document(source.strip())
|
||||
return f"삭제 완료: {os.path.basename(source.strip())}", await list_docs()
|
||||
except Exception as e:
|
||||
return f"오류: {e}", await list_docs()
|
||||
@@ -365,7 +364,7 @@ with gr.Blocks(title="율봇") as demo:
|
||||
|
||||
if __name__ == "__main__":
|
||||
demo.launch(
|
||||
server_name=container.config.server_host,
|
||||
server_port=container.config.server_port,
|
||||
server_name=container.config().server_host,
|
||||
server_port=container.config().server_port,
|
||||
theme=gr.themes.Soft(),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user