- Python 100%
| assets | ||
| docs | ||
| schemas | ||
| scripts | ||
| suites | ||
| tests | ||
| .gitignore | ||
| embeddings_runner.py | ||
| imagegen_runner.py | ||
| README.md | ||
| runner.py | ||
| stt_runner.py | ||
| tts_runner.py | ||
| vision_runner.py | ||
PCT Agent Benchmarks
Benchmark framework for testing PCT AI agents (VMIDs 200-206) against standardized test suites.
Overview
This framework evaluates agent performance across three key categories:
- Basic Reasoning: Mathematical problems, logical deduction, reading comprehension
- Tool Calling: Function calling format validation, parameter extraction, API interaction patterns
- Code Generation: Python, PowerShell, and bash snippet generation and correctness
Prerequisites
- Python 3.8+
requestslibrary (pip install requests)- Access to LiteLLM endpoint at
192.168.50.250:8000 - OpenAI-compatible API format
Running Benchmarks
Basic Usage
python runner.py --suite suites/basic-reasoning.json --endpoint http://192.168.50.250:8000
Options
--suite <path>: Path to suite JSON file (required)--endpoint <url>: LiteLLM endpoint URL (default:http://192.168.50.250:8000)--model <name>: Model name to use (default:gpt-4-turbo)--max-retries <n>: Maximum retries per test (default: 1)
Current modalities
- Text/inference benchmarks are runnable today via
runner.py - Embeddings are runnable via
embeddings_runner.pyand save schema-validated outputs throughsave_embeddings_results(...) - Vision benchmarks are runnable via
vision_runner.pyusing image inputs and schema-validated saved outputs - Speech-to-text benchmarks are runnable via
stt_runner.pyusing local audio assets, WER/word-accuracy scoring, and schema-validated saved outputs - Text-to-speech benchmarks are runnable via
tts_runner.pyusing prompt/voice matrices, timing metrics, and schema-validated saved outputs - Image-generation benchmarks are runnable via
imagegen_runner.pyusing prompt suites, saved PNG artifacts, and schema-validated saved outputs
Example
python runner.py --suite suites/tool-calling.json --endpoint http://192.168.50.250:8000 --model gpt-4
Embeddings examples
python embeddings_runner.py --suite suites/embeddings-retrieval.json --endpoint http://192.168.50.250:8000 --model nomic-embed-text-v2-moe-GGUF --embedding-dim 768 --index-time-s 5.57
python embeddings_runner.py --suite suites/embeddings-retrieval-canonical.json --endpoint http://192.168.50.250:8000 --model nomic-embed-text-v2-moe-GGUF --embedding-dim 768 --index-time-s 5.57 --historical-metrics-file ../infra-ai/benchmarking/embed-2026-03-04.json
Vision examples
# Current local benchmark waves run VLM suites against the main endpoint on :8000.
# A separate :8081 vision endpoint may not be present on every host.
python vision_runner.py --suite suites/vision-basic.json --endpoint http://192.168.50.250:8000 --model Qwen3-VL-4B-Instruct-GGUF
python vision_runner.py --suite suites/vision-ocr.json --endpoint http://192.168.50.250:8000 --model Qwen3-VL-4B-Instruct-GGUF
python vision_runner.py --suite suites/vision-ui.json --endpoint http://192.168.50.250:8000 --model Qwen3-VL-4B-Instruct-GGUF
python vision_runner.py --suite suites/vision-diagram.json --endpoint http://192.168.50.250:8000 --model Qwen3-VL-4B-Instruct-GGUF
python vision_runner.py --suite suites/vision-ticket-attachments.json --endpoint http://192.168.50.250:8000 --model Qwen3-VL-4B-Instruct-GGUF
python vision_runner.py --suite suites/vision-document-classification.json --endpoint http://192.168.50.250:8000 --model Qwen3-VL-4B-Instruct-GGUF
STT example
python stt_runner.py --suite suites/stt-basic.json --endpoint http://192.168.50.250:8000 --model Whisper-Base --chunk-seconds 25
TTS example
python tts_runner.py --suite suites/tts-basic.json --endpoint http://192.168.50.250:8000 --model kokoro-v1
Image generation examples
# Turbo preview models only
python imagegen_runner.py --suite suites/imagegen-basic.json --endpoint http://192.168.50.250:8000 --model SD-Turbo
# SD-1.5 quality rerun
python imagegen_runner.py --suite suites/imagegen-quality-rerun.json --endpoint http://192.168.50.250:8000 --model SD-1.5
# SDXL base quality rerun
python imagegen_runner.py --suite suites/imagegen-quality-rerun-sdxl.json --endpoint http://192.168.50.250:8000 --model SDXL-Base-1.0
Suite Format
Each suite is a JSON array of test case objects:
[
{
"id": "test_001",
"prompt": "What is 2 + 2?",
"expected_contains": ["4"],
"max_tokens": 100,
"category": "basic-reasoning"
}
]
Test Case Fields
| Field | Type | Description |
|---|---|---|
id |
string | Unique test identifier |
prompt |
string | Input prompt to send to agent |
expected_contains |
array | At least one string must appear in response (OR condition) |
expected_all_contains |
array | All listed strings must appear in response |
exact_match |
string | Response must exactly match this value after trim |
regex_match |
string | Python regex that must match the response |
forbidden_contains |
array | Strings that must not appear in response |
tool_call |
object | Structured tool-call expectation with name, arguments, optional forbidden_arguments, and optional forbid_extra_arguments |
code |
object | Executable code validation config with language and exec |
max_tokens |
integer | Maximum tokens for response |
category |
string | Test category (basic-reasoning, tool-calling, code-generation) |
You can combine assertion styles in one test case. All supplied checks must pass.
Results
Saved results now use a structured layout:
results/
YYYY-MM-DD/
<suite-name>/
<suite-name>-YYYYMMDD_HHMMSS.json
Before writing a result file, the runner validates the payload against:
schemas/benchmark-run.schema.jsonschemas/inference.schema.json
It also writes a convenience file at:
results/latest-summary.json
Schema files:
schemas/benchmark-run.schema.json— base canonical runner outputschemas/inference.schema.json— current text/inference benchmark schemaschemas/embeddings.schema.json— retrieval benchmark schema for the embeddings modalityschemas/vision.schema.json— dedicated schema for image-input vision benchmark runsschemas/stt.schema.json— dedicated schema for audio-input speech-to-text benchmark runsschemas/tts.schema.json— dedicated schema for text-to-speech benchmark runsschemas/imagegen.schema.json— dedicated schema for image-generation benchmark runs
Output format:
results/
2026-04-09/
basic-reasoning/
basic-reasoning-20260409_143022.json
Output format:
{
"suite": "basic-reasoning.json",
"model": "gpt-4-turbo",
"endpoint": "http://192.168.50.250:8000",
"timestamp": "2024-03-05T14:30:22Z",
"total_tests": 5,
"passed": 4,
"failed": 1,
"pass_rate": 80.0,
"total_prompt_tokens": 40,
"total_completion_tokens": 17,
"total_tokens": 57,
"total_wall_s": 1.75,
"avg_wall_s": 0.35,
"avg_tps": 18.7,
"results": [
{
"id": "test_001",
"category": "basic-reasoning",
"prompt": "What is 2 + 2?",
"passed": true,
"response": "2 + 2 equals 4.",
"expected_contains": ["4"],
"expected_all_contains": [],
"exact_match": null,
"regex_match": null,
"forbidden_contains": [],
"matched_strings": ["4"],
"matched_all_strings": [],
"forbidden_found": [],
"exact_match_passed": null,
"regex_match_passed": null,
"finish_reason": "stop",
"prompt_tokens": 9,
"completion_tokens": 5,
"total_tokens": 14,
"wall_s": 0.25,
"tps": 20.0,
"error": null
}
]
}
Additional telemetry captured when the endpoint returns it:
- Per test:
finish_reasonprompt_tokenscompletion_tokenstotal_tokenswall_s— end-to-end request wall timetps— derived completion tokens per seconderror— timeout/HTTP/connection classification when the request failstool_call_passed/tool_call_errorfor structured JSON tool-call checkscode_validation_passed/code_validation_errorfor executable code checks
- Per suite:
total_prompt_tokenstotal_completion_tokenstotal_tokenstotal_wall_savg_wall_savg_tps
- Convenience summary output:
results/latest-summary.json- contains latest run path, suite, model, pass rate, and aggregate timing fields
Infrastructure
Containers & VMIDs
- VMID 205: Ephemeral sandbox environment
- VMID 206: Secondary ephemeral sandbox
- VMIDs 200-204: Agent instances
LiteLLM Endpoint
Runs on 192.168.50.250:8000 with OpenAI-compatible API format.
Supports standard OpenAI parameters:
model: Model identifiermessages: Chat message formatmax_tokens: Response length limittemperature: Sampling temperature (0.0-2.0)
Troubleshooting
Connection Refused
Verify LiteLLM service is running and endpoint is accessible:
curl -I http://192.168.50.250:8000/health
Invalid JSON Response
Check that the endpoint is returning proper JSON format. LiteLLM should return:
{
"choices": [
{
"message": {
"content": "response text"
}
}
]
}
Files
runner.py- Main text/inference benchmark runner scriptembeddings_runner.py- Embeddings retrieval benchmark runnervision_runner.py- Vision benchmark runner for image-input evaluationsuites/basic-reasoning.json- Basic reasoning test casessuites/tool-calling.json- Tool calling test casessuites/code-generation.json- Code generation test casessuites/embeddings-retrieval.json- Suite skeleton for embeddings retrieval benchmarkssuites/vision-basic.json- Starter suite for image-input vision benchmarksschemas/- JSON schemas for benchmark result formatsdocs/embeddings-format.md- Embeddings benchmark format and implementation target.gitignore- Ignores Python cache files and generatedresults/results/- Output directory for benchmark results