diff --git a/app/services/summarizer.py b/app/services/summarizer.py index 061ed2a..f359f67 100644 --- a/app/services/summarizer.py +++ b/app/services/summarizer.py @@ -8,6 +8,24 @@ client = OpenAI(api_key=settings.openai_api_key) +def _to_text(value) -> str: + if value is None: + return "" + + if isinstance(value, str): + return value.strip() + + if isinstance(value, list): + return "\n".join(text for item in value if (text := _to_text(item))) + + if isinstance(value, dict): + return "\n".join( + f"{key}: {text}" for key, val in value.items() if (text := _to_text(val)) + ) + + return str(value) + + def summarize_notice(title: str, content: str) -> NoticeSummaryData: settings = get_settings() prompt = f""" @@ -39,9 +57,9 @@ def summarize_notice(title: str, content: str) -> NoticeSummaryData: payload = json.loads(response_text) return NoticeSummaryData( - summary=payload["summary"], - target_info=payload.get("target_info"), - schedule_info=payload.get("schedule_info"), - caution_info=payload.get("caution_info"), + summary=_to_text(payload.get("summary")), + target_info=_to_text(payload.get("target_info")), + schedule_info=_to_text(payload.get("schedule_info")), + caution_info=_to_text(payload.get("caution_info")), generated_model=response.model, ) diff --git a/tests/test_summarizer.py b/tests/test_summarizer.py new file mode 100644 index 0000000..7a388c9 --- /dev/null +++ b/tests/test_summarizer.py @@ -0,0 +1,41 @@ +import json +from types import SimpleNamespace + +from app.services import summarizer + + +def test_summarize_notice_normalizes_structured_llm_fields(monkeypatch) -> None: + payload = { + "summary": {"핵심": "생활관 소독 안내입니다."}, + "target_info": {"소독 대상": "전체 생활관"}, + "schedule_info": {"일시": "2026년 5월 8일 10시"}, + "caution_info": ["귀중품은 보관해 주세요.", "소독 시간에는 협조 바랍니다."], + } + + fake_response = SimpleNamespace( + choices=[ + SimpleNamespace( + message=SimpleNamespace(content=json.dumps(payload, ensure_ascii=False)) + ) + ], + model="fake-model", + ) + fake_client = SimpleNamespace( + chat=SimpleNamespace( + completions=SimpleNamespace(create=lambda **_kwargs: fake_response) + ) + ) + monkeypatch.setattr(summarizer, "client", fake_client) + + result = summarizer.summarize_notice("소독 안내", "생활관 소독을 진행합니다.") + + assert result.summary == "핵심: 생활관 소독 안내입니다." + assert result.target_info == "소독 대상: 전체 생활관" + assert result.schedule_info == "일시: 2026년 5월 8일 10시" + assert result.caution_info == "귀중품은 보관해 주세요.\n소독 시간에는 협조 바랍니다." + assert result.generated_model == "fake-model" + + +def test_to_text_omits_empty_nested_values() -> None: + assert summarizer._to_text(["A", None, " ", "B"]) == "A\nB" + assert summarizer._to_text({"대상": "전체", "비고": None, "공백": " "}) == "대상: 전체"