pydantic-evals 0.4.3__py3-none-any.whl → 0.4.5__py3-none-any.whl
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.
Potentially problematic release.
This version of pydantic-evals might be problematic. Click here for more details.
- pydantic_evals/evaluators/llm_as_a_judge.py +45 -52
- pydantic_evals/generation.py +2 -2
- {pydantic_evals-0.4.3.dist-info → pydantic_evals-0.4.5.dist-info}/METADATA +8 -8
- {pydantic_evals-0.4.3.dist-info → pydantic_evals-0.4.5.dist-info}/RECORD +6 -6
- {pydantic_evals-0.4.3.dist-info → pydantic_evals-0.4.5.dist-info}/WHEEL +0 -0
- {pydantic_evals-0.4.3.dist-info → pydantic_evals-0.4.5.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from collections.abc import Sequence
|
|
3
4
|
from textwrap import dedent
|
|
4
5
|
from typing import Any
|
|
5
6
|
|
|
@@ -7,6 +8,7 @@ from pydantic import BaseModel, Field
|
|
|
7
8
|
from pydantic_core import to_json
|
|
8
9
|
|
|
9
10
|
from pydantic_ai import Agent, models
|
|
11
|
+
from pydantic_ai.messages import MultiModalContentTypes, UserContent
|
|
10
12
|
from pydantic_ai.settings import ModelSettings
|
|
11
13
|
|
|
12
14
|
__all__ = (
|
|
@@ -62,16 +64,7 @@ async def judge_output(
|
|
|
62
64
|
If the model is not specified, a default model is used. The default model starts as 'openai:gpt-4o',
|
|
63
65
|
but this can be changed using the `set_default_judge_model` function.
|
|
64
66
|
"""
|
|
65
|
-
user_prompt =
|
|
66
|
-
f"""
|
|
67
|
-
<Output>
|
|
68
|
-
{_stringify(output)}
|
|
69
|
-
</Output>
|
|
70
|
-
<Rubric>
|
|
71
|
-
{rubric}
|
|
72
|
-
</Rubric>
|
|
73
|
-
"""
|
|
74
|
-
)
|
|
67
|
+
user_prompt = _build_prompt(output=output, rubric=rubric)
|
|
75
68
|
return (
|
|
76
69
|
await _judge_output_agent.run(user_prompt, model=model or _default_model, model_settings=model_settings)
|
|
77
70
|
).output
|
|
@@ -112,19 +105,8 @@ async def judge_input_output(
|
|
|
112
105
|
If the model is not specified, a default model is used. The default model starts as 'openai:gpt-4o',
|
|
113
106
|
but this can be changed using the `set_default_judge_model` function.
|
|
114
107
|
"""
|
|
115
|
-
user_prompt =
|
|
116
|
-
|
|
117
|
-
<Input>
|
|
118
|
-
{_stringify(inputs)}
|
|
119
|
-
</Input>
|
|
120
|
-
<Output>
|
|
121
|
-
{_stringify(output)}
|
|
122
|
-
</Output>
|
|
123
|
-
<Rubric>
|
|
124
|
-
{rubric}
|
|
125
|
-
</Rubric>
|
|
126
|
-
"""
|
|
127
|
-
)
|
|
108
|
+
user_prompt = _build_prompt(inputs=inputs, output=output, rubric=rubric)
|
|
109
|
+
|
|
128
110
|
return (
|
|
129
111
|
await _judge_input_output_agent.run(user_prompt, model=model or _default_model, model_settings=model_settings)
|
|
130
112
|
).output
|
|
@@ -168,22 +150,7 @@ async def judge_input_output_expected(
|
|
|
168
150
|
If the model is not specified, a default model is used. The default model starts as 'openai:gpt-4o',
|
|
169
151
|
but this can be changed using the `set_default_judge_model` function.
|
|
170
152
|
"""
|
|
171
|
-
user_prompt =
|
|
172
|
-
f"""
|
|
173
|
-
<Input>
|
|
174
|
-
{_stringify(inputs)}
|
|
175
|
-
</Input>
|
|
176
|
-
<ExpectedOutput>
|
|
177
|
-
{_stringify(expected_output)}
|
|
178
|
-
</ExpectedOutput>
|
|
179
|
-
<Output>
|
|
180
|
-
{_stringify(output)}
|
|
181
|
-
</Output>
|
|
182
|
-
<Rubric>
|
|
183
|
-
{rubric}
|
|
184
|
-
</Rubric>
|
|
185
|
-
"""
|
|
186
|
-
)
|
|
153
|
+
user_prompt = _build_prompt(inputs=inputs, output=output, rubric=rubric, expected_output=expected_output)
|
|
187
154
|
|
|
188
155
|
return (
|
|
189
156
|
await _judge_input_output_expected_agent.run(
|
|
@@ -227,19 +194,7 @@ async def judge_output_expected(
|
|
|
227
194
|
If the model is not specified, a default model is used. The default model starts as 'openai:gpt-4o',
|
|
228
195
|
but this can be changed using the `set_default_judge_model` function.
|
|
229
196
|
"""
|
|
230
|
-
user_prompt =
|
|
231
|
-
f"""
|
|
232
|
-
<ExpectedOutput>
|
|
233
|
-
{_stringify(expected_output)}
|
|
234
|
-
</ExpectedOutput>
|
|
235
|
-
<Output>
|
|
236
|
-
{_stringify(output)}
|
|
237
|
-
</Output>
|
|
238
|
-
<Rubric>
|
|
239
|
-
{rubric}
|
|
240
|
-
</Rubric>
|
|
241
|
-
"""
|
|
242
|
-
)
|
|
197
|
+
user_prompt = _build_prompt(output=output, rubric=rubric, expected_output=expected_output)
|
|
243
198
|
return (
|
|
244
199
|
await _judge_output_expected_agent.run(
|
|
245
200
|
user_prompt, model=model or _default_model, model_settings=model_settings
|
|
@@ -265,3 +220,41 @@ def _stringify(value: Any) -> str:
|
|
|
265
220
|
return to_json(value).decode()
|
|
266
221
|
except Exception:
|
|
267
222
|
return repr(value)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def _build_prompt(
|
|
226
|
+
output: Any,
|
|
227
|
+
rubric: str,
|
|
228
|
+
inputs: Any | None = None,
|
|
229
|
+
expected_output: Any | None = None,
|
|
230
|
+
) -> str | Sequence[str | UserContent]:
|
|
231
|
+
"""Build a prompt that includes input, output, and rubric."""
|
|
232
|
+
sections: list[str | UserContent] = []
|
|
233
|
+
|
|
234
|
+
if inputs is not None:
|
|
235
|
+
if isinstance(inputs, str):
|
|
236
|
+
sections.append(f'<Input>\n{inputs}\n</Input>')
|
|
237
|
+
else:
|
|
238
|
+
sections.append('<Input>\n')
|
|
239
|
+
if isinstance(inputs, Sequence):
|
|
240
|
+
for item in inputs: # type: ignore
|
|
241
|
+
if isinstance(item, (str, MultiModalContentTypes)):
|
|
242
|
+
sections.append(item)
|
|
243
|
+
else:
|
|
244
|
+
sections.append(_stringify(item))
|
|
245
|
+
elif isinstance(inputs, MultiModalContentTypes):
|
|
246
|
+
sections.append(inputs)
|
|
247
|
+
else:
|
|
248
|
+
sections.append(_stringify(inputs))
|
|
249
|
+
sections.append('</Input>')
|
|
250
|
+
|
|
251
|
+
sections.append(f'<Output>\n{_stringify(output)}\n</Output>')
|
|
252
|
+
sections.append(f'<Rubric>\n{rubric}\n</Rubric>')
|
|
253
|
+
|
|
254
|
+
if expected_output is not None:
|
|
255
|
+
sections.append(f'<ExpectedOutput>\n{_stringify(expected_output)}\n</ExpectedOutput>')
|
|
256
|
+
|
|
257
|
+
if inputs is None or isinstance(inputs, str):
|
|
258
|
+
return '\n\n'.join(sections) # type: ignore[arg-type]
|
|
259
|
+
else:
|
|
260
|
+
return sections
|
pydantic_evals/generation.py
CHANGED
|
@@ -47,7 +47,7 @@ async def generate_dataset(
|
|
|
47
47
|
path: Optional path to save the generated dataset. If provided, the dataset will be saved to this location.
|
|
48
48
|
dataset_type: The type of dataset to generate, with the desired input, output, and metadata types.
|
|
49
49
|
custom_evaluator_types: Optional sequence of custom evaluator classes to include in the schema.
|
|
50
|
-
model: The
|
|
50
|
+
model: The Pydantic AI model to use for generation. Defaults to 'gpt-4o'.
|
|
51
51
|
n_examples: Number of examples to generate. Defaults to 3.
|
|
52
52
|
extra_instructions: Optional additional instructions to provide to the LLM.
|
|
53
53
|
|
|
@@ -59,7 +59,7 @@ async def generate_dataset(
|
|
|
59
59
|
"""
|
|
60
60
|
output_schema = dataset_type.model_json_schema_with_evaluators(custom_evaluator_types)
|
|
61
61
|
|
|
62
|
-
# TODO(DavidM): Update this once we add better response_format and/or ResultTool support to
|
|
62
|
+
# TODO(DavidM): Update this once we add better response_format and/or ResultTool support to Pydantic AI
|
|
63
63
|
agent = Agent(
|
|
64
64
|
model,
|
|
65
65
|
system_prompt=(
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pydantic-evals
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.5
|
|
4
4
|
Summary: Framework for evaluating stochastic code execution, especially code making use of LLMs
|
|
5
5
|
Project-URL: Homepage, https://ai.pydantic.dev/evals
|
|
6
6
|
Project-URL: Source, https://github.com/pydantic/pydantic-ai
|
|
7
7
|
Project-URL: Documentation, https://ai.pydantic.dev/evals
|
|
8
8
|
Project-URL: Changelog, https://github.com/pydantic/pydantic-ai/releases
|
|
9
|
-
Author-email: David Montague <david@pydantic.dev>
|
|
9
|
+
Author-email: Samuel Colvin <samuel@pydantic.dev>, Marcelo Trylesinski <marcelotryle@gmail.com>, David Montague <david@pydantic.dev>, Alex Hall <alex@pydantic.dev>, Douwe Maan <douwe@pydantic.dev>
|
|
10
10
|
License-Expression: MIT
|
|
11
11
|
License-File: LICENSE
|
|
12
12
|
Classifier: Development Status :: 4 - Beta
|
|
@@ -32,7 +32,7 @@ Requires-Python: >=3.9
|
|
|
32
32
|
Requires-Dist: anyio>=0
|
|
33
33
|
Requires-Dist: eval-type-backport>=0; python_version < '3.11'
|
|
34
34
|
Requires-Dist: logfire-api>=1.2.0
|
|
35
|
-
Requires-Dist: pydantic-ai-slim==0.4.
|
|
35
|
+
Requires-Dist: pydantic-ai-slim==0.4.5
|
|
36
36
|
Requires-Dist: pydantic>=2.10
|
|
37
37
|
Requires-Dist: pyyaml>=6.0.2
|
|
38
38
|
Requires-Dist: rich>=13.9.4
|
|
@@ -51,18 +51,18 @@ Description-Content-Type: text/markdown
|
|
|
51
51
|
This is a library for evaluating non-deterministic (or "stochastic") functions in Python. It provides a simple,
|
|
52
52
|
Pythonic interface for defining and running stochastic functions, and analyzing the results of running those functions.
|
|
53
53
|
|
|
54
|
-
While this library is developed as part of [
|
|
54
|
+
While this library is developed as part of [Pydantic AI](https://ai.pydantic.dev), it only uses Pydantic AI for a small
|
|
55
55
|
subset of generative functionality internally, and it is designed to be used with arbitrary "stochastic function"
|
|
56
|
-
implementations. In particular, it can be used with other (non-
|
|
56
|
+
implementations. In particular, it can be used with other (non-Pydantic AI) AI libraries, agent frameworks, etc.
|
|
57
57
|
|
|
58
|
-
As with
|
|
58
|
+
As with Pydantic AI, this library prioritizes type safety and use of common Python syntax over esoteric, domain-specific
|
|
59
59
|
use of Python syntax.
|
|
60
60
|
|
|
61
61
|
Full documentation is available at [ai.pydantic.dev/evals](https://ai.pydantic.dev/evals).
|
|
62
62
|
|
|
63
63
|
## Example
|
|
64
64
|
|
|
65
|
-
While you'd typically use Pydantic Evals with more complex functions (such as
|
|
65
|
+
While you'd typically use Pydantic Evals with more complex functions (such as Pydantic AI agents or graphs), here's a
|
|
66
66
|
quick example that evaluates a simple function against a test case using both custom and built-in evaluators:
|
|
67
67
|
|
|
68
68
|
```python
|
|
@@ -110,7 +110,7 @@ report.print(include_input=True, include_output=True)
|
|
|
110
110
|
"""
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
-
Using the library with more complex functions, such as
|
|
113
|
+
Using the library with more complex functions, such as Pydantic AI agents, is similar — all you need to do is define a
|
|
114
114
|
task function wrapping the function you want to evaluate, with a signature that matches the inputs and outputs of your
|
|
115
115
|
test cases.
|
|
116
116
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
pydantic_evals/__init__.py,sha256=OKRbfhdc8UZPzrPJMZUQwvzIxLhXmEZxz1ZuD921fy4,839
|
|
2
2
|
pydantic_evals/_utils.py,sha256=PfhmPbdQp-q90s568LuG45zDDXxgO13BEz8MQJK8qw4,2922
|
|
3
3
|
pydantic_evals/dataset.py,sha256=SY0k2htYG0d0KRRem3pnQdN7rPztJ_TCFnCb0zkXbCk,46477
|
|
4
|
-
pydantic_evals/generation.py,sha256
|
|
4
|
+
pydantic_evals/generation.py,sha256=Yd1rfbsDjjBBHDk-1KDu48hlITjM2-74rTnPBD_sqbA,3494
|
|
5
5
|
pydantic_evals/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
6
|
pydantic_evals/evaluators/__init__.py,sha256=uj110viFiDvqrIcuDcWexk_uBgJqhKMGPHT2YvDb7LA,624
|
|
7
7
|
pydantic_evals/evaluators/_run_evaluator.py,sha256=Dsnqxno7CrcKWYcnkLuwvPKWQGDRBmbBTwwstcmc0ak,2448
|
|
@@ -9,7 +9,7 @@ pydantic_evals/evaluators/_spec.py,sha256=Xi_FHwnmAZ1x2hoJFw4MBZuG0TilNKqMRW3P74
|
|
|
9
9
|
pydantic_evals/evaluators/common.py,sha256=ZBrNTfPJoOpT4WNXTRGS0UcKhnuhfYJxjNzum-zHFk8,12064
|
|
10
10
|
pydantic_evals/evaluators/context.py,sha256=8osQRCFW8Vekw7JiiOOCHHH3HOGdhDaUlr8i-twSetg,3870
|
|
11
11
|
pydantic_evals/evaluators/evaluator.py,sha256=yOEKLOxElm7_4tLcq6_myXI0e4Ei9svZP9y5DTq4SYI,11147
|
|
12
|
-
pydantic_evals/evaluators/llm_as_a_judge.py,sha256=
|
|
12
|
+
pydantic_evals/evaluators/llm_as_a_judge.py,sha256=xQjaGuCRXZdlExacFyR4Y4kFmwBh2QxAfEyaed_aqvk,9615
|
|
13
13
|
pydantic_evals/otel/__init__.py,sha256=i2p3vDrOW039N4XM-UkozDhCm0ZmE6ZSs1yV5t03vd0,117
|
|
14
14
|
pydantic_evals/otel/_context_in_memory_span_exporter.py,sha256=vIDF9-6lDuNKZuSM5hN_R8VRK4jzmdfe1DgWdXwxVbc,6758
|
|
15
15
|
pydantic_evals/otel/_context_subtree.py,sha256=Iazp4w3IIBMCrkqWL-hTG-2QG_-2X81p794WG9MAsGk,1175
|
|
@@ -17,7 +17,7 @@ pydantic_evals/otel/_errors.py,sha256=aW1414eTofpA7R_DUgOeT-gj7YA6OXmm8Y4oYeFukD
|
|
|
17
17
|
pydantic_evals/otel/span_tree.py,sha256=LV5Hsyo4riJzevHyBz8wxP82S-ry5zeKYi9bKWjGCS8,23057
|
|
18
18
|
pydantic_evals/reporting/__init__.py,sha256=k_3tteqXGh0yGvgpN68gB0CjG9wzrakzDTve2GHend4,42148
|
|
19
19
|
pydantic_evals/reporting/render_numbers.py,sha256=8SKlK3etbD7HnSWWHCE993ceCNLZCepVQ-SsqUIhyxk,6916
|
|
20
|
-
pydantic_evals-0.4.
|
|
21
|
-
pydantic_evals-0.4.
|
|
22
|
-
pydantic_evals-0.4.
|
|
23
|
-
pydantic_evals-0.4.
|
|
20
|
+
pydantic_evals-0.4.5.dist-info/METADATA,sha256=6axvUhXnQNjpGjtEIsUv2FHDNQnOQeBMEZmaqzfoo_s,7938
|
|
21
|
+
pydantic_evals-0.4.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
22
|
+
pydantic_evals-0.4.5.dist-info/licenses/LICENSE,sha256=vA6Jc482lEyBBuGUfD1pYx-cM7jxvLYOxPidZ30t_PQ,1100
|
|
23
|
+
pydantic_evals-0.4.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|