의료 챗봇 개발기 (1): GraphRAG의 이상과 현실, 실패회고

hbjs97·2025년 8월 12일

의료 챗봇

목록 보기
1/2

안과 의료 챗봇을 개발하며 GraphRAG를 도입했다가 실패한 경험을 공유한다.
이 글은 GraphRAG를 고려하는 분들에게 "이론의 매력"과 "현실 구현의 함정"을 함께 보여주고, 실무에서 바로 적용할 수 있는 교훈을 남기기 위해 작성한다.

의료 도메인의 특수성과 GraphRAG 도입 배경

프로젝트 요구사항

처음 받은 요구사항은 명확했다. 단순한 의료 상담 챗봇이 아니라, 정확한 수치와 근거를 기반으로 한 전문적 수준의 답변을 제공하는 시스템이 필요했다.

예를 들어, "백내장 수술을 고민 중입니다"라는 질문에 대해:

  • 병리학적 관점: 백내장의 진행 단계와 수술 필요성 판단 기준
  • 임상적 관점: 수술 방법별 특징과 적응증
  • 약리학적 관점: 수술 전후 사용 약물과 주의사항
  • 예후적 관점: 수술 후 시력 회복 과정과 장기 결과
  • 경제적 관점: 보험 적용 여부와 비용

추가로 한국 의료 환경에 맞춰 국내 유통 의약품 정보와 보험 급여 기준까지 포함해야 했다.

환자 컨텍스트와 대화 이력 활용

가장 중요한 요구사항 중 하나는 환자 개별 컨텍스트를 반영한 맞춤형 답변이었다. 시스템은 대화 중에 계속해서 추론하고 데이터를 검색하도록 설계되어야 했다:

  1. 환자 정보 통합: 나이, 기저질환, 현재 복용 약물을 고려한 답변
  2. 대화 이력 추적: 이전 질문-답변을 기억하고 문맥 유지
  3. 연속적 추론: 답변 생성 중에도 필요한 정보를 실시간으로 검색
  4. 점진적 정제: 초기 답변을 생성하면서 동시에 추가 정보로 보완

예를 들어 "당뇨가 있는데 백내장 수술 가능한가요?"라는 질문에:

  • 일반적인 백내장 수술 정보 검색
  • 당뇨 환자의 수술 위험도 추가 검색
  • 혈당 조절 관련 가이드라인 확인
  • 수술 전후 약물 조정 사항 검토

이 모든 과정이 하나의 답변을 생성하는 동안 연속적으로 일어나야 한다는 점이 핵심 요구사항이었다.

위 요구사항은 예시이며, 사용자의 질문에 따라 대화 맥락에 따라 구체적이고 다양한 관점에서의 답변을 제공하는것이 요구사항이었다. (추상적임)

왜 GraphRAG였나

의료 지식은 본질적으로 관계형 데이터다. 질병과 증상, 약물과 부작용, 치료법과 예후가 복잡하게 연결되어 있기 때문에, GraphRAG(Graph Retrieval-Augmented Generation)가 이러한 구조를 활용해 정확한 답변을 생성할 수 있을 것으로 기대했다. 특히 LangGraph를 통해 체계적인 파이프라인을 구축할 수 있다는 점도 매력적이었다.

UMLS - 국제 표준 의료 온톨로지

의료 지식 베이스가 필요한 상황에서 UMLS(Unified Medical Language System)를 선택하게 되었다. NIH에서 제공하는 이 시스템은 세계 최대 규모의 의료 온톨로지로, 우리의 요구사항을 충족시킬 수 있을 것으로 판단했다.

UMLS 데이터 다운로드와 Neo4j 변환

UMLS 다운로드 - 첫 번째 난관

UMLS는 보안상의 이유로 직접 다운로드가 불가능하며, UTS(UMLS Terminology Services) 계정 생성과 의료 라이센스 동의가 필수다.

1. UTS 계정 생성 (https://uts.nlm.nih.gov/uts/signup-login)
2. 라이센스 동의 (의료 목적 사용 조건)
3. 2025AA Full Release 다운로드 (5.1GB)

5.1GB라는 대용량 파일을 다루어야 했다.

MetamorphoSys로 서브셋 추출

전체 UMLS 데이터는 방대해서 필요한 부분만 추출해야 한다는 결론에 도달했다. MetamorphoSys라는 도구를 사용해 CDSS(Clinical Decision Support System)에 필요한 서브셋을 만들었는데, 여기서 수백 개의 Semantic Types 중 어떤 것을 선택할 것인가라는 중요한 결정을 내려야 했다.

13개 Semantic Types 선택

긴 고민 끝에 다음 13개만 선택하기로 결정했다:

질병 관련 (5개)

  • T047: Disease or Syndrome → Disease
  • T191: Neoplastic Process → Cancer
  • T037: Injury or Poisoning → Injury
  • T048: Mental or Behavioral Dysfunction → PsychiatricCondition
  • T046: Pathologic Function → DisorderFunction

증상/소견 (3개)

  • T184: Sign or Symptom → Symptom
  • T033: Finding → ClinicalFinding
  • T034: Laboratory or Test Result → LabResult

약물 (2개)

  • T121: Pharmacologic Substance → Drug (순수 활성성분)
  • T200: Clinical Drug → Medication (실제 처방되는 완제품)

시술 (2개)

  • T061: Therapeutic or Preventive Procedure → MedicalProcedure
  • T060: Diagnostic Procedure → DiagnosticTest

기타 (1개)

  • T170: Intellectual Product → ClinicalGuideline

Drug와 Medication의 구분이 특히 중요했는데, "아스피린"은 Drug(성분)에 해당하고 "바이엘 아스피린 100mg 장용정"은 Medication(실제 제품)에 해당한다.
UMLS의 미국 중심 의약품 정보와 별도로 확보한 한국 의약품 데이터를 함께 사용해야 했다. (UMLS 그래프에 데이터 추가 필요)

22개 관계 타입 매핑

UMLS의 복잡한 관계 이름을 LLM이 이해하기 쉽게 변환했다:

UMLS 관계LLM 친화적 이름건수
isaIS_A1.96M
inverse_isaHAS_SUBTYPE1.96M
has_ingredientHAS_INGREDIENT145K
has_manifestationCAUSES_SYMPTOM133K
disease_may_have_findingMAY_PRESENT_WITH19K

이런 식으로 22개 관계를 모두 매핑했다.

Neo4j 변환 결과

변환 스크립트를 돌린 결과:

입력 파일:
- MRCONSO.RRF: 551MB (개념 정보)
- MRREL.RRF: 1.3GB (관계 정보)
- MRSTY.RRF: 91MB (Semantic Type)

출력:
- 약 1.3M개 개념 노드 (영어 용어만)
- 약 4.2M개 관계 엣지

처음에는 Cypher 스크립트로 임포트를 시도했다. APOC의 apoc.export.cypher.all()로 추출한 스크립트를 실행했는데, 너무 느려 포기했다. 결국 neo4j-admin import를 사용해 6.8초만에 임포트를 완료했다.

GraphRAG 시스템 구현

LangGraph 7단계 파이프라인

LangGraph를 사용해 파이프라인을 구축했다.

1. normalize_query: 질문 정규화 (한국어 → 영어, UMLS 표준화)
2. discover_entities: 의료 엔티티 발견
3. analyze_and_decompose: 복잡한 질문 분해 및 템플릿 매칭
4. generate_cypher: Cypher 쿼리 생성
5. validate_cypher: 쿼리 검증
6. execute_cypher: Neo4j 실행
7. make_context: 컨텍스트 생성

연속적 추론과 데이터 검색 프로세스

단순히 순차적으로 실행되는 것이 아니라, validate_cypher 실패 시 generate_cypher로 돌아가는 루프 구조였다:

질문: "당뇨약 복용 중인데 백내장 수술 가능한가요?"

[1. 의료 용어 정규화]
  → "당뇨약" → "antidiabetic medication", "diabetes medication"
  → "백내장 수술" → "cataract surgery", "phacoemulsification"
  → 한국어-영어 의료 용어 매핑 테이블 참조

[2. discover_entities]
  → 정규화된 용어로 UMLS 엔티티 검색
  → "당뇨약", "백내장 수술" 엔티티 추출
  → 환자 컨텍스트와 함께 전달

[3. analyze_and_decompose]
  → 질문을 여러 관점으로 분해
  → 113개 템플릿 중 매칭되는 것 선택
  → 병렬로 처리할 서브 질문 생성

[4-5-6 루프: generate → validate → execute]
  1차 시도:
    → generate_cypher: 잘못된 관계 타입 사용
    → validate_cypher: 검증 실패 (is_valid: false)
    → 다시 generate_cypher로 (최대 3회)

  2차 시도:
    → generate_cypher: 피드백 반영하여 재생성
    → validate_cypher: 검증 성공
    → execute_cypher: 결과 없음 (0 rows)

  3차 시도:
    → 다른 템플릿 시도
    → 검증 성공했지만 여전히 결과 없음

[7. make_context]
  → Neo4j 쿼리 결과를 의료적 내러티브로 변환
  → Semantic Field Analysis: 동적 키-값 구조에서 의미 추출
  → 결과가 없을 때: Cypher 쿼리 패턴 분석 → 의료적 검색 방향 제시

Self-healing 메커니즘

Cypher 쿼리가 잘못 생성되면 자동으로 재시도하는 기능을 구현했다:

  1. 검증 실패 감지
  2. 오류 메시지와 개선 제안 수집
  3. 피드백을 포함한 개선된 프롬프트로 재생성
  4. 최대 3회까지 재시도

문제점:

  • Cypher 생성-검증만 루프를 돌아 근본적 해결 안 됨
  • 재시도 사이클마다 llm 호출 및 cypher 실행, 검증으로 응답 시간 증가

첫 번째 문제 - Text to Cypher 정확도

복잡한 스키마의 함정

13개 노드 타입 × 22개 관계 타입 = 복잡한 조합의 문제

LLM에게 이 복잡한 스키마를 이해시키고 올바른 Cypher 쿼리를 생성하게 하는 것은 거의 불가능했다.

실제로 생성된 쿼리들을 보면:

잘못된 예시 1: 한국어 직접 사용

MATCH (d:Disease {name: '황반변성'})-[:HAS_SYMPTOM]->(s)

문제: UMLS는 영어만 있고, HAS_SYMPTOM이 아니라 CAUSES_SYMPTOM이 맞다.

잘못된 예시 2: Cartesian Product

MATCH (d:Disease), (s:Symptom)
WHERE d.name CONTAINS 'diabetic' AND s.name CONTAINS 'vision'
RETURN d, s
LIMIT 10

문제: Cartesian Product로 인한 성능 문제:

  • 질병 노드 500개 × 증상 노드 200개 = 100,000개 조합 생성
  • WHERE 절 필터링 전에 모든 조합을 메모리에 로드
  • LIMIT 10을 적용해도 이미 10만개 조합 계산 완료
  • 올바른 접근: MATCH (d:Disease)-[:CAUSES_SYMPTOM]->(s:Symptom) 처럼 관계 명시

템플릿 기반 개선 시도

이 문제를 해결하기 위해 113개의 의료 질문-쿼리 템플릿을 만들었다. 각 템플릿은:

  • 질문 패턴
  • 필요한 노드 타입
  • 사용할 관계 타입
  • 검증된 Cypher 쿼리

여기에 BAAI/bge-reranker-base 리랭커까지 도입해서 가장 적합한 템플릿을 선택하도록 했다.

어느 정도 개선되었지만, 여전히 잘못된 쿼리를 생성하는 경우가 있다.
추가적인 cypher 생성 rule 은 cypher 생성 프롬프트에 더 구체적으로 추가했다.

두 번째 문제 - 검색 정확도

다국어 → UMLS 변환 문제

사용자는 다국어로 질문하고, UMLS는 영어 표준 용어만 있다. 이 간극을 메우는 게 생각보다 훨씬 어려웠다.

같은 의미의 질문도 다양하게 표현된다:

  • "당뇨병성 망막병증"
  • "당뇨 망막병증"
  • "당뇨성 망막증"
  • "DM retinopathy"

LLM에게 이걸 UMLS 표준 용어로 변환하라고 하면 Temperature를 0으로 설정해도 종종 다른 결과가 나왔다.

Neo4j + Milvus 하이브리드 검색

이 문제를 해결하기 위해 벡터 검색을 추가했다:

  1. Neo4j 그래프를 1-hop 관계까지 포함해서 Milvus에 임베딩
  2. 사용자 질문을 벡터화해서 유사한 개념 검색
  3. 찾은 CUI로 다시 Neo4j 쿼리

문제는 백만 개가 넘는 노드를 임베딩해야 한다는 것이었다. intfloat/multilingual-e5-base 모델을 로컬 CPU에서 실행했다.

의료 문서 청킹 전략

Neo4j 노드 임베딩과 함께, 의료 문서들도 Milvus에 저장해야 했다. 의료 문서는 일반 문서와 다른 특성이 있다:

  1. 전문 용어와 약어: OCT, AMD, RPE 등 19개의 핵심 약어
  2. 표 데이터: 검사 결과, 수치 데이터가 표 형태로 제공
  3. 계층적 구조: 진단 → 검사 → 치료의 논리적 흐름
  4. 문맥 의존성: 원인-결과, 치료-반응의 밀접한 연관성

어떤 청킹 전략이 가장 효과적일지 4가지를 실험했다:

  1. SimpleChunkingStrategy: 기본적인 토큰 기반 분할
  2. TablePreservingChunker: 테이블 무결성 보장
  3. MedicalSemanticChunker: 의료 용어 패턴 인식

RAGAS(Retrieval Augmented Generation Assessment)로 평가한 결과:

전략RAGAS 점수특징
TablePreservingChunker0.8571테이블 보호 + 안정성
MedicalSemanticChunker0.8786의료 용어 특화
Simple Recursive0.7981기본 방식

MedicalSemanticChunker가 더 높은 점수를 보였지만, 실제 운영 환경에서는 TablePreservingChunker를 선택했다:

선택 이유:

  1. 과적합 위험: MedicalSemanticChunker는 19개 약어와 복잡한 가중치 계산(50-30-20)으로 특정 테스트셋에 과적합될 가능성
  2. 운영 안정성: TablePreservingChunker는 단순한 규칙(테이블 앞뒤 100자 포함)으로 예측 가능한 동작
  3. 유지보수성: 하이퍼파라미터가 적어 튜닝과 디버깅이 용이

실제로 점수 차이보다 운영 환경에서의 안정성과 예측 가능성이 더 중요했다.

임베딩 병목 현상

로컬 임베딩 실행 환경:

모델: intfloat/multilingual-e5-base (768차원)
장비: M4 MacBook Pro (24GB)
배치 크기: 50개
워커 수: 15개 (ThreadPoolExecutor)
처리 시간: 약 1시간

임베딩 데이터 구조:

Neo4j 노드를 단순히 이름만 임베딩한 것이 아니라, 관계 정보를 포함한 JSON 구조로 변환했다. 각 노드는 최대 20개의 관계(들어오는 10개, 나가는 10개)를 포함하여 평균 250토큰 정도의 크기를 가졌다.

OpenAI API 비용 분석:

노드 수: 1,324,567개
평균 토큰: 250 per node (관계 정보 포함)
총 토큰: 331,141,750

text-embedding-3-large 비용:
- 단가: $0.13 per 1M tokens
- 총 비용: 약 $43.05

문제점:
- Neo4j 데이터 업데이트 시마다 재임베딩 필요
- 업데이트 할 노드의 연관관계에 있는 노드들도 함께 재임베딩 필요 (복잡도 증가)

위 사항들을 고려해 우선 로컬 임베딩을 선택했다. M4 MacBook Pro에서 1시간이면 완료되었다.

리랭커 사용 이슈

BAAI/bge-reranker-base를 로컬에서 실행했다. M4 MacBook Pro에서는 사용할 만한 성능이었지만, 순수 CPU 환경에서는 성능 문제가 예상되었다. GPU 서버를 두고 사용하기에는 비용, 운영 복잡성, 디바이스 호환성 등 고려할 사항이 너무 많았다.

복잡한 시스템의 현실

과도한 엔지니어링

완성된 시스템을 돌아보니 너무 복잡했다:

인프라 복잡성:

  • 4개 데이터베이스 (Neo4j, Milvus, PostgreSQL, Redis)
  • HuggingFace 모델 사용 (리랭커, 임베딩 모델)
  • 113개 템플릿 관리
  • 13개 노드 타입 × 22개 관계 타입

실제 활용도:

전체: 1.3M 노드, 4.2M 관계
실제 사용: 주요 안과 질환, 관련 약물

백내장, 녹내장, 황반변성 등 안과에서 다루는 핵심 데이터를 위주로 사용되었고, UMLS의 대부분은 조회되지 않았다.

정말 Neo4j가 필요했을까?

Neo4j를 선택한 이유:

  • 의료 지식은 관계형 데이터
  • GraphRAG가 주목받는 기술
  • 복잡한 관계 탐색이 필요할 것으로 예상

실제로 필요했던 것:

  • 신뢰할 수 있는 의료 정보
  • 빠른 검색 속도
  • 한국 의료 환경 데이터
  • 운영 가능한 시스템

Neo4j가 준 것:

  • 복잡한 스키마 설계 고민
  • Text-to-Cypher 정확도 문제
  • 130만개 노드 중 소수만 활용
  • 운영 복잡성 증가

결론적으로, 복잡한 그래프 구조 대신 벡터 검색과 실시간 웹 검색의 조합이 더 실용적이었다. GraphRAG의 이론적 우아함에 매료되어, 실제 필요한 것이 무엇인지를 놓쳤다.

실패에서 얻은 교훈

1. 복잡한 솔루션의 함정

"의료 도메인은 복잡하므로 복잡한 솔루션이 필요하다"는 생각이 틀렸다. 복잡성은 복잡성을 낳을 뿐, 문제를 해결하지 못했다.

GraphRAG는 이론적으로 매력적이지만, 실제 구현에서는:

  • 스키마 설계의 어려움
  • LLM의 이해도 한계
  • 운영 복잡성 증가
  • 디버깅 복잡성

2. 데이터의 질 > 양

UMLS는 방대하지만 치명적인 단점이 있었다. 대부분의 노드에 description이 없다. 단순히 개념 이름과 관계만 있을 뿐, 실제 의료 정보가 부족했다.

결과적으로 LLM이 답변을 생성할 때 할루시네이션이 발생할 위험이 높았다. "이 약물이 이 질병을 치료한다"는 관계는 알지만, "어떻게, 왜, 언제" 치료하는지는 알 수 없었다.

3. 단순함의 가치

청킹 전략 실험에서 배운 가장 중요한 교훈이다. TablePreservingChunker처럼 단순하지만 핵심을 지키는 접근이 더 효과적이었다.

# 최종 선택
config = ChunkingConfig(
    chunk_size=1000,
    chunk_overlap=200,
    strategy="table_preserving_chunker",
    splitter="sentence_transformer"
)

4. 연속적 추론의 함정

"대화 중 계속 추론하고 데이터를 검색한다"는 요구사항이 시스템을 복잡하게 만들었다.

  • 이상: 필요한 정보를 실시간으로 찾아가는 지능적 시스템
  • 현실: 무한 루프에 빠지거나 관련 없는 정보를 계속 검색
  • 교훈: 명확한 경계와 제한이 없는 "연속적 추론"은 위험

GraphRAG 성공을 위한 올바른 접근법

실패를 돌아보며, "만약 GraphRAG를 성공적으로 도입하려면 어떻게 해야 했을까?"를 고민해봤다.

우리가 잘못한 것

1. 기존 데이터를 그대로 사용

UMLS라는 거대한 데이터셋을 그대로 가져와 사용하려 했다. 이는 근본적인 실수였다:

  • 신뢰할 수 있는 지식 그래프가 아님: UMLS는 개념과 관계만 있을 뿐, 실제 의료 지식이 부족
  • 과도한 규모: 1.3M 노드 중 실제 사용은 극소수
  • 도메인 불일치: 안과 전문 시스템에 전체 의료 온톨로지는 과잉

2. 양(Quantity) > 질(Quality) 접근

"데이터가 많으면 좋겠지"라는 안일한 생각이 문제였다. 실제로는:

  • 노드에 description이 없어 LLM이 할루시네이션 생성
  • 관계만 있고 "왜, 어떻게, 언제"에 대한 정보 부재
  • 검증되지 않은 관계들로 인한 신뢰성 문제

올바른 접근법

1. 도메인 전문가와 함께 지식 그래프 구축

잘못된 방법: UMLS 다운로드 → 필터링 → Neo4j 임포트
올바른 방법: 의료 문서 분석 → 핵심 개념 추출 → 수동 검증 → 그래프 구축

구체적 실행 방안:

  1. 신뢰할 수 있는 소스 선정

    • 안과 교과서 (예: Kanski's Clinical Ophthalmology)
    • 최신 연구 논문 (PubMed, 대한안과학회지)
    • 임상 가이드라인 (AAO, 건강보험심사평가원)
  2. 핵심 노드와 관계 추출

    • 안과 질환 50-100개 (백내장, 녹내장, 황반변성 등)
    • 치료법 30-50개 (수술, 약물, 레이저)
    • 증상과 징후 100-200개
    • 검증된 인과 관계만 포함

위 갯수는 단순 예시이며, 준비된 문서의 양에 다라 달라질 수 있다.

  1. 품질 중심 구축
    • 각 노드에 충분한 설명 추가
    • 관계에 근거 문헌 링크
    • 정기적 업데이트 체계 구축

2. 문서 기반 그래프 구축 도구 활용

최근에는 문서에서 지식 그래프를 자동으로 구축하는 다양한 도구들이 등장했다. 이런 도구들을 활용하면:

핵심 기능:

  • PDF, 논문, 교과서에서 자동으로 엔티티와 관계 추출
  • 텍스트를 구조화된 그래프로 변환
  • 의료 도메인에 특화된 트리플 생성
  • 계층적 구조와 커뮤니티 자동 탐지

중요한 것은 도구가 아니라 프로세스:

  1. 신뢰할 수 있는 문서를 입력으로 사용
  2. 자동 추출된 결과를 도메인 전문가가 검증
  3. 품질 중심으로 적은 수의 정확한 트리플 유지
  4. 지속적인 업데이트와 검증 체계 구축

핵심 차이점

측면우리의 접근 (실패)올바른 접근
데이터 소스UMLS 전체 다운로드검증된 의료 문서에서 추출
규모1.3M 노드 (대부분 미사용)소수 노드
품질소수 노드에만 Description 존재풍부한 설명, 근거 포함
구축 방법일괄 임포트점진적 구축 + 지속적 검증
도구 활용수동 변환 스크립트전문 그래프 구축 도구 활용
검증사후 검증 (이미 늦음)구축 단계별 도메인 전문가 검증

교훈

GraphRAG가 실패한 것은 기술의 문제가 아니라 접근 방법의 문제였다:

  1. 검증된 고품질 데이터 > 검증되지 않은 대량 데이터
    • 소수의 잘 정의된 노드가 130만개의 불완전한 노드보다 실용적
    • 각 노드와 관계에 충분한 설명과 근거가 있어야 함
    • 너무 많은 노드와 관계를 정의하는 것은 피해야 함
  2. 도메인 전문가 참여가 필수
  3. 자동화 도구를 활용하되, 검증은 수동으로
  4. 점진적 구축과 지속적 개선

만약 처음부터 이렇게 접근했다면, GraphRAG의 장점(구조화된 지식, 명확한 관계, 추론 가능)을 살리면서도 운영 가능한 시스템을 만들 수 있었을 것이다.

React Agent로의 전환

위의 교훈과 올바른 접근법을 고민한 끝에, 우리는 다른 길을 선택했다.

현재 진행 중인 개선 방향

  1. Neo4j 의존성 제거: 복잡한 그래프 구조 대신 간단한 구조화
  2. ReAct 패턴 도입: 자율적으로 필요한 정보를 찾아가는 에이전트
  3. 핵심 검색 엔진:
    • Milvus 벡터 검색: 의료 문서와 지식 베이스 검색
    • 실시간 웹 검색: 최신 의료 연구와 가이드라인 조회

왜 React Agent인가

GraphRAG를 제대로 구축하는 것도 방법이지만, 우리의 상황에서는 React Agent가 더 실용적이었다.

Neo4j의 실제 역할: CoT(Chain of Thought) 도구

실제 운영 경험에서 깨달은 중요한 사실이 있다:

  • 그래프의 한계: Neo4j 노드에는 구체적인 의료 내용이 거의 없었음
  • 실제 지식의 출처: LLM과 지식 베이스 문서(논문, 교과서)가 실제 답변의 근거
  • 그래프의 진짜 역할: 단지 CoT처럼 사고의 방향성을 제시하는 도구
    • 관련 개념을 찾아주는 네비게이터
    • 생각의 흐름을 구조화하는 가이드
    • 실제 의료 정보가 아닌 "추론 과정"

이 깨달음이 중요한 이유는, 복잡한 그래프 인프라가 사실상 ReAct 패턴으로 대체 가능하다는 것이다.

ReAct Agent의 장점

  • 즉시 활용 가능: 지식 그래프 구축에 몇 달을 투자할 필요 없음
  • 유연한 확장: 새로운 의료 정보를 실시간으로 검색하고 활용
  • 운영 단순화: 복잡한 그래프 관리 대신 검색 엔진 활용
  • 비용 효율성: 그래프 구축과 유지보수 비용 절감
  • CoT 기능 내재화: ReAct 패턴 자체가 추론 과정을 구조화

GraphRAG의 복잡성을 제거하고, ReAct Agent가 Milvus와 웹 검색을 활용해 스스로 판단하고 필요한 정보를 수집하는 방식으로 전환했다.

마무리

핵심 메시지:

"의료 AI는 복잡한 그래프가 아니라, 신뢰할 수 있는 답변을 원한다"

기술적 우아함에 매료되어 실용성을 놓쳤던 실수를 반복하지 않기 위해 이 글을 썼다. 때로는 한 발 물러서서 "정말 이 복잡한 시스템이 필요한가?"라고 묻는 용기가 필요하다.

다음 포스팅에서는 ReAct Agent 기반의 새로운 접근법과 실제 개선 결과를 공유할 예정이다.

0개의 댓글