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!') # passesYanı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_callsalanının boş olmadığını denetleyin tc.function.name == 'expected_tool'ile doğru araç adını doğrulayıntc.function.argumentsdeğ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_reasondeğerini ve adım sayılarını denetleyin - Birden çok girdi senaryosu için
@pytest.mark.parametrizekullanı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
- Aracıları Sınamak Neden Farklıdır
- Sınamalarda LLM Çağrılarını Taklit Etme
- Doğrulama Tabanlı Aracı Sınaması
- Aracı İş Akışları İçin Tümleştirme Sınamaları