Tekoälyagentit · Oppitunti

Väitteisiin perustuva agenttien testaus

Työkalukutsujen, välivaiheiden ja lopullisen tulosteen rakenteen tarkistaminen

Oppitunti 3/413 vaihetta

Väitteisiin perustuva agenttien testaus on ilmainen Tekoälyagentit-oppitunti CoddyKitissä. Tämä on oppitunti 3/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Tekoälyagentit-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Tekoälyagentit-kurssilla on yhteensä 4 oppituntia.

Tarkan merkkijonovastaavuuden tuolle puolen

Koska LLM-tulokset eivät ole deterministisiä, niiden testaaminen muodossa assert response == 'exact text' on hauraaa. Kirjoittakaa sen sijaan assertioita, jotka tarkistavat vastauksen rakenteen ja tarkoituksen riippumatta täsmällisestä sanamuodosta.

Tarkistetaan, että työkalukutsut tehtiin

Funktiokutsuja käyttävien agenttien tapauksessa luotettavin assertio on varmistaa, että agentti valitsi oikean työkalun kutsuttavaksi. Tämä on rakenteellinen tarkistus, joka ei riipu LLM:n ajatusprosessin täsmällisestä sanamuodosta.

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')

Tarkistetaan oikea työkalun nimi

Sen lisäksi, että tarkistatte työkalukutsujen olemassaolon, varmistakaa, että työkalun nimi vastaa odotettua. Näin löytyvät tilanteet, joissa agentti valitsee kyselyyn väärän työkalun.

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')

Työkalun argumenttien tarkistaminen

Kun olette tarkistaneet työkalun nimen, tarkistakaa, että argumentit ovat oikein. Agentin on valittava oikea työkalu ja täytettävä se käyttäjän pyynnöstä johdetuilla oikeilla parametreilla.

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')

Tulosten validointi JSON-skeemalla

Kun agenttinne palauttaa jäsenneltyä JSON-dataa, validoikaa tulos JSON-skeemaa vasten varmistaaksenne, että kaikki pakolliset kentät ovat mukana ja että niiden tyypit ovat oikeat. jsonschema-kirjasto tekee tästä helppoa.

# 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}')

Avainsanojen esiintymisen tarkistukset

Kun tekstivastauksen täsmällinen sanamuoto vaihtelee, tarkistakaa, että tuloksessa esiintyy keskeisiä käsitteitä tai sanoja. Tämä on joustavaa mutta silti merkityksellistä — agentin vastauksen on vähintään mainittava olennaiset termit.

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

Vastauksen muodon tarkistaminen: tyyppitarkistukset

Tyyppeihin perustuvat assertiot ovat nopeita ja luotettavia. Varmistakaa, että agentti palauttaa sanakirjan eikä arvoa None, että listakentät ovat listoja ja että numeeriset kentät ovat kelvollisilla arvoalueilla.

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-kentän tarkistaminen

finish_reason-kenttä kertoo, miksi malli lopetti generoinnin. Sen tarkistaminen auttaa havaitsemaan ongelmia: 'stop' tarkoittaa siistiä vastausta, 'tool_calls' tarkoittaa, että agentti haluaa kutsua työkalua, ja 'length' tarkoittaa katkaisua.

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')

Silmukan vaiheiden määrän tarkistaminen

Silmukassa toimivan agentin pitäisi valmistua kohtuullisessa määrässä vaiheita. Tarkistakaa, että agentti päättää toimintansa enimmäisiterointimäärän puitteissa — näin löytyvät infinite loop -tilanteet, joita max_iterations-rajoituksen on tarkoitus estää.

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')

Testien parametrisoiminen useille syötteille

pytestin @pytest.mark.parametrize-koristeella voitte suorittaa saman testin monilla eri syötteillä. Tämä sopii erinomaisesti sen testaamiseen, että agenttinne ohjaa erityyppiset kyselyt oikeille työkaluille.

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

Mukautettujen assertioapureiden kirjoittaminen

Kun agenttien testikokonaisuus kasvaa, siirtäkää yleiset assertiomallit apufunktioihin. Näin testeistä tulee lyhyempiä, luettavampia ja helpommin ylläpidettäviä, kun agentin vastausmuoto muuttuu.

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')

Osaamisen tarkistus: Assertioihin perustuva agenttien testaus

Testatkaa, miten hyvin hallitsette agenttitestien assertiostrategiat.

Kertaus: Assertioihin perustuva agenttien testaus

Teillä on nyt kattava assertiotyökalupakki agenttitestejä varten:

  • Tarkistakaa, että tool_calls ei ole tyhjä, kun agentin pitäisi käyttää työkalua
  • Tarkistakaa oikea työkalun nimi ehdolla tc.function.name == 'expected_tool'
  • Validoikaa työkalun argumentit jäsentämällä tc.function.arguments JSON-muodossa
  • Käyttäkää jsonschema.validate()-funktiota jäsennellyn tulosteen validointiin
  • Käyttäkää avainsanojen esiintymisen tarkistuksia joustaviin tekstivastauksen assertioihin
  • Tarkistakaa silmukka-agenttien finish_reason ja vaiheiden määrät
  • Käyttäkää @pytest.mark.parametrize-koristetta useiden syöteskenaarioiden testaamiseen
Aloita maksutta

Opi Tekoälyagentit tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
60
Oppitunnit
239

Usein kysytyt kysymykset

Onko oppitunti ”Väitteisiin perustuva agenttien testaus” ilmainen?

Kyllä – oppitunnin ”Väitteisiin perustuva agenttien testaus” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Tekoälyagentit-kurssin, päivitä CoddyKit PROhon. Tekoälyagentit-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Väitteisiin perustuva agenttien testaus”?

Työkalukutsujen, välivaiheiden ja lopullisen tulosteen rakenteen tarkistaminen Harjoittelet Tekoälyagentit-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Tekoälyagentit-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Tekoälyagentit-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 3/4.

Kuinka kauan ”Väitteisiin perustuva agenttien testaus”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Tekoälyagentit-oppitunnilla?

Kyllä. Jokainen Tekoälyagentit-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Miksi agenttien testaaminen on erilaista
  2. LLM-kutsujen simulointi testeissä
  3. Väitteisiin perustuva agenttien testaus
  4. Agenttiputkien integraatiotestit
← Takaisin: Tekoälyagentit