Tutorial Weave: Observabilitas dan Evaluasi Aplikasi LLM dengan Weights & Biases

# Tutorial Weave: Observabilitas dan Evaluasi Aplikasi LLM dengan Weights & Biases Membangun aplikasi berbasis Large Language Model (LLM) semakin mudah, tetapi memantau, men-debug, dan mengevaluasi k...

By Ruby Abdullah · · tutorial
WeaveLLM EvaluationObservabilityWeights & BiasesMLOps

Tutorial Weave: Observabilitas dan Evaluasi Aplikasi LLM dengan Weights & Biases

Membangun aplikasi berbasis Large Language Model (LLM) semakin mudah, tetapi memantau, men-debug, dan mengevaluasi kualitas output-nya tetap menjadi tantangan besar. Bagaimana Anda tahu apakah prompt yang baru memberikan hasil yang lebih baik? Bagaimana melacak setiap panggilan LLM di production? Di sinilah Weave dari Weights & Biases hadir sebagai solusi.

Weave adalah framework open-source untuk tracing, evaluasi, dan monitoring aplikasi LLM. Berbeda dengan W&B tradisional yang fokus pada experiment tracking untuk training model, Weave dirancang khusus untuk siklus hidup aplikasi LLM mulai dari development hingga production.

Dalam tutorial ini, kita akan mempelajari cara menggunakan Weave untuk melacak panggilan LLM, membuat evaluasi otomatis, mengelola dataset, dan memantau aplikasi LLM di production.

Instalasi dan Setup

Instalasi Weave

pip install weave openai

Weave mendukung Python 3.9+ dan terintegrasi dengan berbagai provider LLM seperti OpenAI, Anthropic, Google, Mistral, dan lainnya.

Konfigurasi API Key

Anda memerlukan akun Weights & Biases. Daftar gratis di wandb.ai, lalu dapatkan API key Anda.

export WANDBAPIKEY="your-api-key-here"

export OPENAIAPIKEY="your-openai-key-here"

Inisialisasi Project

import weave

weave.init("my-llm-project")

Setelah inisialisasi, semua operasi yang di-trace akan muncul di dashboard Weave pada platform W&B.

Basic Usage: Tracing LLM Calls

Auto-Tracing dengan Integrasi Built-in

Weave secara otomatis melacak panggilan ke provider LLM populer tanpa perlu kode tambahan.

import weave

from openai import OpenAI

weave.init("tracing-demo")

client = OpenAI()

response = client.chat.completions.create(

model="gpt-4o-mini",

messages=[

{"role": "system", "content": "Kamu adalah asisten yang membantu."},

{"role": "user", "content": "Jelaskan apa itu machine learning dalam 2 kalimat."}

]

)

print(response.choices[0].message.content)

Hanya dengan menambahkan weave.init(), setiap panggilan OpenAI secara otomatis di-trace. Anda bisa melihat input, output, latency, token usage, dan cost di dashboard Weave.

Custom Tracing dengan Decorator @weave.op

Untuk fungsi kustom Anda sendiri, gunakan decorator @weave.op:

import weave

import json

from openai import OpenAI

weave.init("custom-tracing")

client = OpenAI()

@weave.op

def extractentities(text: str) -> dict:

"""Ekstrak entitas dari teks menggunakan LLM."""

response = client.chat.completions.create(

model="gpt-4o-mini",

messages=[

{

"role": "system",

"content": "Ekstrak entitas (orang, tempat, organisasi) dari teks. Kembalikan dalam format JSON."

},

{"role": "user", "content": text}

],

responseformat={"type": "jsonobject"}

)

return json.loads(response.choices[0].message.content)

@weave.op

def processdocument(document: str) -> dict:

"""Proses dokumen: ekstrak entitas dan buat ringkasan."""

entities = extractentities(document)

return {

"entities": entities,

"entitycount": sum(len(v) for v in entities.values() if isinstance(v, list))

}

result = processdocument(

"Joko Widodo bertemu dengan Joe Biden di Jakarta untuk membahas "

"kerjasama ASEAN dan investasi di Indonesia."

)

print(json.dumps(result, indent=2, ensureascii=False))

Decorator @weave.op membuat hierarchical trace, sehingga Anda bisa melihat bagaimana processdocument memanggil extractentities, lengkap dengan input/output di setiap level.

Tracing dengan Metadata Tambahan

Anda bisa menambahkan atribut kustom ke trace untuk mempermudah filtering dan analisis:

import weave

weave.init("metadata-demo")

@weave.op

def classifysentiment(text: str, language: str = "id") -> dict:

response = client.chat.completions.create(

model="gpt-4o-mini",

messages=[

{

"role": "system",

"content": f"Klasifikasikan sentimen teks berikut dalam bahasa {'Indonesia' if language == 'id' else 'Inggris'}. Jawab dengan: positif, negatif, atau netral."

},

{"role": "user", "content": text}

]

)

return {

"text": text,

"language": language,

"sentiment": response.choices[0].message.content

}

result = classifysentiment("Produk ini sangat bagus dan berkualitas!", language="id")

print(result)

Evaluasi Otomatis dengan Weave Evaluation

Salah satu fitur terkuat Weave adalah framework evaluasi yang memungkinkan Anda mengukur kualitas output LLM secara sistematis.

Membuat Dataset Evaluasi

import weave

weave.init("evaluation-demo")

dataset = weave.Dataset(

name="sentiment-test-set",

rows=[

{"text": "Makanan di restoran ini enak sekali!", "expected": "positif"},

{"text": "Pelayanannya sangat buruk dan lambat.", "expected": "negatif"},

{"text": "Harga produk ini standar di pasaran.", "expected": "netral"},

{"text": "Saya kecewa dengan kualitas barangnya.", "expected": "negatif"},

{"text": "Tim support sangat responsif dan membantu.", "expected": "positif"},

{"text": "Pengiriman sesuai estimasi waktu.", "expected": "netral"},

{"text": "Aplikasinya sering crash dan tidak stabil.", "expected": "negatif"},

{"text": "Desain produknya modern dan elegan.", "expected": "positif"},

]

)

weave.publish(dataset)

Mendefinisikan Model untuk Evaluasi

Weave menggunakan konsep Model sebagai wrapper untuk fungsi yang ingin Anda evaluasi:

import weave

from openai import OpenAI

class SentimentClassifier(weave.Model):

modelname: str = "gpt-4o-mini"

systemprompt: str = "Klasifikasikan sentimen teks berikut. Jawab HANYA dengan satu kata: positif, negatif, atau netral."

@weave.op

def predict(self, text: str) -> dict:

client = OpenAI()

response = client.chat.completions.create(

model=self.modelname,

messages=[

{"role": "system", "content": self.systemprompt},

{"role": "user", "content": text}

]

)

result = response.choices[0].message.content.strip().lower()

return {"sentiment": result}

Membuat Scorer

Scorer adalah fungsi yang menilai kualitas output model:

@weave.op

def accuracyscorer(expected: str, modeloutput: dict) -> dict:

"""Mengecek apakah prediksi sentimen sesuai dengan expected."""

predicted = modeloutput.get("sentiment", "").strip().lower()

expectedclean = expected.strip().lower()

match = predicted == expectedclean

return {"correct": match}

@weave.op

def formatscorer(modeloutput: dict) -> dict:

"""Mengecek apakah output sesuai format yang diharapkan."""

sentiment = modeloutput.get("sentiment", "")

validsentiments = ["positif", "negatif", "netral"]

isvalid = sentiment.strip().lower() in validsentiments

return {"validformat": isvalid}

Menjalankan Evaluasi

import asyncio

async def runevaluation():

model = SentimentClassifier()

evaluation = weave.Evaluation(

dataset=dataset,

scorers=[accuracyscorer, formatscorer]

)

results = await evaluation.evaluate(model)

print(f"Accuracy: {results['accuracyscorer']['correct']['truecount']}/{len(dataset.rows)}")

print(f"Format validity: {results['formatscorer']['validformat']['truecount']}/{len(dataset.rows)}")

return results

results = asyncio.run(runevaluation())

Membandingkan Model atau Prompt

Kekuatan evaluasi Weave terletak pada kemampuan membandingkan berbagai konfigurasi:

async def comparemodels():

models = [

SentimentClassifier(

modelname="gpt-4o-mini",

systemprompt="Klasifikasikan sentimen: positif, negatif, atau netral."

),

SentimentClassifier(

modelname="gpt-4o-mini",

systemprompt="Kamu adalah ahli analisis sentimen bahasa Indonesia. Analisis teks berikut dan tentukan sentimennya. Jawab HANYA: positif, negatif, atau netral."

),

SentimentClassifier(

modelname="gpt-4o",

systemprompt="Klasifikasikan sentimen: positif, negatif, atau netral."

),

]

evaluation = weave.Evaluation(

dataset=dataset,

scorers=[accuracyscorer, formatscorer]

)

for model in models:

print(f"\nEvaluating: {model.modelname} with prompt variant...")

results = await evaluation.evaluate(model)

print(f"Results: {results}")

asyncio.run(comparemodels())

Setiap evaluasi tersimpan di dashboard Weave, memungkinkan Anda membandingkan hasil secara visual di satu tempat.

Advanced Usage

LLM-as-Judge Scorer

Untuk evaluasi yang lebih kompleks, Anda bisa menggunakan LLM sebagai judge:

@weave.op

def llmjudgescorer(text: str, modeloutput: dict) -> dict:

"""Gunakan LLM untuk menilai kualitas klasifikasi sentimen."""

client = OpenAI()

predicted = modeloutput.get("sentiment", "")

response = client.chat.completions.create(

model="gpt-4o",

messages=[

{

"role": "system",

"content": (

"Kamu adalah evaluator yang menilai apakah klasifikasi sentimen sudah tepat. "

"Nilai dari 1-5 (1=sangat salah, 5=sangat tepat). "

"Jawab HANYA dengan angka."

)

},

{

"role": "user",

"content": f"Teks: {text}\nKlasifikasi: {predicted}"

}

]

)

score = int(response.choices[0].message.content.strip())

return {"judgescore": score, "isgood": score >= 4}

Tracing RAG Pipeline

Weave sangat berguna untuk men-trace pipeline RAG yang kompleks:

import weave

import numpy as np

from openai import OpenAI

weave.init("rag-tracing")

client = OpenAI()

@weave.op

def getembedding(text: str) -> list:

"""Dapatkan embedding dari teks."""

response = client.embeddings.create(

model="text-embedding-3-small",

input=text

)

return response.data[0].embedding

@weave.op

def searchdocuments(query: str, documents: list[dict], topk: int = 3) -> list[dict]:

"""Cari dokumen yang relevan berdasarkan similarity."""

queryembedding = getembedding(query)

scoreddocs = []

for doc in documents:

docembedding = getembedding(doc["content"])

similarity = np.dot(queryembedding, docembedding) / (

np.linalg.norm(queryembedding) * np.linalg.norm(docembedding)

)

scoreddocs.append({doc, "score": float(similarity)})

scoreddocs.sort(key=lambda x: x["score"], reverse=True)

return scoreddocs[:topk]

@weave.op

def generateanswer(query: str, contextdocs: list[dict]) -> str:

"""Generate jawaban berdasarkan konteks dokumen."""

context = "\n\n".join([

f"Dokumen {i+1}: {doc['content']}"

for i, doc in enumerate(contextdocs)

])

response = client.chat.completions.create(

model="gpt-4o-mini",

messages=[

{

"role": "system",

"content": "Jawab pertanyaan berdasarkan konteks yang diberikan. Jika informasi tidak ada di konteks, katakan tidak tersedia."

},

{

"role": "user",

"content": f"Konteks:\n{context}\n\nPertanyaan: {query}"

}

]

)

return response.choices[0].message.content

@weave.op

def ragpipeline(query: str, knowledgebase: list[dict]) -> dict:

"""Pipeline RAG lengkap: retrieve lalu generate."""

relevantdocs = searchdocuments(query, knowledgebase)

answer = generateanswer(query, relevantdocs)

return {

"query": query,

"retrieveddocs": relevantdocs,

"answer": answer

}

knowledgebase = [

{"content": "Python adalah bahasa pemrograman yang dibuat oleh Guido van Rossum pada tahun 1991."},

{"content": "Machine learning adalah cabang AI yang memungkinkan komputer belajar dari data."},

{"content": "Django adalah framework web Python yang mengikuti pola MVT (Model-View-Template)."},

{"content": "FastAPI adalah framework Python modern untuk membangun API dengan performa tinggi."},

{"content": "PyTorch adalah library deep learning yang dikembangkan oleh Meta AI."},

]

result = ragpipeline("Apa itu FastAPI?", knowledgebase)

print(result["answer"])

Dengan tracing ini, Anda bisa melihat setiap langkah di pipeline RAG: embedding generation, similarity search, dan answer generation, lengkap dengan latency dan token usage di setiap langkah.

Evaluasi RAG Pipeline

ragdataset = weave.Dataset(

name="rag-test-set",

rows=[

{

"query": "Siapa pembuat Python?",

"expectedanswer": "Guido van Rossum",

"knowledgebase": knowledgebase

},

{

"query": "Apa itu FastAPI?",

"expectedanswer": "framework Python modern untuk membangun API",

"knowledgebase": knowledgebase

},

{

"query": "Framework deep learning dari Meta?",

"expectedanswer": "PyTorch",

"knowledgebase": knowledgebase

},

]

)

@weave.op

def answerrelevancescorer(expectedanswer: str, modeloutput: dict) -> dict:

"""Cek apakah jawaban mengandung informasi yang diharapkan."""

answer = modeloutput.get("answer", "").lower()

expected = expectedanswer.lower()

containsexpected = expected in answer

return {"relevant": containsexpected}

@weave.op

def retrievalscorer(modeloutput: dict) -> dict:

"""Evaluasi kualitas retrieval."""

docs = modeloutput.get("retrieveddocs", [])

avgscore = sum(d["score"] for d in docs) / len(docs) if docs else 0

return {"avgretrievalscore": round(avgscore, 4)}

class RAGModel(weave.Model):

@weave.op

def predict(self, query: str, knowledgebase: list) -> dict:

return ragpipeline(query, knowledgebase)

async def evaluaterag():

model = RAGModel()

evaluation = weave.Evaluation(

dataset=ragdataset,

scorers=[answerrelevancescorer, retrievalscorer]

)

results = await evaluation.evaluate(model)

print(f"RAG Evaluation Results: {results}")

asyncio.run(evaluaterag())

Monitoring di Production

Weave bisa diintegrasikan ke aplikasi production untuk monitoring real-time:

import weave

from fastapi import FastAPI

from pydantic import BaseModel

weave.init("production-monitoring")

app = FastAPI()

class QueryRequest(BaseModel):

question: str

class QueryResponse(BaseModel):

answer: str

sources: list[str]

@weave.op

def handlequery(question: str) -> dict:

result = ragpipeline(question, knowledgebase)

return {

"answer": result["answer"],

"sources": [d["content"][:50] for d in result["retrieveddocs"]]

}

@app.post("/query", responsemodel=QueryResponse)

async def queryendpoint(request: QueryRequest):

result = handlequery(request.question)

return QueryResponse(result)

Dengan setup ini, setiap request ke API Anda secara otomatis di-trace di Weave. Anda bisa memantau latency, error rate, token usage, dan kualitas respons secara real-time melalui dashboard.

Best Practices

1. Organisasi Project

Gunakan nama project yang deskriptif dan konsisten untuk memudahkan navigasi:

weave.init("company/product-chatbot-v2")

2. Trace Setiap Langkah Penting

Jangan hanya trace panggilan LLM. Trace juga langkah preprocessing, retrieval, dan postprocessing:

@weave.op

def preprocessquery(query: str) -> str:

query = query.strip().lower()

return query

@weave.op

def postprocessresponse(response: str) -> str:

response = response.strip()

if not response.endswith("."):

response += "."

return response

3. Versioning Model dengan weave.Model

Gunakan weave.Model untuk melacak konfigurasi model Anda:

class MyAssistant(weave.Model):

modelname: str = "gpt-4o-mini"

temperature: float = 0.7

maxtokens: int = 500

systemprompt: str = "Kamu adalah asisten yang membantu."

@weave.op

def predict(self, usermessage: str) -> str:

client = OpenAI()

response = client.chat.completions.create(

model=self.modelname,

temperature=self.temperature,

maxtokens=self.maxtokens,

messages=[

{"role": "system", "content": self.systemprompt},

{"role": "user", "content": usermessage}

]

)

return response.choices[0].message.content

Setiap kali parameter berubah, Weave akan membuat versi baru secara otomatis, sehingga Anda bisa melacak perubahan apa yang memengaruhi kualitas output.

4. Evaluasi Secara Berkala

Buat pipeline CI/CD yang menjalankan evaluasi setiap ada perubahan prompt atau konfigurasi:

async def cievaluation():

"""Jalankan evaluasi sebagai bagian dari CI/CD pipeline."""

model = SentimentClassifier()

evaluation = weave.Evaluation(

dataset=dataset,

scorers=[accuracyscorer]

)

results = await evaluation.evaluate(model)

accuracy = results["accuracyscorer"]["correct"]["truefraction"]

assert accuracy >= 0.8, f"Accuracy {accuracy} di bawah threshold 0.8"

print(f"CI evaluation passed with accuracy: {accuracy}")

5. Gunakan Multiple Scorer

Kombinasikan berbagai scorer untuk evaluasi yang komprehensif:

evaluation = weave.Evaluation(

dataset=dataset,

scorers=[

accuracyscorer,

formatscorer,

llmjudgescorer,

latencyscorer,

]

)

Integrasi dengan Provider LLM Lain

Weave mendukung berbagai provider LLM secara native:

# Anthropic

from anthropic import Anthropic

client = Anthropic()

Google Gemini

import google.generativeai as genai

model = genai.GenerativeModel("gemini-pro")

Mistral

from mistralai.client import MistralClient

client = MistralClient()

LiteLLM (multi-provider)

import litellm

response = litellm.completion(model="gpt-4o-mini", messages=[...])

Semua panggilan di atas secara otomatis di-trace oleh Weave tanpa kode tambahan.

Kesimpulan

Weave dari Weights & Biases adalah alat yang sangat berharga untuk pengembangan aplikasi LLM yang serius. Dengan fitur tracing otomatis, framework evaluasi yang fleksibel, dan kemampuan monitoring production, Weave membantu Anda membangun aplikasi LLM yang lebih andal dan berkualitas tinggi.

Poin-poin utama yang telah kita pelajari:

  • Tracing: Gunakan weave.init() untuk auto-trace dan @weave.op untuk custom tracing
  • Evaluasi: Buat dataset, definisikan scorer, dan jalankan evaluasi sistematik menggunakan weave.Evaluation
  • Model Versioning: Gunakan weave.Model untuk melacak konfigurasi dan membandingkan performa
  • Production Monitoring: Integrasikan Weave ke aplikasi production untuk monitoring real-time
  • Perbandingan: Bandingkan model, prompt, dan konfigurasi secara side-by-side di dashboard

Mulailah dengan menginstal Weave (pip install weave) dan tambahkan tracing ke proyek LLM Anda. Anda akan terkejut betapa banyak insight yang bisa Anda dapatkan tentang perilaku aplikasi LLM Anda.

Artikel Terkait

Tutorial Vertex AI Model Monitoring: Observabilitas Model Produksi

Tutorial Lengkap Vertex AI Model Monitoring: Monitoring ML Berkelanjutan Vertex AI Model Monitoring secara otomatis mend...

Tutorial AWS SageMaker Model Monitor: Monitoring Model Produksi

Tutorial Lengkap AWS SageMaker Model Monitor: Monitoring Model ML di Production Amazon SageMaker Model Monitor secara ot...

Tutorial Lengkap Weights & Biases: Experiment Tracking untuk Machine Learning

Tutorial Lengkap Weights & Biases: ML Experiment Tracking dan Visualization Weights & Biases (W&B) adalah platform MLOps...

Portkey: Satu Gateway AI buat Ngatur Semua LLM dari Banyak Provider

Portkey: Satu Gateway AI buat Ngatur Semua LLM dari Banyak Provider Temen-temen, kalau kamu udah pernah bikin aplikasi y...