From d44eb03a6c9360dcc71ac4f66c46308a66e4d9b1 Mon Sep 17 00:00:00 2001 From: kimssirr Date: Wed, 6 May 2026 18:32:23 +0900 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=EA=B3=B5=EC=A7=80=20=EC=9A=94?= =?UTF-8?q?=EC=95=BD=20=ED=95=84=EB=93=9C=20=EB=AC=B8=EC=9E=90=EC=97=B4=20?= =?UTF-8?q?=EC=A0=95=EA=B7=9C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/services/summarizer.py | 24 ++++++++++++++++++++---- tests/test_summarizer.py | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 tests/test_summarizer.py diff --git a/app/services/summarizer.py b/app/services/summarizer.py index 061ed2a..e912a56 100644 --- a/app/services/summarizer.py +++ b/app/services/summarizer.py @@ -8,6 +8,22 @@ 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(_to_text(item) for item in value) + + if isinstance(value, dict): + return "\n".join(f"{key}: {_to_text(val)}" for key, val in value.items()) + + return str(value) + + def summarize_notice(title: str, content: str) -> NoticeSummaryData: settings = get_settings() prompt = f""" @@ -39,9 +55,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..c0575d3 --- /dev/null +++ b/tests/test_summarizer.py @@ -0,0 +1,36 @@ +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" From 81d78a3732a3d8f4671b1eb8d8ea3e16f7a0aa2b Mon Sep 17 00:00:00 2001 From: kimssirr Date: Wed, 6 May 2026 18:38:15 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=EA=B3=B5=EC=A7=80=20=EC=9A=94?= =?UTF-8?q?=EC=95=BD=20=EB=B9=88=20=EA=B5=AC=EC=A1=B0=ED=99=94=20=EA=B0=92?= =?UTF-8?q?=20=EC=A0=9C=EC=99=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/services/summarizer.py | 6 ++++-- tests/test_summarizer.py | 5 +++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/app/services/summarizer.py b/app/services/summarizer.py index e912a56..f359f67 100644 --- a/app/services/summarizer.py +++ b/app/services/summarizer.py @@ -16,10 +16,12 @@ def _to_text(value) -> str: return value.strip() if isinstance(value, list): - return "\n".join(_to_text(item) for item in value) + return "\n".join(text for item in value if (text := _to_text(item))) if isinstance(value, dict): - return "\n".join(f"{key}: {_to_text(val)}" for key, val in value.items()) + return "\n".join( + f"{key}: {text}" for key, val in value.items() if (text := _to_text(val)) + ) return str(value) diff --git a/tests/test_summarizer.py b/tests/test_summarizer.py index c0575d3..7a388c9 100644 --- a/tests/test_summarizer.py +++ b/tests/test_summarizer.py @@ -34,3 +34,8 @@ def test_summarize_notice_normalizes_structured_llm_fields(monkeypatch) -> None: 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, "공백": " "}) == "대상: 전체"