judgeval 0.0.11__py3-none-any.whl → 0.22.2__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 judgeval might be problematic. Click here for more details.
- judgeval/__init__.py +177 -12
- judgeval/api/__init__.py +519 -0
- judgeval/api/api_types.py +407 -0
- judgeval/cli.py +79 -0
- judgeval/constants.py +76 -47
- judgeval/data/__init__.py +3 -3
- judgeval/data/evaluation_run.py +125 -0
- judgeval/data/example.py +15 -56
- judgeval/data/judgment_types.py +450 -0
- judgeval/data/result.py +29 -73
- judgeval/data/scorer_data.py +29 -62
- judgeval/data/scripts/fix_default_factory.py +23 -0
- judgeval/data/scripts/openapi_transform.py +123 -0
- judgeval/data/trace.py +121 -0
- judgeval/dataset/__init__.py +264 -0
- judgeval/env.py +52 -0
- judgeval/evaluation/__init__.py +344 -0
- judgeval/exceptions.py +27 -0
- judgeval/integrations/langgraph/__init__.py +13 -0
- judgeval/integrations/openlit/__init__.py +50 -0
- judgeval/judges/__init__.py +2 -3
- judgeval/judges/base_judge.py +2 -3
- judgeval/judges/litellm_judge.py +100 -20
- judgeval/judges/together_judge.py +101 -20
- judgeval/judges/utils.py +20 -24
- judgeval/logger.py +62 -0
- judgeval/prompt/__init__.py +330 -0
- judgeval/scorers/__init__.py +18 -25
- judgeval/scorers/agent_scorer.py +17 -0
- judgeval/scorers/api_scorer.py +45 -41
- judgeval/scorers/base_scorer.py +83 -38
- judgeval/scorers/example_scorer.py +17 -0
- judgeval/scorers/exceptions.py +1 -0
- judgeval/scorers/judgeval_scorers/__init__.py +0 -148
- judgeval/scorers/judgeval_scorers/api_scorers/__init__.py +19 -17
- judgeval/scorers/judgeval_scorers/api_scorers/answer_correctness.py +13 -19
- judgeval/scorers/judgeval_scorers/api_scorers/answer_relevancy.py +12 -19
- judgeval/scorers/judgeval_scorers/api_scorers/faithfulness.py +13 -19
- judgeval/scorers/judgeval_scorers/api_scorers/instruction_adherence.py +15 -0
- judgeval/scorers/judgeval_scorers/api_scorers/prompt_scorer.py +327 -0
- judgeval/scorers/score.py +77 -306
- judgeval/scorers/utils.py +4 -199
- judgeval/tracer/__init__.py +1122 -2
- judgeval/tracer/constants.py +1 -0
- judgeval/tracer/exporters/__init__.py +40 -0
- judgeval/tracer/exporters/s3.py +119 -0
- judgeval/tracer/exporters/store.py +59 -0
- judgeval/tracer/exporters/utils.py +32 -0
- judgeval/tracer/keys.py +63 -0
- judgeval/tracer/llm/__init__.py +7 -0
- judgeval/tracer/llm/config.py +78 -0
- judgeval/tracer/llm/constants.py +9 -0
- judgeval/tracer/llm/llm_anthropic/__init__.py +3 -0
- judgeval/tracer/llm/llm_anthropic/config.py +6 -0
- judgeval/tracer/llm/llm_anthropic/messages.py +452 -0
- judgeval/tracer/llm/llm_anthropic/messages_stream.py +322 -0
- judgeval/tracer/llm/llm_anthropic/wrapper.py +59 -0
- judgeval/tracer/llm/llm_google/__init__.py +3 -0
- judgeval/tracer/llm/llm_google/config.py +6 -0
- judgeval/tracer/llm/llm_google/generate_content.py +127 -0
- judgeval/tracer/llm/llm_google/wrapper.py +30 -0
- judgeval/tracer/llm/llm_openai/__init__.py +3 -0
- judgeval/tracer/llm/llm_openai/beta_chat_completions.py +216 -0
- judgeval/tracer/llm/llm_openai/chat_completions.py +501 -0
- judgeval/tracer/llm/llm_openai/config.py +6 -0
- judgeval/tracer/llm/llm_openai/responses.py +506 -0
- judgeval/tracer/llm/llm_openai/utils.py +42 -0
- judgeval/tracer/llm/llm_openai/wrapper.py +63 -0
- judgeval/tracer/llm/llm_together/__init__.py +3 -0
- judgeval/tracer/llm/llm_together/chat_completions.py +406 -0
- judgeval/tracer/llm/llm_together/config.py +6 -0
- judgeval/tracer/llm/llm_together/wrapper.py +52 -0
- judgeval/tracer/llm/providers.py +19 -0
- judgeval/tracer/managers.py +167 -0
- judgeval/tracer/processors/__init__.py +220 -0
- judgeval/tracer/utils.py +19 -0
- judgeval/trainer/__init__.py +14 -0
- judgeval/trainer/base_trainer.py +122 -0
- judgeval/trainer/config.py +128 -0
- judgeval/trainer/console.py +144 -0
- judgeval/trainer/fireworks_trainer.py +396 -0
- judgeval/trainer/trainable_model.py +243 -0
- judgeval/trainer/trainer.py +70 -0
- judgeval/utils/async_utils.py +39 -0
- judgeval/utils/decorators/__init__.py +0 -0
- judgeval/utils/decorators/dont_throw.py +37 -0
- judgeval/utils/decorators/use_once.py +13 -0
- judgeval/utils/file_utils.py +97 -0
- judgeval/utils/guards.py +36 -0
- judgeval/utils/meta.py +27 -0
- judgeval/utils/project.py +15 -0
- judgeval/utils/serialize.py +253 -0
- judgeval/utils/testing.py +70 -0
- judgeval/utils/url.py +10 -0
- judgeval/utils/version_check.py +28 -0
- judgeval/utils/wrappers/README.md +3 -0
- judgeval/utils/wrappers/__init__.py +15 -0
- judgeval/utils/wrappers/immutable_wrap_async.py +74 -0
- judgeval/utils/wrappers/immutable_wrap_async_iterator.py +84 -0
- judgeval/utils/wrappers/immutable_wrap_sync.py +66 -0
- judgeval/utils/wrappers/immutable_wrap_sync_iterator.py +84 -0
- judgeval/utils/wrappers/mutable_wrap_async.py +67 -0
- judgeval/utils/wrappers/mutable_wrap_sync.py +67 -0
- judgeval/utils/wrappers/py.typed +0 -0
- judgeval/utils/wrappers/utils.py +35 -0
- judgeval/version.py +5 -0
- judgeval/warnings.py +4 -0
- judgeval-0.22.2.dist-info/METADATA +265 -0
- judgeval-0.22.2.dist-info/RECORD +112 -0
- judgeval-0.22.2.dist-info/entry_points.txt +2 -0
- judgeval/clients.py +0 -39
- judgeval/common/__init__.py +0 -8
- judgeval/common/exceptions.py +0 -28
- judgeval/common/logger.py +0 -189
- judgeval/common/tracer.py +0 -798
- judgeval/common/utils.py +0 -763
- judgeval/data/api_example.py +0 -111
- judgeval/data/datasets/__init__.py +0 -5
- judgeval/data/datasets/dataset.py +0 -286
- judgeval/data/datasets/eval_dataset_client.py +0 -193
- judgeval/data/datasets/ground_truth.py +0 -54
- judgeval/data/datasets/utils.py +0 -74
- judgeval/evaluation_run.py +0 -132
- judgeval/judges/mixture_of_judges.py +0 -248
- judgeval/judgment_client.py +0 -354
- judgeval/run_evaluation.py +0 -439
- judgeval/scorers/judgeval_scorer.py +0 -140
- judgeval/scorers/judgeval_scorers/api_scorers/contextual_precision.py +0 -19
- judgeval/scorers/judgeval_scorers/api_scorers/contextual_recall.py +0 -19
- judgeval/scorers/judgeval_scorers/api_scorers/contextual_relevancy.py +0 -22
- judgeval/scorers/judgeval_scorers/api_scorers/hallucination.py +0 -19
- judgeval/scorers/judgeval_scorers/api_scorers/json_correctness.py +0 -32
- judgeval/scorers/judgeval_scorers/api_scorers/summarization.py +0 -20
- judgeval/scorers/judgeval_scorers/api_scorers/tool_correctness.py +0 -19
- judgeval/scorers/judgeval_scorers/classifiers/__init__.py +0 -3
- judgeval/scorers/judgeval_scorers/classifiers/text2sql/__init__.py +0 -3
- judgeval/scorers/judgeval_scorers/classifiers/text2sql/text2sql_scorer.py +0 -54
- judgeval/scorers/judgeval_scorers/local_implementations/__init__.py +0 -24
- judgeval/scorers/judgeval_scorers/local_implementations/answer_correctness/__init__.py +0 -4
- judgeval/scorers/judgeval_scorers/local_implementations/answer_correctness/answer_correctness_scorer.py +0 -277
- judgeval/scorers/judgeval_scorers/local_implementations/answer_correctness/prompts.py +0 -169
- judgeval/scorers/judgeval_scorers/local_implementations/answer_relevancy/__init__.py +0 -4
- judgeval/scorers/judgeval_scorers/local_implementations/answer_relevancy/answer_relevancy_scorer.py +0 -298
- judgeval/scorers/judgeval_scorers/local_implementations/answer_relevancy/prompts.py +0 -174
- judgeval/scorers/judgeval_scorers/local_implementations/contextual_precision/__init__.py +0 -3
- judgeval/scorers/judgeval_scorers/local_implementations/contextual_precision/contextual_precision_scorer.py +0 -264
- judgeval/scorers/judgeval_scorers/local_implementations/contextual_precision/prompts.py +0 -106
- judgeval/scorers/judgeval_scorers/local_implementations/contextual_recall/__init__.py +0 -3
- judgeval/scorers/judgeval_scorers/local_implementations/contextual_recall/contextual_recall_scorer.py +0 -254
- judgeval/scorers/judgeval_scorers/local_implementations/contextual_recall/prompts.py +0 -142
- judgeval/scorers/judgeval_scorers/local_implementations/contextual_relevancy/__init__.py +0 -3
- judgeval/scorers/judgeval_scorers/local_implementations/contextual_relevancy/contextual_relevancy_scorer.py +0 -245
- judgeval/scorers/judgeval_scorers/local_implementations/contextual_relevancy/prompts.py +0 -121
- judgeval/scorers/judgeval_scorers/local_implementations/faithfulness/__init__.py +0 -3
- judgeval/scorers/judgeval_scorers/local_implementations/faithfulness/faithfulness_scorer.py +0 -325
- judgeval/scorers/judgeval_scorers/local_implementations/faithfulness/prompts.py +0 -268
- judgeval/scorers/judgeval_scorers/local_implementations/hallucination/__init__.py +0 -3
- judgeval/scorers/judgeval_scorers/local_implementations/hallucination/hallucination_scorer.py +0 -263
- judgeval/scorers/judgeval_scorers/local_implementations/hallucination/prompts.py +0 -104
- judgeval/scorers/judgeval_scorers/local_implementations/json_correctness/__init__.py +0 -5
- judgeval/scorers/judgeval_scorers/local_implementations/json_correctness/json_correctness_scorer.py +0 -134
- judgeval/scorers/judgeval_scorers/local_implementations/summarization/__init__.py +0 -3
- judgeval/scorers/judgeval_scorers/local_implementations/summarization/prompts.py +0 -247
- judgeval/scorers/judgeval_scorers/local_implementations/summarization/summarization_scorer.py +0 -550
- judgeval/scorers/judgeval_scorers/local_implementations/tool_correctness/__init__.py +0 -3
- judgeval/scorers/judgeval_scorers/local_implementations/tool_correctness/tool_correctness_scorer.py +0 -157
- judgeval/scorers/prompt_scorer.py +0 -439
- judgeval-0.0.11.dist-info/METADATA +0 -36
- judgeval-0.0.11.dist-info/RECORD +0 -84
- {judgeval-0.0.11.dist-info → judgeval-0.22.2.dist-info}/WHEEL +0 -0
- {judgeval-0.0.11.dist-info → judgeval-0.22.2.dist-info}/licenses/LICENSE.md +0 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import importlib.metadata
|
|
2
|
+
import httpx
|
|
3
|
+
import threading
|
|
4
|
+
from judgeval.logger import judgeval_logger
|
|
5
|
+
from judgeval.utils.decorators.use_once import use_once
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@use_once
|
|
9
|
+
def check_latest_version(package_name: str = "judgeval"):
|
|
10
|
+
def _check():
|
|
11
|
+
try:
|
|
12
|
+
current_version = importlib.metadata.version(package_name)
|
|
13
|
+
response = httpx.get(
|
|
14
|
+
f"https://pypi.org/pypi/{package_name}/json", timeout=2
|
|
15
|
+
)
|
|
16
|
+
latest_version = response.json()["info"]["version"]
|
|
17
|
+
|
|
18
|
+
if current_version != latest_version:
|
|
19
|
+
judgeval_logger.warning(
|
|
20
|
+
f"UPDATE AVAILABLE: You are using '{package_name}=={current_version}', "
|
|
21
|
+
f"but the latest version is '{latest_version}'. While this version is still supported, "
|
|
22
|
+
f"we recommend upgrading to avoid potential issues or missing features: "
|
|
23
|
+
f"`pip install --upgrade {package_name}`"
|
|
24
|
+
)
|
|
25
|
+
except Exception:
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
threading.Thread(target=_check, daemon=True).start()
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from .immutable_wrap_sync import immutable_wrap_sync
|
|
2
|
+
from .immutable_wrap_async import immutable_wrap_async
|
|
3
|
+
from .immutable_wrap_sync_iterator import immutable_wrap_sync_iterator
|
|
4
|
+
from .immutable_wrap_async_iterator import immutable_wrap_async_iterator
|
|
5
|
+
from .mutable_wrap_sync import mutable_wrap_sync
|
|
6
|
+
from .mutable_wrap_async import mutable_wrap_async
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"immutable_wrap_sync",
|
|
10
|
+
"immutable_wrap_async",
|
|
11
|
+
"immutable_wrap_sync_iterator",
|
|
12
|
+
"immutable_wrap_async_iterator",
|
|
13
|
+
"mutable_wrap_sync",
|
|
14
|
+
"mutable_wrap_async",
|
|
15
|
+
]
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
from functools import wraps
|
|
2
|
+
from typing import (
|
|
3
|
+
Awaitable,
|
|
4
|
+
Callable,
|
|
5
|
+
TypeVar,
|
|
6
|
+
Any,
|
|
7
|
+
Dict,
|
|
8
|
+
ParamSpec,
|
|
9
|
+
Concatenate,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
from judgeval.utils.decorators.dont_throw import dont_throw
|
|
13
|
+
|
|
14
|
+
P = ParamSpec("P")
|
|
15
|
+
R = TypeVar("R")
|
|
16
|
+
Ctx = Dict[str, Any]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _void_pre_hook(ctx: Ctx, *args: Any, **kwargs: Any) -> None:
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _void_post_hook(ctx: Ctx, result: Any) -> None:
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _void_error_hook(ctx: Ctx, error: Exception) -> None:
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _void_finally_hook(ctx: Ctx) -> None:
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def immutable_wrap_async(
|
|
36
|
+
func: Callable[P, Awaitable[R]],
|
|
37
|
+
/,
|
|
38
|
+
*,
|
|
39
|
+
pre_hook: Callable[Concatenate[Ctx, P], None] = _void_pre_hook,
|
|
40
|
+
post_hook: Callable[[Ctx, R], None] = _void_post_hook,
|
|
41
|
+
error_hook: Callable[[Ctx, Exception], None] = _void_error_hook,
|
|
42
|
+
finally_hook: Callable[[Ctx], None] = _void_finally_hook,
|
|
43
|
+
) -> Callable[P, Awaitable[R]]:
|
|
44
|
+
"""
|
|
45
|
+
Wraps an async function with lifecycle hooks.
|
|
46
|
+
|
|
47
|
+
- pre_hook: called before func with (ctx, *args, **kwargs) matching func's signature
|
|
48
|
+
- post_hook: called after successful func execution with (ctx, result)
|
|
49
|
+
- error_hook: called if func raises an exception with (ctx, error)
|
|
50
|
+
- finally_hook: called in finally block with (ctx)
|
|
51
|
+
|
|
52
|
+
The wrapped function's result is returned unchanged, and exceptions are re-raised.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
pre_hook = dont_throw(pre_hook)
|
|
56
|
+
post_hook = dont_throw(post_hook)
|
|
57
|
+
error_hook = dont_throw(error_hook)
|
|
58
|
+
finally_hook = dont_throw(finally_hook)
|
|
59
|
+
|
|
60
|
+
@wraps(func)
|
|
61
|
+
async def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
|
|
62
|
+
ctx: Ctx = {}
|
|
63
|
+
pre_hook(ctx, *args, **kwargs)
|
|
64
|
+
try:
|
|
65
|
+
result = await func(*args, **kwargs)
|
|
66
|
+
post_hook(ctx, result)
|
|
67
|
+
return result
|
|
68
|
+
except Exception as e:
|
|
69
|
+
error_hook(ctx, e)
|
|
70
|
+
raise
|
|
71
|
+
finally:
|
|
72
|
+
finally_hook(ctx)
|
|
73
|
+
|
|
74
|
+
return wrapper
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
from functools import wraps
|
|
2
|
+
from typing import (
|
|
3
|
+
Callable,
|
|
4
|
+
TypeVar,
|
|
5
|
+
Any,
|
|
6
|
+
Dict,
|
|
7
|
+
Mapping,
|
|
8
|
+
ParamSpec,
|
|
9
|
+
AsyncIterator,
|
|
10
|
+
Concatenate,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
from judgeval.utils.decorators.dont_throw import dont_throw
|
|
14
|
+
|
|
15
|
+
P = ParamSpec("P")
|
|
16
|
+
Y = TypeVar("Y")
|
|
17
|
+
Ctx = Dict[str, Any]
|
|
18
|
+
ImmCtx = Mapping[str, Any]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _void_pre_hook(ctx: Ctx, *args: Any, **kwargs: Any) -> None:
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _void_yield_hook(ctx: Ctx, value: Any) -> None:
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _void_post_hook(ctx: Ctx) -> None:
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _void_error_hook(ctx: Ctx, error: Exception) -> None:
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _void_finally_hook(ctx: Ctx) -> None:
|
|
38
|
+
pass
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def immutable_wrap_async_iterator(
|
|
42
|
+
func: Callable[P, AsyncIterator[Y]],
|
|
43
|
+
/,
|
|
44
|
+
*,
|
|
45
|
+
pre_hook: Callable[Concatenate[Ctx, P], None] = _void_pre_hook,
|
|
46
|
+
yield_hook: Callable[[Ctx, Y], None] = _void_yield_hook,
|
|
47
|
+
post_hook: Callable[[Ctx], None] = _void_post_hook,
|
|
48
|
+
error_hook: Callable[[Ctx, Exception], None] = _void_error_hook,
|
|
49
|
+
finally_hook: Callable[[Ctx], None] = _void_finally_hook,
|
|
50
|
+
) -> Callable[P, AsyncIterator[Y]]:
|
|
51
|
+
"""
|
|
52
|
+
Wraps an async iterator function with lifecycle hooks.
|
|
53
|
+
|
|
54
|
+
- pre_hook: called when iterator function is invoked with (ctx, *args, **kwargs) matching func's signature
|
|
55
|
+
- yield_hook: called after each yield with (ctx, yielded_value)
|
|
56
|
+
- post_hook: called when iterator completes successfully with (ctx)
|
|
57
|
+
- error_hook: called if iterator raises an exception with (ctx, error)
|
|
58
|
+
- finally_hook: called when iterator closes with (ctx)
|
|
59
|
+
|
|
60
|
+
The wrapped iterator yields values unchanged, and exceptions are re-raised.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
pre_hook = dont_throw(pre_hook)
|
|
64
|
+
yield_hook = dont_throw(yield_hook)
|
|
65
|
+
post_hook = dont_throw(post_hook)
|
|
66
|
+
error_hook = dont_throw(error_hook)
|
|
67
|
+
finally_hook = dont_throw(finally_hook)
|
|
68
|
+
|
|
69
|
+
@wraps(func)
|
|
70
|
+
async def wrapper(*args: P.args, **kwargs: P.kwargs) -> AsyncIterator[Y]:
|
|
71
|
+
ctx: Ctx = {}
|
|
72
|
+
pre_hook(ctx, *args, **kwargs)
|
|
73
|
+
try:
|
|
74
|
+
async for value in func(*args, **kwargs):
|
|
75
|
+
yield_hook(ctx, value)
|
|
76
|
+
yield value
|
|
77
|
+
post_hook(ctx)
|
|
78
|
+
except Exception as e:
|
|
79
|
+
error_hook(ctx, e)
|
|
80
|
+
raise
|
|
81
|
+
finally:
|
|
82
|
+
finally_hook(ctx)
|
|
83
|
+
|
|
84
|
+
return wrapper
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from functools import wraps
|
|
2
|
+
from typing import Callable, TypeVar, Any, Dict, ParamSpec, Concatenate
|
|
3
|
+
|
|
4
|
+
from judgeval.utils.decorators.dont_throw import dont_throw
|
|
5
|
+
|
|
6
|
+
P = ParamSpec("P")
|
|
7
|
+
R = TypeVar("R")
|
|
8
|
+
Ctx = Dict[str, Any]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _void_pre_hook(ctx: Ctx, *args: Any, **kwargs: Any) -> None:
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _void_post_hook(ctx: Ctx, result: Any) -> None:
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _void_error_hook(ctx: Ctx, error: Exception) -> None:
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _void_finally_hook(ctx: Ctx) -> None:
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def immutable_wrap_sync(
|
|
28
|
+
func: Callable[P, R],
|
|
29
|
+
/,
|
|
30
|
+
*,
|
|
31
|
+
pre_hook: Callable[Concatenate[Ctx, P], None] = _void_pre_hook,
|
|
32
|
+
post_hook: Callable[[Ctx, R], None] = _void_post_hook,
|
|
33
|
+
error_hook: Callable[[Ctx, Exception], None] = _void_error_hook,
|
|
34
|
+
finally_hook: Callable[[Ctx], None] = _void_finally_hook,
|
|
35
|
+
) -> Callable[P, R]:
|
|
36
|
+
"""
|
|
37
|
+
Wraps a function with lifecycle hooks.
|
|
38
|
+
|
|
39
|
+
- pre_hook: called before func with (ctx, *args, **kwargs) matching func's signature
|
|
40
|
+
- post_hook: called after successful func execution with (ctx, result)
|
|
41
|
+
- error_hook: called if func raises an exception with (ctx, error)
|
|
42
|
+
- finally_hook: called in finally block with (ctx)
|
|
43
|
+
|
|
44
|
+
The wrapped function's result is returned unchanged, and exceptions are re-raised.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
pre_hook = dont_throw(pre_hook)
|
|
48
|
+
post_hook = dont_throw(post_hook)
|
|
49
|
+
error_hook = dont_throw(error_hook)
|
|
50
|
+
finally_hook = dont_throw(finally_hook)
|
|
51
|
+
|
|
52
|
+
@wraps(func)
|
|
53
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
|
|
54
|
+
ctx: Ctx = {}
|
|
55
|
+
pre_hook(ctx, *args, **kwargs)
|
|
56
|
+
try:
|
|
57
|
+
result = func(*args, **kwargs)
|
|
58
|
+
post_hook(ctx, result)
|
|
59
|
+
return result
|
|
60
|
+
except Exception as e:
|
|
61
|
+
error_hook(ctx, e)
|
|
62
|
+
raise
|
|
63
|
+
finally:
|
|
64
|
+
finally_hook(ctx)
|
|
65
|
+
|
|
66
|
+
return wrapper
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
from functools import wraps
|
|
2
|
+
from typing import (
|
|
3
|
+
Callable,
|
|
4
|
+
TypeVar,
|
|
5
|
+
Any,
|
|
6
|
+
Dict,
|
|
7
|
+
Mapping,
|
|
8
|
+
ParamSpec,
|
|
9
|
+
Iterator,
|
|
10
|
+
Concatenate,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
from judgeval.utils.decorators.dont_throw import dont_throw
|
|
14
|
+
|
|
15
|
+
P = ParamSpec("P")
|
|
16
|
+
Y = TypeVar("Y")
|
|
17
|
+
Ctx = Dict[str, Any]
|
|
18
|
+
ImmCtx = Mapping[str, Any]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _void_pre_hook(ctx: Ctx, *args: Any, **kwargs: Any) -> None:
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _void_yield_hook(ctx: Ctx, value: Any) -> None:
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _void_post_hook(ctx: Ctx) -> None:
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _void_error_hook(ctx: Ctx, error: Exception) -> None:
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _void_finally_hook(ctx: Ctx) -> None:
|
|
38
|
+
pass
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def immutable_wrap_sync_iterator(
|
|
42
|
+
func: Callable[P, Iterator[Y]],
|
|
43
|
+
/,
|
|
44
|
+
*,
|
|
45
|
+
pre_hook: Callable[Concatenate[Ctx, P], None] = _void_pre_hook,
|
|
46
|
+
yield_hook: Callable[[Ctx, Y], None] = _void_yield_hook,
|
|
47
|
+
post_hook: Callable[[Ctx], None] = _void_post_hook,
|
|
48
|
+
error_hook: Callable[[Ctx, Exception], None] = _void_error_hook,
|
|
49
|
+
finally_hook: Callable[[Ctx], None] = _void_finally_hook,
|
|
50
|
+
) -> Callable[P, Iterator[Y]]:
|
|
51
|
+
"""
|
|
52
|
+
Wraps an iterator function with lifecycle hooks.
|
|
53
|
+
|
|
54
|
+
- pre_hook: called when iterator function is invoked with (ctx, *args, **kwargs) matching func's signature
|
|
55
|
+
- yield_hook: called after each yield with (ctx, yielded_value)
|
|
56
|
+
- post_hook: called when iterator completes successfully with (ctx)
|
|
57
|
+
- error_hook: called if iterator raises an exception with (ctx, error)
|
|
58
|
+
- finally_hook: called when iterator closes with (ctx)
|
|
59
|
+
|
|
60
|
+
The wrapped iterator yields values unchanged, and exceptions are re-raised.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
pre_hook = dont_throw(pre_hook)
|
|
64
|
+
yield_hook = dont_throw(yield_hook)
|
|
65
|
+
post_hook = dont_throw(post_hook)
|
|
66
|
+
error_hook = dont_throw(error_hook)
|
|
67
|
+
finally_hook = dont_throw(finally_hook)
|
|
68
|
+
|
|
69
|
+
@wraps(func)
|
|
70
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> Iterator[Y]:
|
|
71
|
+
ctx: Ctx = {}
|
|
72
|
+
pre_hook(ctx, *args, **kwargs)
|
|
73
|
+
try:
|
|
74
|
+
for value in func(*args, **kwargs):
|
|
75
|
+
yield_hook(ctx, value)
|
|
76
|
+
yield value
|
|
77
|
+
post_hook(ctx)
|
|
78
|
+
except Exception as e:
|
|
79
|
+
error_hook(ctx, e)
|
|
80
|
+
raise
|
|
81
|
+
finally:
|
|
82
|
+
finally_hook(ctx)
|
|
83
|
+
|
|
84
|
+
return wrapper
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from functools import wraps
|
|
2
|
+
from typing import Awaitable, Callable, TypeVar, Any, Dict, ParamSpec, Concatenate
|
|
3
|
+
|
|
4
|
+
from judgeval.utils.decorators.dont_throw import dont_throw
|
|
5
|
+
from judgeval.utils.wrappers.utils import identity_on_throw
|
|
6
|
+
|
|
7
|
+
P = ParamSpec("P")
|
|
8
|
+
R = TypeVar("R")
|
|
9
|
+
Ctx = Dict[str, Any]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def mutable_wrap_async(
|
|
13
|
+
func: Callable[P, Awaitable[R]],
|
|
14
|
+
/,
|
|
15
|
+
*,
|
|
16
|
+
pre_hook: Callable[Concatenate[Ctx, P], None] | None = None,
|
|
17
|
+
mutate_args_hook: Callable[[Ctx, tuple[Any, ...]], tuple[Any, ...]] | None = None,
|
|
18
|
+
mutate_kwargs_hook: Callable[[Ctx, dict[str, Any]], dict[str, Any]] | None = None,
|
|
19
|
+
post_hook: Callable[[Ctx, R], None] | None = None,
|
|
20
|
+
mutate_hook: Callable[[Ctx, R], R] | None = None,
|
|
21
|
+
error_hook: Callable[[Ctx, Exception], None] | None = None,
|
|
22
|
+
finally_hook: Callable[[Ctx], None] | None = None,
|
|
23
|
+
) -> Callable[P, Awaitable[R]]:
|
|
24
|
+
"""
|
|
25
|
+
Wraps an async function with lifecycle hooks that can mutate args, kwargs, and result.
|
|
26
|
+
|
|
27
|
+
- pre_hook: called before func with (ctx, *args, **kwargs) matching func's signature
|
|
28
|
+
- mutate_args_hook: called after pre_hook with (ctx, args), returns potentially modified args
|
|
29
|
+
- mutate_kwargs_hook: called after pre_hook with (ctx, kwargs), returns potentially modified kwargs
|
|
30
|
+
- post_hook: called after successful func execution with (ctx, result)
|
|
31
|
+
- mutate_hook: called after post_hook with (ctx, result), returns potentially modified result
|
|
32
|
+
- error_hook: called if func raises an exception with (ctx, error)
|
|
33
|
+
- finally_hook: called in finally block with (ctx)
|
|
34
|
+
|
|
35
|
+
The mutate hooks can transform args/kwargs/result. Exceptions are re-raised.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
safe_pre_hook = dont_throw(pre_hook) if pre_hook else (lambda ctx, *a, **kw: None)
|
|
39
|
+
safe_post_hook = dont_throw(post_hook) if post_hook else (lambda ctx, r: None)
|
|
40
|
+
safe_error_hook = dont_throw(error_hook) if error_hook else (lambda ctx, e: None)
|
|
41
|
+
safe_finally_hook = dont_throw(finally_hook) if finally_hook else (lambda ctx: None)
|
|
42
|
+
|
|
43
|
+
safe_mutate_args = identity_on_throw(mutate_args_hook) if mutate_args_hook else None
|
|
44
|
+
safe_mutate_kwargs = (
|
|
45
|
+
identity_on_throw(mutate_kwargs_hook) if mutate_kwargs_hook else None
|
|
46
|
+
)
|
|
47
|
+
safe_mutate_hook = identity_on_throw(mutate_hook) if mutate_hook else None
|
|
48
|
+
|
|
49
|
+
@wraps(func)
|
|
50
|
+
async def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
|
|
51
|
+
ctx: Ctx = {}
|
|
52
|
+
safe_pre_hook(ctx, *args, **kwargs)
|
|
53
|
+
|
|
54
|
+
final_args = safe_mutate_args(ctx, args) if safe_mutate_args else args
|
|
55
|
+
final_kwargs = safe_mutate_kwargs(ctx, kwargs) if safe_mutate_kwargs else kwargs
|
|
56
|
+
|
|
57
|
+
try:
|
|
58
|
+
result = await func(*final_args, **final_kwargs)
|
|
59
|
+
safe_post_hook(ctx, result)
|
|
60
|
+
return safe_mutate_hook(ctx, result) if safe_mutate_hook else result
|
|
61
|
+
except Exception as e:
|
|
62
|
+
safe_error_hook(ctx, e)
|
|
63
|
+
raise
|
|
64
|
+
finally:
|
|
65
|
+
safe_finally_hook(ctx)
|
|
66
|
+
|
|
67
|
+
return wrapper
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from functools import wraps
|
|
2
|
+
from typing import Callable, TypeVar, Any, Dict, ParamSpec, Concatenate
|
|
3
|
+
|
|
4
|
+
from judgeval.utils.decorators.dont_throw import dont_throw
|
|
5
|
+
from judgeval.utils.wrappers.utils import identity_on_throw
|
|
6
|
+
|
|
7
|
+
P = ParamSpec("P")
|
|
8
|
+
R = TypeVar("R")
|
|
9
|
+
Ctx = Dict[str, Any]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def mutable_wrap_sync(
|
|
13
|
+
func: Callable[P, R],
|
|
14
|
+
/,
|
|
15
|
+
*,
|
|
16
|
+
pre_hook: Callable[Concatenate[Ctx, P], None] | None = None,
|
|
17
|
+
mutate_args_hook: Callable[[Ctx, tuple[Any, ...]], tuple[Any, ...]] | None = None,
|
|
18
|
+
mutate_kwargs_hook: Callable[[Ctx, dict[str, Any]], dict[str, Any]] | None = None,
|
|
19
|
+
post_hook: Callable[[Ctx, R], None] | None = None,
|
|
20
|
+
mutate_hook: Callable[[Ctx, R], R] | None = None,
|
|
21
|
+
error_hook: Callable[[Ctx, Exception], None] | None = None,
|
|
22
|
+
finally_hook: Callable[[Ctx], None] | None = None,
|
|
23
|
+
) -> Callable[P, R]:
|
|
24
|
+
"""
|
|
25
|
+
Wraps a function with lifecycle hooks that can mutate args, kwargs, and result.
|
|
26
|
+
|
|
27
|
+
- pre_hook: called before func with (ctx, *args, **kwargs) matching func's signature
|
|
28
|
+
- mutate_args_hook: called after pre_hook with (ctx, args), returns potentially modified args
|
|
29
|
+
- mutate_kwargs_hook: called after pre_hook with (ctx, kwargs), returns potentially modified kwargs
|
|
30
|
+
- post_hook: called after successful func execution with (ctx, result)
|
|
31
|
+
- mutate_hook: called after post_hook with (ctx, result), returns potentially modified result
|
|
32
|
+
- error_hook: called if func raises an exception with (ctx, error)
|
|
33
|
+
- finally_hook: called in finally block with (ctx)
|
|
34
|
+
|
|
35
|
+
The mutate hooks can transform args/kwargs/result. Exceptions are re-raised.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
safe_pre_hook = dont_throw(pre_hook) if pre_hook else (lambda ctx, *a, **kw: None)
|
|
39
|
+
safe_post_hook = dont_throw(post_hook) if post_hook else (lambda ctx, r: None)
|
|
40
|
+
safe_error_hook = dont_throw(error_hook) if error_hook else (lambda ctx, e: None)
|
|
41
|
+
safe_finally_hook = dont_throw(finally_hook) if finally_hook else (lambda ctx: None)
|
|
42
|
+
|
|
43
|
+
safe_mutate_args = identity_on_throw(mutate_args_hook) if mutate_args_hook else None
|
|
44
|
+
safe_mutate_kwargs = (
|
|
45
|
+
identity_on_throw(mutate_kwargs_hook) if mutate_kwargs_hook else None
|
|
46
|
+
)
|
|
47
|
+
safe_mutate_hook = identity_on_throw(mutate_hook) if mutate_hook else None
|
|
48
|
+
|
|
49
|
+
@wraps(func)
|
|
50
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
|
|
51
|
+
ctx: Ctx = {}
|
|
52
|
+
safe_pre_hook(ctx, *args, **kwargs)
|
|
53
|
+
|
|
54
|
+
final_args = safe_mutate_args(ctx, args) if safe_mutate_args else args
|
|
55
|
+
final_kwargs = safe_mutate_kwargs(ctx, kwargs) if safe_mutate_kwargs else kwargs
|
|
56
|
+
|
|
57
|
+
try:
|
|
58
|
+
result = func(*final_args, **final_kwargs)
|
|
59
|
+
safe_post_hook(ctx, result)
|
|
60
|
+
return safe_mutate_hook(ctx, result) if safe_mutate_hook else result
|
|
61
|
+
except Exception as e:
|
|
62
|
+
safe_error_hook(ctx, e)
|
|
63
|
+
raise
|
|
64
|
+
finally:
|
|
65
|
+
safe_finally_hook(ctx)
|
|
66
|
+
|
|
67
|
+
return wrapper
|
|
File without changes
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from typing import Callable, TypeVar, ParamSpec
|
|
2
|
+
|
|
3
|
+
from judgeval.logger import judgeval_logger
|
|
4
|
+
|
|
5
|
+
P = ParamSpec("P")
|
|
6
|
+
T = TypeVar("T")
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def identity_on_throw(func: Callable[P, T]) -> Callable[P, T]:
|
|
10
|
+
"""
|
|
11
|
+
Wraps a mutation function to preserve the last argument (identity) if it fails.
|
|
12
|
+
|
|
13
|
+
This is used for mutation hooks where we want to fall back to the original value
|
|
14
|
+
if the mutation fails, ensuring the wrapper is always safe and non-breaking.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
func: A mutation function where the last positional argument is the value to mutate.
|
|
18
|
+
The function should return a potentially modified version of this value.
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
A wrapped function that returns the last positional argument (original value) if mutation fails
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
|
|
25
|
+
try:
|
|
26
|
+
return func(*args, **kwargs)
|
|
27
|
+
except Exception as e:
|
|
28
|
+
judgeval_logger.debug(
|
|
29
|
+
f"[Caught] Mutation function {func.__name__} failed, using identity",
|
|
30
|
+
exc_info=e,
|
|
31
|
+
)
|
|
32
|
+
# The last positional argument is always the value to mutate
|
|
33
|
+
return args[-1] # type: ignore[return-value]
|
|
34
|
+
|
|
35
|
+
return wrapper
|
judgeval/version.py
ADDED
judgeval/warnings.py
ADDED