gllm-core-binary 0.4.4__py3-none-macosx_13_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. gllm_core/__init__.py +1 -0
  2. gllm_core/__init__.pyi +0 -0
  3. gllm_core/adapters/__init__.py +5 -0
  4. gllm_core/adapters/__init__.pyi +3 -0
  5. gllm_core/adapters/tool/__init__.py +6 -0
  6. gllm_core/adapters/tool/__init__.pyi +4 -0
  7. gllm_core/adapters/tool/google_adk.py +91 -0
  8. gllm_core/adapters/tool/google_adk.pyi +23 -0
  9. gllm_core/adapters/tool/langchain.py +130 -0
  10. gllm_core/adapters/tool/langchain.pyi +31 -0
  11. gllm_core/constants.py +55 -0
  12. gllm_core/constants.pyi +36 -0
  13. gllm_core/event/__init__.py +6 -0
  14. gllm_core/event/__init__.pyi +4 -0
  15. gllm_core/event/event_emitter.py +211 -0
  16. gllm_core/event/event_emitter.pyi +155 -0
  17. gllm_core/event/handler/__init__.py +7 -0
  18. gllm_core/event/handler/__init__.pyi +5 -0
  19. gllm_core/event/handler/console_event_handler.py +48 -0
  20. gllm_core/event/handler/console_event_handler.pyi +32 -0
  21. gllm_core/event/handler/event_handler.py +89 -0
  22. gllm_core/event/handler/event_handler.pyi +51 -0
  23. gllm_core/event/handler/print_event_handler.py +130 -0
  24. gllm_core/event/handler/print_event_handler.pyi +33 -0
  25. gllm_core/event/handler/stream_event_handler.py +85 -0
  26. gllm_core/event/handler/stream_event_handler.pyi +62 -0
  27. gllm_core/event/hook/__init__.py +5 -0
  28. gllm_core/event/hook/__init__.pyi +3 -0
  29. gllm_core/event/hook/event_hook.py +30 -0
  30. gllm_core/event/hook/event_hook.pyi +18 -0
  31. gllm_core/event/hook/json_stringify_event_hook.py +32 -0
  32. gllm_core/event/hook/json_stringify_event_hook.pyi +16 -0
  33. gllm_core/event/messenger.py +133 -0
  34. gllm_core/event/messenger.pyi +66 -0
  35. gllm_core/schema/__init__.py +8 -0
  36. gllm_core/schema/__init__.pyi +6 -0
  37. gllm_core/schema/chunk.py +148 -0
  38. gllm_core/schema/chunk.pyi +66 -0
  39. gllm_core/schema/component.py +546 -0
  40. gllm_core/schema/component.pyi +205 -0
  41. gllm_core/schema/event.py +50 -0
  42. gllm_core/schema/event.pyi +33 -0
  43. gllm_core/schema/schema_generator.py +150 -0
  44. gllm_core/schema/schema_generator.pyi +35 -0
  45. gllm_core/schema/tool.py +418 -0
  46. gllm_core/schema/tool.pyi +198 -0
  47. gllm_core/utils/__init__.py +32 -0
  48. gllm_core/utils/__init__.pyi +13 -0
  49. gllm_core/utils/analyzer.py +256 -0
  50. gllm_core/utils/analyzer.pyi +123 -0
  51. gllm_core/utils/binary_handler_factory.py +99 -0
  52. gllm_core/utils/binary_handler_factory.pyi +62 -0
  53. gllm_core/utils/chunk_metadata_merger.py +102 -0
  54. gllm_core/utils/chunk_metadata_merger.pyi +41 -0
  55. gllm_core/utils/concurrency.py +184 -0
  56. gllm_core/utils/concurrency.pyi +94 -0
  57. gllm_core/utils/event_formatter.py +69 -0
  58. gllm_core/utils/event_formatter.pyi +30 -0
  59. gllm_core/utils/google_sheets.py +115 -0
  60. gllm_core/utils/google_sheets.pyi +18 -0
  61. gllm_core/utils/imports.py +91 -0
  62. gllm_core/utils/imports.pyi +42 -0
  63. gllm_core/utils/logger_manager.py +339 -0
  64. gllm_core/utils/logger_manager.pyi +176 -0
  65. gllm_core/utils/main_method_resolver.py +185 -0
  66. gllm_core/utils/main_method_resolver.pyi +54 -0
  67. gllm_core/utils/merger_method.py +130 -0
  68. gllm_core/utils/merger_method.pyi +49 -0
  69. gllm_core/utils/retry.py +258 -0
  70. gllm_core/utils/retry.pyi +41 -0
  71. gllm_core/utils/similarity.py +29 -0
  72. gllm_core/utils/similarity.pyi +10 -0
  73. gllm_core/utils/validation.py +26 -0
  74. gllm_core/utils/validation.pyi +12 -0
  75. gllm_core_binary-0.4.4.dist-info/METADATA +177 -0
  76. gllm_core_binary-0.4.4.dist-info/RECORD +78 -0
  77. gllm_core_binary-0.4.4.dist-info/WHEEL +5 -0
  78. gllm_core_binary-0.4.4.dist-info/top_level.txt +1 -0
@@ -0,0 +1,205 @@
1
+ from gllm_core.event.event_emitter import EventEmitter as EventEmitter
2
+ from gllm_core.schema.schema_generator import generate_params_model as generate_params_model
3
+ from gllm_core.schema.tool import Tool as Tool, tool as tool
4
+ from gllm_core.utils import BinaryHandlingStrategy as BinaryHandlingStrategy, binary_handler_factory as binary_handler_factory
5
+ from gllm_core.utils.analyzer import MethodSignature as MethodSignature, ParameterInfo as ParameterInfo, ParameterKind as ParameterKind, RunProfile as RunProfile, analyze_method as analyze_method
6
+ from gllm_core.utils.logger_manager import LoggerManager as LoggerManager
7
+ from gllm_core.utils.main_method_resolver import MainMethodResolver as MainMethodResolver
8
+ from pydantic import BaseModel as BaseModel
9
+ from typing import Any, Callable
10
+
11
+ def main(method: Callable) -> Callable:
12
+ """Decorate a Component method as the async main entrypoint.
13
+
14
+ Usage:
15
+ Declare the coroutine that should act as the primary execution path
16
+ for a `Component` subclass. The decorated coroutine will be resolved by
17
+ `Component.run()` unless another subclass overrides the decoration.
18
+
19
+ Args:
20
+ method (Callable): Coroutine to mark as the main entrypoint.
21
+
22
+ Returns:
23
+ Callable: The same coroutine that is passed to the decorator. The decorator only marks the method as the main
24
+ entrypoint. It does not wrap or change its behavior or signature.
25
+
26
+ Raises:
27
+ TypeError: If the decorated callable is not asynchronous.
28
+ """
29
+
30
+ class Component:
31
+ '''An abstract base class for all components used throughout the Gen AI applications.
32
+
33
+ Every instance of Component has access to class-level `_default_log_level` and `_logger`, as detailed below.
34
+ For components that require high observability, it is recommended to set `_default_log_level` to `logging.INFO`
35
+ or higher.
36
+
37
+ Defining Custom Components:
38
+ There are two ways to define the main execution logic for a component:
39
+
40
+ 1. **Using the @main decorator (Recommended)**:
41
+ Decorate an async method with `@main` to mark it as the primary entrypoint.
42
+ This is the preferred approach as it provides explicit control over the main method.
43
+
44
+ ```python
45
+ class MyComponent(Component):
46
+ _default_log_level = logging.INFO
47
+
48
+ @main
49
+ async def execute(self, **kwargs: Any) -> Any:
50
+ return "Hello from @main!"
51
+ ```
52
+
53
+ 2. **Implementing _run method (Deprecated)**:
54
+ Override the abstract `_run` method. This is the traditional approach and still supported.
55
+
56
+ ```python
57
+ class MyComponent(Component):
58
+ _default_log_level = logging.INFO
59
+
60
+ async def _run(self, **kwargs: Any) -> Any:
61
+ return "Hello, World!"
62
+ ```
63
+
64
+ The `run()` method resolves the main entrypoint using the following precedence:
65
+ 1. Method decorated with @main in the current class.
66
+ 2. Method decorated with @main in the nearest ancestor class.
67
+ 3. Method named in __main_method__ property.
68
+ 4. The _run method (with deprecation warning).
69
+
70
+ Attributes:
71
+ run_profile (RunProfile): The profile of the `_run` method.
72
+ This property is used by `Pipeline` to analyze the input requirements of the component.
73
+ In most cases, unless you are working with `Pipeline` and `PipelineStep`s, you will not need to use this
74
+ property.
75
+
76
+ **Do not override this property in your subclass.**
77
+
78
+ You also do not need to write this attribute in your component\'s docstring.
79
+ '''
80
+ def __init_subclass__(cls, **kwargs) -> None:
81
+ """Hook called when a subclass is created.
82
+
83
+ This validates the __main_method__ property and checks for multiple @main decorators
84
+ within the current class definition. Uses MainMethodResolver for consistent validation logic.
85
+
86
+ Note: Multiple inheritance conflicts are intentionally deferred to runtime (get_main())
87
+ to allow class definition to succeed.
88
+
89
+ Raises:
90
+ AttributeError: If __main_method__ refers to a non-existent method.
91
+ TypeError: If multiple methods are decorated with @main in the same class.
92
+ """
93
+ @classmethod
94
+ def get_main(cls) -> Callable | None:
95
+ """Return the resolved main coroutine for this Component class.
96
+
97
+ This method resolves the main method for the Component class following
98
+ the precedence rules:
99
+ 1. Most derived coroutine decorated with `@main`.
100
+ 2. Method named by `__main_method__`.
101
+ 3. `_run` coroutine as a deprecated fallback.
102
+
103
+ Results are cached for performance.
104
+
105
+ Returns:
106
+ Callable | None: The coroutine that will be executed by `run()` or
107
+ `None` when no entrypoint can be determined.
108
+
109
+ Raises:
110
+ TypeError: If conflicting main methods are inherited from multiple ancestors.
111
+ """
112
+ @property
113
+ def input_params(self) -> type[BaseModel] | None:
114
+ '''Return the Pydantic model describing this component\'s main method input parameters.
115
+
116
+ Returns:
117
+ type[BaseModel] | None: The cached model that mirrors the signature of
118
+ the resolved main method, or `None` if no main method can be
119
+ determined.
120
+
121
+ Examples:
122
+ ```python
123
+ from pydantic import ValidationError
124
+
125
+ component = SomeComponent()
126
+ ParamsModel = component.input_params
127
+ assert ParamsModel.__name__ == "SomeComponentParams"
128
+ fields = list(ParamsModel.model_fields)
129
+
130
+ # Validation with valid params
131
+ params = ParamsModel(text="hello")
132
+
133
+ # Validation catches missing required fields
134
+ try:
135
+ invalid_params = ParamsModel() # Missing required \'text\' field
136
+ except ValidationError as e:
137
+ print(f"Validation failed: {e.error_count()} errors")
138
+
139
+ # Argument construction
140
+ payload = params.model_dump()
141
+ result = await component.run(**payload)
142
+ ```
143
+ '''
144
+ async def run(self, **kwargs: Any) -> Any:
145
+ """Runs the operations defined for the component.
146
+
147
+ This method emits the provided input arguments using an EventEmitter instance if available, executes the
148
+ resolved main method, and emits the resulting output if the EventEmitter is provided.
149
+
150
+ The main method is resolved using the following precedence:
151
+ 1. Method decorated with @main in the current class.
152
+ 2. Method decorated with @main in the nearest ancestor class.
153
+ 3. Method named in __main_method__ property.
154
+ 4. The _run method (with deprecation warning).
155
+
156
+ Args:
157
+ **kwargs (Any): A dictionary of arguments to be processed. May include an `event_emitter`
158
+ key with an EventEmitter instance.
159
+
160
+ Returns:
161
+ Any: The result of the resolved main method.
162
+
163
+ Raises:
164
+ TypeError: If conflicting main methods are inherited from multiple ancestors.
165
+ AttributeError: If __main_method__ refers to a non-existent method.
166
+ """
167
+ def as_tool(self, name: str | None = None, description: str | None = None, title: str | None = None) -> Tool:
168
+ """Convert the component's main method into a `Tool` instance.
169
+
170
+ Example:
171
+ ```python
172
+ from gllm_core.schema import Component, main
173
+
174
+ class MyComponent(Component):
175
+ @main
176
+ async def my_method(self, param: str) -> str:
177
+ return param
178
+
179
+ component = MyComponent()
180
+ tool = component.as_tool()
181
+ ```
182
+
183
+ Args:
184
+ name (str | None, optional): Identifier for the resulting tool. Defaults to the component class name.
185
+ description (str | None, optional): Summary of the tool's behavior. Defaults to None, in which case the
186
+ main method's docstring is used.
187
+ title (str | None, optional): Optional display title for the tool. Defaults to None, in which case the
188
+ component's class name is used.
189
+
190
+ Returns:
191
+ Tool: The tool wrapping the component's main method.
192
+
193
+ Raises:
194
+ RuntimeError: If the component does not declare a main method using @main or __main_method__.
195
+ """
196
+ @property
197
+ def run_profile(self) -> RunProfile:
198
+ """Analyzes the `_run` method and retrieves its profile.
199
+
200
+ This property method analyzes the `_run` method of the class to generate a `RunProfile` object.
201
+ It also updates the method signatures for methods that fully utilize the arguments.
202
+
203
+ Returns:
204
+ RunProfile: The profile of the `_run` method, including method signatures for full-pass argument usages.
205
+ """
@@ -0,0 +1,50 @@
1
+ """Defines the Event schema, which represents an event emitted by the system.
2
+
3
+ Authors:
4
+ Dimitrij Ray (dimitrij.ray@gdplabs.id)
5
+ Henry Wicaksono (henry.wicaksono@gdplabs.id)
6
+
7
+ References:
8
+ NONE
9
+ """
10
+
11
+ from datetime import datetime
12
+ from typing import Any
13
+
14
+ from pydantic import BaseModel, Field, field_serializer
15
+
16
+ from gllm_core.constants import EventLevel, EventType
17
+
18
+
19
+ class Event(BaseModel):
20
+ """A data class to store an event attributes.
21
+
22
+ Attributes:
23
+ id (str): The ID of the event. Defaults to None.
24
+ value (str | dict[str, Any]): The value of the event. Defaults to an empty string.
25
+ level (EventLevel): The severity level of the event. Defaults to EventLevel.INFO.
26
+ type (str): The type of the event. Defaults to EventType.RESPONSE.
27
+ timestamp (datetime): The timestamp of the event. Defaults to the current timestamp.
28
+ metadata (dict[str, Any]): The metadata of the event. Defaults to an empty dictionary.
29
+ """
30
+
31
+ id: str | None = None
32
+ value: str | dict[str, Any] = ""
33
+ level: EventLevel = EventLevel.INFO
34
+ type: str = EventType.RESPONSE.value
35
+ timestamp: datetime = Field(default_factory=datetime.now)
36
+ metadata: dict[str, Any] = Field(default_factory=dict)
37
+
38
+ @field_serializer("level")
39
+ def serialize_level(self, level: EventLevel) -> str:
40
+ """Serializes an EventLevel object into its string representation.
41
+
42
+ This method serializes the given EventLevel object by returning its name as a string.
43
+
44
+ Args:
45
+ level (EventLevel): The EventLevel object to be serialized.
46
+
47
+ Returns:
48
+ str: The name of the EventLevel object.
49
+ """
50
+ return level.name
@@ -0,0 +1,33 @@
1
+ from datetime import datetime
2
+ from gllm_core.constants import EventLevel as EventLevel, EventType as EventType
3
+ from pydantic import BaseModel
4
+ from typing import Any
5
+
6
+ class Event(BaseModel):
7
+ """A data class to store an event attributes.
8
+
9
+ Attributes:
10
+ id (str): The ID of the event. Defaults to None.
11
+ value (str | dict[str, Any]): The value of the event. Defaults to an empty string.
12
+ level (EventLevel): The severity level of the event. Defaults to EventLevel.INFO.
13
+ type (str): The type of the event. Defaults to EventType.RESPONSE.
14
+ timestamp (datetime): The timestamp of the event. Defaults to the current timestamp.
15
+ metadata (dict[str, Any]): The metadata of the event. Defaults to an empty dictionary.
16
+ """
17
+ id: str | None
18
+ value: str | dict[str, Any]
19
+ level: EventLevel
20
+ type: str
21
+ timestamp: datetime
22
+ metadata: dict[str, Any]
23
+ def serialize_level(self, level: EventLevel) -> str:
24
+ """Serializes an EventLevel object into its string representation.
25
+
26
+ This method serializes the given EventLevel object by returning its name as a string.
27
+
28
+ Args:
29
+ level (EventLevel): The EventLevel object to be serialized.
30
+
31
+ Returns:
32
+ str: The name of the EventLevel object.
33
+ """
@@ -0,0 +1,150 @@
1
+ """Utility for generating Pydantic models from component methods.
2
+
3
+ Authors:
4
+ Dimitrij Ray (dimitrij.ray@gdplabs.id)
5
+
6
+ References:
7
+ NONE
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import inspect
13
+ from typing import Any, Callable, get_type_hints
14
+
15
+ from pydantic import BaseModel, ConfigDict, create_model
16
+
17
+ from gllm_core.utils.analyzer import analyze_method
18
+
19
+
20
+ def generate_params_model(method: Callable, class_name: str) -> type[BaseModel]:
21
+ """Generate a Pydantic model representing a component method signature.
22
+
23
+ The generated class is named `{class_name}Params` and contains one field for
24
+ every parameter in `method`. The first `self` parameter is ignored, `*args` are
25
+ skipped entirely, and `**kwargs` trigger `extra="allow"` to permit arbitrary
26
+ keyword arguments at runtime.
27
+
28
+ For legacy `_run` methods with only `**kwargs`, this function will use
29
+ RunAnalyzer to infer parameters from the method body usage patterns.
30
+
31
+ Args:
32
+ method (Callable): Method whose signature should be represented.
33
+ class_name (str): Component class name used to derive the generated model name.
34
+
35
+ Returns:
36
+ type[BaseModel]: A Pydantic `BaseModel` subclass describing the method's
37
+ parameters.
38
+
39
+ Example:
40
+ ```python
41
+ class_name = "TextProcessor"
42
+
43
+ def process(self, text: str, count: int = 5) -> str:
44
+ return text * count
45
+
46
+ Model = generate_params_model(process, class_name)
47
+ assert Model.__name__ == "TextProcessorParams"
48
+ assert Model(text="hello", count=2).model_dump() == {"text": "hello", "count": 2}
49
+ ```
50
+ """
51
+ signature = inspect.signature(method)
52
+
53
+ non_self_params = [param for param in signature.parameters.values() if param.name != "self"]
54
+
55
+ if len(non_self_params) == 1 and non_self_params[0].kind == inspect.Parameter.VAR_KEYWORD:
56
+ return _generate_from_analyzer(method, class_name)
57
+
58
+ return _generate_from_signature(method, class_name)
59
+
60
+
61
+ def _generate_from_signature(method: Callable, class_name: str) -> type[BaseModel]:
62
+ """Generate model using method signature analysis.
63
+
64
+ This function is used for modern methods with explicit parameter annotations.
65
+
66
+ Args:
67
+ method (Callable): Method whose signature should be represented.
68
+ class_name (str): Component class name used to derive the generated model name.
69
+
70
+ Returns:
71
+ type[BaseModel]: A Pydantic `BaseModel` subclass describing the method's
72
+ parameters.
73
+ """
74
+ signature = inspect.signature(method)
75
+
76
+ try:
77
+ type_hints = get_type_hints(method)
78
+ except Exception: # pragma: no cover - defensive fallback
79
+ type_hints = {}
80
+
81
+ fields: dict[str, tuple[type[Any], Any]] = {}
82
+ extra_setting = "forbid"
83
+
84
+ for param_name, param in signature.parameters.items():
85
+ if param_name == "self":
86
+ continue
87
+ if param.kind == inspect.Parameter.VAR_POSITIONAL:
88
+ continue
89
+ if param.kind == inspect.Parameter.VAR_KEYWORD:
90
+ extra_setting = "allow"
91
+ continue
92
+
93
+ annotation = type_hints.get(param_name, Any)
94
+ if param.default is inspect.Parameter.empty:
95
+ fields[param_name] = (annotation, ...)
96
+ else:
97
+ fields[param_name] = (annotation, param.default)
98
+
99
+ model_name = f"{class_name}Params"
100
+ return create_model( # type: ignore[call-overload]
101
+ model_name,
102
+ __config__=ConfigDict(extra=extra_setting, arbitrary_types_allowed=True),
103
+ **fields,
104
+ )
105
+
106
+
107
+ def _generate_from_analyzer(method: Callable, class_name: str) -> type[BaseModel]:
108
+ """Generate model using RunAnalyzer to infer parameters from method body.
109
+
110
+ This is used for legacy `_run` methods that only have `**kwargs` in their signature
111
+ but use specific parameters within the method body.
112
+
113
+ Args:
114
+ method (Callable): Method whose signature should be represented.
115
+ class_name (str): Component class name used to derive the generated model name.
116
+
117
+ Returns:
118
+ type[BaseModel]: A Pydantic `BaseModel` subclass describing the method's
119
+ parameters.
120
+ """
121
+
122
+ class MockClass:
123
+ pass
124
+
125
+ MockClass._run = method
126
+ config_dict = ConfigDict(extra="allow", arbitrary_types_allowed=True)
127
+
128
+ try:
129
+ profile = analyze_method(MockClass, method)
130
+
131
+ fields: dict[str, tuple[type[Any], Any]] = {}
132
+
133
+ for param_name in profile.arg_usages.required:
134
+ fields[param_name] = (Any, ...)
135
+
136
+ for param_name in profile.arg_usages.optional:
137
+ fields[param_name] = (Any, None)
138
+
139
+ model_name = f"{class_name}Params"
140
+ return create_model( # type: ignore[call-overload]
141
+ model_name,
142
+ __config__=config_dict,
143
+ **fields,
144
+ )
145
+ except Exception:
146
+ model_name = f"{class_name}Params"
147
+ return create_model( # type: ignore[call-overload]
148
+ model_name,
149
+ __config__=config_dict,
150
+ )
@@ -0,0 +1,35 @@
1
+ from gllm_core.utils.analyzer import analyze_method as analyze_method
2
+ from pydantic import BaseModel as BaseModel
3
+ from typing import Callable
4
+
5
+ def generate_params_model(method: Callable, class_name: str) -> type[BaseModel]:
6
+ '''Generate a Pydantic model representing a component method signature.
7
+
8
+ The generated class is named `{class_name}Params` and contains one field for
9
+ every parameter in `method`. The first `self` parameter is ignored, `*args` are
10
+ skipped entirely, and `**kwargs` trigger `extra="allow"` to permit arbitrary
11
+ keyword arguments at runtime.
12
+
13
+ For legacy `_run` methods with only `**kwargs`, this function will use
14
+ RunAnalyzer to infer parameters from the method body usage patterns.
15
+
16
+ Args:
17
+ method (Callable): Method whose signature should be represented.
18
+ class_name (str): Component class name used to derive the generated model name.
19
+
20
+ Returns:
21
+ type[BaseModel]: A Pydantic `BaseModel` subclass describing the method\'s
22
+ parameters.
23
+
24
+ Example:
25
+ ```python
26
+ class_name = "TextProcessor"
27
+
28
+ def process(self, text: str, count: int = 5) -> str:
29
+ return text * count
30
+
31
+ Model = generate_params_model(process, class_name)
32
+ assert Model.__name__ == "TextProcessorParams"
33
+ assert Model(text="hello", count=2).model_dump() == {"text": "hello", "count": 2}
34
+ ```
35
+ '''