Conversation
There was a problem hiding this comment.
Code Review
This pull request improves the notice crawling and summarization logic by refining text extraction from HTML and adding specific formatting rules for LLM-generated summaries. Key changes include a new _extract_detail_text_lines function to preserve block boundaries and updated LLM prompts to ensure consistent string output for schedule and caution information. Review feedback identified a potential data loss issue in the HTML text extraction logic where text nodes in parent elements might be skipped. Additionally, improvements were suggested for the _format_caution_info function to strictly exclude dictionary keys, and a typo in the LLM prompt was noted.
| text_lines: list[str] = [] | ||
|
|
||
| for element in soup.find_all(DETAIL_TEXT_BLOCK_TAGS): | ||
| if element.find(DETAIL_TEXT_BLOCK_TAGS): | ||
| continue | ||
|
|
||
| text = _normalize_text(element.get_text(" ", strip=True)) | ||
| if not text: | ||
| continue | ||
|
|
||
| text_lines.append(text) | ||
|
|
||
| if text_lines: | ||
| return text_lines | ||
|
|
||
| return [ | ||
| _normalize_text(line) | ||
| for line in soup.get_text("\n", strip=True).splitlines() | ||
| if _normalize_text(line) | ||
| ] |
There was a problem hiding this comment.
현재 구현된 _extract_detail_text_lines 로직은 데이터 유실 위험이 있습니다. element.find(DETAIL_TEXT_BLOCK_TAGS)를 통해 자식 블록 요소가 있는 부모 요소를 건너뛰게 되면, 부모 요소의 직접적인 자식인 텍스트 노드들이 무시됩니다.
예를 들어 <div>본문 시작 <p>중간 내용</p> 본문 끝</div>과 같은 구조에서 "본문 시작"과 "본문 끝"은 유실되고 "중간 내용"만 추출됩니다. 블록 요소들에 명시적으로 개행 문자를 삽입한 뒤 텍스트를 추출하는 방식이 더 안전하고 의도한 대로 인라인 태그들을 합칠 수 있습니다.
for element in soup.find_all(DETAIL_TEXT_BLOCK_TAGS):
element.append("\n")
text = soup.get_text(" ", strip=True)
return [
_normalize_text(line)
for line in text.splitlines()
if _normalize_text(line)
]| def _format_caution_info(value) -> str: | ||
| return _to_text(value) |
There was a problem hiding this comment.
_format_caution_info가 사용하는 _to_text는 딕셔너리 처리 시 키 이름을 포함합니다 (예: {"caution": "..."} -> "caution: ..."). 이는 72번 라인의 프롬프트 지침("caution, warning 같은 키 이름을 내용에 포함하지 마")과 충돌할 수 있습니다. LLM이 지침을 어기고 객체 형태로 응답할 경우를 대비해, _format_schedule_info처럼 키를 제외하고 값만 추출하도록 개선하는 것이 좋습니다.
def _format_caution_info(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 := _format_caution_info(item)))
if isinstance(value, dict):
return "\n".join(text for val in value.values() if (text := _format_caution_info(val)))
return str(value)| - 반드시 문자열 또는 null로 반환해. 객체나 배열로 반환하지 마. | ||
| - date, details 같은 키 이름을 내용에 포함하지 마. | ||
| - 요일과 시간만 적어. 양식은 ####년 ##월 ##일, 시간은 오전 또는 오후 #시 이렇게. | ||
| - 생활관 별로 시간이 다르면 생활간 별 시간으로 적어. |
작업 내용
공지 수집/요약 과정에서 본문과 요약 정보가 의도와 다르게 저장되는 문제를 수정했습니다.
변경 사항 (있다면)
schedule_info,caution_info가 구조화 키가 아닌 사용자에게 바로 보여줄 수 있는 문자열로 저장되도록 후처리 보완리뷰 포인트
schedule_info,caution_info가 DB에 문자열 형태로 저장되는 방식이 서비스 응답 요구사항과 맞는지테스트
/docs수동 확인pytest실행