</> LLMOps / GenAI Production

0 / 16 section completed
Section 00

LLMOps / GenAI Production OpenAI MLflow

A kurzus a production GenAI és RAG alkalmazások üzemeltetésének teljes életciklusát fedi le. Megtanulod, hogyan kezeld a promptokat kódként (version control, A/B testing, rollback), hogyan készíts eval datasetet a minőség mérésére, hogyan detektáld a hallucinációt, hogyan monitorozd a válaszidőt, és hogyan építs guardrails rendszert a biztonság érdekében.

A kurzus során a WebShop Pro fiktív webáruház ügyfélszolgálati chatbotját építjük fel production-ready szintre. Ez a gyakorlati projekt végigkíséri az összes fogalmat: a prompt tervezéstől a skálázásig.

Előfeltételek: Python alapismeretek, REST API fogalmak, alapvető ML ismeretek. Az AIOps & MLOps kurzus elvégzése ajánlott, de nem kötelező.

Tartalom

Prompt management, evaluation, A/B testing, monitoring, guardrails, deployment, scaling

Projekt

Production-ready RAG chatbot a WebShop Pro ügyfélszolgálatához

Szójegyzék

RAG · Guardrails · Hallucination

Section 01

LLMOps fogalmak

Az LLMOps az MLOps kiterjesztése nagy nyelvi modellek (LLM) specifikus kihívásaira. Míg a hagyományos MLOps a modell tanítására és deploymentjére fókuszál, az LLMOps olyan új problémákat is kezel, mint a prompt management, a kontextus optimalizálás, a hallucináció ellenőrzés és a token-alapú költségkezelés.

Miért más az LLM-ek üzemeltetése? A hagyományos ML modellekkel ellentétben az LLM-eket ritkán tanítjuk újra — ehelyett a prompt engineerings, a RAG pipeline és a guardrails képezik a minőség alapját. A modellek fekete dobozok, ezért az eval és a monitoring sokkal kritikusabb szerepet kap. A válaszidő, a token-költség és a biztonság egyensúlyozása folyamatos feladat.

Termelési környezetben egy LLM alkalmazás sikeressége nem a modell képességein múlik, hanem azon, hogyan kezeljük a promptokat, hogyan mérjük a minőséget, hogyan védjük a rendszert a visszaélésektől, és hogyan biztosítjuk a megbízható működést.

FogalomLeírás
Prompt EngineeringSystem/user prompt tervezés és tesztelés
RAGRetrieval-Augmented Generation
Eval DatasetTesztadat a minőség mérésére
GuardrailsBiztonsági szűrők és korlátok
HallucinationAI által generált hamis információ
LatencyVálaszidő monitorozás
[1]
# LLMOps stack overview
stack = {
    'LLM': 'OpenAI GPT-4o',
    'Embedding': 'text-embedding-3-small',
    'Vector DB': 'ChromaDB',
    'Framework': 'LangChain',
    'Tracking': 'MLflow',
    'Serving': 'FastAPI',
    'Monitoring': 'Prometheus + Grafana'
}
for k, v in stack.items():
    print(f'{k:12s}: {v}')
Output:
LLM         : OpenAI GPT-4o
Embedding    : text-embedding-3-small
Vector DB    : ChromaDB
Framework    : LangChain
Tracking     : MLflow
Serving      : FastAPI
Monitoring   : Prometheus + Grafana
Section 02

Prompt versioning

A prompt versioning a promptok forráskódként való kezelését jelenti: minden prompt módosítás naplózott, verziózott és visszavonható, pontosan úgy, mint a szoftveres kód. Ez magában foglalja a version controlt, az A/B testinget és a rollback lehetőségét.

Miért kritikus? Egy LLM alkalmazásban a system prompt a viselkedés legfontosabb meghatározója. Ha megváltoztatod a promptot, a válaszok minősége drámaian megváltozhat — akár jobbra, akár rosszabbra. Verziózás nélkül lehetetlen visszanyomozni, melyik prompt változat milyen eredményt hozott, és nincs lehetőség a visszaállításra sem.

A folyamat: A kódban három prompt verziót naplózunk MLflow-ba: v1 (generikus), v2 (kontextus-specifikus) és v3 (guardrails-szel kiegészített). Minden verzió egy MLflow run-ként van rögzítve, így a teljes history nyomon követhető, és bármelyik verzió aktiválható.

Tip: Használj strukturált prompt tárolást (pl. YAML fájlok vagy adatbázis), és a prompt változtatásokat mindig párosítsd eval futtatással, hogy a hatás azonnal mérhető legyen.

[2]
import mlflow

mlflow.set_experiment('/webshop/chatbot-prompts')

prompts = {
    'v1': 'You are a helpful customer service agent.',
    'v2': 'You are a helpful customer service agent for WebShop Pro. Always be polite and concise.',
    'v3': 'You are a WebShop Pro agent. Answer only about orders, products, returns. If unsure, say so.'
}

for version, prompt in prompts.items():
    with mlflow.start_run(run_name=f'prompt-{version}'):
        mlflow.log_param('prompt', prompt)
        mlflow.log_param('version', version)
        mlflow.set_tag('type', 'system_prompt')
Output:
Logged 3 prompt versions
v1: generic, v2: with context, v3: with guardrails
Section 03

Evaluation dataset

Az evaluation dataset (eval dataset) egy kézzel összeállított tesztadat-halmaz, amely kérdés-válasz párokat és az elvárt válaszokat tartalmazza. Ez a kiindulópontja minden LLM minőségmérésnek: a modell válaszait ehhez az aranystandardhoz hasonlítjuk.

Miért szükséges? Az LLM-ek outputja nem determinisztikus — ugyanarra a kérdésre is különböző válaszokat adhatnak. Eval dataset nélkül csak szubjektív ítéletre vagyunk utalva, ami nem skálázható és nem reprodukálható. Az eval dataset objektív, mérhető alapot ad a minőség nyomon követéséhez.

A folyamat: A kódban 5 kategóriát fedünk le: policy (visszaküldési szabályzat), order_status (rendelés státusz), product (termékinformáció), guardrail (hatókörön kívüli kérdés) és account (fiókkezelés). Minden minta tartalmazza a kérdést, az elvárt választ és a kategóriát. Ezt a datasetet a későbbi eval és regression tesztek fogják használni.

Tip: Az eval datasetet folyamatosan bővítsd: minden éles hibát (amikor a chatbot rosszul válaszolt) adj hozzá tesztesetként. Így a dataset egyre jobban lefedi a valós edge case-eket. Célozz meg legalább 50-100 mintát kategóriánként.

[3]
eval_dataset = [
    {'question': 'What is the return policy?', 'expected': 'Returns within 30 days', 'category': 'policy'},
    {'question': 'Where is my order #12345?', 'expected': 'Order status lookup', 'category': 'order_status'},
    {'question': 'Do you sell laptops?', 'expected': 'Yes, Laptop Pro 16', 'category': 'product'},
    {'question': 'What is the weather?', 'expected': 'OUT_OF_SCOPE', 'category': 'guardrail'},
    {'question': 'How to reset password?', 'expected': 'Account settings', 'category': 'account'},
]

import json
with open('eval/qa_dataset.json', 'w') as f:
    json.dump(eval_dataset, f, indent=2)
print(f'Eval dataset: {len(eval_dataset)} samples')
Output:
Eval dataset: 5 samples across 5 categories
Saved to eval/qa_dataset.json
Section 04

Hallucination detection

A hallucináció akkor fordul elő, amikor az AI magabiztosan olyan információt generál, ami nem fedi le a valóságot vagy nem található meg a megadott kontextusban. Ez az LLM-ek egyik legkomolyabb kockázata: a válasz hihetőnek hangzik, de téves. A detektálás és prevenció kulcsfontosságú minden production GenAI rendszerben.

Miért veszélyes? Egy ügyfélszolgálati chatbotban a hallucináció közvetlen üzleti kárt okozhat: ha a chatbot 90 napos visszaküldési határidőt mond 30 nap helyett, az ügyfél jogosan fog panaszt tenni. A hallucináció rontja a felhasználói bizalmat és jogi kockázatot is jelenthet.

A folyamat: A kódban egy LLM-alapú hallucináció ellenőrzőt implementálunk: a kontextust, a kérdést és a választ beadja egy másik LLM-nek, amely eldönti, hogy a válasz teljes mértékben alátámasztott-e a kontextus által. A példában a válasz „90 days"-t mond, de a kontextus „30 days"-t ír — a detektor ezt helyesen azonosítja.

Tip: Több rétegű védelem alkalmazz: (1) RAG-val korlátozd a kontextust, (2) hallucináció detektorral ellenőrizd a választ, (3) guardrails-szel szűrd a kimenetet, és (4) használd a temperature=0 beállítást a determinisztikusabb válaszok érdekében.

[4]
import openai

def check_hallucination(question, answer, context):
    'Check if answer is grounded in context'
    prompt = f"""
    Context: {context}
    Question: {question}
    Answer: {answer}
    
    Is the answer fully supported by the context? Answer YES or NO.
    """
    response = openai.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{'role': 'user', 'content': prompt}],
        temperature=0
    )
    return response.choices[0].message.content.strip()

result = check_hallucination(
    'What is the return policy?',
    'You can return within 90 days for free.',  # Hallucination!
    'Return policy: 30 days, shipping fee applies.'
)
print(f'Hallucination check: {result}')
Output:
Hallucination check: NO
Reason: Answer claims 90 days but context says 30 days
Section 05

RAG pipeline production

A production RAG pipeline a Retrieval-Augmented Generation ipari szabványa: a felhasználói kérdésre először releváns dokumentumokat keresünk vissza (retrieval), majd azokat kontextusként beadva generáljuk a választ (generation). A fejlett RAG rendszerek rerankingot (eredmények újrasorrendezése relevancia szerint), forráshivatkozást (citation) és kontextus-ablak optimalizációt is alkalmaznak.

Miért jobb, mint a sima LLM? Egy alap LLM csak a tanító adatait „tudja" — nem ismeri a cég termékeit, árait, szabályzatait. A RAG a válaszadást a tényleges dokumentumokra alapozza, ami drasztikusan csökkenti a hallucinációt és naprakész információt biztosít a dokumentumtár frissítésével.

A folyamat: A kódban a LangChain keretrendszert használjuk: ChromaDB vektor adatbázisból visszakeressük a top-5 releváns dokumentumot, majd a ChatPromptTemplate segítségével a kontextust és a kérdést egy structúrátlan promptba foglaljuk. Az LLM a kontextusra hivatkozva válaszol, és forrásokat is megjelöl.

Tip: Productionben használj top-k értéket 3-5 között (túl sok kontextus rontja a minőséget és növeli a költséget), alkalmazz reranking modellt (pl. Cohere Rerank), és a chunking stratégiát optimalizáld a dokumentumtípusnak megfelelően.

[5]
from langchain_openai import ChatOpenAI
from langchain_chroma import Chroma
from langchain_core.prompts import ChatPromptTemplate

# RAG pipeline
llm = ChatOpenAI(model='gpt-4o', temperature=0)
retriever = Chroma(persist_directory='chroma_db').as_retriever(k=5)

prompt = ChatPromptTemplate.from_messages([
    ('system', 'Answer based on context. If unsure, say so. Cite sources.'),
    ('user', 'Context: {context}\n\nQuestion: {question}')
])

def rag_query(question):
    docs = retriever.invoke(question)
    context = '\n'.join(d.page_content for d in docs)
    chain = prompt | llm
    return chain.invoke({'context': context, 'question': question})

response = rag_query('What is the return policy?')
print(response.content)
Output:
Based on the return policy document:
- Returns accepted within 30 days of purchase
- Shipping fee of $5.99 applies
- Items must be in original packaging

Source: returns_policy.pdf
Section 06

Latency monitoring

A latency monitoring a válaszidő folyamatos mérését és riasztását jelenti. Production LLM rendszereknél a válaszidő kritikus UX-tényező: ha a chatbot 10 másodpercig gondolkodik, a felhasználók frusztrálódnak és elhagyják a beszélgetést. A Prometheus és Grafana kombinációval valós idejű metrikákat és alerteket építhetünk.

Mértékegységek: A legfontosabb mutatók: p50 (medián), p95 (95. percentilis) és p99 válaszidő, a kérelmek száma percenként (requests/min), és a hibaarány (error rate). A p95/p99 különösen fontos, mert a „legrosszabb eseteket" mutatja — ha ez túl magas, a felhasználói élmény romlik.

A folyamat: A kódban Prometheus Histogram metrikát használunk a kérés-időtartam mérésére, Counter metrikát a kérések és hibák számolására. A @request_duration.time() dekorátor automatikusan méri a függvény végrehajtási idejét. A hibakezelés (try/except) biztosítja, hogy a hibák is naplózásra kerüljenek.

Tip: Állíts be alerteket: ha a p95 válaszidő meghaladja az 5 másodpercet, vagy a hibaarány meghaladja az 1%-ot, automatikus riasztás küldése. Érdemes SLA-t (Service Level Agreement) definiálni: pl. „p95 < 3s, availability > 99.5%".

[6]
import time
import prometheus_client as prom

# Metrics
request_duration = prom.Histogram('llm_request_duration_seconds', 'LLM request duration')
request_total = prom.Counter('llm_requests_total', 'Total LLM requests')
error_total = prom.Counter('llm_errors_total', 'Total LLM errors')

@request_duration.time()
def chat_with_monitoring(question):
    request_total.inc()
    try:
        start = time.time()
        response = rag_query(question)
        latency = time.time() - start
        print(f'Latency: {latency:.2f}s')
        return response
    except Exception as e:
        error_total.inc()
        raise
Output:
Latency: 1.23s (p50: 1.1s, p95: 2.5s, p99: 4.1s)
Requests: 1500/min
Errors: 0.2%
Section 07

Guardrails és safety

A guardrails (biztonsági korlátok) olyan szűrők, amelyek garantálják, hogy az AI ne adjon ki káros, nemkívánatos vagy jogilag problematikus választ. Három fő területet fednek le: toxicitás (sértő, agresszív tartalom szűrése), PII szivárgás (személyes adatok, email címek, telefonszámok védelme) és topic restriction (a chatbot csak a meghatározott témákban válaszoljon).

Miért kritikus? Egy ügyfélszolgálati chatbot a cég arca. Ha trágár választ ad, kiszivárogtat személyes adatokat, vagy politikai kérdésekre válaszol, az márkakárosodást és jogi következményeket vonhat maga után. A guardrails a utolsó védelmi vonal a generáció után.

A folyamat: A kódban a Guardrails AI könyvtárat használjuk: ToxicLanguage szűri a mérgező tartalmat, PIIFilter védi a személyes adatokat, NoOffTopic pedig biztosítja, hogy a chatbot csak a megengedett témákban (rendelések, termékek, visszaküldés, szállítás) válaszoljon. A szűrés mind a bemeneten (input), mind a kimeneten (output) megtörténik.

Tip: A guardrails thresholdokat a kockázati profilhoz igazítsd: egészségügyi chatbotnál szigorúbb, belső FAQ botnál lazább. Teszteld a guardrails-t szándékosan káros inputokkal (red teaming), hogy megbizonyosodj a hatékonyságáról.

[7]
from guardrails import Guard
from guardrails.hub import ToxicLanguage, PIIFilter, NoOffTopic

guard = Guard().use_many(
    ToxicLanguage(threshold=0.8, validation_method='sentence'),
    PIIFilter(pii_entities=['EMAIL', 'PHONE', 'SSN']),
    NoOffTopic(
        valid_topics=['orders', 'products', 'returns', 'shipping'],
        model='gpt-4o-mini'
    )
)

def safe_chat(question):
    # Check input
    guard.validate(question)
    # Generate response
    answer = rag_query(question)
    # Check output
    guard.validate(answer.content)
    return answer
Output:
Guardrails active:
- ToxicLanguage: threshold 0.8
- PIIFilter: EMAIL, PHONE, SSN
- NoOffTopic: orders, products, returns, shipping

All checks passed!
Section 08

A/B testing prompts

Az A/B testing két prompt verzió párhuzamos futtatását jelenti valós felhasználói kéréseken, hogy adatvezérelt döntést hozhassunk arról, melyik prompt teljesít jobban. A forgalom véletlenszerűen oszlik meg az A és B variáns között, és a teljesítményt objektív metrikákkal (latencia, válaszhossz, elégedettség) mérjük.

Miért jobb, mint a tesztelés? Belső teszteléssel sosem fedezhető fel, hogy a valós felhasználók hogyan reagálnak az új promptról. Az A/B tesztelés biztosítja, hogy a döntés nem vélemyényen, hanem mérhető adatokon alapul. Különösen fontos, ha a prompt módosításának nem egyértelmű a hatása.

A folyamat: A kódban minden bejövő kérésnél véletlenszerűen választunk az A vagy B prompt variáns között. Minden kérésnél MLflow-ba naplózzuk a latenciát és a válasz hosszát, variáns szerint bontva. Elegendő adat (pl. 1000 kérés/variáns) összegyűlése után statisztikailag összehasonlíthatók a variánsok.

Tip: Ne egyszerre több dolgot tesztelj (csak egy változtatás A/B tesztenként). Definiálj előre egy „győztes" kritériumot (pl. elégedettség +5% és latencia növekedés <10%), és ne a teszt eredménye alapján döntsd el, mi a sikeres — az ad hoc döntés torzítja az eredményt.

[8]
import random
import mlflow

prompt_a = 'You are a helpful agent. Be concise.'
prompt_b = 'You are a WebShop Pro expert. Answer with bullet points.'

def ab_test_chat(question):
    variant = random.choice(['A', 'B'])
    prompt = prompt_a if variant == 'A' else prompt_b
    
    start = time.time()
    response = call_llm(prompt, question)
    latency = time.time() - start
    
    mlflow.log_metrics({
        f'latency_{variant}': latency,
        f'response_length_{variant}': len(response),
    })
    return response, variant

# After 1000 requests:
# Variant A: avg latency 1.1s, avg length 85 chars
# Variant B: avg latency 1.3s, avg length 120 chars, 15% better satisfaction
Output:
A/B Test Results (1000 requests each):
Variant A: latency=1.1s, satisfaction=72%
Variant B: latency=1.3s, satisfaction=87%
Winner: Variant B (+15% satisfaction)
Section 09

Fallback model strategy

A fallback model stratégia biztosítja a szolgáltatás folytonosságát, ha a primer LLM nem elérhető vagy túl lassú. A modellek láncba vannak szervezve: ha az első (legtöbbet tudó, de legdrágább) modell timeout-ot vagy API hibát ad, automatikusan a következő (gyorsabb, olcsóbb) modell próbálkozik.

Miért szükséges? Az LLM API-k nem 100%-ban megbízhatóak: rate limit, szerver leállás, hálózati problémák bármikor előfordulhatnak. Fallback nélkül a teljes chatbot leáll, ami üzleti szempontból elfogadhatatlan. A fallback stratégia biztosítja, hogy a felhasználók mindig kapjanak valamilyen választ.

A folyamat: A kódban három modell van sorba rendezve: gpt-4o (legjobb minőség, 3s limit), gpt-4o-mini (jó minőség, 2s limit), gpt-3.5-turbo (alapvető, 1s limit). A chat_with_fallback függvény végigmegy a listán, és az első sikeresen válaszoló modellt használja. Ha minden modell elbukik, egy előre definiált hibaüzenetet ad vissza.

Tip: A fallback modellek válaszait külön naplózd (MLflow-ban), és heti szinten elemezd, milyen gyakran aktiválódik a fallback. Ha túl gyakran, az arra utal, hogy a primer modell SLA-ját javítani kell.

[9]
models = [
    {'name': 'gpt-4o', 'max_latency': 3.0, 'max_cost': 0.03},
    {'name': 'gpt-4o-mini', 'max_latency': 2.0, 'max_cost': 0.005},
    {'name': 'gpt-3.5-turbo', 'max_latency': 1.0, 'max_cost': 0.001},
]

def chat_with_fallback(question, context):
    for model in models:
        try:
            response = call_llm(model['name'], question, context, timeout=model['max_latency'])
            return {'response': response, 'model': model['name']}
        except (Timeout, RateLimit, APIError):
            print(f'{model["name"]} failed, trying fallback...')
    return {'response': 'Sorry, all models are busy. Please try again.', 'model': 'fallback'}
Output:
gpt-4o: timeout after 3.0s
gpt-4o-mini: success (1.2s)
Using fallback model: gpt-4o-mini
Section 10

Streaming responses

A streaming responses (token-by-token streamelés) technika lényege, hogy a szerver nem várja meg, amíg a teljes válasz elkészül, hanem azonnal, tokenenként küldi az adatot a kliensnek. Ez drasztikusan javítja a felhasználói élményt: a felhasználó az első token megjelenésétől (Time To First Byte, TTFB) kezdve látja a válasz épülését.

Miért fontos? Egy tipikus LLM válasz 1-5 másodperc alatt generálódik teljes egészében. Ha a felhasználó ennyi ideig egy üres képernyőt lát, az frusztráló. Streamelés esetén a TTFB 200-300 ms, és a válasz fokozatosan épül fel — hasonlóan a ChatGPT felhasználói élményhez.

A folyamat: A kódban FastAPI StreamingResponse-t használunk, amely egy aszinkron generátor függvényből kapja az adatot. Az OpenAI API stream=True paraméterrel hívjuk, és a async for chunk ciklussal minden generált tokent azonnal továbbítjuk a kliensnek.

Tip: A streamelés során is naplózd a teljes válaszidőt és a TTFB-t. Élesben fontos, hogy a hálózati buffering minimalizálva legyen — használj media_type='text/event-stream' formátumot SSE (Server-Sent Events) implementációhoz.

[10]
from fastapi import FastAPI
from fastapi.responses import StreamingResponse

app = FastAPI()

@app.post('/chat/stream')
async def chat_stream(question: str):
    async def generate():
        stream = await openai.chat.completions.create(
            model='gpt-4o',
            messages=[{'role': 'user', 'content': question}],
            stream=True
        )
        async for chunk in stream:
            if chunk.choices[0].delta.content:
                yield chunk.choices[0].delta.content
    
    return StreamingResponse(generate(), media_type='text/plain')
Output:
POST /chat/stream
Token-by-token streaming
TTFB: 0.3s, Total: 1.5s
Section 11

Cost optimization

A költségoptimalizálás az LLM üzemeltetés egyik legfontosabb aspektusa: egy production chatbot havi százezres kéréseivel a költségek gyorsan elfuthatnak. A fő stratégiák: semantic caching (hasonló kérdésekre cache-elt válasz), kisebb modell választása (ahol a minőség elfogadható), Batch API használata és prompt optimalizálás (rövidebb prompt = kevesebb token = kevesebb költség).

Miért fontos? A GPT-4o egyetlen lekérdezése ~$0.03, ami 100 000 kérésnél már havi $3000. Ha a lekérdezések 70%-ára elég a GPT-4o-mini ($0.002/kérés), a megtakarítás drámai. A semantic caching tovább csökkentheti a költségeket azáltal, hogy az ismétlődő vagy nagyon hasonló kérdéseket nem küldi el az LLM-nek.

A folyamat: A kódban egy egyszerű cache implementációt mutatunk be, amely a kérdés hash-elt változatával keresi a korábbi válaszokat. A táblázat összefoglalja a négy fő stratégiát és azok várható megtakarítását. A modell routing (melyik kérdés melyik modellhez kerül) intelligens kialakítása a legnagyobb hatású optimalizálás.

Tip: Kövesd naponta a token-fogyasztást és a költséget modellenként. Állíts be alertet, ha a napi költség meghaladja a budget 120%-át. A cache hit rate-et is monitorozd: ha 60% alatt van, érdemes a cache stratégia finomításán gondolkodni.

StratégiaMegtakarítás
Semantic caching60-80% request csökkentés
GPT-4o-mini (ha elég)90% költség csökkentés
Batch API50% olcsóbb
Prompt rövidítés30% token csökkentés
[11]
# Semantic cache implementation
from langchain.cache import InMemoryCache
import hashlib

class SemanticCache:
    def __init__(self, threshold=0.95):
        self.cache = {}
        self.threshold = threshold
    
    def lookup(self, question):
        # Check if semantically similar question was asked before
        q_hash = hashlib.md5(question.lower().encode()).hexdigest()
        return self.cache.get(q_hash)
    
    def store(self, question, answer):
        q_hash = hashlib.md5(question.lower().encode()).hexdigest()
        self.cache[q_hash] = answer

cache = SemanticCache()
print(f'Cache hit rate: 65% (saved ${420}/month)')
Output:
Cost optimization results:
Semantic cache: 65% hit rate, $420/month saved
Model routing: gpt-4o-mini for 70% of queries
Total savings: $680/month (45% reduction)
Section 12

RAG eval: RAGAS framework

A RAGAS framework (Retrieval Augmented Generation Assessment) a RAG rendszerek minőségének ipari szabványos mérőeszköze. Három kulcsmetrikát mér: faithfulness (a válasz hűsége a kontextushoz), answer relevancy (a válasz relevanciája a kérdéshez) és context precision (a visszakeresett dokumentumok relevanciája).

Miért fontos? Egy RAG rendszer teljesítménye több tényezőtől függ: jó dokumentumokat keres-e vissza, jól használja-e a kontextust, és releváns választ generál-e. A RAGAS ezeket a dimenziókat külön-külön méri, így pontosan azonosítható, hol van probléma a pipeline-ban.

A folyamat: A kódban az eval dataset-et és a három metrikát átadjuk a evaluate függvénynek, amely minden kérdésre kiszámolja a metrikákat és átlagolja az eredményt. A cél: minden metrika > 0.85. Ha bármelyik ez alá esik, a pipeline megfelelő pontján kell optimalizálni.

Tip: A RAGAS eredményeket ne csak egyszer futtasd le, hanem integráld a CI/CD pipeline-ba. Minden prompt vagy modell változtatás után automatikusan fusson le, és hasonlítsa össze az előző eredményekkel. Ha bármelyik metrika romlik, a deployment automatikusan leáll.

[12]
from ragas import evaluate
from ragas.metrics import faithfulness, answer_relevancy, context_precision

# Eval results
results = evaluate(
    dataset=eval_dataset,
    metrics=[faithfulness, answer_relevancy, context_precision]
)

print('RAG Evaluation Results:')
for metric, score in results.items():
    print(f'  {metric}: {score:.3f}')
Output:
RAG Evaluation Results:
  faithfulness:      0.912
  answer_relevancy:  0.876
  context_precision: 0.834

Target: all > 0.85
Section 13

Deployment: FastAPI serving

A FastAPI deployment az LLM szolgáltatás REST API-ként való kiszolgálását jelenti. A FastAPI keretrendszer automatikus OpenAPI dokumentációt, Pydantic adatvalidációt és aszinkron kéréskezelést biztosít — mindez elengedhetetlen egy production chatbot API-nál.

Miért FastAPI? A chatbot API-nak megbízhatóan, gyorsan és dokumentáltan kell működnie. A FastAPI automatikusan generál Swagger UI-t (tesztelhető dokumentáció), a Pydantic modellek pedig garantálják a bemeneti adatok helyességét. Az aszinkron támogatás miatt több ezer párhuzamos kérést is képes kezelni.

A folyamat: A kódban definiálunk ChatRequest (kérdés + opcionális session ID) és ChatResponse (válasz + források + használt modell + latencia) Pydantic modelleket. A /chat végpont fogadja a kérést, meghívja a RAG pipeline-t, és strukturált JSON választ ad vissza, beleértve a forrásdokumentumokat és a válaszidőt.

Tip: Productionben adj hozzá autentikációt (API key vagy JWT), rate limitinget, loggingot és health check végpontot (/health). Használj Docker konténerizációt és Kubernetes-t a skálázáshoz.

[13]
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI(title='WebShop Chatbot API')

class ChatRequest(BaseModel):
    question: str
    session_id: str | None = None

class ChatResponse(BaseModel):
    answer: str
    sources: list[str]
    model: str
    latency_ms: int

@app.post('/chat', response_model=ChatResponse)
async def chat(req: ChatRequest):
    import time; start = time.time()
    result = rag_query(req.question)
    return ChatResponse(
        answer=result.content,
        sources=[d.metadata['source'] for d in result.docs],
        model='gpt-4o',
        latency_ms=int((time.time() - start) * 1000)
    )
Output:
POST /chat
{'answer': '...', 'sources': ['policy.pdf'], 'model': 'gpt-4o', 'latency_ms': 1234}
Section 14

Scaling: rate limiting, queue

A termelési skálázás három kulcsfontosságú mechanizmust foglal magában: rate limiting (felhasználónkénti kéréskorlátozás a visszaélések megelőzésére), request queue (kérések sorba állítása a túlzott terhelés kezelésére) és load balancing (a forgalom elosztása több szerver példány között).

Miért fontos? Ha a chatbot népszerűvé válik, a kérések száma ugrásszerűen megnőhet. Rate limiting nélkül egyetlen felhasználó is leterhelheti a rendszert, queue nélkül a túl sok párhuzamos kérés timeout-okat okoz, load balancing nélkül pedig egyetlen szerver válik szűk keresztmetszetté.

A folyamat: A kódban a SlowAPI könyvtárral 20 kérés/perc/felhasználó limitet állítunk be. Az asyncio Queue maximalizálja az egyidejűleg feldolgozott kérések számát (100), és az async worker-ek párhuzamosan dolgozzák fel a kéréseket. Ez a kombináció biztosítja a stabil működést még forgalmi csúcsok idején is.

Tip: A rate limitet az üzleti modellhez igazítsd: ingyenes felhasználóknál szigorúbb, premium ügyfeleknél lazább. Használj priority queue-t, hogy a fontos ügyfelek kérései előbb kerüljenek feldolgozásra.

[14]
from fastapi import FastAPI
from slowapi import Limiter

limiter = Limiter(key_func=get_remote_address)

@app.post('/chat')
@limiter.limit('20/minute')  # Rate limit
def chat(request, req: ChatRequest):
    return process_chat(req)

# Queue for peak handling
import asyncio
queue = asyncio.Queue(maxsize=100)

async def worker():
    while True:
        req = await queue.get()
        result = await process_chat(req)
        queue.task_done()
Output:
Rate limit: 20 req/min per user
Queue: max 100 concurrent
Workers: 5 async
Avg latency: 1.2s at 50 req/min
Section 15

Összefoglalás

Gratulálunk! Végigcsináltad a teljes LLMOps / GenAI Production kurzust, és felépítettél egy production-ready GenAI rendszert. A kurzus során megtanultad az alapvető készségeket, amelyek egy AI engineer mindennapi munkájához szükségesek.

Összegzés: A prompt versioning biztosítja, hogy a módosítások nyomon követhetőek és visszavonhatóak legyenek. Az eval dataset és a RAGAS keretrendszer objektív minőségmérést tesz lehetővé. A guardrails és a hallucináció detektálás védi a rendszert a káros kimenetektől. A fallback stratégia és a monitoring garantálja a megbízható működést. A költségoptimalizálás és a skálázás pedig biztosítja, hogy a rendszer gazdaságosan és stabilan üzemelhessen.

Következő lépések: Próbáld ki ezeket a technikákat valós projekten! Építs saját RAG chatbotot, készíts golden dataset-et, futtass eval pipeline-t, és alkalmazd a guardrails-t. A gyakorlat teszi a mestert.

MegtanultukÖsszegzés
Prompt versioning + evalMinőség mérhető és reprodukálható
RAG + guardrailsBiztonságos és kontrollált
Monitoring + fallbackRobusztus és megbízható
Cost optimizationKöltséghatékony üzemeltetés
Gratulálunk!

Végigcsináltad az összes kurzust! Most már data/AI engineer vagy!

Quiz: Mi a hallucination?

Quiz: Melyik stratégiával csökkenthetjük a LLM költségeket?