0Pricing
AI Agents · Ders

Doğrulama Tabanlı Aracı Sınaması

Araç çağrılarını, ara adımları ve nihai çıktı yapısını denetleme.

Doğrulama Tabanlı Aracı Sınaması, CoddyKit'te ücretsiz bir AI Agents dersidir. Bu, 4 dersinin 3. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, AI Agents öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. AI Agents kursu toplamda 4 dersten oluşur.

Tam Dize Eşleştirmesinin Ötesine Geçme

LLM çıktıları belirlenemez olduğundan, bunları assert response == 'exact text' ile sınamak kırılgandır. Bunun yerine, tam ifadeye bağlı kalmadan yanıtın yapısını ve amacını denetleyen doğrulamalar yazın.

Araç Çağrılarının Yapıldığını Doğrulama

İşlev çağıran aracılarda en güvenilir doğrulama, aracının doğru aracı çağırmayı seçtiğini denetlemektir. Bu yapısaldır; LLM'nin düşünce sürecini ifade ederken kullandığı kesin sözcüklere bağlı değildir.

import json
from unittest.mock import patch, MagicMock

@patch('myagent.client.chat.completions.create')
def test_agent_calls_search_tool(mock_create):
    # Mock: agent decides to call search_web
    tool_call = MagicMock()
    tool_call.function.name = 'search_web'
    tool_call.function.arguments = json.dumps({'query': 'Python tutorials'})
    mock_create.return_value = MagicMock(
        choices=[MagicMock(message=MagicMock(tool_calls=[tool_call]))]
    )

    response = mock_create()  # simulating the agent call
    tc = response.choices[0].message.tool_calls

    assert tc is not None
    assert len(tc) > 0
    assert tc[0].function.name == 'search_web'

# --- demo: give unittest.mock.patch a real dotted path to patch ---
import sys
import types

_myagent = types.ModuleType('myagent')
_myagent.client = types.SimpleNamespace(
    chat=types.SimpleNamespace(completions=types.SimpleNamespace(create=lambda *a, **k: None))
)
sys.modules['myagent'] = _myagent

test_agent_calls_search_tool()
print('test_agent_calls_search_tool: PASS')

Doğru Araç Adını Doğrulama

Araç çağrılarının var olduğunu denetlemenin ötesine geçerek belirli araç adının beklendiğiyle eşleştiğini doğrulayın. Bu, aracının belirli bir sorgu için yanlış aracı seçtiği durumları yakalar.

import json
from unittest.mock import MagicMock

def extract_tool_calls(response) -> list:
    message = response.choices[0].message
    if not message.tool_calls:
        return []
    return [
        {
            'name': tc.function.name,
            'args': json.loads(tc.function.arguments)
        }
        for tc in message.tool_calls
    ]

# In a test:
# calls = extract_tool_calls(mock_response)
# assert calls[0]['name'] == 'get_weather'
# assert calls[0]['args']['city'] == 'Paris'
print('Tool name and argument assertions are the most reliable agent tests')

Araç Bağımsız Değişkenlerini Doğrulama

Araç adını doğruladıktan sonra bağımsız değişkenlerin doğru olup olmadığını denetleyin. Aracı yalnızca doğru aracı seçmekle kalmamalı, kullanıcının isteğindeki doğru parametrelerle onu doldurmalıdır.

import json
from unittest.mock import patch, MagicMock

@patch('myagent.client.chat.completions.create')
def test_weather_tool_gets_correct_city(mock_create):
    tool_call = MagicMock()
    tool_call.function.name = 'get_weather'
    tool_call.function.arguments = json.dumps({'city': 'Tokyo', 'unit': 'celsius'})
    mock_create.return_value = MagicMock(
        choices=[MagicMock(message=MagicMock(tool_calls=[tool_call]))]
    )

    response = mock_create()
    args = json.loads(response.choices[0].message.tool_calls[0].function.arguments)

    assert args['city'] == 'Tokyo'
    assert args.get('unit') in ['celsius', 'fahrenheit', None]  # flexible

# --- demo: give unittest.mock.patch a real dotted path to patch ---
import sys
import types

_myagent = types.ModuleType('myagent')
_myagent.client = types.SimpleNamespace(
    chat=types.SimpleNamespace(completions=types.SimpleNamespace(create=lambda *a, **k: None))
)
sys.modules['myagent'] = _myagent

test_weather_tool_gets_correct_city()
print('test_weather_tool_gets_correct_city: PASS')

Çıktılar için JSON Schema Doğrulaması

Aracınız yapılandırılmış JSON döndürdüğünde, gerekli tüm alanların mevcut olduğundan ve doğru türlere sahip olduğundan emin olmak için çıktıyı bir JSON Schema'ya göre doğrulayın. jsonschema kütüphanesi bunu kolaylaştırır.

# pip install jsonschema
import jsonschema

AGENT_RESPONSE_SCHEMA = {
    'type': 'object',
    'required': ['answer', 'sources', 'confidence'],
    'properties': {
        'answer': {'type': 'string', 'minLength': 1},
        'sources': {
            'type': 'array',
            'items': {'type': 'string', 'format': 'uri'}
        },
        'confidence': {'type': 'number', 'minimum': 0, 'maximum': 1}
    }
}

def test_agent_output_schema(agent_output: dict):
    try:
        jsonschema.validate(instance=agent_output, schema=AGENT_RESPONSE_SCHEMA)
        print('Schema validation passed')
    except jsonschema.ValidationError as e:
        raise AssertionError(f'Invalid agent output: {e.message}')

Anahtar Sözcüklerin Bulunduğunu Doğrulama

Tam ifadenin değiştiği metin yanıtlarında, temel kavramların veya sözcüklerin çıktıda yer alıp almadığını denetleyin. Bu yaklaşım esnek olduğu gibi anlamlıdır da; aracının yanıtında en azından ilgili terimlerden söz edilmelidir.

def assert_keywords_present(text: str, keywords: list, require_all: bool = True):
    lower_text = text.lower()
    found = [kw.lower() in lower_text for kw in keywords]

    if require_all:
        missing = [kw for kw, f in zip(keywords, found) if not f]
        assert not missing, f'Missing keywords: {missing}'
    else:
        assert any(found), f'None of {keywords} found in: {text[:100]}'

# Tests
response = 'The capital city of France is Paris, located in western Europe.'
assert_keywords_present(response, ['paris', 'france', 'capital'])
print('All keywords present!')  # passes

assert_keywords_present(response, ['spain', 'france'], require_all=False)
print('At least one keyword present!')  # passes

Yanıt Biçimini Doğrulama: Tür Denetimleri

Tür doğrulamaları hızlı ve güvenilirdir. Aracının None değil bir sözlük döndürdüğünü, liste alanlarının liste olduğunu ve sayısal alanların geçerli aralıklarda bulunduğunu doğrulayın.

def test_agent_returns_valid_structure(agent_result):
    # Type checks
    assert isinstance(agent_result, dict), 'Result must be a dict'
    assert isinstance(agent_result.get('answer'), str), 'answer must be a string'
    assert isinstance(agent_result.get('steps'), list), 'steps must be a list'

    # Non-empty checks
    assert len(agent_result['answer']) > 0, 'answer must not be empty'
    assert len(agent_result['steps']) >= 1, 'must have at least one step'

    # Range checks
    confidence = agent_result.get('confidence', 0)
    assert 0.0 <= confidence <= 1.0, 'confidence must be 0-1'

print('Structural assertions are fast and reliable')

finish_reason'ı Doğrulama

finish_reason alanı, modelin üretmeyi neden durdurduğunu belirtir. Bunu doğrulamak sorunları algılamaya yardımcı olur: 'stop' temiz bir yanıtı, 'tool_calls' aracının bir araç çağırmak istediğini, 'length' ise kesilmeyi belirtir.

from unittest.mock import MagicMock

def test_agent_stops_cleanly(mock_response):
    finish_reason = mock_response.choices[0].finish_reason
    assert finish_reason in ('stop', 'tool_calls'), \
        f'Unexpected finish_reason: {finish_reason}'

def test_no_truncation(mock_response):
    finish_reason = mock_response.choices[0].finish_reason
    assert finish_reason != 'length', \
        'Response was truncated — increase max_tokens'

# Example mock for a clean stop
mock = MagicMock()
mock.choices = [MagicMock(finish_reason='stop')]
test_agent_stops_cleanly(mock)
print('finish_reason: stop — clean termination')

Bir Döngüdeki Adım Sayısını Doğrulama

Döngü içinde çalışan bir aracı, makul sayıda adımda tamamlanmalıdır. Aracının en fazla yineleme sayısı içinde tamamlandığını doğrulayın — bu, max_iterations korumasının önlemeyi amaçladığı sonsuz döngüleri yakalar.

def test_agent_completes_in_bounded_steps(mock_agent):
    result = mock_agent.run('Search for the weather in Paris')

    # Agent should complete within 5 steps
    assert result['steps_taken'] <= 5, \
        f'Agent took too many steps: {result["steps_taken"]}'

    # Agent should produce a final answer, not exit on timeout
    assert result['status'] == 'completed', \
        f'Agent did not complete: {result["status"]}'

    assert result['answer'] is not None

print('Bounding step count prevents runaway agents from passing tests')

Birden Çok Girdi İçin Sınamaları Parametreleştirme

pytest'in @pytest.mark.parametrize özelliği, aynı sınamayı birçok farklı girdiyle çalıştırmanızı sağlar. Bu, aracınızın farklı sorgu türlerini doğru araçlara yönlendirdiğini sınamak için idealdir.

import pytest
from unittest.mock import patch, MagicMock
import json

@pytest.mark.parametrize('query,expected_tool', [
    ('What is the weather in Tokyo?', 'get_weather'),
    ('Calculate 15% of 200', 'calculator'),
    ('Search for Python books', 'web_search'),
    ('What time is it in Berlin?', 'get_time'),
])
@patch('myagent.client.chat.completions.create')
def test_agent_tool_routing(mock_create, query, expected_tool):
    tool_call = MagicMock()
    tool_call.function.name = expected_tool
    tool_call.function.arguments = json.dumps({'input': query})
    mock_create.return_value = MagicMock(
        choices=[MagicMock(message=MagicMock(tool_calls=[tool_call]))]
    )
    response = mock_create()
    actual = response.choices[0].message.tool_calls[0].function.name
    assert actual == expected_tool

Özel Doğrulama Yardımcıları Yazma

Aracı sınama paketiniz büyüdükçe yaygın doğrulama kalıplarını yardımcı işlevlere ayırın. Bu, aracının yanıt biçimi değiştiğinde sınamaları kısaltır, daha okunaklı hâle getirir ve bakımlarını kolaylaştırır.

import json

def assert_tool_called(response, tool_name: str, required_args: dict = None):
    message = response.choices[0].message
    assert message.tool_calls, 'Expected tool call but got plain text'
    names = [tc.function.name for tc in message.tool_calls]
    assert tool_name in names, f'Expected {tool_name}, got {names}'

    if required_args:
        for tc in message.tool_calls:
            if tc.function.name == tool_name:
                args = json.loads(tc.function.arguments)
                for key, val in required_args.items():
                    assert args.get(key) == val, \
                        f'Arg {key}: expected {val}, got {args.get(key)}'

# Clean test using the helper:
# assert_tool_called(response, 'get_weather', {'city': 'Paris'})

# --- demo ---
from unittest.mock import MagicMock

tool_call = MagicMock()
tool_call.function.name = 'get_weather'
tool_call.function.arguments = json.dumps({'city': 'Paris'})
response = MagicMock(choices=[MagicMock(message=MagicMock(tool_calls=[tool_call]))])

assert_tool_called(response, 'get_weather', {'city': 'Paris'})
print('assert_tool_called passed: agent called get_weather with city=Paris')

Bilgi Denetimi: Doğrulama Tabanlı Aracı Sınaması

Aracı sınamalarında doğrulama stratejilerini anlayıp anlamadığınızı sınayın.

Özet: Doğrulama Tabanlı Aracı Sınaması

Artık aracı sınamaları için eksiksiz bir doğrulama araç takımına sahipsiniz:

  • Aracının bir araç kullanması gerektiğinde tool_calls alanının boş olmadığını denetleyin
  • tc.function.name == 'expected_tool' ile doğru araç adını doğrulayın
  • tc.function.arguments değerini JSON olarak ayrıştırarak araç bağımsız değişkenlerini doğrulayın
  • Yapılandırılmış çıktı doğrulaması için jsonschema.validate() kullanın
  • Esnek metin doğrulamaları için anahtar sözcük bulunma denetimlerini kullanın
  • Döngü kullanan aracılarda finish_reason değerini ve adım sayılarını denetleyin
  • Birden çok girdi senaryosu için @pytest.mark.parametrize kullanın

Sıkça Sorulan Sorular

“Doğrulama Tabanlı Aracı Sınaması” dersi ücretsiz mi?

Evet — “Doğrulama Tabanlı Aracı Sınaması” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve AI Agents kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. AI Agents kursu toplamda 4 dersten oluşur.

“Doğrulama Tabanlı Aracı Sınaması” dersinde ne öğreneceğim?

Araç çağrılarını, ara adımları ve nihai çıktı yapısını denetleme. AI Agents ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

AI Agents öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te AI Agents, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 3. dersidir.

“Doğrulama Tabanlı Aracı Sınaması” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu AI Agents dersinde kod yazıp çalıştırabilir miyim?

Evet. Her AI Agents dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. Aracıları Sınamak Neden Farklıdır
  2. Sınamalarda LLM Çağrılarını Taklit Etme
  3. Doğrulama Tabanlı Aracı Sınaması
  4. Aracı İş Akışları İçin Tümleştirme Sınamaları
← AI Agents Sayfasına Dön