agenta 0.57.0__py3-none-any.whl → 0.63.2__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.
- agenta/__init__.py +12 -3
- agenta/client/__init__.py +4 -4
- agenta/client/backend/__init__.py +4 -4
- agenta/client/backend/api_keys/client.py +2 -2
- agenta/client/backend/billing/client.py +2 -2
- agenta/client/backend/billing/raw_client.py +2 -2
- agenta/client/backend/client.py +56 -48
- agenta/client/backend/core/client_wrapper.py +2 -2
- agenta/client/backend/core/file.py +3 -1
- agenta/client/backend/core/http_client.py +3 -3
- agenta/client/backend/core/pydantic_utilities.py +13 -3
- agenta/client/backend/human_evaluations/client.py +2 -2
- agenta/client/backend/human_evaluations/raw_client.py +2 -2
- agenta/client/backend/organization/client.py +46 -34
- agenta/client/backend/organization/raw_client.py +32 -26
- agenta/client/backend/raw_client.py +26 -26
- agenta/client/backend/testsets/client.py +18 -18
- agenta/client/backend/testsets/raw_client.py +30 -30
- agenta/client/backend/types/__init__.py +4 -4
- agenta/client/backend/types/account_request.py +3 -1
- agenta/client/backend/types/account_response.py +3 -1
- agenta/client/backend/types/agenta_node_dto.py +3 -1
- agenta/client/backend/types/agenta_nodes_response.py +3 -1
- agenta/client/backend/types/agenta_root_dto.py +3 -1
- agenta/client/backend/types/agenta_roots_response.py +3 -1
- agenta/client/backend/types/agenta_tree_dto.py +3 -1
- agenta/client/backend/types/agenta_trees_response.py +3 -1
- agenta/client/backend/types/aggregated_result.py +3 -1
- agenta/client/backend/types/analytics_response.py +3 -1
- agenta/client/backend/types/annotation.py +6 -4
- agenta/client/backend/types/annotation_create.py +3 -1
- agenta/client/backend/types/annotation_edit.py +3 -1
- agenta/client/backend/types/annotation_link.py +3 -1
- agenta/client/backend/types/annotation_link_response.py +3 -1
- agenta/client/backend/types/annotation_query.py +3 -1
- agenta/client/backend/types/annotation_query_request.py +3 -1
- agenta/client/backend/types/annotation_reference.py +3 -1
- agenta/client/backend/types/annotation_references.py +3 -1
- agenta/client/backend/types/annotation_response.py +3 -1
- agenta/client/backend/types/annotations_response.py +3 -1
- agenta/client/backend/types/app.py +3 -1
- agenta/client/backend/types/app_variant_response.py +3 -1
- agenta/client/backend/types/app_variant_revision.py +3 -1
- agenta/client/backend/types/artifact.py +6 -4
- agenta/client/backend/types/base_output.py +3 -1
- agenta/client/backend/types/body_fetch_workflow_revision.py +3 -1
- agenta/client/backend/types/body_import_testset.py +3 -1
- agenta/client/backend/types/bucket_dto.py +3 -1
- agenta/client/backend/types/collect_status_response.py +3 -1
- agenta/client/backend/types/config_db.py +3 -1
- agenta/client/backend/types/config_dto.py +3 -1
- agenta/client/backend/types/config_response_model.py +3 -1
- agenta/client/backend/types/correct_answer.py +3 -1
- agenta/client/backend/types/create_app_output.py +3 -1
- agenta/client/backend/types/custom_model_settings_dto.py +3 -1
- agenta/client/backend/types/custom_provider_dto.py +3 -1
- agenta/client/backend/types/custom_provider_kind.py +1 -1
- agenta/client/backend/types/custom_provider_settings_dto.py +3 -1
- agenta/client/backend/types/delete_evaluation.py +3 -1
- agenta/client/backend/types/environment_output.py +3 -1
- agenta/client/backend/types/environment_output_extended.py +3 -1
- agenta/client/backend/types/environment_revision.py +3 -1
- agenta/client/backend/types/error.py +3 -1
- agenta/client/backend/types/evaluation.py +3 -1
- agenta/client/backend/types/evaluation_scenario.py +3 -1
- agenta/client/backend/types/evaluation_scenario_input.py +3 -1
- agenta/client/backend/types/evaluation_scenario_output.py +3 -1
- agenta/client/backend/types/evaluation_scenario_result.py +3 -1
- agenta/client/backend/types/evaluator.py +6 -4
- agenta/client/backend/types/evaluator_config.py +6 -4
- agenta/client/backend/types/evaluator_flags.py +3 -1
- agenta/client/backend/types/evaluator_mapping_output_interface.py +3 -1
- agenta/client/backend/types/evaluator_output_interface.py +3 -1
- agenta/client/backend/types/evaluator_query.py +3 -1
- agenta/client/backend/types/evaluator_query_request.py +3 -1
- agenta/client/backend/types/evaluator_request.py +3 -1
- agenta/client/backend/types/evaluator_response.py +3 -1
- agenta/client/backend/types/evaluators_response.py +3 -1
- agenta/client/backend/types/exception_dto.py +3 -1
- agenta/client/backend/types/extended_o_tel_tracing_response.py +3 -1
- agenta/client/backend/types/get_config_response.py +3 -1
- agenta/client/backend/types/header.py +3 -1
- agenta/client/backend/types/http_validation_error.py +3 -1
- agenta/client/backend/types/human_evaluation.py +3 -1
- agenta/client/backend/types/human_evaluation_scenario.py +3 -1
- agenta/client/backend/types/human_evaluation_scenario_input.py +3 -1
- agenta/client/backend/types/human_evaluation_scenario_output.py +3 -1
- agenta/client/backend/types/invite_request.py +3 -1
- agenta/client/backend/types/legacy_analytics_response.py +3 -1
- agenta/client/backend/types/legacy_data_point.py +3 -1
- agenta/client/backend/types/legacy_evaluator.py +3 -1
- agenta/client/backend/types/legacy_scope_request.py +3 -1
- agenta/client/backend/types/legacy_scopes_response.py +3 -1
- agenta/client/backend/types/legacy_subscription_request.py +3 -1
- agenta/client/backend/types/legacy_user_request.py +3 -1
- agenta/client/backend/types/legacy_user_response.py +3 -1
- agenta/client/backend/types/lifecycle_dto.py +3 -1
- agenta/client/backend/types/link_dto.py +3 -1
- agenta/client/backend/types/list_api_keys_response.py +3 -1
- agenta/client/backend/types/llm_run_rate_limit.py +3 -1
- agenta/client/backend/types/meta_request.py +3 -1
- agenta/client/backend/types/metrics_dto.py +3 -1
- agenta/client/backend/types/new_testset.py +3 -1
- agenta/client/backend/types/node_dto.py +3 -1
- agenta/client/backend/types/o_tel_context_dto.py +3 -1
- agenta/client/backend/types/o_tel_event.py +6 -4
- agenta/client/backend/types/o_tel_event_dto.py +3 -1
- agenta/client/backend/types/o_tel_extra_dto.py +3 -1
- agenta/client/backend/types/o_tel_flat_span.py +6 -4
- agenta/client/backend/types/o_tel_link.py +6 -4
- agenta/client/backend/types/o_tel_link_dto.py +3 -1
- agenta/client/backend/types/o_tel_links_response.py +3 -1
- agenta/client/backend/types/o_tel_span.py +1 -1
- agenta/client/backend/types/o_tel_span_dto.py +3 -1
- agenta/client/backend/types/o_tel_spans_tree.py +3 -1
- agenta/client/backend/types/o_tel_tracing_data_response.py +3 -1
- agenta/client/backend/types/o_tel_tracing_request.py +3 -1
- agenta/client/backend/types/o_tel_tracing_response.py +3 -1
- agenta/client/backend/types/organization.py +3 -1
- agenta/client/backend/types/organization_details.py +3 -1
- agenta/client/backend/types/organization_membership_request.py +3 -1
- agenta/client/backend/types/organization_output.py +3 -1
- agenta/client/backend/types/organization_request.py +3 -1
- agenta/client/backend/types/parent_dto.py +3 -1
- agenta/client/backend/types/project_membership_request.py +3 -1
- agenta/client/backend/types/project_request.py +3 -1
- agenta/client/backend/types/project_scope.py +3 -1
- agenta/client/backend/types/projects_response.py +3 -1
- agenta/client/backend/types/reference.py +6 -4
- agenta/client/backend/types/reference_dto.py +3 -1
- agenta/client/backend/types/reference_request_model.py +3 -1
- agenta/client/backend/types/result.py +3 -1
- agenta/client/backend/types/root_dto.py +3 -1
- agenta/client/backend/types/scopes_response_model.py +3 -1
- agenta/client/backend/types/secret_dto.py +3 -1
- agenta/client/backend/types/secret_response_dto.py +3 -1
- agenta/client/backend/types/simple_evaluation_output.py +3 -1
- agenta/client/backend/types/span_dto.py +6 -4
- agenta/client/backend/types/standard_provider_dto.py +3 -1
- agenta/client/backend/types/standard_provider_settings_dto.py +3 -1
- agenta/client/backend/types/status_dto.py +3 -1
- agenta/client/backend/types/tags_request.py +3 -1
- agenta/client/backend/types/testcase_response.py +6 -4
- agenta/client/backend/types/testset.py +6 -4
- agenta/client/backend/types/{test_set_output_response.py → testset_output_response.py} +4 -2
- agenta/client/backend/types/testset_request.py +3 -1
- agenta/client/backend/types/testset_response.py +3 -1
- agenta/client/backend/types/{test_set_simple_response.py → testset_simple_response.py} +4 -2
- agenta/client/backend/types/testsets_response.py +3 -1
- agenta/client/backend/types/time_dto.py +3 -1
- agenta/client/backend/types/tree_dto.py +3 -1
- agenta/client/backend/types/update_app_output.py +3 -1
- agenta/client/backend/types/user_request.py +3 -1
- agenta/client/backend/types/validation_error.py +3 -1
- agenta/client/backend/types/workflow_artifact.py +6 -4
- agenta/client/backend/types/workflow_data.py +3 -1
- agenta/client/backend/types/workflow_flags.py +3 -1
- agenta/client/backend/types/workflow_request.py +3 -1
- agenta/client/backend/types/workflow_response.py +3 -1
- agenta/client/backend/types/workflow_revision.py +6 -4
- agenta/client/backend/types/workflow_revision_request.py +3 -1
- agenta/client/backend/types/workflow_revision_response.py +3 -1
- agenta/client/backend/types/workflow_revisions_response.py +3 -1
- agenta/client/backend/types/workflow_variant.py +6 -4
- agenta/client/backend/types/workflow_variant_request.py +3 -1
- agenta/client/backend/types/workflow_variant_response.py +3 -1
- agenta/client/backend/types/workflow_variants_response.py +3 -1
- agenta/client/backend/types/workflows_response.py +3 -1
- agenta/client/backend/types/workspace.py +3 -1
- agenta/client/backend/types/workspace_member_response.py +3 -1
- agenta/client/backend/types/workspace_membership_request.py +3 -1
- agenta/client/backend/types/workspace_permission.py +3 -1
- agenta/client/backend/types/workspace_request.py +3 -1
- agenta/client/backend/types/workspace_response.py +3 -1
- agenta/client/backend/workspace/client.py +2 -2
- agenta/client/client.py +102 -88
- agenta/sdk/__init__.py +52 -3
- agenta/sdk/agenta_init.py +43 -16
- agenta/sdk/assets.py +22 -15
- agenta/sdk/context/serving.py +20 -8
- agenta/sdk/context/tracing.py +40 -22
- agenta/sdk/contexts/__init__.py +0 -0
- agenta/sdk/contexts/routing.py +38 -0
- agenta/sdk/contexts/running.py +57 -0
- agenta/sdk/contexts/tracing.py +86 -0
- agenta/sdk/decorators/__init__.py +1 -0
- agenta/sdk/decorators/routing.py +284 -0
- agenta/sdk/decorators/running.py +692 -98
- agenta/sdk/decorators/serving.py +20 -21
- agenta/sdk/decorators/tracing.py +176 -131
- agenta/sdk/engines/__init__.py +0 -0
- agenta/sdk/engines/running/__init__.py +0 -0
- agenta/sdk/engines/running/utils.py +17 -0
- agenta/sdk/engines/tracing/__init__.py +1 -0
- agenta/sdk/engines/tracing/attributes.py +185 -0
- agenta/sdk/engines/tracing/conventions.py +49 -0
- agenta/sdk/engines/tracing/exporters.py +130 -0
- agenta/sdk/engines/tracing/inline.py +1154 -0
- agenta/sdk/engines/tracing/processors.py +190 -0
- agenta/sdk/engines/tracing/propagation.py +102 -0
- agenta/sdk/engines/tracing/spans.py +136 -0
- agenta/sdk/engines/tracing/tracing.py +324 -0
- agenta/sdk/evaluations/__init__.py +2 -0
- agenta/sdk/evaluations/metrics.py +37 -0
- agenta/sdk/evaluations/preview/__init__.py +0 -0
- agenta/sdk/evaluations/preview/evaluate.py +765 -0
- agenta/sdk/evaluations/preview/utils.py +861 -0
- agenta/sdk/evaluations/results.py +66 -0
- agenta/sdk/evaluations/runs.py +153 -0
- agenta/sdk/evaluations/scenarios.py +48 -0
- agenta/sdk/litellm/litellm.py +12 -0
- agenta/sdk/litellm/mockllm.py +6 -8
- agenta/sdk/litellm/mocks/__init__.py +5 -5
- agenta/sdk/managers/applications.py +304 -0
- agenta/sdk/managers/config.py +2 -2
- agenta/sdk/managers/evaluations.py +0 -0
- agenta/sdk/managers/evaluators.py +303 -0
- agenta/sdk/managers/secrets.py +161 -24
- agenta/sdk/managers/shared.py +3 -1
- agenta/sdk/managers/testsets.py +441 -0
- agenta/sdk/managers/vault.py +3 -3
- agenta/sdk/middleware/auth.py +0 -176
- agenta/sdk/middleware/vault.py +203 -8
- agenta/sdk/middlewares/__init__.py +0 -0
- agenta/sdk/middlewares/routing/__init__.py +0 -0
- agenta/sdk/middlewares/routing/auth.py +263 -0
- agenta/sdk/middlewares/routing/cors.py +30 -0
- agenta/sdk/middlewares/routing/otel.py +29 -0
- agenta/sdk/middlewares/running/__init__.py +0 -0
- agenta/sdk/middlewares/running/normalizer.py +321 -0
- agenta/sdk/middlewares/running/resolver.py +161 -0
- agenta/sdk/middlewares/running/vault.py +140 -0
- agenta/sdk/models/__init__.py +0 -0
- agenta/sdk/models/blobs.py +33 -0
- agenta/sdk/models/evaluations.py +119 -0
- agenta/sdk/models/git.py +126 -0
- agenta/sdk/models/shared.py +167 -0
- agenta/sdk/models/testsets.py +163 -0
- agenta/sdk/models/tracing.py +202 -0
- agenta/sdk/models/workflows.py +753 -0
- agenta/sdk/tracing/exporters.py +67 -17
- agenta/sdk/tracing/processors.py +97 -0
- agenta/sdk/tracing/propagation.py +3 -1
- agenta/sdk/tracing/spans.py +4 -0
- agenta/sdk/tracing/tracing.py +13 -13
- agenta/sdk/types.py +211 -17
- agenta/sdk/utils/cache.py +1 -1
- agenta/sdk/utils/client.py +38 -0
- agenta/sdk/utils/helpers.py +13 -12
- agenta/sdk/utils/logging.py +18 -78
- agenta/sdk/utils/references.py +23 -0
- agenta/sdk/workflows/builtin.py +600 -0
- agenta/sdk/workflows/configurations.py +22 -0
- agenta/sdk/workflows/errors.py +292 -0
- agenta/sdk/workflows/handlers.py +1791 -0
- agenta/sdk/workflows/interfaces.py +948 -0
- agenta/sdk/workflows/sandbox.py +118 -0
- agenta/sdk/workflows/utils.py +303 -6
- {agenta-0.57.0.dist-info → agenta-0.63.2.dist-info}/METADATA +33 -30
- agenta-0.63.2.dist-info/RECORD +421 -0
- agenta/sdk/middleware/adapt.py +0 -253
- agenta/sdk/middleware/base.py +0 -40
- agenta/sdk/middleware/flags.py +0 -40
- agenta/sdk/workflows/types.py +0 -472
- agenta-0.57.0.dist-info/RECORD +0 -371
- /agenta/sdk/{workflows → engines/running}/registry.py +0 -0
- {agenta-0.57.0.dist-info → agenta-0.63.2.dist-info}/WHEEL +0 -0
agenta/sdk/tracing/exporters.py
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
from typing import Sequence, Dict, List, Optional
|
|
1
|
+
from typing import Sequence, Dict, List, Optional, Any
|
|
2
|
+
from threading import Thread
|
|
3
|
+
from os import environ
|
|
4
|
+
from uuid import UUID
|
|
2
5
|
|
|
3
6
|
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
|
|
4
7
|
from opentelemetry.sdk.trace.export import (
|
|
@@ -8,18 +11,21 @@ from opentelemetry.sdk.trace.export import (
|
|
|
8
11
|
ReadableSpan,
|
|
9
12
|
)
|
|
10
13
|
|
|
14
|
+
from agenta.sdk.utils.constants import TRUTHY
|
|
11
15
|
from agenta.sdk.utils.logging import get_module_logger
|
|
12
16
|
from agenta.sdk.utils.exceptions import suppress
|
|
13
17
|
from agenta.sdk.utils.cache import TTLLRUCache
|
|
14
|
-
from agenta.sdk.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
from agenta.sdk.contexts.tracing import (
|
|
19
|
+
otlp_context_manager,
|
|
20
|
+
otlp_context,
|
|
21
|
+
OTLPContext,
|
|
18
22
|
)
|
|
19
23
|
|
|
20
24
|
|
|
21
25
|
log = get_module_logger(__name__)
|
|
22
26
|
|
|
27
|
+
_ASYNC_EXPORT = environ.get("AGENTA_OTLP_ASYNC_EXPORT", "true").lower() in TRUTHY
|
|
28
|
+
|
|
23
29
|
|
|
24
30
|
class InlineTraceExporter(SpanExporter):
|
|
25
31
|
def __init__(
|
|
@@ -45,6 +51,8 @@ class InlineTraceExporter(SpanExporter):
|
|
|
45
51
|
|
|
46
52
|
self._registry[trace_id].append(span)
|
|
47
53
|
|
|
54
|
+
return
|
|
55
|
+
|
|
48
56
|
def shutdown(self) -> None:
|
|
49
57
|
self._shutdown = True
|
|
50
58
|
|
|
@@ -84,7 +92,7 @@ class OTLPExporter(OTLPSpanExporter):
|
|
|
84
92
|
self.credentials = credentials
|
|
85
93
|
|
|
86
94
|
def export(self, spans: Sequence[ReadableSpan]) -> SpanExportResult:
|
|
87
|
-
grouped_spans: Dict[str, List[
|
|
95
|
+
grouped_spans: Dict[Optional[str], List[ReadableSpan]] = dict()
|
|
88
96
|
|
|
89
97
|
for span in spans:
|
|
90
98
|
trace_id = span.get_span_context().trace_id
|
|
@@ -94,18 +102,28 @@ class OTLPExporter(OTLPSpanExporter):
|
|
|
94
102
|
credentials = self.credentials.get(trace_id)
|
|
95
103
|
|
|
96
104
|
if credentials not in grouped_spans:
|
|
97
|
-
grouped_spans[credentials] =
|
|
105
|
+
grouped_spans[credentials] = list()
|
|
98
106
|
|
|
99
107
|
grouped_spans[credentials].append(span)
|
|
100
108
|
|
|
101
109
|
serialized_spans = []
|
|
102
110
|
|
|
103
111
|
for credentials, _spans in grouped_spans.items():
|
|
104
|
-
with
|
|
105
|
-
context=
|
|
112
|
+
with otlp_context_manager(
|
|
113
|
+
context=OTLPContext(
|
|
106
114
|
credentials=credentials,
|
|
107
115
|
)
|
|
108
116
|
):
|
|
117
|
+
for _span in _spans:
|
|
118
|
+
trace_id = _span.get_span_context().trace_id
|
|
119
|
+
span_id = _span.get_span_context().span_id
|
|
120
|
+
|
|
121
|
+
# log.debug(
|
|
122
|
+
# "[SPAN] [EXPORT]",
|
|
123
|
+
# trace_id=UUID(int=trace_id).hex,
|
|
124
|
+
# span_id=UUID(int=span_id).hex[-16:],
|
|
125
|
+
# )
|
|
126
|
+
|
|
109
127
|
serialized_spans.append(super().export(_spans))
|
|
110
128
|
|
|
111
129
|
if all(serialized_spans):
|
|
@@ -114,16 +132,48 @@ class OTLPExporter(OTLPSpanExporter):
|
|
|
114
132
|
return SpanExportResult.FAILURE
|
|
115
133
|
|
|
116
134
|
def _export(self, serialized_data: bytes, timeout_sec: Optional[float] = None):
|
|
117
|
-
|
|
135
|
+
try:
|
|
136
|
+
credentials = otlp_context.get().credentials
|
|
137
|
+
|
|
138
|
+
if credentials:
|
|
139
|
+
self._session.headers.update({"Authorization": credentials})
|
|
140
|
+
|
|
141
|
+
def __export():
|
|
142
|
+
with suppress():
|
|
143
|
+
resp = None
|
|
144
|
+
if timeout_sec is not None:
|
|
145
|
+
resp = super(OTLPExporter, self)._export(
|
|
146
|
+
serialized_data,
|
|
147
|
+
timeout_sec,
|
|
148
|
+
)
|
|
149
|
+
else:
|
|
150
|
+
resp = super(OTLPExporter, self)._export(
|
|
151
|
+
serialized_data,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# log.debug(
|
|
155
|
+
# "[SPAN] [_EXPORT]",
|
|
156
|
+
# data=serialized_data,
|
|
157
|
+
# resp=resp,
|
|
158
|
+
# )
|
|
159
|
+
|
|
160
|
+
if _ASYNC_EXPORT is True:
|
|
161
|
+
# log.debug("[SPAN] [ASYNC.X]", credentials=(credentials is not None))
|
|
162
|
+
thread = Thread(target=__export, daemon=False)
|
|
163
|
+
thread.start()
|
|
164
|
+
else:
|
|
165
|
+
# log.debug("[SPAN] [ SYNC.X]", credentials=(credentials is not None))
|
|
166
|
+
return __export()
|
|
118
167
|
|
|
119
|
-
|
|
120
|
-
|
|
168
|
+
except Exception as e:
|
|
169
|
+
log.error(f"Export failed with error: {e}", exc_info=True)
|
|
121
170
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
171
|
+
finally:
|
|
172
|
+
|
|
173
|
+
class Response:
|
|
174
|
+
ok = True
|
|
175
|
+
|
|
176
|
+
return Response()
|
|
127
177
|
|
|
128
178
|
|
|
129
179
|
ConsoleExporter = ConsoleSpanExporter
|
agenta/sdk/tracing/processors.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from typing import Optional, Dict, List
|
|
2
2
|
from threading import Lock
|
|
3
|
+
from json import dumps
|
|
4
|
+
from uuid import UUID
|
|
3
5
|
|
|
4
6
|
from opentelemetry.baggage import get_all as get_baggage
|
|
5
7
|
from opentelemetry.context import Context
|
|
@@ -9,10 +11,13 @@ from opentelemetry.sdk.trace.export import (
|
|
|
9
11
|
ReadableSpan,
|
|
10
12
|
BatchSpanProcessor,
|
|
11
13
|
)
|
|
14
|
+
from opentelemetry.trace import SpanContext
|
|
12
15
|
|
|
13
16
|
from agenta.sdk.utils.logging import get_module_logger
|
|
14
17
|
from agenta.sdk.tracing.conventions import Reference
|
|
15
18
|
|
|
19
|
+
from agenta.sdk.contexts.tracing import TracingContext
|
|
20
|
+
|
|
16
21
|
log = get_module_logger(__name__)
|
|
17
22
|
|
|
18
23
|
|
|
@@ -50,6 +55,15 @@ class TraceProcessor(SpanProcessor):
|
|
|
50
55
|
span: Span,
|
|
51
56
|
parent_context: Optional[Context] = None,
|
|
52
57
|
) -> None:
|
|
58
|
+
trace_id = span.context.trace_id
|
|
59
|
+
span_id = span.context.span_id
|
|
60
|
+
|
|
61
|
+
# log.debug(
|
|
62
|
+
# "[SPAN] [START] ",
|
|
63
|
+
# trace_id=UUID(int=trace_id).hex,
|
|
64
|
+
# span_id=UUID(int=span_id).hex[-16:],
|
|
65
|
+
# )
|
|
66
|
+
|
|
53
67
|
for key in self.references.keys():
|
|
54
68
|
span.set_attribute(f"ag.refs.{key}", self.references[key])
|
|
55
69
|
|
|
@@ -61,6 +75,83 @@ class TraceProcessor(SpanProcessor):
|
|
|
61
75
|
if _key in [_.value for _ in Reference.__members__.values()]:
|
|
62
76
|
span.set_attribute(key, baggage[key])
|
|
63
77
|
|
|
78
|
+
context = TracingContext.get()
|
|
79
|
+
|
|
80
|
+
trace_type = span.attributes.get("trace_type") if span.attributes else None
|
|
81
|
+
|
|
82
|
+
context.annotate = (
|
|
83
|
+
context.annotate
|
|
84
|
+
or (context.type == "annotation")
|
|
85
|
+
or (trace_type == "annotation")
|
|
86
|
+
)
|
|
87
|
+
context.type = (
|
|
88
|
+
(str(trace_type) if trace_type else None)
|
|
89
|
+
or context.type
|
|
90
|
+
or ("annotation" if context.annotate else "invocation")
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
span.set_attribute("ag.type.tree", context.type)
|
|
94
|
+
|
|
95
|
+
if context.flags:
|
|
96
|
+
for key in context.flags.keys():
|
|
97
|
+
span.set_attribute(f"ag.flags.{key}", context.flags[key])
|
|
98
|
+
# if context.tags:
|
|
99
|
+
# for key in context.tags.keys():
|
|
100
|
+
# span.set_attribute(f"ag.tags.{key}", context.tags[key])
|
|
101
|
+
# if context.meta:
|
|
102
|
+
# span.set_attribute(f"ag.meta.", dumps(context.meta))
|
|
103
|
+
|
|
104
|
+
# --- DISTRIBUTED
|
|
105
|
+
if not self.inline:
|
|
106
|
+
if context.links:
|
|
107
|
+
for key, link in context.links.items():
|
|
108
|
+
try:
|
|
109
|
+
link = link.model_dump(mode="json", exclude_none=True)
|
|
110
|
+
except: # pylint: disable=bare-except
|
|
111
|
+
pass
|
|
112
|
+
if not isinstance(link, dict):
|
|
113
|
+
continue
|
|
114
|
+
if not link.get("trace_id") or not link.get("span_id"):
|
|
115
|
+
continue
|
|
116
|
+
|
|
117
|
+
span.add_link(
|
|
118
|
+
context=SpanContext(
|
|
119
|
+
trace_id=int(str(link.get("trace_id")), 16),
|
|
120
|
+
span_id=int(str(link.get("span_id")), 16),
|
|
121
|
+
is_remote=True,
|
|
122
|
+
),
|
|
123
|
+
attributes=dict(
|
|
124
|
+
key=str(key),
|
|
125
|
+
),
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
if context.references:
|
|
129
|
+
for key, ref in context.references.items():
|
|
130
|
+
try:
|
|
131
|
+
ref = ref.model_dump(mode="json", exclude_none=True)
|
|
132
|
+
except: # pylint: disable=bare-except
|
|
133
|
+
pass
|
|
134
|
+
if not isinstance(ref, dict):
|
|
135
|
+
continue
|
|
136
|
+
if not ref.get("id") and not ref.get("slug") and not ref.get("version"):
|
|
137
|
+
continue
|
|
138
|
+
|
|
139
|
+
if ref.get("id"):
|
|
140
|
+
span.set_attribute(
|
|
141
|
+
f"ag.refs.{key}.id",
|
|
142
|
+
str(ref.get("id")),
|
|
143
|
+
)
|
|
144
|
+
if ref.get("slug"):
|
|
145
|
+
span.set_attribute(
|
|
146
|
+
f"ag.refs.{key}.slug",
|
|
147
|
+
str(ref.get("slug")),
|
|
148
|
+
)
|
|
149
|
+
if ref.get("version"):
|
|
150
|
+
span.set_attribute(
|
|
151
|
+
f"ag.refs.{key}.version",
|
|
152
|
+
str(ref.get("version")),
|
|
153
|
+
)
|
|
154
|
+
|
|
64
155
|
trace_id = span.context.trace_id
|
|
65
156
|
span_id = span.context.span_id
|
|
66
157
|
|
|
@@ -74,6 +165,12 @@ class TraceProcessor(SpanProcessor):
|
|
|
74
165
|
trace_id = span.context.trace_id
|
|
75
166
|
span_id = span.context.span_id
|
|
76
167
|
|
|
168
|
+
# log.debug(
|
|
169
|
+
# "[SPAN] [END] ",
|
|
170
|
+
# trace_id=UUID(int=trace_id).hex,
|
|
171
|
+
# span_id=UUID(int=span_id).hex[-16:],
|
|
172
|
+
# )
|
|
173
|
+
|
|
77
174
|
self._spans.setdefault(trace_id, []).append(span)
|
|
78
175
|
self._registry.setdefault(trace_id, {})
|
|
79
176
|
self._registry[trace_id].pop(span_id, None)
|
|
@@ -6,6 +6,8 @@ from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapProp
|
|
|
6
6
|
from opentelemetry.baggage import set_baggage
|
|
7
7
|
from opentelemetry.context import get_current
|
|
8
8
|
|
|
9
|
+
from agenta.sdk.contexts.tracing import TracingContext
|
|
10
|
+
|
|
9
11
|
import agenta as ag
|
|
10
12
|
|
|
11
13
|
|
|
@@ -72,7 +74,7 @@ def inject(
|
|
|
72
74
|
|
|
73
75
|
_context = get_current()
|
|
74
76
|
|
|
75
|
-
ctx =
|
|
77
|
+
ctx = TracingContext.get()
|
|
76
78
|
|
|
77
79
|
# --- Inject traceparent --- #
|
|
78
80
|
try:
|
agenta/sdk/tracing/spans.py
CHANGED
agenta/sdk/tracing/tracing.py
CHANGED
|
@@ -99,19 +99,6 @@ class Tracing(metaclass=Singleton):
|
|
|
99
99
|
resource=Resource(attributes={"service.name": "agenta-sdk"})
|
|
100
100
|
)
|
|
101
101
|
|
|
102
|
-
# --- INLINE
|
|
103
|
-
if inline:
|
|
104
|
-
# TRACE PROCESSORS -- INLINE
|
|
105
|
-
self.inline = TraceProcessor(
|
|
106
|
-
InlineExporter(
|
|
107
|
-
registry=self.inline_spans,
|
|
108
|
-
),
|
|
109
|
-
references=self.references,
|
|
110
|
-
inline=inline,
|
|
111
|
-
)
|
|
112
|
-
self.tracer_provider.add_span_processor(self.inline)
|
|
113
|
-
# --- INLINE
|
|
114
|
-
|
|
115
102
|
# TRACE PROCESSORS -- OTLP
|
|
116
103
|
try:
|
|
117
104
|
log.info("Agenta - OLTP URL: %s", self.otlp_url)
|
|
@@ -129,6 +116,19 @@ class Tracing(metaclass=Singleton):
|
|
|
129
116
|
except: # pylint: disable=bare-except
|
|
130
117
|
log.warning("Agenta - OLTP unreachable, skipping exports.")
|
|
131
118
|
|
|
119
|
+
# --- INLINE
|
|
120
|
+
if inline:
|
|
121
|
+
# TRACE PROCESSORS -- INLINE
|
|
122
|
+
self.inline = TraceProcessor(
|
|
123
|
+
InlineExporter(
|
|
124
|
+
registry=self.inline_spans,
|
|
125
|
+
),
|
|
126
|
+
references=self.references,
|
|
127
|
+
inline=inline,
|
|
128
|
+
)
|
|
129
|
+
self.tracer_provider.add_span_processor(self.inline)
|
|
130
|
+
# --- INLINE
|
|
131
|
+
|
|
132
132
|
# GLOBAL TRACER PROVIDER -- INSTRUMENTATION LIBRARIES
|
|
133
133
|
set_tracer_provider(self.tracer_provider)
|
|
134
134
|
# TRACER
|
agenta/sdk/types.py
CHANGED
|
@@ -3,7 +3,7 @@ from dataclasses import dataclass
|
|
|
3
3
|
from typing import List, Union, Optional, Dict, Literal, Any
|
|
4
4
|
|
|
5
5
|
from pydantic import ConfigDict, BaseModel, HttpUrl
|
|
6
|
-
from pydantic import BaseModel, Field, model_validator
|
|
6
|
+
from pydantic import BaseModel, Field, model_validator, AliasChoices
|
|
7
7
|
|
|
8
8
|
from starlette.responses import StreamingResponse
|
|
9
9
|
|
|
@@ -71,15 +71,15 @@ class StreamResponse(StreamingResponse):
|
|
|
71
71
|
):
|
|
72
72
|
headers = dict(extra_headers or {})
|
|
73
73
|
if version is not None:
|
|
74
|
-
headers["
|
|
74
|
+
headers["x-ag-version"] = version
|
|
75
75
|
if content_type:
|
|
76
|
-
headers["
|
|
76
|
+
headers["x-ag-content-type"] = content_type
|
|
77
77
|
if tree_id:
|
|
78
|
-
headers["
|
|
78
|
+
headers["x-ag-tree-id"] = tree_id
|
|
79
79
|
if trace_id:
|
|
80
|
-
headers["
|
|
80
|
+
headers["x-ag-trace-id"] = trace_id
|
|
81
81
|
if span_id:
|
|
82
|
-
headers["
|
|
82
|
+
headers["x-ag-span-id"] = span_id
|
|
83
83
|
|
|
84
84
|
super().__init__(
|
|
85
85
|
content=content,
|
|
@@ -335,7 +335,29 @@ class ContentPartImage(BaseModel):
|
|
|
335
335
|
image_url: ImageURL
|
|
336
336
|
|
|
337
337
|
|
|
338
|
-
|
|
338
|
+
class FileInput(BaseModel):
|
|
339
|
+
file_id: Optional[str] = Field(
|
|
340
|
+
default=None,
|
|
341
|
+
alias="file_id",
|
|
342
|
+
validation_alias=AliasChoices("file_id", "fileId"),
|
|
343
|
+
)
|
|
344
|
+
file_data: Optional[str] = Field(
|
|
345
|
+
default=None,
|
|
346
|
+
alias="file_data",
|
|
347
|
+
validation_alias=AliasChoices("file_data", "fileData"),
|
|
348
|
+
)
|
|
349
|
+
filename: Optional[str] = None
|
|
350
|
+
format: Optional[str] = None
|
|
351
|
+
|
|
352
|
+
model_config = {"populate_by_name": True}
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
class ContentPartFile(BaseModel):
|
|
356
|
+
type: Literal["file"] = "file"
|
|
357
|
+
file: FileInput
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
ContentPart = Union[ContentPartText, ContentPartImage, ContentPartFile]
|
|
339
361
|
|
|
340
362
|
|
|
341
363
|
class Message(BaseModel):
|
|
@@ -387,7 +409,7 @@ class ModelConfig(BaseModel):
|
|
|
387
409
|
"""Configuration for model parameters"""
|
|
388
410
|
|
|
389
411
|
model: str = MCField(
|
|
390
|
-
default="gpt-
|
|
412
|
+
default="gpt-4o-mini",
|
|
391
413
|
choices=supported_llm_models,
|
|
392
414
|
)
|
|
393
415
|
|
|
@@ -421,6 +443,14 @@ class ModelConfig(BaseModel):
|
|
|
421
443
|
le=2.0,
|
|
422
444
|
description="Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far",
|
|
423
445
|
)
|
|
446
|
+
reasoning_effort: Optional[Literal["none", "low", "medium", "high"]] = Field(
|
|
447
|
+
default=None,
|
|
448
|
+
description="Controls the reasoning effort for thinking models. Options: 'none' (cost-optimized, 0 tokens), 'low' (1024 tokens), 'medium' (2048 tokens), 'high' (4096 tokens)",
|
|
449
|
+
json_schema_extra={
|
|
450
|
+
"x-parameter": "choice",
|
|
451
|
+
"enum": ["none", "low", "medium", "high"],
|
|
452
|
+
},
|
|
453
|
+
)
|
|
424
454
|
response_format: Optional[ResponseFormat] = Field(
|
|
425
455
|
default=None,
|
|
426
456
|
description="An object specifying the format that the model must output",
|
|
@@ -462,6 +492,154 @@ class TemplateFormatError(PromptTemplateError):
|
|
|
462
492
|
super().__init__(message)
|
|
463
493
|
|
|
464
494
|
|
|
495
|
+
import json
|
|
496
|
+
import re
|
|
497
|
+
from typing import Any, Dict, Iterable, Tuple, Optional
|
|
498
|
+
|
|
499
|
+
# --- Optional dependency: python-jsonpath (provides JSONPath + JSON Pointer) ---
|
|
500
|
+
try:
|
|
501
|
+
import jsonpath # ✅ use module API
|
|
502
|
+
from jsonpath import JSONPointer # pointer class is fine to use
|
|
503
|
+
except Exception:
|
|
504
|
+
jsonpath = None
|
|
505
|
+
JSONPointer = None
|
|
506
|
+
|
|
507
|
+
# ========= Scheme detection =========
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
def detect_scheme(expr: str) -> str:
|
|
511
|
+
"""Return 'json-path', 'json-pointer', or 'dot-notation' based on the placeholder prefix."""
|
|
512
|
+
if expr.startswith("$"):
|
|
513
|
+
return "json-path"
|
|
514
|
+
if expr.startswith("/"):
|
|
515
|
+
return "json-pointer"
|
|
516
|
+
return "dot-notation"
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
# ========= Resolvers =========
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
def resolve_dot_notation(expr: str, data: dict) -> object:
|
|
523
|
+
if "[" in expr or "]" in expr:
|
|
524
|
+
raise KeyError(f"Bracket syntax is not supported in dot-notation: {expr!r}")
|
|
525
|
+
|
|
526
|
+
# First, check if the expression exists as a literal key (e.g., "topic.story" as a single key)
|
|
527
|
+
# This allows users to use dots in their variable names without nested access
|
|
528
|
+
if expr in data:
|
|
529
|
+
return data[expr]
|
|
530
|
+
|
|
531
|
+
# If not found as a literal key, try to parse as dot-notation path
|
|
532
|
+
cur = data
|
|
533
|
+
for token in (p for p in expr.split(".") if p):
|
|
534
|
+
if isinstance(cur, list) and token.isdigit():
|
|
535
|
+
cur = cur[int(token)]
|
|
536
|
+
else:
|
|
537
|
+
if not isinstance(cur, dict):
|
|
538
|
+
raise KeyError(
|
|
539
|
+
f"Cannot access key {token!r} on non-dict while resolving {expr!r}"
|
|
540
|
+
)
|
|
541
|
+
if token not in cur:
|
|
542
|
+
raise KeyError(f"Missing key {token!r} while resolving {expr!r}")
|
|
543
|
+
cur = cur[token]
|
|
544
|
+
return cur
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
def resolve_json_path(expr: str, data: dict) -> object:
|
|
548
|
+
if jsonpath is None:
|
|
549
|
+
raise ImportError("python-jsonpath is required for json-path ($...)")
|
|
550
|
+
|
|
551
|
+
if not (expr == "$" or expr.startswith("$.") or expr.startswith("$[")):
|
|
552
|
+
raise ValueError(
|
|
553
|
+
f"Invalid json-path expression {expr!r}. "
|
|
554
|
+
"Must start with '$', '$.' or '$[' (no implicit normalization)."
|
|
555
|
+
)
|
|
556
|
+
|
|
557
|
+
# Use package-level APIf
|
|
558
|
+
results = jsonpath.findall(expr, data) # always returns a list
|
|
559
|
+
return results[0] if len(results) == 1 else results
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
def resolve_json_pointer(expr: str, data: Dict[str, Any]) -> Any:
|
|
563
|
+
"""Resolve a JSON Pointer; returns a single value."""
|
|
564
|
+
if JSONPointer is None:
|
|
565
|
+
raise ImportError("python-jsonpath is required for json-pointer (/...)")
|
|
566
|
+
return JSONPointer(expr).resolve(data)
|
|
567
|
+
|
|
568
|
+
|
|
569
|
+
def resolve_any(expr: str, data: Dict[str, Any]) -> Any:
|
|
570
|
+
"""Dispatch to the right resolver based on detected scheme."""
|
|
571
|
+
scheme = detect_scheme(expr)
|
|
572
|
+
if scheme == "json-path":
|
|
573
|
+
return resolve_json_path(expr, data)
|
|
574
|
+
if scheme == "json-pointer":
|
|
575
|
+
return resolve_json_pointer(expr, data)
|
|
576
|
+
return resolve_dot_notation(expr, data)
|
|
577
|
+
|
|
578
|
+
|
|
579
|
+
# ========= Placeholder & coercion helpers =========
|
|
580
|
+
|
|
581
|
+
_PLACEHOLDER_RE = re.compile(r"\{\{\s*(.*?)\s*\}\}")
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
def extract_placeholders(template: str) -> Iterable[str]:
|
|
585
|
+
"""Yield the inner text of all {{ ... }} occurrences (trimmed)."""
|
|
586
|
+
for m in _PLACEHOLDER_RE.finditer(template):
|
|
587
|
+
yield m.group(1).strip()
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
def coerce_to_str(value: Any) -> str:
|
|
591
|
+
"""Pretty stringify values for embedding into templates."""
|
|
592
|
+
if isinstance(value, (dict, list)):
|
|
593
|
+
return json.dumps(value, ensure_ascii=False)
|
|
594
|
+
return str(value)
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
def build_replacements(
|
|
598
|
+
placeholders: Iterable[str], data: Dict[str, Any]
|
|
599
|
+
) -> Tuple[Dict[str, str], set]:
|
|
600
|
+
"""
|
|
601
|
+
Resolve all placeholders against data.
|
|
602
|
+
Returns (replacements, unresolved_placeholders).
|
|
603
|
+
"""
|
|
604
|
+
replacements: Dict[str, str] = {}
|
|
605
|
+
unresolved: set = set()
|
|
606
|
+
for expr in set(placeholders):
|
|
607
|
+
try:
|
|
608
|
+
val = resolve_any(expr, data)
|
|
609
|
+
# Escape backslashes to avoid regex replacement surprises
|
|
610
|
+
replacements[expr] = coerce_to_str(val).replace("\\", "\\\\")
|
|
611
|
+
except Exception:
|
|
612
|
+
unresolved.add(expr)
|
|
613
|
+
return replacements, unresolved
|
|
614
|
+
|
|
615
|
+
|
|
616
|
+
def apply_replacements(template: str, replacements: Dict[str, str]) -> str:
|
|
617
|
+
"""Replace {{ expr }} using a callback to avoid regex-injection issues."""
|
|
618
|
+
|
|
619
|
+
def _repl(m: re.Match) -> str:
|
|
620
|
+
expr = m.group(1).strip()
|
|
621
|
+
return replacements.get(expr, m.group(0))
|
|
622
|
+
|
|
623
|
+
return _PLACEHOLDER_RE.sub(_repl, template)
|
|
624
|
+
|
|
625
|
+
|
|
626
|
+
def compute_truly_unreplaced(original: set, rendered: str) -> set:
|
|
627
|
+
"""Only count placeholders that were in the original template and remain."""
|
|
628
|
+
now = set(extract_placeholders(rendered))
|
|
629
|
+
return original & now
|
|
630
|
+
|
|
631
|
+
|
|
632
|
+
def missing_lib_hints(unreplaced: set) -> Optional[str]:
|
|
633
|
+
"""Suggest installing python-jsonpath if placeholders indicate json-path or json-pointer usage."""
|
|
634
|
+
if any(expr.startswith("$") or expr.startswith("/") for expr in unreplaced) and (
|
|
635
|
+
jsonpath is None or JSONPointer is None
|
|
636
|
+
):
|
|
637
|
+
return (
|
|
638
|
+
"Install python-jsonpath to enable json-path ($...) and json-pointer (/...)"
|
|
639
|
+
)
|
|
640
|
+
return None
|
|
641
|
+
|
|
642
|
+
|
|
465
643
|
class PromptTemplate(BaseModel):
|
|
466
644
|
"""A template for generating prompts with formatting capabilities"""
|
|
467
645
|
|
|
@@ -508,6 +686,7 @@ class PromptTemplate(BaseModel):
|
|
|
508
686
|
try:
|
|
509
687
|
if self.template_format == "fstring":
|
|
510
688
|
return content.format(**kwargs)
|
|
689
|
+
|
|
511
690
|
elif self.template_format == "jinja2":
|
|
512
691
|
from jinja2 import Template, TemplateError
|
|
513
692
|
|
|
@@ -518,22 +697,33 @@ class PromptTemplate(BaseModel):
|
|
|
518
697
|
f"Jinja2 template error in content: '{content}'. Error: {str(e)}",
|
|
519
698
|
original_error=e,
|
|
520
699
|
)
|
|
700
|
+
|
|
521
701
|
elif self.template_format == "curly":
|
|
522
|
-
|
|
702
|
+
original_placeholders = set(extract_placeholders(content))
|
|
703
|
+
|
|
704
|
+
replacements, _unresolved = build_replacements(
|
|
705
|
+
original_placeholders, kwargs
|
|
706
|
+
)
|
|
707
|
+
|
|
708
|
+
result = apply_replacements(content, replacements)
|
|
523
709
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
if
|
|
528
|
-
|
|
710
|
+
truly_unreplaced = compute_truly_unreplaced(
|
|
711
|
+
original_placeholders, result
|
|
712
|
+
)
|
|
713
|
+
if truly_unreplaced:
|
|
714
|
+
hint = missing_lib_hints(truly_unreplaced)
|
|
715
|
+
suffix = f" Hint: {hint}" if hint else ""
|
|
529
716
|
raise TemplateFormatError(
|
|
530
|
-
f"Unreplaced variables in curly template: {
|
|
717
|
+
f"Unreplaced variables in curly template: {sorted(truly_unreplaced)}.{suffix}"
|
|
531
718
|
)
|
|
719
|
+
|
|
532
720
|
return result
|
|
721
|
+
|
|
533
722
|
else:
|
|
534
723
|
raise TemplateFormatError(
|
|
535
724
|
f"Unknown template format: {self.template_format}"
|
|
536
725
|
)
|
|
726
|
+
|
|
537
727
|
except KeyError as e:
|
|
538
728
|
key = str(e).strip("'")
|
|
539
729
|
raise TemplateFormatError(
|
|
@@ -541,7 +731,8 @@ class PromptTemplate(BaseModel):
|
|
|
541
731
|
)
|
|
542
732
|
except Exception as e:
|
|
543
733
|
raise TemplateFormatError(
|
|
544
|
-
f"Error formatting template '{content}': {str(e)}",
|
|
734
|
+
f"Error formatting template '{content}': {str(e)}",
|
|
735
|
+
original_error=e,
|
|
545
736
|
)
|
|
546
737
|
|
|
547
738
|
def _substitute_variables(self, obj: Any, kwargs: Dict[str, Any]) -> Any:
|
|
@@ -616,7 +807,7 @@ class PromptTemplate(BaseModel):
|
|
|
616
807
|
)
|
|
617
808
|
)
|
|
618
809
|
|
|
619
|
-
new_llm_config = self.llm_config.
|
|
810
|
+
new_llm_config = self.llm_config.model_copy(deep=True)
|
|
620
811
|
if new_llm_config.response_format is not None:
|
|
621
812
|
rf_dict = new_llm_config.response_format.model_dump(by_alias=True)
|
|
622
813
|
substituted = self._substitute_variables(rf_dict, kwargs)
|
|
@@ -658,6 +849,9 @@ class PromptTemplate(BaseModel):
|
|
|
658
849
|
if self.llm_config.presence_penalty is not None:
|
|
659
850
|
kwargs["presence_penalty"] = self.llm_config.presence_penalty
|
|
660
851
|
|
|
852
|
+
if self.llm_config.reasoning_effort is not None:
|
|
853
|
+
kwargs["reasoning_effort"] = self.llm_config.reasoning_effort
|
|
854
|
+
|
|
661
855
|
if self.llm_config.response_format:
|
|
662
856
|
kwargs["response_format"] = self.llm_config.response_format.dict(
|
|
663
857
|
by_alias=True
|
agenta/sdk/utils/cache.py
CHANGED
|
@@ -5,7 +5,7 @@ from collections import OrderedDict
|
|
|
5
5
|
from threading import Lock
|
|
6
6
|
|
|
7
7
|
CACHE_CAPACITY = int(getenv("AGENTA_MIDDLEWARE_CACHE_CAPACITY", "512"))
|
|
8
|
-
CACHE_TTL = int(getenv("AGENTA_MIDDLEWARE_CACHE_TTL", str(
|
|
8
|
+
CACHE_TTL = int(getenv("AGENTA_MIDDLEWARE_CACHE_TTL", str(1 * 60))) # 1 minutes
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class TTLLRUCache:
|