AWS 기술 블로그

Amazon Bedrock 으로 만든 의료 전문 Q&A 챗봇 구현 여정

인티그레이션은 치과 의료 플랫폼 ‘데니어(DENEER)‘를 운영하는 메디테크 기업입니다. 데니어는 전국 치과의사와 치대생의 53%가 가입한 국내 최대 치과 전문 커뮤니티 ‘모어덴(moreDEN)‘을 통해 의료진 간 네트워킹, 구인/구직, 커머스, 온라인 교육 등 종합적인 디지털 헬스케어 서비스를 제공하고 있습니다.

인티그레이션이 운영하는 모어덴 플랫폼에는 현직 치과의사들이 공유한 3만여 개의 임상 Q&A 데이터가 축적되어 있습니다. 이 데이터는 단순한 질문과 답변의 모음이 아닌, 임상 의료진들의 전문적인 노하우와 치과의료진 동료들의 검증된 추천, 그리고 커뮤니티 운영진의 체계적인 관리를 통해 정제된 귀중한 의료 지식의 보고입니다. 이러한 고품질 데이터는 치과 의료 서비스 혁신의 핵심 동력이 되고 있습니다.

이러한 양질의 데이터를 보다 효과적으로 활용하고, 증가하는 의료 정보 문의에 대한 24시간 응대 체계를 구축하여, 의료진의 반복적인 기초 문의 응대 업무 부담을 해소하기 위해 인티그레이션은 AWS 기반의 AI 챗봇 서비스 ‘FRIDAY’를 개발했습니다. 마블 코믹스의 아이언맨에 등장하는 AI 비서 ‘자비스’의 후속 버전에서 착안한 FRIDAY는 의료진들에게 실시간으로 전문적인 의료 정보를 제공하는 AI 비서 역할을 수행합니다.

Amazon Bedrock 서비스를 선택한 이유

인티그레이션은 모어덴의 풍부한 Q&A 데이터를 활용하여 마치 경험 많은 선배 의료진이 실시간으로 조언해주는 듯한 의료 전문 AI 챗봇을 구현하고자 했습니다. 기존 단순 검색 엔진의 키워드 매칭만으로는 의료 전문가 수준의 맥락 이해가 어려웠고, 일반적인 생성형 AI는 의료 정보의 정확성을 보장하기 어려운 환각 문제가 있었습니다.

이러한 기술적 과제를 해결하기 위해 인티그레이션은 RAG(Retrieval-Augmented Generation) 시스템을 구현하기로 결정했고, 이를 위한 핵심 서비스로 Amazon Bedrock을 선택했습니다. Amazon Bedrock은 Claude와 Amazon의 벡터 모델 등 다양한 고성능 FM(Foundation Model) 모델을 제공하여 전문적인 의료 임상 정보를 정확하게 처리할 수 있었습니다.

특히 Amazon Bedrock 선택의 주요 이점은 기존 AWS 인프라와의 원활한 통합이었습니다. 인티그레이션은 이미 많은 시스템을 AWS상에서 운영하고 있었기 때문에, Amazon Bedrock 도입으로 추가적인 기술 부채 없이 신속하게 AI 서비스를 구현할 수 있었습니다. 또한 AWS의 강력한 인프라를 기반으로 한 높은 확장성과 안정성, 의료 데이터 처리에 필수적인 보안 기능도 주요한 선택 요인이었습니다.

비용 측면에서도 Amazon Bedrock은 사용량 기반 과금 모델을 제공하여 초기 투자 부담을 크게 줄일 수 있었습니다. 더불어 AWS는 인티그레이션의 혁신적인 의료 AI 프로젝트의 가치를 인정하여 초기 개발 단계에서 상당한 기술 지원과 비용 혜택을 제공했습니다. 이는 프로젝트의 빠른 시작과 안정적인 개발 진행에 큰 도움이 되었습니다.

RAG 시스템 접근 방식

인티그레이션은 의료 Q&A 챗봇의 정확성과 신뢰성을 보장하기 위해 Amazon Bedrock 기반의 RAG 시스템을 구축했습니다. RAG 시스템은 효과적인 정보 검색과 정확한 답변 생성이라는 두 가지 핵심 요소를 중심으로 설계되었습니다.

  1. 데이터 전처리: 계층적 청킹(hierarchical chunking) 기법을 사용하여 데이터를 분할했습니다. 단순 질의 응답 뿐만 아니라 의료진들이 함께 평가한 상위 우수 답변이 데이터에 포함되도록 전처리 과정을 거쳤습니다.
  2. 검색 최적화: 검색할 때에는 작은 크기의 청크를 사용하여 정확한 검색 결과를 얻도록 하였고, 답변을 생성할 때에는 보다 큰 크기의 청크를 사용하여 풍부한 맥락 정보를 제공하였습니다.
  3. 프롬프트 전략: 응답의 정확성을 높이기 위하여 적절한 역할을 부여하고, 지시 기반의 프롬프팅 기법과 추가 맥락을 설정함으로써 보다 정확하면서도 상황에 맞는 답변을 유도하였습니다.
  4. 질의 재작성: 사용자의 질문을 분석하여 핵심 키워드를 추출하고, 이를 바탕으로 사용자의 의도를 반영한 검색 질의를 작성하였습니다. 이를 통해 Q&A 데이터 뿐만 아니라 관련 논문도 찾아보게 함으로써 답변의 품질을 높였습니다.
  5. 세션 비유지 전략: 각 질문을 독립적으로 처리하여 시스템의 복잡도를 낮추고 확장성을 높였습니다. 이를 통해 항상 최신 정보를 바탕으로 일관성 있는 답변을 제공할 수 있게 되었습니다.

이 외에 인테그레이션이 보유한 Q&A 데이터 외에도, 관련 논문을 활용하여 보다 깊이있는 정보를 제공하였습니다. 질문에 관련된 논문 정보를 제공하기 위하여 PDF 원본을 압축하고, 내용을 요약했으며 주요 키워드 추출을 진행했습니다.

  1. PDF 압축: Ghostscript를 사용하여 대부분의 논문 PDF를 5MB 이하로 압축했습니다.
  2. 요약: 치과 분야의 전문성을 유지하면서도 검색에 최적화된 형태로 쿼리를 재작성했습니다. 구조화된 출력 형식을 사용하여 일관성 있는 요약을 생성했습니다.
  3. 키워드 추출: 학술적 가치와 검색 효율성을 모두 고려한 키워드를 추출했습니다. 추출된 키워드를 이용해 유사한 논문들을 추천하는 기능도 구현했습니다.

Friday Backend 아키텍처 소개

의료 AI 시스템의 성능과 신뢰성은 실제 현장에서의 검증이 무엇보다 중요합니다. Friday는 이러한 철학을 바탕으로, 수 개월에 걸친 실제 치과 의사들의 피드백과 테스트를 통해 핵심 프로세스를 지속적으로 발전시켜 왔습니다. 특히 AWS 담당자분들과의 지속적인 미팅과 아이디에이션(Ideation)을 통해 시스템 아키텍처를 보다 효율적으로 구성할 수 있었습니다.

또한 Amazon API Gateway 대신 Amazon CloudFront를 사용함으로써, 타임아웃(timeout) 시간을 최대 15분까지 확보하여 보다 상세하고 정확한 응답을 생성할 수 있게 되었습니다. 이는 복잡한 임상 케이스나 깊이 있는 학술 연구에 대한 질의응답에서 특히 큰 장점으로 작용하고 있습니다.

핵심 프로세스

1. 검색 요청 처리

Friday의 모든 검색 요청은 실시간으로 중앙 데이터베이스에 기록되며, 요청부터 응답까지의 전 과정을 추적할 수 있습니다. 이는 시스템의 투명성과 신뢰성을 보장하는 핵심 요소입니다.

2. 키워드 분석

  • 검색어로부터 핵심 키워드 추출
  • 학술 연구 관련 질문 자동 분류
  • 지식베이스 외 추가 논문 검색 및 추천 기능

3. 질의 최적화

Friday는 사용자의 질문을 더 정확하고 유용한 답변으로 이어지도록 다음과 같은 최적화 과정을 거칩니다:

  • 도메인 지식 보강: 부족한 전문 영역 지식 자동 보완
  • 질문 재구성: 더 정확하고 풍부한 답변을 위한 질문 개선
  • 자동 필터링: 부적절하거나 모호한 질문에 대한 사전 처리

4. 응답 생성

최종 응답은 다음과 같은 과정을 통해 생성됩니다:

  1. 최적화된 질문을 기반으로 지식베이스 검색 수행
  2. 관련성 높은 정보들을 종합적으로 분석
  3. 구조화된 형태의 응답 생성

Friday 프롬프트

실제 임상 현장에서 활용되는 다양한 용어와 표현들을 분석하여, Friday 만의 특화된 프롬프트 시스템을 구축하였습니다. 특히 치과 전문의들의 실제 상담 내용과 진료 기록을 바탕으로 자연스러운 대화가 가능하도록 최적화하였으며, FDI 치아 번호 체계 등 치과 현장에서 사용되는 전문적인 표기법을 인식하고 처리할 수 있도록 구현하였습니다. 아래는 Friday 응답 품질 향상 전략입니다.

1. 하이브리드 검색 방식

  • 벡터 검색 + 키워드 검색 병합
  • 검색 결과 수 최적화

2. 맥락 이해 강화

  • 치과 전문용어 인식
  • FDI 치아 번호 체계 적용 업계 특화 용어 처리

아래는 실제 사용된 프롬프트의 핵심 구조만을 간략화하여 한글로 설명한 것입니다. 실제 프롬프트는 더 상세하고 복잡한 영문 구조를 가지고 있습니다.

키워드 추출 프롬프트 예시

키워드 추출 지시사항:
1. 학술성 여부 판단:
  - "Non-academic topic" 또는 JSON 응답
  
2. 키워드 추출 기준:
  - 중요도 기반 2-5개 선정
  - 연구분야, 술식, 재료, 질환명 등
  
3. 출력 형식:
{
  "keywordKo": ["키워드1", "키워드2"],
  "keywordEn": ["Keyword1", "Keyword2"]
}

질의 재작성 프롬프트 예시

1. 치과 전문용어 처리

약어 확장: "CF" → "canal filling"
업계 용어: "원생마" → "원장실에서 생 마감"

2. FDI 번호 체계 적용

#16 → "우측 상악 제1대구치"
#45 → "우측 하악 제2소구치"

3. 통화 표기 규칙

"800" → "800만원"

모델 호출 예시 스크립트

import {
 BedrockRuntimeClient,
 InvokeModelWithResponseStreamCommand,
 InvokeModelCommand
} from '@aws-sdk/client-bedrock-runtime';

// Bedrock Runtime 클라이언트 초기화
const clientRuntime = new BedrockRuntimeClient({
 region: process.env.BEDROCK_AWS_REGION
});

export const invokeModel = async ({
 prompt,
 streaming = false,
 ...options
}) => {
 if (!prompt) {
   throw new Error('프롬프트는 필수 입력값입니다.');
 }

 // API 요청 파라미터 설정
 const params = {
   modelId: process.env.DEFAULT_MODEL_ID,
   contentType: 'application/json', 
   accept: 'application/json',
   body: JSON.stringify({
     anthropic_version: 'bedrock-2023-05-31',
     max_tokens: parseInt(process.env.MAX_TOKENS),
     messages: [
       {
         role: 'user',
         content: prompt,
       },
     ],
     temperature: parseFloat(process.env.TEMPERATURE),
     top_p: parseFloat(process.env.TOP_P),
     top_k: parseInt(process.env.TOP_K),
     ...options, // 사용자 지정 옵션으로 기본값 덮어쓰기
   }),
 };

 try {
   if (streaming) {
     const command = new InvokeModelWithResponseStreamCommand(params);
     const response = await clientRuntime.send(command);
     return response.body;
   } else {
     const command = new InvokeModelCommand(params);
     const response = await clientRuntime.send(command);
     const responseBody = JSON.parse(new TextDecoder().decode(response.body));
     return responseBody.content[0].text.trim();
   }
 } catch (error) {
   console.error('Bedrock 모델 호출 오류:', error);
   throw error;
 }
};

Knowledge Base 답변 프롬프트 예시

핵심 지시사항:
1. 질문 언어로 응답
2. 치과 전문의 관점 유지
3. 근거 기반 정보 우선
4. 개인 경험은 참고사항으로 표시
5. 수치 데이터 포함시 구체적 명시

Knowledge Base 호출 예시 스크립트

import { BedrockAgentRuntimeClient, RetrieveAndGenerateCommand } from '@aws-sdk/client-bedrock-agent-runtime';
import { knowledgeBaseConfig } from './config.js';

// Bedrock Agent Runtime 클라이언트 초기화
const client = new BedrockAgentRuntimeClient({
   region: process.env.BEDROCK_AWS_REGION
});

// Bedrock Knowledge Base 기본 설정
const knowledgeBaseConfig = {
   type: 'KNOWLEDGE_BASE',
   knowledgeBaseConfiguration: {
       // Knowledge Base ID와 모델 ARN 설정
       knowledgeBaseId: process.env.BEDROCK_KNOWLEDGEBASE_ID,
       modelArn: process.env.BEDROCK_MODEL_ARN,
       // 벡터 검색 설정
       retrievalConfiguration: {
           vectorSearchConfiguration: {
               numberOfResults: parseInt(process.env.VECTOR_SEARCH_NUM_RESULTS), // 검색 결과 개수
               overrideSearchType: 'HYBRID', // 검색 타입 (HYBRID: 벡터 + 키워드 검색 혼합 )
           },
       },
       // 텍스트 생성 설정
       generationConfiguration: {
           inferenceConfig: {
               textInferenceConfig: {
                   maxTokens: parseInt(process.env.MAX_TOKENS), // 최대 토큰 수
                   stopSequences: ['\\nObservation'], // 생성 중단 시퀀스
                   temperature: parseFloat(process.env.TEMPERA TURE),
                   topP: parseFloat(process.env.TOP_P),
               },
           },
           promptTemplate: {
               textPromptTemplate: promptTemplate, // 프롬프트 템플릿 적용
           },
       },
   },
};

export const retrieveAndGenerate = async (prompt) => {
   // 프롬프트 유효성 검사
   if (!prompt) {
       throw new Error('입력받은 prompt가 없습니다.');
   }

   // API 요청 설정
   const input = {
       input: {
           text: prompt,
       },
       retrieveAndGenerateConfiguration: knowledgeBaseConfig,
   };

   try {
       // Bedrock 명령 실행
       const command = new RetrieveAndGenerateCommand(input);
       const response = await client.send(command);

       // 응답 데이터 처리
       const result = {
           text: response.output?.text || '', // 생성된 텍스트
           references: response.references || [], // 참조된 문서 정보
       };

       return result;
   } catch (error) {
       console.error('retrieveAndGenerate 오류:', error);
       // 오류 발생 시 기본값 반환
       return {
           text: '',
           references: [],
       };
   }
};

클로즈드 베타 서비스 운영 결과

실제 현장의 목소리를 듣기 위해 클로즈드 베타 서비스를 진행했습니다. 많은 치과 의사분들이 체험단에 참여해 주셨고, 기존 지식을 효과적으로 활용할 수 있는 새로운 도구의 등장에 긍정적인 반응을 보여주셨습니다.

현재의 한계와 향후 계획

시스템 개발 과정에서 가장 큰 도전 과제는 답변의 정확성 검증이었습니다. 의료 정보의 특성상 전문가 검증이 필수적이지만, 이를 자동화하는 것은 여전히 어려운 과제로 남아있습니다. 현재는 사내 치과의사들의 도움을 받아 답변 내용을 검증하며 프롬프트의 정확도를 지속적으로 개선하고 있습니다. Friday는 다음과 같은 방향으로 시스템을 발전시켜 나갈 계획입니다:

  1. 멀티모달 기능 확장
    • 텍스트와 이미지를 통합적으로 이해하고 분석
    • 임상 데이터 기반의 종합적인 의사결정 지원
  2. 개인화된 논문 관리 시스템
    • 사용자별 맞춤형 논문 추천
    • 효율적인 학술 자료 관리 기능
  3. 의료 도메인 확장
    • 치과 분야에서 축적한 노하우를 바탕으로
    • 한의학 등 다양한 의료 분야로 서비스 확대

데니어가 꿈꾸는 미래

이 프로젝트를 통해 우리는 의료 AI의 현재 한계와 미래 가능성을 동시에 마주했습니다. 아직 가야 할 길이 멀지만, 한 걸음씩 나아가며 혁신적인 의료 AI 시스템을 만들어가고 있습니다. 데니어의 목표는 단순한 기술 개발을 넘어, 의료진들이 진료의 본질에 더욱 집중할 수 있는 환경을 만드는 것입니다. 이를 통해 궁극적으로 모든 환자가 더 나은 의료 서비스를 받을 수 있도록 하는 것이 우리의 비전입니다.

앞으로도 데니어는 치과 의료 시장의 혁신을 선도하며, 지속적인 기술 발전을 통해 의료 서비스의 질적 향상에 기여하겠습니다. 보다 건강한 미래를 향한 우리의 여정에 많은 관심과 응원 부탁드립니다.

류중경

류중경

류중경 데이터 엔지니어는 RAG(Retrieval-Augmented Generation) 기술과 데이터 엔지니어링 전문가입니다. RAG 기술을 활용하여 기업의 데이터를 효과적으로 활용하고, 고품질의 AI 응답을 생성하는 시스템 개발에 주력하고 있습니다.

송기명

송기명

송기명 치과 의사는 RAG 답변의 퀄리티 및 프롬프트에 많은 도움을 주신 치의학 한/영 도메인 전문가입니다. (토론토대학교 생명과학과 학사, 토론토대학교 생화학과 석사, 고려대학교 의과대학 해부학교실 전문연구요원 복무, 서울대학교 치의학대학원 재학중)

김자운

김자운

김자운 프론트엔드 엔지니어는 인티그레이션의 사용자 경험 개선을 위한 새로운 기능 설계 및 개발, 성능 최적화, 그리고 확장 가능한 컴포넌트 시스템 구축을 통해 더 나은 서비스를 만들어가고 있습니다.

박세희

박세희

박세희 백엔드 엔지니어는 인티그레이션 테라 스쿼드 소속의 백엔드 개발자로 유저들이 커뮤니티를 보다 활발하고 효율적으로 활용할 수 있도록 최적화된 서비스와 시스템을 설계 및 관리하고 있습니다. 사용자 경험 향상을 위해 다양한 기술 솔루션을 적용하여 커뮤니티 플랫폼의 안정성과 확장성을 지속적으로 개선하고 있습니다.

김동혁

김동혁

김동혁 데이터 엔지니어는 인티그레이션에서 데이터 인프라와 파이프라인 구축 및 유지보수를 담당하고 있습니다.효율적인 데이터 처리 시스템을 구축하여 안정적인 데이터 흐름을 보장하고, 조직의 데이터 기반 의사결정을 지원하는 역할을 수행하고 있습니다. 데이터의 수집부터 저장, 처리, 분석에 이르는 전체 파이프라인의 최적화를 통해 비즈니스 가치 창출에 기여하고 있습니다.

Jungseob Shin

Jungseob Shin

신정섭 Solutions Architect는 다양한 분야의 Backend 서버 개발 경험을 바탕으로 Startup 고객이 비즈니스 목표를 달성하도록 AWS 서비스의 효율적인 사용을 위한 아키텍처 설계 가이드와 기술을 지원하는 역할을 수행하고 있습니다. 컨테이너와 서버리스 기술에 관심이 많습니다.

JuHyung Lee

JuHyung Lee

이주형님은 AWS에서 스타트업 팀 어카운트 매니저로 일하고 있습니다. 스타트업이 AWS를 통해 비즈니스 혁신을 이루고 성장할 수 있도록 어카운트 지원을 하고 있습니다.

Sungmin Kim

Sungmin Kim

김성민님은 AWS의 솔루션즈 아키텍트 입니다. Startup 고객들과 협력하여 비즈니스 성과를 실현하는데 도움을 드리고 있습니다.