agenta 0.19.9__tar.gz → 0.20.0a0__tar.gz

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 (167) hide show
  1. {agenta-0.19.9 → agenta-0.20.0a0}/PKG-INFO +1 -1
  2. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/__init__.py +1 -1
  3. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/create_span.py +4 -1
  4. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/llm_tokens.py +3 -3
  5. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/sdk/__init__.py +1 -1
  6. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/sdk/decorators/llm_entrypoint.py +197 -78
  7. agenta-0.20.0a0/agenta/sdk/decorators/tracing.py +91 -0
  8. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/sdk/tracing/llm_tracing.py +172 -58
  9. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/sdk/tracing/tasks_manager.py +3 -2
  10. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/sdk/tracing/tracing_context.py +9 -6
  11. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/sdk/types.py +5 -6
  12. {agenta-0.19.9 → agenta-0.20.0a0}/pyproject.toml +1 -1
  13. agenta-0.19.9/agenta/sdk/decorators/tracing.py +0 -186
  14. {agenta-0.19.9 → agenta-0.20.0a0}/README.md +0 -0
  15. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/cli/evaluation_commands.py +0 -0
  16. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/cli/helper.py +0 -0
  17. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/cli/main.py +0 -0
  18. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/cli/telemetry.py +0 -0
  19. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/cli/variant_commands.py +0 -0
  20. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/cli/variant_configs.py +0 -0
  21. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/Readme.md +0 -0
  22. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/__init__.py +0 -0
  23. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/api.py +0 -0
  24. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/api_models.py +0 -0
  25. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/__init__.py +0 -0
  26. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/client.py +0 -0
  27. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/core/__init__.py +0 -0
  28. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/core/api_error.py +0 -0
  29. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/core/client_wrapper.py +0 -0
  30. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/core/datetime_utils.py +0 -0
  31. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/core/jsonable_encoder.py +0 -0
  32. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/core/remove_none_from_dict.py +0 -0
  33. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/errors/__init__.py +0 -0
  34. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/errors/unprocessable_entity_error.py +0 -0
  35. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/__init__.py +0 -0
  36. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/apps/__init__.py +0 -0
  37. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/apps/client.py +0 -0
  38. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/bases/__init__.py +0 -0
  39. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/bases/client.py +0 -0
  40. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/configs/__init__.py +0 -0
  41. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/configs/client.py +0 -0
  42. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/containers/__init__.py +0 -0
  43. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/containers/client.py +0 -0
  44. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/containers/types/__init__.py +0 -0
  45. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/containers/types/container_templates_response.py +0 -0
  46. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/environments/__init__.py +0 -0
  47. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/environments/client.py +0 -0
  48. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/evaluations/__init__.py +0 -0
  49. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/evaluations/client.py +0 -0
  50. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/evaluators/__init__.py +0 -0
  51. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/evaluators/client.py +0 -0
  52. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/observability/__init__.py +0 -0
  53. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/observability/client.py +0 -0
  54. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/testsets/__init__.py +0 -0
  55. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/testsets/client.py +0 -0
  56. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/variants/__init__.py +0 -0
  57. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/variants/client.py +0 -0
  58. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/variants/types/__init__.py +0 -0
  59. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/resources/variants/types/add_variant_from_base_and_config_response.py +0 -0
  60. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/__init__.py +0 -0
  61. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/aggregated_result.py +0 -0
  62. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/aggregated_result_evaluator_config.py +0 -0
  63. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/app.py +0 -0
  64. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/app_variant_response.py +0 -0
  65. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/app_variant_revision.py +0 -0
  66. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/base_output.py +0 -0
  67. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/body_import_testset.py +0 -0
  68. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/config_db.py +0 -0
  69. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/create_app_output.py +0 -0
  70. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/create_trace_response.py +0 -0
  71. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/docker_env_vars.py +0 -0
  72. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/environment_output.py +0 -0
  73. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/environment_output_extended.py +0 -0
  74. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/environment_revision.py +0 -0
  75. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/error.py +0 -0
  76. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/evaluation.py +0 -0
  77. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/evaluation_scenario.py +0 -0
  78. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/evaluation_scenario_input.py +0 -0
  79. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/evaluation_scenario_output.py +0 -0
  80. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/evaluation_scenario_result.py +0 -0
  81. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/evaluation_scenario_score_update.py +0 -0
  82. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/evaluation_status_enum.py +0 -0
  83. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/evaluation_type.py +0 -0
  84. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/evaluation_webhook.py +0 -0
  85. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/evaluator.py +0 -0
  86. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/evaluator_config.py +0 -0
  87. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/feedback.py +0 -0
  88. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/get_config_response.py +0 -0
  89. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/http_validation_error.py +0 -0
  90. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/human_evaluation.py +0 -0
  91. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/human_evaluation_scenario.py +0 -0
  92. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/human_evaluation_scenario_input.py +0 -0
  93. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/human_evaluation_scenario_output.py +0 -0
  94. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/human_evaluation_scenario_update.py +0 -0
  95. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/human_evaluation_update.py +0 -0
  96. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/image.py +0 -0
  97. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/invite_request.py +0 -0
  98. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/list_api_keys_response.py +0 -0
  99. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/llm_run_rate_limit.py +0 -0
  100. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/new_human_evaluation.py +0 -0
  101. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/new_testset.py +0 -0
  102. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/organization.py +0 -0
  103. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/organization_output.py +0 -0
  104. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/permission.py +0 -0
  105. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/result.py +0 -0
  106. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/score.py +0 -0
  107. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/simple_evaluation_output.py +0 -0
  108. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/span.py +0 -0
  109. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/span_detail.py +0 -0
  110. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/span_kind.py +0 -0
  111. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/span_status_code.py +0 -0
  112. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/span_variant.py +0 -0
  113. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/template.py +0 -0
  114. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/template_image_info.py +0 -0
  115. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/test_set_output_response.py +0 -0
  116. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/test_set_simple_response.py +0 -0
  117. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/trace_detail.py +0 -0
  118. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/uri.py +0 -0
  119. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/validation_error.py +0 -0
  120. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/validation_error_loc_item.py +0 -0
  121. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/variant_action.py +0 -0
  122. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/variant_action_enum.py +0 -0
  123. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/with_pagination.py +0 -0
  124. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/workspace_member_response.py +0 -0
  125. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/workspace_permission.py +0 -0
  126. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/workspace_response.py +0 -0
  127. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/workspace_role.py +0 -0
  128. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/backend/types/workspace_role_response.py +0 -0
  129. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/client.py +0 -0
  130. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/client/exceptions.py +0 -0
  131. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/config.py +0 -0
  132. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/config.toml +0 -0
  133. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/docker/docker-assets/Dockerfile.cloud.template +0 -0
  134. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/docker/docker-assets/Dockerfile.template +0 -0
  135. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/docker/docker-assets/README.md +0 -0
  136. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/docker/docker-assets/entrypoint.sh +0 -0
  137. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/docker/docker-assets/lambda_function.py +0 -0
  138. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/docker/docker-assets/main.py +0 -0
  139. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/docker/docker_utils.py +0 -0
  140. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/sdk/agenta_init.py +0 -0
  141. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/sdk/client.py +0 -0
  142. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/sdk/context.py +0 -0
  143. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/sdk/decorators/base.py +0 -0
  144. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/sdk/router.py +0 -0
  145. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/sdk/tracing/__init__.py +0 -0
  146. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/sdk/tracing/callbacks.py +0 -0
  147. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/sdk/tracing/context_manager.py +0 -0
  148. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/sdk/tracing/logger.py +0 -0
  149. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/sdk/utils/debug.py +0 -0
  150. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/sdk/utils/globals.py +0 -0
  151. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/sdk/utils/helper/openai_cost.py +0 -0
  152. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/sdk/utils/preinit.py +0 -0
  153. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/templates/compose_email/README.md +0 -0
  154. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/templates/compose_email/app.py +0 -0
  155. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/templates/compose_email/env.example +0 -0
  156. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/templates/compose_email/requirements.txt +0 -0
  157. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/templates/compose_email/template.toml +0 -0
  158. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/templates/extract_data_to_json/README.md +0 -0
  159. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/templates/extract_data_to_json/app.py +0 -0
  160. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/templates/extract_data_to_json/env.example +0 -0
  161. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/templates/extract_data_to_json/requirements.txt +0 -0
  162. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/templates/extract_data_to_json/template.toml +0 -0
  163. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/templates/simple_prompt/README.md +0 -0
  164. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/templates/simple_prompt/app.py +0 -0
  165. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/templates/simple_prompt/env.example +0 -0
  166. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/templates/simple_prompt/requirements.txt +0 -0
  167. {agenta-0.19.9 → agenta-0.20.0a0}/agenta/templates/simple_prompt/template.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: agenta
3
- Version: 0.19.9
3
+ Version: 0.20.0a0
4
4
  Summary: The SDK for agenta is an open-source LLMOps platform.
5
5
  Home-page: https://agenta.ai
6
6
  Keywords: LLMOps,LLM,evaluation,prompt engineering
@@ -17,7 +17,7 @@ from .sdk.types import (
17
17
  from .sdk.tracing.logger import llm_logger as logging
18
18
  from .sdk.tracing.llm_tracing import Tracing
19
19
  from .sdk.decorators.tracing import instrument
20
- from .sdk.decorators.llm_entrypoint import entrypoint, app
20
+ from .sdk.decorators.llm_entrypoint import entrypoint, app, route
21
21
  from .sdk.agenta_init import Config, AgentaSingleton, init
22
22
  from .sdk.utils.helper.openai_cost import calculate_token_usage
23
23
  from .sdk.client import Agenta
@@ -20,7 +20,10 @@ class CreateSpan(pydantic.BaseModel):
20
20
  variant_id: typing.Optional[str]
21
21
  variant_name: typing.Optional[str]
22
22
  inputs: typing.Optional[typing.Dict[str, typing.Any]]
23
- outputs: typing.Optional[typing.List[str]]
23
+ internals: typing.Optional[typing.Dict[str, typing.Any]]
24
+ outputs: typing.Optional[
25
+ typing.Union[typing.Dict[str, typing.Any], typing.List[str]]
26
+ ]
24
27
  config: typing.Optional[typing.Dict[str, typing.Any]]
25
28
  environment: typing.Optional[str]
26
29
  tags: typing.Optional[typing.List[str]]
@@ -12,9 +12,9 @@ except ImportError:
12
12
 
13
13
 
14
14
  class LlmTokens(pydantic.BaseModel):
15
- prompt_tokens: typing.Optional[int]
16
- completion_tokens: typing.Optional[int]
17
- total_tokens: typing.Optional[int]
15
+ prompt_tokens: typing.Optional[int] = 0
16
+ completion_tokens: typing.Optional[int] = 0
17
+ total_tokens: typing.Optional[int] = 0
18
18
 
19
19
  def json(self, **kwargs: typing.Any) -> str:
20
20
  kwargs_with_defaults: typing.Any = {
@@ -16,7 +16,7 @@ from .types import (
16
16
 
17
17
  from .tracing.llm_tracing import Tracing
18
18
  from .decorators.tracing import instrument
19
- from .decorators.llm_entrypoint import entrypoint, app
19
+ from .decorators.llm_entrypoint import entrypoint, app, route
20
20
  from .agenta_init import Config, AgentaSingleton, init
21
21
  from .utils.helper.openai_cost import calculate_token_usage
22
22
 
@@ -3,6 +3,7 @@
3
3
  import os
4
4
  import sys
5
5
  import time
6
+ import json
6
7
  import inspect
7
8
  import argparse
8
9
  import asyncio
@@ -15,11 +16,11 @@ from typing import Any, Callable, Dict, Optional, Tuple, List
15
16
  from fastapi.middleware.cors import CORSMiddleware
16
17
  from fastapi import Body, FastAPI, UploadFile, HTTPException
17
18
 
18
- import agenta
19
+ import agenta as ag
19
20
  from agenta.sdk.context import save_context
20
21
  from agenta.sdk.router import router as router
21
22
  from agenta.sdk.tracing.logger import llm_logger as logging
22
- from agenta.sdk.tracing.llm_tracing import Tracing
23
+ from agenta.sdk.tracing.tracing_context import tracing_context, TracingContext
23
24
  from agenta.sdk.decorators.base import BaseDecorator
24
25
  from agenta.sdk.types import (
25
26
  Context,
@@ -32,10 +33,12 @@ from agenta.sdk.types import (
32
33
  TextParam,
33
34
  MessagesInput,
34
35
  FileInputURL,
35
- FuncResponse,
36
+ BaseResponse,
36
37
  BinaryParam,
37
38
  )
38
39
 
40
+ from pydantic import BaseModel, HttpUrl
41
+
39
42
  app = FastAPI()
40
43
 
41
44
  origins = [
@@ -52,16 +55,56 @@ app.add_middleware(
52
55
 
53
56
  app.include_router(router, prefix="")
54
57
 
55
-
56
58
  from agenta.sdk.utils.debug import debug, DEBUG, SHIFT
57
59
 
58
60
 
59
61
  logging.setLevel("DEBUG")
60
62
 
61
63
 
64
+ class PathValidator(BaseModel):
65
+ url: HttpUrl
66
+
67
+
68
+ class route(BaseDecorator):
69
+ # This decorator is used to expose specific stages of a workflow (embedding, retrieval, summarization, etc.)
70
+ # as independent endpoints. It is designed for backward compatibility with existing code that uses
71
+ # the @entrypoint decorator, which has certain limitations. By using @route(), we can create new
72
+ # routes without altering the main workflow entrypoint. This helps in modularizing the services
73
+ # and provides flexibility in how we expose different functionalities as APIs.
74
+ def __init__(self, path):
75
+ path = "/" + path.strip("/").strip()
76
+ path = "" if path == "/" else path
77
+
78
+ PathValidator(url=f"http://example.com{path}")
79
+
80
+ self.route_path = path
81
+
82
+ def __call__(self, f):
83
+ self.e = entrypoint(f, route_path=self.route_path)
84
+
85
+ return f
86
+
87
+
62
88
  class entrypoint(BaseDecorator):
63
- """Decorator class to wrap a function for HTTP POST, terminal exposure and enable tracing.
89
+ """
90
+ Decorator class to wrap a function for HTTP POST, terminal exposure and enable tracing.
91
+
92
+ This decorator generates the following endpoints:
93
+
94
+ Playground Endpoints
95
+ - /generate with @entrypoint, @route("/"), @route(path="") # LEGACY
96
+ - /playground/run with @entrypoint, @route("/"), @route(path="")
97
+ - /playground/run/{route} with @route({route}), @route(path={route})
64
98
 
99
+ Deployed Endpoints:
100
+ - /generate_deployed with @entrypoint, @route("/"), @route(path="") # LEGACY
101
+ - /run with @entrypoint, @route("/"), @route(path="")
102
+ - /run/{route} with @route({route}), @route(path={route})
103
+
104
+ The rationale is:
105
+ - There may be multiple endpoints, based on the different routes.
106
+ - It's better to make it explicit that an endpoint is for the playground.
107
+ - Prefixing the routes with /run is more futureproof in case we add more endpoints.
65
108
 
66
109
  Example:
67
110
  ```python
@@ -73,31 +116,64 @@ class entrypoint(BaseDecorator):
73
116
  ```
74
117
  """
75
118
 
76
- def __init__(self, func: Callable[..., Any]):
77
- endpoint_name = "generate"
119
+ routes = list()
120
+
121
+ def __init__(self, func: Callable[..., Any], route_path=""):
122
+ DEFAULT_PATH = "generate"
123
+ PLAYGROUND_PATH = "/playground"
124
+ RUN_PATH = "/run"
125
+
78
126
  func_signature = inspect.signature(func)
79
- config_params = agenta.config.all()
127
+ config_params = ag.config.all()
80
128
  ingestible_files = self.extract_ingestible_files(func_signature)
81
129
 
130
+ ### --- Playground --- #
82
131
  @debug()
83
132
  @functools.wraps(func)
84
133
  async def wrapper(*args, **kwargs) -> Any:
85
134
  func_params, api_config_params = self.split_kwargs(kwargs, config_params)
86
135
  self.ingest_files(func_params, ingestible_files)
87
- agenta.config.set(**api_config_params)
136
+ ag.config.set(**api_config_params)
88
137
 
89
138
  # Set the configuration and environment of the LLM app parent span at run-time
90
- agenta.tracing.update_baggage(
139
+ ag.tracing.update_baggage(
91
140
  {"config": config_params, "environment": "playground"}
92
141
  )
93
142
 
94
- # Exceptions are all handled inside self.execute_function()
95
- llm_result = await self.execute_function(
143
+ entrypoint_result = await self.execute_function(
96
144
  func, *args, params=func_params, config_params=config_params
97
145
  )
98
146
 
99
- return llm_result
147
+ return entrypoint_result
148
+
149
+ self.update_function_signature(
150
+ wrapper, func_signature, config_params, ingestible_files
151
+ )
100
152
 
153
+ #
154
+ if route_path == "":
155
+ route = f"/{DEFAULT_PATH}"
156
+ app.post(route, response_model=BaseResponse)(wrapper)
157
+ entrypoint.routes.append(
158
+ {
159
+ "func": func.__name__,
160
+ "endpoint": DEFAULT_PATH,
161
+ "params": {**config_params, **func_signature.parameters},
162
+ }
163
+ )
164
+
165
+ route = f"{PLAYGROUND_PATH}{RUN_PATH}{route_path}"
166
+ app.post(route, response_model=BaseResponse)(wrapper)
167
+ entrypoint.routes.append(
168
+ {
169
+ "func": func.__name__,
170
+ "endpoint": route[1:].replace("/", "_"),
171
+ "params": {**config_params, **func_signature.parameters},
172
+ }
173
+ )
174
+ ### ---------------------------- #
175
+
176
+ ### --- Deployed / Published --- #
101
177
  @debug()
102
178
  @functools.wraps(func)
103
179
  async def wrapper_deployed(*args, **kwargs) -> Any:
@@ -106,44 +182,51 @@ class entrypoint(BaseDecorator):
106
182
  }
107
183
 
108
184
  if "environment" in kwargs and kwargs["environment"] is not None:
109
- agenta.config.pull(environment_name=kwargs["environment"])
185
+ ag.config.pull(environment_name=kwargs["environment"])
110
186
  elif "config" in kwargs and kwargs["config"] is not None:
111
- agenta.config.pull(config_name=kwargs["config"])
187
+ ag.config.pull(config_name=kwargs["config"])
112
188
  else:
113
- agenta.config.pull(config_name="default")
189
+ ag.config.pull(config_name="default")
114
190
 
115
191
  # Set the configuration and environment of the LLM app parent span at run-time
116
- agenta.tracing.update_baggage(
192
+ ag.tracing.update_baggage(
117
193
  {"config": config_params, "environment": kwargs["environment"]}
118
194
  )
119
195
 
120
- llm_result = await self.execute_function(
196
+ entrypoint_result = await self.execute_function(
121
197
  func, *args, params=func_params, config_params=config_params
122
198
  )
123
199
 
124
- return llm_result
125
-
126
- self.update_function_signature(
127
- wrapper, func_signature, config_params, ingestible_files
128
- )
129
- route = f"/{endpoint_name}"
130
- app.post(route, response_model=FuncResponse)(wrapper)
200
+ return entrypoint_result
131
201
 
132
202
  self.update_deployed_function_signature(
133
203
  wrapper_deployed,
134
204
  func_signature,
135
205
  ingestible_files,
136
206
  )
137
- route_deployed = f"/{endpoint_name}_deployed"
138
- app.post(route_deployed, response_model=FuncResponse)(wrapper_deployed)
139
- self.override_schema(
140
- openapi_schema=app.openapi(),
141
- func_name=func.__name__,
142
- endpoint=endpoint_name,
143
- params={**config_params, **func_signature.parameters},
144
- )
145
207
 
146
- if self.is_main_script(func):
208
+ if route_path == "/":
209
+ route_deployed = f"/{DEFAULT_PATH}_deployed"
210
+ app.post(route_deployed, response_model=BaseResponse)(wrapper_deployed)
211
+
212
+ route_deployed = f"{RUN_PATH}{route_path}"
213
+ app.post(route_deployed, response_model=BaseResponse)(wrapper_deployed)
214
+ ### ---------------------------- #
215
+
216
+ ### --- Update OpenAPI --- #
217
+ app.openapi_schema = None # Forces FastAPI to re-generate the schema
218
+ openapi_schema = app.openapi()
219
+
220
+ for route in entrypoint.routes:
221
+ self.override_schema(
222
+ openapi_schema=openapi_schema,
223
+ func=route["func"],
224
+ endpoint=route["endpoint"],
225
+ params=route["params"],
226
+ )
227
+ ### ---------------------- #
228
+
229
+ if self.is_main_script(func) and route_path == "":
147
230
  self.handle_terminal_run(
148
231
  func,
149
232
  func_signature.parameters, # type: ignore
@@ -198,51 +281,55 @@ class entrypoint(BaseDecorator):
198
281
  For synchronous functions, it calls them directly, while for asynchronous functions,
199
282
  it awaits their execution.
200
283
  """
284
+ data = None
285
+ trace = None
286
+
287
+ token = None
288
+ if tracing_context.get() is None:
289
+ token = tracing_context.set(TracingContext())
290
+
201
291
  is_coroutine_function = inspect.iscoroutinefunction(func)
202
- start_time = time.perf_counter()
203
292
 
204
293
  if is_coroutine_function:
205
294
  result = await func(*args, **func_params["params"])
206
295
  else:
207
296
  result = func(*args, **func_params["params"])
208
297
 
209
- end_time = time.perf_counter()
210
- latency = end_time - start_time
298
+ if token is not None:
299
+ trace = ag.tracing.dump_trace()
300
+ tracing_context.reset(token)
211
301
 
212
302
  if isinstance(result, Context):
213
303
  save_context(result)
304
+
214
305
  if isinstance(result, Dict):
215
- return FuncResponse(**result, latency=round(latency, 4))
216
- if isinstance(result, str):
217
- return FuncResponse(
218
- message=result, usage=None, cost=None, latency=round(latency, 4)
219
- )
220
- if isinstance(result, int) or isinstance(result, float):
221
- return FuncResponse(
222
- message=str(result),
223
- usage=None,
224
- cost=None,
225
- latency=round(latency, 4),
226
- )
227
- if result is None:
228
- return FuncResponse(
229
- message="Function executed successfully, but did return None. \n Are you sure you did not forget to return a value?",
230
- usage=None,
231
- cost=None,
232
- latency=round(latency, 4),
306
+ data = result
307
+ elif isinstance(result, str):
308
+ data = {"message": result}
309
+ elif isinstance(result, int) or isinstance(result, float):
310
+ data = {"message": str(result)}
311
+
312
+ if data is None:
313
+ warning = (
314
+ "Function executed successfully, but did return None. \n Are you sure you did not forget to return a value?",
233
315
  )
316
+
317
+ data = {"message": warning}
318
+
319
+ return BaseResponse(data=data, trace=trace)
320
+
234
321
  except Exception as e:
235
322
  self.handle_exception(e)
236
- return FuncResponse(message="Unexpected error occurred when calling the @entrypoint decorated function", latency=0) # type: ignore
237
323
 
238
324
  def handle_exception(self, e: Exception):
239
- """Handle exceptions."""
325
+ status_code = e.status_code if hasattr(e, "status_code") else 500
326
+ message = str(e)
327
+ stacktrace = traceback.format_exception(e, value=e, tb=e.__traceback__) # type: ignore
328
+ detail = {"message": message, "stacktrace": stacktrace}
240
329
 
241
- status_code: int = e.status_code if hasattr(e, "status_code") else 500
242
- traceback_str = traceback.format_exception(e, value=e, tb=e.__traceback__) # type: ignore
243
330
  raise HTTPException(
244
331
  status_code=status_code,
245
- detail={"error": str(e), "traceback": "".join(traceback_str)},
332
+ detail=detail,
246
333
  )
247
334
 
248
335
  def update_wrapper_signature(
@@ -418,26 +505,29 @@ class entrypoint(BaseDecorator):
418
505
  file_path=args_func_params[name],
419
506
  )
420
507
 
421
- agenta.config.set(**args_config_params)
508
+ ag.config.set(**args_config_params)
422
509
 
423
510
  # Set the configuration and environment of the LLM app parent span at run-time
424
- agenta.tracing.update_baggage(
425
- {"config": agenta.config.all(), "environment": "bash"}
426
- )
511
+ ag.tracing.update_baggage({"config": ag.config.all(), "environment": "bash"})
427
512
 
428
513
  loop = asyncio.get_event_loop()
514
+
429
515
  result = loop.run_until_complete(
430
516
  self.execute_function(
431
517
  func,
432
518
  **{"params": args_func_params, "config_params": args_config_params},
433
519
  )
434
520
  )
435
- print(
436
- f"\n========== Result ==========\n\nMessage: {result.message}\nCost: {result.cost}\nToken Usage: {result.usage}"
437
- )
521
+
522
+ print(f"\n========== Result ==========\n")
523
+
524
+ print("-> data")
525
+ print(json.dumps(result.data, indent=2))
526
+ print("-> trace")
527
+ print(json.dumps(result.trace, indent=2))
438
528
 
439
529
  def override_schema(
440
- self, openapi_schema: dict, func_name: str, endpoint: str, params: dict
530
+ self, openapi_schema: dict, func: str, endpoint: str, params: dict
441
531
  ):
442
532
  """
443
533
  Overrides the default openai schema generated by fastapi with additional information about:
@@ -452,7 +542,7 @@ class entrypoint(BaseDecorator):
452
542
 
453
543
  Args:
454
544
  openapi_schema (dict): The openapi schema generated by fastapi
455
- func_name (str): The name of the function to override
545
+ func (str): The name of the function to override
456
546
  endpoint (str): The name of the endpoint to override
457
547
  params (dict(param_name, param_val)): The dictionary of the parameters for the function
458
548
  """
@@ -484,8 +574,29 @@ class entrypoint(BaseDecorator):
484
574
  # value = {'temperature': { "type": "number", "title": "Temperature", "x-parameter": "float" }}
485
575
  return value
486
576
 
577
+ def get_type_from_param(param_val):
578
+ param_type = "string"
579
+ annotation = param_val.annotation
580
+
581
+ if annotation == int:
582
+ param_type = "integer"
583
+ elif annotation == float:
584
+ param_type = "number"
585
+ elif annotation == dict:
586
+ param_type = "object"
587
+ elif annotation == bool:
588
+ param_type = "boolean"
589
+ elif annotation == list:
590
+ param_type = "list"
591
+ elif annotation == str:
592
+ param_type = "string"
593
+ else:
594
+ print("ERROR, unhandled annotation:", annotation)
595
+
596
+ return param_type
597
+
487
598
  schema_to_override = openapi_schema["components"]["schemas"][
488
- f"Body_{func_name}_{endpoint}_post"
599
+ f"Body_{func}_{endpoint}_post"
489
600
  ]["properties"]
490
601
  for param_name, param_val in params.items():
491
602
  if isinstance(param_val, GroupedMultipleChoiceParam):
@@ -501,7 +612,7 @@ class entrypoint(BaseDecorator):
501
612
  subschema["choices"] = param_val.choices # type: ignore
502
613
  subschema["default"] = param_val.default # type: ignore
503
614
 
504
- if isinstance(param_val, MultipleChoiceParam):
615
+ elif isinstance(param_val, MultipleChoiceParam):
505
616
  subschema = find_in_schema(
506
617
  param_val.__schema_type_properties__(),
507
618
  schema_to_override,
@@ -520,7 +631,7 @@ class entrypoint(BaseDecorator):
520
631
  default if default in param_choices else choices[0]
521
632
  )
522
633
 
523
- if isinstance(param_val, FloatParam):
634
+ elif isinstance(param_val, FloatParam):
524
635
  subschema = find_in_schema(
525
636
  param_val.__schema_type_properties__(),
526
637
  schema_to_override,
@@ -531,7 +642,7 @@ class entrypoint(BaseDecorator):
531
642
  subschema["maximum"] = param_val.maxval # type: ignore
532
643
  subschema["default"] = param_val
533
644
 
534
- if isinstance(param_val, IntParam):
645
+ elif isinstance(param_val, IntParam):
535
646
  subschema = find_in_schema(
536
647
  param_val.__schema_type_properties__(),
537
648
  schema_to_override,
@@ -542,7 +653,7 @@ class entrypoint(BaseDecorator):
542
653
  subschema["maximum"] = param_val.maxval # type: ignore
543
654
  subschema["default"] = param_val
544
655
 
545
- if (
656
+ elif (
546
657
  isinstance(param_val, inspect.Parameter)
547
658
  and param_val.annotation is DictInput
548
659
  ):
@@ -554,7 +665,7 @@ class entrypoint(BaseDecorator):
554
665
  )
555
666
  subschema["default"] = param_val.default["default_keys"]
556
667
 
557
- if isinstance(param_val, TextParam):
668
+ elif isinstance(param_val, TextParam):
558
669
  subschema = find_in_schema(
559
670
  param_val.__schema_type_properties__(),
560
671
  schema_to_override,
@@ -563,7 +674,7 @@ class entrypoint(BaseDecorator):
563
674
  )
564
675
  subschema["default"] = param_val
565
676
 
566
- if (
677
+ elif (
567
678
  isinstance(param_val, inspect.Parameter)
568
679
  and param_val.annotation is MessagesInput
569
680
  ):
@@ -575,7 +686,7 @@ class entrypoint(BaseDecorator):
575
686
  )
576
687
  subschema["default"] = param_val.default
577
688
 
578
- if (
689
+ elif (
579
690
  isinstance(param_val, inspect.Parameter)
580
691
  and param_val.annotation is FileInputURL
581
692
  ):
@@ -587,7 +698,7 @@ class entrypoint(BaseDecorator):
587
698
  )
588
699
  subschema["default"] = "https://example.com"
589
700
 
590
- if isinstance(param_val, BinaryParam):
701
+ elif isinstance(param_val, BinaryParam):
591
702
  subschema = find_in_schema(
592
703
  param_val.__schema_type_properties__(),
593
704
  schema_to_override,
@@ -595,3 +706,11 @@ class entrypoint(BaseDecorator):
595
706
  "bool",
596
707
  )
597
708
  subschema["default"] = param_val.default # type: ignore
709
+ else:
710
+ subschema = {
711
+ "title": str(param_name).capitalize(),
712
+ "type": get_type_from_param(param_val),
713
+ }
714
+ if param_val.default != inspect._empty:
715
+ subschema["default"] = param_val.default # type: ignore
716
+ schema_to_override[param_name] = subschema
@@ -0,0 +1,91 @@
1
+ # Stdlib Imports
2
+ import inspect
3
+ import traceback
4
+ from functools import wraps
5
+ from typing import Any, Callable, Optional
6
+
7
+ # Own Imports
8
+ import agenta as ag
9
+ from agenta.sdk.decorators.base import BaseDecorator
10
+ from agenta.sdk.tracing.logger import llm_logger as logging
11
+ from agenta.sdk.utils.debug import debug, DEBUG, SHIFT
12
+
13
+
14
+ logging.setLevel("DEBUG")
15
+
16
+
17
+ class instrument(BaseDecorator):
18
+ """Decorator class for monitoring llm apps functions.
19
+
20
+ Args:
21
+ BaseDecorator (object): base decorator class
22
+
23
+ Example:
24
+ ```python
25
+ import agenta as ag
26
+
27
+ prompt_config = {"system_prompt": ..., "temperature": 0.5, "max_tokens": ...}
28
+
29
+ @ag.instrument(spankind="llm")
30
+ async def litellm_openai_call(prompt:str) -> str:
31
+ return "do something"
32
+
33
+ @ag.instrument(config=prompt_config) # spankind for parent span defaults to workflow
34
+ async def generate(prompt: str):
35
+ return ...
36
+ ```
37
+ """
38
+
39
+ def __init__(
40
+ self,
41
+ config: Optional[dict] = None,
42
+ spankind: str = "workflow",
43
+ ) -> None:
44
+ self.config = config
45
+ self.spankind = spankind
46
+
47
+ def __call__(self, func: Callable[..., Any]):
48
+ is_coroutine_function = inspect.iscoroutinefunction(func)
49
+
50
+ def get_inputs(*args, **kwargs):
51
+ func_args = inspect.getfullargspec(func).args
52
+ input_dict = {name: value for name, value in zip(func_args, args)}
53
+ input_dict.update(kwargs)
54
+
55
+ return input_dict
56
+
57
+ @wraps(func)
58
+ async def async_wrapper(*args, **kwargs):
59
+ async def wrapped_func(*args, **kwargs):
60
+ with ag.tracing.Context(
61
+ name=func.__name__,
62
+ input=get_inputs(*args, **kwargs),
63
+ spankind=self.spankind,
64
+ config=self.config,
65
+ ):
66
+ result = await func(*args, **kwargs)
67
+
68
+ ag.tracing.store_outputs(result)
69
+
70
+ return result
71
+
72
+ return await wrapped_func(*args, **kwargs)
73
+
74
+ @wraps(func)
75
+ def sync_wrapper(*args, **kwargs):
76
+ def wrapped_func(*args, **kwargs):
77
+ with ag.tracing.Context(
78
+ name=func.__name__,
79
+ input=get_inputs(*args, **kwargs),
80
+ spankind=self.spankind,
81
+ config=self.config,
82
+ ):
83
+ result = func(*args, **kwargs)
84
+
85
+ ag.tracing.store_outputs(result)
86
+
87
+ return result
88
+
89
+ return wrapped_func(*args, **kwargs)
90
+
91
+ return async_wrapper if is_coroutine_function else sync_wrapper