Evaluacija LLM aplikacija u 2026: izgradnja eval cjevovoda s DeepEval, RAGAS i Langfuseom

Praktični vodič za izgradnju LLM eval cjevovoda u 2026.: DeepEval za jedinične testove, RAGAS za RAG metrike, Langfuse za online tragove, plus CI gating pragovi i sintetički testovi.

Evaluacija LLM-ova 2026: DeepEval Vodič

Ažurirano: 14. lipnja 2026.

Evaluacija LLM aplikacija u 2026. je proces sustavnog mjerenja kvalitete izlaza jezičnih modela pomoću automatiziranih metrika, LLM-as-a-judge ocjenjivača i opservabilnosti u produkciji. Bez nje svaka izmjena prompta postaje slijepi let. U mojoj praksi tri alata pokrivaju 90% slučajeva: DeepEval za jedinične i regresijske testove, RAGAS za RAG metrike i Langfuse za online tragove i ocjene. U nastavku ću pokazati kako ih zajedno spojiti u jedan cjevovod koji izvršavate u CI-ju i koji vam šalje upozorenje kad model krene halucinirati.

  • Klasične metrike poput BLEU i ROUGE više nisu dovoljne. Produkcija u 2026. traži LLM-as-a-judge metrike (G-Eval, DAG) koje koreliraju s ljudskom prosudbom.
  • DeepEval 2.x donosi assert_test, paralelnu evaluaciju i nativnu integraciju s Pytestom, što ga čini de facto standardom za CI/CD evaluaciju.
  • RAGAS 0.2 pokriva pet ključnih RAG metrika: faithfulness, answer relevancy, context precision, context recall i noise sensitivity.
  • Langfuse 3.0 omogućuje hibridni model, gdje offline evaluacija radi na zlatnom skupu, a online ocjenjivanje na produkcijskom prometu koristi isti skup metrika.
  • Sintetička evaluacijska data postaje obvezna. RAGAS TestsetGenerator i DeepEval Synthesizer stvaraju realistične test slučajeve iz vaših dokumenata.
  • Bez gating thresholda u CI-ju, evaluacija je teatar. Postavite tvrde pragove za faithfulness ≥ 0.85 i hallucination ≤ 0.05 i odbijajte PR-ove koji ih prekrše.

Što je evaluacija LLM aplikacija i zašto je potrebna

Evaluacija LLM aplikacije je disciplina mjerenja koliko dobro generirani izlaz odgovara očekivanjima, bilo na zlatnom skupu primjera prije izlaska ili na živom prometu u produkciji. Za razliku od klasičnog softvera, gdje test ili prolazi ili pada, LLM izlaz je vjerojatnostni: isti prompt s temperaturom 0.7 daje drugačije rečenice svaki put. Zato evaluacija mora biti kontinuirana, ne jednokratna.

Iskreno, timovi koji preskaču evaluaciju u mojoj praksi upadnu u istu zamku: prompt koji "radi" na pet ručno odabranih primjera u Jupyteru pada u produkciji čim korisnik napiše nešto neočekivano. Evaluacijski cjevovod rješava tri konkretna problema:

  • Regresije pri izmjeni prompta. Mijenjate sustav prompt da popravite jedan slučaj i pokvarite tri druga. Bez automatiziranog skupa, to nikad ne vidite.
  • Drift modela. Vendor (OpenAI, Anthropic, Google) tiho nadograđuje model, npr. gpt-4o-2024-08-06 u noviji snapshot, i ponašanje se mijenja preko noći.
  • Halucinacije u RAG-u. Model ignorira dohvaćeni kontekst i izmišlja činjenice. Faithfulness metrika hvata to objektivno.

Ozbiljna evaluacija u 2026. kombinira offline mjerenje (zlatni skup u CI-ju) s online mjerenjem (uzorkovanje produkcijskih tragova i ocjenjivanje LLM-judgeom). Bez oboje, vidite samo pola slike.

Koje metrike koristiti u 2026.

Klasične referentne metrike, poput BLEU, ROUGE i METEOR, projektirane su za strojno prevođenje i sažimanje gdje postoji jedan "točan" odgovor. Za generativne LLM aplikacije slabo koreliraju s ljudskom prosudbom. Istraživanja iz 2024.–2025. (vidi rad G-Eval: NLG Evaluation using GPT-4) pokazala su da LLM-as-a-judge metrike postižu Spearmanovu korelaciju 0.5+ s ljudskim ocjenjivačima, dok BLEU jedva probija 0.2.

Današnji standardni skup metrika, prema mojem iskustvu, izgleda ovako:

MetrikaŠto mjeriTipNajbolji alat
FaithfulnessJe li odgovor podržan kontekstom (anti-halucinacija)RAGRAGAS
Answer RelevancyOdgovara li izlaz na korisničko pitanjeOpćenitaRAGAS / DeepEval
Context PrecisionJesu li dohvaćeni dokumenti relevantni i dobro rangiraniRAG retrievalRAGAS
Context RecallJe li dohvaćen sav potreban kontekstRAG retrievalRAGAS
G-EvalProizvoljan kriterij ocijenjen LLM-om s CoTOpćenitaDeepEval
HallucinationPostotak izmišljenih tvrdnjiOpćenitaDeepEval
Toxicity / BiasDetekcija štetnog ili pristranog sadržajaSigurnostDeepEval / Langfuse
Task CompletionJe li agent uspješno izvršio zadatak (tool-use)AgentiDeepEval

Za produkcijske RAG sustave uvijek mjerim sve četiri RAG metrike plus halucinaciju. Za agente s alatima dodajem Task Completion i provjeravam korake tool-callova. Za chatbotove se fokusiram na Answer Relevancy i Toxicity. Manje je više: pet metrika koje stvarno pratite vredi više od dvadeset koje nitko ne čita.

DeepEval: jedinični testovi za LLM-ove

DeepEval (paket deepeval od Confident AI) tretira LLM evaluaciju kao Pytest. Pišete LLMTestCase, kombinirate metrike i pokrećete deepeval test run. Verzija 2.x donosi paralelno izvršavanje (do 100 test slučajeva odjednom), nativne G-Eval metrike i izvoz u Confident AI Cloud za dashboard.

Instalacija i osnovni test:

pip install -U deepeval==2.4.0 openai
export OPENAI_API_KEY="sk-..."

Datoteka tests/test_summarizer.py s G-Eval kriterijem za "sažetak ne smije izostaviti ključne brojke":

import pytest
from deepeval import assert_test
from deepeval.test_case import LLMTestCase, LLMTestCaseParams
from deepeval.metrics import GEval, AnswerRelevancyMetric, HallucinationMetric

# Kriterij definiran prirodnim jezikom, sudac je GPT-4o
numerical_accuracy = GEval(
    name="Numerical Accuracy",
    criteria=(
        "Provjeri zadrzava li sazetak SVE brojcane vrijednosti "
        "iz ulaznog teksta (postotke, datume, iznose)."
    ),
    evaluation_params=[
        LLMTestCaseParams.INPUT,
        LLMTestCaseParams.ACTUAL_OUTPUT,
    ],
    threshold=0.8,
    model="gpt-4o",
)

relevancy = AnswerRelevancyMetric(threshold=0.85, model="gpt-4o-mini")
hallucination = HallucinationMetric(threshold=0.1, model="gpt-4o")

@pytest.mark.parametrize("case", load_golden_set("data/summaries.jsonl"))
def test_summary_quality(case):
    tc = LLMTestCase(
        input=case["input"],
        actual_output=run_summarizer(case["input"]),  # vasa funkcija
        context=[case["input"]],
    )
    assert_test(tc, [numerical_accuracy, relevancy, hallucination])

Pokrenete s deepeval test run tests/ -n 8 (osam paralelnih radnika). Kad neki test padne, dobivate detaljan reasoning od suca, npr. "Sažetak izostavlja porast prihoda od 24%.", što je puno korisnije od običnog "score: 0.42". Točno na tu poruku sam se prvi put oslonio kad sam shvatio da naš financijski sažetak gubi datume kvartala.

DeepEval također podržava Component-Level Evaluation, odnosno ocjenjivanje pojedinačnih koraka unutar agentičkog tijeka rada (retrieval, reranking, generacija) odvojeno. To je nezamjenjivo kada debugirate gdje u cjevovodu kvaliteta pada. Detalji su u službenoj DeepEval dokumentaciji.

RAGAS: evaluacija RAG cjevovoda

RAGAS (Retrieval-Augmented Generation Assessment) je specijaliziran za RAG metrike i jedini alat koji odvojeno mjeri kvalitetu retrievala od kvalitete generacije. To je važno. Ako odgovor ima nisku faithfulness, ali retrieval je dobar, problem je generator (prompt, model). Ako je retrieval loš, popravljate vektorsku bazu, ne prompt.

Verzija 0.2 prešla je na evaluator-pristup koji ne ovisi o LangChainu i radi izravno s vašim podacima:

pip install -U ragas==0.2.14 datasets
from ragas import evaluate, EvaluationDataset
from ragas.metrics import (
    Faithfulness, AnswerRelevancy,
    ContextPrecision, ContextRecall, NoiseSensitivity,
)
from ragas.llms import LangchainLLMWrapper
from langchain_openai import ChatOpenAI

eval_llm = LangchainLLMWrapper(ChatOpenAI(model="gpt-4o"))

dataset = EvaluationDataset.from_list([
    {
        "user_input": "Koja je kazna za neprijavljivanje GDPR povrede?",
        "retrieved_contexts": [doc1, doc2, doc3],   # iz vaseg retrievera
        "response": rag_pipeline(query),            # generirani odgovor
        "reference": "Do 10 milijuna EUR ili 2% globalnog prometa.",
    },
    # ... 50-200 slucajeva za stabilne rezultate
])

result = evaluate(
    dataset=dataset,
    metrics=[
        Faithfulness(llm=eval_llm),
        AnswerRelevancy(llm=eval_llm),
        ContextPrecision(llm=eval_llm),
        ContextRecall(llm=eval_llm),
        NoiseSensitivity(llm=eval_llm),
    ],
)

df = result.to_pandas()
print(df.mean(numeric_only=True))
# faithfulness          0.91
# answer_relevancy      0.88
# context_precision     0.76   <- ovo je problem, retrieval treba popravak
# context_recall        0.94
# noise_sensitivity     0.12

Niski context_precision uz visok context_recall znači da retriever vraća previše šuma, dohvaća sve relevantno, ali i puno nepotrebnog. To je signal za reranking (npr. Cohere Rerank 3.5 ili BGE reranker) između početnog dohvata i prompta. Dokumentaciju metrika i njihovu matematičku definiciju nađete na docs.ragas.io.

Langfuse: online evaluacija u produkciji

DeepEval i RAGAS pokrivaju offline evaluaciju na fiksnom skupu. Ali korisnici postavljaju pitanja koja niste predvidjeli, i tu dolazi Langfuse, open-source platforma za LLM opservabilnost s tracing-om, dashboard-om i online evaluacijom. U verziji 3.0 dodali su Evaluator Templates koji LLM-as-a-judge primjenjuju automatski na uzorkovane produkcijske tragove.

Instrumentacija je trivijalna. Dekorator @observe obuhvaća funkciju:

pip install -U langfuse==3.0.4 openai
export LANGFUSE_PUBLIC_KEY="pk-lf-..."
export LANGFUSE_SECRET_KEY="sk-lf-..."
export LANGFUSE_HOST="https://cloud.langfuse.com"
from langfuse import observe, get_client
from openai import OpenAI

lf = get_client()
client = OpenAI()

@observe(as_type="generation")
def answer_question(question: str, context: list[str]) -> str:
    resp = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": "Odgovori SAMO na temelju konteksta."},
            {"role": "user", "content": f"Kontekst:\n{context}\n\nPitanje: {question}"},
        ],
    )
    output = resp.choices[0].message.content
    # Dodaj korisnicki feedback kasnije preko trace_id
    lf.update_current_trace(metadata={"context_chunks": len(context)})
    return output

U Langfuse UI-ju zatim definirate Evaluator, npr. faithfulness prompt koji ocjenjuje izlaz prema kontekstu, i postavite uzorkovanje na 10% produkcijskih tragova. Rezultati se pojavljuju kao scores uz svaki trag, a dashboard prikazuje trend u vremenu. Kad faithfulness padne ispod 0.85 u zadnjih 24 sata, alert se pali. Kompletan pregled je u Langfuse dokumentaciji za scores.

Spojite to sa zaštitnim ogradama za AI agente i imate dvoslojnu obranu. Guardrails blokira loš izlaz u stvarnom vremenu, a Langfuse mjeri koliko često se to događa i šalje vam podatke za daljnju iteraciju.

Kako radi LLM-as-a-judge i kada mu vjerovati

LLM-as-a-judge je tehnika gdje moćniji model (sudac) ocjenjuje izlaz slabijeg modela (ispitanik) prema kriteriju u prirodnom jeziku. G-Eval, glavna implementacija u DeepEvalu, dodaje dva trika: Chain-of-Thought obrazloženje prije ocjene i token probability weighting umjesto jedne diskretne brojke. Rezultat je korelacija s ljudima koja konkurira ljudskim međusobnim slaganjem.

Ipak, sudac nije magija. Tri zamke koje sam vidio:

  1. Position bias. Kod parnog poređenja (A vs B), sudac sustavno preferira prvu opciju. Rješenje: pokrenite svaki par dvaput s obrnutim redoslijedom i prosječite.
  2. Self-preference. GPT-4o kao sudac preferira izlaze drugih GPT modela nad Claudeom ili Geminijem. Za benchmarking između vendora, koristite trećeg suca (npr. Claude Opus 4.7 ocjenjuje GPT vs Gemini).
  3. Granularnost. Ocjene 1–10 imaju lošu pouzdanost. Koristite binarno (prošao / nije prošao) ili 1–5 Likert s eksplicitnim sidrima za svaku ocjenu.

Suca uvijek kalibrirate. Uzmite 30–50 primjera koje ste ručno ocijenili, pustite suca na njih i provjerite slaganje. Ako Cohenov κ padne ispod 0.6, promijenite prompt suca ili koristite drugi model.

Generiranje sintetičkog test skupa

Najveći problem evaluacije nije pisati metrike, već imati dovoljno testnih slučajeva. Ručno označavanje 500 primjera je skupo. Zato i RAGAS i DeepEval imaju generatore sintetičkog skupa koji uzimaju vaše dokumente i prave realistična pitanja s ground-truth odgovorima.

from ragas.testset import TestsetGenerator
from ragas.llms import LangchainLLMWrapper
from ragas.embeddings import LangchainEmbeddingsWrapper
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.document_loaders import DirectoryLoader

generator_llm = LangchainLLMWrapper(ChatOpenAI(model="gpt-4o"))
embeddings = LangchainEmbeddingsWrapper(OpenAIEmbeddings(model="text-embedding-3-large"))

docs = DirectoryLoader("./knowledge_base").load()
generator = TestsetGenerator(llm=generator_llm, embedding_model=embeddings)

testset = generator.generate_with_langchain_docs(
    docs,
    testset_size=100,
    # Mix tipova pitanja: jednostavna, multi-hop, abstraktna
    query_distribution=[
        ("single_hop_specific", 0.5),
        ("multi_hop_specific", 0.3),
        ("multi_hop_abstract", 0.2),
    ],
)
testset.to_pandas().to_csv("eval/synthetic_testset.csv", index=False)

Bitno: sintetički skup je polaz, ne kraj. Uvijek ručno pregledajte uzorak od 20% i izbacite besmislena pitanja. Inače mjerite kako vaš RAG odgovara na pitanja koja nitko neće postaviti. Na jednom internom projektu ja sam upravo tako izbacio 18 pitanja koja su tražila izmišljene paragrafe.

CI/CD gating i regresijsko testiranje

Evaluacija koja se ne pokreće automatski je teatar. Stvarna vrijednost dolazi kad svaki PR koji mijenja prompt ili model mora proći eval suite prije mergea. Evo minimalnog GitHub Actions workflowa:

name: llm-eval
on:
  pull_request:
    paths:
      - "prompts/**"
      - "src/llm/**"

jobs:
  evaluate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: { python-version: "3.12" }
      - run: pip install -e ".[eval]"
      - name: Run DeepEval
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
        run: deepeval test run tests/eval/ -n 8 --json-report=results.json
      - name: Gate on thresholds
        run: |
          python scripts/check_thresholds.py results.json \
            --faithfulness 0.85 \
            --hallucination-max 0.05 \
            --relevancy 0.80

Skripta check_thresholds.py učitava JSON izvještaj, uspoređuje prosjeke s pragovima i izlazi kodom 1 ako bilo koja metrika padne ispod praga, što obara CI i blokira merge. Za regresijsku usporedbu (PR vs main), pohranite rezultate main grane u artefakt i upozorite ako PR uvodi pad > 3% na bilo kojoj metrici.

Česti problemi i kako ih izbjeći

Iz dosadašnjih projekata, ovo su greške koje vidim ponavljano:

  • Premali zlatni skup. 10 primjera ne mjeri ništa. Minimum je 50, realno 200–500 za stabilne rezultate s ±1% interval pouzdanosti.
  • Sudac i ispitanik isti model. GPT-4o ocjenjuje izlaze GPT-4o-mini? Bias je predvidiv. Koristite Claude ili Gemini kao neutralnog suca.
  • Statički testset zauvijek. Korisnička pitanja evoluiraju. Mjesečno uzorkujte 20 novih primjera iz produkcije, ručno označite, dodajte u zlatni skup.
  • Pratite samo prosjek. Pad prosjeka s 0.88 na 0.85 može značiti da je 15% slučajeva sada katastrofa. Pratite i 5. percentil, ne samo srednju vrijednost.
  • Ne testirate strukturirane izlaze odvojeno. Validacija sheme (Pydantic) je drugačiji test od semantičke ispravnosti, pokrijte oba.

I konačno: evaluacija ne zamjenjuje ljudski pregled. Tretirajte je kao test-driven development za LLM, gdje automatski testovi hvataju regresije, ali design i kvaliteta i dalje traže ljudsko oko jednom u tjednu.

Često postavljana pitanja

Koja je razlika između DeepEval-a i RAGAS-a?

DeepEval je opći okvir za LLM testiranje s Pytest integracijom i prilagodljivim G-Eval metrikama za bilo koji LLM zadatak. RAGAS je specijaliziran za RAG sustave i odvojeno mjeri kvalitetu retrievala (context precision, context recall) od kvalitete generacije (faithfulness, answer relevancy). U produkciji ih kombiniram, gdje DeepEval radi jedinične testove i CI gating, a RAGAS detaljnu RAG dijagnostiku.

Mogu li koristiti otvoreni model kao LLM suca umjesto GPT-4o?

Možete, ali korelacija s ljudskom prosudbom obično pada. Llama 3.3 70B i Qwen 2.5 72B su pristojni sudci za jednostavnije metrike (relevancy, format checks), ali za G-Eval i nijansirane kriterije GPT-4o ili Claude Opus 4.7 daju značajno bolje rezultate. Ako trošak nije problem, ostanite na komercijalnim modelima za suca.

Koliko često trebam pokretati evaluaciju?

Offline evaluaciju (zlatni skup, DeepEval/RAGAS) pokrenite na svakom pull requestu koji mijenja prompt, model, retriever ili chunking. Online evaluaciju (Langfuse) ostavite uključenu kontinuirano s uzorkovanjem 5–10% produkcijskog prometa. Dnevni dashboard pregled dovoljan je za detekciju drifta.

Kako mjerim performanse AI agenata s alatima?

Za agente koristite Task Completion metriku (je li krajnji zadatak izvršen) i Tool Correctness (jesu li pravi alati pozvani s pravim argumentima). DeepEval 2.x ima nativnu podršku za oboje preko ToolCorrectnessMetric. Dodatno mjerite broj koraka i ukupni latency, jer agent koji uspije u 12 koraka skuplji je od onog koji uspije u 4.

Što je dobar prag za faithfulness u RAG sustavu?

Za korporativni RAG (HR, legal, medicina) postavljam tvrdi prag faithfulness ≥ 0.90 i hallucination ≤ 0.03, jer netočan odgovor ovdje nosi pravne posljedice. Za korisničku podršku i interno znanje 0.85 / 0.05 je razuman kompromis između kvalitete i troškova suca. Ispod 0.80 sustav ne treba ići u produkciju.

Nikhil Verma
O Autoru Nikhil Verma

AI automation engineer chaining LLMs into workflows that actually work. Bullish on tool use; bearish on prompt theatre.