Skip to content

refactor: introduce chatbot tool routing abstraction - #119

Merged
Yu-JeSeung merged 2 commits into
mainfrom
refactor/chatbot-tool-routing
May 23, 2026
Merged

refactor: introduce chatbot tool routing abstraction#119
Yu-JeSeung merged 2 commits into
mainfrom
refactor/chatbot-tool-routing

Conversation

@Yu-JeSeung

@Yu-JeSeung Yu-JeSeung commented May 22, 2026

Copy link
Copy Markdown
Contributor

관련 이슈

Open #118

🎯 배경

  • 챗봇 서비스의 mode별 분기와 검색/후처리 호출이 service.py에 집중되어 있어, 비용 우선 tool routing 구조를 명확히 드러내기 어려웠습니다.
  • 실서비스 제약을 유지하면서 LLM 호출 전에 deterministic tool을 우선 실행하는 구조를 분리할 필요가 있었습니다.

🔍 주요 내용

  • LLM/OSS/tools.py를 추가해 ToolResult와 deterministic chatbot tool routing helper를 분리했습니다.
  • service.pyfast/policy/dorm/grad/topic/oss 반복 분기를 run_mode_tools(), run_oss_fast_path_tools() 중심으로 정리했습니다.
  • 기존 검색, 일정, metadata direct answer, postprocess 로직은 재사용해 기능 변경 범위를 최소화했습니다.
  • docs/PLANS.md에 새 챗봇 tool routing 모듈을 반영했습니다.

변경 요약

챗봇의 도구 라우팅 로직을 추상화하여 service.py의 복잡한 모드별 분기를 체계적으로 정리했습니다. 새로운 tools.py 모듈에서 ToolResult 기반 결정적 도구 실행 흐름을 구성하고, service.py는 이를 활용해 더 간결하게 리팩토링했습니다.

주요 변경점

  • ToolResult 데이터클래스 추가: 모든 도구의 결과를 표준화하여 name, text, engine, confidence, llm_required 등을 관리
  • 모드별 도구 실행 함수: run_mode_tools(), run_oss_fast_path_tools(), run_empty_oss_fallback_tools(), run_final_fallback_tools() 추가로 단계별 라우팅 구현
  • 개별 도구 헬퍼: 메타데이터 직접 답변, 스케줄 검색, 학과 명확화, 후처리, 자신감 기반 답변 등을 독립적인 함수로 분리
  • service.py 간소화: 흩어진 fast/policy/dorm/grad/topic/oss 분기를 도구 함수로 통합해 chat_with_oss() 가독성 개선
  • 폴백 전략 체계화: OSS 출력 비어있을 때와 최종 폴백 처리를 명확한 단계로 구분
  • 기존 로직 재사용: 검색, 캘린더, 메타데이터, 후처리 로직을 기존 함수로 유지하여 기능 변화 최소화
  • 문서 업데이트: docs/PLANS.mdtools.py를 "비용 우선 결정적 도구 라우팅"으로 등록

주의/리스크

  • 큰 리팩토링으로 인한 회귀 테스트 필수: 모드별 동작이 분산되었으므로 각 모드(fast, policy, dorm, grad, topic, oss)별 엔드투엔드 테스트 확인 필요
  • 도구 우선순위 변경: 모드에 따라 도구 실행 순서가 변경되었으므로 기존과 동일한 응답이 나오는지 검증 필요
  • OSS 폴백 흐름의 복잡성: 빈 출력 → 폴백 → 최종 폴백까지 여러 단계를 거치므로, 각 단계의 조건과 반환값을 정확히 추적할 것

다음 액션

  • 모드별(특히 oss 모드) 통합 테스트 실행 및 응답 품질 확인
  • 로그에서 도구 실행 단계와 엔진 선택 이유가 명확히 기록되는지 모니터링
  • 폴백 조건(연락처/문의/위원회 키워드)이 정상 작동하는지 유즈 케이스로 검증

Review Change Stack

@Yu-JeSeung Yu-JeSeung self-assigned this May 22, 2026
@coderabbitai

coderabbitai Bot commented May 22, 2026

Copy link
Copy Markdown
📝 Walkthrough

워크스루

OSS 쿼리 처리 로직을 도구 기반 라우팅으로 재구성했습니다. 새로운 ToolResult 데이터클래스와 도구 헬퍼(_direct_answer_tool, _schedule_tool 등) 및 모드별 라우팅 진입점(run_mode_tools, run_oss_fast_path_tools, run_empty_oss_fallback_tools, run_final_fallback_tools)을 LLM/OSS/tools.py에 추가했고, service.pychat_with_oss()에서 기존 조건부 로직을 새 도구 호출로 대체했습니다.

변경 사항

도구 기반 라우팅 중앙화

레이어 / 파일 요약
도구 결과 데이터 계약 및 초기화
LLM/OSS/tools.py
ToolResult 불변 데이터클래스가 도구의 name, text, url, engine, confidence, llm_required 필드와 resolved, handled 상태 판정 프로퍼티, to_response() 직렬화 메서드를 제공합니다. EMPTY_TOOL_RESULT 상수는 공통 폴백을 제공하며, 모듈 의존성과 설정이 초기화됩니다.
개별 도구 헬퍼 함수 구현
LLM/OSS/tools.py
메타데이터 기반 직접 답변(_direct_answer_tool), 스케줄 탐색 후 render_chatty_schedule 적용(_schedule_tool), 부서/학과 명확화(_clarification_tool), build_answer()schedule_search() 조합(call_submodel()), 후처리 적용(_postprocess_tool), 신감도 기반 답변(_confident_search_tool)이 각각 ToolResult로 래핑되며, 실패 시 EMPTY_TOOL_RESULT를 반환합니다.
모드별 도구 라우팅 진입점
LLM/OSS/tools.py
run_mode_tools()fast 모드에서는 스케줄→직접답변→명확화 우선순위, policy/grad에서는 직접답변 우선, dorm/topic에서는 후처리를 수행하고 resolved 시점에 즉시 반환합니다. run_oss_fast_path_tools()는 직접답변과 신감도 답변만 시도하며, run_empty_oss_fallback_tools()는 스케줄 유사도 및 주제 유사도에 따른 폴백, run_final_fallback_tools()llm_required=True로 RAG 컨텍스트 필요 상태를 반환합니다.
service.py의 chat_with_oss() 리팩토링
LLM/OSS/service.py
LLM.OSS.formatter에서 dept_clarification_message, render_chatty_schedule 가져오기를 제거하고 LLM.OSS.tools의 라우팅 함수들을 import합니다. 모듈 레벨 call_submodel() 함수가 삭제되고(tools.py로 이동), chat_with_oss() 내부의 mode 값별 하드코딩 분기(fast/policy/dorm/grad/topic/oss)를 run_mode_tools(mode, user_text) 호출로 통합합니다. mode == "oss"인 경우에는 run_oss_fast_path_tools()call_oss_async() → 연락처 스크럽 → run_empty_oss_fallback_tools()run_final_fallback_tools() → 컨텍스트 포함 최종 OSS 호출 파이프라인을 적용하고, 결과가 비면 run_mode_tools("topic", user_text).text로 응답을 확정합니다.
문서 업데이트
docs/PLANS.md
아키텍처 구조 스냅샷에 LLM/OSS/tools.py 파일을 추가하고 역할을 "비용 우선 deterministic tool routing"으로 명시하며, "챗봇 코어" 핵심 영역 목록에도 포함합니다.

🎯 3 (중간) | ⏱️ ~20분

관련된 가능성 있는 PR

  • dongsooop/AI#75: 두 PR 모두 dept_clarification_message 로직을 OSS 처리의 핵심으로 다루며, 이 PR은 해당 기능을 LLM/OSS/tools.py_clarification_toolrun_mode_tools 라우팅으로 재구성한 반면, 해당 PR은 LLM/OSS/Open_AI_OSS.py에 직접 구현하고 fast 모드에서 선단락 처리합니다.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

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.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 주요 변경사항인 'chatbot tool routing abstraction' 도입을 명확하게 설명하고 있습니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed PR 설명이 필수 템플릿 항목을 완전히 포함하고 있으며, 배경과 주요 내용이 명확하게 작성되어 있습니다.

✏️ 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 refactor/chatbot-tool-routing

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: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@LLM/OSS/service.py`:
- Around line 334-358: The OSS branch currently returns early (including
caching/logging) after handling empty-OSS fallbacks or static canned replies,
preventing downstream run_final_fallback_tools() and the fused fallback path
from executing; modify the mode == "oss" block so: 1) keep the fast-path
short-circuit via run_oss_fast_path_tools() and cache_and_return(), 2) call
call_oss_async() and scrub_non_contact() as now, 3) if output is empty run
run_empty_oss_fallback_tools() and if it.handled set output =
fallback.to_response() (but do NOT return immediately), otherwise set output to
the greeting or "잘 이해하지 못했어요..." text and continue (do not log/return here), and
4) remove the early _log_chatbot submit + return at the end of the oss block so
execution falls through to the shared final fallback/fusion logic
(run_final_fallback_tools(), fused fallback and final logging) while still using
the same identifiers (_log_chatbot, run_empty_oss_fallback_tools,
run_final_fallback_tools, call_oss_async, scrub_non_contact, cache_and_return).
- Around line 330-332: The current early return after run_mode_tools(mode,
user_text) checks tool_result.handled, but per stack contract this router must
only return immediately when the ToolResult is resolved; change the condition to
check tool_result.resolved (or the ToolResult.is_resolved/ resolved property)
before calling cache_and_return(tool_result.to_response()), so that
handled-but-unresolved ToolResult instances do not short-circuit OSS calls or
the final fallback; leave run_mode_tools, cache_and_return and to_response usage
intact and only gate the immediate return on resolved.

In `@LLM/OSS/tools.py`:
- Around line 183-189: The postprocess URL returned by run_postprocess is being
discarded (text, _ = run_postprocess(...)) which loses reference info; change
that to capture the URL (text, url = run_postprocess(mode, user_text,
sub_answer)) and include it in the returned ToolResult (e.g., add url=url or
source_url=url in the ToolResult construction that returns
name=f"{mode}_oss_empty_fallback", text=text, engine="oss", confidence=...), so
the fallback response preserves the postprocessing reference.
- Around line 66-129: The helper functions _direct_answer_tool, _schedule_tool,
_clarification_tool, _postprocess_tool, and _confident_search_tool currently
call external helpers (metadata_direct_answer, schedule_search,
dept_clarification_message, call_submodel/run_postprocess,
confident_search_answer) without exception handling; wrap each external call in
a try/except that catches broad exceptions, logs the error, and returns
EMPTY_TOOL_RESULT on failure so a single tool error won't abort routing. Ensure
you handle both the initial call (e.g., metadata_direct_answer, schedule_search,
dept_clarification_message, confident_search_answer) and the
submodel/postprocess sequence (call_submodel then run_postprocess) in
_postprocess_tool, returning EMPTY_TOOL_RESULT if either step raises.
- Around line 45-59: call_submodel currently silences all exceptions in both
build_answer and schedule_search which hides failures; update call_submodel to
catch specific exceptions (e.g., network/IO or model-specific errors) instead of
bare except Exception, and log the full exception details when build_answer or
schedule_search fails (use the module logger or processLogger) while preserving
fallback behavior: reference build_answer/result and schedule_search/schedule
and ensure settings.json_only_mode logic remains unchanged.
🪄 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: 2c22addd-b975-4afb-ab23-ce4411a50fe6

📥 Commits

Reviewing files that changed from the base of the PR and between c8c8670 and a22b903.

📒 Files selected for processing (3)
  • LLM/OSS/service.py
  • LLM/OSS/tools.py
  • docs/PLANS.md

Comment thread LLM/OSS/service.py
Comment thread LLM/OSS/service.py Outdated
Comment thread LLM/OSS/tools.py
Comment thread LLM/OSS/tools.py
Comment thread LLM/OSS/tools.py Outdated
@Yu-JeSeung Yu-JeSeung added run-rag-check check rag eval and removed run-rag-check check rag eval labels May 22, 2026
@Yu-JeSeung
Yu-JeSeung merged commit 409523d into main May 23, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant