Skip to content
바람부는 자유
Go back
LLM Engineering

LangChain vs LiteLLM 비교 가이드

LLM Engineering (16/21)

  1. LLM 토큰 기본 개념
  2. LLM Tokenizer 추가 학습
  3. LLM Inference 이해하기: 토큰 예측의 마법
  4. LLM API 기초 (Part 1/3)
  5. LLM API 중급 (Part 2/3)
  6. LLM API 고급 (Part 3/3)
  7. System Message 활용하기
  8. LLM을 활용한 회의록 자동 요약 시스템
  9. Multi-Modal AI 기초
  10. Gradio 기본 사용법
  11. Hugging Face 완전 정복: AI 모델의 GitHub
  12. Google Colab 사용해보기: 무료로 GPU 환경에서 AI 모델 실행하기
  13. Tool Use (Function Calling)
  14. LLM 벤치마크 완전 가이드: 모델 성능 평가의 모든 것
  15. Vector Embeddings와 RAG 기초
  16. LangChain vs LiteLLM 비교 가이드
  17. 고급 RAG: 벡터 데이터베이스를 활용한 문서 검색 시스템
  18. RAG 기반 고객 상담 챗봇 만들기
  19. RAG 시스템 평가 (RAG Evaluation)
  20. 고급 RAG 기법 (Advanced RAG Techniques)
  21. 08-1. 데이터셋 개념 정리

원문: LangChain vs LiteLLM by Hey Amit

개요

LangChain과 LiteLLM은 모두 AI 커뮤니티에서 인기 있는 프레임워크이지만, 서로 매우 다른 요구사항을 충족합니다. 이 노트북에서는 두 도구의 특성과 적합한 사용 시나리오를 알아보고, 실제 코드 예제를 통해 비교해봅니다.

주제내용
LangChain복잡한 워크플로우를 위한 범용 프레임워크
LiteLLM경량화된 통합 LLM 인터페이스
비교 분석장단점, 사용 사례, 선택 가이드
실습두 프레임워크의 실제 사용 예제

학습 목표

  1. LangChain의 핵심 개념과 사용법 이해하기
  2. LiteLLM의 특징과 장점 파악하기
  3. 프로젝트 요구사항에 맞는 프레임워크 선택하기
  4. 두 프레임워크를 함께 사용하는 방법 익히기

0. 필요한 라이브러리 설치 및 임포트

pip install openai langchain langchain-openai langchain-community litellm python-dotenv
import os
from dotenv import load_dotenv

# API 키 설정
load_dotenv(override=True)
openai_api_key = os.getenv('OPENAI_API_KEY')

if openai_api_key:
    print(f"✅ OpenAI API Key loaded (시작: {openai_api_key[:8]}...)")
else:
    print("❌ OpenAI API Key not found")
✅ OpenAI API Key loaded (시작: sk-proj-...)

1. LangChain 소개

핵심 철학

"복잡한 문제를 해결하려면 복잡한 도구가 필요하다"

LangChain은 복잡한 워크플로우를 위한 강력한 범용 프레임워크입니다. 2022년 Harrison Chase가 시작한 이 프로젝트는 LLM과 외부 데이터 소스, 도구들을 쉽게 연결할 수 있게 해줍니다.

주요 특징

특징설명
모듈성 (Modularity)다양한 LLM 작업을 체인으로 연결하여 복잡한 워크플로우 구축
확장성 (Extensibility)여러 데이터 소스에서 데이터를 가져와 단계별로 처리 가능
체이닝 컴포넌트다양한 컴포넌트를 연결하여 고급 사용 사례 구현
외부 도구 통합다양한 외부 도구 및 서비스와 쉽게 통합
커스터마이징체인의 각 컴포넌트를 세밀하게 제어 가능

핵심 구성 요소

구성 요소설명
ModelsOpenAI, Anthropic, HuggingFace 등 다양한 LLM 통합
Prompts프롬프트 템플릿 및 관리
Chains여러 컴포넌트를 연결한 워크플로우
Retrievers벡터 DB, 검색 엔진 등에서 문서 검색
Memory대화 히스토리 관리
AgentsLLM이 도구를 선택하고 실행하는 자율 시스템

적합한 사용 사례

LangChain 기본 사용 예제

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

# 1. 모델 초기화
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.7)

# 2. 프롬프트 템플릿 정의
prompt = ChatPromptTemplate.from_messages([
    ("system", "당신은 {topic} 전문가입니다. 간결하고 명확하게 답변해주세요."),
    ("user", "{question}")
])

# 3. 체인 구성 (LCEL - LangChain Expression Language)
chain = prompt | llm | StrOutputParser()

# 4. 체인 실행
response = chain.invoke({
    "topic": "Python 프로그래밍",
    "question": "리스트 컴프리헨션이란 무엇인가요?"
})

print("🔗 LangChain 응답:")
print(response)
🔗 LangChain 응답:
리스트 컴프리헨션(List Comprehension)은 파이썬에서 리스트를 간결하게 생성할 수 있는 방법입니다. 일반적인 리스트 생성 방식보다 더 짧고 읽기 쉽게 표현할 수 있습니다. 

기본 문법은 다음과 같습니다:

```python
[표현식 for 아이템 in iterable if 조건]

예를 들어, 0부터 9까지의 숫자 중 짝수만 포함하는 리스트를 생성하고 싶다면:

even_numbers = [x for x in range(10) if x % 2 == 0]

위 코드는 [0, 2, 4, 6, 8]을 생성합니다. 리스트 컴프리헨션은 가독성이 좋고, 코드의 간결성을 향상시킵니다.


</div>


### LangChain 체이닝 예제

여러 단계를 연결하여 복잡한 워크플로우를 구성할 수 있습니다.


```python
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough

# 리뷰할 코드 (의도적으로 개선이 필요한 코드)
sample_code = """
def calculate_average(numbers):
    total = 0
    for i in range(len(numbers)):
        total = total + numbers[i]
    average = total / len(numbers)
    return average
"""

# 1단계: 코드 문제점 분석
review_prompt = ChatPromptTemplate.from_template(
    "다음 Python 코드의 문제점과 개선할 점을 분석하세요:\n```python\n{code}\n```\n\n문제점:"
)

# 2단계: 개선된 코드 생성
improve_prompt = ChatPromptTemplate.from_template(
    "원본 코드:\n```python\n{code}\n```\n\n발견된 문제점:\n{issues}\n\n위 문제점을 해결한 개선된 코드를 작성하세요:"
)

# 체인 구성: 문제점 분석 → 개선된 코드 생성
review_chain = review_prompt | llm | StrOutputParser()

full_chain = (
    {"issues": review_chain, "code": RunnablePassthrough()}
    | improve_prompt
    | llm
    | StrOutputParser()
)

# 실행
print("📝 원본 코드:")
print(sample_code)
print("\n" + "="*50 + "\n")

result = full_chain.invoke(sample_code)

print("🔧 코드 리뷰 결과 (개선된 코드):")
print(result)
📝 원본 코드:

def calculate_average(numbers):
    total = 0
    for i in range(len(numbers)):
        total = total + numbers[i]
    average = total / len(numbers)
    return average


==================================================

🔧 코드 리뷰 결과 (개선된 코드):
아래는 주어진 문제점을 해결하고 개선된 코드를 작성한 예시입니다. 이 코드는 입력 검증, 빈 리스트 처리, 가독성을 높이기 위해 Python 내장 함수를 사용합니다.

```python
def calculate_average(numbers):
    # 입력 검증: numbers가 리스트인지 확인하고 빈 리스트인지 체크
    if not isinstance(numbers, list) or not numbers:
        return None  # 또는 적절한 예외 처리

    # 모든 요소가 숫자인지 확인
    for number in numbers:
        if not isinstance(number, (int, float)):
            raise ValueError("All elements must be numbers")

    # 총합 계산 및 평균 반환
    total = sum(numbers)
    average = total / len(numbers)
    return average

개선된 코드의 특징 및 장점

  1. 입력 검증: numbers가 리스트인지 확인하고, 빈 리스트인 경우 None을 반환하여 안정성을 높였습니다.
  2. 모든 요소 타입 검사: 리스트의 모든 요소가 숫자인지 확인하여, 잘못된 입력에 대해 ValueError를 발생시킵니다.
  3. 가독성 향상: sum() 함수를 사용하여 코드를 간결하게 만들었습니다. 반복문을 통한 수동 합계 계산을 피했습니다.
  4. Pythonic한 접근: Python의 내장 기능을 사용하여 코드의 가독성과 효율성을 높였습니다.

이 개선된 코드는 다양한 입력 상황에서 안정적으로 작동하며, 오류 상황을 명확하게 처리합니다.


</div>


#### 위 코드 상세 설명

##### LCEL (LangChain Expression Language)

LangChain 0.1 버전부터 도입된 **LCEL**은 체인을 구성하는 선언적 방식입니다. 파이프 연산자(`|`)를 사용하여 컴포넌트들을 직관적으로 연결합니다.

```python
chain = prompt | llm | output_parser
핵심 개념
개념설명
RunnableLCEL의 기본 단위. 모든 컴포넌트(prompt, llm, parser 등)는 Runnable 인터페이스를 구현
파이프 연산자 (|)왼쪽 Runnable의 출력을 오른쪽 Runnable의 입력으로 전달
RunnablePassthrough입력을 그대로 다음 단계로 전달. 여러 입력을 병렬로 처리할 때 유용
RunnableParallel여러 Runnable을 병렬로 실행하고 결과를 딕셔너리로 결합

예제 시나리오: 코드 리뷰 체인

이 예제에서는 문제가 있는 코드를 입력받아 문제점 분석 → 개선된 코드 생성의 2단계를 거칩니다.

입력 코드의 문제점:

def calculate_average(numbers):
    total = 0
    for i in range(len(numbers)):      # ❌ 파이썬답지 않은 반복문
        total = total + numbers[i]      # ❌ += 연산자 미사용
    average = total / len(numbers)      # ❌ 빈 리스트 처리 없음 (ZeroDivisionError)
    return average

Step 1: 프롬프트 템플릿 정의
# 1단계: 코드 문제점 분석 프롬프트
review_prompt = ChatPromptTemplate.from_template(
    "다음 Python 코드의 문제점과 개선할 점을 분석하세요:\n```python\n{code}\n```\n\n문제점:"
)

# 2단계: 개선된 코드 생성 프롬프트
improve_prompt = ChatPromptTemplate.from_template(
    "원본 코드:\n```python\n{code}\n```\n\n발견된 문제점:\n{issues}\n\n위 문제점을 해결한 개선된 코드를 작성하세요:"
)
  • {code}: 리뷰할 원본 코드가 들어갈 자리
  • {issues}: 1단계에서 분석한 문제점이 들어갈 자리

Step 2: 첫 번째 체인 구성 (문제점 분석)
review_chain = review_prompt | llm | StrOutputParser()

이 체인의 동작:

입력: "def calculate_average(numbers):..."
  │
  ▼ review_prompt
"다음 Python 코드의 문제점과 개선할 점을 분석하세요:
```python
def calculate_average(numbers):
    total = 0
    ...

문제점:" │ ▼ llm AIMessage(content="1. for i in range(len())은 파이썬답지 않습니다...") │ ▼ StrOutputParser() "1. for i in range(len())은 파이썬답지 않습니다. 2. 빈 리스트 입력 시 ZeroDivisionError 발생 3. total = total + 대신 += 사용 권장"


---

##### Step 3: 전체 체인 구성 (핵심!)

```python
full_chain = (
    {"issues": review_chain, "code": RunnablePassthrough()}
    | improve_prompt
    | llm
    | StrOutputParser()
)

{"issues": review_chain, "code": RunnablePassthrough()}

이것이 핵심입니다! 딕셔너리는 RunnableParallel의 축약 문법으로, 두 작업을 병렬로 실행합니다:

동작
issuesreview_chain코드를 분석하여 문제점 추출
codeRunnablePassthrough()원본 코드를 그대로 전달
입력: "def calculate_average(numbers):..."
                    │
        ┌───────────┴───────────┐
        ▼                       ▼
   review_chain           RunnablePassthrough()
   (문제점 분석)              (원본 코드 유지)
        │                       │
        ▼                       ▼
"1. for i in range..."    "def calculate_average..."
        │                       │
        └───────────┬───────────┘
                    ▼
    {
      "issues": "1. for i in range(len())은 파이썬답지 않습니다...",
      "code": "def calculate_average(numbers):..."
    }

RunnablePassthrough()가 필요한가?

2단계 프롬프트(improve_prompt)에는 원본 코드문제점 둘 다 필요합니다.

  • issues: 1단계 분석 결과 (새로 생성)
  • code: 원본 코드 (그대로 유지) ← RunnablePassthrough()의 역할

Step 4: 최종 프롬프트 생성 및 실행

딕셔너리가 improve_prompt로 전달되면:

"원본 코드:
```python
def calculate_average(numbers):
    total = 0
    for i in range(len(numbers)):
        total = total + numbers[i]
    average = total / len(numbers)
    return average

발견된 문제점:

  1. for i in range(len())은 파이썬답지 않습니다.
  2. 빈 리스트 입력 시 ZeroDivisionError 발생
  3. total = total + 대신 += 사용 권장

위 문제점을 해결한 개선된 코드를 작성하세요:"


이 프롬프트가 LLM에 전달되어 개선된 코드가 생성됩니다.

---

##### 전체 실행 흐름 요약

"def calculate_average(numbers):..." │ ▼ ┌─────────────────────────────────────────┐ │ RunnableParallel (병렬 실행) │ │ ┌───────────────┬─────────────────┐ │ │ │ issues: │ code: │ │ │ │ review_chain │ RunnablePass │ │ │ │ (문제점 분석) │ through() │ │ │ │ │ │ (원본 유지) │ │ │ │ ▼ │ ▼ │ │ │ │ "1. for i..." │ 원본 코드 │ │ │ └───────────────┴─────────────────┘ │ └─────────────────────────────────────────┘ │ ▼ {"issues": "1. for i...", "code": "def calculate..."} │ ▼ ┌─────────────────────────────────────────┐ │ improve_prompt │ │ "원본 코드: ... 문제점: ... 개선하세요:" │ └─────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────┐ │ llm → StrOutputParser() │ │ 개선된 코드 생성 │ └─────────────────────────────────────────┘ │ ▼ "def calculate_average(numbers): if not numbers: return 0 return sum(numbers) / len(numbers)"


---

##### 왜 체이닝이 유용한가?

1. **관심사 분리**: 문제점 분석과 코드 개선을 독립적인 단계로 분리
2. **재사용성**: `review_chain`을 다른 워크플로우에서도 재사용 가능
3. **디버깅 용이**: 각 단계의 입출력을 독립적으로 확인 가능
4. **유연한 구성**: 새로운 단계 추가(예: 테스트 코드 생성)가 쉬움

---

## 2. LiteLLM 소개

### 핵심 철학

> "효율성과 단순함을 위한 민첩하고 세련된 도구"

LiteLLM은 **경량화된 미니멀리스트 접근방식**의 LLM 통합 도구입니다. 100개 이상의 LLM을 **동일한 OpenAI 형식의 API**로 호출할 수 있게 해줍니다.

### 주요 특징

| 특징 | 설명 |
|------|------|
| **경량 아키텍처** | 복잡한 체인이나 모듈 없이 효율적이고 쉬운 통합 |
| **통합 인터페이스** | OpenAI, Azure, Anthropic, Cohere 등 여러 모델을 단일 API로 접근 |
| **간편한 통합** | 몇 줄의 코드로 기존 시스템에 빠르게 적용 가능 |
| **성능 최적화** | 최소한의 리소스 오버헤드로 모델 실행 |
| **편리한 인증** | 환경 변수 설정만으로 인증 및 연결 관리 |
| **빠른 프로토타이핑** | 간단한 API로 빠른 실험 및 개발 지원 |

### 지원하는 LLM 제공자

- OpenAI (GPT-4, GPT-4o, GPT-3.5)
- Anthropic (Claude 3.5, Claude 3)
- Google (Gemini)
- Azure OpenAI
- AWS Bedrock
- Cohere
- HuggingFace
- Ollama (로컬 모델)
- 그 외 100개 이상...

### 적합한 사용 사례

- 제한된 인프라의 웹 앱에서 AI 기능 구동
- 실시간, 저지연 LLM 애플리케이션
- 빠른 프로토타이핑 및 개발
- 여러 LLM 제공자 간 유연한 전환이 필요한 프로젝트
- 벤더 종속 방지가 필요한 경우

### LiteLLM 기본 사용 예제


```python
from litellm import completion

# OpenAI 모델 호출 (기본)
response = completion(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "리스트 컴프리헨션이란 무엇인가요? 간결하게 설명해주세요."}],
    temperature=0.7
)

print("⚡ LiteLLM 응답 (OpenAI):")
print(response.choices[0].message.content)
⚡ LiteLLM 응답 (OpenAI):
리스트 컴프리헨션(List Comprehension)은 파이썬에서 리스트를 간결하고 효율적으로 생성하는 방법입니다. 기존 리스트나 반복 가능한 객체를 기반으로 새로운 리스트를 만들 수 있으며, 조건문을 통해 필터링도 가능합니다. 기본 구조는 다음과 같습니다:

```python
[expression for item in iterable if condition]

예를 들어, 0부터 9까지의 짝수 리스트를 생성하려면 다음과 같이 작성할 수 있습니다:

even_numbers = [x for x in range(10) if x % 2 == 0]

위 코드는 [0, 2, 4, 6, 8]이라는 리스트를 생성합니다. 리스트 컴프리헨션을 사용하면 코드가 더 간결하고 가독성이 높아집니다.


</div>


### LiteLLM의 강점: 동일한 인터페이스로 다양한 모델 호출

LiteLLM의 가장 큰 장점은 모든 LLM을 **동일한 OpenAI 형식**으로 호출할 수 있다는 점입니다.


```python
from litellm import completion

# 다양한 모델을 동일한 인터페이스로 호출하는 예제
models_to_test = [
    "gpt-4o-mini",           # OpenAI
    # "claude-3-haiku-20240307",  # Anthropic (API 키 필요)
    # "gemini/gemini-pro",        # Google (API 키 필요)
]

question = "Python의 장점을 한 문장으로 설명해주세요."

for model in models_to_test:
    try:
        response = completion(
            model=model,
            messages=[{"role": "user", "content": question}],
            temperature=0.7
        )
        print(f"\n📌 {model}:")
        print(response.choices[0].message.content)
    except Exception as e:
        print(f"\n❌ {model}: {str(e)[:50]}...")

LiteLLM 스트리밍 예제

from litellm import completion

# 스트리밍 응답
print("⚡ LiteLLM 스트리밍 응답:\n")

response = completion(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "1부터 5까지 숫자를 세면서 각 숫자에 대한 재미있는 사실을 알려주세요."}],
    stream=True
)

for chunk in response:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)

print()  # 줄바꿈
⚡ LiteLLM 스트리밍 응답:

물론입니다! 1부터 5까지 각 숫자에 대한 재미있는 사실을 소개할게요.

1. **1**: 숫자 1은 종종 '유일한 존재'를 나타내며, 수학적으로는 모든 수의 곱셈 항등원입니다. 즉, 어떤 숫자에 1을 곱해도 그 숫자 자신이 나옵니다. 또한, 여러 문화에서 중요한 상징적 의미를 가지며 '일체'나 '첫 번째'를 나타내기도 합니다.

2. **2**: 숫자 2는 대칭과 짝을 의미합니다. 대부분의 동물은 쌍으로 된 감각 기관(눈, 귀 등)을 가지고 있으며, 이는 생물학적으로 적응과 생존에 도움을 줍니다. 또한, '2'는 첫 번째 소수이기도 합니다.

3. **3**: 숫자 3은 매우 크고 다양한 의미를 지니고 있습니다. 서양 문화에서는 '세 가지 단위'가 여러 가지 것들(예: 과거, 현재, 미래; 정신, 육체, 영혼 등)을 상징합니다. 또한, 삼각형은 가장 안정적인 형체로 알려져 있습니다.

4. **4**: 숫자 4는 많은 문화에서 '완전함'을 상징합니다. 예를 들어, 동서양 모두에서 사계절(봄, 여름, 가을, 겨울)이라는 네 가지 주기가 중요시됩니다. 하지만, 일부 아시아 문화에서는 4가 '죽음'과 관련되어 있어 불행한 숫자로 여겨지기도 합니다.

5. **5**: 숫자 5는 인간의 손가락 수와 맞닿아 있어 많은 문화에서 특별한 중요성을 가집니다. 예를 들어, 다섯은 완전한 수로 간주되며, 자연에서 5각형(예: 별)이 자주 발견됩니다. 또한, 다섯은 '오감'을 대표하여 감각적인 경험과 관련이 깊습니다.

각 숫자는 단순한 수 이상의 의미와 상징을 지닙니다. 흥미로운 사실들로 여러분의 하루가 더욱 풍성해지기를 바랍니다!

3. LangChain vs LiteLLM 비교

비교 요약

항목LangChainLiteLLM
설계 철학복잡성 & 커스터마이징단순성 & 효율성
학습 곡선높음 (모듈 구조 이해 필요)낮음 (초보자 친화적)
사용 사례복잡한 멀티스텝 워크플로우빠른 프로토타이핑, 간단한 앱
아키텍처모듈식, 체이닝 기반스트림라인, 경량화
리소스 요구상대적으로 높음최소화된 오버헤드
주요 강점유연성, 확장성, 다기능속도, 간편함, 통합 API

코드 복잡성 비교

# 동일한 작업을 두 프레임워크로 구현

question = "Python에서 리스트와 튜플의 차이점은?"

# === LangChain 방식 ===
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

llm = ChatOpenAI(model="gpt-4o-mini")
prompt = ChatPromptTemplate.from_template("{question}")
chain = prompt | llm | StrOutputParser()
langchain_response = chain.invoke({"question": question})

print("🔗 LangChain (5줄의 설정 코드):")
print(langchain_response[:200] + "...\n")

# === LiteLLM 방식 ===
from litellm import completion

response = completion(model="gpt-4o-mini", messages=[{"role": "user", "content": question}])
litellm_response = response.choices[0].message.content

print("⚡ LiteLLM (1줄의 설정 코드):")
print(litellm_response[:200] + "...")
🔗 LangChain (5줄의 설정 코드):
리스트와 튜플은 둘 다 파이썬에서 순서가 있는 컬렉션 데이터 타입이지만, 몇 가지 중요한 차이점이 있습니다. 아래에서 그 차이점을 설명합니다.

1. **변경 가능성 (Mutability)**:
   - **리스트**: 변경 가능합니다. 즉, 리스트의 요소를 추가, 삭제 또는 수정할 수 있습니다.
     ```python
     my_list = [1,...

⚡ LiteLLM (1줄의 설정 코드):
Python에서 리스트(`list`)와 튜플(`tuple`)은 둘 다 순서가 있는 컬렉션 타입이지만, 몇 가지 중요한 차이점이 있습니다.

1. **변경 가능성 (Mutability)**:
   - **리스트**: 변경 가능(mutable)합니다. 즉, 리스트의 요소를 추가, 삭제, 수정할 수 있습니다.
   - **튜플**: 변경 불가능(immutable...

언제 무엇을 선택할까?

LangChain을 선택하세요 if:

  • ✅ 복잡한 멀티스텝 워크플로우가 필요한 경우
  • ✅ 문서 처리, RAG, 에이전트 시스템을 구축하는 경우
  • ✅ 다양한 컴포넌트의 세밀한 제어가 필요한 경우
  • ✅ 외부 도구와의 깊은 통합이 필요한 경우

LiteLLM을 선택하세요 if:

  • ✅ 간단하고 빠른 LLM 통합이 필요한 경우
  • ✅ 복잡한 프레임워크 학습 없이 빠르게 시작하고 싶은 경우
  • ✅ 리소스 제약이 있는 환경에서 작업하는 경우
  • ✅ 여러 LLM 제공자 간 유연하게 전환하고 싶은 경우
  • ✅ 신속한 배포가 우선인 경우

4. 두 프레임워크 함께 사용하기

두 도구는 상호 배타적이지 않습니다. 실제로 많은 프로젝트에서 함께 사용됩니다.

LangChain의 강력한 오케스트레이션 기능과 LiteLLM의 제공자 유연성을 결합하여 두 세계의 장점을 모두 활용할 수 있습니다.

# LangChain 내에서 LiteLLM을 LLM Provider로 사용하는 예시
from langchain_community.chat_models import ChatLiteLLM
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

# LiteLLM을 통해 모델 호출 (LangChain 체인 내에서)
chat = ChatLiteLLM(model="gpt-4o-mini", temperature=0.7)

prompt = ChatPromptTemplate.from_messages([
    ("system", "당신은 도움이 되는 AI 어시스턴트입니다."),
    ("user", "{question}")
])

chain = prompt | chat | StrOutputParser()

response = chain.invoke({"question": "LangChain과 LiteLLM을 함께 사용하는 장점은 무엇인가요?"})

print("🔗⚡ LangChain + LiteLLM 조합:")
print(response)

실전 예제: 모델 폴백(Fallback) 전략

LiteLLM의 모델 전환 기능을 활용하여, 주 모델이 실패할 경우 대체 모델을 사용하는 전략을 구현할 수 있습니다.

from litellm import completion
import litellm

# 폴백 모델 목록
fallback_models = [
    "gpt-4o-mini",      # 1순위: GPT-4o-mini
    "gpt-3.5-turbo",    # 2순위: GPT-3.5
]

def completion_with_fallback(messages, **kwargs):
    """폴백 전략이 적용된 completion 함수"""
    for model in fallback_models:
        try:
            response = completion(
                model=model,
                messages=messages,
                **kwargs
            )
            print(f"✅ 성공: {model}")
            return response
        except Exception as e:
            print(f"❌ 실패 ({model}): {str(e)[:50]}")
            continue
    raise Exception("모든 모델이 실패했습니다.")

# 테스트
response = completion_with_fallback(
    messages=[{"role": "user", "content": "안녕하세요!"}],
    temperature=0.7
)
print(f"\n응답: {response.choices[0].message.content}")

5. 요약

핵심 정리

프레임워크한 줄 요약
LangChain복잡한 LLM 워크플로우를 위한 풀스택 프레임워크
LiteLLM100+ LLM을 단일 API로 호출하는 경량 라이브러리

선택 가이드

프로젝트 요구사항 분석
        │
        ▼
┌─────────────────────────────┐
│ 복잡한 체인/에이전트 필요?  │
└─────────────────────────────┘
        │
   Yes  │  No
        │
   ▼    │    ▼
LangChain    │
             │
     ┌───────────────────────┐
     │ 여러 LLM 제공자 전환?  │
     └───────────────────────┘
             │
        Yes  │  No
             │
        ▼    │    ▼
     LiteLLM │  직접 API 호출

결론

선택은 프로젝트의 구체적인 요구사항에 따라 달라집니다:

  • 단순성과 빠른 개발이 우선이라면 → LiteLLM
  • 복잡한 워크플로우와 커스터마이징이 필요하다면 → LangChain
  • 두 가지 모두 필요하다면함께 사용

두 도구의 차이점을 이해하면 언어 모델 애플리케이션에 적합한 도구를 선택하는 데 도움이 됩니다.


참고 자료


Share this post on:

Previous Post
고급 RAG: 벡터 데이터베이스를 활용한 문서 검색 시스템
Next Post
Vector Embeddings와 RAG 기초