Tutorial Opik: Platform Evaluasi dan Observabilitas LLM

# Tutorial Opik: Platform Evaluasi dan Observabilitas LLM Opik adalah platform open-source yang dikembangkan oleh Comet untuk evaluasi, testing, dan monitoring aplikasi berbasis Large Language Model...

By Ruby Abdullah · · tutorial
OpikLLM EvaluationObservabilityCometPython

Tutorial Opik: Platform Evaluasi dan Observabilitas LLM

Opik adalah platform open-source yang dikembangkan oleh Comet untuk evaluasi, testing, dan monitoring aplikasi berbasis Large Language Model (LLM). Dalam ekosistem AI modern, membangun aplikasi LLM saja tidak cukup. Kita perlu memastikan bahwa respons model konsisten, akurat, dan sesuai ekspektasi. Opik menyediakan toolkit lengkap untuk tracing, evaluasi otomatis, dan monitoring produksi yang membantu tim AI mengembangkan aplikasi LLM dengan percaya diri.

Tutorial ini akan membahas cara menggunakan Opik mulai dari instalasi, tracing request LLM, membuat evaluasi otomatis, hingga monitoring aplikasi di produksi. Semua contoh kode bisa langsung dijalankan di environment Python lokal Anda.

Mengapa Opik?

Saat membangun aplikasi LLM, ada beberapa tantangan utama yang sering dihadapi:

  • Debugging yang sulit: Sulit melacak mengapa model memberikan respons tertentu, terutama dalam pipeline multi-step seperti RAG
  • Evaluasi yang tidak konsisten: Mengevaluasi kualitas output LLM secara manual memakan waktu dan tidak scalable
  • Monitoring produksi: Tidak ada visibilitas terhadap performa model setelah di-deploy
  • Regression testing: Perubahan prompt atau model bisa menyebabkan degradasi yang tidak terdeteksi
  • Opik mengatasi semua tantangan ini dengan menyediakan:

    • Tracing: Mencatat setiap langkah dalam pipeline LLM secara detail
    • Evaluation: Framework evaluasi otomatis dengan metrik bawaan dan custom
    • Dataset Management: Mengelola test dataset untuk evaluasi yang reproducible
    • Monitoring Dashboard: Visualisasi real-time performa aplikasi LLM

    Instalasi

    Instalasi via pip

    pip install opik
    

    Konfigurasi Opik

    Ada dua cara menggunakan Opik: menggunakan Comet Cloud (hosted) atau self-hosted.

    Opsi 1: Comet Cloud (Recommended untuk memulai)

    opik configure
    

    Perintah ini akan meminta API key dari akun Comet Anda. Daftar gratis di comet.com jika belum punya akun.

    Opsi 2: Self-Hosted dengan Docker

    # Clone repository
    

    git clone https://github.com/comet-ml/opik.git

    cd opik

    Jalankan dengan Docker Compose

    docker compose up -d

    Setelah berjalan, Opik dashboard tersedia di http://localhost:5173.

    Konfigurasi client untuk self-hosted:

    import opik
    
    

    opik.configure(uselocal=True)

    Verifikasi Instalasi

    import opik
    
    

    client = opik.Opik()

    print("Opik connected successfully!")

    print(f"Workspace: {client.workspace}")

    Tracing: Mencatat Setiap Langkah Pipeline LLM

    Tracing adalah fitur inti Opik yang memungkinkan Anda merekam setiap langkah dalam pipeline LLM. Ini sangat berguna untuk debugging dan analisis performa.

    Basic Tracing dengan Decorator

    Cara termudah menggunakan tracing adalah dengan decorator @opik.track:

    import opik
    

    from openai import OpenAI

    client = OpenAI()

    @opik.track

    def generateresponse(prompt: str) -> str:

    response = client.chat.completions.create(

    model="gpt-4o-mini",

    messages=[{"role": "user", "content": prompt}]

    )

    return response.choices[0].message.content

    @opik.track

    def processquery(userquery: str) -> dict:

    enhancedprompt = f"Jawab pertanyaan berikut dengan jelas dan ringkas:\n{userquery}"

    response = generateresponse(enhancedprompt)

    return {

    "query": userquery,

    "response": response

    }

    result = processquery("Apa itu machine learning?")

    print(result["response"])

    Setiap pemanggilan fungsi yang di-decorate dengan @opik.track akan otomatis dicatat sebagai span dalam trace. Fungsi nested akan membentuk hierarki parent-child secara otomatis.

    Tracing dengan Metadata

    Anda bisa menambahkan metadata tambahan ke trace untuk memperkaya informasi:

    import opik
    

    from opik import opikcontext

    @opik.track

    def classifytext(text: str, categories: list) -> str:

    opikcontext.updatecurrenttrace(

    tags=["classification", "production"],

    metadata={

    "model": "gpt-4o-mini",

    "numcategories": len(categories),

    "textlength": len(text)

    }

    )

    prompt = f"""Klasifikasikan teks berikut ke salah satu kategori: {', '.join(categories)}

    Teks: {text}

    Kategori:"""

    response = client.chat.completions.create(

    model="gpt-4o-mini",

    messages=[{"role": "user", "content": prompt}]

    )

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

    opikcontext.updatecurrentspan(

    metadata={"resultcategory": result}

    )

    return result

    result = classifytext(

    "Harga saham BBCA naik 2% hari ini",

    ["finance", "technology", "sports", "politics"]

    )

    print(f"Kategori: {result}")

    Integrasi dengan OpenAI

    Opik menyediakan integrasi langsung dengan OpenAI sehingga semua API call otomatis di-trace:

    from opik.integrations.openai import trackopenai
    

    from openai import OpenAI

    client = OpenAI()

    client = trackopenai(client)

    response = client.chat.completions.create(

    model="gpt-4o-mini",

    messages=[

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

    {"role": "user", "content": "Jelaskan konsep RAG dalam 2 kalimat."}

    ]

    )

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

    Integrasi dengan LangChain

    Jika Anda menggunakan LangChain, Opik menyediakan callback handler:

    from opik.integrations.langchain import OpikTracer
    

    from langchainopenai import ChatOpenAI

    from langchaincore.prompts import ChatPromptTemplate

    opiktracer = OpikTracer()

    llm = ChatOpenAI(model="gpt-4o-mini")

    prompt = ChatPromptTemplate.frommessages([

    ("system", "Kamu adalah ahli {topic}."),

    ("user", "{question}")

    ])

    chain = prompt | llm

    response = chain.invoke(

    {"topic": "data science", "question": "Apa perbedaan supervised dan unsupervised learning?"},

    config={"callbacks": [opiktracer]}

    )

    print(response.content)

    Tracing Pipeline RAG

    Salah satu use case paling umum adalah tracing pipeline RAG (Retrieval-Augmented Generation):

    import opik
    

    from openai import OpenAI

    client = OpenAI()

    @opik.track(name="embedquery")

    def embedquery(query: str) -> list:

    response = client.embeddings.create(

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

    input=query

    )

    return response.data[0].embedding

    @opik.track(name="retrievedocuments")

    def retrievedocuments(queryembedding: list, topk: int = 3) -> list:

    documents = [

    {"id": 1, "text": "Python adalah bahasa pemrograman yang populer untuk data science.", "score": 0.92},

    {"id": 2, "text": "Machine learning adalah cabang dari artificial intelligence.", "score": 0.87},

    {"id": 3, "text": "Data preprocessing adalah langkah penting sebelum training model.", "score": 0.83},

    ]

    return documents[:topk]

    @opik.track(name="generateanswer")

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

    context = "\n".join([doc["text"] for doc in contextdocs])

    response = client.chat.completions.create(

    model="gpt-4o-mini",

    messages=[

    {"role": "system", "content": f"Jawab berdasarkan konteks berikut:\n{context}"},

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

    ]

    )

    return response.choices[0].message.content

    @opik.track(name="ragpipeline")

    def ragpipeline(query: str) -> dict:

    embedding = embedquery(query)

    documents = retrievedocuments(embedding)

    answer = generateanswer(query, documents)

    return {

    "query": query,

    "numdocsretrieved": len(documents),

    "answer": answer

    }

    result = ragpipeline("Bagaimana cara memulai belajar data science?")

    print(result["answer"])

    Di Opik dashboard, Anda akan melihat trace lengkap dengan hierarki: ragpipeline -> embedquery -> retrievedocuments -> generateanswer, lengkap dengan input/output setiap langkah.

    Evaluasi Otomatis

    Evaluasi adalah fitur yang membuat Opik sangat berguna. Anda bisa mengevaluasi output LLM secara otomatis menggunakan metrik bawaan atau custom.

    Membuat Dataset

    Pertama, buat dataset untuk evaluasi:

    import opik
    
    

    client = opik.Opik()

    dataset = client.getorcreatedataset(name="qa-evaluation-dataset")

    dataset.insert([

    {

    "input": {"question": "Apa itu Python?"},

    "expectedoutput": "Python adalah bahasa pemrograman tingkat tinggi yang populer untuk data science, web development, dan scripting."

    },

    {

    "input": {"question": "Apa kegunaan pandas?"},

    "expectedoutput": "Pandas adalah library Python untuk manipulasi dan analisis data, terutama data tabular."

    },

    {

    "input": {"question": "Jelaskan apa itu neural network."},

    "expectedoutput": "Neural network adalah model komputasi yang terinspirasi dari otak manusia, terdiri dari layer-layer neuron yang saling terhubung untuk memproses informasi."

    },

    {

    "input": {"question": "Apa perbedaan SQL dan NoSQL?"},

    "expectedoutput": "SQL menggunakan skema relasional dengan tabel terstruktur, sedangkan NoSQL menggunakan model data fleksibel seperti dokumen, key-value, atau graph."

    },

    {

    "input": {"question": "Apa itu API?"},

    "expectedoutput": "API (Application Programming Interface) adalah antarmuka yang memungkinkan dua aplikasi berkomunikasi satu sama lain."

    }

    ])

    print(f"Dataset '{dataset.name}' created with {len(dataset)} items")

    Menggunakan Metrik Bawaan

    Opik menyediakan beberapa metrik bawaan untuk evaluasi LLM:

    from opik.evaluation.metrics import Hallucination, AnswerRelevance, ContextRecall
    

    from opik.evaluation import evaluate

    @opik.track

    def qatask(inputdata: dict) -> dict:

    question = inputdata["question"]

    response = client.chat.completions.create(

    model="gpt-4o-mini",

    messages=[{"role": "user", "content": question}]

    )

    answer = response.choices[0].message.content

    return {

    "output": answer,

    "context": [f"Pertanyaan terkait: {question}"]

    }

    hallucinationmetric = Hallucination()

    relevancemetric = AnswerRelevance()

    results = evaluate(

    dataset=dataset,

    task=qatask,

    scoringmetrics=[hallucinationmetric, relevancemetric],

    experimentname="qa-evaluation-v1"

    )

    print(f"Evaluation complete!")

    print(f"Average Hallucination Score: {results.averagescores.get('hallucination', 'N/A')}")

    print(f"Average Relevance Score: {results.averagescores.get('answerrelevance', 'N/A')}")

    Membuat Custom Metric

    Anda juga bisa membuat metrik evaluasi sendiri:

    from opik.evaluation.metrics import basemetric, scoreresult
    
    

    class ResponseLengthMetric(basemetric.BaseMetric):

    def init(self, minlength: int = 50, maxlength: int = 500):

    self.name = "responselength"

    self.minlength = minlength

    self.maxlength = maxlength

    def score(self, output: str, kwargs) -> scoreresult.ScoreResult:

    length = len(output)

    if self.minlength <= length <= self.maxlength:

    scorevalue = 1.0

    reason = f"Response length ({length}) is within acceptable range [{self.minlength}, {self.maxlength}]"

    elif length < self.minlength:

    scorevalue = length / self.minlength

    reason = f"Response too short ({length} < {self.minlength})"

    else:

    scorevalue = max(0, 1 - (length - self.maxlength) / self.maxlength)

    reason = f"Response too long ({length} > {self.maxlength})"

    return scoreresult.ScoreResult(

    name=self.name,

    value=scorevalue,

    reason=reason

    )

    class KeywordPresenceMetric(basemetric.BaseMetric):

    def init(self, requiredkeywords: list):

    self.name = "keywordpresence"

    self.requiredkeywords = [kw.lower() for kw in requiredkeywords]

    def score(self, output: str, kwargs) -> scoreresult.ScoreResult:

    outputlower = output.lower()

    found = [kw for kw in self.requiredkeywords if kw in outputlower]

    scorevalue = len(found) / len(self.requiredkeywords) if self.requiredkeywords else 1.0

    return scoreresult.ScoreResult(

    name=self.name,

    value=scorevalue,

    reason=f"Found {len(found)}/{len(self.requiredkeywords)} keywords: {found}"

    )

    lengthmetric = ResponseLengthMetric(minlength=30, maxlength=300)

    keywordmetric = KeywordPresenceMetric(requiredkeywords=["python", "programming"])

    results = evaluate(

    dataset=dataset,

    task=qatask,

    scoringmetrics=[lengthmetric, keywordmetric],

    experimentname="qa-custom-metrics-v1"

    )

    Evaluasi dengan LLM-as-Judge

    Opik mendukung penggunaan LLM sebagai evaluator, yang sangat berguna untuk menilai kualitas respons secara semantik:

    from opik.evaluation.metrics import LLMJudge
    
    

    judgemetric = LLMJudge(

    name="qualityjudge",

    model="gpt-4o-mini",

    prompttemplate="""Evaluasi kualitas jawaban berikut berdasarkan pertanyaan yang diberikan.

    Pertanyaan: {input}

    Jawaban: {output}

    Jawaban yang diharapkan: {expectedoutput}

    Berikan skor 0-1 berdasarkan kriteria:

    • Akurasi: Apakah jawaban benar?
    • Kelengkapan: Apakah jawaban mencakup poin-poin penting?
    • Kejelasan: Apakah jawaban mudah dipahami?

    Skor (0-1):""",

    )

    results = evaluate(

    dataset=dataset,

    task=qatask,

    scoringmetrics=[judgemetric],

    experimentname="qa-llm-judge-v1"

    )

    Membandingkan Eksperimen

    Salah satu kekuatan Opik adalah kemampuan membandingkan hasil antar eksperimen:

    @opik.track
    

    def qataskdetailed(inputdata: dict) -> dict:

    question = inputdata["question"]

    response = client.chat.completions.create(

    model="gpt-4o-mini",

    messages=[

    {"role": "system", "content": "Jawab dengan detail dan berikan contoh jika memungkinkan. Gunakan bahasa yang mudah dipahami."},

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

    ],

    temperature=0.3

    )

    return {"output": response.choices[0].message.content}

    resultsv2 = evaluate(

    dataset=dataset,

    task=qataskdetailed,

    scoringmetrics=[hallucinationmetric, relevancemetric, lengthmetric],

    experimentname="qa-evaluation-v2-detailed"

    )

    Di Opik dashboard, Anda bisa membandingkan qa-evaluation-v1 dan qa-evaluation-v2-detailed secara side-by-side untuk melihat dampak perubahan prompt.

    Monitoring Produksi

    Opik juga bisa digunakan untuk monitoring aplikasi LLM di produksi.

    Logging Feedback dari User

    import opik
    
    

    client = opik.Opik()

    @opik.track(name="productionquery", projectname="my-llm-app-production")

    def handleuserquery(query: str, userid: str) -> str:

    from opik import opikcontext

    opikcontext.updatecurrenttrace(

    tags=["production"],

    metadata={

    "userid": userid,

    "environment": "production"

    }

    )

    response = openaiclient.chat.completions.create(

    model="gpt-4o-mini",

    messages=[{"role": "user", "content": query}]

    )

    answer = response.choices[0].message.content

    traceid = opikcontext.getcurrenttracedata().id

    return answer, traceid

    def submitfeedback(traceid: str, score: float, reason: str = ""):

    client.logtracesfeedback(

    traceids=[traceid],

    scores=[score],

    reasons=[reason],

    name="usersatisfaction"

    )

    answer, traceid = handleuserquery(

    query="Bagaimana cara menggunakan Docker?",

    userid="user123"

    )

    submitfeedback(

    traceid=traceid,

    score=0.9,

    reason="Jawaban lengkap dan mudah dipahami"

    )

    Online Scoring Rules

    Anda bisa mengatur scoring rules yang berjalan otomatis untuk setiap trace di produksi:

    client.createonlinescoringrule(
    

    projectname="my-llm-app-production",

    name="auto-hallucination-check",

    metric=Hallucination(),

    samplingrate=0.1

    )

    Ini akan otomatis mengevaluasi 10% dari semua trace di produksi menggunakan metrik hallucination.

    Prompt Management

    Opik juga menyediakan fitur prompt management untuk versioning dan tracking prompt:

    import opik
    
    

    client = opik.Opik()

    prompt = client.createprompt(

    name="qa-system-prompt",

    prompt="Kamu adalah asisten AI yang membantu menjawab pertanyaan tentang {topic}. "

    "Jawab dengan jelas, akurat, dan ringkas. "

    "Jika tidak tahu jawabannya, katakan dengan jujur."

    )

    print(f"Prompt version: {prompt.commit}")

    retrievedprompt = client.getprompt(name="qa-system-prompt")

    formatted = retrievedprompt.format(topic="machine learning")

    print(formatted)

    Versioning Prompt

    promptv2 = client.createprompt(
    

    name="qa-system-prompt",

    prompt="Kamu adalah asisten AI ahli di bidang {topic}. "

    "Berikan jawaban yang terstruktur dengan poin-poin jika diperlukan. "

    "Sertakan contoh praktis jika memungkinkan. "

    "Jika tidak tahu jawabannya, arahkan user ke sumber yang relevan."

    )

    print(f"Updated prompt version: {promptv2.commit}")

    history = client.getpromptversions(name="qa-system-prompt")

    for version in history:

    print(f"Version {version.commit}: created at {version.createdat}")

    Best Practices

    1. Struktur Tracing yang Baik

    Beri nama yang deskriptif pada setiap trace dan span:

    @opik.track(name="customersupportpipeline")
    

    def handlesupportticket(ticket: dict):

    intent = classifyintent(ticket["message"])

    context = retrieveknowledge(intent, ticket["message"])

    response = generateresponse(ticket["message"], context)

    return response

    2. Gunakan Tags untuk Filtering

    @opik.track
    

    def processrequest(request: dict):

    from opik import opikcontext

    opikcontext.updatecurrenttrace(

    tags=[

    f"model:{request.get('model', 'default')}",

    f"env:{request.get('environment', 'dev')}",

    f"priority:{request.get('priority', 'normal')}"

    ]

    )

    3. Evaluasi Secara Berkala

    Jalankan evaluasi secara berkala, terutama saat:

    • Mengubah prompt atau system message
    • Upgrade versi model
    • Menambahkan data baru ke knowledge base
    • Sebelum dan sesudah deploy perubahan

    4. Pisahkan Project per Environment

    @opik.track(projectname="my-app-development")
    

    def devpipeline(query: str):

    pass

    @opik.track(projectname="my-app-staging")

    def stagingpipeline(query: str):

    pass

    @opik.track(projectname="my-app-production")

    def prodpipeline(query: str):

    pass

    5. Simpan Hasil Evaluasi sebagai Baseline

    Setiap kali mendapatkan hasil evaluasi yang baik, simpan sebagai baseline:

    results = evaluate(
    

    dataset=dataset,

    task=qatask,

    scoringmetrics=[hallucinationmetric, relevancemetric],

    experimentname=f"baseline-v1-{datetime.now().strftime('%Y%m%d')}"

    )

    Integrasi dengan Framework Lain

    Selain OpenAI dan LangChain, Opik juga mendukung integrasi dengan:

    • LlamaIndex: from opik.integrations.llamaindex import LlamaIndexCallbackHandler
    • Anthropic: from opik.integrations.anthropic import trackanthropic
    • Google Gemini: from opik.integrations.gemini import trackgemini
    • Ollama: Melalui integrasi OpenAI-compatible
    • LiteLLM: from opik.integrations.litellm import tracklitellm
    • Haystack: from opik.integrations.haystack import OpikConnector
    • CrewAI: from opik.integrations.crewai import trackcrewai

    Contoh integrasi dengan LlamaIndex:

    from opik.integrations.llamaindex import LlamaIndexCallbackHandler
    

    from llamaindex.core import Settings, VectorStoreIndex, SimpleDirectoryReader

    from llamaindex.core.callbacks import CallbackManager

    opikhandler = LlamaIndexCallbackHandler()

    Settings.callbackmanager = CallbackManager([opikhandler])

    documents = SimpleDirectoryReader("./data").loaddata()

    index = VectorStoreIndex.fromdocuments(documents)

    queryengine = index.asqueryengine()

    response = queryengine.query("Apa itu vector database?")

    print(response)

    Kesimpulan

    Opik menyediakan toolkit lengkap untuk mengelola lifecycle aplikasi LLM dari development hingga produksi. Dengan fitur tracing, Anda bisa mendapatkan visibilitas penuh ke dalam pipeline LLM. Fitur evaluasi memungkinkan testing otomatis yang konsisten dan reproducible. Dan fitur monitoring memastikan aplikasi tetap berjalan sesuai harapan di produksi.

    Keunggulan utama Opik dibandingkan tools serupa adalah sifatnya yang open-source, mudah di-setup (bisa self-hosted atau cloud), dan memiliki integrasi yang luas dengan berbagai framework AI populer. Untuk tim yang serius membangun aplikasi LLM production-grade, Opik adalah pilihan yang layak dipertimbangkan sebagai bagian dari stack observabilitas AI Anda.

    Langkah selanjutnya yang disarankan:

    • Eksplorasi Opik dashboard untuk visualisasi trace dan evaluasi
    • Implementasikan tracing di pipeline LLM yang sudah ada
    • Buat dataset evaluasi dari data produksi nyata
    • Setup monitoring rules untuk deteksi dini masalah kualitas

    Artikel Terkait

    Panduan Lengkap TruLens: Evaluasi dan Observabilitas Aplikasi LLM

    Panduan Lengkap TruLens: Evaluasi dan Observabilitas Aplikasi LLM Penulis: Ruby Abdullah - PT RUBYTHALIB DATA KONSULTA D...

    Tutorial Logfire: Platform Observability untuk Aplikasi Python dan AI

    Tutorial Logfire: Platform Observability untuk Aplikasi Python dan AI Logfire adalah platform observability buatan tim P...

    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...

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

    Tutorial Weave: Observabilitas dan Evaluasi Aplikasi LLM dengan Weights & Biases Membangun aplikasi berbasis Large Langu...