agenta 0.12.3__py3-none-any.whl → 0.32.0a1__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 agenta might be problematic. Click here for more details.

Files changed (244) hide show
  1. agenta/__init__.py +64 -7
  2. agenta/cli/helper.py +7 -3
  3. agenta/cli/main.py +15 -50
  4. agenta/cli/variant_commands.py +50 -29
  5. agenta/client/Readme.md +72 -64
  6. agenta/client/api.py +2 -2
  7. agenta/client/backend/__init__.py +193 -22
  8. agenta/client/backend/access_control/__init__.py +1 -0
  9. agenta/client/backend/access_control/client.py +167 -0
  10. agenta/client/backend/apps/__init__.py +1 -0
  11. agenta/client/backend/apps/client.py +1691 -0
  12. agenta/client/backend/bases/__init__.py +1 -0
  13. agenta/client/backend/bases/client.py +190 -0
  14. agenta/client/backend/client.py +2508 -5712
  15. agenta/client/backend/configs/__init__.py +1 -0
  16. agenta/client/backend/configs/client.py +604 -0
  17. agenta/client/backend/containers/__init__.py +5 -0
  18. agenta/client/backend/containers/client.py +648 -0
  19. agenta/client/backend/containers/types/__init__.py +5 -0
  20. agenta/client/backend/{types → containers/types}/container_templates_response.py +1 -2
  21. agenta/client/backend/core/__init__.py +30 -0
  22. agenta/client/backend/core/client_wrapper.py +42 -9
  23. agenta/client/backend/core/file.py +70 -0
  24. agenta/client/backend/core/http_client.py +575 -0
  25. agenta/client/backend/core/jsonable_encoder.py +33 -39
  26. agenta/client/backend/core/pydantic_utilities.py +325 -0
  27. agenta/client/backend/core/query_encoder.py +60 -0
  28. agenta/client/backend/core/remove_none_from_dict.py +2 -2
  29. agenta/client/backend/core/request_options.py +35 -0
  30. agenta/client/backend/core/serialization.py +276 -0
  31. agenta/client/backend/environments/__init__.py +1 -0
  32. agenta/client/backend/environments/client.py +196 -0
  33. agenta/client/backend/evaluations/__init__.py +1 -0
  34. agenta/client/backend/evaluations/client.py +1469 -0
  35. agenta/client/backend/evaluators/__init__.py +1 -0
  36. agenta/client/backend/evaluators/client.py +1283 -0
  37. agenta/client/backend/observability/__init__.py +1 -0
  38. agenta/client/backend/observability/client.py +1286 -0
  39. agenta/client/backend/observability_v_1/__init__.py +5 -0
  40. agenta/client/backend/observability_v_1/client.py +763 -0
  41. agenta/client/backend/observability_v_1/types/__init__.py +7 -0
  42. agenta/client/backend/observability_v_1/types/format.py +5 -0
  43. agenta/client/backend/observability_v_1/types/query_analytics_response.py +7 -0
  44. agenta/client/backend/observability_v_1/types/query_traces_response.py +11 -0
  45. agenta/client/backend/scopes/__init__.py +1 -0
  46. agenta/client/backend/scopes/client.py +114 -0
  47. agenta/client/backend/testsets/__init__.py +1 -0
  48. agenta/client/backend/testsets/client.py +1284 -0
  49. agenta/client/backend/types/__init__.py +154 -26
  50. agenta/client/backend/types/agenta_node_dto.py +48 -0
  51. agenta/client/backend/types/agenta_node_dto_nodes_value.py +6 -0
  52. agenta/client/backend/types/agenta_nodes_response.py +30 -0
  53. agenta/client/backend/types/agenta_root_dto.py +30 -0
  54. agenta/client/backend/types/agenta_roots_response.py +30 -0
  55. agenta/client/backend/types/agenta_tree_dto.py +30 -0
  56. agenta/client/backend/types/agenta_trees_response.py +30 -0
  57. agenta/client/backend/types/aggregated_result.py +16 -31
  58. agenta/client/backend/types/aggregated_result_evaluator_config.py +8 -0
  59. agenta/client/backend/types/analytics_response.py +24 -0
  60. agenta/client/backend/types/app.py +17 -30
  61. agenta/client/backend/types/app_variant_response.py +36 -0
  62. agenta/client/backend/types/app_variant_revision.py +17 -32
  63. agenta/client/backend/types/base_output.py +13 -28
  64. agenta/client/backend/types/body_import_testset.py +15 -31
  65. agenta/client/backend/types/bucket_dto.py +26 -0
  66. agenta/client/backend/types/collect_status_response.py +22 -0
  67. agenta/client/backend/types/config_db.py +16 -31
  68. agenta/client/backend/types/config_dto.py +32 -0
  69. agenta/client/backend/types/config_response_model.py +32 -0
  70. agenta/client/backend/types/correct_answer.py +22 -0
  71. agenta/client/backend/types/create_app_output.py +13 -28
  72. agenta/client/backend/types/create_span.py +45 -0
  73. agenta/client/backend/types/create_trace_response.py +22 -0
  74. agenta/client/backend/types/docker_env_vars.py +13 -28
  75. agenta/client/backend/types/environment_output.py +22 -34
  76. agenta/client/backend/types/environment_output_extended.py +31 -0
  77. agenta/client/backend/types/environment_revision.py +26 -0
  78. agenta/client/backend/types/error.py +22 -0
  79. agenta/client/backend/types/evaluation.py +22 -33
  80. agenta/client/backend/types/evaluation_scenario.py +18 -33
  81. agenta/client/backend/types/evaluation_scenario_input.py +16 -31
  82. agenta/client/backend/types/evaluation_scenario_output.py +17 -30
  83. agenta/client/backend/types/evaluation_scenario_result.py +14 -29
  84. agenta/client/backend/types/evaluation_scenario_score_update.py +21 -0
  85. agenta/client/backend/types/evaluation_status_enum.py +11 -29
  86. agenta/client/backend/types/evaluation_type.py +3 -21
  87. agenta/client/backend/types/evaluator.py +20 -31
  88. agenta/client/backend/types/evaluator_config.py +21 -33
  89. agenta/client/backend/types/evaluator_mapping_output_interface.py +21 -0
  90. agenta/client/backend/types/evaluator_output_interface.py +21 -0
  91. agenta/client/backend/types/exception_dto.py +26 -0
  92. agenta/client/backend/types/get_config_response.py +23 -0
  93. agenta/client/backend/types/header_dto.py +22 -0
  94. agenta/client/backend/types/http_validation_error.py +14 -29
  95. agenta/client/backend/types/human_evaluation.py +18 -34
  96. agenta/client/backend/types/human_evaluation_scenario.py +22 -38
  97. agenta/client/backend/types/human_evaluation_scenario_input.py +13 -28
  98. agenta/client/backend/types/human_evaluation_scenario_output.py +13 -28
  99. agenta/client/backend/types/human_evaluation_scenario_update.py +30 -0
  100. agenta/client/backend/types/human_evaluation_update.py +22 -0
  101. agenta/client/backend/types/image.py +18 -32
  102. agenta/client/backend/types/invite_request.py +16 -30
  103. agenta/client/backend/types/legacy_analytics_response.py +29 -0
  104. agenta/client/backend/types/legacy_data_point.py +27 -0
  105. agenta/client/backend/types/lifecycle_dto.py +24 -0
  106. agenta/client/backend/types/link_dto.py +24 -0
  107. agenta/client/backend/types/list_api_keys_response.py +24 -0
  108. agenta/client/backend/types/llm_run_rate_limit.py +13 -28
  109. agenta/client/backend/types/llm_tokens.py +23 -0
  110. agenta/client/backend/types/metrics_dto.py +24 -0
  111. agenta/client/backend/types/new_human_evaluation.py +27 -0
  112. agenta/client/backend/types/new_testset.py +16 -31
  113. agenta/client/backend/types/node_dto.py +24 -0
  114. agenta/client/backend/types/node_type.py +19 -0
  115. agenta/client/backend/types/o_tel_context_dto.py +22 -0
  116. agenta/client/backend/types/o_tel_event_dto.py +23 -0
  117. agenta/client/backend/types/o_tel_extra_dto.py +26 -0
  118. agenta/client/backend/types/o_tel_link_dto.py +23 -0
  119. agenta/client/backend/types/o_tel_span_dto.py +37 -0
  120. agenta/client/backend/types/o_tel_span_kind.py +15 -0
  121. agenta/client/backend/types/o_tel_spans_response.py +24 -0
  122. agenta/client/backend/types/o_tel_status_code.py +8 -0
  123. agenta/client/backend/types/organization.py +22 -35
  124. agenta/client/backend/types/organization_output.py +13 -28
  125. agenta/client/backend/types/outputs.py +5 -0
  126. agenta/client/backend/types/parent_dto.py +21 -0
  127. agenta/client/backend/types/permission.py +41 -0
  128. agenta/client/backend/types/projects_response.py +28 -0
  129. agenta/client/backend/types/provider_key_dto.py +23 -0
  130. agenta/client/backend/types/provider_kind.py +21 -0
  131. agenta/client/backend/types/reference_dto.py +23 -0
  132. agenta/client/backend/types/reference_request_model.py +23 -0
  133. agenta/client/backend/types/result.py +18 -31
  134. agenta/client/backend/types/root_dto.py +21 -0
  135. agenta/client/backend/types/{human_evaluation_scenario_score.py → score.py} +1 -1
  136. agenta/client/backend/types/secret_dto.py +24 -0
  137. agenta/client/backend/types/{human_evaluation_scenario_update_score.py → secret_kind.py} +1 -1
  138. agenta/client/backend/types/secret_response_dto.py +27 -0
  139. agenta/client/backend/types/simple_evaluation_output.py +13 -28
  140. agenta/client/backend/types/span.py +39 -49
  141. agenta/client/backend/types/span_detail.py +44 -0
  142. agenta/client/backend/types/span_dto.py +54 -0
  143. agenta/client/backend/types/span_dto_nodes_value.py +9 -0
  144. agenta/client/backend/types/span_status_code.py +5 -0
  145. agenta/client/backend/types/span_variant.py +23 -0
  146. agenta/client/backend/types/status_code.py +5 -0
  147. agenta/client/backend/types/status_dto.py +23 -0
  148. agenta/client/backend/types/template.py +14 -29
  149. agenta/client/backend/types/template_image_info.py +21 -35
  150. agenta/client/backend/types/test_set_output_response.py +20 -33
  151. agenta/client/backend/types/test_set_simple_response.py +13 -28
  152. agenta/client/backend/types/time_dto.py +23 -0
  153. agenta/client/backend/types/trace_detail.py +44 -0
  154. agenta/client/backend/types/tree_dto.py +23 -0
  155. agenta/client/backend/types/tree_type.py +5 -0
  156. agenta/client/backend/types/update_app_output.py +22 -0
  157. agenta/client/backend/types/uri.py +13 -28
  158. agenta/client/backend/types/validation_error.py +13 -28
  159. agenta/client/backend/types/variant_action.py +14 -29
  160. agenta/client/backend/types/variant_action_enum.py +1 -19
  161. agenta/client/backend/types/with_pagination.py +26 -0
  162. agenta/client/backend/types/workspace_member_response.py +23 -0
  163. agenta/client/backend/types/workspace_permission.py +25 -0
  164. agenta/client/backend/types/workspace_response.py +29 -0
  165. agenta/client/backend/types/workspace_role.py +15 -0
  166. agenta/client/backend/types/workspace_role_response.py +23 -0
  167. agenta/client/backend/variants/__init__.py +5 -0
  168. agenta/client/backend/variants/client.py +2814 -0
  169. agenta/client/backend/variants/types/__init__.py +7 -0
  170. agenta/client/backend/variants/types/add_variant_from_base_and_config_response.py +8 -0
  171. agenta/client/backend/vault/__init__.py +1 -0
  172. agenta/client/backend/vault/client.py +685 -0
  173. agenta/client/client.py +1 -1
  174. agenta/config.py +0 -2
  175. agenta/config.toml +0 -1
  176. agenta/docker/docker-assets/Dockerfile.cloud.template +2 -1
  177. agenta/docker/docker-assets/Dockerfile.template +2 -1
  178. agenta/docker/docker_utils.py +11 -12
  179. agenta/sdk/__init__.py +58 -7
  180. agenta/sdk/agenta_init.py +182 -164
  181. agenta/sdk/assets.py +95 -0
  182. agenta/sdk/client.py +56 -0
  183. agenta/sdk/context/__init__.py +0 -0
  184. agenta/sdk/context/exporting.py +25 -0
  185. agenta/sdk/context/routing.py +27 -0
  186. agenta/sdk/context/tracing.py +28 -0
  187. agenta/sdk/decorators/__init__.py +0 -0
  188. agenta/sdk/decorators/routing.py +576 -0
  189. agenta/sdk/decorators/tracing.py +296 -0
  190. agenta/sdk/litellm/__init__.py +1 -0
  191. agenta/sdk/litellm/litellm.py +314 -0
  192. agenta/sdk/litellm/mockllm.py +27 -0
  193. agenta/sdk/litellm/mocks/__init__.py +26 -0
  194. agenta/sdk/managers/__init__.py +6 -0
  195. agenta/sdk/managers/config.py +208 -0
  196. agenta/sdk/managers/deployment.py +45 -0
  197. agenta/sdk/managers/secrets.py +38 -0
  198. agenta/sdk/managers/shared.py +639 -0
  199. agenta/sdk/managers/variant.py +182 -0
  200. agenta/sdk/managers/vault.py +16 -0
  201. agenta/sdk/middleware/__init__.py +0 -0
  202. agenta/sdk/middleware/auth.py +180 -0
  203. agenta/sdk/middleware/cache.py +47 -0
  204. agenta/sdk/middleware/config.py +255 -0
  205. agenta/sdk/middleware/cors.py +29 -0
  206. agenta/sdk/middleware/inline.py +38 -0
  207. agenta/sdk/middleware/mock.py +33 -0
  208. agenta/sdk/middleware/otel.py +40 -0
  209. agenta/sdk/middleware/vault.py +145 -0
  210. agenta/sdk/router.py +0 -7
  211. agenta/sdk/tracing/__init__.py +1 -0
  212. agenta/sdk/tracing/attributes.py +141 -0
  213. agenta/sdk/tracing/conventions.py +49 -0
  214. agenta/sdk/tracing/exporters.py +103 -0
  215. agenta/sdk/tracing/inline.py +1146 -0
  216. agenta/sdk/tracing/processors.py +121 -0
  217. agenta/sdk/tracing/spans.py +136 -0
  218. agenta/sdk/tracing/tracing.py +237 -0
  219. agenta/sdk/types.py +478 -74
  220. agenta/sdk/utils/__init__.py +0 -0
  221. agenta/sdk/utils/constants.py +1 -0
  222. agenta/sdk/utils/{helper/openai_cost.py → costs.py} +3 -0
  223. agenta/sdk/utils/exceptions.py +59 -0
  224. agenta/sdk/utils/globals.py +6 -10
  225. agenta/sdk/utils/helpers.py +8 -0
  226. agenta/sdk/utils/logging.py +21 -0
  227. agenta/sdk/utils/singleton.py +13 -0
  228. agenta/sdk/utils/timing.py +58 -0
  229. {agenta-0.12.3.dist-info → agenta-0.32.0a1.dist-info}/METADATA +98 -151
  230. agenta-0.32.0a1.dist-info/RECORD +263 -0
  231. {agenta-0.12.3.dist-info → agenta-0.32.0a1.dist-info}/WHEEL +1 -1
  232. agenta/client/backend/types/add_variant_from_base_and_config_response.py +0 -7
  233. agenta/client/backend/types/app_variant_output.py +0 -47
  234. agenta/client/backend/types/app_variant_output_extended.py +0 -50
  235. agenta/client/backend/types/delete_evaluation.py +0 -36
  236. agenta/client/backend/types/evaluation_webhook.py +0 -36
  237. agenta/client/backend/types/feedback.py +0 -40
  238. agenta/client/backend/types/get_config_reponse.py +0 -39
  239. agenta/client/backend/types/list_api_keys_output.py +0 -39
  240. agenta/client/backend/types/trace.py +0 -48
  241. agenta/sdk/agenta_decorator.py +0 -443
  242. agenta/sdk/context.py +0 -41
  243. agenta-0.12.3.dist-info/RECORD +0 -114
  244. {agenta-0.12.3.dist-info → agenta-0.32.0a1.dist-info}/entry_points.txt +0 -0
agenta/sdk/types.py CHANGED
@@ -1,13 +1,32 @@
1
1
  import json
2
- from typing import Any, Dict, List, Optional
2
+ from dataclasses import dataclass
3
+ from typing import Dict, List, Optional, Any, Union
3
4
 
4
- from pydantic import BaseModel, Extra, HttpUrl, Field
5
+ from pydantic import ConfigDict, BaseModel, HttpUrl
5
6
 
7
+ from agenta.client.backend.types.agenta_node_dto import AgentaNodeDto
8
+ from agenta.client.backend.types.agenta_nodes_response import AgentaNodesResponse
9
+ from typing import Annotated, List, Union, Optional, Dict, Literal, Any
10
+ from pydantic import BaseModel, Field, root_validator
11
+ from agenta.sdk.assets import supported_llm_models
6
12
 
7
- class InFile:
8
- def __init__(self, file_name: str, file_path: str):
9
- self.file_name = file_name
10
- self.file_path = file_path
13
+
14
+ @dataclass
15
+ class MultipleChoice:
16
+ choices: Union[List[str], Dict[str, List[str]]]
17
+
18
+
19
+ def MCField( # pylint: disable=invalid-name
20
+ default: str,
21
+ choices: Union[List[str], Dict[str, List[str]]],
22
+ ) -> Field:
23
+ field = Field(default=default, description="ID of the model to use")
24
+ if isinstance(choices, dict):
25
+ field.json_schema_extra = {"choices": choices, "x-parameter": "grouped_choice"}
26
+ elif isinstance(choices, list):
27
+ field.json_schema_extra = {"choices": choices, "x-parameter": "choice"}
28
+
29
+ return field
11
30
 
12
31
 
13
32
  class LLMTokenUsage(BaseModel):
@@ -16,95 +35,84 @@ class LLMTokenUsage(BaseModel):
16
35
  total_tokens: int
17
36
 
18
37
 
19
- class FuncResponse(BaseModel):
20
- message: str
21
- usage: Optional[LLMTokenUsage]
22
- cost: Optional[float]
23
- latency: float
38
+ class BaseResponse(BaseModel):
39
+ version: Optional[str] = "3.1"
40
+ data: Optional[Union[str, Dict[str, Any]]] = None
41
+ content_type: Optional[str] = "string"
42
+ tree: Optional[AgentaNodesResponse] = None
43
+ tree_id: Optional[str] = None
24
44
 
25
45
 
26
46
  class DictInput(dict):
27
- def __new__(cls, default_keys=None):
47
+ def __new__(cls, default_keys: Optional[List[str]] = None):
28
48
  instance = super().__new__(cls, default_keys)
29
49
  if default_keys is None:
30
50
  default_keys = []
31
- instance.data = [key for key in default_keys]
51
+ instance.data = [key for key in default_keys] # type: ignore
32
52
  return instance
33
53
 
34
54
  @classmethod
35
- def __modify_schema__(cls, field_schema):
36
- field_schema.update({"x-parameter": "dict"})
55
+ def __schema_type_properties__(cls) -> dict:
56
+ return {"x-parameter": "dict"}
37
57
 
38
58
 
39
59
  class TextParam(str):
40
60
  @classmethod
41
- def __modify_schema__(cls, field_schema):
42
- field_schema.update({"x-parameter": "text"})
61
+ def __schema_type_properties__(cls) -> dict:
62
+ return {"x-parameter": "text", "type": "string"}
43
63
 
44
64
 
45
65
  class BinaryParam(int):
46
66
  def __new__(cls, value: bool = False):
47
67
  instance = super().__new__(cls, int(value))
48
- instance.default = value
68
+ instance.default = value # type: ignore
49
69
  return instance
50
70
 
51
71
  @classmethod
52
- def __modify_schema__(cls, field_schema):
53
- field_schema.update(
54
- {
55
- "x-parameter": "bool",
56
- "type": "boolean",
57
- }
58
- )
72
+ def __schema_type_properties__(cls) -> dict:
73
+ return {
74
+ "x-parameter": "bool",
75
+ "type": "boolean",
76
+ }
59
77
 
60
78
 
61
79
  class IntParam(int):
62
80
  def __new__(cls, default: int = 6, minval: float = 1, maxval: float = 10):
63
81
  instance = super().__new__(cls, default)
64
- instance.minval = minval
65
- instance.maxval = maxval
82
+ instance.minval = minval # type: ignore
83
+ instance.maxval = maxval # type: ignore
66
84
  return instance
67
85
 
68
86
  @classmethod
69
- def __modify_schema__(cls, field_schema):
70
- field_schema.update(
71
- {
72
- "x-parameter": "int",
73
- "type": "integer",
74
- "minimum": 1,
75
- "maximum": 10,
76
- }
77
- )
87
+ def __schema_type_properties__(cls) -> dict:
88
+ return {"x-parameter": "int", "type": "integer"}
78
89
 
79
90
 
80
91
  class FloatParam(float):
81
92
  def __new__(cls, default: float = 0.5, minval: float = 0.0, maxval: float = 1.0):
82
93
  instance = super().__new__(cls, default)
83
- instance.minval = minval
84
- instance.maxval = maxval
94
+ instance.default = default # type: ignore
95
+ instance.minval = minval # type: ignore
96
+ instance.maxval = maxval # type: ignore
85
97
  return instance
86
98
 
87
99
  @classmethod
88
- def __modify_schema__(cls, field_schema):
89
- field_schema.update(
90
- {
91
- "x-parameter": "float",
92
- "type": "number",
93
- "minimum": 0.0,
94
- "maximum": 1.0,
95
- }
96
- )
100
+ def __schema_type_properties__(cls) -> dict:
101
+ return {"x-parameter": "float", "type": "number"}
97
102
 
98
103
 
99
104
  class MultipleChoiceParam(str):
100
- def __new__(cls, default: str = None, choices: List[str] = None):
101
- if type(default) is list:
105
+ def __new__(
106
+ cls, default: Optional[str] = None, choices: Optional[List[str]] = None
107
+ ):
108
+ if default is not None and type(default) is list:
102
109
  raise ValueError(
103
110
  "The order of the parameters for MultipleChoiceParam is wrong! It's MultipleChoiceParam(default, choices) and not the opposite"
104
111
  )
105
- if default is None and choices:
112
+
113
+ if not default and choices is not None:
106
114
  # if a default value is not provided,
107
- # uset the first value in the choices list
115
+ # set the first value in the choices list
108
116
  default = choices[0]
109
117
 
110
118
  if default is None and not choices:
@@ -112,24 +120,53 @@ class MultipleChoiceParam(str):
112
120
  raise ValueError("You must provide either a default value or choices")
113
121
 
114
122
  instance = super().__new__(cls, default)
115
- instance.choices = choices
116
- instance.default = default
123
+ instance.choices = choices # type: ignore
124
+ instance.default = default # type: ignore
117
125
  return instance
118
126
 
119
127
  @classmethod
120
- def __modify_schema__(cls, field_schema: dict[str, Any]):
121
- field_schema.update(
122
- {
123
- "x-parameter": "choice",
124
- "type": "string",
125
- "enum": [],
126
- }
127
- )
128
+ def __schema_type_properties__(cls) -> dict:
129
+ return {"x-parameter": "choice", "type": "string", "enum": []}
130
+
131
+
132
+ class GroupedMultipleChoiceParam(str):
133
+ def __new__(
134
+ cls,
135
+ default: Optional[str] = None,
136
+ choices: Optional[Dict[str, List[str]]] = None,
137
+ ):
138
+ if choices is None:
139
+ choices = {}
140
+ if default and not any(
141
+ default in choice_list for choice_list in choices.values()
142
+ ):
143
+ if not choices:
144
+ print(
145
+ f"Warning: Default value {default} provided but choices are empty."
146
+ )
147
+ else:
148
+ raise ValueError(
149
+ f"Default value {default} is not in the provided choices"
150
+ )
151
+
152
+ if not default:
153
+ default_selected_choice = next(
154
+ (choices for choices in choices.values()), None
155
+ )
156
+ if default_selected_choice:
157
+ default = default_selected_choice[0]
128
158
 
159
+ instance = super().__new__(cls, default)
160
+ instance.choices = choices # type: ignore
161
+ instance.default = default # type: ignore
162
+ return instance
129
163
 
130
- class Message(BaseModel):
131
- role: str
132
- content: str
164
+ @classmethod
165
+ def __schema_type_properties__(cls) -> dict:
166
+ return {
167
+ "x-parameter": "grouped_choice",
168
+ "type": "string",
169
+ }
133
170
 
134
171
 
135
172
  class MessagesInput(list):
@@ -144,30 +181,397 @@ class MessagesInput(list):
144
181
 
145
182
  """
146
183
 
147
- def __new__(cls, messages: List[Dict[str, str]] = None):
148
- instance = super().__new__(cls, messages)
149
- instance.default = messages
184
+ def __new__(cls, messages: List[Dict[str, str]] = []):
185
+ instance = super().__new__(cls)
186
+ instance.default = messages # type: ignore
150
187
  return instance
151
188
 
152
189
  @classmethod
153
- def __modify_schema__(cls, field_schema: dict[str, Any]):
154
- field_schema.update({"x-parameter": "messages", "type": "array"})
190
+ def __schema_type_properties__(cls) -> dict:
191
+ return {"x-parameter": "messages", "type": "array"}
155
192
 
156
193
 
157
194
  class FileInputURL(HttpUrl):
195
+ def __new__(cls, url: str):
196
+ instance = super().__new__(cls, url)
197
+ instance.default = url # type: ignore
198
+ return instance
199
+
158
200
  @classmethod
159
- def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None:
160
- field_schema.update({"x-parameter": "file_url", "type": "string"})
201
+ def __schema_type_properties__(cls) -> dict:
202
+ return {"x-parameter": "file_url", "type": "string"}
161
203
 
162
204
 
163
205
  class Context(BaseModel):
164
- class Config:
165
- extra = Extra.allow
206
+ model_config = ConfigDict(extra="allow")
166
207
 
167
208
  def to_json(self):
168
- return self.json()
209
+ return self.model_dump()
169
210
 
170
211
  @classmethod
171
212
  def from_json(cls, json_str: str):
172
213
  data = json.loads(json_str)
173
214
  return cls(**data)
215
+
216
+
217
+ class ReferencesResponse(BaseModel):
218
+ app_id: Optional[str] = None
219
+ app_slug: Optional[str] = None
220
+ variant_id: Optional[str] = None
221
+ variant_slug: Optional[str] = None
222
+ variant_version: Optional[int] = None
223
+ environment_id: Optional[str] = None
224
+ environment_slug: Optional[str] = None
225
+ environment_version: Optional[int] = None
226
+
227
+ def __str__(self):
228
+ return str(self.model_dump(exclude_none=True))
229
+
230
+
231
+ class LifecyclesResponse(ReferencesResponse):
232
+ committed_at: Optional[str] = None
233
+ committed_by: Optional[str] = None
234
+ committed_by_id: Optional[str] = None
235
+ deployed_at: Optional[str] = None
236
+ deployed_by: Optional[str] = None
237
+ deployed_by_id: Optional[str] = None
238
+
239
+ def __str__(self):
240
+ return self.model_dump_json(indent=4)
241
+
242
+ def __repr__(self):
243
+ return self.__str__()
244
+
245
+
246
+ class ConfigurationResponse(LifecyclesResponse):
247
+ params: Dict[str, Any]
248
+
249
+
250
+ class DeploymentResponse(LifecyclesResponse):
251
+ pass
252
+
253
+
254
+ class Prompt(BaseModel):
255
+ temperature: float
256
+ model: str
257
+ max_tokens: int
258
+ prompt_system: str
259
+ prompt_user: str
260
+ top_p: float
261
+ frequency_penalty: float
262
+ presence_penalty: float
263
+
264
+
265
+ # -----------------------------------------------------
266
+ # New Prompt model
267
+ # -----------------------------------------------------
268
+
269
+
270
+ class ToolCall(BaseModel):
271
+ id: str
272
+ type: Literal["function"] = "function"
273
+ function: Dict[str, str]
274
+
275
+
276
+ class Message(BaseModel):
277
+ role: Literal["system", "user", "assistant", "tool", "function"]
278
+ content: Optional[str] = None
279
+ name: Optional[str] = None
280
+ tool_calls: Optional[List[ToolCall]] = None
281
+ tool_call_id: Optional[str] = None
282
+
283
+
284
+ class ResponseFormatText(BaseModel):
285
+ type: Literal["text"]
286
+ """The type of response format being defined: `text`"""
287
+
288
+
289
+ class ResponseFormatJSONObject(BaseModel):
290
+ type: Literal["json_object"]
291
+ """The type of response format being defined: `json_object`"""
292
+
293
+
294
+ class JSONSchema(BaseModel):
295
+ name: str
296
+ """The name of the response format."""
297
+ description: Optional[str] = None
298
+ """A description of what the response format is for."""
299
+ schema_: Optional[Dict[str, object]] = Field(alias="schema", default=None)
300
+ """The schema for the response format, described as a JSON Schema object."""
301
+ strict: Optional[bool] = None
302
+ """Whether to enable strict schema adherence."""
303
+
304
+ model_config = {
305
+ "populate_by_name": True,
306
+ "json_schema_extra": {"required": ["name", "schema"]},
307
+ }
308
+
309
+
310
+ class ResponseFormatJSONSchema(BaseModel):
311
+ type: Literal["json_schema"]
312
+ """The type of response format being defined: `json_schema`"""
313
+ json_schema: JSONSchema
314
+
315
+
316
+ ResponseFormat = Union[
317
+ ResponseFormatText, ResponseFormatJSONObject, ResponseFormatJSONSchema
318
+ ]
319
+
320
+
321
+ class ModelConfig(BaseModel):
322
+ """Configuration for model parameters"""
323
+
324
+ model: str = MCField(
325
+ default="gpt-3.5-turbo",
326
+ choices=supported_llm_models,
327
+ )
328
+
329
+ temperature: Optional[float] = Field(
330
+ default=1,
331
+ ge=0.0,
332
+ le=2.0,
333
+ description="What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic",
334
+ )
335
+ max_tokens: Optional[int] = Field(
336
+ default=-1,
337
+ ge=0,
338
+ description="The maximum number of tokens that can be generated in the chat completion",
339
+ )
340
+ top_p: Optional[float] = Field(
341
+ default=0.5,
342
+ ge=0.0,
343
+ le=1.0,
344
+ description="An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass",
345
+ )
346
+ frequency_penalty: Optional[float] = Field(
347
+ default=0,
348
+ ge=-2.0,
349
+ le=2.0,
350
+ description="Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far",
351
+ )
352
+ presence_penalty: Optional[float] = Field(
353
+ default=0,
354
+ ge=-2.0,
355
+ le=2.0,
356
+ description="Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far",
357
+ )
358
+ response_format: Optional[ResponseFormat] = Field(
359
+ default=None,
360
+ description="An object specifying the format that the model must output",
361
+ )
362
+ stream: Optional[bool] = Field(
363
+ default=None, description="If set, partial message deltas will be sent"
364
+ )
365
+ tools: Optional[List[Dict]] = Field(
366
+ default=None,
367
+ description="A list of tools the model may call. Currently, only functions are supported as a tool",
368
+ )
369
+ tool_choice: Optional[Union[Literal["none", "auto"], Dict]] = Field(
370
+ default=None, description="Controls which (if any) tool is called by the model"
371
+ )
372
+
373
+
374
+ class PromptTemplateError(Exception):
375
+ """Base exception for all PromptTemplate errors"""
376
+
377
+ pass
378
+
379
+
380
+ class InputValidationError(PromptTemplateError):
381
+ """Raised when input validation fails"""
382
+
383
+ def __init__(
384
+ self, message: str, missing: Optional[set] = None, extra: Optional[set] = None
385
+ ):
386
+ self.missing = missing
387
+ self.extra = extra
388
+ super().__init__(message)
389
+
390
+
391
+ class TemplateFormatError(PromptTemplateError):
392
+ """Raised when template formatting fails"""
393
+
394
+ def __init__(self, message: str, original_error: Optional[Exception] = None):
395
+ self.original_error = original_error
396
+ super().__init__(message)
397
+
398
+
399
+ class PromptTemplate(BaseModel):
400
+ """A template for generating prompts with formatting capabilities"""
401
+
402
+ messages: List[Message] = Field(
403
+ default=[Message(role="system", content=""), Message(role="user", content="")]
404
+ )
405
+ system_prompt: Optional[str] = None
406
+ user_prompt: Optional[str] = None
407
+ template_format: Literal["fstring", "jinja2", "curly"] = Field(
408
+ default="fstring",
409
+ description="Format type for template variables: fstring {var}, jinja2 {{ var }}, or curly {{var}}",
410
+ )
411
+ input_keys: Optional[List[str]] = Field(
412
+ default=None,
413
+ description="Optional list of input keys for validation. If not provided, any inputs will be accepted",
414
+ )
415
+ llm_config: ModelConfig = Field(
416
+ default_factory=ModelConfig,
417
+ description="Configuration for the model parameters",
418
+ )
419
+
420
+ model_config = {
421
+ "json_schema_extra": {
422
+ "x-parameters": {
423
+ "prompt": "true",
424
+ }
425
+ }
426
+ }
427
+
428
+ @root_validator(pre=True)
429
+ def init_messages(cls, values):
430
+ if "messages" not in values:
431
+ messages = []
432
+ if "system_prompt" in values and values["system_prompt"]:
433
+ messages.append(Message(role="system", content=values["system_prompt"]))
434
+ if "user_prompt" in values and values["user_prompt"]:
435
+ messages.append(Message(role="user", content=values["user_prompt"]))
436
+ if messages:
437
+ values["messages"] = messages
438
+ return values
439
+
440
+ def _format_with_template(self, content: str, kwargs: Dict[str, Any]) -> str:
441
+ """Internal method to format content based on template_format"""
442
+ try:
443
+ if self.template_format == "fstring":
444
+ return content.format(**kwargs)
445
+ elif self.template_format == "jinja2":
446
+ from jinja2 import Template, TemplateError
447
+
448
+ try:
449
+ return Template(content).render(**kwargs)
450
+ except TemplateError as e:
451
+ raise TemplateFormatError(
452
+ f"Jinja2 template error in content: '{content}'. Error: {str(e)}",
453
+ original_error=e,
454
+ )
455
+ elif self.template_format == "curly":
456
+ import re
457
+
458
+ result = content
459
+ for key, value in kwargs.items():
460
+ result = re.sub(r"\{\{" + key + r"\}\}", str(value), result)
461
+ if re.search(r"\{\{.*?\}\}", result):
462
+ unreplaced = re.findall(r"\{\{(.*?)\}\}", result)
463
+ raise TemplateFormatError(
464
+ f"Unreplaced variables in curly template: {unreplaced}"
465
+ )
466
+ return result
467
+ else:
468
+ raise TemplateFormatError(
469
+ f"Unknown template format: {self.template_format}"
470
+ )
471
+ except KeyError as e:
472
+ key = str(e).strip("'")
473
+ raise TemplateFormatError(
474
+ f"Missing required variable '{key}' in template: '{content}'"
475
+ )
476
+ except Exception as e:
477
+ raise TemplateFormatError(
478
+ f"Error formatting template '{content}': {str(e)}", original_error=e
479
+ )
480
+
481
+ def format(self, **kwargs) -> "PromptTemplate":
482
+ """
483
+ Format the template with provided inputs.
484
+ Only validates against input_keys if they are specified.
485
+
486
+ Raises:
487
+ InputValidationError: If input validation fails
488
+ TemplateFormatError: If template formatting fails
489
+ """
490
+ # Validate inputs if input_keys is set
491
+ if self.input_keys is not None:
492
+ missing = set(self.input_keys) - set(kwargs.keys())
493
+ extra = set(kwargs.keys()) - set(self.input_keys)
494
+
495
+ error_parts = []
496
+ if missing:
497
+ error_parts.append(
498
+ f"Missing required inputs: {', '.join(sorted(missing))}"
499
+ )
500
+ if extra:
501
+ error_parts.append(f"Unexpected inputs: {', '.join(sorted(extra))}")
502
+
503
+ if error_parts:
504
+ raise InputValidationError(
505
+ " | ".join(error_parts),
506
+ missing=missing if missing else None,
507
+ extra=extra if extra else None,
508
+ )
509
+
510
+ new_messages = []
511
+ for i, msg in enumerate(self.messages):
512
+ if msg.content:
513
+ try:
514
+ new_content = self._format_with_template(msg.content, kwargs)
515
+ except TemplateFormatError as e:
516
+ raise TemplateFormatError(
517
+ f"Error in message {i} ({msg.role}): {str(e)}",
518
+ original_error=e.original_error,
519
+ )
520
+ else:
521
+ new_content = None
522
+
523
+ new_messages.append(
524
+ Message(
525
+ role=msg.role,
526
+ content=new_content,
527
+ name=msg.name,
528
+ tool_calls=msg.tool_calls,
529
+ tool_call_id=msg.tool_call_id,
530
+ )
531
+ )
532
+
533
+ return PromptTemplate(
534
+ messages=new_messages,
535
+ template_format=self.template_format,
536
+ llm_config=self.llm_config,
537
+ input_keys=self.input_keys,
538
+ )
539
+
540
+ def to_openai_kwargs(self) -> dict:
541
+ """Convert the prompt template to kwargs compatible with litellm/openai"""
542
+ kwargs = {
543
+ "model": self.llm_config.model,
544
+ "messages": [msg.dict(exclude_none=True) for msg in self.messages],
545
+ }
546
+
547
+ # Add optional parameters only if they are set
548
+ if self.llm_config.temperature is not None:
549
+ kwargs["temperature"] = self.llm_config.temperature
550
+
551
+ if self.llm_config.top_p is not None:
552
+ kwargs["top_p"] = self.llm_config.top_p
553
+
554
+ if self.llm_config.stream is not None:
555
+ kwargs["stream"] = self.llm_config.stream
556
+
557
+ if self.llm_config.max_tokens is not None:
558
+ kwargs["max_tokens"] = self.llm_config.max_tokens
559
+
560
+ if self.llm_config.frequency_penalty is not None:
561
+ kwargs["frequency_penalty"] = self.llm_config.frequency_penalty
562
+
563
+ if self.llm_config.presence_penalty is not None:
564
+ kwargs["presence_penalty"] = self.llm_config.presence_penalty
565
+
566
+ if self.llm_config.response_format:
567
+ kwargs["response_format"] = self.llm_config.response_format.dict(
568
+ by_alias=True
569
+ )
570
+
571
+ if self.llm_config.tools:
572
+ kwargs["tools"] = self.llm_config.tools
573
+ # Only set tool_choice if tools are present
574
+ if self.llm_config.tool_choice is not None:
575
+ kwargs["tool_choice"] = self.llm_config.tool_choice
576
+
577
+ return kwargs
File without changes
@@ -0,0 +1 @@
1
+ TRUTHY = {"true", "1", "t", "y", "yes", "on", "enable", "enabled"}
@@ -49,6 +49,9 @@ MODEL_COST_PER_1K_TOKENS = {
49
49
  "gpt-35-turbo-16k-completion": 0.004,
50
50
  "gpt-35-turbo-16k-0613-completion": 0.004,
51
51
  # Others
52
+ "text-embedding-ada-002": 0.1,
53
+ "text-ada-002": 0.1,
54
+ "adav2": 0.1,
52
55
  "text-ada-001": 0.0004,
53
56
  "ada": 0.0004,
54
57
  "text-babbage-001": 0.0005,