Skip to content

fix: rule_book LMM empty answer and BM25 search quality improvement - #86

Merged
Yu-JeSeung merged 2 commits into
mainfrom
fix/chatbot_rulebook_timeout
Apr 17, 2026
Merged

fix: rule_book LMM empty answer and BM25 search quality improvement#86
Yu-JeSeung merged 2 commits into
mainfrom
fix/chatbot_rulebook_timeout

Conversation

@Yu-JeSeung

@Yu-JeSeung Yu-JeSeung commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

관련 이슈

Open #85

🎯 배경

  • 챗봇 규정집 내용 질문 시 타임아웃 현상을 해결하기 위한 작업

🔍 주요 내용

  • LLM reasoning max_token값 증가
  • BM25 source article id 가중치 부여
  • run_in_executor 비동기 처리 도입
  • 에러 메시지 고정 문자열 변경, 서버 로그 기록

변경 요약

규정집 관련 챗봇의 타임아웃 문제를 해결하고 BM25 기반 검색 품질을 개선했습니다. LLM 토큰 한도를 늘리고 프롬프트 컨텍스트와 검색 색인을 조정했습니다.

주요 변경점

  • 규정집 컨텍스트로 포함하는 각 청크의 텍스트를 300자만 사용하도록 제한
  • LLM 추론용 max_tokens를 512→1024로 증가
  • 시스템 프롬프트 강화: 제공된 규정집 내용만 사용하고 추측 금지 명시
  • 규정 미검출 시 응답을 '해당 규정을 찾을 수 없습니다'로 통일
  • PDF 청크에 index_text 필드 추가(소스·article_id 반복 포함)하여 BM25 색인에 가중치 반영
  • 모델 응답의 finish_reason과 길이 로깅, 빈 응답 발생 시 경고 로그 기록
  • run_in_executor 적용으로 비동기 처리 개선

주의/리스크

  • 300자 제한으로 긴 규정의 일부 문맥 손실 가능
  • BM25 가중치 변경으로 검색 순위가 예상과 달라질 수 있음(모니터링 필요)
  • max_tokens 증가로 API 비용 상승 가능

다음 액션

  • 프로덕션 배포 후 타임아웃 및 빈 응답 발생 여부 모니터링
  • 검색 결과 품질을 실제 쿼리/사용자 피드백으로 검증
  • 필요 시 컨텍스트 자르기 전략이나 색인 가중치 세부 조정 시행

@Yu-JeSeung Yu-JeSeung self-assigned this Apr 15, 2026
@Yu-JeSeung Yu-JeSeung added the fix label Apr 15, 2026
@coderabbitai

coderabbitai Bot commented Apr 15, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 45f53a96-0dad-4be6-8349-244c5b86b29d

📥 Commits

Reviewing files that changed from the base of the PR and between 6435d7f and 5a06bb4.

📒 Files selected for processing (2)
  • LLM/rule_book/graph.py
  • LLM/rule_book/index.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • LLM/rule_book/index.py
  • LLM/rule_book/graph.py

📝 Walkthrough

Walkthrough

LLM 규정집 검색·응답 로직을 조정합니다: 검색 청크 텍스트를 300자로 잘라 프롬프트 컨텍스트를 축소, 시스템 프롬프트를 엄격화하여 제공된 규정집만 사용하도록 제한, max_tokens 확대(512→1024), 응답의 finish_reason 및 빈 응답 로깅 추가, BM25용 청크 인덱스 텍스트 필드 도입으로 토크나이제이션 변경.

Changes

Cohort / File(s) Summary
LLM 컨텍스트 및 응답 처리
LLM/rule_book/graph.py
검색 결과 청크를 각 300자까지만 <규정집 내용>에 포함하도록 축소; 시스템 프롬프트를 명확히 수정해 제공된 텍스트만 사용하도록 요구하고, 관련 내용 없을 때 정확히 해당 규정을 찾을 수 없습니다 출력 지시; max_tokens 512→1024; 첫 번째 choice의 finish_reason 캡처·로깅; 빈 응답에 대한 경고 로깅 추가.
청크 메타데이터 및 인덱싱
LLM/rule_book/index.py
PDF 기반 기사 청크의 메타데이터에 새 index_text 필드 추가(기존 text 대신 c.get("index_text", c["text"])로 BM25에 토크나이즈), index_text에 source/article 식별자 중복 포함으로 인덱스 입력 변경.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

chore

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive PR 설명이 템플릿 구조를 따르고 있으나, 실제 구현된 변경사항과 설명 내용 사이에 불일치가 있습니다. run_in_executor 비동기 처리 도입 내용은 제공된 코드 요약에 나타나지 않으므로 확인 및 수정이 필요합니다.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목은 주요 변경사항(LLM 빈 응답 개선 및 BM25 검색 품질 개선)을 명확하게 요약하고 있으며, 실제 코드 변경사항과 일치합니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/chatbot_rulebook_timeout

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
LLM/rule_book/graph.py (1)

75-75: max_tokens는 환경변수로 분리하는 것을 권장합니다.

Line 75 하드코딩 값은 운영 중 모델/트래픽 상황에 맞춘 즉시 튜닝이 어렵습니다.

제안 diff
 TOP_K = int(os.getenv("RULE_BOOK_TOP_K", "5"))
+RULE_BOOK_MAX_TOKENS = int(os.getenv("RULE_BOOK_MAX_TOKENS", "1024"))
@@
-            max_tokens=1024,
+            max_tokens=RULE_BOOK_MAX_TOKENS,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@LLM/rule_book/graph.py` at line 75, The hardcoded max_tokens=1024 should be
replaced with a configurable environment-backed value so it can be tuned without
code changes; update the call that contains max_tokens=1024 to read an
environment variable (e.g., os.getenv or a config loader), parse/validate it as
an integer with a sensible default (e.g., 1024) and use that variable instead of
the literal; ensure the change is applied where max_tokens is passed (the call
containing max_tokens=1024) and add a brief validation/fallback to prevent
non-integer or out-of-range values.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@LLM/rule_book/graph.py`:
- Around line 59-63: The code returns different "no results" messages depending
on the branch: one branch forces "해당 규정을 찾을 수 없습니다" (around the prompt
construction) while the early-return when chunks is empty (around the chunks
handling) uses a different phrase; unify them by introducing a single constant
(e.g., NO_RESULTS_MSG = "해당 규정을 찾을 수 없습니다") and use that constant both where you
currently early-return when chunks is empty and where you insert that message
into the prompt/template (references: the variable chunks and the
prompt-building logic in LLM/rule_book/graph.py).

In `@LLM/rule_book/index.py`:
- Around line 40-44: The current chunks.append call mixes BM25-weighted metadata
into the LLM prompt by duplicating source/article into the "text" field; instead
keep search-weighted text separate and make "text" contain only the actual
content for LLM. Change the dict in chunks.append to add a new key like
"bm25_text" or "search_text" that concatenates source and article_id for
retrieval weighting, keep "source" and "article" as metadata, and set "text" to
just content (or minimal context + content). Also update downstream usage (e.g.,
graph.py where the 300-char slice is applied) to use "text" for LLM context and
"bm25_text"/"search_text" for BM25/search operations.

---

Nitpick comments:
In `@LLM/rule_book/graph.py`:
- Line 75: The hardcoded max_tokens=1024 should be replaced with a configurable
environment-backed value so it can be tuned without code changes; update the
call that contains max_tokens=1024 to read an environment variable (e.g.,
os.getenv or a config loader), parse/validate it as an integer with a sensible
default (e.g., 1024) and use that variable instead of the literal; ensure the
change is applied where max_tokens is passed (the call containing
max_tokens=1024) and add a brief validation/fallback to prevent non-integer or
out-of-range values.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: cc294ffb-9c7d-448f-b9a1-de42c02afed4

📥 Commits

Reviewing files that changed from the base of the PR and between f2eaa38 and 6435d7f.

📒 Files selected for processing (2)
  • LLM/rule_book/graph.py
  • LLM/rule_book/index.py

Comment thread LLM/rule_book/graph.py
Comment on lines +59 to +63
"반드시 아래 <규정집 내용> 안의 텍스트만을 근거로 질문에 답하세요.\n"
"<규정집 내용> 외의 정보는 절대 사용하지 마세요.\n"
"답변은 간결하고 명확하게, 관련 조문 번호와 출처를 함께 안내하세요.\n"
"규정집에 없는 내용은 '해당 규정을 찾을 수 없습니다'라고 답하세요.\n"
"임의로 정보를 만들지 마세요."
"<규정집 내용>에 질문과 관련된 내용이 없으면 '해당 규정을 찾을 수 없습니다'라고만 답하세요.\n"
"추측하거나 임의로 정보를 만들지 마세요."

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

미검색 응답 문구를 분기 전체에서 동일하게 맞춰 주세요.

Line 62에서 "해당 규정을 찾을 수 없습니다"를 강제했는데, chunks가 비어 바로 반환되는 경로(Line 49)는 다른 문구를 사용합니다. 클라이언트가 고정 문구를 기준으로 처리하면 분기별 동작이 달라질 수 있습니다.

제안 diff
+NO_RULE_MSG = "해당 규정을 찾을 수 없습니다"
+
 async def generate(state: RuleState) -> RuleState:
@@
-    if not chunks:
-        return {**state, "answer": "관련 규정을 찾지 못했습니다. 더 구체적인 키워드로 질문해 주세요."}
+    if not chunks:
+        return {**state, "answer": NO_RULE_MSG}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@LLM/rule_book/graph.py` around lines 59 - 63, The code returns different "no
results" messages depending on the branch: one branch forces "해당 규정을 찾을 수 없습니다"
(around the prompt construction) while the early-return when chunks is empty
(around the chunks handling) uses a different phrase; unify them by introducing
a single constant (e.g., NO_RESULTS_MSG = "해당 규정을 찾을 수 없습니다") and use that
constant both where you currently early-return when chunks is empty and where
you insert that message into the prompt/template (references: the variable
chunks and the prompt-building logic in LLM/rule_book/graph.py).

Comment thread LLM/rule_book/index.py
@Yu-JeSeung
Yu-JeSeung merged commit 28d28ef into main Apr 17, 2026
1 check passed
@Yu-JeSeung
Yu-JeSeung deleted the fix/chatbot_rulebook_timeout branch April 17, 2026 07:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant