{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "61a87b9a",
   "metadata": {},
   "source": [
    "# Part 7.3: LangChain으로 LLM 애플리케이션 개발 맛보기\n",
    "\n",
    "**⬅️ 이전 시간: [Part 7.2: Transformer와 LLM의 핵심 원리](./part_7.2_transformer_and_llm_principles.md)**\n",
    "**➡️ 다음 시간: [Part 7.4: 그래프 신경망 (GNN)](./part_7.4_graph_neural_networks.md)**\n",
    "\n",
    "---\n",
    "\n",
    "<br>\n",
    "\n",
    "> ## 1. 학습 목표 (Learning Objectives)\n",
    ">\n",
    "> 이번 파트가 끝나면, 여러분은 다음을 할 수 있게 됩니다.\n",
    "> \n",
    "> - LLM의 한계점(최신성 부족, 환각 등)을 설명하고, RAG가 이를 어떻게 해결하는지 이해할 수 있습니다.\n",
    "> - LangChain의 역할을 이해하고, RAG 파이프라인의 핵심 5단계(Load, Split, Embed, Store, Retrieve)를 설명할 수 있습니다.\n",
    "> - 문서 분할(Chunking)의 중요성을 이해하고, 기본적인 분할 전략을 적용할 수 있습니다.\n",
    "> - LangChain을 사용하여 외부 문서의 내용을 기반으로 질문에 답변하는 RAG 시스템을 직접 코드로 구현할 수 있습니다.\n",
    "\n",
    "<br>\n",
    "\n",
    "> ## 2. 핵심 키워드 (Keywords)\n",
    "> \n",
    "> `거대 언어 모델(LLM)`, `LangChain`, `검색 증강 생성(RAG)`, `환각(Hallucination)`, `임베딩(Embedding)`, `벡터 저장소(Vector Store)`, `FAISS`, `Chroma`, `문서 분할(Chunking)`\n",
    "\n",
    "<br>\n",
    "\n",
    "> ## 3. 도입: 똑똑한 LLM을 더 똑똑하게 만들기 (Introduction)\n",
    "> \n",
    "> 우리는 앞에서 LLM이라는 강력한 '두뇌'를 배웠습니다. 하지만 이 두뇌는 몇 가지 결정적인 한계를 가집니다. 훈련 데이터에 없는 최신 정보나, 우리 회사 내부 문서 같은 사적인 내용은 전혀 알지 못합니다. 가끔은 그럴듯한 거짓말, 즉 '환각' 현상을 보이기도 하죠.\n",
    "> \n",
    "> 이번 시간에는 이 한계를 극복하는 가장 효과적인 기술인 **검색 증강 생성(RAG, Retrieval-Augmented Generation)**을 배웁니다. RAG의 핵심 아이디어는 간단합니다.\n",
    "> \n",
    "> > \"LLM에게 정답을 바로 묻지 말고, 먼저 관련 정보를 찾아서 '오픈북 시험'을 보게 하자!\"\n",
    "> \n",
    "> 그리고 이 복잡한 '오픈북 시험' 과정을 손쉽게 만들어주는 도구가 바로 **LangChain**입니다. LangChain을 통해 LLM이 외부 지식과 소통하게 하여, 훨씬 더 정확하고 신뢰성 있는 AI 애플리케이션을 만드는 방법을 탐험해 봅시다.\n",
    "> \n",
    "> > [!TIP]\n",
    "> > 본 파트의 모든 예제 코드는 `../../source_code/part_7_5_llm_application_development.py` 파일에서 직접 실행하고 수정해볼 수 있습니다.\n",
    "\n",
    "---\n",
    "\n",
    "<br>\n",
    "\n",
    "> ## 4. RAG 파이프라인: 5단계로 완전 정복\n",
    "> \n",
    "> RAG는 크게 **'인덱싱(Indexing)'**과 **'검색 및 생성(Retrieval & Generation)'** 두 단계로 나뉩니다. 이 과정을 5개의 세부 단계로 나누어 살펴보겠습니다.\n",
    "> \n",
    "> ![RAG Pipeline](https://raw.githubusercontent.com/gogodov/Images/main/ai_expert_course/rag_pipeline.png)\n",
    "> \n",
    "> ### [인덱싱 단계: 도서관에 책 정리하기]\n",
    "> \n",
    "> #### 1단계: Load (문서 불러오기)\n",
    "> - PDF, 웹사이트, DB 등 다양한 소스에서 원본 문서를 불러옵니다. (`Document Loaders`)\n",
    "> \n",
    "> #### 2단계: Split (문서 분할하기)\n",
    "> - 문서를 LLM이 처리하기 좋은 작은 조각(Chunk)으로 나눕니다. 의미가 잘 유지되도록 자르는 것이 중요합니다. (`Text Splitters`)\n",
    "> - **왜 중요할까?** 너무 작게 자르면 문맥을 잃고, 너무 크면 관련 없는 내용이 섞여 LLM의 집중력을 방해합니다.\n",
    "> \n",
    "> #### 3단계: Embed (의미의 벡터화)\n",
    "> - 각 Chunk를 텍스트 임베딩 모델을 사용해, 의미를 담은 숫자들의 배열, 즉 '벡터'로 변환합니다.\n",
    "> \n",
    "> #### 4단계: Store (벡터 저장소에 저장)\n",
    "> - 변환된 벡터와 원본 Chunk를 '벡터 저장소(Vector Store)'에 저장하여 언제든 빠르게 검색할 수 있도록 준비합니다.\n",
    "> - > [!NOTE] 비유: 벡터 저장소는 '의미로 책을 찾는 도서관 사서'\n",
    "  > > 일반 DB가 '정확한 제목'으로 책을 찾는다면, 벡터 저장소는 \"사랑과 희생에 관한 이야기\"처럼 **추상적인 의미**로 책을 찾아주는 똑똑한 사서와 같습니다. **FAISS** (빠른 임시 저장), **Chroma** (영구 저장) 등이 대표적입니다.\n",
    "> \n",
    "> ### [검색 및 생성 단계: 똑똑하게 질문하고 답변하기]\n",
    "> \n",
    "> #### 5단계: Retrieve & Generate (검색 후 생성)\n",
    "> - **Retrieve**: 사용자의 질문도 벡터로 변환한 뒤, 벡터 저장소에서 의미적으로 가장 유사한 Chunk들을 찾아냅니다.\n",
    "> - **Generate**: 검색된 Chunk들을 사용자의 원본 질문과 함께 프롬프트에 담아 LLM에게 전달합니다. LLM은 이 '참고 자료'를 바탕으로 신뢰성 높은 답변을 생성합니다.\n",
    "\n",
    "---\n",
    "\n",
    "<br>\n",
    "\n",
    "> ## 5. 직접 해보기 (Hands-on Lab): 나만의 RAG 챗봇 만들기\n",
    "> \n",
    "> 이제 LangChain을 사용하여, 주어진 텍스트에 대해 답변할 수 있는 간단한 RAG 시스템을 직접 구축해 보겠습니다.\n",
    "> \n",
    "> > [!WARNING]\n",
    "> > 이 실습은 OpenAI의 `gpt-3.5-turbo` 모델을 사용하므로, `OPENAI_API_KEY`가 필요합니다. [이곳](https://platform.openai.com/api-keys)에서 API 키를 발급받아 아래 코드에 입력해주세요.\n",
    "> \n",
    "> ### 문제:\n",
    "> 아래 `my_document` 텍스트를 RAG 파이프라인에 넣어, 마지막 `query`에 대한 답변을 생성하는 전체 코드를 완성하세요.\n",
    "> \n",
    "> "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "93feaf31",
   "metadata": {},
   "outputs": [],
   "source": [
    "// ... existing code ...\n",
    "query = \"AI 비전공자가 입문하기 좋은 책은 무엇인가요? 그리고 그 이유는 무엇인가요?\"\n",
    "response = qa_chain.invoke(query)\n",
    "print(response[\"result\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "387286c4",
   "metadata": {},
   "source": [
    "\n",
    ">\n",
    "> ---\n",
    ">\n",
    "> ### 캡스톤 프로젝트 연계 미니 프로젝트: \"회사 내부 문서 Q&A 봇 만들기 (실전 RAG)\"\n",
    "> \n",
    "> 앞서 배운 RAG 파이프라인을 활용하여, 단순 텍스트가 아닌 실제 파일(`.md`)을 기반으로 질문에 답변하는 실용적인 Q&A 봇을 구축합니다. 이 과제는 최종 캡스톤 프로젝트에서 특정 도메인(예: 법률, 의료, 금융)의 문서를 다루는 LLM 애플리케이션을 구현할 때 훌륭한 기반이 됩니다.\n",
    "> \n",
    "> -   **목표**: LangChain의 `DocumentLoader`를 사용하여 외부 마크다운 파일을 로드하고, 해당 문서의 내용에 대해서만 정확하게 답변하는 RAG 시스템을 완성합니다.\n",
    "> -   **과제**:\n",
    ">     1.  **샘플 문서 확인**: `../../source_code/data/rag_sample_company_rules.md` 파일의 내용을 확인합니다. 이 문서는 가상의 회사 보안 규정에 대한 내용을 담고 있습니다.\n",
    ">     2.  **Document Loader 사용**: 기존의 `my_document` 변수 대신, LangChain의 `TextLoader`를 사용하여 위 마크다운 파일을 로드하도록 코드를 수정하세요.\n",
    ">     3.  **성능 테스트**:\n",
    ">         -   **문서 기반 질문**: \"업무용 노트북에서 개인 이메일 사용이 가능한가요?\" 와 같이 문서에 명시된 내용에 대해 질문하고, RAG 시스템이 정확한 답변을 생성하는지 확인합니다.\n",
    ">         -   **문서 외 질문 (Grounding 테스트)**: \"회사의 연봉 정책에 대해 알려줘\" 와 같이 문서에 없는 내용에 대해 질문했을 때, 모델이 \"문서에서 관련 정보를 찾을 수 없습니다\" 또는 \"알 수 없습니다\" 와 같이 솔직하게 답변하는지(Grounding) 확인합니다.\n",
    "> -   **기대 효과**:\n",
    ">     -   `DocumentLoader`의 역할을 이해하고, 다양한 포맷의 문서를 LLM 애플리케이션에 통합하는 방법을 학습합니다.\n",
    ">     -   RAG 시스템의 핵심 역량인 'Grounding'(제공된 정보에 기반하여 답변하는 능력)의 중요성을 체감합니다.\n",
    ">     -   환각(Hallucination) 현상을 줄이고 LLM의 신뢰도를 높이는 실용적인 방법을 터득합니다.\n",
    "> -   **구현 가이드**: `../../source_code/part_7_5_llm_application_development.py` 파일의 주석 가이드를 따라 코드를 완성해보세요.\n",
    "\n",
    "---\n",
    "\n",
    "<br>\n",
    "\n",
    "> ## 6. 되짚어보기 (Summary)\n",
    "> \n",
    "> 이번 시간에는 LLM의 한계를 넘어, 외부 세계와 소통하는 AI를 만드는 강력한 기술인 RAG를 배웠습니다.\n",
    "> \n",
    "> - **RAG의 필요성**: LLM의 최신성 부족, 환각 현상과 같은 문제를 해결하기 위해, LLM에게 '오픈북 시험'을 보게 하는 방식이 RAG임을 이해했습니다.\n",
    "> - **RAG 파이프라인**: **Load → Split → Embed → Store → Retrieve & Generate** 로 이어지는 5단계의 과정을 통해 RAG 시스템이 어떻게 작동하는지 파악했습니다.\n",
    "> - **실전 RAG 구축**: LangChain을 사용하여, 주어진 문서의 내용을 기반으로 질문에 답변하는 RAG 챗봇을 직접 코드로 구현하는 경험을 쌓았습니다.\n",
    "> \n",
    "> 이제 여러분은 단순히 LLM을 사용하는 것을 넘어, LLM을 다른 데이터, 다른 도구와 '연결'하여 훨씬 더 지능적이고 실용적인 애플리케이션을 만들 수 있는 첫걸음을 뗐습니다.\n",
    "\n",
    "<br>\n",
    "\n",
    "> ## 7. 더 깊이 알아보기 (Further Reading)\n",
    "> - [LangChain 공식 문서: RAG](https://python.langchain.com/v0.2/docs/concepts/#retrieval-augmented-generation-rag): LangChain이 설명하는 RAG의 개념과 다양한 활용법\n",
    "> - [Pinecone: What is RAG?](https://www.pinecone.io/learn/retrieval-augmented-generation/): 대표적인 벡터 DB 회사인 Pinecone이 설명하는 RAG 가이드\n",
    "> - [Hugging Face 블로그: RAG](https://huggingface.co/docs/transformers/main/en/rag): 허깅페이스에서 제공하는 RAG에 대한 기술적인 설명\n",
    "\n",
    "---\n",
    "\n",
    "<br>\n",
    "\n",
    "> ### ⚠️ What Could Go Wrong? (토론 주제)\n",
    "> \n",
    "> LangChain은 LLM 기반 애플리케이션 개발을 가속화하는 강력한 도구이지만, 실제 프로덕션 환경에 적용할 때는 여러 잠재적 위험과 한계를 고려해야 합니다.\n",
    "> \n",
    "> 1.  **지나친 추상화의 함정 (The Pitfall of Over-abstraction)**\n",
    ">     *   LangChain의 고수준 추상화가 내부 동작을 이해하기 어렵게 만들어, 특정 요구사항에 맞게 커스터마이징하거나 디버깅할 때 오히려 더 복잡해지는 상황이 발생할 수 있습니다. \"간단한 일은 더 간단하게, 복잡한 일은 불가능하게\" 만드는 경우가 될 수 있을까요?\n",
    ">     *   특정 컴포넌트(예: Vectorstore)를 교체하거나 세부 동작을 수정하려 할 때, LangChain의 추상화 계층 때문에 예상보다 많은 노력이 드는 경우를 겪어본 적이 있나요?\n",
    "> \n",
    "> 2.  **프롬프트 주입 및 보안 취약점 (Prompt Injection & Security Vulnerabilities)**\n",
    ">     *   RAG(Retrieval-Augmented Generation) 파이프라인에서 사용자가 악의적으로 조작한 문서를 데이터 소스에 포함시켜, 시스템 프롬프트를 탈취하거나 의도치 않은 결과를 유도하는 '프롬프트 주입' 공격에 어떻게 대비해야 할까요?\n",
    ">     *   LangChain 에이전트가 파일 시스템 접근이나 API 호출과 같은 위험한 도구(Tool)를 사용할 때, 권한 상승이나 데이터 유출과 같은 보안 사고를 방지하기 위한 안전장치는 무엇이 있을까요?\n",
    "> \n",
    "> 3.  **에이전트의 예측 불가능성과 제어의 어려움 (Unpredictability and Controllability of Agents)**\n",
    ">     *   ReAct와 같은 복잡한 에이전트가 잘못된 추론 경로에 빠져 무한 루프를 돌거나, 의도치 않게 비싼 유료 API를 계속 호출하여 막대한 비용을 발생시키는 상황을 어떻게 방지할 수 있을까요?\n",
    ">     *   \"목표를 줄 테니 알아서 해줘\"라는 에이전트의 방식이, 실제 비즈니스 로직처럼 엄격한 제어가 필요한 경우에 적합할까요? 에이전트의 자율성과 시스템의 안정성 사이의 균형점은 어디일까요?\n",
    "> \n",
    "> 4.  **디버깅과 투명성 부족 (Lack of Debuggability and Transparency)**\n",
    ">     *   여러 체인과 에이전트, 도구가 복잡하게 얽혀 있을 때, 최종 결과가 어떤 중간 단계를 거쳐 나왔는지 추적하기 어려운 경험을 한 적이 있나요? (e.g., \"왜 이 답변이 나왔지?\")\n",
    ">     *   LangSmith와 같은 추적 도구가 이러한 문제를 어느 정도 해결해주지만, 근본적인 복잡성 자체는 여전히 높은 진입 장벽이 될 수 있지 않을까요?\n",
    "> \n",
    "> 5.  **프레임워크 종속성 문제 (Framework Lock-in)**\n",
    ">     *   애플리케이션의 핵심 로직을 LangChain의 특정 구조와 기능에 깊이 의존하여 개발했을 때, 나중에 다른 프레임워크나 순수 API 호출 기반의 코드로 전환하기 어려워지는 '기술 부채'가 될 수 있습니다. 이러한 종속성을 최소화하며 LangChain을 현명하게 활용하는 전략은 무엇일까요?\n",
    "\n",
    "---\n",
    "\n",
    "<br>\n",
    "\n",
    "**➡️ 다음 시간: [Part 7.4: 그래프 신경망 (GNN)](./part_7.4_graph_neural_networks.md)** "
   ]
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 5
}
