1. 멀티모달(Multimodal)이란?
멀티모달은 텍스트, 이미지, 음성, 영상 등 **서로 다른 형태의 데이터(Modality)**를 함께 처리하는 기술입니다. 단순히 이미지를 텍스트로 설명하는 수준을 넘어, 여러 정보를 동시에 받아들여 통합적으로 사고하는 것이 핵심입니다.
- LMM (Large Multimodal Model): 텍스트 기반 LLM에 시각/청각 능력이 통합된 모델 (예: GPT-4o, Gemini 1.5 Pro, Claude 3.5 Sonnet).
2. 핵심 원리: 공유된 공간 (Shared Embedding Space)
서로 다른 데이터들이 어떻게 서로 소통할까요? 비결은 **'공통 언어'**로 변환하는 데 있습니다.
- 인코더 (Encoders): 이미지는 Vision Encoder가, 텍스트는 Text Encoder가 각각 숫자의 묶음(벡터)으로 변환합니다.
- 얼라이먼트 (Alignment): '강아지 사진' 벡터와 '강아지'라는 단어 벡터가 공간상에서 가까운 위치에 놓이도록 맞춥니다.
- 프로젝션 (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가 뭐야?
검색으로 근거 문서를 먼저 꺼내고, 그걸 프롬프트에 붙여서 생성 모델이 답하게 하는 방식이야.
→ 그래서 **헛말(환각)**이 줄고, 출처 기반의 답을 만들 수 있어.
큰 그림 (무엇을 하는 코드인가?)
이 코드는 사용자의 질문을 받아서,
- 도메인 라우팅(records vs insurance) →
- 해당 도메인 문서 검색(벡터 검색) →
- 문서 기반 답변 생성
까지를 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에는 두 가지 정보가 있어요:
- page_content → 실제 문서 내용
- metadata['domain'] → 이 문서가 속한 카테고리 (records / insurance)
즉, 모델이 user_query를 받으면:
- 질문 내용과 문서 내용을 비교
- 더 잘 맞는 문서의 domain을 선택
→ "분류"가 되는 거예요.
1. InMemoryVectorStore.from_documents(...)
- Vector Store(벡터 저장소) = 문서를 벡터로 변환해서 저장해두는 데이터베이스 같은 것.
- InMemory라는 이름에서 알 수 있듯이, 디스크(DB)에 저장하지 않고 메모리(RAM)에만 임시로 저장하는 버전이에요.
- from_documents(sample_docs, embeddings) 뜻은:
- sample_docs → 우리가 가진 문서들 (page_content, metadata 포함)
- embeddings → 문장을 벡터로 바꿔주는 함수/모델 (예: OpenAI Embeddings, HuggingFace 임베딩 모델 등)
- 모든 문서를 벡터화해서 InMemoryVectorStore에 저장
즉, 한마디로
👉 “문서를 벡터로 바꿔서 메모리에 넣는다”
2. medical_records_store.as_retriever()
- VectorStore는 단순히 "저장소" 역할만 해요.
- .as_retriever()를 붙이면 → "저장소를 검색기(retriever)로 바꿔라"라는 뜻.
- 검색기란?
- 사용자가 질문(쿼리)을 던지면, 그 질문을 임베딩 → 벡터 변환
- 저장소에 있는 문서 벡터들과 비교해서 가장 유사한 문서를 찾아줌
👉 즉,
- medical_records_store = 문서를 벡터로 저장해둔 데이터베이스
- medical_records_retriever = 질문 넣으면 관련 문서 찾아주는 검색기
3. 예시 흐름
동작 순서:
- "코로나 관련 기록 보여줘" → embeddings로 벡터화
- 저장소에 있는 문서 벡터들과 거리(코사인 유사도 등) 계산
- 가장 비슷한 문서(예: records 도메인 문서) 반환
4. 비유 📝
- VectorStore = 도서관 (책이 벡터로 정리돼 있음)
- Retriever = 사서 (내가 질문하면, 가장 관련 있는 책을 꺼내줌)
✅ 정리:
- InMemoryVectorStore.from_documents(...) → 문서들을 벡터 DB(메모리용)에 저장
- .as_retriever() → 질문하면 관련 문서를 꺼내주는 검색기 역할 부여
1. StateGraph란?
- LangGraph에서 제공하는 “상태 그래프”를 만드는 클래스예요.
- 쉽게 말하면:
👉 대화나 워크플로우를 상태(State) 단위로 관리할 수 있는 그래프(흐름도)를 만들겠다 라는 뜻.
예를 들어, “Input → Domain 분류 → 문서 검색 → 답변 생성 → Output” 같은 단계들이 하나의 그래프로 정의돼요.
2. 코드 해석
- 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 |