deepeval 3.7.4__py3-none-any.whl → 3.7.6__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.
Files changed (224) hide show
  1. deepeval/_version.py +1 -1
  2. deepeval/config/settings.py +35 -1
  3. deepeval/dataset/api.py +23 -1
  4. deepeval/dataset/golden.py +139 -2
  5. deepeval/evaluate/evaluate.py +16 -11
  6. deepeval/evaluate/execute.py +13 -181
  7. deepeval/evaluate/utils.py +6 -26
  8. deepeval/integrations/pydantic_ai/agent.py +19 -2
  9. deepeval/integrations/pydantic_ai/instrumentator.py +62 -23
  10. deepeval/key_handler.py +3 -0
  11. deepeval/metrics/__init__.py +14 -16
  12. deepeval/metrics/answer_relevancy/answer_relevancy.py +118 -116
  13. deepeval/metrics/answer_relevancy/template.py +22 -3
  14. deepeval/metrics/arena_g_eval/arena_g_eval.py +98 -96
  15. deepeval/metrics/arena_g_eval/template.py +17 -1
  16. deepeval/metrics/argument_correctness/argument_correctness.py +81 -87
  17. deepeval/metrics/argument_correctness/template.py +19 -2
  18. deepeval/metrics/base_metric.py +13 -44
  19. deepeval/metrics/bias/bias.py +102 -108
  20. deepeval/metrics/bias/template.py +14 -2
  21. deepeval/metrics/contextual_precision/contextual_precision.py +96 -94
  22. deepeval/metrics/contextual_precision/template.py +115 -66
  23. deepeval/metrics/contextual_recall/contextual_recall.py +94 -84
  24. deepeval/metrics/contextual_recall/template.py +106 -55
  25. deepeval/metrics/contextual_relevancy/contextual_relevancy.py +86 -84
  26. deepeval/metrics/contextual_relevancy/template.py +87 -58
  27. deepeval/metrics/conversation_completeness/conversation_completeness.py +101 -119
  28. deepeval/metrics/conversation_completeness/template.py +23 -3
  29. deepeval/metrics/conversational_dag/conversational_dag.py +12 -8
  30. deepeval/metrics/conversational_dag/nodes.py +66 -123
  31. deepeval/metrics/conversational_dag/templates.py +16 -0
  32. deepeval/metrics/conversational_g_eval/conversational_g_eval.py +47 -66
  33. deepeval/metrics/dag/dag.py +10 -0
  34. deepeval/metrics/dag/nodes.py +63 -126
  35. deepeval/metrics/dag/templates.py +16 -2
  36. deepeval/metrics/exact_match/exact_match.py +9 -1
  37. deepeval/metrics/faithfulness/faithfulness.py +138 -149
  38. deepeval/metrics/faithfulness/schema.py +1 -1
  39. deepeval/metrics/faithfulness/template.py +200 -115
  40. deepeval/metrics/g_eval/g_eval.py +87 -78
  41. deepeval/metrics/g_eval/template.py +18 -1
  42. deepeval/metrics/g_eval/utils.py +7 -6
  43. deepeval/metrics/goal_accuracy/goal_accuracy.py +91 -76
  44. deepeval/metrics/goal_accuracy/template.py +21 -3
  45. deepeval/metrics/hallucination/hallucination.py +60 -75
  46. deepeval/metrics/hallucination/template.py +13 -0
  47. deepeval/metrics/indicator.py +7 -10
  48. deepeval/metrics/json_correctness/json_correctness.py +40 -38
  49. deepeval/metrics/json_correctness/template.py +10 -0
  50. deepeval/metrics/knowledge_retention/knowledge_retention.py +60 -97
  51. deepeval/metrics/knowledge_retention/schema.py +9 -3
  52. deepeval/metrics/knowledge_retention/template.py +12 -0
  53. deepeval/metrics/mcp/mcp_task_completion.py +68 -38
  54. deepeval/metrics/mcp/multi_turn_mcp_use_metric.py +92 -74
  55. deepeval/metrics/mcp/template.py +52 -0
  56. deepeval/metrics/mcp_use_metric/mcp_use_metric.py +58 -64
  57. deepeval/metrics/mcp_use_metric/template.py +12 -0
  58. deepeval/metrics/misuse/misuse.py +77 -97
  59. deepeval/metrics/misuse/template.py +15 -0
  60. deepeval/metrics/multimodal_metrics/__init__.py +0 -19
  61. deepeval/metrics/multimodal_metrics/image_coherence/image_coherence.py +59 -53
  62. deepeval/metrics/multimodal_metrics/image_editing/image_editing.py +79 -95
  63. deepeval/metrics/multimodal_metrics/image_helpfulness/image_helpfulness.py +59 -53
  64. deepeval/metrics/multimodal_metrics/image_reference/image_reference.py +59 -53
  65. deepeval/metrics/multimodal_metrics/text_to_image/text_to_image.py +111 -109
  66. deepeval/metrics/non_advice/non_advice.py +79 -105
  67. deepeval/metrics/non_advice/template.py +12 -0
  68. deepeval/metrics/pattern_match/pattern_match.py +12 -4
  69. deepeval/metrics/pii_leakage/pii_leakage.py +75 -106
  70. deepeval/metrics/pii_leakage/template.py +14 -0
  71. deepeval/metrics/plan_adherence/plan_adherence.py +63 -89
  72. deepeval/metrics/plan_adherence/template.py +11 -0
  73. deepeval/metrics/plan_quality/plan_quality.py +63 -87
  74. deepeval/metrics/plan_quality/template.py +9 -0
  75. deepeval/metrics/prompt_alignment/prompt_alignment.py +72 -83
  76. deepeval/metrics/prompt_alignment/template.py +12 -0
  77. deepeval/metrics/ragas.py +3 -3
  78. deepeval/metrics/role_adherence/role_adherence.py +48 -71
  79. deepeval/metrics/role_adherence/template.py +14 -0
  80. deepeval/metrics/role_violation/role_violation.py +75 -108
  81. deepeval/metrics/role_violation/template.py +12 -0
  82. deepeval/metrics/step_efficiency/step_efficiency.py +55 -65
  83. deepeval/metrics/step_efficiency/template.py +11 -0
  84. deepeval/metrics/summarization/summarization.py +115 -183
  85. deepeval/metrics/summarization/template.py +19 -0
  86. deepeval/metrics/task_completion/task_completion.py +67 -73
  87. deepeval/metrics/tool_correctness/tool_correctness.py +45 -44
  88. deepeval/metrics/tool_use/tool_use.py +42 -66
  89. deepeval/metrics/topic_adherence/template.py +13 -0
  90. deepeval/metrics/topic_adherence/topic_adherence.py +53 -67
  91. deepeval/metrics/toxicity/template.py +13 -0
  92. deepeval/metrics/toxicity/toxicity.py +80 -99
  93. deepeval/metrics/turn_contextual_precision/schema.py +21 -0
  94. deepeval/metrics/turn_contextual_precision/template.py +187 -0
  95. deepeval/metrics/turn_contextual_precision/turn_contextual_precision.py +592 -0
  96. deepeval/metrics/turn_contextual_recall/schema.py +21 -0
  97. deepeval/metrics/turn_contextual_recall/template.py +178 -0
  98. deepeval/metrics/turn_contextual_recall/turn_contextual_recall.py +563 -0
  99. deepeval/metrics/{multimodal_metrics/multimodal_contextual_relevancy → turn_contextual_relevancy}/schema.py +7 -1
  100. deepeval/metrics/turn_contextual_relevancy/template.py +161 -0
  101. deepeval/metrics/turn_contextual_relevancy/turn_contextual_relevancy.py +576 -0
  102. deepeval/metrics/{multimodal_metrics/multimodal_faithfulness → turn_faithfulness}/schema.py +11 -3
  103. deepeval/metrics/turn_faithfulness/template.py +218 -0
  104. deepeval/metrics/turn_faithfulness/turn_faithfulness.py +627 -0
  105. deepeval/metrics/turn_relevancy/template.py +14 -0
  106. deepeval/metrics/turn_relevancy/turn_relevancy.py +56 -69
  107. deepeval/metrics/utils.py +158 -122
  108. deepeval/models/__init__.py +0 -12
  109. deepeval/models/base_model.py +49 -33
  110. deepeval/models/embedding_models/__init__.py +7 -0
  111. deepeval/models/embedding_models/azure_embedding_model.py +79 -33
  112. deepeval/models/embedding_models/local_embedding_model.py +39 -20
  113. deepeval/models/embedding_models/ollama_embedding_model.py +52 -19
  114. deepeval/models/embedding_models/openai_embedding_model.py +42 -22
  115. deepeval/models/llms/amazon_bedrock_model.py +226 -72
  116. deepeval/models/llms/anthropic_model.py +178 -63
  117. deepeval/models/llms/azure_model.py +218 -60
  118. deepeval/models/llms/constants.py +2032 -0
  119. deepeval/models/llms/deepseek_model.py +95 -40
  120. deepeval/models/llms/gemini_model.py +209 -64
  121. deepeval/models/llms/grok_model.py +139 -68
  122. deepeval/models/llms/kimi_model.py +140 -90
  123. deepeval/models/llms/litellm_model.py +131 -37
  124. deepeval/models/llms/local_model.py +125 -21
  125. deepeval/models/llms/ollama_model.py +147 -24
  126. deepeval/models/llms/openai_model.py +222 -269
  127. deepeval/models/llms/portkey_model.py +81 -22
  128. deepeval/models/llms/utils.py +8 -3
  129. deepeval/models/retry_policy.py +17 -14
  130. deepeval/models/utils.py +106 -5
  131. deepeval/optimizer/__init__.py +5 -0
  132. deepeval/optimizer/algorithms/__init__.py +6 -0
  133. deepeval/optimizer/algorithms/base.py +29 -0
  134. deepeval/optimizer/algorithms/configs.py +18 -0
  135. deepeval/optimizer/algorithms/copro/__init__.py +5 -0
  136. deepeval/{optimization/copro/loop.py → optimizer/algorithms/copro/copro.py} +112 -113
  137. deepeval/optimizer/algorithms/gepa/__init__.py +5 -0
  138. deepeval/{optimization/gepa/loop.py → optimizer/algorithms/gepa/gepa.py} +175 -115
  139. deepeval/optimizer/algorithms/miprov2/__init__.py +17 -0
  140. deepeval/optimizer/algorithms/miprov2/bootstrapper.py +435 -0
  141. deepeval/optimizer/algorithms/miprov2/miprov2.py +752 -0
  142. deepeval/optimizer/algorithms/miprov2/proposer.py +301 -0
  143. deepeval/optimizer/algorithms/simba/__init__.py +5 -0
  144. deepeval/{optimization/simba/loop.py → optimizer/algorithms/simba/simba.py} +128 -112
  145. deepeval/{optimization → optimizer}/configs.py +5 -8
  146. deepeval/{optimization/policies/selection.py → optimizer/policies.py} +63 -2
  147. deepeval/optimizer/prompt_optimizer.py +263 -0
  148. deepeval/optimizer/rewriter/__init__.py +5 -0
  149. deepeval/optimizer/rewriter/rewriter.py +124 -0
  150. deepeval/optimizer/rewriter/utils.py +214 -0
  151. deepeval/optimizer/scorer/__init__.py +5 -0
  152. deepeval/optimizer/scorer/base.py +86 -0
  153. deepeval/optimizer/scorer/scorer.py +316 -0
  154. deepeval/optimizer/scorer/utils.py +30 -0
  155. deepeval/optimizer/types.py +148 -0
  156. deepeval/{optimization → optimizer}/utils.py +47 -165
  157. deepeval/prompt/prompt.py +5 -9
  158. deepeval/simulator/conversation_simulator.py +43 -0
  159. deepeval/simulator/template.py +13 -0
  160. deepeval/test_case/__init__.py +1 -3
  161. deepeval/test_case/api.py +26 -45
  162. deepeval/test_case/arena_test_case.py +7 -2
  163. deepeval/test_case/conversational_test_case.py +68 -1
  164. deepeval/test_case/llm_test_case.py +206 -1
  165. deepeval/test_case/utils.py +4 -8
  166. deepeval/test_run/api.py +18 -14
  167. deepeval/test_run/test_run.py +3 -3
  168. deepeval/tracing/patchers.py +9 -4
  169. deepeval/tracing/tracing.py +2 -2
  170. deepeval/utils.py +65 -0
  171. {deepeval-3.7.4.dist-info → deepeval-3.7.6.dist-info}/METADATA +1 -4
  172. {deepeval-3.7.4.dist-info → deepeval-3.7.6.dist-info}/RECORD +180 -193
  173. deepeval/metrics/multimodal_metrics/multimodal_answer_relevancy/multimodal_answer_relevancy.py +0 -343
  174. deepeval/metrics/multimodal_metrics/multimodal_answer_relevancy/schema.py +0 -19
  175. deepeval/metrics/multimodal_metrics/multimodal_answer_relevancy/template.py +0 -122
  176. deepeval/metrics/multimodal_metrics/multimodal_contextual_precision/multimodal_contextual_precision.py +0 -301
  177. deepeval/metrics/multimodal_metrics/multimodal_contextual_precision/schema.py +0 -15
  178. deepeval/metrics/multimodal_metrics/multimodal_contextual_precision/template.py +0 -132
  179. deepeval/metrics/multimodal_metrics/multimodal_contextual_recall/multimodal_contextual_recall.py +0 -285
  180. deepeval/metrics/multimodal_metrics/multimodal_contextual_recall/schema.py +0 -15
  181. deepeval/metrics/multimodal_metrics/multimodal_contextual_recall/template.py +0 -112
  182. deepeval/metrics/multimodal_metrics/multimodal_contextual_relevancy/multimodal_contextual_relevancy.py +0 -282
  183. deepeval/metrics/multimodal_metrics/multimodal_contextual_relevancy/template.py +0 -102
  184. deepeval/metrics/multimodal_metrics/multimodal_faithfulness/__init__.py +0 -0
  185. deepeval/metrics/multimodal_metrics/multimodal_faithfulness/multimodal_faithfulness.py +0 -356
  186. deepeval/metrics/multimodal_metrics/multimodal_faithfulness/template.py +0 -175
  187. deepeval/metrics/multimodal_metrics/multimodal_g_eval/__init__.py +0 -0
  188. deepeval/metrics/multimodal_metrics/multimodal_g_eval/multimodal_g_eval.py +0 -386
  189. deepeval/metrics/multimodal_metrics/multimodal_g_eval/schema.py +0 -11
  190. deepeval/metrics/multimodal_metrics/multimodal_g_eval/template.py +0 -148
  191. deepeval/metrics/multimodal_metrics/multimodal_g_eval/utils.py +0 -68
  192. deepeval/metrics/multimodal_metrics/multimodal_tool_correctness/__init__.py +0 -0
  193. deepeval/metrics/multimodal_metrics/multimodal_tool_correctness/multimodal_tool_correctness.py +0 -290
  194. deepeval/models/mlllms/__init__.py +0 -4
  195. deepeval/models/mlllms/azure_model.py +0 -343
  196. deepeval/models/mlllms/gemini_model.py +0 -313
  197. deepeval/models/mlllms/ollama_model.py +0 -175
  198. deepeval/models/mlllms/openai_model.py +0 -309
  199. deepeval/optimization/__init__.py +0 -13
  200. deepeval/optimization/adapters/__init__.py +0 -2
  201. deepeval/optimization/adapters/deepeval_scoring_adapter.py +0 -588
  202. deepeval/optimization/aggregates.py +0 -14
  203. deepeval/optimization/copro/configs.py +0 -31
  204. deepeval/optimization/gepa/__init__.py +0 -7
  205. deepeval/optimization/gepa/configs.py +0 -115
  206. deepeval/optimization/miprov2/configs.py +0 -134
  207. deepeval/optimization/miprov2/loop.py +0 -785
  208. deepeval/optimization/mutations/__init__.py +0 -0
  209. deepeval/optimization/mutations/prompt_rewriter.py +0 -458
  210. deepeval/optimization/policies/__init__.py +0 -16
  211. deepeval/optimization/policies/tie_breaker.py +0 -67
  212. deepeval/optimization/prompt_optimizer.py +0 -462
  213. deepeval/optimization/simba/__init__.py +0 -0
  214. deepeval/optimization/simba/configs.py +0 -33
  215. deepeval/optimization/types.py +0 -361
  216. deepeval/test_case/mllm_test_case.py +0 -170
  217. /deepeval/metrics/{multimodal_metrics/multimodal_answer_relevancy → turn_contextual_precision}/__init__.py +0 -0
  218. /deepeval/metrics/{multimodal_metrics/multimodal_contextual_precision → turn_contextual_recall}/__init__.py +0 -0
  219. /deepeval/metrics/{multimodal_metrics/multimodal_contextual_recall → turn_contextual_relevancy}/__init__.py +0 -0
  220. /deepeval/metrics/{multimodal_metrics/multimodal_contextual_relevancy → turn_faithfulness}/__init__.py +0 -0
  221. /deepeval/{optimization → optimizer/algorithms}/simba/types.py +0 -0
  222. {deepeval-3.7.4.dist-info → deepeval-3.7.6.dist-info}/LICENSE.md +0 -0
  223. {deepeval-3.7.4.dist-info → deepeval-3.7.6.dist-info}/WHEEL +0 -0
  224. {deepeval-3.7.4.dist-info → deepeval-3.7.6.dist-info}/entry_points.txt +0 -0
@@ -1,14 +1,21 @@
1
- from ollama import Client, AsyncClient, ChatResponse
2
- from typing import Optional, Tuple, Union, Dict
1
+ from typing import TYPE_CHECKING, Optional, Tuple, Union, Dict, List
3
2
  from pydantic import BaseModel
3
+ import base64
4
4
 
5
+ from deepeval.errors import DeepEvalError
5
6
  from deepeval.config.settings import get_settings
7
+ from deepeval.utils import require_dependency, require_param
6
8
  from deepeval.models.retry_policy import (
7
9
  create_retry_decorator,
8
10
  )
11
+ from deepeval.utils import convert_to_multi_modal_array, check_if_multimodal
12
+ from deepeval.test_case import MLLMImage
9
13
  from deepeval.models import DeepEvalBaseLLM
10
14
  from deepeval.constants import ProviderSlug as PS
15
+ from deepeval.models.llms.constants import OLLAMA_MODELS_DATA
11
16
 
17
+ if TYPE_CHECKING:
18
+ from ollama import ChatResponse
12
19
 
13
20
  retry_ollama = create_retry_decorator(PS.OLLAMA)
14
21
 
@@ -18,27 +25,47 @@ class OllamaModel(DeepEvalBaseLLM):
18
25
  self,
19
26
  model: Optional[str] = None,
20
27
  base_url: Optional[str] = None,
21
- temperature: float = 0,
28
+ temperature: Optional[float] = None,
22
29
  generation_kwargs: Optional[Dict] = None,
23
30
  **kwargs,
24
31
  ):
25
32
  settings = get_settings()
26
- model_name = model or settings.LOCAL_MODEL_NAME
27
- self.base_url = (
28
- base_url
29
- or (
30
- settings.LOCAL_MODEL_BASE_URL
31
- and str(settings.LOCAL_MODEL_BASE_URL)
32
- )
33
- or "http://localhost:11434"
33
+ model = model or settings.OLLAMA_MODEL_NAME
34
+ self.model_data = OLLAMA_MODELS_DATA.get(model)
35
+
36
+ if base_url is not None:
37
+ self.base_url = str(base_url).rstrip("/")
38
+ elif settings.LOCAL_MODEL_BASE_URL is not None:
39
+ self.base_url = str(settings.LOCAL_MODEL_BASE_URL).rstrip("/")
40
+ else:
41
+ self.base_url = "http://localhost:11434"
42
+
43
+ if temperature is not None:
44
+ temperature = float(temperature)
45
+ elif settings.TEMPERATURE is not None:
46
+ temperature = settings.TEMPERATURE
47
+ else:
48
+ temperature = 0.0
49
+
50
+ # validation
51
+ model = require_param(
52
+ model,
53
+ provider_label="OllamaModel",
54
+ env_var_name="LOCAL_MODEL_NAME",
55
+ param_hint="model",
34
56
  )
57
+
35
58
  if temperature < 0:
36
- raise ValueError("Temperature must be >= 0.")
59
+ raise DeepEvalError("Temperature must be >= 0.")
37
60
  self.temperature = temperature
38
- # Raw kwargs destined for the underlying Ollama client
61
+ # Keep sanitized kwargs for client call to strip legacy keys
39
62
  self.kwargs = kwargs
40
- self.generation_kwargs = generation_kwargs or {}
41
- super().__init__(model_name)
63
+ self.kwargs.pop("temperature", None)
64
+
65
+ self.generation_kwargs = dict(generation_kwargs or {})
66
+ self.generation_kwargs.pop("temperature", None)
67
+
68
+ super().__init__(model)
42
69
 
43
70
  ###############################################
44
71
  # Other generate functions
@@ -47,11 +74,18 @@ class OllamaModel(DeepEvalBaseLLM):
47
74
  @retry_ollama
48
75
  def generate(
49
76
  self, prompt: str, schema: Optional[BaseModel] = None
50
- ) -> Tuple[Union[str, Dict], float]:
77
+ ) -> Tuple[Union[str, BaseModel], float]:
51
78
  chat_model = self.load_model()
79
+
80
+ if check_if_multimodal(prompt):
81
+ prompt = convert_to_multi_modal_array(prompt)
82
+ messages = self.generate_messages(prompt)
83
+ else:
84
+ messages = [{"role": "user", "content": prompt}]
85
+
52
86
  response: ChatResponse = chat_model.chat(
53
- model=self.model_name,
54
- messages=[{"role": "user", "content": prompt}],
87
+ model=self.name,
88
+ messages=messages,
55
89
  format=schema.model_json_schema() if schema else None,
56
90
  options={
57
91
  **{"temperature": self.temperature},
@@ -70,11 +104,18 @@ class OllamaModel(DeepEvalBaseLLM):
70
104
  @retry_ollama
71
105
  async def a_generate(
72
106
  self, prompt: str, schema: Optional[BaseModel] = None
73
- ) -> Tuple[str, float]:
107
+ ) -> Tuple[Union[str, BaseModel], float]:
74
108
  chat_model = self.load_model(async_mode=True)
109
+
110
+ if check_if_multimodal(prompt):
111
+ prompt = convert_to_multi_modal_array(prompt)
112
+ messages = self.generate_messages(prompt)
113
+ else:
114
+ messages = [{"role": "user", "content": prompt}]
115
+
75
116
  response: ChatResponse = await chat_model.chat(
76
- model=self.model_name,
77
- messages=[{"role": "user", "content": prompt}],
117
+ model=self.name,
118
+ messages=messages,
78
119
  format=schema.model_json_schema() if schema else None,
79
120
  options={
80
121
  **{"temperature": self.temperature},
@@ -90,14 +131,96 @@ class OllamaModel(DeepEvalBaseLLM):
90
131
  0,
91
132
  )
92
133
 
134
+ def generate_messages(
135
+ self, multimodal_input: List[Union[str, MLLMImage]] = []
136
+ ):
137
+ messages = []
138
+
139
+ for element in multimodal_input:
140
+ if isinstance(element, str):
141
+ messages.append(
142
+ {
143
+ "role": "user",
144
+ "content": element,
145
+ }
146
+ )
147
+ elif isinstance(element, MLLMImage):
148
+ if element.url and not element.local:
149
+ import requests
150
+ from PIL import Image
151
+ import io
152
+
153
+ settings = get_settings()
154
+ try:
155
+ response = requests.get(
156
+ element.url,
157
+ stream=True,
158
+ timeout=(
159
+ settings.MEDIA_IMAGE_CONNECT_TIMEOUT_SECONDS,
160
+ settings.MEDIA_IMAGE_READ_TIMEOUT_SECONDS,
161
+ ),
162
+ )
163
+ response.raise_for_status()
164
+
165
+ # Convert to JPEG and encode
166
+ image = Image.open(io.BytesIO(response.content))
167
+ buffered = io.BytesIO()
168
+
169
+ # Convert RGBA/LA/P to RGB for JPEG
170
+ if image.mode in ("RGBA", "LA", "P"):
171
+ image = image.convert("RGB")
172
+
173
+ image.save(buffered, format="JPEG")
174
+ img_b64 = base64.b64encode(buffered.getvalue()).decode()
175
+
176
+ except (requests.exceptions.RequestException, OSError) as e:
177
+ print(f"Image fetch/encode failed: {e}")
178
+ raise
179
+ else:
180
+ element.ensure_images_loaded()
181
+ img_b64 = element.dataBase64
182
+
183
+ messages.append(
184
+ {
185
+ "role": "user",
186
+ "images": [img_b64],
187
+ }
188
+ )
189
+
190
+ return messages
191
+
192
+ ###############################################
193
+ # Capabilities
194
+ ###############################################
195
+
196
+ def supports_log_probs(self) -> Union[bool, None]:
197
+ return self.model_data.supports_log_probs
198
+
199
+ def supports_temperature(self) -> Union[bool, None]:
200
+ return self.model_data.supports_temperature
201
+
202
+ def supports_multimodal(self) -> Union[bool, None]:
203
+ return self.model_data.supports_multimodal
204
+
205
+ def supports_structured_outputs(self) -> Union[bool, None]:
206
+ return self.model_data.supports_structured_outputs
207
+
208
+ def supports_json_mode(self) -> Union[bool, None]:
209
+ return self.model_data.supports_json
210
+
93
211
  ###############################################
94
212
  # Model
95
213
  ###############################################
96
214
 
97
215
  def load_model(self, async_mode: bool = False):
216
+ ollama = require_dependency(
217
+ "ollama",
218
+ provider_label="OllamaModel",
219
+ install_hint="Install it with `pip install ollama`.",
220
+ )
98
221
  if not async_mode:
99
- return self._build_client(Client)
100
- return self._build_client(AsyncClient)
222
+ return self._build_client(ollama.Client)
223
+ return self._build_client(ollama.AsyncClient)
101
224
 
102
225
  def _client_kwargs(self) -> Dict:
103
226
  """Return kwargs forwarded to the underlying Ollama Client/AsyncClient."""
@@ -111,4 +234,4 @@ class OllamaModel(DeepEvalBaseLLM):
111
234
  return cls(**kw)
112
235
 
113
236
  def get_model_name(self):
114
- return f"{self.model_name} (Ollama)"
237
+ return f"{self.name} (Ollama)"