mantisdk 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of mantisdk might be problematic. Click here for more details.
- mantisdk/__init__.py +22 -0
- mantisdk/adapter/__init__.py +15 -0
- mantisdk/adapter/base.py +94 -0
- mantisdk/adapter/messages.py +270 -0
- mantisdk/adapter/triplet.py +1028 -0
- mantisdk/algorithm/__init__.py +39 -0
- mantisdk/algorithm/apo/__init__.py +5 -0
- mantisdk/algorithm/apo/apo.py +889 -0
- mantisdk/algorithm/apo/prompts/apply_edit_variant01.poml +22 -0
- mantisdk/algorithm/apo/prompts/apply_edit_variant02.poml +18 -0
- mantisdk/algorithm/apo/prompts/text_gradient_variant01.poml +18 -0
- mantisdk/algorithm/apo/prompts/text_gradient_variant02.poml +16 -0
- mantisdk/algorithm/apo/prompts/text_gradient_variant03.poml +107 -0
- mantisdk/algorithm/base.py +162 -0
- mantisdk/algorithm/decorator.py +264 -0
- mantisdk/algorithm/fast.py +250 -0
- mantisdk/algorithm/gepa/__init__.py +59 -0
- mantisdk/algorithm/gepa/adapter.py +459 -0
- mantisdk/algorithm/gepa/gepa.py +364 -0
- mantisdk/algorithm/gepa/lib/__init__.py +18 -0
- mantisdk/algorithm/gepa/lib/adapters/README.md +12 -0
- mantisdk/algorithm/gepa/lib/adapters/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/adapters/anymaths_adapter/README.md +341 -0
- mantisdk/algorithm/gepa/lib/adapters/anymaths_adapter/__init__.py +1 -0
- mantisdk/algorithm/gepa/lib/adapters/anymaths_adapter/anymaths_adapter.py +174 -0
- mantisdk/algorithm/gepa/lib/adapters/anymaths_adapter/requirements.txt +1 -0
- mantisdk/algorithm/gepa/lib/adapters/default_adapter/README.md +0 -0
- mantisdk/algorithm/gepa/lib/adapters/default_adapter/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/adapters/default_adapter/default_adapter.py +209 -0
- mantisdk/algorithm/gepa/lib/adapters/dspy_adapter/README.md +7 -0
- mantisdk/algorithm/gepa/lib/adapters/dspy_adapter/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/adapters/dspy_adapter/dspy_adapter.py +307 -0
- mantisdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/README.md +99 -0
- mantisdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/dspy_program_proposal_signature.py +137 -0
- mantisdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/full_program_adapter.py +266 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/GEPA_RAG.md +621 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/__init__.py +56 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/evaluation_metrics.py +226 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/generic_rag_adapter.py +496 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/rag_pipeline.py +238 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_store_interface.py +212 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/__init__.py +2 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/chroma_store.py +196 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/lancedb_store.py +422 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/milvus_store.py +409 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/qdrant_store.py +368 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/weaviate_store.py +418 -0
- mantisdk/algorithm/gepa/lib/adapters/mcp_adapter/README.md +552 -0
- mantisdk/algorithm/gepa/lib/adapters/mcp_adapter/__init__.py +37 -0
- mantisdk/algorithm/gepa/lib/adapters/mcp_adapter/mcp_adapter.py +705 -0
- mantisdk/algorithm/gepa/lib/adapters/mcp_adapter/mcp_client.py +364 -0
- mantisdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/README.md +9 -0
- mantisdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/terminal_bench_adapter.py +217 -0
- mantisdk/algorithm/gepa/lib/api.py +375 -0
- mantisdk/algorithm/gepa/lib/core/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/core/adapter.py +180 -0
- mantisdk/algorithm/gepa/lib/core/data_loader.py +74 -0
- mantisdk/algorithm/gepa/lib/core/engine.py +356 -0
- mantisdk/algorithm/gepa/lib/core/result.py +233 -0
- mantisdk/algorithm/gepa/lib/core/state.py +636 -0
- mantisdk/algorithm/gepa/lib/examples/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/examples/aime.py +24 -0
- mantisdk/algorithm/gepa/lib/examples/anymaths-bench/eval_default.py +111 -0
- mantisdk/algorithm/gepa/lib/examples/anymaths-bench/prompt-templates/instruction_prompt.txt +9 -0
- mantisdk/algorithm/gepa/lib/examples/anymaths-bench/prompt-templates/optimal_prompt.txt +24 -0
- mantisdk/algorithm/gepa/lib/examples/anymaths-bench/train_anymaths.py +177 -0
- mantisdk/algorithm/gepa/lib/examples/dspy_full_program_evolution/arc_agi.ipynb +25705 -0
- mantisdk/algorithm/gepa/lib/examples/dspy_full_program_evolution/example.ipynb +348 -0
- mantisdk/algorithm/gepa/lib/examples/mcp_adapter/__init__.py +4 -0
- mantisdk/algorithm/gepa/lib/examples/mcp_adapter/mcp_optimization_example.py +455 -0
- mantisdk/algorithm/gepa/lib/examples/rag_adapter/RAG_GUIDE.md +613 -0
- mantisdk/algorithm/gepa/lib/examples/rag_adapter/__init__.py +9 -0
- mantisdk/algorithm/gepa/lib/examples/rag_adapter/rag_optimization.py +824 -0
- mantisdk/algorithm/gepa/lib/examples/rag_adapter/requirements-rag.txt +29 -0
- mantisdk/algorithm/gepa/lib/examples/terminal-bench/prompt-templates/instruction_prompt.txt +16 -0
- mantisdk/algorithm/gepa/lib/examples/terminal-bench/prompt-templates/terminus.txt +9 -0
- mantisdk/algorithm/gepa/lib/examples/terminal-bench/train_terminus.py +161 -0
- mantisdk/algorithm/gepa/lib/gepa_utils.py +117 -0
- mantisdk/algorithm/gepa/lib/logging/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/logging/experiment_tracker.py +187 -0
- mantisdk/algorithm/gepa/lib/logging/logger.py +75 -0
- mantisdk/algorithm/gepa/lib/logging/utils.py +103 -0
- mantisdk/algorithm/gepa/lib/proposer/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/proposer/base.py +31 -0
- mantisdk/algorithm/gepa/lib/proposer/merge.py +357 -0
- mantisdk/algorithm/gepa/lib/proposer/reflective_mutation/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/proposer/reflective_mutation/base.py +49 -0
- mantisdk/algorithm/gepa/lib/proposer/reflective_mutation/reflective_mutation.py +176 -0
- mantisdk/algorithm/gepa/lib/py.typed +0 -0
- mantisdk/algorithm/gepa/lib/strategies/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/strategies/batch_sampler.py +77 -0
- mantisdk/algorithm/gepa/lib/strategies/candidate_selector.py +50 -0
- mantisdk/algorithm/gepa/lib/strategies/component_selector.py +36 -0
- mantisdk/algorithm/gepa/lib/strategies/eval_policy.py +64 -0
- mantisdk/algorithm/gepa/lib/strategies/instruction_proposal.py +127 -0
- mantisdk/algorithm/gepa/lib/utils/__init__.py +10 -0
- mantisdk/algorithm/gepa/lib/utils/stop_condition.py +196 -0
- mantisdk/algorithm/gepa/tracing.py +105 -0
- mantisdk/algorithm/utils.py +177 -0
- mantisdk/algorithm/verl/__init__.py +5 -0
- mantisdk/algorithm/verl/interface.py +202 -0
- mantisdk/cli/__init__.py +56 -0
- mantisdk/cli/prometheus.py +115 -0
- mantisdk/cli/store.py +131 -0
- mantisdk/cli/vllm.py +29 -0
- mantisdk/client.py +408 -0
- mantisdk/config.py +348 -0
- mantisdk/emitter/__init__.py +43 -0
- mantisdk/emitter/annotation.py +370 -0
- mantisdk/emitter/exception.py +54 -0
- mantisdk/emitter/message.py +61 -0
- mantisdk/emitter/object.py +117 -0
- mantisdk/emitter/reward.py +320 -0
- mantisdk/env_var.py +156 -0
- mantisdk/execution/__init__.py +15 -0
- mantisdk/execution/base.py +64 -0
- mantisdk/execution/client_server.py +443 -0
- mantisdk/execution/events.py +69 -0
- mantisdk/execution/inter_process.py +16 -0
- mantisdk/execution/shared_memory.py +282 -0
- mantisdk/instrumentation/__init__.py +119 -0
- mantisdk/instrumentation/agentops.py +314 -0
- mantisdk/instrumentation/agentops_langchain.py +45 -0
- mantisdk/instrumentation/litellm.py +83 -0
- mantisdk/instrumentation/vllm.py +81 -0
- mantisdk/instrumentation/weave.py +500 -0
- mantisdk/litagent/__init__.py +11 -0
- mantisdk/litagent/decorator.py +536 -0
- mantisdk/litagent/litagent.py +252 -0
- mantisdk/llm_proxy.py +1890 -0
- mantisdk/logging.py +370 -0
- mantisdk/reward.py +7 -0
- mantisdk/runner/__init__.py +11 -0
- mantisdk/runner/agent.py +845 -0
- mantisdk/runner/base.py +182 -0
- mantisdk/runner/legacy.py +309 -0
- mantisdk/semconv.py +170 -0
- mantisdk/server.py +401 -0
- mantisdk/store/__init__.py +23 -0
- mantisdk/store/base.py +897 -0
- mantisdk/store/client_server.py +2092 -0
- mantisdk/store/collection/__init__.py +30 -0
- mantisdk/store/collection/base.py +587 -0
- mantisdk/store/collection/memory.py +970 -0
- mantisdk/store/collection/mongo.py +1412 -0
- mantisdk/store/collection_based.py +1823 -0
- mantisdk/store/insight.py +648 -0
- mantisdk/store/listener.py +58 -0
- mantisdk/store/memory.py +396 -0
- mantisdk/store/mongo.py +165 -0
- mantisdk/store/sqlite.py +3 -0
- mantisdk/store/threading.py +357 -0
- mantisdk/store/utils.py +142 -0
- mantisdk/tracer/__init__.py +16 -0
- mantisdk/tracer/agentops.py +242 -0
- mantisdk/tracer/base.py +287 -0
- mantisdk/tracer/dummy.py +106 -0
- mantisdk/tracer/otel.py +555 -0
- mantisdk/tracer/weave.py +677 -0
- mantisdk/trainer/__init__.py +6 -0
- mantisdk/trainer/init_utils.py +263 -0
- mantisdk/trainer/legacy.py +367 -0
- mantisdk/trainer/registry.py +12 -0
- mantisdk/trainer/trainer.py +618 -0
- mantisdk/types/__init__.py +6 -0
- mantisdk/types/core.py +553 -0
- mantisdk/types/resources.py +204 -0
- mantisdk/types/tracer.py +515 -0
- mantisdk/types/tracing.py +218 -0
- mantisdk/utils/__init__.py +1 -0
- mantisdk/utils/id.py +18 -0
- mantisdk/utils/metrics.py +1025 -0
- mantisdk/utils/otel.py +578 -0
- mantisdk/utils/otlp.py +536 -0
- mantisdk/utils/server_launcher.py +1045 -0
- mantisdk/utils/system_snapshot.py +81 -0
- mantisdk/verl/__init__.py +8 -0
- mantisdk/verl/__main__.py +6 -0
- mantisdk/verl/async_server.py +46 -0
- mantisdk/verl/config.yaml +27 -0
- mantisdk/verl/daemon.py +1154 -0
- mantisdk/verl/dataset.py +44 -0
- mantisdk/verl/entrypoint.py +248 -0
- mantisdk/verl/trainer.py +549 -0
- mantisdk-0.1.0.dist-info/METADATA +119 -0
- mantisdk-0.1.0.dist-info/RECORD +190 -0
- mantisdk-0.1.0.dist-info/WHEEL +4 -0
- mantisdk-0.1.0.dist-info/entry_points.txt +2 -0
- mantisdk-0.1.0.dist-info/licenses/LICENSE +19 -0
mantisdk/config.py
ADDED
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
# Copyright (c) Microsoft. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
This file is not carefully reviewed.
|
|
5
|
+
It might contain unintentional bugs and issues.
|
|
6
|
+
Please always review the parsed construction arguments before using them.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import argparse
|
|
12
|
+
import inspect
|
|
13
|
+
import logging
|
|
14
|
+
from typing import _GenericAlias # type: ignore
|
|
15
|
+
from typing import (
|
|
16
|
+
Any,
|
|
17
|
+
Callable,
|
|
18
|
+
Dict,
|
|
19
|
+
List,
|
|
20
|
+
Tuple,
|
|
21
|
+
Type,
|
|
22
|
+
TypeVar,
|
|
23
|
+
Union,
|
|
24
|
+
get_args,
|
|
25
|
+
get_origin,
|
|
26
|
+
get_type_hints,
|
|
27
|
+
overload,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
CliConfigurable = Any
|
|
31
|
+
|
|
32
|
+
logger = logging.getLogger(__name__)
|
|
33
|
+
|
|
34
|
+
__all__ = ["lightning_cli"]
|
|
35
|
+
|
|
36
|
+
# TypeVars for precise return type hinting with overloads
|
|
37
|
+
_C = TypeVar("_C", bound=CliConfigurable)
|
|
38
|
+
_C1 = TypeVar("_C1", bound=CliConfigurable)
|
|
39
|
+
_C2 = TypeVar("_C2", bound=CliConfigurable)
|
|
40
|
+
_C3 = TypeVar("_C3", bound=CliConfigurable)
|
|
41
|
+
_C4 = TypeVar("_C4", bound=CliConfigurable)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
# Custom type for CLI arguments that can be string or None
|
|
45
|
+
def nullable_str(value: str) -> str | None:
|
|
46
|
+
"""Converts specific string values (case-insensitive) to None, otherwise returns the string."""
|
|
47
|
+
if value.lower() in ["none", "null", "~", "nil"]: # Define keywords for None
|
|
48
|
+
return None
|
|
49
|
+
return value
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def nullable_int(value: str) -> int | None:
|
|
53
|
+
"""Converts specific string values (case-insensitive) to None, otherwise returns the integer."""
|
|
54
|
+
if value.lower() in ["none", "null", "~", "nil"]: # Define keywords for None
|
|
55
|
+
return None
|
|
56
|
+
try:
|
|
57
|
+
return int(value)
|
|
58
|
+
except ValueError:
|
|
59
|
+
raise argparse.ArgumentTypeError(f"Invalid integer value: '{value}'")
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def nullable_float(value: str) -> float | None:
|
|
63
|
+
"""Converts specific string values (case-insensitive) to None, otherwise returns the float."""
|
|
64
|
+
if value.lower() in ["none", "null", "~", "nil"]: # Define keywords for None
|
|
65
|
+
return None
|
|
66
|
+
try:
|
|
67
|
+
return float(value)
|
|
68
|
+
except ValueError:
|
|
69
|
+
raise argparse.ArgumentTypeError(f"Invalid float value: '{value}'")
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _str_to_bool(v: str) -> bool:
|
|
73
|
+
"""Converts common string representations of bool to Python bool (case-insensitive)."""
|
|
74
|
+
if isinstance(v, bool): # type: ignore
|
|
75
|
+
return v # Allow passing bools directly if used programmatically
|
|
76
|
+
lowered_v = v.lower()
|
|
77
|
+
if lowered_v in ("yes", "true", "t", "y", "1"):
|
|
78
|
+
return True
|
|
79
|
+
elif lowered_v in ("no", "false", "f", "n", "0"):
|
|
80
|
+
return False
|
|
81
|
+
else:
|
|
82
|
+
raise argparse.ArgumentTypeError(f"Boolean value expected (e.g., 'true', 'false', 'yes', 'no'), got '{v}'")
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _get_param_type_details(param_annotation: Any) -> Tuple[Any, bool, bool]:
|
|
86
|
+
"""Normalize an annotation into its core type, optionality, and list status.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
param_annotation: The annotation to inspect.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
A tuple ``(core_type, is_optional, is_list)`` describing the normalized type.
|
|
93
|
+
|
|
94
|
+
- For ``Optional[T]`` → ``(T, True, is_list_status_of_T)``
|
|
95
|
+
- For ``List[T]`` → ``(List[T], is_optional_status_of_List, True)``
|
|
96
|
+
- For ``Optional[List[T]]`` → ``(List[T], True, True)``
|
|
97
|
+
"""
|
|
98
|
+
is_optional = False
|
|
99
|
+
is_list = False
|
|
100
|
+
current_type = param_annotation
|
|
101
|
+
|
|
102
|
+
# Check for outer Optional
|
|
103
|
+
origin = get_origin(current_type)
|
|
104
|
+
if origin is Union:
|
|
105
|
+
union_args = get_args(current_type)
|
|
106
|
+
if len(union_args) == 2 and type(None) in union_args:
|
|
107
|
+
is_optional = True
|
|
108
|
+
current_type = next(arg for arg in union_args if arg is not type(None)) # Unwrap Optional
|
|
109
|
+
|
|
110
|
+
# Check if the (potentially unwrapped) type is a List
|
|
111
|
+
origin = get_origin(current_type) # Re-check origin after potential unwrap
|
|
112
|
+
if origin is list or (isinstance(current_type, _GenericAlias) and current_type.__origin__ is list):
|
|
113
|
+
is_list = True
|
|
114
|
+
|
|
115
|
+
return current_type, is_optional, is_list
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _determine_argparse_type(param_type: Any) -> Callable[[str], Any]:
|
|
119
|
+
"""Determines the type for argparse based on parameter type details."""
|
|
120
|
+
core_type, is_optional, _ = _get_param_type_details(param_type)
|
|
121
|
+
if core_type is str and is_optional:
|
|
122
|
+
return nullable_str # Special handling for Optional[str]
|
|
123
|
+
elif core_type is int and is_optional:
|
|
124
|
+
return nullable_int
|
|
125
|
+
elif core_type is float and is_optional:
|
|
126
|
+
return nullable_float
|
|
127
|
+
elif core_type is bool:
|
|
128
|
+
return _str_to_bool # Special handling for bool
|
|
129
|
+
elif core_type in (int, float, str):
|
|
130
|
+
return core_type
|
|
131
|
+
return str # Default to str if no specific type is provided (including empty)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _determine_argparse_type_and_nargs(
|
|
135
|
+
core_param_type: Any, is_param_list: bool # The type after unwrapping an outer Optional
|
|
136
|
+
) -> Dict[str, Any]:
|
|
137
|
+
"""Determines the 'type' and 'nargs' for argparse based on parameter type details."""
|
|
138
|
+
kwargs: Dict[str, Any] = {}
|
|
139
|
+
|
|
140
|
+
if is_param_list:
|
|
141
|
+
kwargs["nargs"] = "*" # Allows zero or more arguments for lists
|
|
142
|
+
list_item_annotations = get_args(core_param_type) # For List[T], core_param_type is List[T]
|
|
143
|
+
|
|
144
|
+
if list_item_annotations and list_item_annotations[0] is not Any:
|
|
145
|
+
item_ann = list_item_annotations[0]
|
|
146
|
+
# Check if the list item itself is, e.g., Optional[str] or bool
|
|
147
|
+
kwargs["type"] = _determine_argparse_type(item_ann)
|
|
148
|
+
else:
|
|
149
|
+
kwargs["type"] = str
|
|
150
|
+
else: # Not a list
|
|
151
|
+
kwargs["type"] = _determine_argparse_type(core_param_type)
|
|
152
|
+
return kwargs
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def _build_help_string(cls_name: str, param_name: str, core_type: Any, is_optional: bool, is_list: bool) -> str:
|
|
156
|
+
"""Constructs a descriptive help string for a CLI argument."""
|
|
157
|
+
type_display_name = "Any"
|
|
158
|
+
if core_type is not inspect.Parameter.empty:
|
|
159
|
+
type_display_name = getattr(core_type, "__name__", str(core_type))
|
|
160
|
+
|
|
161
|
+
if is_list:
|
|
162
|
+
list_item_args = get_args(core_type) # core_type is List[T] here
|
|
163
|
+
item_name = "Any"
|
|
164
|
+
if list_item_args and list_item_args[0] is not Any:
|
|
165
|
+
inner_item_core_type, inner_item_optional, _ = _get_param_type_details(list_item_args[0])
|
|
166
|
+
item_name = getattr(inner_item_core_type, "__name__", str(inner_item_core_type))
|
|
167
|
+
if inner_item_optional: # e.g. List[Optional[str]]
|
|
168
|
+
item_name = f"Optional[{item_name}]"
|
|
169
|
+
type_display_name = f"List[{item_name}]"
|
|
170
|
+
|
|
171
|
+
full_type_display = f"Optional[{type_display_name}]" if is_optional and not is_list else type_display_name
|
|
172
|
+
if is_optional and is_list: # e.g. Optional[List[str]]
|
|
173
|
+
full_type_display = f"Optional[{type_display_name}]"
|
|
174
|
+
|
|
175
|
+
help_str = f"For {cls_name}: '{param_name}'. Inferred type: {full_type_display}."
|
|
176
|
+
return help_str
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def _add_argument_for_parameter(
|
|
180
|
+
parser: argparse.ArgumentParser,
|
|
181
|
+
cls: Type[CliConfigurable],
|
|
182
|
+
param_name: str,
|
|
183
|
+
param_obj: inspect.Parameter,
|
|
184
|
+
dest_name: str,
|
|
185
|
+
resolved_param_annotation: Any = None,
|
|
186
|
+
) -> None:
|
|
187
|
+
"""Configures and adds a single CLI argument for an __init__ parameter."""
|
|
188
|
+
if resolved_param_annotation is None:
|
|
189
|
+
param_type_annotation = param_obj.annotation
|
|
190
|
+
else:
|
|
191
|
+
param_type_annotation = resolved_param_annotation
|
|
192
|
+
|
|
193
|
+
# core_type is the main type (e.g., int, str, List[str]), after unwrapping the outermost Optional.
|
|
194
|
+
# is_overall_optional indicates if the parameter itself can be None (e.g. param: Optional[T] = None)
|
|
195
|
+
# is_list indicates if core_type is a List.
|
|
196
|
+
core_type, is_overall_optional, is_list = _get_param_type_details(param_type_annotation)
|
|
197
|
+
|
|
198
|
+
has_init_default = param_obj.default is not inspect.Parameter.empty
|
|
199
|
+
init_default_value = param_obj.default if has_init_default else None
|
|
200
|
+
|
|
201
|
+
argparse_kwargs = _determine_argparse_type_and_nargs(core_type if is_list else param_type_annotation, is_list)
|
|
202
|
+
|
|
203
|
+
if has_init_default:
|
|
204
|
+
argparse_kwargs["default"] = init_default_value
|
|
205
|
+
elif is_overall_optional: # Parameter is Optional (e.g. Optional[int]) and no explicit default in __init__
|
|
206
|
+
argparse_kwargs["default"] = None # So, if not provided on CLI, it becomes None.
|
|
207
|
+
|
|
208
|
+
argparse_kwargs["help"] = _build_help_string(cls.__name__, param_name, core_type, is_overall_optional, is_list)
|
|
209
|
+
|
|
210
|
+
if not has_init_default and not is_overall_optional: # Required if no __init__ default AND not Optional
|
|
211
|
+
argparse_kwargs["required"] = True
|
|
212
|
+
if "default" in argparse_kwargs: # Should not happen if logic is correct
|
|
213
|
+
del argparse_kwargs["default"]
|
|
214
|
+
|
|
215
|
+
cli_arg_name = f"--{cls.__name__.lower()}.{param_name.replace('_', '-')}"
|
|
216
|
+
parser.add_argument(cli_arg_name, dest=dest_name, **argparse_kwargs)
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def _add_arguments_for_class(
|
|
220
|
+
parser: argparse.ArgumentParser,
|
|
221
|
+
cls: Type[CliConfigurable],
|
|
222
|
+
class_arg_configs_maps: Dict[Type[CliConfigurable], Dict[str, str]], # Maps cls to {param_name: dest_name}
|
|
223
|
+
) -> None:
|
|
224
|
+
"""Adds all relevant CLI arguments for a given class by processing its __init__ parameters."""
|
|
225
|
+
cls_name_lower = cls.__name__.lower()
|
|
226
|
+
sig = inspect.signature(cls.__init__)
|
|
227
|
+
|
|
228
|
+
try:
|
|
229
|
+
# Resolve string annotations to actual types using get_type_hints.
|
|
230
|
+
# For methods, get_type_hints automatically uses obj.__globals__ for globalns.
|
|
231
|
+
resolved_hints = get_type_hints(cls.__init__)
|
|
232
|
+
except Exception as e:
|
|
233
|
+
logger.warning(
|
|
234
|
+
f"Could not resolve type hints for {cls.__name__}.__init__ using get_type_hints: {e}. "
|
|
235
|
+
f"CLI argument parsing for this class might be based on string annotations, "
|
|
236
|
+
"which could be unreliable for complex types."
|
|
237
|
+
)
|
|
238
|
+
resolved_hints = {} # Fallback to an empty dict if resolution fails
|
|
239
|
+
|
|
240
|
+
if cls not in class_arg_configs_maps: # Ensure the class entry exists
|
|
241
|
+
class_arg_configs_maps[cls] = {}
|
|
242
|
+
|
|
243
|
+
for param_name, param_obj in sig.parameters.items():
|
|
244
|
+
if param_name == "self": # Skip 'self'
|
|
245
|
+
continue
|
|
246
|
+
|
|
247
|
+
dest_name = f"{cls_name_lower}_{param_name}" # Unique destination for argparse
|
|
248
|
+
class_arg_configs_maps[cls][param_name] = dest_name # Store mapping for later instantiation
|
|
249
|
+
|
|
250
|
+
# Use the resolved hint if available, otherwise fallback to param_obj.annotation (which might be a string)
|
|
251
|
+
actual_param_annotation = resolved_hints.get(param_name, param_obj.annotation)
|
|
252
|
+
_add_argument_for_parameter(parser, cls, param_name, param_obj, dest_name, actual_param_annotation)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def _create_argument_parser() -> argparse.ArgumentParser:
|
|
256
|
+
"""Creates and returns the main ArgumentParser with default settings."""
|
|
257
|
+
return argparse.ArgumentParser(
|
|
258
|
+
description="CLI configurator for application components.",
|
|
259
|
+
formatter_class=argparse.ArgumentDefaultsHelpFormatter, # Automatically shows default values in help
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def _instantiate_classes(
|
|
264
|
+
parsed_args: argparse.Namespace,
|
|
265
|
+
classes: Tuple[Type[CliConfigurable], ...],
|
|
266
|
+
class_arg_configs_maps: Dict[Type[CliConfigurable], Dict[str, str]],
|
|
267
|
+
) -> Tuple[CliConfigurable, ...]:
|
|
268
|
+
"""Instantiates classes using the parsed CLI arguments and the stored mappings."""
|
|
269
|
+
instances_list: List[CliConfigurable] = []
|
|
270
|
+
for cls in classes:
|
|
271
|
+
constructor_args: Dict[str, Any] = {}
|
|
272
|
+
# Get the {__init__ param_name: argparse_dest_name} map for the current class
|
|
273
|
+
param_to_dest_map = class_arg_configs_maps.get(cls, {})
|
|
274
|
+
|
|
275
|
+
sig = inspect.signature(cls.__init__)
|
|
276
|
+
for param_name_in_sig, _ in sig.parameters.items():
|
|
277
|
+
if param_name_in_sig == "self":
|
|
278
|
+
continue
|
|
279
|
+
|
|
280
|
+
dest_name_for_arg = param_to_dest_map.get(param_name_in_sig)
|
|
281
|
+
if dest_name_for_arg and hasattr(parsed_args, dest_name_for_arg):
|
|
282
|
+
value = getattr(parsed_args, dest_name_for_arg)
|
|
283
|
+
constructor_args[param_name_in_sig] = value
|
|
284
|
+
# If an argument was required by argparse, parse_args() would have exited if missing.
|
|
285
|
+
# If not required and not provided, its default value (set by argparse) is used.
|
|
286
|
+
|
|
287
|
+
try:
|
|
288
|
+
logger.info("Instantiating %s with args: %s", cls.__name__, constructor_args)
|
|
289
|
+
instances_list.append(cls(**constructor_args))
|
|
290
|
+
except Exception as e:
|
|
291
|
+
parsed_args_for_cls = {
|
|
292
|
+
k: getattr(parsed_args, v) for k, v in param_to_dest_map.items() if hasattr(parsed_args, v)
|
|
293
|
+
}
|
|
294
|
+
logger.error(
|
|
295
|
+
f"Error instantiating {cls.__name__} with resolved args {constructor_args}. "
|
|
296
|
+
f"Parsed args for class: "
|
|
297
|
+
f"{parsed_args_for_cls}. "
|
|
298
|
+
f"Error: {e}"
|
|
299
|
+
)
|
|
300
|
+
raise
|
|
301
|
+
|
|
302
|
+
return tuple(instances_list)
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
@overload
|
|
306
|
+
def lightning_cli(cls1: Type[_C1]) -> _C1: ...
|
|
307
|
+
@overload
|
|
308
|
+
def lightning_cli(cls1: Type[_C1], cls2: Type[_C2]) -> Tuple[_C1, _C2]: ...
|
|
309
|
+
@overload
|
|
310
|
+
def lightning_cli(cls1: Type[_C1], cls2: Type[_C2], cls3: Type[_C3]) -> Tuple[_C1, _C2, _C3]: ...
|
|
311
|
+
@overload
|
|
312
|
+
def lightning_cli(cls1: Type[_C1], cls2: Type[_C2], cls3: Type[_C3], cls4: Type[_C4]) -> Tuple[_C1, _C2, _C3, _C4]: ...
|
|
313
|
+
@overload # Fallback for more than 4 or a dynamic number of classes
|
|
314
|
+
def lightning_cli(*classes: Type[CliConfigurable]) -> Tuple[CliConfigurable, ...]: ...
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
# FIXME: lightning_cli needs to be fixed to comply with the latest trainer implementation.
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def lightning_cli(*classes: Type[CliConfigurable]) -> CliConfigurable | Tuple[CliConfigurable, ...]: # type: ignore
|
|
321
|
+
"""
|
|
322
|
+
Parses command-line arguments to configure and instantiate provided CliConfigurable classes.
|
|
323
|
+
|
|
324
|
+
Args:
|
|
325
|
+
*classes: One or more classes that inherit from CliConfigurable. Each class's
|
|
326
|
+
__init__ parameters will be exposed as command-line arguments.
|
|
327
|
+
|
|
328
|
+
Returns:
|
|
329
|
+
A tuple of instantiated objects, corresponding to the input classes in order.
|
|
330
|
+
"""
|
|
331
|
+
if not classes:
|
|
332
|
+
return tuple() # Return an empty tuple if no classes are provided
|
|
333
|
+
|
|
334
|
+
parser = _create_argument_parser()
|
|
335
|
+
|
|
336
|
+
# This map will store {cls: {init_param_name: argparse_dest_name}}
|
|
337
|
+
class_arg_configs_maps: Dict[Type[CliConfigurable], Dict[str, str]] = {}
|
|
338
|
+
|
|
339
|
+
for cls in classes:
|
|
340
|
+
_add_arguments_for_class(parser, cls, class_arg_configs_maps)
|
|
341
|
+
|
|
342
|
+
parsed_args = parser.parse_args() # Uses sys.argv[1:] by default
|
|
343
|
+
|
|
344
|
+
# Correctly handle single class case for return type matching overloads
|
|
345
|
+
instances = _instantiate_classes(parsed_args, classes, class_arg_configs_maps)
|
|
346
|
+
if len(classes) == 1:
|
|
347
|
+
return instances[0]
|
|
348
|
+
return instances
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Copyright (c) Microsoft. All rights reserved.
|
|
2
|
+
|
|
3
|
+
"""Convenient helpers for creating spans / traces.
|
|
4
|
+
|
|
5
|
+
All emitters operate in two modes, switchable via the `propagate` parameter.
|
|
6
|
+
The emitters first [`SpanCreationRequest`][mantisdk.SpanCreationRequest] object, then:
|
|
7
|
+
|
|
8
|
+
1. When `propagate` is True, this creation request will be propagated to the active tracer
|
|
9
|
+
and a [`Span`][mantisdk.Span] instance will be created (possibly deferred).
|
|
10
|
+
2. When `propagate` is False, the creation request will be returned directly. Useful for cases
|
|
11
|
+
when you don't have a tracer but you want to create a creation request for later use.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from .annotation import emit_annotation, operation
|
|
15
|
+
from .exception import emit_exception
|
|
16
|
+
from .message import emit_message, get_message_value
|
|
17
|
+
from .object import emit_object, get_object_value
|
|
18
|
+
from .reward import (
|
|
19
|
+
emit_reward,
|
|
20
|
+
find_final_reward,
|
|
21
|
+
find_reward_spans,
|
|
22
|
+
get_reward_value,
|
|
23
|
+
get_rewards_from_span,
|
|
24
|
+
is_reward_span,
|
|
25
|
+
reward,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
__all__ = [
|
|
29
|
+
"reward",
|
|
30
|
+
"operation",
|
|
31
|
+
"emit_reward",
|
|
32
|
+
"get_reward_value",
|
|
33
|
+
"get_rewards_from_span",
|
|
34
|
+
"is_reward_span",
|
|
35
|
+
"find_reward_spans",
|
|
36
|
+
"find_final_reward",
|
|
37
|
+
"emit_message",
|
|
38
|
+
"emit_object",
|
|
39
|
+
"emit_exception",
|
|
40
|
+
"emit_annotation",
|
|
41
|
+
"get_message_value",
|
|
42
|
+
"get_object_value",
|
|
43
|
+
]
|