LangChain-Upstage 패키지 완벽 가이드
📚 목차
- 개요
- Upstage 소개
- 설치 및 설정
- 핵심 컴포넌트
- 사용 가능한 모델
- 실전 활용 예제
- 다른 LLM 제공자와 비교
- 요금 정책
- 트러블슈팅
- 참고 자료
개요
langchain-upstage는 한국 AI 기업 Upstage의 Solar 모델 시리즈를 LangChain 프레임워크에서 원활하게 사용할 수 있도록 제공하는 공식 통합 패키지입니다.
주요 특징
- ✅ LangChain 네이티브 통합: LangChain의 모든 기능과 완벽 호환
- ✅ 한국어 최적화: 한국어 처리 성능이 뛰어난 Solar 모델
- ✅ 다양한 기능: LLM, 임베딩, 문서 파싱, Groundedness Check 지원
- ✅ 비용 효율적: OpenAI 대비 경제적인 가격
- ✅ 빠른 응답 속도: 경량화된 모델로 빠른 추론
Upstage 소개
회사 정보
- 설립: 2020년
- 창업자: 김성훈 교수 (홍콩과기대 교수, 전 네이버 Clova AI 헤드)
- 미션: "Making AI Beneficial"
- 주요 제품: Solar LLM, Document AI, Groundedness Check
Solar 모델의 특징
- Depth Up-Scaling (DUS): 작은 모델을 효율적으로 확장하는 기술
- 한국어 특화: 한국어 벤치마크에서 우수한 성능
- 경량화: 동급 성능 대비 작은 모델 크기
- 실용성: 실제 서비스에 바로 적용 가능한 기능들
설치 및 설정
1. 패키지 설치
pip install langchain-upstage
pip install langchain-upstage==0.2.0
pip install langchain-upstage[dev]
2. API 키 발급
단계별 가이드:
- Upstage Console 접속
- 회원가입 또는 로그인
- 좌측 메뉴에서 "API Keys" 클릭
- "Create API Key" 버튼 클릭
- API 키 이름 입력 후 생성
- 생성된 키 복사 (한 번만 표시됨!)
3. 환경 변수 설정
방법 1: .env 파일 사용
UPSTAGE_API_KEY=your-api-key-here
from dotenv import load_dotenv
import os
load_dotenv()
api_key = os.getenv("UPSTAGE_API_KEY")
방법 2: 직접 전달
from langchain_upstage import ChatUpstage
llm = ChatUpstage(
api_key="your-api-key-here"
)
방법 3: 환경 변수 export
export UPSTAGE_API_KEY="your-api-key-here"
핵심 컴포넌트
1. ChatUpstage - LLM 대화 모델
기본 사용법
from langchain_upstage import ChatUpstage
from langchain_core.messages import HumanMessage, SystemMessage
llm = ChatUpstage(
model="solar-pro",
temperature=0.7,
max_tokens=1000
)
response = llm.invoke("파이썬의 장점을 3가지 알려줘")
print(response.content)
messages = [
SystemMessage(content="너는 친절한 AI 어시스턴트야"),
HumanMessage(content="LangChain이 뭐야?")
]
response = llm.invoke(messages)
스트리밍
for chunk in llm.stream("긴 이야기를 들려줘"):
print(chunk.content, end="", flush=True)
비동기 사용
import asyncio
async def async_chat():
response = await llm.ainvoke("비동기로 대화하기")
return response
asyncio.run(async_chat())
2. UpstageEmbeddings - 임베딩 모델
문서 임베딩
from langchain_upstage import UpstageEmbeddings
embeddings = UpstageEmbeddings(
model="solar-embedding-1-large"
)
docs = [
"LangChain은 LLM 애플리케이션 개발 프레임워크입니다.",
"Upstage는 한국의 AI 스타트업입니다.",
"Solar는 Upstage의 LLM 모델입니다."
]
doc_vectors = embeddings.embed_documents(docs)
print(f"벡터 차원: {len(doc_vectors[0])}")
쿼리 임베딩
query = "LangChain이란 무엇인가요?"
query_vector = embeddings.embed_query(query)
유사도 검색 예제
import numpy as np
from numpy.linalg import norm
def cosine_similarity(a, b):
return np.dot(a, b) / (norm(a) * norm(b))
for i, doc in enumerate(docs):
doc_vec = doc_vectors[i]
similarity = cosine_similarity(query_vector, doc_vec)
print(f"문서 {i+1} 유사도: {similarity:.4f}")
3. UpstageDocumentParseLoader - 문서 파싱
PDF 파싱
from langchain_upstage import UpstageDocumentParseLoader
loader = UpstageDocumentParseLoader(
file_path="document.pdf",
split="page",
use_ocr=True,
output_format="html"
)
documents = loader.load()
for doc in documents:
print(f"페이지: {doc.metadata['page_number']}")
print(f"내용: {doc.page_content[:200]}...")
이미지 파싱
image_loader = UpstageDocumentParseLoader(
file_path="image.png",
use_ocr=True
)
text_from_image = image_loader.load()
레이아웃 분석
from langchain_upstage import UpstageLayoutAnalysisLoader
layout_loader = UpstageLayoutAnalysisLoader(
file_path="complex_document.pdf",
output_type="json"
)
layout_analysis = layout_loader.load()
4. UpstageGroundednessCheck - 답변 검증
기본 사용법
from langchain_upstage import UpstageGroundednessCheck
checker = UpstageGroundednessCheck()
context = """
LangChain은 Harrison Chase가 2022년 10월에 만든
오픈소스 프레임워크입니다. LLM 애플리케이션 개발을
쉽게 만들어주는 도구입니다.
"""
answer = "LangChain은 2022년 10월에 만들어진 LLM 프레임워크입니다."
result = checker.check_groundedness(
context=context,
answer=answer
)
print(f"Grounded: {result['is_grounded']}")
print(f"Score: {result['score']}")
RAG 시스템과 통합
def verify_rag_response(question, context, answer):
"""RAG 응답의 신뢰도 검증"""
checker = UpstageGroundednessCheck()
result = checker.check_groundedness(
context=context,
answer=answer
)
if result['score'] < 0.8:
return f"⚠️ 신뢰도 낮음 ({result['score']:.2f}): {answer}"
return f"✅ 검증됨: {answer}"
사용 가능한 모델
LLM 모델
| 모델명 | 용도 | 컨텍스트 길이 | 특징 |
|---|
| solar-pro | 고성능 대화 | 4,096 | 최고 성능, 복잡한 작업 |
| solar-1-mini-chat | 경량 대화 | 4,096 | 빠른 응답, 일반 대화 |
| solar-1-mini-chat-ja | 일본어 특화 | 4,096 | 일본어 최적화 |
임베딩 모델
| 모델명 | 차원 | 컨텍스트 길이 | 용도 |
|---|
| solar-embedding-1-large | 4,096 | 4,096 | 범용 임베딩 |
| solar-embedding-1-large-query | 4,096 | 4,096 | 쿼리 특화 |
| solar-embedding-1-large-passage | 4,096 | 4,096 | 문서 특화 |
모델 선택 가이드
complex_llm = ChatUpstage(model="solar-pro")
fast_llm = ChatUpstage(model="solar-1-mini-chat")
embeddings = UpstageEmbeddings(model="solar-embedding-1-large")
query_embeddings = UpstageEmbeddings(model="solar-embedding-1-large-query")
doc_embeddings = UpstageEmbeddings(model="solar-embedding-1-large-passage")
실전 활용 예제
1. 완전한 RAG 시스템 구축
from langchain_upstage import ChatUpstage, UpstageEmbeddings
from langchain_community.vectorstores import Chroma
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
documents = [...]
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200
)
chunks = text_splitter.split_documents(documents)
embeddings = UpstageEmbeddings(model="solar-embedding-1-large")
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory="./chroma_db"
)
llm = ChatUpstage(
model="solar-pro",
temperature=0.1,
max_tokens=1000
)
template = """주어진 컨텍스트를 바탕으로 질문에 답변해주세요.
컨텍스트에 없는 내용은 모른다고 답변하세요.
컨텍스트: {context}
질문: {question}
답변:"""
prompt = PromptTemplate(
template=template,
input_variables=["context", "question"]
)
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=vectorstore.as_retriever(search_kwargs={"k": 3}),
chain_type_kwargs={"prompt": prompt}
)
question = "LangChain의 주요 기능은 무엇인가요?"
answer = qa_chain.run(question)
print(answer)
2. 대화형 챗봇 구축
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationalRetrievalChain
memory = ConversationBufferMemory(
memory_key="chat_history",
return_messages=True,
output_key="answer"
)
conversational_chain = ConversationalRetrievalChain.from_llm(
llm=llm,
retriever=vectorstore.as_retriever(),
memory=memory,
return_source_documents=True
)
chat_history = []
while True:
user_input = input("질문: ")
if user_input.lower() == 'quit':
break
result = conversational_chain({
"question": user_input,
"chat_history": chat_history
})
print(f"답변: {result['answer']}\n")
chat_history.append((user_input, result['answer']))
3. 문서 요약 파이프라인
from langchain.chains.summarize import load_summarize_chain
from langchain_upstage import UpstageDocumentParseLoader
loader = UpstageDocumentParseLoader("long_document.pdf")
docs = loader.load()
summarize_chain = load_summarize_chain(
llm=ChatUpstage(model="solar-pro"),
chain_type="map_reduce"
)
summary = summarize_chain.run(docs)
print(f"요약: {summary}")
4. 스트리밍 웹 서버 (FastAPI)
from fastapi import FastAPI, StreamingResponse
from fastapi.responses import StreamingResponse
import asyncio
app = FastAPI()
llm = ChatUpstage(model="solar-1-mini-chat")
@app.post("/chat/stream")
async def stream_chat(question: str):
async def generate():
async for chunk in llm.astream(question):
yield f"data: {chunk.content}\n\n"
return StreamingResponse(
generate(),
media_type="text/event-stream"
)
다른 LLM 제공자와 비교
성능 비교
| 제공자 | 모델 | 한국어 성능 | 속도 | 비용 | 컨텍스트 |
|---|
| Upstage | Solar-pro | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 4K |
| OpenAI | GPT-4 | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ | 8K-128K |
| Anthropic | Claude 3 | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ | 200K |
| Google | Gemini Pro | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | 32K |
코드 비교
OpenAI에서 Upstage로 마이그레이션
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
llm = ChatOpenAI(model="gpt-3.5-turbo")
embeddings = OpenAIEmbeddings()
from langchain_upstage import ChatUpstage, UpstageEmbeddings
llm = ChatUpstage(model="solar-1-mini-chat")
embeddings = UpstageEmbeddings(model="solar-embedding-1-large")
요금 정책
현재 가격 (2024년 기준)
| 서비스 | 모델 | 입력 (1M 토큰) | 출력 (1M 토큰) |
|---|
| Chat | solar-pro | $3.00 | $15.00 |
| Chat | solar-1-mini-chat | $0.50 | $1.50 |
| Embedding | solar-embedding-1-large | $0.10 | - |
| Document Parse | - | $0.01/페이지 | - |
| Groundedness Check | - | $0.05/검사 | - |
비용 최적화 팁
from langchain.cache import InMemoryCache
import langchain
langchain.llm_cache = InMemoryCache()
embeddings.embed_documents(docs)
트러블슈팅
자주 발생하는 오류와 해결법
1. API 키 오류
import os
print(os.getenv("UPSTAGE_API_KEY"))
2. Rate Limit 오류
from tenacity import retry, wait_exponential, stop_after_attempt
@retry(
wait=wait_exponential(multiplier=1, min=4, max=10),
stop=stop_after_attempt(3)
)
def call_llm(prompt):
return llm.invoke(prompt)
3. 타임아웃 오류
llm = ChatUpstage(
model="solar-pro",
request_timeout=60
)
4. 토큰 제한 초과
from langchain.text_splitter import TokenTextSplitter
splitter = TokenTextSplitter(
chunk_size=3000,
chunk_overlap=100
)
디버깅 팁
import logging
logging.basicConfig(level=logging.DEBUG)
response = llm.invoke("테스트")
print(response.response_metadata)
for chunk in llm.stream("테스트"):
print(f"Chunk: {chunk}")
print(f"Type: {type(chunk)}")
모범 사례 (Best Practices)
1. 환경별 설정 분리
import os
from enum import Enum
class Environment(Enum):
DEV = "development"
PROD = "production"
def get_llm_config(env: Environment):
if env == Environment.DEV:
return {
"model": "solar-1-mini-chat",
"temperature": 0.7,
"max_tokens": 500
}
else:
return {
"model": "solar-pro",
"temperature": 0.1,
"max_tokens": 2000
}
2. 에러 핸들링
from typing import Optional
import logging
logger = logging.getLogger(__name__)
def safe_llm_call(prompt: str) -> Optional[str]:
"""안전한 LLM 호출"""
try:
response = llm.invoke(prompt)
return response.content
except Exception as e:
logger.error(f"LLM 호출 실패: {e}")
return None
3. 성능 모니터링
import time
from functools import wraps
def monitor_performance(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
duration = time.time() - start
print(f"{func.__name__} 실행 시간: {duration:.2f}초")
return result
return wrapper
@monitor_performance
def generate_response(prompt):
return llm.invoke(prompt)
고급 활용
1. 커스텀 프롬프트 엔지니어링
from langchain.prompts import FewShotPromptTemplate, PromptTemplate
examples = [
{"input": "파이썬이 뭐야?", "output": "파이썬은 프로그래밍 언어입니다."},
{"input": "LangChain이 뭐야?", "output": "LangChain은 LLM 애플리케이션 개발 프레임워크입니다."}
]
example_prompt = PromptTemplate(
input_variables=["input", "output"],
template="입력: {input}\n출력: {output}"
)
few_shot_prompt = FewShotPromptTemplate(
examples=examples,
example_prompt=example_prompt,
prefix="다음 예제를 참고하여 답변하세요:\n",
suffix="\n입력: {input}\n출력:",
input_variables=["input"]
)
2. 멀티모달 처리
from langchain_upstage import UpstageDocumentParseLoader
def process_multimodal_document(file_path):
loader = UpstageDocumentParseLoader(
file_path=file_path,
use_ocr=True,
extract_images=True
)
docs = loader.load()
for doc in docs:
if doc.metadata.get("type") == "image":
description = llm.invoke(f"이 이미지를 설명해줘: {doc.page_content}")
else:
summary = llm.invoke(f"요약: {doc.page_content}")
return docs
3. 파인튜닝 데이터 준비
import json
def prepare_finetuning_data(qa_pairs):
"""Solar 모델 파인튜닝용 데이터 준비"""
training_data = []
for question, answer in qa_pairs:
training_data.append({
"messages": [
{"role": "user", "content": question},
{"role": "assistant", "content": answer}
]
})
with open("training_data.jsonl", "w", encoding="utf-8") as f:
for item in training_data:
f.write(json.dumps(item, ensure_ascii=False) + "\n")
return "training_data.jsonl"
참고 자료
공식 문서
튜토리얼 및 예제
커뮤니티
관련 논문
유용한 도구
부록: 빠른 참조
환경 설정 체크리스트
✅ pip install langchain-upstage
✅ export UPSTAGE_API_KEY="your-key"
✅ python -c "from langchain_upstage import ChatUpstage"
기본 코드 템플릿
from langchain_upstage import ChatUpstage, UpstageEmbeddings
from dotenv import load_dotenv
load_dotenv()
llm = ChatUpstage(model="solar-pro")
embeddings = UpstageEmbeddings(model="solar-embedding-1-large")
response = llm.invoke("Hello, Solar!")
vectors = embeddings.embed_documents(["Document"])