deepeval 3.4.7__py3-none-any.whl → 3.4.9__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.
- deepeval/__init__.py +8 -7
- deepeval/_version.py +1 -1
- deepeval/cli/dotenv_handler.py +71 -0
- deepeval/cli/main.py +1021 -280
- deepeval/cli/utils.py +116 -2
- deepeval/confident/api.py +29 -14
- deepeval/config/__init__.py +0 -0
- deepeval/config/settings.py +565 -0
- deepeval/config/settings_manager.py +133 -0
- deepeval/config/utils.py +86 -0
- deepeval/dataset/__init__.py +1 -0
- deepeval/dataset/dataset.py +70 -10
- deepeval/dataset/test_run_tracer.py +82 -0
- deepeval/dataset/utils.py +23 -0
- deepeval/key_handler.py +64 -2
- deepeval/metrics/__init__.py +4 -1
- deepeval/metrics/answer_relevancy/template.py +7 -2
- deepeval/metrics/conversational_dag/__init__.py +7 -0
- deepeval/metrics/conversational_dag/conversational_dag.py +139 -0
- deepeval/metrics/conversational_dag/nodes.py +931 -0
- deepeval/metrics/conversational_dag/templates.py +117 -0
- deepeval/metrics/dag/dag.py +13 -4
- deepeval/metrics/dag/graph.py +47 -15
- deepeval/metrics/dag/utils.py +103 -38
- deepeval/metrics/faithfulness/template.py +11 -8
- deepeval/metrics/multimodal_metrics/multimodal_answer_relevancy/template.py +6 -4
- deepeval/metrics/multimodal_metrics/multimodal_faithfulness/template.py +6 -4
- deepeval/metrics/tool_correctness/tool_correctness.py +7 -3
- deepeval/models/llms/amazon_bedrock_model.py +24 -3
- deepeval/models/llms/openai_model.py +37 -41
- deepeval/models/retry_policy.py +280 -0
- deepeval/openai_agents/agent.py +4 -2
- deepeval/synthesizer/chunking/doc_chunker.py +87 -51
- deepeval/test_run/api.py +1 -0
- deepeval/tracing/otel/exporter.py +20 -8
- deepeval/tracing/otel/utils.py +57 -0
- deepeval/tracing/tracing.py +37 -16
- deepeval/tracing/utils.py +98 -1
- deepeval/utils.py +111 -70
- {deepeval-3.4.7.dist-info → deepeval-3.4.9.dist-info}/METADATA +3 -1
- {deepeval-3.4.7.dist-info → deepeval-3.4.9.dist-info}/RECORD +44 -34
- deepeval/env.py +0 -35
- {deepeval-3.4.7.dist-info → deepeval-3.4.9.dist-info}/LICENSE.md +0 -0
- {deepeval-3.4.7.dist-info → deepeval-3.4.9.dist-info}/WHEEL +0 -0
- {deepeval-3.4.7.dist-info → deepeval-3.4.9.dist-info}/entry_points.txt +0 -0
deepeval/cli/utils.py
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
from
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
2
4
|
import webbrowser
|
|
3
5
|
import pyfiglet
|
|
4
|
-
|
|
6
|
+
|
|
7
|
+
from enum import Enum
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from rich import print
|
|
10
|
+
from typing import Optional, Dict, Iterable, List, Tuple, Union
|
|
5
11
|
from opentelemetry.trace import Span
|
|
6
12
|
|
|
7
13
|
from deepeval.key_handler import (
|
|
@@ -14,8 +20,25 @@ from deepeval.test_run.test_run import (
|
|
|
14
20
|
global_test_run_manager,
|
|
15
21
|
)
|
|
16
22
|
from deepeval.confident.api import get_confident_api_key, set_confident_api_key
|
|
23
|
+
from deepeval.cli.dotenv_handler import DotenvHandler
|
|
17
24
|
|
|
25
|
+
|
|
26
|
+
StrOrEnum = Union[str, "Enum"]
|
|
18
27
|
PROD = "https://app.confident-ai.com"
|
|
28
|
+
# List all mutually exclusive USE_* keys
|
|
29
|
+
USE_MODEL_KEYS: List[ModelKeyValues | EmbeddingKeyValues] = [
|
|
30
|
+
ModelKeyValues.USE_OPENAI_MODEL,
|
|
31
|
+
ModelKeyValues.USE_AZURE_OPENAI,
|
|
32
|
+
ModelKeyValues.USE_LOCAL_MODEL,
|
|
33
|
+
ModelKeyValues.USE_GROK_MODEL,
|
|
34
|
+
ModelKeyValues.USE_MOONSHOT_MODEL,
|
|
35
|
+
ModelKeyValues.USE_DEEPSEEK_MODEL,
|
|
36
|
+
ModelKeyValues.USE_GEMINI_MODEL,
|
|
37
|
+
ModelKeyValues.USE_LITELLM,
|
|
38
|
+
EmbeddingKeyValues.USE_AZURE_OPENAI_EMBEDDING,
|
|
39
|
+
EmbeddingKeyValues.USE_LOCAL_EMBEDDINGS,
|
|
40
|
+
# MAINTENANCE: add more if new USE_* keys appear
|
|
41
|
+
]
|
|
19
42
|
|
|
20
43
|
|
|
21
44
|
def render_login_message():
|
|
@@ -65,3 +88,94 @@ def clear_evaluation_model_keys():
|
|
|
65
88
|
def clear_embedding_model_keys():
|
|
66
89
|
for key in EmbeddingKeyValues:
|
|
67
90
|
KEY_FILE_HANDLER.remove_key(key)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _to_str_key(k: StrOrEnum) -> str:
|
|
94
|
+
return k.value if hasattr(k, "value") else str(k)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _normalize_kv(updates: Dict[StrOrEnum, str]) -> Dict[str, str]:
|
|
98
|
+
return {_to_str_key(k): v for k, v in updates.items()}
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _normalize_keys(keys: Iterable[StrOrEnum]) -> list[str]:
|
|
102
|
+
return [_to_str_key(k) for k in keys]
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _parse_save_option(
|
|
106
|
+
save_opt: str | None, default_path: str = ".env.local"
|
|
107
|
+
) -> Tuple[bool, str | None]:
|
|
108
|
+
if not save_opt:
|
|
109
|
+
return False, None
|
|
110
|
+
kind, *rest = save_opt.split(":", 1)
|
|
111
|
+
if kind != "dotenv":
|
|
112
|
+
return False, None
|
|
113
|
+
path = rest[0] if rest else default_path
|
|
114
|
+
return True, path
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def resolve_save_target(save_opt: Optional[str]) -> Optional[str]:
|
|
118
|
+
"""
|
|
119
|
+
Returns a normalized save target string like 'dotenv:.env.local' or None.
|
|
120
|
+
Precedence:
|
|
121
|
+
1) --save=...
|
|
122
|
+
2) DEEPEVAL_DEFAULT_SAVE (opt-in project default)
|
|
123
|
+
3) None (no save)
|
|
124
|
+
"""
|
|
125
|
+
if save_opt:
|
|
126
|
+
return save_opt
|
|
127
|
+
|
|
128
|
+
env_default = os.getenv("DEEPEVAL_DEFAULT_SAVE")
|
|
129
|
+
if env_default and env_default.strip():
|
|
130
|
+
return env_default.strip()
|
|
131
|
+
|
|
132
|
+
return None
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def save_environ_to_store(
|
|
136
|
+
save_opt: str | None, updates: Dict[StrOrEnum, str]
|
|
137
|
+
) -> Tuple[bool, str | None]:
|
|
138
|
+
"""
|
|
139
|
+
Save 'updates' into the selected store (currently only dotenv). Idempotent upsert.
|
|
140
|
+
Returns (handled, path).
|
|
141
|
+
"""
|
|
142
|
+
ok, path = _parse_save_option(save_opt)
|
|
143
|
+
if not ok:
|
|
144
|
+
return False, None
|
|
145
|
+
if updates:
|
|
146
|
+
DotenvHandler(path).upsert(_normalize_kv(updates))
|
|
147
|
+
return True, path
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def unset_environ_in_store(
|
|
151
|
+
save_opt: str | None, keys: Iterable[StrOrEnum]
|
|
152
|
+
) -> Tuple[bool, str | None]:
|
|
153
|
+
"""
|
|
154
|
+
Remove keys from the selected store (currently only dotenv).
|
|
155
|
+
Returns (handled, path).
|
|
156
|
+
"""
|
|
157
|
+
ok, path = _parse_save_option(save_opt)
|
|
158
|
+
if not ok:
|
|
159
|
+
return False, None
|
|
160
|
+
norm = _normalize_keys(keys)
|
|
161
|
+
if norm:
|
|
162
|
+
DotenvHandler(path).unset(norm)
|
|
163
|
+
return True, path
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def switch_model_provider(target: ModelKeyValues, save: str = None) -> None:
|
|
167
|
+
"""
|
|
168
|
+
Ensure exactly one USE_* model flag is set to "YES" and the rest to "NO",
|
|
169
|
+
both in the .deepeval json store and in a dotenv file (if save is provided).
|
|
170
|
+
"""
|
|
171
|
+
if target not in USE_MODEL_KEYS:
|
|
172
|
+
raise ValueError(f"{target} is not a recognized USE_* model key")
|
|
173
|
+
|
|
174
|
+
for key in USE_MODEL_KEYS:
|
|
175
|
+
value = "YES" if key == target else "NO"
|
|
176
|
+
KEY_FILE_HANDLER.write_key(key, value)
|
|
177
|
+
|
|
178
|
+
if save:
|
|
179
|
+
handled, path = save_environ_to_store(save, {key: value})
|
|
180
|
+
if not handled:
|
|
181
|
+
print("Unsupported --save option. Use --save=dotenv[:path].")
|
deepeval/confident/api.py
CHANGED
|
@@ -14,6 +14,8 @@ from tenacity import (
|
|
|
14
14
|
import deepeval
|
|
15
15
|
from deepeval.key_handler import KEY_FILE_HANDLER, KeyValues
|
|
16
16
|
from deepeval.confident.types import ApiResponse, ConfidentApiError
|
|
17
|
+
from deepeval.config.settings import get_settings
|
|
18
|
+
|
|
17
19
|
|
|
18
20
|
CONFIDENT_API_KEY_ENV_VAR = "CONFIDENT_API_KEY"
|
|
19
21
|
DEEPEVAL_BASE_URL = "https://deepeval.confident-ai.com"
|
|
@@ -31,20 +33,33 @@ def get_base_api_url():
|
|
|
31
33
|
return API_BASE_URL
|
|
32
34
|
|
|
33
35
|
|
|
34
|
-
def get_confident_api_key():
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def set_confident_api_key(api_key:
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
36
|
+
def get_confident_api_key() -> Optional[str]:
|
|
37
|
+
s = get_settings()
|
|
38
|
+
key: Optional[SecretStr] = s.CONFIDENT_API_KEY or s.API_KEY
|
|
39
|
+
return key.get_secret_value() if key else None
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def set_confident_api_key(api_key: Optional[str]) -> None:
|
|
43
|
+
"""
|
|
44
|
+
- Always updates runtime (os.environ) via settings.edit()
|
|
45
|
+
- If DEEPEVAL_DEFAULT_SAVE is set, also persists to dotenv
|
|
46
|
+
- Never writes secrets to the legacy JSON keystore (your Settings logic already skips secrets)
|
|
47
|
+
"""
|
|
48
|
+
s = get_settings()
|
|
49
|
+
save = (
|
|
50
|
+
s.DEEPEVAL_DEFAULT_SAVE or None
|
|
51
|
+
) # e.g. "dotenv" or "dotenv:/path/.env"
|
|
52
|
+
|
|
53
|
+
# If you *only* want runtime changes unless a default save is present:
|
|
54
|
+
if save is None:
|
|
55
|
+
with s.edit(persist=False):
|
|
56
|
+
s.CONFIDENT_API_KEY = SecretStr(api_key) if api_key else None
|
|
57
|
+
s.API_KEY = SecretStr(api_key) if api_key else None
|
|
58
|
+
else:
|
|
59
|
+
# Respect default save: update runtime + write to dotenv, but not JSON
|
|
60
|
+
with s.edit(save=save, persist=None):
|
|
61
|
+
s.CONFIDENT_API_KEY = SecretStr(api_key) if api_key else None
|
|
62
|
+
s.API_KEY = SecretStr(api_key) if api_key else None
|
|
48
63
|
|
|
49
64
|
|
|
50
65
|
def is_confident():
|
|
File without changes
|