# Part 13: 생성형 AI 및 AI 에이전트 심화 **⬅️ 이전 시간: [Part 12: 대규모 AI 모델 최적화 및 서빙](./part_12_model_optimization.md)** **➡️ 다음 시간: [Part 14: AI 윤리 및 거버넌스 실무](./part_14_ai_ethics.md)** --- ## 1. 학습 목표 (Learning Objectives) > 이 섹션에서는 최신 생성형 AI 기술의 핵심을 이해하고, 스스로 생각하고 행동하는 자율 AI 에이전트를 설계 및 구축하는 방법을 학습합니다. - PEFT, 특히 LoRA의 원리를 이해하고, 적은 리소스로 거대 언어 모델(LLM)을 효율적으로 파인튜닝할 수 있습니다. - 쿼리 변환, 재순위화 등 고급 RAG 기술을 적용하여 검색 증강 생성의 정확도를 향상시킬 수 있습니다. - ReAct 프레임워크를 이해하고, LangGraph를 사용하여 복잡한 작업을 수행하는 자율 AI 에이전트를 설계 및 구현할 수 있습니다. - LangSmith를 활용하여 LLM 및 에이전트 기반 애플리케이션을 추적, 모니터링, 평가하는 LLMOps/AgentOps의 개념을 이해합니다. ## 2. 핵심 키워드 (Keywords) `PEFT`, `LoRA`, `RAG`, `쿼리 변환`, `Re-ranking`, `AI 에이전트`, `ReAct`, `LangGraph`, `LLMOps`, `LangSmith` ## 3. 도입 거대 언어 모델(LLM)의 등장은 AI의 패러다임을 바꾸어 놓았습니다. 이제 AI는 단순히 주어진 데이터를 처리하는 것을 넘어, 스스로 지식을 생성하고, 도구를 사용하며, 목표를 향해 자율적으로 행동하는 단계로 진화하고 있습니다. Part 13에서는 생성형 AI의 최전선에 있는 기술들을 탐험합니다. LLM을 내 목적에 맞게 길들이는 효율적인 파인튜닝 방법부터, 더 똑똑하게 정보를 찾아 활용하는 RAG 심화 기술, 그리고 궁극적으로 스스로 문제를 해결하는 AI 에이전트를 만드는 설계도까지, 차세대 AI 애플리케이션을 구축하는 핵심 역량을 배우게 될 것입니다. --- ## 4. LLM 효율적 Fine-tuning 및 RAG 심화 사전 학습된 거대 언어 모델(LLM)은 그 자체로도 강력하지만, 특정 도메인이나 스타일에 맞게 성능을 최적화하기 위해서는 파인튜닝(Fine-tuning) 과정이 필요합니다. 하지만 수백억, 수천억 개의 파라미터를 가진 LLM 전체를 파인튜닝하는 것은 엄청난 컴퓨팅 자원을 요구하며, 때로는 원본 모델이 가진 일반적인 지식을 잃어버리는 '치명적 망각(Catastrophic Forgetting)' 현상을 겪기도 합니다. 이러한 문제를 해결하기 위해, 모델의 극히 일부 파라미터만 업데이트하여 효율적으로 파인튜닝하는 **PEFT(Parameter-Efficient Fine-Tuning)** 기법들이 등장했습니다. ### PEFT (Parameter-Efficient Fine-Tuning) 란? PEFT는 LLM의 사전 학습된 가중치(weights) 대부분을 그대로 두고, 일부 추가되거나 선택된 파라미터만을 학습시키는 방법론의 총칭입니다. 이를 통해 다음과 같은 장점을 얻습니다. - **메모리 효율성**: 전체 모델이 아닌, 수백만 개 수준의 적은 파라미터만 학습하므로 훨씬 적은 GPU 메모리로 파인튜닝이 가능합니다. (예: 단일 GPU에서도 가능) - **빠른 학습 속도**: 학습 대상 파라미터가 적어 학습 시간이 단축됩니다. - **치명적 망각 방지**: 원본 모델의 가중치를 변경하지 않으므로, 기존에 학습된 지식을 보존하는 데 유리합니다. - **다중 작업 용이성**: 원본 LLM 하나에 여러 개의 작은 PEFT 모듈(어댑터)을 추가하여, 작업에 따라 어댑터만 교체하며 사용할 수 있습니다. ### LoRA (Low-Rank Adaptation of Large Language Models) LoRA는 가장 대표적이고 널리 사용되는 PEFT 기법 중 하나입니다. **핵심 아이디어**: LoRA는 "사전 학습된 언어 모델은 낮은 내재적 차원(low intrinsic rank)을 가진다"는 가정에서 출발합니다. 즉, 특정 작업에 맞게 모델을 업데이트할 때, 가중치 행렬의 변화량(Weight Update Matrix, ΔW) 또한 낮은 랭크(low rank)를 가질 것이라고 가정합니다. **작동 방식**: 기존의 가중치 행렬 `W` (d x d)를 직접 업데이트하는 대신, `W` 옆에 작은 크기의 학습 가능한 행렬 `A` (d x r)와 `B` (r x d)를 추가합니다. 여기서 `r`은 랭크(rank)로, `d`보다 훨씬 작은 값(예: 8, 16, 64)입니다. 학습 중에는 원본 `W`는 고정된 채 `A`와 `B` 행렬만 업데이트됩니다. 최종적으로 모델의 가중치는 `W + BA`로 계산됩니다. ``` Input (x) | +-----+ | W | (Frozen) <-- 기존 가중치 (d x d) +-----+ | +----------------> Output (h = Wx + BAx) | +-----+ | A | (Trainable) <-- Low-rank matrix (r x d) +-----+ | +-----+ | B | (Trainable) <-- Low-rank matrix (d x r) +-----+ | ``` Hugging Face의 `peft` 라이브러리를 사용하면 LoRA를 매우 쉽게 적용할 수 있습니다. ```python from peft import LoraConfig, get_peft_model from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-chat-hf") # LoRA 설정 config = LoraConfig( r=16, # rank lora_alpha=32, # alpha scaling target_modules=["q_proj", "v_proj"], # 적용할 레이어 lora_dropout=0.05, bias="none", task_type="CAUSAL_LM" ) # 모델에 PEFT 적용 lora_model = get_peft_model(model, config) lora_model.print_trainable_parameters() # 출력: trainable params: 8,388,608 || all params: 6,746,832,896 || trainable%: 0.12433 ``` ### RAG (Retrieval-Augmented Generation) 심화 기본적인 RAG는 외부 문서에서 관련 정보를 검색하여 LLM의 답변에 활용하는 강력한 기술이지만, 복잡한 질문에 대해서는 한계를 보이기도 합니다. 사용자의 질문이 모호하거나, 검색된 문서의 순위가 최적이 아닐 수 있기 때문입니다. 고급 RAG는 이러한 문제를 해결하기 위해 '쿼리 변환'과 '재순위화' 같은 기법들을 도입합니다. #### 1. 쿼리 변환 (Query Transformation) 사용자의 원본 질문을 그대로 벡터 검색에 사용하기보다, 더 나은 검색 결과를 얻기 위해 질문을 여러 개로 변형하거나 더 명확하게 만드는 과정입니다. - **Multi-Query**: LLM을 사용하여 사용자의 단일 질문을 다양한 관점의 여러 질문으로 확장합니다. 예를 들어, "RAG의 장단점은?" 이라는 질문을 "RAG의 장점은 무엇인가?", "RAG의 단점은 무엇인가?", "RAG는 어떤 경우에 유용한가?" 와 같이 여러 개로 만들어 각각 검색을 수행하고 결과를 종합합니다. - **RAG-Fusion**: Multi-Query와 유사하지만, 검색된 결과들의 순위를 Reciprocal Rank Fusion (RRF) 알고리즘을 사용하여 지능적으로 결합하여 가장 관련성 높은 문서를 찾아냅니다. - **Step-back Prompting**: 사용자의 구체적인 질문에서 한 단계 물러나, 더 일반적이고 근원적인 질문을 생성하여 검색에 활용합니다. 예를 들어, "우리 회사 복지제도 중 출산휴가는 며칠이야?" 라는 질문에 대해 "회사의 휴가 관련 복지제도" 라는 상위 개념의 질문을 생성하여 먼저 검색하고, 그 결과를 바탕으로 구체적인 답변을 찾게 하여 더 정확한 컨텍스트를 확보합니다. #### 2. 재순위화 (Re-ranking) 벡터 검색(Retriever)은 수많은 문서 중에서 관련성이 있을 법한 후보 문서들을 빠르게 찾아내는 데 효과적입니다. 하지만 이 초기 검색 결과가 항상 최적의 순서를 보장하지는 않습니다. **재순위화**는 Retriever가 찾아온 상위 K개의 문서를 더 정교하지만 느린 모델(Cross-Encoder)을 사용하여 다시 평가하고, 사용자 질문과의 관련성이 가장 높은 순서로 재정렬하는 과정입니다. - **작동 방식**: 1. **1단계 (Retrieval)**: Bi-Encoder 기반의 빠른 벡터 검색으로 후보 문서 50~100개를 검색합니다. 2. **2단계 (Re-ranking)**: Cross-Encoder 모델이 '(질문, 문서1)', '(질문, 문서2)' ... 와 같이 질문과 각 후보 문서를 쌍으로 입력받아, 두 텍스트 간의 실제 관련도를 0과 1 사이의 점수로 계산합니다. 3. 이 점수를 기준으로 문서들의 순위를 다시 매겨, 가장 관련도 높은 상위 3~5개의 문서를 최종적으로 LLM에 전달합니다. - **장점**: 검색의 정확도(Precision)를 크게 향상시켜, LLM이 더 정확하고 관련성 높은 답변을 생성하도록 돕습니다. **고급 RAG 파이프라인 아키텍처:** ``` User Query --> [Query Transformation] --> Multi-Queries --> [Retrieval (Vector Search)] --> Candidate Docs --> [Re-ranking (Cross-Encoder)] --> Top-K Docs --> LLM --> Final Answer ``` --- ## 5. 자율 AI 에이전트 설계 및 구축 AI 에이전트(Agent)는 단순히 주어진 질문에 답변하는 것을 넘어, 목표 달성을 위해 스스로 생각하고, 도구를 사용하며, 계획을 수정하는 능동적인 시스템을 의미합니다. 에이전트는 LLM을 '뇌'로 사용하여 주변 환경(API, 데이터베이스, 웹 검색 등)과 상호작용하며 복잡한 문제를 해결합니다. ### ReAct (Reason + Act) 프레임워크 ReAct는 에이전트가 어떻게 행동해야 할지 결정하는 가장 대표적인 프레임워크 중 하나입니다. 이름 그대로 **추론(Reasoning)**과 **행동(Action)**을 결합합니다. **작동 방식**: LLM은 단순히 최종 답변을 내놓는 것이 아니라, 다음과 같은 생각의 연쇄 과정을 통해 목표를 달성합니다. 1. **Thought (생각)**: 현재 상황을 분석하고 목표를 달성하기 위한 다음 행동 계획을 세웁니다. 2. **Action (행동)**: 계획에 따라 사용할 도구(Tool)와 그 도구에 전달할 입력(Input)을 결정합니다. 예를 들어, '웹 검색' 도구에 'AI 에이전트 최신 동향'이라는 입력을 전달할 수 있습니다. 3. **Observation (관찰)**: 행동의 결과(도구의 출력)를 관찰합니다. 웹 검색 결과, API 호출 결과 등이 해당됩니다. 4. **Thought (생각)**: 관찰된 결과를 바탕으로 목표가 달성되었는지, 또는 다음 행동은 무엇이어야 할지 다시 생각합니다. 5. 위 과정을 목표가 달성될 때까지 반복합니다. 이러한 "생각-행동-관찰"의 순환 구조를 통해 에이전트는 복잡한 작업을 체계적으로 해결하고, 중간에 문제가 발생했을 때 대처할 수 있는 능력을 갖게 됩니다. ### LangGraph: 복잡한 에이전트 워크플로우 구축 하나의 에이전트만으로는 해결하기 어려운 복잡한 작업(예: 여러 리서치 결과를 종합하여 보고서 작성)을 위해서는 여러 전문 에이전트가 서로 협력하는 '멀티-에이전트(Multi-agent)' 시스템이 필요합니다. **LangGraph**는 LangChain에서派生된 라이브러리로, 이러한 멀티-에이전트 시스템이나 순환(cyclic)적인 계산 흐름을 그래프(Graph) 형태로 쉽게 구현할 수 있도록 돕습니다. **주요 개념:** - **State (상태)**: 그래프 전체에서 공유되는 데이터 객체입니다. 각 단계(노드)를 거치면서 상태가 업데이트됩니다. 예를 들어, '수집된 정보', '남은 작업 목록' 등이 상태에 포함될 수 있습니다. - **Nodes (노드)**: 그래프의 각 단계를 나타내며, 특정 작업을 수행하는 함수나 LangChain Runnable 객체입니다. 각 노드는 현재 상태를 입력받아 작업을 수행하고, 변경된 상태를 반환합니다. - **Edges (엣지)**: 노드 간의 연결을 정의하며, 다음으로 어떤 노드로 이동할지 결정하는 역할을 합니다. - **Conditional Edges (조건부 엣지)**: 특정 노드의 실행 결과(상태)에 따라 다음에 실행될 노드를 동적으로 결정할 수 있습니다. 예를 들어, '리서치 결과가 충분하면 보고서 작성 노드로, 부족하면 추가 검색 노드로 이동'과 같은 분기 처리를 구현할 수 있습니다. **LangGraph의 장점:** - **순환성 및 제어**: 기존의 LangChain Expression Language (LCEL)이 비순환 그래프(DAG)에 최적화된 것과 달리, LangGraph는 "생각-행동-관찰" 루프와 같은 순환적인 흐름을 자연스럽게 구현할 수 있습니다. - **상태 관리**: 중앙 집중화된 상태 객체를 통해 여러 에이전트나 노드 간의 정보 공유 및 흐름 제어가 명확하고 용이합니다. - **시각화 및 디버깅**: 복잡한 에이전트의 작동 흐름을 그래프로 시각화할 수 있어, 전체 구조를 이해하고 디버깅하기 편리합니다. **LangGraph 코드 예시 (의사 코드):** ```python from langgraph.graph import StateGraph, END # 1. 상태 정의 class AgentState(TypedDict): task: str result: str # 2. 노드(함수) 정의 def research_node(state): # ... 리서치 수행 ... return {"result": "리서치 결과"} def report_node(state): # ... 보고서 작성 ... return {"result": "최종 보고서"} # 3. 조건부 엣지를 위한 함수 정의 def should_continue(state): if "보고서" in state['result']: return "end" else: return "continue" # 4. 그래프 구축 workflow = StateGraph(AgentState) workflow.add_node("researcher", research_node) workflow.add_node("reporter", report_node) workflow.set_entry_point("researcher") # 엣지 연결 workflow.add_conditional_edges( "researcher", should_continue, {"continue": "reporter", "end": END} ) workflow.add_edge('reporter', END) # 5. 그래프 컴파일 및 실행 app = workflow.compile() final_state = app.invoke({"task": "AI 에이전트 동향 보고서 작성"}) ``` LangGraph를 사용하면, 각자 다른 전문성을 가진 여러 에이전트(리서처, 작가, 비평가 등)가 서로의 작업 결과를 바탕으로 협력하고, 필요에 따라 작업을 반복하거나 수정하는 정교한 자율 에이전트 시스템을 효과적으로 구축할 수 있습니다. --- ## 6. LLMOps & AgentOps LLM과 에이전트 기반의 애플리케이션이 프로덕션 환경에서 안정적으로 운영되기 위해서는 기존의 MLOps를 넘어서는 새로운 운영 패러다임이 필요합니다. 이것이 바로 **LLMOps**와 **AgentOps**입니다. ### LLMOps: LLM 기반 애플리케이션을 위한 MLOps LLMOps는 LLM 기반 애플리케이션의 전체 수명 주기(프로토타이핑, 테스트, 배포, 모니터링, 유지보수)를 관리하고 자동화하기 위한 DevOps 원칙과 MLOps 프랙티스를 확장한 개념입니다. **기존 MLOps와의 차이점 및 LLMOps의 고유한 과제:** - **프롬프트 관리 (Prompt Management)**: LLM 앱의 성능은 프롬프트에 매우 민감합니다. 프롬프트의 버전을 관리하고, 여러 프롬프트를 A/B 테스트하며, 성능을 지속적으로 최적화하는 '프롬프트 엔지니어링'이 핵심적인 관리 대상이 됩니다. - **성능 평가의 모호성**: 모델의 정확도, F1 점수 등으로 비교적 명확하게 평가할 수 있었던 기존 ML 모델과 달리, LLM의 출력은 정성적인 평가(예: 답변의 유용성, 창의성, 적절성)가 중요합니다. 이를 위해 LLM 자체를 평가자(LLM-as-a-judge)로 활용하거나, 사람이 직접 피드백하는 등 새로운 평가 파이프라인이 필요합니다. - **실시간 추적 및 디버깅의 어려움**: 복잡한 체인(Chain)이나 에이전트의 작동 과정에서 어떤 프롬프트와 컨텍스트가 사용되었고, 중간 결과는 어떠했는지 추적하기 어렵습니다. 문제 발생 시 원인을 파악하기 위한 상세한 실행 로그와 추적 기능이 필수적입니다. - **컨텍스트 및 외부 데이터 관리**: RAG 시스템의 경우, 벡터 데이터베이스, 검색 알고리즘, 외부 API 등 관리해야 할 요소가 추가됩니다. 데이터가 변경되었을 때 전체 시스템에 미치는 영향을 관리하고 최신 상태를 유지해야 합니다. ### AgentOps: 자율 에이전트 시스템을 위한 운영 AgentOps는 LLMOps에서 한 단계 더 나아가, 여러 도구와 상호작용하며 자율적으로 작업을 수행하는 AI 에이전트 시스템에 특화된 운영 방법론입니다. 에이전트의 복잡한 "생각-행동-관찰" 루프와 멀티-에이전트 간의 상호작용을 안정적으로 운영하는 데 중점을 둡니다. **AgentOps의 주요 관심사:** - **도구 사용 모니터링**: 에이전트가 사용하는 외부 도구(API, 데이터베이스 등)의 성공/실패 여부, 지연 시간, 비용 등을 모니터링합니다. - **에이전트 궤적(Trajectory) 분석**: 에이전트가 목표를 달성하기 위해 거친 전체 의사결정 과정(생각의 연쇄)을 추적하고 분석하여, 비효율적인 행동이나 잘못된 판단을 개선합니다. - **동적 계획 및 회복력(Resilience)**: 예기치 않은 오류(예: API 실패, 잘못된 도구 사용)가 발생했을 때, 에이전트가 스스로 문제를 인식하고 계획을 수정하여 작업을 계속할 수 있도록 하는 메커니즘을 구축합니다. ### LangSmith: LLMOps & AgentOps를 위한 통합 플랫폼 LangSmith는 LangChain 개발팀이 만든 LLM 애플리케이션 개발 및 운영을 위한 통합 플랫폼입니다. 복잡한 LLM 및 에이전트 애플리케이션의 내부 작동을 투명하게 들여다보고, 문제를 진단하며, 성능을 평가하는 데 강력한 기능을 제공합니다. **주요 기능:** - **추적 (Tracing)**: - LLM 호출, 체인 실행, 에이전트의 모든 단계를 시각적으로 추적합니다. - 각 단계별 입력, 출력, 사용된 프롬프트, 토큰 사용량, 지연 시간 등의 상세 정보를 확인할 수 있어 디버깅에 매우 유용합니다. - **모니터링 (Monitoring)**: - 프로덕션 환경에서 운영되는 LLM 앱의 전반적인 상태를 모니터링하는 대시보드를 제공합니다. - API 에러율, 평균 지연 시간, 토큰 사용량, 사용자 피드백 등을 통해 서비스의 이상 징후를 신속하게 파악할 수 있습니다. - **평가 (Evaluation)**: - 특정 데이터셋에 대한 LLM 앱의 성능을 정량적/정성적으로 평가하는 프레임워크를 제공합니다. - 사용자 정의 평가 기준(예: 답변의 간결성, 유해성)을 만들거나, LLM을 평가자로 사용하여 "답변이 컨텍스트에 기반하는가?"와 같은 항목을 자동으로 채점할 수 있습니다. - 여러 버전의 프롬프트나 모델을 비교 평가하여 최적의 조합을 찾는 데 활용됩니다. - **프롬프트 허브 (Prompt Hub)**: - 자주 사용되거나 성능이 검증된 프롬프트를 중앙에서 관리하고 버전 제어를 할 수 있습니다. (LangChain 커뮤니티와 프롬프트를 공유할 수도 있습니다) LangSmith는 개발 초기 단계의 디버깅부터 프로덕션 환경의 모니터링 및 성능 최적화에 이르기까지, LLMOps와 AgentOps의 거의 모든 과정을 지원하는 핵심적인 도구라고 할 수 있습니다. --- ## 7. 개념 확인 퀴즈 (Concept Check Quiz) 1. LLM을 파인튜닝할 때 전체 파라미터를 학습시키는 것과 비교하여 LoRA 방식이 갖는 가장 큰 장점은 무엇인가요? 2. 고급 RAG 파이프라인에서 '재순위화(Re-ranking)' 단계가 필요한 이유는 무엇인가요? 3. AI 에이전트의 ReAct 프레임워크에서 'Thought', 'Action', 'Observation'의 순환 구조는 어떤 역할을 하나요? --- ## 8. 과제 (Assignment) 1. **고급 RAG 파이프라인 설계**: 여러분 회사의 내부 문서를 기반으로 답변하는 Q&A 챗봇을 만들려고 합니다. 사용자의 질문이 모호하거나 너무 구체적인 경우에도 정확한 답변을 찾을 수 있도록, 본문에서 배운 '쿼리 변환' 기법 중 2가지 이상을 조합하여 RAG 파이프라인을 어떻게 개선할지 구체적인 예시와 함께 설명해 주세요. 2. **AI 에이전트 설계**: LangGraph를 사용하여 '오늘 날씨를 확인하고, 날씨에 맞는 옷차림을 추천해 주는' 간단한 AI 에이전트를 설계해 보세요. 어떤 노드(Node)들이 필요하고, 노드 간의 엣지(Edge)는 어떻게 연결되어야 할지 순서도나 의사 코드로 표현해 보세요. --- ## 9. 되짚어보기 (Summary) 이번 파트에서는 생성형 AI의 최전선에 있는 기술들과, 스스로 문제를 해결하는 자율 AI 에이전트를 구축하는 방법을 탐험했습니다. - **효율적 LLM 파인튜닝**: PEFT의 개념을 이해하고, 대표적인 기법인 LoRA를 사용하여 적은 리소스로 LLM을 특정 작업에 맞게 효율적으로 튜닝하는 방법을 배웠습니다. - **RAG 심화**: 기본적인 RAG를 넘어 쿼리 변환, 재순위화 등의 고급 기술을 통해 검색 증강 생성의 정확도를 한 단계 끌어올리는 방법을 확인했습니다. - **자율 AI 에이전트**: LLM을 두뇌로 사용하는 AI 에이전트의 개념을 이해하고, ReAct 프레임워크와 LangGraph를 사용하여 복잡한 작업을 수행하는 에이전트를 설계하고 구축하는 방법을 학습했습니다. - **LLMOps & AgentOps**: LLM 기반 애플리케이션의 안정적인 운영을 위한 LLMOps의 개념과 LangSmith를 활용한 추적, 모니터링, 평가 방법을 이해했습니다. --- ## 10. 더 깊이 알아보기 (Further Reading) - [Hugging Face PEFT 라이브러리](https://huggingface.co/docs/peft/index): LoRA 등 다양한 PEFT 기법 구현체 - [LangChain RAG 문서](https://python.langchain.com/v0.2/docs/concepts/#retrieval-augmented-generation-rag): 쿼리 변환, 재순위화 등 다양한 RAG 관련 기능 소개 - [LangGraph 공식 문서](https://langchain-ai.github.io/langgraph/): 순환적인 에이전트 워크플로우 구축 가이드 - [LangSmith 공식 문서](https://docs.smith.langchain.com/): LLM 애플리케이션 추적 및 평가 플랫폼 --- **➡️ 다음 시간: [Part 14: AI 윤리 및 거버넌스 실무](./part_14_ai_ethics.md)**