LLM 파인튜닝 · RAG · 내과 도메인 데모

알려줄고양
내과 데이터로 직접 파인튜닝한 RAG 챗봇

내과 데이터를 학습시킨 도메인 특화 AI를 RAG로 구축한 내과 자문 챗봇입니다. 응급 상황을 대비해 Red Flag를 설계했고, 검색과 생성으로 사용자에게 자문을 제공합니다.

참고용 자문 도구이며 의학적 진단·처방을 대체하지 않습니다. 이상 증상은 전문 의료기관 방문.
이주형 · Lee Ju Hyeong팀장 · PM · 프론트엔드 · UX · AI 파이프라인 기획 · BM25+Hybrid 검색 설계 · 모델 학습·백엔드 50% 기여
Qwen2.5-7B-Instruct + LoRA Hybrid RAG (ChromaDB + BM25) FastAPI · Streamlit LLM Guardrails (RedFlag · PostFilter)
알려줄고양
안전 필터 ON
멋사 AI 엔지니어 NLP 부트캠프 · 팀 프로젝트 2
※ 참고용 자문 — 진단·처방 대체 불가
RedFlag 안전장치
응급 신호는 13개 BYPASS 정규식으로 LLM·RAG(검색 증강 생성) 도달 전에 즉시 종료하고 119를 안내합니다. 별도 37개 Red Flag 키워드(예: 고열)는 경고 배너로 응급실 방문을 안내한 뒤 대화를 이어갑니다.
RAG 출처 인용
Hybrid Retrieval(의미 검색 + 키워드 BM25 결합, α=0.5)로 의학 문서를 찾은 뒤, 참조한 청크와 유사도를 함께 보여줍니다.
멀티턴 문진
기간·악화요인·동반증상을 추가 질문으로 수집해 감별진단 정보 확보.
QueryNormalizer
일상어("머리 지끈")를 표준 의학용어("두통")로 변환해 검색어를 맞춥니다. 논문 근거로 설계했습니다.
QLoRA 도메인 특화
Qwen2.5-7B-Instruct를 내과 데이터로 LoRA(r=16, 일부 가중치만 학습하는 경량 미세조정) + 4-bit 양자화(NF4/QLoRA) 파인튜닝했습니다.
의사용 문진 요약 리포트
의심질병·참조 문서·인근 병원(카카오맵)을 의사 전달용으로 정리. PostFilter가 면책 조항 자동 삽입.

총 valid 1,248건을 유형별로 평가했습니다 — 객관식 995 · 단답형 148 · 서술형 105. 아래 점수는 각 유형 표본에서 나온 값입니다. (EM = 정답과 정확히 일치한 비율 · BERTScore·ROUGE-L = 서술 답변의 의미·표현 일치도)

Red Flag를 설계해 응급 상황을 대비한 이유: 2026 JAMA Network Open은 LLM 21종을 29개 임상 vignette로 평가해 감별진단 실패율 0.90–1.00을 보고했습니다. 외부 연구 결과이며 본 프로젝트의 성능 측정이 아닙니다. 이 위험이 안전 계층을 코드로 분리한 이유입니다.
0.71
객관식 EM · Mode C (LoRA+RAG)
Mode A 0.69 대비 · 객관식 995문항 기준 · 발표자료 p.35 · 독립 재실행 아님
0.73
서술형 BERTScore · Mode C
Mode A 0.70 대비 · ROUGE-L 0.14 vs 0.12 · 서술형 105문항 기준 · 발표자료 p.35
0.05
단답형 EM · Mode A
단답형 148문항 기준 · 전 모드 0.05~0.06 · 발표자료 p.35
Mode C가 전 지표에서 가장 높지만 Mode A 대비 +0.02~0.03 수준의 소폭 우위입니다. 3원 통제에서 Mode B(PDF 정본)는 객관식 EM 0.67 · 서술형 BERTScore 0.69 · ROUGE-L 0.11입니다. 단답형 EM은 0.05~0.06으로 낮습니다 — 한↔영 의학용어 표기 차이가 가능한 설명이지만 원인 비중은 검증하지 않았습니다. 모든 점수는 발표자료 기준이며, 버전 관리된 예측 CSV·평가 로그로 독립 재실행한 값은 아닙니다.
Problem Space

"인터넷 건강정보 이용률 84.4%인 사회에서, 범용 LLM의 감별진단 실패율은 90–100%."

한국보건사회연구원에 따르면 인터넷 건강정보 이용률은 84.4%이며, 이투데이 2021 기준 디지털 헬스케어 수요는 86.8% 늘었습니다. 하지만 병원 챗봇은 예약 안내 중심이고 LLM은 할루시네이션을 제공하며 포털 검색은 사이버콘드리아를 만들어냅니다. "내과 도메인을 학습시키고 안전하게 자문할 수 있도록" LoRA 파인튜닝+하이브리드 RAG+Guardrails로 만들었습니다.

※ 출처 — 인터넷 건강정보 이용률 84.4%: 한국보건사회연구원 · 디지털 헬스케어 수요 86.8%: 이투데이(2021) · 감별진단 실패율 90–100%: 2026 JAMA Network Open(LLM 21종 · 임상 vignette 29개) · LLM 할루시네이션 사례: 보도.

팀 구성4인 팀 프로젝트멋쟁이사자처럼 AI 엔지니어 NLP 부트캠프
역할팀장 · PM · 프론트 · UXAI 파이프라인 기획 · BM25+Hybrid 검색 설계 · 모델 학습·백엔드 50% 기여
기간약 1주일멋쟁이사자처럼 NLP 부트캠프 팀 프로젝트
현재 상태데모공개 데모 단계
베이스 모델Qwen2.5-7B-InstructQLoRA · LoRA r=16 · 4-bit NF4
Key Features

핵심 기능

UI/UX부터 LLM Guardrails(위험 출력을 막는 안전장치)까지, 의료 도메인 특성을 설계에 녹인 세 가지 기능입니다.

정규화 · Query

QueryNormalizer

일상 언어("머리 지끈지끈")를 표준 의학용어("두통")로 자동 변환합니다. BM25 키워드 검색의 재현율 저하를 막아 비전문가도 자연어로 접근할 수 있습니다. 피부질환 의료상담 챗봇 논문을 내과에 응용해 증상 표현→표준 의학용어 매핑(SYMPTOM_PATTERNS)을 설계했습니다. [설계]

안전 · LLM Guardrails

RedFlag · Emergency Exit

BYPASS 13개 정규식(심근경색·뇌졸중 등) 감지 즉시 LLM·RAG를 완전히 건너뛰고 119·응급실 가이드를 반환합니다. RED_FLAG 37개 키워드는 배너 경고를 띄운 뒤 정상 처리합니다. PostFilter가 단정형 어미를 권유형으로 바꿉니다.

리포트 · PostFilter

의사용 문진 요약 리포트

채팅 종료 후 의심 질병·참조 데이터·증상 목록·병원 안내(카카오맵)를 의사 전달용 리포트로 만듭니다. PostFilter가 면책 조항을 자동으로 붙입니다.

Engineering Deep-Dive

3대 설계 결정

컴퓨팅 제약·검색 품질·의료 안전, 세 병목을 각각 코드로 해결한 기록입니다.

01

QLoRA(r=16) — 컴퓨팅 제약을 설계로 역전 QLoRA · CoT

문제

Qwen2.5-7B-Instruct(76.1억 파라미터)는 당시 컴퓨팅으로 Full Fine-Tuning이 불가능했습니다.

해결

QLoRA — LoRA(모델을 가볍게 미세조정하는 기법 · r=16)에 4-bit 양자화(nf4)를 더해(train_config.yaml) 단일 GPU에서 도메인을 적응시켰습니다. 학습 데이터는 OpenAI API로 CoT(Chain-of-Thought, 단계별 추론 과정을 명시하는 기법) 전처리했습니다. instruction = "주어진 임상 문제 및 환자 상태를 분석하여, 최적의 진단/처치 또는 의학적 근거를 논리적인 추론 과정과 함께 서술하시오." Raw {question, answer} → PreCleaned {instruction, input, output: [상황 및 핵심 파악]→[의학적 추론 및 근거]→[최종 결론]} 3단 구조로 재구성했습니다. 평가: 객관식 EM(정답과 정확히 일치한 비율) 0.71 (Mode C) [실측-발표자료]

02

FAISS→ChromaDB + BM25 하이브리드 α=0.5 RAG · Kiwi

문제

초기 FAISS 기반 밀집 검색은 의학 전문용어의 형태 변형에 취약했습니다. 메타데이터 관리와 확장성도 부족했습니다.

해결

ChromaDB로 전환 후 BM25Okapi+Kiwi 형태소와 α=0.5 가중치로 Hybrid Retrieval(키워드 검색과 의미 검색을 합친 방식)을 구성했습니다. QueryNormalizer로 일상어→표준 의학용어를 매핑해 27,000 chunk [설계]에서 재현율과 접근성을 함께 확보했습니다.

03

LLM Guardrails — RedFlag 3층 안전필터 코드화 Safety · PostFilter

문제

응급 상황에서 LLM 응답이 그대로 나가거나 단정적 진단 표현이 출력되면 법적·의료적 위험이 생깁니다.

해결

Guardrails 3층 구조를 코드로 구현했습니다. ① BYPASS 13 정규식 → Emergency Exit(119 안내, LLM 완전 우회) ② RED_FLAG 37 키워드 → 경고 배너 표시 후 정상 처리 ③ PostFilter → 단정형 어미를 권유형으로 변환하고 면책 조항을 자동 삽입합니다. [설계]

System Design

아키텍처 & 데이터 흐름

사용자 쿼리가 Guardrails·검색·생성 파이프라인을 거쳐 검증된 응답으로 나오는 구조입니다.

↩ 검증된 응답 (PostFilter → 권유형·면책 삽입) · downlink 사용자 Query 자연어 증상 입력 Streamlit :8501 4단계 플로우 UI FastAPI :8000 ChatService 오케스트레이터 LLM Guardrails RedFlag + PostFilter Retrieval Dense + BM25 Hybrid GenerationService OpenAI / Qwen+LoRA ChromaDB 27,000 chunk query uplink →
3-Stage 학습 커리큘럼 [실측-발표자료] 질문 유형별 점진 학습 — max_len 점증 · lr 점감
Stage 질문 유형 max_len batch learning rate epoch
Stage 1 단답형 560 4 0.002 2
Stage 2 서술형 730 2 0.001 2
Stage 3 객관식 840 2 0.0005 2
max_len 560 → 730 → 840 점증 · lr 0.002 → 0.001 → 0.0005 점감 커리큘럼 — 짧고 명확한 유형 먼저 학습 후 복잡 유형으로 점진 전환.
① Streamlit :8501 — 4단계 플로우

Disclaimer → Profile → Chat → Report

면책 동의 없이는 시작할 수 없습니다(Step -1). 연령·성별 버튼 입력(Step 0). 증상 자연어 채팅 + RedFlag 배너(Step 1). 의사용 문진 요약 리포트(Step 2). 알려줄고양 고양이 페르소나가 온보딩 친근 톤("~다냥")↔결과 전문 톤으로 전환합니다.

Streamlit4-step Flow카카오맵 API
HTTP REST ↑
② FastAPI :8000 — ChatService 오케스트레이터

LLM Guardrails · RetrievalService · GenerationService

요청이 들어오면 Guardrails(BYPASS→Emergency Exit / RED_FLAG→배너)가 먼저 판단합니다. 통과하면 RetrievalService(Dense+BM25 Hybrid·QueryNormalizer)→GenerationService(OpenAI/Qwen+LoRA) 순으로 처리하고 PostFilter가 어미를 교정합니다.

FastAPIRedFlagDetectorPostFilterko-sroberta-multitask
Vector + BM25 Search
③ RAG 계층 — ChromaDB + BM25 Hybrid

27,000 chunk · α=0.5 하이브리드 결합

3,447 내과 문서(약 1,229만 자)를 size500/overlap50으로 청킹해 ChromaDB에 저장했습니다. ko-sroberta-multitask(768차원) 밀집 검색 + Kiwi 형태소 BM25 키워드 검색을 α=0.5로 합쳐 의학 전문용어 재현율을 보강합니다.

ChromaDBBM25OkapiKiwiko-sroberta-multitask 768d
Experiment Results

3원 통제 비교 실험

동일 평가셋(valid 1,248)에서 변수(RAG·LoRA)를 하나씩 추가해 각 설계 선택의 독립 기여도를 분리했습니다.

Mode A
베이스라인
Qwen2.5-7B
+ RAG
Mode B
검색 결합
Qwen2.5-7B+ Hybrid RAG
+ LoRA
Mode C
도메인 파인튜닝
Qwen2.5-7B+ LoRA+ Hybrid RAG
eval 루프 평가셋 설계 통제 비교 지표 해석 한계 인식
EM정답 정확 일치(객관식·단답형) Rouge-L서술형 문장 재현 BERT Score서술형 의미 유사
Mode 구성 객관식 EM
valid 995
서술형 BERT
valid 105
서술형 Rouge-L
valid 105
단답형 EM
전 모드
Mode A LLM 단독 0.69 0.70 0.12 0.05 — 지표 한계
Mode B LLM + RAG 0.67 0.69 0.11 0.06 — 지표 한계
Mode C LoRA + RAG 0.71 (+0.02) 0.73 (+0.03) 0.14 (+0.02) 0.06 — 지표 한계
위 수치는 발표자료 기준 측정값입니다. [실측-발표자료] (출처: 발표자료 Generation 2/2 슬라이드 · Mode B는 PDF 정본값) 단답형 EM(0.05~0.06)이 낮은 데는 한↔영 의학용어 표기 차이가 가능한 설명입니다 — "두통" vs "headache"처럼 동일 개념의 한영 혼재로 엄격 EM이 과소평가될 수 있어, 채점용 한영 사전을 만들어 분석했습니다(원인 비중은 검증하지 않았습니다). Mode C의 정성적 강점은 일상어→의학용어 자동 변환(QueryNormalizer)·응급 종료(Emergency Exit)·의사용 문진 요약 리포트 UX로 의료 도메인 특성을 설계에 녹인 점입니다.
Demo

데모 영상 — 시나리오 4종

RedFlag 2단 안전장치(긴급/경고)와 싱글·멀티턴을 실제 시연한 4개 시나리오.

RAG · 검증 연계

멀티홉 팩트체킹 — 같은 설계 사고

부트캠프 팀 프로젝트 1(멀티홉)에서 같은 하이브리드 검색 설계 사고를 다른 도메인에 구현했습니다. ChromaDB 밀집 검색 단독으로는 홉 깊이가 깊어질수록 의미론적 오류가 급증합니다. 이를 데이터로 확인하고 BM25+ProgramFC 하이브리드로 전환한 근거를 만들었습니다.

ChromaDB 단독 · 홉별 의미론적 오류율 [실측-자체분석]

홉 깊이가 깊을수록 오류 급증 → BM25 하이브리드 전환 근거
2홉
29%
29%
3홉
38%
38%
4홉
77%
77%
출처: 멀티홉 구현 Read.me 자체 오류 분석 · [실측-프로젝트자체분석]
최종 성능치(Recall@10·Macro-F1): [측정전] — 구현 Read.me "미정" 명시
공통 설계 사고

두 프로젝트 모두 "하이브리드 검색으로 검색 품질을 보강하고, 단계별 Guardrails(RedFlag / Unknown Guard)로 오류 전파를 차단한다"는 같은 검증 설계 사고를 공유합니다.

작가 기여 (멀티홉)

팀장 · 검색 모듈(BM25+하이브리드 리트리버) 담당.

적용 근거 (의료챗봇)

멀티홉에서 확인한 벡터 검색 단독의 한계를, 의료챗봇 BM25+ChromaDB 하이브리드 설계에 직접 반영했습니다. 같은 방법론을 다른 도메인에 이식한 사례입니다. RAG(검색해서 그 내용으로 답하는 구조)를 단계별로 분해해 평가하는 관점이 두 프로젝트를 관통합니다.

멀티홉 팩트체킹 포트폴리오 열기
Retrospect

회고 · 현재 한계 · 다음 단계

현재 한계와 다음 단계를 기록합니다.

단답형 EM 지표 한계 — 0.05~0.06 [실측-발표자료]

한↔영 의학용어 표기 차이(예: "두통" vs "headache")로 EM(정답과 정확히 일치한 비율) 자체가 낮게 측정됩니다. 동일 개념을 한영으로 혼재 표기하면 엄격 일치 채점이 정답을 오답으로 처리합니다. 이를 보완하기 위해 채점용 한영 Dictionary를 생성해 분석했습니다. 발표자료도 과대포장 없이 그대로 노출했습니다.

→ 의학용어 사전 확장 + Fuzzy Match(edit distance 기반) 또는 BERT Score(문장 의미 유사도 점수) 대체 평가로 개선할 수 있습니다. 엄격 EM이 과소평가하는 구조를 인지하고 eval 개선 시 반영할 예정입니다.

현재 한계 — Retrieval 품질: Reranker 미탑재

현재 파이프라인은 하이브리드 검색(BM25+Dense) 결과를 LLM에 바로 넘깁니다. Reranker(검색 결과를 다시 정밀하게 정렬하는 모듈)가 없어 상위 k개 청크 중 노이즈가 섞일 수 있습니다.

다음 단계 — 미구현

Reranker(cross-encoder) 삽입: bi-encoder(현재 ko-sroberta)로 빠르게 후보를 압축한 뒤 cross-encoder로 정밀 재정렬하는 2-stage retrieve→rerank 구조입니다. 속도(bi-encoder)와 정확도(cross-encoder)의 트레이드오프를 분리하는 표준 접근입니다.

근거: Nogueira & Cho, "Passage Re-ranking with BERT" (2019) — 2-stage retrieve→rerank 정립. BAAI bge-reranker(FlagEmbedding) = production RAG 표준 도구.

왜 이 기술인가: 현재 α=0.5 하이브리드 가중치로 검색 품질을 일부 보완했습니다. 의학 전문 쿼리에서 컨텍스트 관련성 순위를 스코어로 재정렬하면 생성 단계 할루시네이션이 줄어들 것으로 봅니다.

→ 다음 파이프라인 개선 시 cross-encoder Reranker 삽입 예정. 현재 단계에선 미구현.

현재 한계 — Retrieval 품질 지표: RAGAS 미측정

현재 eval은 EM·BERT Score(문장 의미 유사도 점수)·Rouge-L로 생성 품질만 측정했습니다. "검색된 컨텍스트가 생성에 얼마나 충실히 반영됐는가(faithfulness, 생성된 답이 근거 문서에 충실한 정도)"와 "관련 컨텍스트를 얼마나 찾았는가(context recall)"는 측정하지 못했습니다.

다음 단계 — 미구현

RAGAS(RAG 품질을 자동 평가하는 프레임워크) 기반 Retrieval 품질 평가: faithfulness·context recall·answer relevancy를 정답 레이블 없이 자동으로 측정합니다. 현재 EM/BERT만으로는 검색 단계의 품질을 진단하기 어렵습니다.

근거: Es et al., "RAGAS: Automated Evaluation of Retrieval Augmented Generation" (arXiv:2309.15217, 2023) — faithfulness·context recall·answer relevancy 자동 평가 체계.

왜 이 기술인가: "생성이 좋다"와 "검색이 좋다"는 별개입니다. RAGAS faithfulness·context recall을 적용하면 할루시네이션이 어느 단계(검색 vs 생성)에서 나오는지 분리해 진단할 수 있습니다. RAG를 단계별로 분해 평가하는 관점의 직접 도구입니다.

→ 향후 파이프라인 개선 시 RAGAS 측정 적용 예정. 이 갭을 인식하는 것 자체가 eval 설계 역량의 일부입니다.

내과 한정 — 타과 확장 시 재설계 필요

현재 27,000 chunk 데이터는 내과 Q-A 쌍입니다. 외과·정신과 등 타 진료과로 확장하려면 도메인별 데이터와 Guardrails를 다시 구성해야 합니다.

→ 진료과별 데이터 파이프라인 모듈화 방향

3-Stage 학습 커리큘럼 확정 [실측-발표자료]

발표자료로 질문 유형별 점진 학습 순서를 확정했습니다. Stage 1(단답형 · max_len 560 · lr 0.002) → Stage 2(서술형 · 730 · 0.001) → Stage 3(객관식 · 840 · 0.0005). max_len을 단계마다 늘리고 lr을 줄이는 점진 커리큘럼으로, 짧고 명확한 유형 먼저 학습 후 복잡 유형으로 전환했습니다. 전 단계 QLoRA(LoRA r=16 · 4-bit nf4) 동일 적용.

→ 발표자료로 확정. 아키텍처 섹션 커리큘럼 표 참조.

리팩토링 예정

현재 성능으로 리팩토링이 가능합니다. 재측정 후 위 수치를 갱신할 예정입니다.

→ 리팩토링 완료 후 수치 일괄 갱신
Tech Stack

기술 스택

LLM · 학습

  • Qwen2.5-7B-Instruct
  • QLoRA (LoRA r=16 · 4-bit nf4)
  • OpenAI API (CoT)
  • ko-sroberta-multitask

RAG · 검색

  • ChromaDB
  • BM25Okapi + Kiwi
  • Hybrid α=0.5
  • QueryNormalizer

LLM Guardrails · 백엔드

  • FastAPI :8000
  • RedFlagDetector
  • PostFilter
  • 카카오맵 API

프론트 · 데이터

  • Streamlit :8501
  • train 10,299 QA
  • valid 1,248
  • 27,000 chunk
Data Provenance

데이터 출처 — 학습·RAG

무엇을 학습시키고 검색시켰는지 출처와 함께 밝힙니다. [실측-AI-Hub] 원본 데이터를 재배포하지 않으며, 본 포트폴리오는 설계·방법·결과만 공개합니다(clean-room).

필수의료 의학지식 데이터

AI-Hub 데이터셋 번호 71875

과학기술정보통신부·한국지능정보사회진흥원(NIA) 구축, 가톨릭대학교 산학협력단 주관. 서울성모·삼성서울·서울대·세브란스·보라매병원 참여. 내과 도메인 질의응답 쌍 수록.

출처 보기

전문 의학지식 데이터

AI-Hub 데이터셋 번호 71874

동일 구축 주관(과학기술정보통신부·NIA·가톨릭대학교 산학협력단). 의학 교과서·학회 가이드라인·온라인 의료 정보를 원천으로 하는 의학 말뭉치 수록. RAG 청킹 원천.

출처 보기
본 프로젝트 사용 범위 [실측-AI-Hub]

내과 도메인 질의응답 12,781쌍을 train / valid(10,299 / 1,248)로 분할·CoT(Chain-of-Thought, 단계별 추론 과정을 명시하는 기법) 전처리 후 LoRA(가볍게 미세조정하는 기법) 학습에 사용했습니다.

원천 의학 말뭉치(의학 교과서·학회 가이드라인·온라인 의료 정보)를 청킹 → RAG(검색해서 그 내용으로 답하는 구조) 약 27,000 chunk 구성. 학술 논문·기타(동의서 등)는 미사용.

이용·라이선스

AI-Hub 보건의료 데이터로 안심존(보안구역) 개방 방식으로 제공됩니다(연구·개발 목적, IRB·내국인 신청 기반).

원본 데이터는 재배포하지 않습니다. 본 포트폴리오는 해당 데이터를 활용한 설계·방법·결과만 공개합니다. 공개 데이터를 활용한 프로젝트입니다.

구축 기관 요약
주무부처: 과학기술정보통신부 · 총괄: 한국지능정보사회진흥원(NIA) · 주관: 가톨릭대학교 산학협력단 · 참여 병원: 서울성모·삼성서울·서울대·세브란스·보라매병원. — AI-Hub 공식 페이지 기준.

안전을 코드로 설계한 내과 자문 챗봇

LoRA·하이브리드 RAG·Guardrails를 결합해 "안전하게 자문하는" 공백을 채웠습니다. 3원 통제 실험으로 각 설계 선택의 기여도를 분리해 측정했습니다.