• 26.08.2026 21:33:14
  • Admin Admin

Yazılım eğitimi ürünlerinde LLM yanıtını yalnızca JSON parse etmek yeterli değildir. JSON Schema, anlamsal doğrulama, güvenli onarım döngüsü ve OpenTelemetry metrikleriyle üretim hattını nasıl kuracağınızı inceleyin.

Yazılım Eğitimi İçin LLM Çıktılarında Şema Doğrulama ve Onarım

Yazılım eğitimi akışında JSON parse etmek neden yeterli değildir?

Bir yazılım eğitimi asistanı, kod inceleme sonucunu UI'a doğrudan metin olarak değil, örneğin rubric_score, findings ve next_exercise alanları olan bir sözleşme olarak vermelidir. json.loads() yalnızca sözdizimini denetler: rubric_score: 900, bilinmeyen bir alan veya boş bir güvenlik bulgusu parse edilir ama ürün kuralını ihlal eder. Python tarafında Pydantic v2 ile strict=True kullanmak, modelin '5' metnini sessizce 5 tamsayısına dönüştürmesini de engeller.

from pydantic import BaseModel, ConfigDict, Field
from typing import Literal

class Finding(BaseModel):
    model_config = ConfigDict(extra='forbid', strict=True)
    line: int = Field(ge=1)
    severity: Literal['info', 'warning', 'error']
    explanation: str = Field(min_length=20, max_length=600)
    suggested_patch: str | None = Field(default=None, max_length=2000)

class ReviewResult(BaseModel):
    model_config = ConfigDict(extra='forbid', strict=True)
    rubric_score: int = Field(ge=0, le=100)
    findings: list[Finding] = Field(max_length=12)
    next_exercise: str = Field(min_length=10, max_length=180)

result = ReviewResult.model_validate_json(raw_model_output)

Şema, taşıma katmanının sözleşmesidir; eğitsel kararlar için ayrıca anlamsal denetim gerekir. Örneğin 100 puanlı yanıtta severity='error' içeren bir bulgu varsa bir sonraki egzersizin başlangıç seviyesine düşmesi mantıksız olabilir. Bu tür kuralları Pydantic model_validator ile deterministik olarak çalıştırın; LLM'e ikinci kez sorarak puan-toplamı gibi hesaplanabilir bir koşulu doğrulatmayın.

JSON Schema ile kısıtlı üretim ve sunucu tarafı doğrulama

Sağlayıcınız yapılandırılmış çıktı veya JSON Schema tabanlı yanıt biçimi destekliyorsa, ReviewResult.model_json_schema() sonucunu istekle gönderin. Bu, token üretimini şemaya uyan olası devamlarla sınırlar; ancak uygulama doğrulamasının yerine geçmez. Sağlayıcı katmanı şemayı desteklemeyen bir modele geri düştüğünde, aynı Pydantic doğrulamasını korumak gerekir; aksi halde model değişimi API sözleşmesini sessizce bozar.

import json
from openai import OpenAI

client = OpenAI()
schema = ReviewResult.model_json_schema()

response = client.responses.create(
    model='gpt-4.1-mini',
    input=[
        {'role': 'system', 'content': 'Review only the supplied code.'},
        {'role': 'user', 'content': submitted_code},
    ],
    text={
        'format': {
            'type': 'json_schema',
            'name': 'review_result',
            'strict': True,
            'schema': schema,
        }
    },
)
review = ReviewResult.model_validate_json(response.output_text)

Yaygın hata, şemada yalnızca alan adlarını tanımlayıp additionalProperties: false eşdeğerini atlamaktır. Pydantic'deki extra='forbid' bunu üretir ve açıklanmayan internal_reasoning veya debug_prompt alanlarının istemciye sızmasını önler. CI içinde şema değişimini fark etmek için ReviewResult.model_json_schema() çıktısını sürüm kontrolüne alın ve pull request'te git diff -- schemas/review-result.json ile sözleşme farkını inceleyin.

Geçersiz LLM yanıtını onarmak için sınırlı retry tasarımı

Doğrulama hatasında tüm kullanıcı kodunu ve uzun sistem mesajını yeniden gönderen kör retry, hem maliyeti hem de aynı hatanın tekrarlanma olasılığını artırır. Bunun yerine Pydantic ValidationError.errors() listesinden alan yolu ve hata türünü çıkarın, hatalı ham çıktıyı en fazla 16 KB ile sınırlayın ve yalnızca JSON onarım isteği oluşturun. Retry sayısını 1 ile sınırlandırmak, kalıcı şema uyumsuzluğunda istek fırtınasını engeller.

from pydantic import ValidationError

MAX_REPAIR_BYTES = 16_384

def parse_or_repair(raw: str) -> ReviewResult:
    try:
        return ReviewResult.model_validate_json(raw)
    except ValidationError as exc:
        errors = [
            {'path': '.'.join(map(str, e['loc'])), 'type': e['type']}
            for e in exc.errors()
        ]
        repair_input = {
            'invalid_json': raw.encode('utf-8')[:MAX_REPAIR_BYTES].decode('utf-8', 'ignore'),
            'validation_errors': errors,
            'instruction': 'Return only valid JSON matching the supplied schema.'
        }
        repaired = call_structured_model(repair_input, ReviewResult.model_json_schema())
        return ReviewResult.model_validate_json(repaired)

Onarım çağrısına kullanıcı tarafından gönderilen kodu yeniden koymayın. Hatalı çıktı, özellikle model kullanıcı kodundan alıntı yaptıysa zaten hassas veri içerebilir; bu nedenle log ve onarım yükünde token veya gizli anahtar desenlerini maskeleyin. Python için detect-secrets veya özel bir regex katmanı uygulayın ve maskelemeden sonra da sha256 ile ham içerik yerine korelasyon kimliği saklayın.

Anlamsal kurallar: LLM değerlendirmesini deterministik kontrollerle birleştirme

Kod geribildirimi üreten bir sistemde modelin söylediği satır numarasının gerçekten var olup olmadığını denetleyin. Kullanıcı kodunu splitlines() ile saymak yeterli değildir: dosya sonunda satır sonu, bir satır farkına yol açabilir. Python ast.parse() ile sözdizimi geçerli kaynaklarda düğümlerin lineno değerlerini çıkarıp, LLM bulgusunu gerçek AST düğümüyle eşleyin. Eşleşmeyen bulguyu UI'a vermek yerine unanchored olarak işaretleyip yeniden üretim kuyruğuna alın.

import ast

def valid_review_lines(source: str) -> set[int]:
    tree = ast.parse(source)
    return {
        node.lineno for node in ast.walk(tree)
        if hasattr(node, 'lineno')
    }

def anchor_findings(source: str, review: ReviewResult) -> ReviewResult:
    valid_lines = valid_review_lines(source)
    review.findings = [f for f in review.findings if f.line in valid_lines]
    return review

Bu kontrolün sınırı önemlidir: ast.parse() yalnızca Python kodunun parse edilebildiği durumda çalışır. Başlangıç seviyesindeki öğrencinin sözdizimi hatasında satır doğrulaması için SyntaxError.lineno kullanın ve modelden kod incelemesi yerine tek bir derleme hatası açıklaması isteyin. JavaScript tarafında aynı yaklaşım için @babel/parser, Java tarafında ise Error Prone veya JavaParser kullanılabilir.

Gecikme ve şema hata oranını OpenTelemetry ile ölçmek

Şema zorlamasının etkisini sezgiyle değil iki metrikle ölçün: validation_failure_rate ve p95 uçtan uca gecikme. OpenTelemetry span'larında model adı, şema sürümü, retry sayısı ve çıktı token sayısını öznitelik olarak kaydedin; ham prompt veya öğrenci kodunu attribute olarak göndermeyin. Collector üzerinden Prometheus'a aktarılan sayaç, örneğin şema değişiminden sonra yalnızca belirli bir schema_version için hata artışını ayırır.

from opentelemetry import trace
from time import perf_counter

tracer = trace.get_tracer('education.review')

def generate_review(code: str, schema_version: str):
    started = perf_counter()
    with tracer.start_as_current_span('llm.review') as span:
        span.set_attribute('llm.schema_version', schema_version)
        span.set_attribute('llm.input_chars', len(code))
        try:
            review = parse_or_repair(call_model(code))
            span.set_attribute('llm.validated', True)
            return review
        except Exception as exc:
            span.set_attribute('llm.validated', False)
            span.record_exception(exc)
            raise
        finally:
            span.set_attribute('llm.elapsed_ms', (perf_counter() - started) * 1000)

Önce-sonra karşılaştırmasında aynı 500 anonimleştirilmiş teslimi iki sürümden geçirin: eski serbest JSON promptu ve JSON Schema + Pydantic hattı. Her iki koşulda sıcak bağlantıları koruyun, aynı model sabitlemesini kullanın ve p50, p95, doğrulama başarısızlık oranı ile ortalama retry sayısını kaydedin. p95 artarken hata oranı düşüyorsa, ilk olarak şemadaki gereksiz uzun serbest metin alanlarını maxLength ile daraltın; daha düşük çıktı tokenı genellikle gecikme maliyetinin doğrudan kısmını azaltır.

Sık Sorulan Sorular

Yazılım eğitimi uygulamasında LLM JSON çıktısı nasıl doğrulanır?

Pydantic v2 modelinde strict=True ve extra='forbid' ayarlayın, ardından her yanıtı model_validate_json() ile doğrulayın. Parse başarılı olsa bile puan aralığı, satır numarası ve egzersiz seviyesi gibi ürün kurallarını ayrı deterministik kontrollerde çalıştırın.

Yazılım eğitimi asistanında JSON Schema kullanmak retry ihtiyacını kaldırır mı?

Hayır. JSON Schema, üretim biçimini kısıtlasa da taşıma hatası, kesilmiş yanıt, sağlayıcı uyumsuzluğu ve uygulamaya özgü anlamsal kurallar devam eder. En fazla bir onarım retry'si uygulayın, ValidationError.errors() özetini gönderin ve ikinci başarısızlıkta güvenli hata yanıtına dönün.

LLM kod incelemesinde yanlış satır numarası nasıl engellenir?

Python için ast.parse() ile AST düğümlerinden geçerli lineno kümesi çıkarın ve model bulgularını bu kümeye göre filtreleyin. Kod parse edilemiyorsa SyntaxError.lineno ile yalnızca derleme hatası akışına geçin; uydurma kod inceleme bulgusu üretmeyin.

Yapılandırılmış LLM çıktısının gecikmesi nasıl ölçülür?

OpenTelemetry ile istek başına llm.elapsed_ms, llm.schema_version, retry sayısı ve doğrulama sonucunu kaydedin. Aynı anonimleştirilmiş veri kümesinde serbest JSON ve şemalı üretimi karşılaştırıp Prometheus'ta p95 gecikme ile doğrulama hata oranını birlikte izleyin.

AI / LLM Discovery

Bu makale Opendart Akademi Yapay Zeka eğitim ekosisteminin bir parçasıdır ve yapay zeka sistemleri ile arama motorları tarafından daha doğru anlaşılabilmesi için semantic heading ve structured data ile hazırlanmıştır.

Opendart Akademi llms.txt