From b737cdba4f18c5405a66ea62c0fdbcffab81430b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=84=B8=EB=B9=88=20=EA=B6=8C?= Date: Tue, 10 Feb 2026 17:36:05 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EB=B0=B1=EC=97=94=EB=93=9C=20api=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=8C=80=EC=9D=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/.gitignore | 10 +++++++ .idea/_AI.iml | 14 +++++++++ .idea/inspectionProfiles/Project_Default.xml | 7 +++++ .../inspectionProfiles/profiles_settings.xml | 6 ++++ .idea/misc.xml | 4 +++ .idea/modules.xml | 8 +++++ .idea/vcs.xml | 6 ++++ app/pipeline/analysis_pipeline.py | 11 ------- app/schemas/request.py | 29 ++++++++++++++++--- 9 files changed, 80 insertions(+), 15 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/_AI.iml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..0a8642f --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,10 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Zeppelin ignored files +/ZeppelinRemoteNotebooks/ diff --git a/.idea/_AI.iml b/.idea/_AI.iml new file mode 100644 index 0000000..f5cf686 --- /dev/null +++ b/.idea/_AI.iml @@ -0,0 +1,14 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..4f33453 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..bd13592 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..cff07f0 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/pipeline/analysis_pipeline.py b/app/pipeline/analysis_pipeline.py index 5b85d38..e92bbc3 100644 --- a/app/pipeline/analysis_pipeline.py +++ b/app/pipeline/analysis_pipeline.py @@ -52,29 +52,20 @@ def run_analysis_pipeline(payload: AnalyzeRequest) -> Dict[str, object]: for message in conversation if message.sender.strip().upper() == "OTHER" and message.content.strip() ] - logger.info( - "Pipeline start: %d turns (other=%d)", - len(conversation), - len(other_contents), - ) # 1. 입력에서 대화 유형 수신 (유형별 신호 범위 결정을 위함) conversation_type = payload.type - logger.info("Step 1 conversation_type(from input): %s", conversation_type) # 2. 규칙 기반 신호 추출 (유형 기반 + 공통 신호) (위험 신호 후보 추출) allowed_signals = resolve_risk_signals(conversation_type) rule_signals = analyze_conversation(other_contents, allowed_signals=allowed_signals) - logger.info("Step 2 signals: %s", rule_signals) # 3. RAG 쿼리 보강 (근거 자료 확보를 위한 검색 품질 향상) signal_terms = signal_query_terms(rule_signals) matched_phrases = extract_signal_phrases(other_contents, allowed_signals=allowed_signals) - logger.info("Step 3 query_terms=%s matched_phrases=%s", signal_terms, matched_phrases) # 4. 결정 오케스트레이터 (위험 단계 산출) risk_stage = decide_risk_stage(rule_signals) - logger.info("Step 4 risk_stage: %s", risk_stage) # 5. RAG 검색 (근거 자료 확보) retrieval_request = RetrievalRequest( @@ -85,7 +76,6 @@ def run_analysis_pipeline(payload: AnalyzeRequest) -> Dict[str, object]: matched_phrases=matched_phrases, ) references = retrieve_evidence(retrieval_request) - logger.info("Step 5 references: %d", len(references)) # 6. 안전 행동 생성 (LLM: references + 대화 발췌 사용) (최종 응답 생성) conversation_lines = _build_conversation_excerpt( @@ -94,7 +84,6 @@ def run_analysis_pipeline(payload: AnalyzeRequest) -> Dict[str, object]: safe_actions = generate_safe_actions( risk_stage, conversation_type, references, conversation_lines, payload.platform ) - logger.info("Step 6 safe_actions generated") rag_references = [ {"source": reference.source, "summary": reference.note} for reference in references diff --git a/app/schemas/request.py b/app/schemas/request.py index b4af952..5e98e80 100644 --- a/app/schemas/request.py +++ b/app/schemas/request.py @@ -1,7 +1,7 @@ from datetime import datetime -from typing import List, Literal +from typing import List, Literal, Optional -from pydantic import BaseModel, Field +from pydantic import BaseModel, Field, field_validator class Message(BaseModel): @@ -11,6 +11,20 @@ class Message(BaseModel): content: str = Field(..., description="Message content") sender: str = Field(..., description="Message sender (e.g. ME, OTHER)") timestamp: datetime = Field(..., description="Message timestamp in ISO 8601") + + @field_validator("type", mode="before") + @classmethod + def uppercase_type(cls, v): + if isinstance(v, str): + return v.upper() + return v + + @field_validator("sender", mode="before") + @classmethod + def uppercase_sender(cls, v): + if isinstance(v, str): + return v.upper() + return v class AnalyzeRequest(BaseModel): @@ -19,9 +33,16 @@ class AnalyzeRequest(BaseModel): platform: Literal["INSTAGRAM", "TELEGRAM"] = Field( ..., description="Platform name (INSTAGRAM or TELEGRAM)" ) - type: Literal["구직", "중고거래", "재테크", "부업"] = Field( - ..., description="Conversation type (구직, 중고거래, 재테크, 부업)" + type: Optional[Literal["구직", "중고거래", "재테크", "부업"]] = Field( + None, description="Conversation type (구직, 중고거래, 재테크, 부업)" ) + + @field_validator("platform", mode="before") + @classmethod + def uppercase_platform(cls, v): + if isinstance(v, str): + return v.upper() + return v class ReportRequest(BaseModel):