Skip to content

refactor: chatbot service logic and routting code separate - #94

Merged
Yu-JeSeung merged 2 commits into
mainfrom
refactor/chatbot_services_routing
Apr 23, 2026
Merged

refactor: chatbot service logic and routting code separate#94
Yu-JeSeung merged 2 commits into
mainfrom
refactor/chatbot_services_routing

Conversation

@Yu-JeSeung

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

Copy link
Copy Markdown
Contributor

관련 이슈

Close #91

🎯 배경

  • 챗봇 시스템 코드가 하나로 이루어져 있어 리팩토링 시 코드가 난잡하게 보였습니다.
  • 라우팅 및 서비스로직을 분리하여 기능별로 작업을 확인 할 수 있도록 변경하였습니다.

🔍 주요 내용

  • 서비스 로직 service.py 생성
  • 챗봇 모드 판별 modes.py 생성
  • 후처리 formatter.py 생성
  • 텍스트 필터링도 같은 프로세스 적용
  • 변경 요약(1~3줄)
    챗봇의 라우팅과 서비스(비즈니스) 로직을 분리해 가독성·유지보수성을 개선했습니다. Open_AI_OSS.py를 라우터 얇은 래퍼로 바꾸고 service.py, modes.py, formatter.py 등을 도입해 기능별 책임을 명확히 했습니다.

  • 주요 변경점(3~7개)

    • Open_AI_OSS.py 리팩토링: 내부 비즈니스 로직 제거 후 FastAPI 라우터로 축소
    • LLM/OSS/service.py 추가: OSS 클라이언트, 캐시, 모드 라우팅, DB 로깅 등을 담당하는 핵심 서비스 로직 추가
    • LLM/OSS/modes.py 추가: 사용자 입력 기반 모드 결정(예: schedule, topic, policy 등) 로직 도입
    • LLM/OSS/formatter.py 추가: 대학 정보 파싱·후처리 및 한 문장 응답 생성 등 포맷터 추가
    • text_filtering 리팩토링: 디바이스 선택 로직(CUDA 우선) 및 import 경로 정리
    • .gitignore 업데이트: LLM/OSS 관련 제외 규칙 변경 및 backup_file 규칙 정리
    • 대형 파일(노트북, fine-tune 스크립트) 삭제: 여러 학습/모델 관련 노트북과 스크립트 제거
  • 주의/리스크(있으면 1~3개)

    • 대규모 코드 이동으로 기능 누락/회귀 가능성 — 통합 테스트 필요
    • service.py, modes.py, formatter.py 간 의존성/데이터 흐름 검증 필요
    • 정규표현식·휴리스틱 기반 로직의 정확성(특히 dept 감지/후처리) 확인 필요
  • 다음 액션(있으면 1~3개)

    • 기존 chatbot API에 대한 통합·회귀 테스트 실행
    • 모드별(일정/주제/정책/기숙사/졸업/연락처 등) 동작 검증
    • 캐시, DB 로깅, SSH 터널링 등 부가 기능의 정상 동작 확인

@Yu-JeSeung Yu-JeSeung self-assigned this Apr 23, 2026
@coderabbitai

coderabbitai Bot commented Apr 23, 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: dc2f0147-9c0c-4080-8dea-650c1ca6776b

📥 Commits

Reviewing files that changed from the base of the PR and between 88b2b33 and a3bb3e4.

📒 Files selected for processing (5)
  • LLM/LSTM-Attention_model.ipynb
  • LLM/MINI_RAG_model.ipynb
  • LLM/OSS/modes.py
  • LLM/finetune_chatbot.py
  • text_filtering/service.py
💤 Files with no reviewable changes (3)
  • LLM/LSTM-Attention_model.ipynb
  • LLM/finetune_chatbot.py
  • LLM/MINI_RAG_model.ipynb
🚧 Files skipped from review as they are similar to previous changes (1)
  • LLM/OSS/modes.py

📝 Walkthrough

Walkthrough

이 PR은 LLM/OSS 챗 엔드포인트를 얇은 FastAPI 라우터로 분리하고 핵심 로직을 LLM/OSS/service.py, 의도 판정은 LLM/OSS/modes.py, 응답 포매팅은 LLM/OSS/formatter.py로 이동시키며 관련 노트북·학습 스크립트와 일부 파일들을 삭제하거나 .gitignore를 조정합니다. 텍스트필터링 디바이스 우선순위도 CUDA 우선으로 변경됩니다.

Changes

Cohort / File(s) Summary
무시 규칙 수정
/.gitignore
LLM/OSS 디렉토리 제외 규칙 제거, backup_file 매칭을 디렉토리 전용(backup_file/)으로 변경.
라우터 얇게 변경
LLM/OSS/Open_AI_OSS.py
기존의 자체 채팅 구현을 제거하고 POST /chatbot 라우트를 유지하되 요청 처리를 LLM.OSS.service.chat_with_oss에 위임하는 얇은 FastAPI 라우터(router)로 대체.
서비스 핵심 추가
LLM/OSS/service.py
새로운 ChatReq 모델, DB 풀 초기화/종료, TTL 캐시, OSS/submodel 호출 래퍼와 chat_with_oss(req) 비동기 엔드포인트(모드 결정·캐시·로깅·하위 모델 융합 등)를 추가.
응답 포매터 추가
LLM/OSS/formatter.py
학과 맵/별칭 로드, 일정 렌더링, 연락처/소개 파싱, URL/전화 정규화, 한 문장 요약 생성 등 한국 대학 정보 쿼리용 포맷터 함수군 추가.
모드 결정 모듈 추가
LLM/OSS/modes.py
정규식/키워드 기반 판정 함수들과 decide_mode(user_text)를 추가하여 응답 모드(일정/정책/기숙사/주제/oss 등)를 결정.
텍스트 필터링 디바이스 우선순위
text_filtering/service.py
get_device()가 CUDA 사용 가능 시 torch.device("cuda")를 반환하도록 변경(기존: MPS 또는 CPU 우선).
임포트 경로 정정
text_filtering/text_filtering.py, text_filtering/text_filtering_rule.py
services.text_filteringtext_filtering.service로 내부 임포트 경로 수정(로직 변화 없음).
노트북·학습 스크립트 제거
LLM/...
LLM/LSTM-Attention_model.ipynb, LLM/MINI_RAG_model.ipynb, LLM/finetune_chatbot.py 등 학습·실험 노트북 및 파인튜닝 스크립트가 삭제됨(대규모 코드/노트북 제거).

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Router as FastAPI Router<br/>(Open_AI_OSS.py)
    participant Service as Chat Service<br/>(LLM/OSS/service.py)
    participant ModeDecider as Mode Decider<br/>(LLM/OSS/modes.py)
    participant Cache as Cache
    participant Formatter as Formatter<br/>(LLM/OSS/formatter.py)
    participant OSS as OSS Model
    participant DB as Database

    Client->>Router: POST /chatbot (ChatReq)
    Router->>Service: chat_with_oss(req)
    Service->>ModeDecider: decide_mode(user_text)
    ModeDecider-->>Service: mode
    Service->>Cache: lookup(key)
    alt cache hit
        Cache-->>Service: cached_response
    else cache miss
        Service->>Service: apply guard / route by mode
        alt mode in ["schedule","policy","dorm","grad","topic"]
            Service->>OSS: call_oss(prompt)
            OSS-->>Service: raw_response
            Service->>Formatter: format by mode
            Formatter-->>Service: formatted_response
        else mode == "oss"
            Service->>OSS: call_oss(prompt)
            OSS-->>Service: raw_response
            Service->>Formatter: scrub_non_contact(raw_response)
            Formatter-->>Service: scrubbed_response
        end
        Service->>Cache: store(key, response)
    end
    Service->>DB: log_interaction (background)
    DB-->>Service: ack
    Service-->>Router: response dict
    Router-->>Client: JSON response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

🚥 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 제목은 주요 변경 사항(라우팅과 서비스 로직 분리)을 명확하게 요약하고 있으며, 전체 리팩토링의 핵심을 잘 반영하고 있습니다.
Description check ✅ Passed PR 설명이 템플릿의 모든 필수 섹션(관련 이슈, 배경, 주요 내용)을 포함하고 있으며, 변경 사항이 명확하게 기술되어 있습니다.
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.

✏️ 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_services_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: 3

🧹 Nitpick comments (1)
LLM/OSS/formatter.py (1)

116-143: load_dept_map() 에서 파싱 실패가 조용히 삭제됩니다 — 부서 매칭 품질 저하를 감지하기 어렵습니다.

라인 135-136 의 except Exception: continue 때문에 쉼표 분리 실패, 인코딩 이슈, 예기치 않은 포맷 등 어떤 오류든 해당 줄이 소리 없이 드롭되고 DEPT_MAP / DEPT_ALIAS 에서 누락됩니다. 이 두 딕셔너리는 모듈 로드 시점에 1회만 채워지고(라인 140) 이후 detect_dept_hint, dept_clarification_message, _parse_bullets_and_pick 의 스코어링 근거가 되므로, 누락된 학과가 있어도 런타임에는 그냥 "힌트 없음" 처럼 동작해 원인 추적이 매우 어렵습니다. 최소한 오류 로깅(또는 드롭 건수 카운트) 을 추가해 주세요. 또한 모듈 import 시점의 파일 I/O 자체도 테스트 환경에서 파일 누락 시 DEPT_MAP 이 영구히 비게 되는 부작용이 있으니, 첫 호출 시 lazy 로드하는 방식도 고려해 볼 만합니다.

♻️ 제안 패치
-            try:
-                name, rest = line.split(",", 1)
-                url_part = rest.split(",")[0].strip()
-                base = url_part.split("?")[0]
-                canon = _canon_unit(name)
-                dept_map[canon] = {"name": name, "path_base": base}
-                aliases[canon] = _make_aliases(name)
-            except Exception:
-                continue
+            try:
+                name, rest = line.split(",", 1)
+                url_part = rest.split(",")[0].strip()
+                base = url_part.split("?")[0]
+                canon = _canon_unit(name)
+                dept_map[canon] = {"name": name, "path_base": base}
+                aliases[canon] = _make_aliases(name)
+            except Exception as exc:
+                print(f"[load_dept_map WARN] skip line {line!r}: {exc}")
+                continue
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@LLM/OSS/formatter.py` around lines 116 - 143, The load_dept_map function
currently swallows all exceptions per-line (except Exception: continue) which
silently drops entries used by DEPT_MAP/DEPT_ALIAS and harms downstream
functions like detect_dept_hint, dept_clarification_message and
_parse_bullets_and_pick; change load_dept_map to catch only expected parsing
errors (e.g., ValueError) or at minimum log the exception and the offending line
(include the raw line text and index) and increment a dropped_lines counter,
then after reading the file emit a summary warning with the drop count;
additionally make module-level initialization lazy (do not call load_dept_map
unconditionally at import) by replacing the immediate DEPT_MAP/DEPT_ALIAS
population with a lazy loader or getter that calls load_dept_map on first access
so tests or missing files don’t leave the maps permanently empty.
🤖 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/OSS/modes.py`:
- Line 13: RELATION_RE currently matches bare Korean tokens like "관계" and "사이"
causing many false positives; update RELATION_RE so the suffixes are required
and add token-boundary checks or context anchors to avoid matching those words
in compound nouns. Specifically, modify RELATION_RE (the compiled pattern named
RELATION_RE) to require the (야|냐) suffix for "사이" and "관계" (remove the trailing
?), and strengthen boundaries using lookarounds (e.g., require preceding
whitespace/start and following whitespace/end/punctuation or use (?<!\S) ...
(?!\S)) or explicitly match conversational phrases like "우리 관계", "우린 무슨 관계", "너와
나", ensuring normal compound words like "인과관계" or "사이버보안학과" are not matched.

In `@LLM/OSS/service.py`:
- Around line 47-90: init_db_pool is not idempotent and can leak SSH tunnels and
DB connections; before creating a new SSHTunnelForwarder or
ThreadedConnectionPool, check for and clean up existing resources: if
_ssh_tunnel is not None call _ssh_tunnel.stop() and set _ssh_tunnel = None, and
if _db_pool is not None call _db_pool.closeall() and set _db_pool = None, then
proceed to create and assign the new instances (refer to init_db_pool,
_ssh_tunnel, _db_pool). Also update shutdown_db_pool to explicitly shutdown the
log executor by calling _log_executor.shutdown(wait=False) (and optionally set
_log_executor = None) after closing the DB pool and stopping the tunnel so the
module-level ThreadPoolExecutor doesn't keep the process alive (refer to
shutdown_db_pool and _log_executor).

In `@text_filtering/service.py`:
- Around line 45-50: get_device() currently prefers MPS over CUDA; change its
priority to CUDA > MPS > CPU to match the project's canonical ordering used in
LLM/finetune_chatbot.py, i.e., check torch.cuda.is_available() first, then
torch.backends.mps.is_available(), otherwise CPU. Also fix the logic in
text_filtering/bad_text_learning_model.py around the device selection (the
incorrect branch at or near line 129 that picks "mps" when CUDA is available) so
it follows the same CUDA > MPS > CPU checks and selects the correct torch.device
string.

---

Nitpick comments:
In `@LLM/OSS/formatter.py`:
- Around line 116-143: The load_dept_map function currently swallows all
exceptions per-line (except Exception: continue) which silently drops entries
used by DEPT_MAP/DEPT_ALIAS and harms downstream functions like
detect_dept_hint, dept_clarification_message and _parse_bullets_and_pick; change
load_dept_map to catch only expected parsing errors (e.g., ValueError) or at
minimum log the exception and the offending line (include the raw line text and
index) and increment a dropped_lines counter, then after reading the file emit a
summary warning with the drop count; additionally make module-level
initialization lazy (do not call load_dept_map unconditionally at import) by
replacing the immediate DEPT_MAP/DEPT_ALIAS population with a lazy loader or
getter that calls load_dept_map on first access so tests or missing files don’t
leave the maps permanently empty.
🪄 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: cf93db65-e51a-4af7-a786-274d84336ce6

📥 Commits

Reviewing files that changed from the base of the PR and between 0615e2e and 88b2b33.

📒 Files selected for processing (9)
  • .gitignore
  • LLM/OSS/Open_AI_OSS.py
  • LLM/OSS/formatter.py
  • LLM/OSS/modes.py
  • LLM/OSS/service.py
  • services/__init__.py
  • text_filtering/service.py
  • text_filtering/text_filtering.py
  • text_filtering/text_filtering_rule.py

Comment thread LLM/OSS/modes.py Outdated
Comment thread LLM/OSS/service.py
Comment on lines +47 to +90
_ssh_tunnel: Optional[SSHTunnelForwarder] = None
_db_pool: Optional[pg_pool.ThreadedConnectionPool] = None
_log_executor = ThreadPoolExecutor(max_workers=4, thread_name_prefix="chatbot_log")

_client: Optional[OpenAI] = None
_client_lock = threading.Lock()


class ChatReq(BaseModel):
text: Optional[str] = None
messages: Optional[list[dict[str, str]]] = None
engine: Optional[str] = None


def init_db_pool() -> None:
global _ssh_tunnel, _db_pool
ssh_host = settings.ssh_host
db_kwargs = dict(
dbname=settings.db_name,
user=settings.db_user,
password=settings.db_password,
connect_timeout=3,
options="-c statement_timeout=5000",
)
if ssh_host:
_ssh_tunnel = SSHTunnelForwarder(
(ssh_host, 22),
ssh_username=settings.ssh_user,
ssh_pkey=settings.ssh_key_path,
remote_bind_address=("localhost", 5433),
)
_ssh_tunnel.start()
db_kwargs.update(host="localhost", port=_ssh_tunnel.local_bind_port)
else:
db_kwargs["host"] = "localhost"
_db_pool = pg_pool.ThreadedConnectionPool(minconn=1, maxconn=5, **db_kwargs)


def shutdown_db_pool() -> None:
if _db_pool:
_db_pool.closeall()
if _ssh_tunnel:
_ssh_tunnel.stop()

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

DB/터널 리소스 초기화·정리 경로 재점검 필요.

두 가지 누수 가능성이 있습니다.

  1. init_db_pool() 이 멱등하지 않습니다. 테스트에서 재호출되거나 lifespan 이 재실행(예: 리로드, 멀티워커에서의 재초기화 시나리오)되면, 기존 _ssh_tunnel / _db_pool 참조를 버리고 새로 할당하므로 이전 터널 스레드와 psycopg2 커넥션이 정리되지 않은 채 남습니다.
  2. shutdown_db_pool()_log_executor 를 종료하지 않습니다. 모듈 임포트 시점에 생성된 ThreadPoolExecutor(max_workers=4) 는 프로세스 종료 시까지 살아 있고, atexit 기본 동작에 의해 인터프리터가 끝날 때 pending 작업을 블로킹으로 기다립니다. 셧다운 훅에서 명시적으로 _log_executor.shutdown(wait=...) 호출이 필요합니다.
🛡️ 제안 패치
 def init_db_pool() -> None:
     global _ssh_tunnel, _db_pool
+    if _db_pool is not None:
+        return
     ssh_host = settings.ssh_host
     ...
 def shutdown_db_pool() -> None:
-    if _db_pool:
-        _db_pool.closeall()
-    if _ssh_tunnel:
-        _ssh_tunnel.stop()
+    global _db_pool, _ssh_tunnel
+    try:
+        _log_executor.shutdown(wait=True, cancel_futures=False)
+    except Exception as exc:
+        print(f"[chatbot_log executor shutdown ERROR] {exc}")
+    if _db_pool:
+        _db_pool.closeall()
+        _db_pool = None
+    if _ssh_tunnel:
+        _ssh_tunnel.stop()
+        _ssh_tunnel = None
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
_ssh_tunnel: Optional[SSHTunnelForwarder] = None
_db_pool: Optional[pg_pool.ThreadedConnectionPool] = None
_log_executor = ThreadPoolExecutor(max_workers=4, thread_name_prefix="chatbot_log")
_client: Optional[OpenAI] = None
_client_lock = threading.Lock()
class ChatReq(BaseModel):
text: Optional[str] = None
messages: Optional[list[dict[str, str]]] = None
engine: Optional[str] = None
def init_db_pool() -> None:
global _ssh_tunnel, _db_pool
ssh_host = settings.ssh_host
db_kwargs = dict(
dbname=settings.db_name,
user=settings.db_user,
password=settings.db_password,
connect_timeout=3,
options="-c statement_timeout=5000",
)
if ssh_host:
_ssh_tunnel = SSHTunnelForwarder(
(ssh_host, 22),
ssh_username=settings.ssh_user,
ssh_pkey=settings.ssh_key_path,
remote_bind_address=("localhost", 5433),
)
_ssh_tunnel.start()
db_kwargs.update(host="localhost", port=_ssh_tunnel.local_bind_port)
else:
db_kwargs["host"] = "localhost"
_db_pool = pg_pool.ThreadedConnectionPool(minconn=1, maxconn=5, **db_kwargs)
def shutdown_db_pool() -> None:
if _db_pool:
_db_pool.closeall()
if _ssh_tunnel:
_ssh_tunnel.stop()
_ssh_tunnel: Optional[SSHTunnelForwarder] = None
_db_pool: Optional[pg_pool.ThreadedConnectionPool] = None
_log_executor = ThreadPoolExecutor(max_workers=4, thread_name_prefix="chatbot_log")
_client: Optional[OpenAI] = None
_client_lock = threading.Lock()
class ChatReq(BaseModel):
text: Optional[str] = None
messages: Optional[list[dict[str, str]]] = None
engine: Optional[str] = None
def init_db_pool() -> None:
global _ssh_tunnel, _db_pool
if _db_pool is not None:
return
ssh_host = settings.ssh_host
db_kwargs = dict(
dbname=settings.db_name,
user=settings.db_user,
password=settings.db_password,
connect_timeout=3,
options="-c statement_timeout=5000",
)
if ssh_host:
_ssh_tunnel = SSHTunnelForwarder(
(ssh_host, 22),
ssh_username=settings.ssh_user,
ssh_pkey=settings.ssh_key_path,
remote_bind_address=("localhost", 5433),
)
_ssh_tunnel.start()
db_kwargs.update(host="localhost", port=_ssh_tunnel.local_bind_port)
else:
db_kwargs["host"] = "localhost"
_db_pool = pg_pool.ThreadedConnectionPool(minconn=1, maxconn=5, **db_kwargs)
def shutdown_db_pool() -> None:
global _db_pool, _ssh_tunnel
try:
_log_executor.shutdown(wait=True, cancel_futures=False)
except Exception as exc:
print(f"[chatbot_log executor shutdown ERROR] {exc}")
if _db_pool:
_db_pool.closeall()
_db_pool = None
if _ssh_tunnel:
_ssh_tunnel.stop()
_ssh_tunnel = None
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@LLM/OSS/service.py` around lines 47 - 90, init_db_pool is not idempotent and
can leak SSH tunnels and DB connections; before creating a new
SSHTunnelForwarder or ThreadedConnectionPool, check for and clean up existing
resources: if _ssh_tunnel is not None call _ssh_tunnel.stop() and set
_ssh_tunnel = None, and if _db_pool is not None call _db_pool.closeall() and set
_db_pool = None, then proceed to create and assign the new instances (refer to
init_db_pool, _ssh_tunnel, _db_pool). Also update shutdown_db_pool to explicitly
shutdown the log executor by calling _log_executor.shutdown(wait=False) (and
optionally set _log_executor = None) after closing the DB pool and stopping the
tunnel so the module-level ThreadPoolExecutor doesn't keep the process alive
(refer to shutdown_db_pool and _log_executor).

Comment thread text_filtering/service.py
Comment on lines 45 to 50
def get_device() -> torch.device:
if torch.backends.mps.is_available():
return torch.device("mps")
if torch.cuda.is_available():
return torch.device("cuda")
return torch.device("cpu")

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 | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: 디바이스 선택 로직을 검색하여 잘못된 패턴이나 일관성 없는 구현을 찾습니다.

# Test 1: torch.device 호출을 모두 찾아 컨텍스트와 함께 표시
echo "=== torch.device 사용 패턴 ==="
rg -n -C3 'torch\.device\(' --type=py

# Test 2: get_device 함수 정의를 모두 찾기
echo -e "\n=== get_device 함수 정의 ==="
ast-grep --pattern 'def get_device($$$): $$$'

# Test 3: CUDA/MPS 가용성 체크 패턴 찾기
echo -e "\n=== CUDA/MPS 가용성 체크 ==="
rg -n 'torch\.(cuda|backends\.mps)\.is_available\(\)' --type=py

Repository: dongsooop/AI

Length of output: 2105


디바이스 선택 로직의 우선순위와 버그를 수정하세요.

get_device() 함수의 MPS > CUDA 우선순위는 일반적인 성능 특성과 일치하지 않습니다. 같은 프로젝트의 LLM/finetune_chatbot.py에서는 CUDA > MPS > CPU 순서를 사용하고 있으므로, 전체 코드베이스에서 일관된 우선순위 전략을 정의하고 적용해야 합니다.

또한 text_filtering/bad_text_learning_model.py:129의 로직 오류를 반드시 수정하세요. 현재 코드는 CUDA가 사용 가능할 때 "mps"를 선택하는데, 이는 명백히 잘못된 조건문입니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@text_filtering/service.py` around lines 45 - 50, get_device() currently
prefers MPS over CUDA; change its priority to CUDA > MPS > CPU to match the
project's canonical ordering used in LLM/finetune_chatbot.py, i.e., check
torch.cuda.is_available() first, then torch.backends.mps.is_available(),
otherwise CPU. Also fix the logic in text_filtering/bad_text_learning_model.py
around the device selection (the incorrect branch at or near line 129 that picks
"mps" when CUDA is available) so it follows the same CUDA > MPS > CPU checks and
selects the correct torch.device string.

@Yu-JeSeung
Yu-JeSeung merged commit 74555e5 into main Apr 23, 2026
1 check passed
@Yu-JeSeung
Yu-JeSeung deleted the refactor/chatbot_services_routing branch April 23, 2026 13:17
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.

[REFACTOR] AI 서비스 전체 코드 리팩토링 진행

1 participant