AI/LLM

[Multimodal] 글자 그 너머로

jumemory 2025. 8. 19. 14:07

1. 멀티모달(Multimodal)이란?

멀티모달은 텍스트, 이미지, 음성, 영상 등 **서로 다른 형태의 데이터(Modality)**를 함께 처리하는 기술입니다. 단순히 이미지를 텍스트로 설명하는 수준을 넘어, 여러 정보를 동시에 받아들여 통합적으로 사고하는 것이 핵심입니다.

  • LMM (Large Multimodal Model): 텍스트 기반 LLM에 시각/청각 능력이 통합된 모델 (예: GPT-4o, Gemini 1.5 Pro, Claude 3.5 Sonnet).

2. 핵심 원리: 공유된 공간 (Shared Embedding Space)

서로 다른 데이터들이 어떻게 서로 소통할까요? 비결은 **'공통 언어'**로 변환하는 데 있습니다.

  1. 인코더 (Encoders): 이미지는 Vision Encoder가, 텍스트는 Text Encoder가 각각 숫자의 묶음(벡터)으로 변환합니다.
  2. 얼라이먼트 (Alignment): '강아지 사진' 벡터와 '강아지'라는 단어 벡터가 공간상에서 가까운 위치에 놓이도록 맞춥니다.
  3. 프로젝션 (Projection): 이미지 벡터를 LLM이 이해할 수 있는 텍스트 토큰처럼 변환하여 모델의 '뇌(Transformer)'에 입력합니다.

3. 멀티모달의 주요 능력

능력 설명 활용 사례
Visual QA 이미지를 보고 질문에 답하기 "이 사진에서 고장 난 부분이 어디야?"
Image-to-Text 이미지 설명 및 텍스트 추출 (OCR) 영수증 인식, 시각 장애인용 설명 생성
Audio-to-Text 음성을 듣고 즉시 이해 및 번역 실시간 동시통역, 감정 분석 챗봇
Video Understanding 영상의 흐름과 인과관계 파악 긴 영화 요약, CCTV 이상 행동 감지

4. 멀티모달 학습의 새로운 흐름: Native Multimodal

과거에는 텍스트 모델과 이미지 모델을 '이어 붙이는' 방식(Late Fusion)이었다면, 최신 모델들은 처음부터 모든 데이터를 동시에 학습하는 Native Multimodal 방식을 택합니다.

  • 특징: 지연 시간(Latency)이 획기적으로 줄어들고, 텍스트로는 표현하기 힘든 미세한 뉘앙스(목소리의 떨림, 표정의 변화 등)를 훨씬 더 잘 포착합니다.
  • 대표 사례: GPT-4o의 실시간 대화 모드가 이 기술의 정점입니다.

5. [선생님의 심화 보충] 멀티모달의 한계: "보는 것과 이해하는 것"

멀티모달 모델도 가끔 **'시각적 환각'**을 일으킵니다. 사진 속의 복잡한 숫자를 잘못 읽거나, 물체 간의 물리적 거리(뭐가 앞에 있고 뒤에 있는지)를 오해하는 경우가 많습니다. 이를 해결하기 위해 최근에는 고해상도 이미지를 쪼개서 자세히 보는 'AnyRes' 기술이나, 영상의 긴 맥락을 기억하는 'Long Context Video Understanding' 연구가 활발히 진행 중입니다.


✍️ 대단원의 막을 내리며

텍스트에서 시작해 멀티모달까지, 우리는 AI가 인간처럼 세상을 보고, 듣고, 판단하는 과정을 모두 살펴보았습니다. 이제 당신이 마주할 AI는 단순한 알고리즘이 아니라, 세상을 입체적으로 이해하는 강력한 도구가 될 것입니다.

 

 

 

 

 

 

 

 

LoRA -low rank adaptation

 

 

작은 RAG 파이프라인

 

 

RAG가 뭐야?

검색으로 근거 문서를 먼저 꺼내고, 그걸 프롬프트에 붙여서 생성 모델이 답하게 하는 방식이야.
→ 그래서 **헛말(환각)**이 줄고, 출처 기반의 답을 만들 수 있어.

큰 그림 (무엇을 하는 코드인가?)

이 코드는 사용자의 질문을 받아서,

  1. 도메인 라우팅(records vs insurance) →
  2. 해당 도메인 문서 검색(벡터 검색)
  3. 문서 기반 답변 생성
    까지를 LangGraph로 “그래프(워크플로우)”로 정의하고 실행하는 예제야.

비유하면:

  • 라우터: “이 문의는 의료기록 팀? 보험팀?” 분류
  • 리트리버: 해당 팀 문서상자에서 관련 문서 꺼내줌
  • 생성기: 꺼낸 문서 읽고 답변 작성

 

코드에 쓰인 핵심 개념들

1) 메시지·프롬프트 (LangChain 메시지 객체)

  • SystemMessage, HumanMessage
    • SystemMessage: 모델에게 역할/규칙을 주는 지침서(“도메인 이름만 출력해!”)
    • HumanMessage: 사용자의 실제 질문

2) 타입 힌트/상태 정의

  • TypedDict, Literal, Annotated[list, add_messages]
    • State: 내부 작업 노트(대화기록, 질문, 도메인, 문서, 답변)
    • Input/Output: 그래프 입·출력의 모양
    • Annotated[list, add_messages]: “messages라는 리스트는 그래프 실행 중 노드가 반환하는 메시지를 **자동으로 누적(add)**해라”는 힌트

3) 임베딩 & 벡터 스토어 & 리트리버

  • OpenAIEmbeddings로 문서를 벡터화 → InMemoryVectorStore에 저장 → .as_retriever()로 질문과 가장 비슷한 문서 찾아주는 검색기 생성

4) LangGraph (상태 그래프)

  • StateGraph(State, input=Input, output=Output)
    • 노드와 엣지로 파이프라인을 그림처럼 정의
    • START → router → (분기) → retrieve_* → generate_answer → END
    • add_conditional_edges로 조건 분기 구현 (도메인 값에 따라 다른 노드로 이동)

5) RAG 패턴(검색-증강-생성)

  • Retrieval Augmented Generation:
    검색(문서찾기) 한 다음 생성(답변쓰기)
    → 환각 줄이고, 문서 근거 기반으로 답변 가능

6) 그래프 시각화

  • get_graph().draw_mermaid_png(...)
    → 정의한 노드/엣지를 도식으로 저장

 

 

TypedDict란?

  • 파이썬에서 딕셔너리의 구조(키와 값의 타입)를 미리 정의해줄 수 있는 기능이에요.
  • 보통은 딕셔너리 아무 키나 막 넣을 수 있는데, TypedDict를 쓰면 “이 딕셔너리는 이런 키들을 꼭 가져야 하고 값은 이런 타입이어야 한다”를 타입 힌트로 명시할 수 있어요.
  • 예:→ 이러면 {"name": "홍길동", "age": 30}은 OK,
    {"nickname": "길동이"}는 타입 검사에서 오류로 잡혀요.
  •   
  •  
  •  
  •  
  •  
  • class Person(TypedDict): name: str age: int
  •  

지금 sample_docs 두 개(records 도메인 문서, insurance 도메인 문서)는 모델이 “어떤 질문이 들어왔을 때 어떤 쪽으로 분류해야 하는지” 학습/판단할 수 있도록 도와주는 기준 데이터 역할을 하는 거예요.


1. sample_docs의 역할

  • 각 Document에는 두 가지 정보가 있어요:
    1. page_content → 실제 문서 내용
    2. metadata['domain'] → 이 문서가 속한 카테고리 (records / insurance)

즉, 모델이 user_query를 받으면:

  1. 질문 내용과 문서 내용을 비교
  2. 더 잘 맞는 문서의 domain을 선택
    → "분류"가 되는 거예요.

 

 

1. InMemoryVectorStore.from_documents(...)

  • Vector Store(벡터 저장소) = 문서를 벡터로 변환해서 저장해두는 데이터베이스 같은 것.
  • InMemory라는 이름에서 알 수 있듯이, 디스크(DB)에 저장하지 않고 메모리(RAM)에만 임시로 저장하는 버전이에요.
  • from_documents(sample_docs, embeddings) 뜻은:
    1. sample_docs → 우리가 가진 문서들 (page_content, metadata 포함)
    2. embeddings → 문장을 벡터로 바꿔주는 함수/모델 (예: OpenAI Embeddings, HuggingFace 임베딩 모델 등)
    3. 모든 문서를 벡터화해서 InMemoryVectorStore에 저장

즉, 한마디로
👉 “문서를 벡터로 바꿔서 메모리에 넣는다”


2. medical_records_store.as_retriever()

  • VectorStore는 단순히 "저장소" 역할만 해요.
  • .as_retriever()를 붙이면 → "저장소를 검색기(retriever)로 바꿔라"라는 뜻.
  • 검색기란?
    • 사용자가 질문(쿼리)을 던지면, 그 질문을 임베딩 → 벡터 변환
    • 저장소에 있는 문서 벡터들과 비교해서 가장 유사한 문서를 찾아줌

👉 즉,

  • medical_records_store = 문서를 벡터로 저장해둔 데이터베이스
  • medical_records_retriever = 질문 넣으면 관련 문서 찾아주는 검색기

3. 예시 흐름

 
query = "코로나 관련 기록 보여줘" docs = medical_records_retriever.get_relevant_documents(query)

동작 순서:

  1. "코로나 관련 기록 보여줘" → embeddings로 벡터화
  2. 저장소에 있는 문서 벡터들과 거리(코사인 유사도 등) 계산
  3. 가장 비슷한 문서(예: records 도메인 문서) 반환

4. 비유 📝

  • VectorStore = 도서관 (책이 벡터로 정리돼 있음)
  • Retriever = 사서 (내가 질문하면, 가장 관련 있는 책을 꺼내줌)

✅ 정리:

  • InMemoryVectorStore.from_documents(...) → 문서들을 벡터 DB(메모리용)에 저장
  • .as_retriever() → 질문하면 관련 문서를 꺼내주는 검색기 역할 부여

 

1. StateGraph란?

  • LangGraph에서 제공하는 “상태 그래프”를 만드는 클래스예요.
  • 쉽게 말하면:
    👉 대화나 워크플로우를 상태(State) 단위로 관리할 수 있는 그래프(흐름도)를 만들겠다 라는 뜻.

예를 들어, “Input → Domain 분류 → 문서 검색 → 답변 생성 → Output” 같은 단계들이 하나의 그래프로 정의돼요.


2. 코드 해석

 
builder = StateGraph(State, input=Input, output=Output)
  • State:
    우리가 아까 만든 대화 상태 전체 구조 (messages, user_query, domain, documents, answer 포함)
  • input=Input:
    외부에서 이 그래프에 들어오는 입력 데이터 타입 (여기서는 user_query 하나만 있음)
  • output=Output:
    그래프가 실행된 후 최종적으로 내보낼 결과 타입 (여기서는 documents + answer)

즉,
👉 "이 그래프는 State 구조를 내부 상태로 쓰고, Input으로 시작해서 Output으로 끝난다"
라는 걸 builder에 등록한 거예요.


3. 왜 필요한가?

  • 그냥 함수로도 만들 수 있는데, LangGraph에서는 복잡한 워크플로우를 **노드(단계)**와 **엣지(연결)**로 시각화/구현할 수 있거든요.
  • 예시:
  •  
    builder.add_node("router", router_fn) builder.add_node("retriever", retriever_fn) builder.add_node("generator", generator_fn) builder.add_edge("router", "retriever") builder.add_edge("retriever", "generator") builder.add_edge("generator", END)
  • 이런 식으로 하면 user_query가 들어와서 → domain 분류(router) → 문서 검색(retriever) → 답변 생성(generator) → 최종 Output 으로 이어지는 **흐름도(그래프)**를 짤 수 있습니다.

4. 비유 📝

  • State = “워크플로우 노트” (모든 중간 결과 저장)
  • Input = “첫 페이지 질문지”
  • Output = “마지막 보고서”
  • StateGraph = “이 질문지가 어떻게 보고서로 바뀌는지 정리한 작업 플로우 차트”

✅ 정리
builder = StateGraph(State, input=Input, output=Output)
👉 “State를 기반으로, Input을 받아 Output을 내보내는 그래프 빌더를 만든다”는 뜻이고, 이후에 add_node, add_edge로 단계들을 붙여서 워크플로우를 완성하게 돼요.

'AI > LLM' 카테고리의 다른 글

[Guardrails] 안전한 AI 설계  (0) 2025.08.14
[Evaluation] 모델의 성적표  (0) 2025.08.13
[Serving] 고속 추론 서빙  (0) 2025.08.12
[Quantization] 모델 경량화  (0) 2025.08.11
[MCP] LLM의 만능 커넥터  (0) 2025.08.08