Tutorial LangChain: Framework Paling Populer untuk Membangun Aplikasi LLM
LangChain adalah framework open-source yang dirancang untuk mempermudah pengembangan aplikasi berbasis Large Language Model (LLM). Dengan ekosistem yang matang dan komunitas yang besar, LangChain menjadi pilihan utama developer untuk membangun chatbot, sistem RAG, AI agent, dan berbagai aplikasi AI lainnya. Tutorial ini akan membahas LangChain secara komprehensif, mulai dari instalasi hingga penggunaan lanjutan.
Mengapa LangChain?
Membangun aplikasi LLM dari nol memerlukan banyak boilerplate code: mengelola prompt, menghubungkan ke berbagai model provider, mengimplementasikan memory, mengorkestrasi chain of thought, dan masih banyak lagi. LangChain menyederhanakan semua ini dengan menyediakan abstraksi yang konsisten dan modular.
Beberapa keunggulan LangChain:
- Abstraksi Model yang Konsisten: Satu interface untuk OpenAI, Anthropic, Google, Ollama, dan puluhan provider lainnya
- Composable Chain: Membangun pipeline kompleks dengan menggabungkan komponen sederhana
- Ekosistem Lengkap: Integrasi dengan vector database, document loader, tool, dan layanan eksternal
- LangChain Expression Language (LCEL): Syntax deklaratif untuk membangun chain yang mendukung streaming dan async secara native
- Komunitas Besar: Ribuan integrasi third-party dan dokumentasi yang lengkap
Instalasi dan Setup
Instalasi Dasar
pip install langchain langchain-core langchain-community
Instalasi dengan Provider Spesifik
# Untuk OpenAI
pip install langchain-openai
Untuk Anthropic (Claude)
pip install langchain-anthropic
Untuk Google (Gemini)
pip install langchain-google-genai
Untuk model lokal via Ollama
pip install langchain-ollama
Untuk vector store
pip install langchain-chroma # ChromaDB
pip install langchain-pinecone # Pinecone
pip install faiss-cpu # FAISS
Konfigurasi API Key
import os
Set API key sebagai environment variable
os.environ["OPENAIAPIKEY"] = "sk-..."
os.environ["ANTHROPICAPIKEY"] = "sk-ant-..."
Atau gunakan file .env dengan python-dotenv
from dotenv import loaddotenv
loaddotenv()
Konsep Dasar LangChain
1. Chat Models
Chat model adalah komponen inti LangChain. Berikut cara menggunakan berbagai provider:
from langchainopenai import ChatOpenAI
from langchain
anthropic import ChatAnthropic
from langchainollama import ChatOllama
OpenAI GPT-4
llmopenai = ChatOpenAI(model="gpt-4o", temperature=0.7)
Anthropic Claude
llmclaude = ChatAnthropic(model="claude-sonnet-4-20250514", temperature=0.7)
Ollama (model lokal)
llmollama = ChatOllama(model="llama3.1")
Panggil model
response = llmopenai.invoke("Jelaskan apa itu machine learning dalam 2 kalimat")
print(response.content)
2. Prompt Templates
Prompt template memungkinkan kita membuat prompt yang dinamis dan reusable:
from langchaincore.prompts import ChatPromptTemplate, MessagesPlaceholder
Prompt sederhana
prompt = ChatPromptTemplate.frommessages([
("system", "Kamu adalah asisten AI yang ahli dalam {domain}."),
("human", "{question}")
])
Gunakan prompt
formatted = prompt.invoke({
"domain": "data science",
"question": "Apa perbedaan supervised dan unsupervised learning?"
})
print(formatted)
3. Output Parsers
Output parser membantu mengubah output LLM menjadi format terstruktur:
from langchaincore.outputparsers import JsonOutputParser, StrOutputParser
from langchain
core.pydanticv1 import BaseModel, Field
String output parser (paling sederhana)
parser = StrOutputParser()
JSON output parser dengan schema
class BookReview(BaseModel):
title: str = Field(description="Judul buku")
rating: int = Field(description="Rating 1-5")
summary: str = Field(description="Ringkasan review")
json
parser = JsonOutputParser(pydanticobject=BookReview)
prompt = ChatPromptTemplate.from
messages([
("system", "Berikan review buku dalam format JSON.\n{formatinstructions}"),
("human", "Review buku: {booktitle}")
])
chain = prompt | llmopenai | jsonparser
result = chain.invoke({
"booktitle": "Clean Code",
"formatinstructions": jsonparser.getformatinstructions()
})
print(result) # {'title': 'Clean Code', 'rating': 5, 'summary': '...'}
LangChain Expression Language (LCEL)
LCEL adalah cara modern untuk membangun chain di LangChain. Dengan operator pipe (|), kita bisa menggabungkan komponen secara deklaratif:
from langchainopenai import ChatOpenAI
from langchaincore.prompts import ChatPromptTemplate
from langchaincore.outputparsers import StrOutputParser
Definisikan chain dengan LCEL
chain = (
ChatPromptTemplate.frommessages([
("system", "Kamu adalah penerjemah profesional."),
("human", "Terjemahkan teks berikut ke {language}: {text}")
])
| ChatOpenAI(model="gpt-4o-mini")
| StrOutputParser()
)
Invoke (synchronous)
result = chain.invoke({
"language": "Jepang",
"text": "Selamat pagi, apa kabar?"
})
print(result)
Streaming
for chunk in chain.stream({
"language": "Jepang",
"text": "Selamat pagi, apa kabar?"
}):
print(chunk, end="", flush=True)
Batch processing
results = chain.batch([
{"language": "Jepang", "text": "Halo"},
{"language": "Korea", "text": "Terima kasih"},
{"language": "Mandarin", "text": "Selamat tinggal"},
])
RunnablePassthrough dan RunnableParallel
from langchaincore.runnables import RunnablePassthrough, RunnableParallel
RunnableParallel - jalankan beberapa chain secara paralel
analysis
chain = RunnableParallel(
sentiment=ChatPromptTemplate.fromtemplate(
"Analisis sentimen teks ini (positif/negatif/netral): {text}"
) | llmopenai | StrOutputParser(),
summary=ChatPromptTemplate.fromtemplate(
"Ringkas teks ini dalam 1 kalimat: {text}"
) | llmopenai | StrOutputParser(),
language=ChatPromptTemplate.fromtemplate(
"Deteksi bahasa teks ini: {text}"
) | llmopenai | StrOutputParser(),
original=RunnablePassthrough()
)
result = analysischain.invoke({
"text": "Produk ini sangat bagus, saya sangat puas dengan kualitasnya!"
})
print(result)
{
'sentiment': 'positif',
'summary': 'Pelanggan puas dengan kualitas produk.',
'language': 'Bahasa Indonesia',
'original': {'text': 'Produk ini sangat bagus...'}
}
Retrieval-Augmented Generation (RAG)
RAG adalah salah satu use case paling populer di LangChain. Berikut implementasi lengkapnya:
Setup Vector Store
from langchaincommunity.documentloaders import PyPDFLoader, TextLoader
from langchain.text
splitter import RecursiveCharacterTextSplitter
from langchainopenai import OpenAIEmbeddings
from langchainchroma import Chroma
1. Load dokumen
loader = PyPDFLoader("dokumenperusahaan.pdf")
documents = loader.load()
2. Split dokumen menjadi chunks
textsplitter = RecursiveCharacterTextSplitter(
chunksize=1000,
chunkoverlap=200,
separators=["\n\n", "\n", ".", " "]
)
chunks = textsplitter.splitdocuments(documents)
3. Buat embeddings dan simpan ke vector store
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma.fromdocuments(
documents=chunks,
embedding=embeddings,
persistdirectory="./chromadb"
)
4. Buat retriever
retriever = vectorstore.asretriever(
searchtype="similarity",
searchkwargs={"k": 5}
)
RAG Chain
from langchaincore.prompts import ChatPromptTemplate
from langchain
core.runnables import RunnablePassthrough
from langchaincore.outputparsers import StrOutputParser
Template RAG
ragprompt = ChatPromptTemplate.frommessages([
("system", """Kamu adalah asisten yang menjawab pertanyaan berdasarkan konteks yang diberikan.
Jawab HANYA berdasarkan konteks. Jika informasi tidak ada di konteks, katakan "Informasi tidak ditemukan."
Konteks:
{context}"""),
("human", "{question}")
])
def formatdocs(docs):
return "\n\n".join(doc.pagecontent for doc in docs)
RAG Chain dengan LCEL
ragchain = (
{
"context": retriever | formatdocs,
"question": RunnablePassthrough()
}
| ragprompt
| llmopenai
| StrOutputParser()
)
Tanya jawab
answer = ragchain.invoke("Berapa total revenue perusahaan tahun lalu?")
print(answer)
Memory dan Conversation History
LangChain menyediakan berbagai cara untuk mengelola conversation history:
from langchaincore.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchaincore.messages import HumanMessage, AIMessage
from langchaincommunity.chatmessagehistories import ChatMessageHistory
from langchaincore.runnables.history import RunnableWithMessageHistory
Setup prompt dengan history
prompt = ChatPromptTemplate.frommessages([
("system", "Kamu adalah asisten AI yang ramah dan membantu."),
MessagesPlaceholder(variablename="history"),
("human", "{input}")
])
chain = prompt | llmopenai | StrOutputParser()
Store untuk menyimpan history per session
store = {}
def getsessionhistory(sessionid: str):
if sessionid not in store:
store[sessionid] = ChatMessageHistory()
return store[sessionid]
Chain dengan memory
chainwithhistory = RunnableWithMessageHistory(
chain,
getsessionhistory,
inputmessageskey="input",
historymessageskey="history"
)
Percakapan multi-turn
config = {"configurable": {"sessionid": "user123"}}
response1 = chainwithhistory.invoke(
{"input": "Nama saya Budi, saya seorang data engineer"},
config=config
)
print(response1)
response2 = chainwithhistory.invoke(
{"input": "Apa nama saya dan apa pekerjaan saya?"},
config=config
)
print(response2) # Model akan mengingat nama dan pekerjaan
Tool Calling dan AI Agents
Mendefinisikan Tools
from langchaincore.tools import tool
from langchainopenai import ChatOpenAI
import requests
@tool
def getweather(city: str) -> str:
"""Mendapatkan informasi cuaca untuk kota tertentu."""
# Simulasi API call
return f"Cuaca di {city}: Cerah, 28°C, Kelembaban 65%"
@tool
def calculate(expression: str) -> str:
"""Menghitung ekspresi matematika."""
try:
result = eval(expression)
return f"Hasil: {result}"
except Exception as e:
return f"Error: {str(e)}"
@tool
def searchdatabase(query: str) -> str:
"""Mencari informasi di database perusahaan."""
# Simulasi database search
data = {
"revenue": "Total revenue Q1 2026: Rp 5.2 Miliar",
"employees": "Jumlah karyawan: 150 orang",
"products": "3 produk utama: Platform AI, Konsultasi Data, Training"
}
for key, value in data.items():
if key in query.lower():
return value
return "Data tidak ditemukan"
Bind tools ke model
llmwithtools = ChatOpenAI(model="gpt-4o").bindtools(
[getweather, calculate, searchdatabase]
)
Membuat Agent dengan LangGraph
from langgraph.prebuilt import createreactagent
Buat ReAct agent
agent = createreactagent(
model=ChatOpenAI(model="gpt-4o"),
tools=[getweather, calculate, searchdatabase]
)
Jalankan agent
result = agent.invoke({
"messages": [("human", "Berapa cuaca di Jakarta dan hitung 15% dari revenue perusahaan")]
})
for message in result["messages"]:
print(f"{message.type}: {message.content}")
Penggunaan Lanjutan
Custom Chain dengan Branching Logic
from langchaincore.runnables import RunnableBranch
Chain yang berbeda berdasarkan bahasa input
classification
chain = (
ChatPromptTemplate.fromtemplate(
"Klasifikasikan bahasa teks ini (indonesia/english/other): {text}\nJawab satu kata saja."
)
| llmopenai
| StrOutputParser()
)
indonesianchain = (
ChatPromptTemplate.fromtemplate("Ringkas teks Bahasa Indonesia ini: {text}")
| llmopenai
| StrOutputParser()
)
englishchain = (
ChatPromptTemplate.fromtemplate("Summarize this English text: {text}")
| llmopenai
| StrOutputParser()
)
branch = RunnableBranch(
(lambda x: "indonesia" in x["language"].lower(), indonesianchain),
(lambda x: "english" in x["language"].lower(), englishchain),
indonesianchain # default
)
fullchain = (
RunnableParallel(
text=RunnablePassthrough(),
language=lambda x: classificationchain.invoke(x)
)
| branch
)
Structured Output dengan Pydantic
from pydantic import BaseModel, Field
from typing import List, Optional
class CompanyAnalysis(BaseModel):
companyname: str = Field(description="Nama perusahaan")
industry: str = Field(description="Industri perusahaan")
strengths: List[str] = Field(description="Kekuatan utama")
weaknesses: List[str] = Field(description="Kelemahan utama")
recommendation: str = Field(description="Rekomendasi")
confidencescore: float = Field(description="Skor kepercayaan 0-1")
Gunakan withstructuredoutput
structuredllm = ChatOpenAI(model="gpt-4o").withstructuredoutput(CompanyAnalysis)
result = structuredllm.invoke(
"Analisis perusahaan Tesla berdasarkan kondisi pasar saat ini"
)
print(f"Perusahaan: {result.companyname}")
print(f"Industri: {result.industry}")
print(f"Kekuatan: {result.strengths}")
print(f"Skor: {result.confidencescore}")
Callback dan Observability
from langchaincore.callbacks import BaseCallbackHandler
from langchaincore.outputs import LLMResult
class CustomCallback(BaseCallbackHandler):
def onllmstart(self, serialized, prompts, kwargs):
print(f"[LLM Start] Model: {serialized.get('name', 'unknown')}")
def onllmend(self, response: LLMResult, kwargs):
tokenusage = response.llmoutput.get("tokenusage", {})
print(f"[LLM End] Tokens: {tokenusage}")
def ontoolstart(self, serialized, inputstr, kwargs):
print(f"[Tool Start] {serialized.get('name')}: {inputstr}")
def ontoolend(self, output, kwargs):
print(f"[Tool End] Output: {output}")
Gunakan callback
llm = ChatOpenAI(model="gpt-4o", callbacks=[CustomCallback()])
response = llm.invoke("Halo, apa kabar?")
Best Practices
1. Gunakan Model yang Tepat untuk Task yang Tepat
# Model kecil untuk klasifikasi sederhana
classifier = ChatOpenAI(model="gpt-4o-mini", temperature=0)
Model besar untuk reasoning kompleks
reasoner = ChatOpenAI(model="gpt-4o", temperature=0.2)
Model lokal untuk prototyping
localllm = ChatOllama(model="llama3.1")
2. Implementasikan Error Handling
from langchaincore.runnables import RunnableConfig
from tenacity import retry, stop
afterattempt, waitexponential
@retry(stop=stopafterattempt(3), wait=waitexponential(min=1, max=10))
def invokewithretry(chain, inputdata):
return chain.invoke(inputdata)
3. Optimasi Token Usage
# Gunakan tiktoken untuk menghitung token sebelum mengirim
import tiktoken
def counttokens(text: str, model: str = "gpt-4o") -> int:
encoding = tiktoken.encodingformodel(model)
return len(encoding.encode(text))
Trim context jika terlalu panjang
def trimcontext(docs, maxtokens=3000):
total = 0
trimmed = []
for doc in docs:
tokens = counttokens(doc.pagecontent)
if total + tokens > maxtokens:
break
trimmed.append(doc)
total += tokens
return trimmed
4. Gunakan Caching
from langchaincore.globals import setllmcache
from langchaincommunity.cache import InMemoryCache, SQLiteCache
In-memory cache (untuk development)
setllmcache(InMemoryCache())
SQLite cache (untuk production)
setllmcache(SQLiteCache(databasepath=".langchaincache.db"))
Sekarang response yang sama akan di-cache
llm = ChatOpenAI(model="gpt-4o")
response1 = llm.invoke("Apa itu AI?") # Hit API
response2 = llm.invoke("Apa itu AI?") # Dari cache (instant)
5. Async untuk Performa Tinggi
import asyncio
async def processbatchasync(texts: list[str]):
chain = (
ChatPromptTemplate.fromtemplate("Ringkas: {text}")
| ChatOpenAI(model="gpt-4o-mini")
| StrOutputParser()
)
tasks = [chain.ainvoke({"text": t}) for t in texts]
results = await asyncio.gather(*tasks)
return results
Jalankan
texts = ["Teks panjang 1...", "Teks panjang 2...", "Teks panjang 3..."]
results = asyncio.run(processbatchasync(texts))
Kesimpulan
LangChain adalah framework yang sangat powerful untuk membangun aplikasi berbasis LLM. Poin-poin penting yang perlu diingat:
LangChain terus berkembang dengan cepat. Pantau selalu dokumentasi resmi di python.langchain.com untuk fitur terbaru. Untuk orkestrasi agent yang lebih kompleks, pertimbangkan untuk mengeksplorasi LangGraph yang merupakan bagian dari ekosistem LangChain.