aieval-py 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aieval_py-0.1.0/.github/workflows/publish.yml +34 -0
- aieval_py-0.1.0/.github/workflows/test.yml +45 -0
- aieval_py-0.1.0/.gitignore +64 -0
- aieval_py-0.1.0/IMPLEMENTATION_PLAN.md +187 -0
- aieval_py-0.1.0/LICENSE +0 -0
- aieval_py-0.1.0/PKG-INFO +200 -0
- aieval_py-0.1.0/PROJECT_DISCOVERY.md +1586 -0
- aieval_py-0.1.0/README.md +167 -0
- aieval_py-0.1.0/examples/01_basic_llm_output.py +77 -0
- aieval_py-0.1.0/examples/02_agent_tool_guardrail.py +74 -0
- aieval_py-0.1.0/examples/03_async_and_severity_routing.py +78 -0
- aieval_py-0.1.0/examples/04_semantic_judge_adapter.py +76 -0
- aieval_py-0.1.0/pyproject.toml +99 -0
- aieval_py-0.1.0/src/aieval/__init__.py +86 -0
- aieval_py-0.1.0/src/aieval/checks/__init__.py +51 -0
- aieval_py-0.1.0/src/aieval/checks/base.py +55 -0
- aieval_py-0.1.0/src/aieval/checks/constraints.py +243 -0
- aieval_py-0.1.0/src/aieval/checks/fields.py +127 -0
- aieval_py-0.1.0/src/aieval/checks/json_check.py +59 -0
- aieval_py-0.1.0/src/aieval/checks/schema.py +86 -0
- aieval_py-0.1.0/src/aieval/checks/tool_call.py +241 -0
- aieval_py-0.1.0/src/aieval/cli/__init__.py +3 -0
- aieval_py-0.1.0/src/aieval/cli/main.py +205 -0
- aieval_py-0.1.0/src/aieval/domain/__init__.py +13 -0
- aieval_py-0.1.0/src/aieval/domain/context.py +13 -0
- aieval_py-0.1.0/src/aieval/domain/failure.py +130 -0
- aieval_py-0.1.0/src/aieval/domain/result.py +65 -0
- aieval_py-0.1.0/src/aieval/py.typed +2 -0
- aieval_py-0.1.0/src/aieval/runner/__init__.py +16 -0
- aieval_py-0.1.0/src/aieval/runner/evaluator.py +184 -0
- aieval_py-0.1.0/src/aieval/runner/routing.py +72 -0
- aieval_py-0.1.0/src/aieval/semantic/__init__.py +3 -0
- aieval_py-0.1.0/src/aieval/semantic/protocol.py +35 -0
- aieval_py-0.1.0/tests/fixtures/golden_invalid_tool_call.json +14 -0
- aieval_py-0.1.0/tests/fixtures/golden_valid_tool_call.json +17 -0
- aieval_py-0.1.0/tests/test_cli.py +49 -0
- aieval_py-0.1.0/tests/test_cli_coverage.py +62 -0
- aieval_py-0.1.0/tests/unit/test_constraints_check.py +61 -0
- aieval_py-0.1.0/tests/unit/test_deep_coverage.py +119 -0
- aieval_py-0.1.0/tests/unit/test_domain.py +75 -0
- aieval_py-0.1.0/tests/unit/test_evaluator.py +104 -0
- aieval_py-0.1.0/tests/unit/test_fields_check.py +38 -0
- aieval_py-0.1.0/tests/unit/test_schema_check.py +57 -0
- aieval_py-0.1.0/tests/unit/test_tool_call_check.py +77 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
pypi-publish:
|
|
9
|
+
name: Build and publish Python ๐ distributions ๐ฆ to PyPI
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
environment: pypi
|
|
12
|
+
permissions:
|
|
13
|
+
id-token: write # Mandatory for PyPI Trusted Publishing (OIDC)
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Set up Python
|
|
19
|
+
uses: actions/setup-python@v5
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.12"
|
|
22
|
+
|
|
23
|
+
- name: Install build tooling
|
|
24
|
+
run: |
|
|
25
|
+
python -m pip install --upgrade pip
|
|
26
|
+
pip install build
|
|
27
|
+
|
|
28
|
+
- name: Build sdist and wheel
|
|
29
|
+
run: |
|
|
30
|
+
python -m build
|
|
31
|
+
|
|
32
|
+
- name: Publish to PyPI
|
|
33
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
34
|
+
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
name: Python ${{ matrix.python-version }} on ${{ matrix.os }}
|
|
12
|
+
runs-on: ${{ matrix.os }}
|
|
13
|
+
strategy:
|
|
14
|
+
fail-fast: false
|
|
15
|
+
matrix:
|
|
16
|
+
os: [ubuntu-latest]
|
|
17
|
+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
18
|
+
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
|
|
22
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
23
|
+
uses: actions/setup-python@v5
|
|
24
|
+
with:
|
|
25
|
+
python-version: ${{ matrix.python-version }}
|
|
26
|
+
cache: "pip"
|
|
27
|
+
|
|
28
|
+
- name: Install dependencies
|
|
29
|
+
run: |
|
|
30
|
+
python -m pip install --upgrade pip
|
|
31
|
+
pip install .[dev]
|
|
32
|
+
|
|
33
|
+
- name: Run Ruff Lint and Format Checks
|
|
34
|
+
run: |
|
|
35
|
+
ruff check src tests
|
|
36
|
+
ruff format --check src tests
|
|
37
|
+
|
|
38
|
+
- name: Run Mypy Type Check
|
|
39
|
+
run: |
|
|
40
|
+
mypy src
|
|
41
|
+
|
|
42
|
+
- name: Run Pytest with Coverage
|
|
43
|
+
run: |
|
|
44
|
+
pytest --cov=aieval --cov-report=term-missing --cov-fail-under=90
|
|
45
|
+
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# Virtual environments
|
|
30
|
+
.venv/
|
|
31
|
+
venv/
|
|
32
|
+
ENV/
|
|
33
|
+
env/
|
|
34
|
+
|
|
35
|
+
# Testing & Coverage
|
|
36
|
+
.tox/
|
|
37
|
+
.nox/
|
|
38
|
+
.coverage
|
|
39
|
+
.coverage.*
|
|
40
|
+
.cache
|
|
41
|
+
nosetests.xml
|
|
42
|
+
coverage.xml
|
|
43
|
+
*.cover
|
|
44
|
+
*.py,cover
|
|
45
|
+
.hypothesis/
|
|
46
|
+
.pytest_cache/
|
|
47
|
+
cover/
|
|
48
|
+
|
|
49
|
+
# Typing & Linting
|
|
50
|
+
.mypy_cache/
|
|
51
|
+
.dmypy.json
|
|
52
|
+
dmypy.json
|
|
53
|
+
.pyre/
|
|
54
|
+
.pytype/
|
|
55
|
+
.ruff_cache/
|
|
56
|
+
|
|
57
|
+
# IDE / Editor
|
|
58
|
+
.vscode/
|
|
59
|
+
.idea/
|
|
60
|
+
*.swp
|
|
61
|
+
*.swo
|
|
62
|
+
*~
|
|
63
|
+
.DS_Store
|
|
64
|
+
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# Implementation Plan: `aieval` (Python)
|
|
2
|
+
|
|
3
|
+
This document tracks the phased implementation plan for the Python counterpart of `aieval` (originally created in TypeScript as `@hamza1331/aieval`).
|
|
4
|
+
|
|
5
|
+
## Guiding Principles
|
|
6
|
+
- **Deterministic-First:** Prioritize zero-cost, sub-millisecond deterministic assertions over expensive, non-deterministic LLM calls.
|
|
7
|
+
- **Zero Bloat:** Minimal external dependencies. Python standard library wherever possible (`dataclasses`, `typing`, `enum`, `re`, `json`, `argparse`, `asyncio`), with `pydantic>=2.0.0` as the standard schema engine (equivalent to Zod in TS).
|
|
8
|
+
- **TypeScript Parity:** Exact equivalence in domain concepts, failure taxonomy codes, severity routing, and golden test fixture schemas.
|
|
9
|
+
- **Idiomatic Python 3.10+:** Dual sync/async execution (`evaluate()` / `aevaluate()`), immutable frozen dataclasses, strict typing (PEP 561 `py.typed`), and modern structural pattern matching/protocols.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Architecture Overview
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
aieval-py/
|
|
17
|
+
โโโ pyproject.toml # PEP 621 metadata, Hatchling build backend, dev deps
|
|
18
|
+
โโโ README.md
|
|
19
|
+
โโโ LICENSE
|
|
20
|
+
โโโ IMPLEMENTATION_PLAN.md
|
|
21
|
+
โโโ PROJECT_DISCOVERY.md
|
|
22
|
+
โโโ .gitignore
|
|
23
|
+
โโโ .github/
|
|
24
|
+
โ โโโ workflows/
|
|
25
|
+
โ โโโ test.yml # Matrix across Python 3.10, 3.11, 3.12, 3.13, 3.14
|
|
26
|
+
โ โโโ publish.yml # PyPI Trusted Publishing (OIDC) on release
|
|
27
|
+
โโโ src/
|
|
28
|
+
โโโ aieval/
|
|
29
|
+
โโโ __init__.py # Clean public exports (evaluate, aevaluate, checks, models)
|
|
30
|
+
โโโ py.typed # PEP 561 marker
|
|
31
|
+
โโโ domain/
|
|
32
|
+
โ โโโ __init__.py
|
|
33
|
+
โ โโโ failure.py # Failure, Severity, FailureCode
|
|
34
|
+
โ โโโ result.py # EvaluationResult, EvaluationSummary
|
|
35
|
+
โ โโโ context.py # EvaluationContext
|
|
36
|
+
โโโ checks/
|
|
37
|
+
โ โโโ __init__.py # Check Protocol & standard check exports
|
|
38
|
+
โ โโโ base.py # Protocol Check, CheckResult
|
|
39
|
+
โ โโโ schema.py # schema_check (Pydantic v2)
|
|
40
|
+
โ โโโ fields.py # required_fields, allowed_fields
|
|
41
|
+
โ โโโ constraints.py # regex_match, allowed_values, range_check, length_check
|
|
42
|
+
โ โโโ tool_call.py # tool_call_check, tool_call_check.one_of
|
|
43
|
+
โ โโโ json_check.py # valid_json check
|
|
44
|
+
โโโ semantic/
|
|
45
|
+
โ โโโ __init__.py
|
|
46
|
+
โ โโโ protocol.py # SemanticJudge Protocol (zero-dependency, optional)
|
|
47
|
+
โโโ runner/
|
|
48
|
+
โ โโโ __init__.py
|
|
49
|
+
โ โโโ evaluator.py # evaluate() & aevaluate() execution engines
|
|
50
|
+
โ โโโ routing.py # Severity threshold evaluation & summary calculation
|
|
51
|
+
โโโ cli/
|
|
52
|
+
โโโ __init__.py
|
|
53
|
+
โโโ main.py # `aieval run <fixture>` and `aieval check` CLI
|
|
54
|
+
โโโ tests/
|
|
55
|
+
โโโ conftest.py
|
|
56
|
+
โโโ unit/
|
|
57
|
+
โ โโโ test_failures.py
|
|
58
|
+
โ โโโ test_schema_check.py
|
|
59
|
+
โ โโโ test_fields_check.py
|
|
60
|
+
โ โโโ test_constraints_check.py
|
|
61
|
+
โ โโโ test_tool_call_check.py
|
|
62
|
+
โ โโโ test_evaluator_sync.py
|
|
63
|
+
โ โโโ test_evaluator_async.py
|
|
64
|
+
โ โโโ test_severity_routing.py
|
|
65
|
+
โโโ fixtures/
|
|
66
|
+
โ โโโ golden_valid_schema.json
|
|
67
|
+
โ โโโ golden_invalid_tool_call.json
|
|
68
|
+
โ โโโ golden_mixed_severities.json
|
|
69
|
+
โโโ test_cli.py
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Failure Code Taxonomy (Parity with TypeScript)
|
|
75
|
+
|
|
76
|
+
| Category | Failure Code | Description |
|
|
77
|
+
|---|---|---|
|
|
78
|
+
| **JSON / Structure** | `INVALID_JSON` | Output is not parseable JSON |
|
|
79
|
+
| **Schema** | `SCHEMA_VALIDATION_ERROR` | Failed Pydantic v2 validation |
|
|
80
|
+
| **Fields** | `MISSING_REQUIRED_FIELD` | Expected object key is absent |
|
|
81
|
+
| **Fields** | `UNEXPECTED_FIELD` | Key present outside allowed whitelist |
|
|
82
|
+
| **Constraints** | `REGEX_MISMATCH` | String does not match required regex pattern |
|
|
83
|
+
| **Constraints** | `ENUM_MISMATCH` | Value not in permitted set / enum |
|
|
84
|
+
| **Constraints** | `VALUE_CONSTRAINT_VIOLATION` | Numeric bounds or custom constraint violated |
|
|
85
|
+
| **Constraints** | `LENGTH_OUT_OF_BOUNDS` | String/list length outside min/max range |
|
|
86
|
+
| **Tool Calls** | `TOOL_CALL_UNKNOWN_TOOL` | Tool name not found in allowed list |
|
|
87
|
+
| **Tool Calls** | `TOOL_CALL_INVALID_ARGS_JSON` | Arguments string could not be parsed as JSON |
|
|
88
|
+
| **Tool Calls** | `TOOL_CALL_MISSING_REQUIRED_ARG` | Required argument missing from tool call |
|
|
89
|
+
| **Tool Calls** | `TOOL_CALL_ARG_TYPE_MISMATCH` | Tool argument failed type or schema check |
|
|
90
|
+
| **Tool Calls** | `TOOL_CALL_UNEXPECTED_ARG` | Tool argument was not in expected schema |
|
|
91
|
+
| **Semantic (Advisory)** | `SEMANTIC_JUDGE_SCORE_LOW` | LLM judge score fell below required threshold |
|
|
92
|
+
| **Semantic (Advisory)** | `SEMANTIC_JUDGE_FAILED` | LLM judge execution failed or raised an error |
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Phased Implementation Roadmap
|
|
97
|
+
|
|
98
|
+
### Phase 1: Repository Setup & Packaging Baseline
|
|
99
|
+
- [x] Configure `pyproject.toml` (PEP 621, Hatchling build backend, Python `>=3.10`).
|
|
100
|
+
- [x] Declare runtime dependencies (`pydantic>=2.0.0`) and dev dependencies (`pytest`, `pytest-asyncio`, `pytest-cov`, `mypy`, `ruff`).
|
|
101
|
+
- [x] Set up package directory structure under `src/aieval`.
|
|
102
|
+
- [x] Add `py.typed` marker (PEP 561).
|
|
103
|
+
- [x] Add `.gitignore` for Python artifacts (`.venv`, `__pycache__`, `.pytest_cache`, `.mypy_cache`, `dist/`).
|
|
104
|
+
- [x] Configure `ruff` and `mypy` strict type checking rules.
|
|
105
|
+
|
|
106
|
+
### Phase 2: Core Domain Model & Failure Classification
|
|
107
|
+
- [x] Implement `Severity` enum (`INFO`, `WARNING`, `ERROR`, `CRITICAL`).
|
|
108
|
+
- [x] Implement `FailureCode` enum for all taxonomy codes.
|
|
109
|
+
- [x] Implement frozen dataclass `Failure`:
|
|
110
|
+
- `code: str | FailureCode`
|
|
111
|
+
- `message: str`
|
|
112
|
+
- `severity: Severity = Severity.ERROR`
|
|
113
|
+
- `path: str | tuple[str | int, ...] | None = None`
|
|
114
|
+
- `metadata: dict[str, Any] = field(default_factory=dict)`
|
|
115
|
+
- `suggested_repair: str | None = None`
|
|
116
|
+
- [x] Implement frozen dataclass `EvaluationSummary`:
|
|
117
|
+
- `total_checks: int`
|
|
118
|
+
- `passed_checks: int`
|
|
119
|
+
- `failed_checks: int`
|
|
120
|
+
- `warnings_count: int`
|
|
121
|
+
- `duration_ms: float`
|
|
122
|
+
- [x] Implement frozen dataclass `EvaluationResult`:
|
|
123
|
+
- `passed: bool`
|
|
124
|
+
- `failures: tuple[Failure, ...]`
|
|
125
|
+
- `warnings: tuple[Failure, ...]`
|
|
126
|
+
- `summary: EvaluationSummary`
|
|
127
|
+
- `to_dict()` and `raise_for_failures()` helper methods.
|
|
128
|
+
- [x] Implement `CheckResult` and `Check` Protocol (callable supporting `(output, context) -> CheckResult | Sequence[Failure]`).
|
|
129
|
+
- [x] Write unit tests for domain classes and serialization.
|
|
130
|
+
|
|
131
|
+
### Phase 3: Built-in Deterministic Checks
|
|
132
|
+
- [x] Implement `valid_json()` check (handles raw string and decodes safely).
|
|
133
|
+
- [x] Implement `schema_check(model: type[BaseModel] | TypeAdapter[T])`:
|
|
134
|
+
- Auto-parses JSON string if needed.
|
|
135
|
+
- Converts Pydantic `ValidationError.errors()` to clean `Failure` objects with dot-notation path strings.
|
|
136
|
+
- [x] Implement field checks:
|
|
137
|
+
- `required_fields(fields: Sequence[str])`
|
|
138
|
+
- `allowed_fields(fields: Sequence[str])`
|
|
139
|
+
- [x] Implement value constraint checks:
|
|
140
|
+
- `regex_match(pattern: str | re.Pattern)`
|
|
141
|
+
- `allowed_values(allowed: Collection[Any])`
|
|
142
|
+
- `numeric_range(min_val: float | None = None, max_val: float | None = None)`
|
|
143
|
+
- `length_bounds(min_len: int | None = None, max_len: int | None = None)`
|
|
144
|
+
- [x] Implement agent tool-call checks:
|
|
145
|
+
- Normalize `{name, arguments}` (OpenAI stringified or dict) and `{name, args}`.
|
|
146
|
+
- Check tool name against allowed list.
|
|
147
|
+
- Parse stringified JSON arguments safely.
|
|
148
|
+
- Validate tool argument presence, unexpected arguments, and Pydantic argument schemas.
|
|
149
|
+
- Support `tool_call_check.one_of([...])` for multi-tool options.
|
|
150
|
+
- [x] Write thorough unit tests for each check across valid and invalid inputs.
|
|
151
|
+
|
|
152
|
+
### Phase 4: Sync & Async Dual Evaluator Engine & Severity Routing
|
|
153
|
+
- [x] Implement severity routing logic:
|
|
154
|
+
- Default: `fail_on="error"` (only `ERROR` and `CRITICAL` cause `passed=False`).
|
|
155
|
+
- Strict mode: `fail_on="warning"` (`WARNING` also causes `passed=False`).
|
|
156
|
+
- [x] Implement synchronous evaluator:
|
|
157
|
+
- `evaluate(output: Any, checks: Sequence[Check], *, context: EvaluationContext | None = None, fail_on: str = "error") -> EvaluationResult`
|
|
158
|
+
- Guard: raise informative `EvaluationConfigError` if an asynchronous check is passed to synchronous `evaluate()`.
|
|
159
|
+
- [x] Implement asynchronous evaluator:
|
|
160
|
+
- `aevaluate(output: Any, checks: Sequence[Check | AsyncCheck], *, context: EvaluationContext | None = None, fail_on: str = "error") -> EvaluationResult`
|
|
161
|
+
- Concurrently runs checks using `asyncio.gather()`.
|
|
162
|
+
- [x] Implement optional, zero-dependency `SemanticJudge` Protocol:
|
|
163
|
+
- Allows injecting user-defined LLM evaluators.
|
|
164
|
+
- Produces advisory results (`SEMANTIC_JUDGE_SCORE_LOW` or `SEMANTIC_JUDGE_FAILED`).
|
|
165
|
+
- [x] Write unit and integration tests for sync/async evaluation and routing behavior.
|
|
166
|
+
|
|
167
|
+
### Phase 5: CLI & Golden Test Fixtures Parity
|
|
168
|
+
- [x] Implement CLI in `aieval.cli.main`:
|
|
169
|
+
- `aieval run <fixture.json>`: Runs validation on a test fixture.
|
|
170
|
+
- `aieval check <file.json> --specs <specs.json>`: Evaluates an arbitrary output against a check specification.
|
|
171
|
+
- Format human-friendly colored terminal output and support `--json` output flag.
|
|
172
|
+
- Return exit code `0` on pass, `1` on failure.
|
|
173
|
+
- [x] Create golden test fixtures in `tests/fixtures/` matching TypeScript fixture schemas.
|
|
174
|
+
- [x] Write CLI execution tests verifying stdout/stderr and exit codes.
|
|
175
|
+
|
|
176
|
+
### Phase 6: Documentation, CI/CD & PyPI Release Setup
|
|
177
|
+
- [x] Write comprehensive `README.md` with:
|
|
178
|
+
- Quickstart guide (sync and async).
|
|
179
|
+
- Pydantic v2 schema validation examples.
|
|
180
|
+
- Agent tool call validation examples.
|
|
181
|
+
- Custom check implementation guide.
|
|
182
|
+
- Comparison table / philosophy (deterministic vs semantic).
|
|
183
|
+
- [x] Set up GitHub Actions CI workflow (`.github/workflows/test.yml`):
|
|
184
|
+
- Matrix across Python 3.10, 3.11, 3.12, 3.13, 3.14.
|
|
185
|
+
- Enforce `ruff check`, `ruff format --check`, `mypy`, and `pytest --cov=aieval --cov-fail-under=90`.
|
|
186
|
+
- [x] Set up PyPI Trusted Publishing GitHub Actions workflow (`.github/workflows/publish.yml`).
|
|
187
|
+
- [x] Add `LICENSE` (MIT) and ensure package build verification (`hatch build` / `pip install -e .`).
|
aieval_py-0.1.0/LICENSE
ADDED
|
File without changes
|
aieval_py-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: aieval-py
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Deterministic-first runtime validation and reliability toolkit for LLM outputs and agent actions.
|
|
5
|
+
Project-URL: Homepage, https://github.com/hamza1331/aieval-py
|
|
6
|
+
Project-URL: Repository, https://github.com/hamza1331/aieval-py
|
|
7
|
+
Project-URL: Issues, https://github.com/hamza1331/aieval-py/issues
|
|
8
|
+
Author-email: Hamza <hamza@example.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: agent,ai,evaluation,guardrails,llm,pydantic,runtime-safety,validation
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
22
|
+
Classifier: Topic :: Software Development :: Testing
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Requires-Dist: pydantic>=2.0.0
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: mypy>=1.9.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: ruff>=0.4.0; extra == 'dev'
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# aieval
|
|
35
|
+
|
|
36
|
+
[](https://github.com/hamza1331/aieval-py/actions/workflows/test.yml)
|
|
37
|
+
[](https://pypi.org/project/aieval-py/)
|
|
38
|
+
[](https://pypi.org/project/aieval-py/)
|
|
39
|
+
[](https://opensource.org/licenses/MIT)
|
|
40
|
+
|
|
41
|
+
**Deterministic-first runtime validation and reliability toolkit for LLM outputs and agent actions.**
|
|
42
|
+
|
|
43
|
+
Catch predictable failures (schema violations, missing required keys, JSON format errors, invalid tool call args, policy constraints) in sub-millisecond execution **before** spending latency and money on semantic LLM-as-a-judge scoring.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Key Highlights
|
|
48
|
+
|
|
49
|
+
- โก **Deterministic First:** Cheap, fast assertions run before calling model judges.
|
|
50
|
+
- ๐ฆ **Zero Bloat:** Minimal external footprint (`pydantic>=2.0.0` as schema engine, pure Python standard library for the rest).
|
|
51
|
+
- ๐ **Dual Sync & Async:** Native support for synchronous scripts (`evaluate()`) and asynchronous pipelines (`await aevaluate()`).
|
|
52
|
+
- ๐ค **Agent Tool Call Pre-flight:** Validates function names, required arguments, type safety, and stringified JSON (OpenAI tool call format).
|
|
53
|
+
- ๐๏ธ **Severity Routing:** Flexible threshold routing (`fail_on="error"` vs strict `fail_on="warning"`).
|
|
54
|
+
- ๐งช **CLI & Golden Fixtures:** Run validation from the command line on JSON test fixtures (`aieval run <fixture.json>`).
|
|
55
|
+
- ๐ฏ **Full TypeScript Parity:** Shares the exact failure taxonomy, code conventions, and golden test formats with `@hamza1331/aieval`.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Installation
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pip install aieval-py
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Quickstart
|
|
68
|
+
|
|
69
|
+
### 1. Synchronous Output Evaluation
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
from aieval import evaluate, schema_check, required_fields
|
|
73
|
+
from pydantic import BaseModel, Field
|
|
74
|
+
|
|
75
|
+
class AnalysisReport(BaseModel):
|
|
76
|
+
summary: str
|
|
77
|
+
confidence_score: float = Field(ge=0.0, le=1.0)
|
|
78
|
+
tags: list[str]
|
|
79
|
+
|
|
80
|
+
llm_output = '{"summary": "All systems nominal", "confidence_score": 0.95, "tags": ["ops", "prod"]}'
|
|
81
|
+
|
|
82
|
+
result = evaluate(
|
|
83
|
+
output=llm_output,
|
|
84
|
+
checks=[
|
|
85
|
+
schema_check(AnalysisReport),
|
|
86
|
+
required_fields(["summary", "confidence_score"]),
|
|
87
|
+
],
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
if result.passed:
|
|
91
|
+
print(f"Passed in {result.summary.duration_ms}ms!")
|
|
92
|
+
else:
|
|
93
|
+
for failure in result.failures:
|
|
94
|
+
print(f"[{failure.code}] {failure.message} (path: {failure.path})")
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 2. Pre-flight Agent Tool Call Validation
|
|
98
|
+
|
|
99
|
+
Validate tool calls before execution to avoid runtime exceptions and agent failure loops:
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
from aieval import evaluate, tool_call_check
|
|
103
|
+
from pydantic import BaseModel
|
|
104
|
+
|
|
105
|
+
class SendEmailArgs(BaseModel):
|
|
106
|
+
recipient: str
|
|
107
|
+
subject: str
|
|
108
|
+
body: str
|
|
109
|
+
|
|
110
|
+
# Works with both native dicts and OpenAI stringified JSON arguments:
|
|
111
|
+
raw_tool_call = {
|
|
112
|
+
"name": "send_email",
|
|
113
|
+
"arguments": '{"recipient": "team@example.com", "subject": "Update"}'
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
result = evaluate(
|
|
117
|
+
output=raw_tool_call,
|
|
118
|
+
checks=[
|
|
119
|
+
tool_call_check("send_email", schema=SendEmailArgs, required_args=["body"]),
|
|
120
|
+
]
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
print(result.passed) # False - missing required argument 'body'
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 3. Asynchronous Pipeline (`aevaluate`)
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
import asyncio
|
|
130
|
+
from aieval import aevaluate, valid_json, regex_match
|
|
131
|
+
|
|
132
|
+
async def main():
|
|
133
|
+
result = await aevaluate(
|
|
134
|
+
output="Order #12345 confirmed.",
|
|
135
|
+
checks=[
|
|
136
|
+
regex_match(r"Order #\d+"),
|
|
137
|
+
],
|
|
138
|
+
)
|
|
139
|
+
print("Passed:", result.passed)
|
|
140
|
+
|
|
141
|
+
asyncio.run(main())
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## CLI Usage
|
|
147
|
+
|
|
148
|
+
### Run Golden Test Fixtures
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
aieval run path/to/fixture.json
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Or output raw JSON:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
aieval run path/to/fixture.json --json
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Check Arbitrary Files
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
aieval check output.json --specs checks.json
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Failure Code Taxonomy
|
|
169
|
+
|
|
170
|
+
| Code | Category | Description |
|
|
171
|
+
|---|---|---|
|
|
172
|
+
| `INVALID_JSON` | Syntax | Output string is not parseable JSON |
|
|
173
|
+
| `SCHEMA_VALIDATION_ERROR` | Schema | Failed Pydantic v2 schema validation |
|
|
174
|
+
| `MISSING_REQUIRED_FIELD` | Fields | Missing expected key |
|
|
175
|
+
| `UNEXPECTED_FIELD` | Fields | Extra key outside allowed whitelist |
|
|
176
|
+
| `REGEX_MISMATCH` | Constraints | Pattern regex search failed |
|
|
177
|
+
| `ENUM_MISMATCH` | Constraints | Value not in permitted set |
|
|
178
|
+
| `VALUE_CONSTRAINT_VIOLATION` | Constraints | Range or boundary violation |
|
|
179
|
+
| `LENGTH_OUT_OF_BOUNDS` | Constraints | Length outside min/max range |
|
|
180
|
+
| `TOOL_CALL_UNKNOWN_TOOL` | Tool Calls | Unknown tool invoked |
|
|
181
|
+
| `TOOL_CALL_INVALID_ARGS_JSON`| Tool Calls | Arguments string is invalid JSON |
|
|
182
|
+
| `TOOL_CALL_MISSING_REQUIRED_ARG` | Tool Calls | Required argument missing |
|
|
183
|
+
| `TOOL_CALL_ARG_TYPE_MISMATCH`| Tool Calls | Argument schema check failed |
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Examples
|
|
188
|
+
|
|
189
|
+
Runnable walkthrough scripts are available in the [`examples/`](examples) directory:
|
|
190
|
+
|
|
191
|
+
- [`01_basic_llm_output.py`](examples/01_basic_llm_output.py): Schema and field constraint validation on LLM output.
|
|
192
|
+
- [`02_agent_tool_guardrail.py`](examples/02_agent_tool_guardrail.py): Agent tool call pre-flight validation (OpenAI stringified arguments & multi-tool selection).
|
|
193
|
+
- [`03_async_and_severity_routing.py`](examples/03_async_and_severity_routing.py): Asynchronous concurrent pipeline with severity routing.
|
|
194
|
+
- [`04_semantic_judge_adapter.py`](examples/04_semantic_judge_adapter.py): Integrating advisory LLM-as-a-judge checks via `SemanticJudge`.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## License
|
|
199
|
+
|
|
200
|
+
MIT
|