agenta 0.57.0__py3-none-any.whl → 0.65.0__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 (267) hide show
  1. agenta/__init__.py +12 -3
  2. agenta/client/__init__.py +4 -4
  3. agenta/client/backend/__init__.py +4 -4
  4. agenta/client/backend/api_keys/client.py +2 -2
  5. agenta/client/backend/billing/client.py +2 -2
  6. agenta/client/backend/billing/raw_client.py +2 -2
  7. agenta/client/backend/client.py +56 -48
  8. agenta/client/backend/core/client_wrapper.py +2 -2
  9. agenta/client/backend/core/file.py +3 -1
  10. agenta/client/backend/core/http_client.py +3 -3
  11. agenta/client/backend/core/pydantic_utilities.py +13 -3
  12. agenta/client/backend/human_evaluations/client.py +2 -2
  13. agenta/client/backend/human_evaluations/raw_client.py +2 -2
  14. agenta/client/backend/organization/client.py +46 -34
  15. agenta/client/backend/organization/raw_client.py +32 -26
  16. agenta/client/backend/raw_client.py +26 -26
  17. agenta/client/backend/testsets/client.py +18 -18
  18. agenta/client/backend/testsets/raw_client.py +30 -30
  19. agenta/client/backend/types/__init__.py +4 -4
  20. agenta/client/backend/types/account_request.py +3 -1
  21. agenta/client/backend/types/account_response.py +3 -1
  22. agenta/client/backend/types/agenta_node_dto.py +3 -1
  23. agenta/client/backend/types/agenta_nodes_response.py +3 -1
  24. agenta/client/backend/types/agenta_root_dto.py +3 -1
  25. agenta/client/backend/types/agenta_roots_response.py +3 -1
  26. agenta/client/backend/types/agenta_tree_dto.py +3 -1
  27. agenta/client/backend/types/agenta_trees_response.py +3 -1
  28. agenta/client/backend/types/aggregated_result.py +3 -1
  29. agenta/client/backend/types/analytics_response.py +3 -1
  30. agenta/client/backend/types/annotation.py +6 -4
  31. agenta/client/backend/types/annotation_create.py +3 -1
  32. agenta/client/backend/types/annotation_edit.py +3 -1
  33. agenta/client/backend/types/annotation_link.py +3 -1
  34. agenta/client/backend/types/annotation_link_response.py +3 -1
  35. agenta/client/backend/types/annotation_query.py +3 -1
  36. agenta/client/backend/types/annotation_query_request.py +3 -1
  37. agenta/client/backend/types/annotation_reference.py +3 -1
  38. agenta/client/backend/types/annotation_references.py +3 -1
  39. agenta/client/backend/types/annotation_response.py +3 -1
  40. agenta/client/backend/types/annotations_response.py +3 -1
  41. agenta/client/backend/types/app.py +3 -1
  42. agenta/client/backend/types/app_variant_response.py +3 -1
  43. agenta/client/backend/types/app_variant_revision.py +3 -1
  44. agenta/client/backend/types/artifact.py +6 -4
  45. agenta/client/backend/types/base_output.py +3 -1
  46. agenta/client/backend/types/body_fetch_workflow_revision.py +3 -1
  47. agenta/client/backend/types/body_import_testset.py +3 -1
  48. agenta/client/backend/types/bucket_dto.py +3 -1
  49. agenta/client/backend/types/collect_status_response.py +3 -1
  50. agenta/client/backend/types/config_db.py +3 -1
  51. agenta/client/backend/types/config_dto.py +3 -1
  52. agenta/client/backend/types/config_response_model.py +3 -1
  53. agenta/client/backend/types/correct_answer.py +3 -1
  54. agenta/client/backend/types/create_app_output.py +3 -1
  55. agenta/client/backend/types/custom_model_settings_dto.py +3 -1
  56. agenta/client/backend/types/custom_provider_dto.py +3 -1
  57. agenta/client/backend/types/custom_provider_kind.py +1 -1
  58. agenta/client/backend/types/custom_provider_settings_dto.py +3 -1
  59. agenta/client/backend/types/delete_evaluation.py +3 -1
  60. agenta/client/backend/types/environment_output.py +3 -1
  61. agenta/client/backend/types/environment_output_extended.py +3 -1
  62. agenta/client/backend/types/environment_revision.py +3 -1
  63. agenta/client/backend/types/error.py +3 -1
  64. agenta/client/backend/types/evaluation.py +3 -1
  65. agenta/client/backend/types/evaluation_scenario.py +3 -1
  66. agenta/client/backend/types/evaluation_scenario_input.py +3 -1
  67. agenta/client/backend/types/evaluation_scenario_output.py +3 -1
  68. agenta/client/backend/types/evaluation_scenario_result.py +3 -1
  69. agenta/client/backend/types/evaluator.py +6 -4
  70. agenta/client/backend/types/evaluator_config.py +6 -4
  71. agenta/client/backend/types/evaluator_flags.py +3 -1
  72. agenta/client/backend/types/evaluator_mapping_output_interface.py +3 -1
  73. agenta/client/backend/types/evaluator_output_interface.py +3 -1
  74. agenta/client/backend/types/evaluator_query.py +3 -1
  75. agenta/client/backend/types/evaluator_query_request.py +3 -1
  76. agenta/client/backend/types/evaluator_request.py +3 -1
  77. agenta/client/backend/types/evaluator_response.py +3 -1
  78. agenta/client/backend/types/evaluators_response.py +3 -1
  79. agenta/client/backend/types/exception_dto.py +3 -1
  80. agenta/client/backend/types/extended_o_tel_tracing_response.py +3 -1
  81. agenta/client/backend/types/get_config_response.py +3 -1
  82. agenta/client/backend/types/header.py +3 -1
  83. agenta/client/backend/types/http_validation_error.py +3 -1
  84. agenta/client/backend/types/human_evaluation.py +3 -1
  85. agenta/client/backend/types/human_evaluation_scenario.py +3 -1
  86. agenta/client/backend/types/human_evaluation_scenario_input.py +3 -1
  87. agenta/client/backend/types/human_evaluation_scenario_output.py +3 -1
  88. agenta/client/backend/types/invite_request.py +3 -1
  89. agenta/client/backend/types/legacy_analytics_response.py +3 -1
  90. agenta/client/backend/types/legacy_data_point.py +3 -1
  91. agenta/client/backend/types/legacy_evaluator.py +3 -1
  92. agenta/client/backend/types/legacy_scope_request.py +3 -1
  93. agenta/client/backend/types/legacy_scopes_response.py +3 -1
  94. agenta/client/backend/types/legacy_subscription_request.py +3 -1
  95. agenta/client/backend/types/legacy_user_request.py +3 -1
  96. agenta/client/backend/types/legacy_user_response.py +3 -1
  97. agenta/client/backend/types/lifecycle_dto.py +3 -1
  98. agenta/client/backend/types/link_dto.py +3 -1
  99. agenta/client/backend/types/list_api_keys_response.py +3 -1
  100. agenta/client/backend/types/llm_run_rate_limit.py +3 -1
  101. agenta/client/backend/types/meta_request.py +3 -1
  102. agenta/client/backend/types/metrics_dto.py +3 -1
  103. agenta/client/backend/types/new_testset.py +3 -1
  104. agenta/client/backend/types/node_dto.py +3 -1
  105. agenta/client/backend/types/o_tel_context_dto.py +3 -1
  106. agenta/client/backend/types/o_tel_event.py +6 -4
  107. agenta/client/backend/types/o_tel_event_dto.py +3 -1
  108. agenta/client/backend/types/o_tel_extra_dto.py +3 -1
  109. agenta/client/backend/types/o_tel_flat_span.py +6 -4
  110. agenta/client/backend/types/o_tel_link.py +6 -4
  111. agenta/client/backend/types/o_tel_link_dto.py +3 -1
  112. agenta/client/backend/types/o_tel_links_response.py +3 -1
  113. agenta/client/backend/types/o_tel_span.py +1 -1
  114. agenta/client/backend/types/o_tel_span_dto.py +3 -1
  115. agenta/client/backend/types/o_tel_spans_tree.py +3 -1
  116. agenta/client/backend/types/o_tel_tracing_data_response.py +3 -1
  117. agenta/client/backend/types/o_tel_tracing_request.py +3 -1
  118. agenta/client/backend/types/o_tel_tracing_response.py +3 -1
  119. agenta/client/backend/types/organization.py +3 -1
  120. agenta/client/backend/types/organization_details.py +3 -1
  121. agenta/client/backend/types/organization_membership_request.py +3 -1
  122. agenta/client/backend/types/organization_output.py +3 -1
  123. agenta/client/backend/types/organization_request.py +3 -1
  124. agenta/client/backend/types/parent_dto.py +3 -1
  125. agenta/client/backend/types/project_membership_request.py +3 -1
  126. agenta/client/backend/types/project_request.py +3 -1
  127. agenta/client/backend/types/project_scope.py +3 -1
  128. agenta/client/backend/types/projects_response.py +4 -1
  129. agenta/client/backend/types/reference.py +6 -4
  130. agenta/client/backend/types/reference_dto.py +3 -1
  131. agenta/client/backend/types/reference_request_model.py +3 -1
  132. agenta/client/backend/types/result.py +3 -1
  133. agenta/client/backend/types/root_dto.py +3 -1
  134. agenta/client/backend/types/scopes_response_model.py +3 -1
  135. agenta/client/backend/types/secret_dto.py +3 -1
  136. agenta/client/backend/types/secret_response_dto.py +3 -1
  137. agenta/client/backend/types/simple_evaluation_output.py +3 -1
  138. agenta/client/backend/types/span_dto.py +6 -4
  139. agenta/client/backend/types/standard_provider_dto.py +3 -1
  140. agenta/client/backend/types/standard_provider_settings_dto.py +3 -1
  141. agenta/client/backend/types/status_dto.py +3 -1
  142. agenta/client/backend/types/tags_request.py +3 -1
  143. agenta/client/backend/types/testcase_response.py +6 -4
  144. agenta/client/backend/types/testset.py +6 -4
  145. agenta/client/backend/types/{test_set_output_response.py → testset_output_response.py} +4 -2
  146. agenta/client/backend/types/testset_request.py +3 -1
  147. agenta/client/backend/types/testset_response.py +3 -1
  148. agenta/client/backend/types/{test_set_simple_response.py → testset_simple_response.py} +4 -2
  149. agenta/client/backend/types/testsets_response.py +3 -1
  150. agenta/client/backend/types/time_dto.py +3 -1
  151. agenta/client/backend/types/tree_dto.py +3 -1
  152. agenta/client/backend/types/update_app_output.py +3 -1
  153. agenta/client/backend/types/user_request.py +3 -1
  154. agenta/client/backend/types/validation_error.py +3 -1
  155. agenta/client/backend/types/workflow_artifact.py +6 -4
  156. agenta/client/backend/types/workflow_data.py +3 -1
  157. agenta/client/backend/types/workflow_flags.py +3 -1
  158. agenta/client/backend/types/workflow_request.py +3 -1
  159. agenta/client/backend/types/workflow_response.py +3 -1
  160. agenta/client/backend/types/workflow_revision.py +6 -4
  161. agenta/client/backend/types/workflow_revision_request.py +3 -1
  162. agenta/client/backend/types/workflow_revision_response.py +3 -1
  163. agenta/client/backend/types/workflow_revisions_response.py +3 -1
  164. agenta/client/backend/types/workflow_variant.py +6 -4
  165. agenta/client/backend/types/workflow_variant_request.py +3 -1
  166. agenta/client/backend/types/workflow_variant_response.py +3 -1
  167. agenta/client/backend/types/workflow_variants_response.py +3 -1
  168. agenta/client/backend/types/workflows_response.py +3 -1
  169. agenta/client/backend/types/workspace.py +3 -1
  170. agenta/client/backend/types/workspace_member_response.py +3 -1
  171. agenta/client/backend/types/workspace_membership_request.py +3 -1
  172. agenta/client/backend/types/workspace_permission.py +3 -1
  173. agenta/client/backend/types/workspace_request.py +3 -1
  174. agenta/client/backend/types/workspace_response.py +3 -1
  175. agenta/client/backend/workspace/client.py +2 -2
  176. agenta/client/client.py +102 -88
  177. agenta/sdk/__init__.py +52 -3
  178. agenta/sdk/agenta_init.py +43 -16
  179. agenta/sdk/assets.py +22 -15
  180. agenta/sdk/context/serving.py +20 -8
  181. agenta/sdk/context/tracing.py +40 -22
  182. agenta/sdk/contexts/__init__.py +0 -0
  183. agenta/sdk/contexts/routing.py +38 -0
  184. agenta/sdk/contexts/running.py +57 -0
  185. agenta/sdk/contexts/tracing.py +86 -0
  186. agenta/sdk/decorators/__init__.py +1 -0
  187. agenta/sdk/decorators/routing.py +284 -0
  188. agenta/sdk/decorators/running.py +692 -98
  189. agenta/sdk/decorators/serving.py +20 -21
  190. agenta/sdk/decorators/tracing.py +176 -131
  191. agenta/sdk/engines/__init__.py +0 -0
  192. agenta/sdk/engines/running/__init__.py +0 -0
  193. agenta/sdk/engines/running/utils.py +17 -0
  194. agenta/sdk/engines/tracing/__init__.py +1 -0
  195. agenta/sdk/engines/tracing/attributes.py +185 -0
  196. agenta/sdk/engines/tracing/conventions.py +49 -0
  197. agenta/sdk/engines/tracing/exporters.py +130 -0
  198. agenta/sdk/engines/tracing/inline.py +1154 -0
  199. agenta/sdk/engines/tracing/processors.py +190 -0
  200. agenta/sdk/engines/tracing/propagation.py +102 -0
  201. agenta/sdk/engines/tracing/spans.py +136 -0
  202. agenta/sdk/engines/tracing/tracing.py +324 -0
  203. agenta/sdk/evaluations/__init__.py +2 -0
  204. agenta/sdk/evaluations/metrics.py +37 -0
  205. agenta/sdk/evaluations/preview/__init__.py +0 -0
  206. agenta/sdk/evaluations/preview/evaluate.py +765 -0
  207. agenta/sdk/evaluations/preview/utils.py +861 -0
  208. agenta/sdk/evaluations/results.py +66 -0
  209. agenta/sdk/evaluations/runs.py +152 -0
  210. agenta/sdk/evaluations/scenarios.py +48 -0
  211. agenta/sdk/litellm/litellm.py +12 -0
  212. agenta/sdk/litellm/mockllm.py +6 -8
  213. agenta/sdk/litellm/mocks/__init__.py +5 -5
  214. agenta/sdk/managers/applications.py +304 -0
  215. agenta/sdk/managers/config.py +2 -2
  216. agenta/sdk/managers/evaluations.py +0 -0
  217. agenta/sdk/managers/evaluators.py +303 -0
  218. agenta/sdk/managers/secrets.py +161 -24
  219. agenta/sdk/managers/shared.py +3 -1
  220. agenta/sdk/managers/testsets.py +441 -0
  221. agenta/sdk/managers/vault.py +3 -3
  222. agenta/sdk/middleware/auth.py +0 -176
  223. agenta/sdk/middleware/vault.py +203 -8
  224. agenta/sdk/middlewares/__init__.py +0 -0
  225. agenta/sdk/middlewares/routing/__init__.py +0 -0
  226. agenta/sdk/middlewares/routing/auth.py +263 -0
  227. agenta/sdk/middlewares/routing/cors.py +30 -0
  228. agenta/sdk/middlewares/routing/otel.py +29 -0
  229. agenta/sdk/middlewares/running/__init__.py +0 -0
  230. agenta/sdk/middlewares/running/normalizer.py +321 -0
  231. agenta/sdk/middlewares/running/resolver.py +161 -0
  232. agenta/sdk/middlewares/running/vault.py +140 -0
  233. agenta/sdk/models/__init__.py +0 -0
  234. agenta/sdk/models/blobs.py +33 -0
  235. agenta/sdk/models/evaluations.py +119 -0
  236. agenta/sdk/models/git.py +126 -0
  237. agenta/sdk/models/shared.py +167 -0
  238. agenta/sdk/models/testsets.py +163 -0
  239. agenta/sdk/models/tracing.py +202 -0
  240. agenta/sdk/models/workflows.py +753 -0
  241. agenta/sdk/tracing/exporters.py +67 -17
  242. agenta/sdk/tracing/processors.py +97 -0
  243. agenta/sdk/tracing/propagation.py +3 -1
  244. agenta/sdk/tracing/spans.py +4 -0
  245. agenta/sdk/tracing/tracing.py +13 -13
  246. agenta/sdk/types.py +211 -17
  247. agenta/sdk/utils/cache.py +1 -1
  248. agenta/sdk/utils/client.py +38 -0
  249. agenta/sdk/utils/helpers.py +13 -12
  250. agenta/sdk/utils/logging.py +18 -78
  251. agenta/sdk/utils/references.py +23 -0
  252. agenta/sdk/workflows/builtin.py +600 -0
  253. agenta/sdk/workflows/configurations.py +22 -0
  254. agenta/sdk/workflows/errors.py +292 -0
  255. agenta/sdk/workflows/handlers.py +1791 -0
  256. agenta/sdk/workflows/interfaces.py +948 -0
  257. agenta/sdk/workflows/sandbox.py +118 -0
  258. agenta/sdk/workflows/utils.py +303 -6
  259. {agenta-0.57.0.dist-info → agenta-0.65.0.dist-info}/METADATA +44 -47
  260. agenta-0.65.0.dist-info/RECORD +421 -0
  261. agenta/sdk/middleware/adapt.py +0 -253
  262. agenta/sdk/middleware/base.py +0 -40
  263. agenta/sdk/middleware/flags.py +0 -40
  264. agenta/sdk/workflows/types.py +0 -472
  265. agenta-0.57.0.dist-info/RECORD +0 -371
  266. /agenta/sdk/{workflows → engines/running}/registry.py +0 -0
  267. {agenta-0.57.0.dist-info → agenta-0.65.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,303 @@
1
+ from typing import Dict, Any, Callable, Optional
2
+ from uuid import uuid4, UUID
3
+ from traceback import print_exc
4
+
5
+ from agenta.sdk.utils.client import authed_api
6
+ from agenta.sdk.decorators.running import auto_workflow, is_workflow
7
+ from agenta.sdk.models.workflows import (
8
+ EvaluatorRevision,
9
+ #
10
+ EvaluatorRevisionResponse,
11
+ #
12
+ SimpleEvaluatorFlags,
13
+ SimpleEvaluatorData,
14
+ SimpleEvaluatorCreate,
15
+ SimpleEvaluatorEdit,
16
+ #
17
+ SimpleEvaluatorResponse,
18
+ #
19
+ Reference,
20
+ )
21
+
22
+ from agenta.sdk.utils.references import get_slug_from_name_and_id
23
+
24
+
25
+ async def _retrieve_evaluator(
26
+ evaluator_id: Optional[UUID] = None,
27
+ evaluator_slug: Optional[str] = None,
28
+ evaluator_revision_id: Optional[UUID] = None,
29
+ evaluator_revision_slug: Optional[str] = None,
30
+ ) -> Optional[EvaluatorRevision]:
31
+ payload = {
32
+ "evaluator_ref": (
33
+ {
34
+ "id": str(evaluator_id) if evaluator_id else None,
35
+ "slug": str(evaluator_slug),
36
+ }
37
+ if evaluator_id or evaluator_slug
38
+ else None
39
+ ),
40
+ "evaluator_revision_ref": (
41
+ {
42
+ "id": str(evaluator_revision_id) if evaluator_revision_id else None,
43
+ "slug": evaluator_revision_slug,
44
+ }
45
+ if evaluator_revision_id or evaluator_revision_slug
46
+ else None
47
+ ),
48
+ }
49
+
50
+ # print(" --- payload:", payload)
51
+
52
+ response = authed_api()(
53
+ method="POST",
54
+ endpoint=f"/preview/evaluators/revisions/retrieve",
55
+ json=payload,
56
+ )
57
+
58
+ response.raise_for_status()
59
+
60
+ evaluator_revision_response = EvaluatorRevisionResponse(**response.json())
61
+
62
+ evaluator_revision = evaluator_revision_response.evaluator_revision
63
+
64
+ # print(" --- evaluator_revision:", evaluator_revision)
65
+
66
+ return evaluator_revision
67
+
68
+
69
+ async def aretrieve(
70
+ evaluator_revision_id: Optional[UUID] = None,
71
+ ) -> Optional[EvaluatorRevision]:
72
+ # print("\n--------- RETRIEVE EVALUATOR")
73
+ response = await _retrieve_evaluator(
74
+ evaluator_revision_id=evaluator_revision_id,
75
+ )
76
+
77
+ return response
78
+
79
+
80
+ async def aupsert(
81
+ *,
82
+ evaluator_id: Optional[UUID] = None,
83
+ evaluator_slug: Optional[str] = None,
84
+ evaluator_revision_id: Optional[UUID] = None,
85
+ evaluator_revision_slug: Optional[str] = None,
86
+ #
87
+ handler: Callable,
88
+ script: Optional[str] = None,
89
+ parameters: Optional[Dict[str, Any]] = None,
90
+ #
91
+ name: Optional[str] = None,
92
+ description: Optional[str] = None,
93
+ ) -> Optional[UUID]:
94
+ # print("\n--------- UPSERT EVALUATOR")
95
+ try:
96
+ if not is_workflow(handler):
97
+ evaluator_workflow = auto_workflow(
98
+ handler,
99
+ #
100
+ script=script,
101
+ parameters=parameters,
102
+ #
103
+ name=name,
104
+ description=description,
105
+ )
106
+ else:
107
+ evaluator_workflow = handler
108
+
109
+ req = await evaluator_workflow.inspect()
110
+
111
+ legacy_application_flags = SimpleEvaluatorFlags(**req.flags)
112
+
113
+ simple_evaluator_data = SimpleEvaluatorData(
114
+ **(
115
+ req.interface.model_dump(mode="json", exclude_none=True)
116
+ if req and req.interface
117
+ else {}
118
+ ),
119
+ **(
120
+ req.configuration.model_dump(mode="json", exclude_none=True)
121
+ if req and req.configuration
122
+ else {}
123
+ ),
124
+ )
125
+ # print(" ---:", simple_evaluator_data.model_dump(mode="json", exclude_none=True))
126
+
127
+ retrieve_response = None
128
+
129
+ if req.references is not None:
130
+ _evaluator_revision_ref = req.references.get("evaluator_revision", {})
131
+ if isinstance(_evaluator_revision_ref, Reference):
132
+ _evaluator_revision_ref = _evaluator_revision_ref.model_dump(
133
+ mode="json",
134
+ exclude_none=True,
135
+ )
136
+ if not isinstance(_evaluator_revision_ref, dict):
137
+ _evaluator_revision_ref = {}
138
+
139
+ _evaluator_revision_id = _evaluator_revision_ref.get("id")
140
+ _evaluator_revision_slug = _evaluator_revision_ref.get("slug")
141
+
142
+ evaluator_revision_id = evaluator_revision_id or _evaluator_revision_id
143
+ evaluator_revision_slug = (
144
+ evaluator_revision_slug or _evaluator_revision_slug
145
+ )
146
+
147
+ _evaluator_ref = req.references.get("evaluator", {})
148
+ if isinstance(_evaluator_ref, Reference):
149
+ _evaluator_ref = _evaluator_ref.model_dump(
150
+ mode="json",
151
+ exclude_none=True,
152
+ )
153
+ if not isinstance(_evaluator_ref, dict):
154
+ _evaluator_ref = {}
155
+
156
+ _evaluator_id = _evaluator_ref.get("id")
157
+ _evaluator_slug = _evaluator_ref.get("slug")
158
+
159
+ evaluator_id = evaluator_id or _evaluator_id
160
+ evaluator_slug = evaluator_slug or _evaluator_slug
161
+
162
+ revision = req.data.revision if req and req.data else None
163
+ if revision:
164
+ name = name or revision.get("name")
165
+ description = description or revision.get("description")
166
+
167
+ name = (
168
+ name or req.data.revision.get("name")
169
+ if req and req.data and req.data.revision
170
+ else None
171
+ )
172
+
173
+ description = (
174
+ description or req.data.revision.get("description")
175
+ if req and req.data and req.data.revision
176
+ else None
177
+ )
178
+
179
+ evaluator_slug = (
180
+ evaluator_slug
181
+ or get_slug_from_name_and_id(
182
+ name=name,
183
+ id=evaluator_id or uuid4(),
184
+ )
185
+ if name
186
+ else uuid4().hex[-12:]
187
+ )
188
+
189
+ # print(
190
+ # evaluator_id,
191
+ # evaluator_slug,
192
+ # evaluator_revision_id,
193
+ # evaluator_revision_slug,
194
+ # )
195
+
196
+ if evaluator_revision_id or evaluator_revision_slug:
197
+ retrieve_response = await _retrieve_evaluator(
198
+ evaluator_revision_id=evaluator_revision_id,
199
+ evaluator_revision_slug=evaluator_revision_slug,
200
+ )
201
+ elif evaluator_id or evaluator_slug:
202
+ retrieve_response = await _retrieve_evaluator(
203
+ evaluator_id=evaluator_id,
204
+ evaluator_slug=evaluator_slug,
205
+ )
206
+
207
+ except Exception as e:
208
+ print("[ERROR]: Failed to prepare evaluator:")
209
+ print_exc()
210
+ return None
211
+
212
+ # print("Retrieve response:", retrieve_response)
213
+
214
+ if retrieve_response and retrieve_response.id and retrieve_response.evaluator_id:
215
+ evaluator_id = retrieve_response.evaluator_id
216
+ # print(" --- Updating evaluator...", evaluator_id)
217
+ evaluator_edit_request = SimpleEvaluatorEdit(
218
+ id=evaluator_id,
219
+ #
220
+ name=name,
221
+ description=description,
222
+ #
223
+ flags=legacy_application_flags,
224
+ #
225
+ data=simple_evaluator_data,
226
+ )
227
+
228
+ # print(" --- evaluator_edit_request:", evaluator_edit_request)
229
+
230
+ response = authed_api()(
231
+ method="PUT",
232
+ endpoint=f"/preview/simple/evaluators/{evaluator_id}",
233
+ json={
234
+ "evaluator": evaluator_edit_request.model_dump(
235
+ mode="json",
236
+ exclude_none=True,
237
+ )
238
+ },
239
+ )
240
+
241
+ # print(" --- response:", response.status_code, response.text)
242
+
243
+ try:
244
+ response.raise_for_status()
245
+ except Exception as e:
246
+ print("[ERROR]: Failed to update evaluator:", e)
247
+ print_exc()
248
+ return None
249
+
250
+ else:
251
+ # print(" --- Creating evaluator...")
252
+ evaluator_create_request = SimpleEvaluatorCreate(
253
+ slug=evaluator_slug or uuid4().hex[-12:],
254
+ #
255
+ name=name,
256
+ description=description,
257
+ #
258
+ flags=legacy_application_flags,
259
+ #
260
+ data=simple_evaluator_data,
261
+ )
262
+
263
+ # print(" --- evaluator_create_request:", evaluator_create_request)
264
+
265
+ response = authed_api()(
266
+ method="POST",
267
+ endpoint="/preview/simple/evaluators/",
268
+ json={
269
+ "evaluator": evaluator_create_request.model_dump(
270
+ mode="json",
271
+ exclude_none=True,
272
+ )
273
+ },
274
+ )
275
+
276
+ # print(" --- response:", response.status_code, response.text)
277
+
278
+ try:
279
+ response.raise_for_status()
280
+ except Exception as e:
281
+ print("[ERROR]: Failed to create evaluator:", e)
282
+ print_exc()
283
+ return None
284
+
285
+ evaluator_response = SimpleEvaluatorResponse(**response.json())
286
+
287
+ evaluator = evaluator_response.evaluator
288
+
289
+ if not evaluator or not evaluator.id:
290
+ return None
291
+
292
+ # print(" --- evaluator:", evaluator)
293
+
294
+ evaluator_revision = await _retrieve_evaluator(
295
+ evaluator_id=evaluator.id,
296
+ )
297
+
298
+ if not evaluator_revision or not evaluator_revision.id:
299
+ return None
300
+
301
+ # print(evaluator_revision, "----------")
302
+
303
+ return evaluator_revision.id
@@ -1,19 +1,27 @@
1
1
  import re
2
2
  from typing import Optional, Dict, Any, List
3
3
 
4
- from agenta.sdk.context.serving import serving_context
4
+ from agenta.sdk.utils.logging import get_module_logger
5
+ from agenta.sdk.contexts.routing import RoutingContext
6
+ from agenta.sdk.contexts.running import RunningContext
5
7
  from agenta.sdk.assets import model_to_provider_mapping as _standard_providers
6
8
 
9
+ from agenta.sdk.middlewares.running.vault import get_secrets
10
+
11
+ import agenta as ag
12
+
13
+ log = get_module_logger(__name__)
14
+
7
15
 
8
16
  class SecretsManager:
9
17
  @staticmethod
10
18
  def get_from_route() -> Optional[List[Dict[str, Any]]]:
11
- context = serving_context.get()
19
+ context = RoutingContext.get()
12
20
 
13
21
  secrets = context.secrets
14
22
 
15
23
  if not secrets:
16
- return None
24
+ return []
17
25
 
18
26
  return secrets
19
27
 
@@ -119,11 +127,17 @@ class SecretsManager:
119
127
  # The reason is that custom providers are in fact openai compatible providers
120
128
  # They need to be passed in litellm as openai/modelname
121
129
 
122
- if "custom" in model:
123
- modified_model = model.replace(f"{provider_slug}/custom/", "openai/")
124
- return modified_model.replace(f"{provider_slug}/", "")
130
+ modified_model = model
131
+
132
+ if "custom" in modified_model:
133
+ modified_model = modified_model.replace(
134
+ f"{provider_slug}/custom/", "openai/"
135
+ )
136
+
137
+ if provider_slug:
138
+ modified_model = modified_model.replace(f"{provider_slug}/", "")
125
139
 
126
- return model.replace(f"{provider_slug}/", "")
140
+ return modified_model
127
141
 
128
142
  @staticmethod
129
143
  def get_provider_settings(model: str) -> Optional[Dict]:
@@ -137,6 +151,8 @@ class SecretsManager:
137
151
  Dict: A dictionary containing all parameters needed for litellm.completion
138
152
  """
139
153
 
154
+ request_provider_model = model
155
+
140
156
  # STEP 1: get vault secrets from route context and transform it
141
157
  secrets = SecretsManager.get_from_route()
142
158
  if not secrets:
@@ -146,11 +162,11 @@ class SecretsManager:
146
162
  secrets = SecretsManager._parse_secrets(secrets=secrets)
147
163
 
148
164
  # STEP 2: check model exists in supported standard models
149
- provider = _standard_providers.get(model)
165
+ provider = _standard_providers.get(request_provider_model)
150
166
  if not provider:
151
167
  # check and get provider kind if model exists in custom provider models
152
168
  provider = SecretsManager._custom_providers_get(
153
- model=model,
169
+ model=request_provider_model,
154
170
  secrets=secrets,
155
171
  )
156
172
 
@@ -159,16 +175,19 @@ class SecretsManager:
159
175
  return None
160
176
 
161
177
  # STEP 2c: get litellm compatible model
162
- provider_slug = SecretsManager._custom_provider_slug_get(
163
- model=model, secrets=secrets
178
+ request_provider_slug = (
179
+ SecretsManager._custom_provider_slug_get(
180
+ model=request_provider_model, secrets=secrets
181
+ )
182
+ or ""
164
183
  )
165
- model = SecretsManager._get_compatible_model(
166
- model=model, provider_slug=provider_slug
184
+ compatible_provider_model = SecretsManager._get_compatible_model(
185
+ model=request_provider_model, provider_slug=request_provider_slug
167
186
  )
168
187
 
169
188
  # STEP 3: initialize provider settings and simplify provider name
170
- provider_settings = {"model": model}
171
- provider_name = re.sub(
189
+ provider_settings = dict(model=compatible_provider_model)
190
+ request_provider_kind = re.sub(
172
191
  r"[\s-]+", "", provider.lower()
173
192
  ) # normalizing other special characters too (azure-openai)
174
193
 
@@ -180,23 +199,141 @@ class SecretsManager:
180
199
  # i). Extract API key if present
181
200
  # (for standard models -- openai/anthropic/gemini, etc)
182
201
  if secret.get("kind") == "provider_key":
183
- provider_kind = secret_data.get("kind", "")
202
+ secret_provider_kind = secret_data.get("kind", "")
184
203
 
185
- if provider_kind == provider_name:
204
+ if request_provider_kind == secret_provider_kind:
186
205
  if "key" in provider_info:
187
206
  provider_settings["api_key"] = provider_info["key"]
188
207
  continue
189
208
 
190
209
  # ii). Extract Credentials if present
191
- # (for custom providers -- aws bedrock/sagemaker, vertexai, etc)
210
+ # (for custom providers -- aws bedrock/sagemaker, vertex_ai, etc)
192
211
  elif secret.get("kind") == "custom_provider":
193
- provider_kind = provider_info.get("kind", "").lower().replace(" ", "")
194
- provider_slug = secret_data.get("provider_slug", "")
195
- provider_extras = provider_info.get("extras", {})
212
+ secret_provider_kind = (
213
+ provider_info.get("kind", "").lower().replace(" ", "")
214
+ )
215
+ secret_provider_slug = secret_data.get("provider_slug", "")
216
+ secret_provider_models = secret_data.get("models", "")
217
+ secret_provider_extras = provider_info.get("extras", {})
218
+
219
+ if (
220
+ request_provider_kind == secret_provider_kind
221
+ and request_provider_slug == secret_provider_slug
222
+ and request_provider_model in secret_provider_models
223
+ ):
224
+ if secret_provider_extras:
225
+ provider_settings.update(secret_provider_extras)
226
+ continue
227
+
228
+ if len(provider_settings.keys()) <= 1:
229
+ return None
230
+
231
+ return provider_settings
232
+
233
+ @staticmethod
234
+ async def retrieve_secrets():
235
+ return await get_secrets(
236
+ f"{ag.DEFAULT_AGENTA_SINGLETON_INSTANCE.host}/api",
237
+ RunningContext.get().credentials,
238
+ )
239
+
240
+ @staticmethod
241
+ async def ensure_secrets_in_workflow():
242
+ ctx = RunningContext.get()
243
+
244
+ ctx.secrets = await SecretsManager.retrieve_secrets()
245
+
246
+ RunningContext.set(ctx)
247
+
248
+ return ctx.secrets
249
+
250
+ @staticmethod
251
+ def get_provider_settings_from_workflow(model: str) -> Optional[Dict]:
252
+ """
253
+ Builds the LLM request with appropriate kwargs based on the custom provider/model
254
+
255
+ Args:
256
+ model (str): The name of the model
257
+
258
+ Returns:
259
+ Dict: A dictionary containing all parameters needed for litellm.completion
260
+ """
261
+
262
+ request_provider_model = model
263
+
264
+ # STEP 1: get vault secrets from route context and transform it
265
+ secrets = RunningContext.get().secrets
266
+ if not secrets:
267
+ return None
268
+
269
+ # STEP 1b: Parse secrets into usable format
270
+ secrets = SecretsManager._parse_secrets(secrets=secrets)
271
+
272
+ # STEP 2: check model exists in supported standard models
273
+ provider = _standard_providers.get(request_provider_model)
274
+ if not provider:
275
+ # check and get provider kind if model exists in custom provider models
276
+ provider = SecretsManager._custom_providers_get(
277
+ model=request_provider_model,
278
+ secrets=secrets,
279
+ )
280
+
281
+ # STEP 2b: return None in the case provider is None
282
+ if not provider:
283
+ return None
284
+
285
+ # STEP 2c: get litellm compatible model
286
+ request_provider_slug = (
287
+ SecretsManager._custom_provider_slug_get(
288
+ model=request_provider_model, secrets=secrets
289
+ )
290
+ or ""
291
+ )
292
+ compatible_provider_model = SecretsManager._get_compatible_model(
293
+ model=request_provider_model, provider_slug=request_provider_slug
294
+ )
196
295
 
197
- if provider_kind == provider_name or provider_slug == provider_name:
198
- if provider_extras:
199
- provider_settings.update(provider_extras)
296
+ # STEP 3: initialize provider settings and simplify provider name
297
+ provider_settings = dict(model=compatible_provider_model)
298
+ request_provider_kind = re.sub(
299
+ r"[\s-]+", "", provider.lower()
300
+ ) # normalizing other special characters too (azure-openai)
301
+
302
+ # STEP 4: get credentials for model
303
+ for secret in secrets:
304
+ secret_data = secret.get("data", {})
305
+ provider_info = secret_data.get("provider", {})
306
+
307
+ # i). Extract API key if present
308
+ # (for standard models -- openai/anthropic/gemini, etc)
309
+ if secret.get("kind") == "provider_key":
310
+ secret_provider_kind = secret_data.get("kind", "")
311
+
312
+ if request_provider_kind == secret_provider_kind:
313
+ if "key" in provider_info:
314
+ provider_settings["api_key"] = provider_info["key"]
200
315
  continue
201
316
 
317
+ # ii). Extract Credentials if present
318
+ # (for custom providers -- aws bedrock/sagemaker, vertex_ai, etc)
319
+ elif secret.get("kind") == "custom_provider":
320
+ secret_provider_kind = (
321
+ provider_info.get("kind", "").lower().replace(" ", "")
322
+ )
323
+ secret_provider_slug = secret_data.get("provider_slug", "")
324
+ secret_provider_models = secret_data.get("models", "")
325
+ secret_provider_extras = provider_info.get("extras", {})
326
+
327
+ if (
328
+ request_provider_kind == secret_provider_kind
329
+ and request_provider_slug == secret_provider_slug
330
+ and request_provider_model in secret_provider_models
331
+ ):
332
+ if secret_provider_extras:
333
+ provider_settings.update(secret_provider_extras)
334
+ continue
335
+
336
+ if len(provider_settings.keys()) <= 1:
337
+ return None
338
+
202
339
  return provider_settings
@@ -478,7 +478,9 @@ class SharedManager:
478
478
  config=ConfigRequest(
479
479
  params=parameters,
480
480
  variant_ref=variant_ref.model_dump() if variant_ref else None, # type: ignore
481
- application_ref=application_ref.model_dump() if application_ref else None, # type: ignore
481
+ application_ref=application_ref.model_dump()
482
+ if application_ref
483
+ else None, # type: ignore
482
484
  )
483
485
  )
484
486