lionagi 0.2.5__py3-none-any.whl → 0.2.7__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.
@@ -26,6 +26,8 @@ load_dotenv()
26
26
 
27
27
  _oai_price_map = {
28
28
  "gpt-4o": (5, 15),
29
+ "gpt-4o-2024-08-06": (2.5, 10),
30
+ "gpt-4o-mini": (0.15, 0.6),
29
31
  "gpt-4-turbo": (10, 30),
30
32
  "gpt-3.5-turbo": (0.5, 1.5),
31
33
  }
@@ -322,6 +324,38 @@ class iModel:
322
324
  node.add_field("embedding", embed["data"][0]["embedding"])
323
325
  node._meta_insert("embedding_meta", payload)
324
326
 
327
+ async def format_structure(
328
+ self,
329
+ data: str | dict,
330
+ json_schema: dict | str = None,
331
+ request_fields: dict | list = None,
332
+ **kwargs,
333
+ ) -> dict:
334
+ if json_schema:
335
+ kwargs["response_format"] = {
336
+ "type": "json_schema",
337
+ "json_schema": json_schema,
338
+ }
339
+ kwargs["model"] = kwargs.pop("model", "gpt-4o-mini")
340
+ if not request_fields and not json_schema:
341
+ raise ValueError("Either request_fields or json_schema must be provided")
342
+ request_fields = request_fields or json_schema["properties"]
343
+
344
+ messages = [
345
+ {
346
+ "role": "system",
347
+ "content": "You are a helpful json formatting assistant.",
348
+ },
349
+ {
350
+ "role": "user",
351
+ "content": f"can you please format the given data into given json schema?"
352
+ f"--- data --- {data} |||| ----json fields required --- {request_fields}",
353
+ },
354
+ ]
355
+
356
+ result = await self.call_chat_completion(messages, **kwargs)
357
+ return result["choices"][0]["message"]["content"]
358
+
325
359
  def to_dict(self):
326
360
  """
327
361
  Converts the model instance to a dictionary representation.
@@ -58,7 +58,7 @@ class Branch(Node, DirectiveMixin):
58
58
  messages: Pile = Field(None)
59
59
  progress: Progression = Field(None)
60
60
  tool_manager: ToolManager = Field(None)
61
- system: System = Field(None)
61
+ system: System | None = Field(None)
62
62
  user: str = Field(None)
63
63
  mailbox: Exchange[Mail] = Field(None)
64
64
  imodel: iModel = Field(None)
@@ -110,14 +110,14 @@ class Branch(Node, DirectiveMixin):
110
110
  system (System): The system message to set.
111
111
  sender (str, optional): The sender of the system message.
112
112
  """
113
- system = system or "You are a helpful assistant."
114
- if len(self.progress) == 0:
115
- self.add_message(system=system, sender=sender)
116
- else:
117
- _msg = System(system=system, sender=sender)
118
- _msg.recipient = self.ln_id
119
- self._remove_system()
120
- self.system = _msg
113
+ if system is not None:
114
+ if len(self.progress) == 0:
115
+ self.add_message(system=system, sender=sender)
116
+ else:
117
+ _msg = System(system=system, sender=sender)
118
+ _msg.recipient = self.ln_id
119
+ self._remove_system()
120
+ self.system = _msg
121
121
 
122
122
  def add_message(
123
123
  self,
@@ -51,6 +51,10 @@ class DirectiveMixin:
51
51
  return_branch=False,
52
52
  images=None,
53
53
  image_path=None,
54
+ template=None,
55
+ verbose=True,
56
+ formatter=None,
57
+ format_kwargs=None,
54
58
  **kwargs,
55
59
  ):
56
60
  """
@@ -114,7 +118,15 @@ class DirectiveMixin:
114
118
  >>> print(result)
115
119
  """
116
120
 
117
- directive = Unit(self, imodel=imodel, rulebook=rulebook)
121
+ directive = Unit(
122
+ self,
123
+ imodel=imodel,
124
+ rulebook=rulebook,
125
+ template=template,
126
+ verbose=verbose,
127
+ formatter=formatter,
128
+ format_kwargs=format_kwargs,
129
+ )
118
130
  if system:
119
131
  self.add_message(system=system)
120
132
 
@@ -174,7 +186,10 @@ class DirectiveMixin:
174
186
  directive=None,
175
187
  images=None,
176
188
  image_path=None,
177
- verbose=False,
189
+ template=None,
190
+ verbose=True,
191
+ formatter=None,
192
+ format_kwargs=None,
178
193
  **kwargs,
179
194
  ):
180
195
  """
@@ -220,7 +235,14 @@ class DirectiveMixin:
220
235
 
221
236
  images = ImageUtil.read_image_to_base64(image_path)
222
237
 
223
- _directive = Unit(self, imodel=imodel, rulebook=rulebook, verbose=verbose)
238
+ _directive = Unit(
239
+ self,
240
+ imodel=imodel,
241
+ rulebook=rulebook,
242
+ verbose=verbose,
243
+ formatter=formatter,
244
+ format_kwargs=format_kwargs,
245
+ )
224
246
 
225
247
  idx = len(self.progress)
226
248
  if directive and isinstance(directive, str):
@@ -232,6 +254,7 @@ class DirectiveMixin:
232
254
  reason=reason,
233
255
  confidence=confidence,
234
256
  images=images,
257
+ template=template,
235
258
  **kwargs,
236
259
  )
237
260
 
@@ -269,6 +292,7 @@ class DirectiveMixin:
269
292
  plan_num_step=plan_num_step,
270
293
  predict_num_sentences=predict_num_sentences,
271
294
  images=images,
295
+ template=template,
272
296
  **kwargs,
273
297
  )
274
298
 
lionagi/core/unit/unit.py CHANGED
@@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  """
16
16
 
17
+ from typing import Callable
17
18
  from lionagi.libs.ln_convert import strip_lower
18
19
  from lionagi.libs.ln_func_call import rcall
19
20
  from lionagi.core.collections.abc import Directive
@@ -40,7 +41,14 @@ class Unit(Directive, DirectiveMixin):
40
41
  default_template = UnitForm
41
42
 
42
43
  def __init__(
43
- self, branch, imodel: iModel = None, template=None, rulebook=None, verbose=False
44
+ self,
45
+ branch,
46
+ imodel: iModel = None,
47
+ template=None,
48
+ rulebook=None,
49
+ verbose=False,
50
+ formatter: Callable = None,
51
+ format_kwargs: dict = {},
44
52
  ) -> None:
45
53
  self.branch = branch
46
54
  if imodel and isinstance(imodel, iModel):
@@ -49,7 +57,11 @@ class Unit(Directive, DirectiveMixin):
49
57
  else:
50
58
  self.imodel = branch.imodel
51
59
  self.form_template = template or self.default_template
52
- self.validator = Validator(rulebook=rulebook) if rulebook else Validator()
60
+ rule_config = {"formatter": formatter, "format_kwargs": format_kwargs}
61
+ if rulebook:
62
+ rule_config["rulebook"] = rulebook
63
+
64
+ self.validator = Validator(**rule_config)
53
65
  self.verbose = verbose
54
66
 
55
67
  async def chat(
@@ -71,6 +83,8 @@ class Unit(Directive, DirectiveMixin):
71
83
  clear_messages=False,
72
84
  use_annotation=True,
73
85
  return_branch=False,
86
+ formatter=None,
87
+ format_kwargs={},
74
88
  **kwargs,
75
89
  ):
76
90
  """
@@ -119,6 +133,8 @@ class Unit(Directive, DirectiveMixin):
119
133
  clear_messages=clear_messages,
120
134
  use_annotation=use_annotation,
121
135
  return_branch=return_branch,
136
+ formatter=formatter,
137
+ format_kwargs=format_kwargs,
122
138
  **kwargs,
123
139
  )
124
140
 
@@ -257,7 +257,6 @@ class DirectiveMixin(ABC):
257
257
  form: Form = None,
258
258
  return_form: bool = True,
259
259
  strict: bool = False,
260
- rulebook: Any = None,
261
260
  use_annotation: bool = True,
262
261
  template_name: str = None,
263
262
  costs=None,
@@ -274,7 +273,6 @@ class DirectiveMixin(ABC):
274
273
  form: Form data.
275
274
  return_form: Flag indicating if form should be returned.
276
275
  strict: Flag indicating if strict validation should be applied.
277
- rulebook: Rulebook instance for validation.
278
276
  use_annotation: Flag indicating if annotations should be used.
279
277
  template_name: Template name for form.
280
278
 
@@ -295,8 +293,7 @@ class DirectiveMixin(ABC):
295
293
  response_ = self._process_model_response(_msg, requested_fields)
296
294
 
297
295
  if form:
298
- validator = Validator(rulebook=rulebook) if rulebook else self.validator
299
- form = await validator.validate_response(
296
+ form = await self.validator.validate_response(
300
297
  form=form,
301
298
  response=response_,
302
299
  strict=strict,
@@ -332,7 +329,6 @@ class DirectiveMixin(ABC):
332
329
  invoke_tool: bool = True,
333
330
  return_form: bool = True,
334
331
  strict: bool = False,
335
- rulebook: Any = None,
336
332
  imodel: Any = None,
337
333
  use_annotation: bool = True,
338
334
  branch: Any = None,
@@ -356,7 +352,6 @@ class DirectiveMixin(ABC):
356
352
  invoke_tool: Flag indicating if tools should be invoked.
357
353
  return_form: Flag indicating if form should be returned.
358
354
  strict: Flag indicating if strict validation should be applied.
359
- rulebook: Rulebook instance for validation.
360
355
  imodel: Model instance.
361
356
  use_annotation: Flag indicating if annotations should be used.
362
357
  branch: Branch instance.
@@ -400,9 +395,8 @@ class DirectiveMixin(ABC):
400
395
  form=form,
401
396
  return_form=return_form,
402
397
  strict=strict,
403
- rulebook=rulebook,
404
398
  use_annotation=use_annotation,
405
- costs=imodel.costs,
399
+ costs=imodel.costs or (0, 0),
406
400
  )
407
401
 
408
402
  return out_, branch if return_branch else out_
@@ -421,13 +415,14 @@ class DirectiveMixin(ABC):
421
415
  invoke_tool=True,
422
416
  return_form=True,
423
417
  strict=False,
424
- rulebook=None,
425
418
  imodel=None,
426
419
  images: Optional[str] = None,
427
420
  clear_messages=False,
428
421
  use_annotation=True,
429
422
  timeout: float = None,
430
423
  return_branch=False,
424
+ formatter=None,
425
+ format_kwargs={},
431
426
  **kwargs,
432
427
  ):
433
428
  """
@@ -470,13 +465,14 @@ class DirectiveMixin(ABC):
470
465
  invoke_tool=invoke_tool,
471
466
  return_form=return_form,
472
467
  strict=strict,
473
- rulebook=rulebook,
474
468
  imodel=imodel,
475
469
  use_annotation=use_annotation,
476
470
  timeout=timeout,
477
471
  branch=branch,
478
472
  clear_messages=clear_messages,
479
473
  return_branch=return_branch,
474
+ formatter=formatter,
475
+ format_kwargs=format_kwargs,
480
476
  **kwargs,
481
477
  )
482
478
 
@@ -609,7 +605,9 @@ class DirectiveMixin(ABC):
609
605
  clear_messages=False,
610
606
  return_branch=False,
611
607
  images: Optional[str] = None,
612
- verbose=None,
608
+ verbose=True,
609
+ formatter=None,
610
+ format_kwargs=None,
613
611
  **kwargs,
614
612
  ):
615
613
  """
@@ -14,10 +14,12 @@ See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  """
16
16
 
17
- from typing import Any, Dict, List, Union
17
+ import asyncio
18
+ from typing import Any, Dict, List, Union, Callable
18
19
  from lionagi.libs import SysUtil
19
20
  from lionagi.libs.ln_func_call import lcall
20
21
  from lionagi.core.collections.abc import FieldError
22
+ from lionagi.core.collections.model import iModel
21
23
  from ..rule.base import Rule
22
24
  from ..rule._default import DEFAULT_RULES
23
25
  from ..rule.rulebook import RuleBook
@@ -56,6 +58,8 @@ class Validator:
56
58
  order: List[str] = None,
57
59
  init_config: Dict[str, Dict] = None,
58
60
  active_rules: Dict[str, Rule] = None,
61
+ formatter: Callable = None,
62
+ format_kwargs: dict = {},
59
63
  ):
60
64
  """
61
65
  Initialize the Validator.
@@ -75,6 +79,8 @@ class Validator:
75
79
  )
76
80
  self.active_rules: Dict[str, Rule] = active_rules or self._initiate_rules()
77
81
  self.validation_log = []
82
+ self.formatter = formatter
83
+ self.format_kwargs = format_kwargs
78
84
 
79
85
  def _initiate_rules(self) -> Dict[str, Rule]:
80
86
  """
@@ -207,9 +213,16 @@ class Validator:
207
213
  if len(form.requested_fields) == 1:
208
214
  response = {form.requested_fields[0]: response}
209
215
  else:
210
- raise ValueError(
211
- "Response is a string, but form has multiple fields to be filled"
212
- )
216
+ if self.formatter:
217
+ if asyncio.iscoroutinefunction(self.formatter):
218
+ response = await self.formatter(response, **self.format_kwargs)
219
+ print("formatter used")
220
+ else:
221
+ response = self.formatter(response, **self.format_kwargs)
222
+ print("formatter used")
223
+
224
+ if not isinstance(response, dict):
225
+ raise ValueError(f"The form response format is invalid for filling.")
213
226
 
214
227
  dict_ = {}
215
228
  for k, v in response.items():
lionagi/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.2.5"
1
+ __version__ = "0.2.7"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lionagi
3
- Version: 0.2.5
3
+ Version: 0.2.7
4
4
  Summary: Towards automated general intelligence.
5
5
  Author: HaiyangLi
6
6
  Author-email: Haiyang Li <ocean@lionagi.ai>
@@ -237,7 +237,7 @@ Requires-Dist: boto3 >=1.34.131
237
237
  ### an AGentic Intelligence Operating System
238
238
 
239
239
  ```
240
- pip install lionagi==0.2.5
240
+ pip install lionagi==0.2.6
241
241
  ```
242
242
 
243
243
  **Powerful Intelligent Workflow Automation**
@@ -1,5 +1,5 @@
1
1
  lionagi/__init__.py,sha256=amQal6CUIv4QDI4Qmb0M5qwTbn3_F430Wl5vaSNG6-U,1952
2
- lionagi/version.py,sha256=Xsa3ayOMVkhUWm4t06YeyHE0apjpZefxLH4ylp0CDtU,22
2
+ lionagi/version.py,sha256=XHypfHSPdgXFKmOdoewn7czU670gt8InhHhzlP5j_aA,22
3
3
  lionagi/core/__init__.py,sha256=Il5Q9ATdX8yXqVxtP_nYqUhExzxPC_qk_WXQ_4h0exg,16
4
4
  lionagi/core/_setting/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  lionagi/core/_setting/_setting.py,sha256=p23fHtrzIZlQ8s8CDZICn8C6k7mdB_088nIDx19JaqM,1907
@@ -23,7 +23,7 @@ lionagi/core/collections/__init__.py,sha256=5374e0qHH75IUvW-xA3Dte25N_oc_YXjtu7e
23
23
  lionagi/core/collections/_logger.py,sha256=_jwZe6BsRaWB2YkHwG01jmiudJkoi5u90Ry3KKa9T-o,12104
24
24
  lionagi/core/collections/exchange.py,sha256=Skx2al0PtNkzdaApb8DdbOO0ukC19kSQnlskHpAHJHw,4832
25
25
  lionagi/core/collections/flow.py,sha256=0tBeVJhENXjVFjtOlrEHXvI4q-rgTyD-kcE7X29AqDE,13189
26
- lionagi/core/collections/model.py,sha256=RQYuvZachSYJi8owQ44GPSZXV22l-KdWqJAL40CG2PE,14846
26
+ lionagi/core/collections/model.py,sha256=U9yFhQ31NH24HwJjnnRxOfZcnUWq8Vuk_iF0r8SZc5A,16079
27
27
  lionagi/core/collections/pile.py,sha256=MF2G846TolIiKZkY0mjSOvD7Bc3__Fb_z-WiiLG1lbM,29444
28
28
  lionagi/core/collections/progression.py,sha256=eDhSbsQWb9TVsNExaJAN27tjoyb6QEKWPxBZKUbNbs0,7295
29
29
  lionagi/core/collections/util.py,sha256=JRu_gCDYopqIUByEtJgnJNkeoWnhge7XbSFejrdbIec,1962
@@ -82,8 +82,8 @@ lionagi/core/rule/rulebook.py,sha256=HlJCIjhsRB0yJs-uF85aK9bJasCDI0K845UGmymzD9Q
82
82
  lionagi/core/rule/string.py,sha256=8nSxEhHUFs-gWM1MW5fiNuDP1Yd_IIZ2ipBVphgCmQ0,1487
83
83
  lionagi/core/rule/util.py,sha256=qqtUqt4BL_sikW2XZ73NDzb3p-Awu4za_2B5mZvzFdA,1042
84
84
  lionagi/core/session/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
85
- lionagi/core/session/branch.py,sha256=6ySBqEZHYbQ1AKJmcoBtU9MwF5WT5wAr3z2NB6TF8gg,14761
86
- lionagi/core/session/directive_mixin.py,sha256=SgLFQwZyqnP6pCoZU1YBJuO6olnSBKZ6FIfl-Je3uVQ,11724
85
+ lionagi/core/session/branch.py,sha256=338N-jw-AfnjksYFo2WiLIeXdzxOYJ_qZBxMuk-U8bU,14769
86
+ lionagi/core/session/directive_mixin.py,sha256=vCoOIA_AYEH7M1ptDBUaOtSuxC5KQSAnsKn9X-LpjFs,12275
87
87
  lionagi/core/session/session.py,sha256=uESwIyGfRrX8Ii03-QIQYUlQKR7lsJWREdSZrHxfNW4,11012
88
88
  lionagi/core/structure/__init__.py,sha256=DkeLUlrb7rGx3nZ04aADU9HXXu5mZTf_DBwT0xhzIv4,7
89
89
  lionagi/core/structure/chain.py,sha256=DkeLUlrb7rGx3nZ04aADU9HXXu5mZTf_DBwT0xhzIv4,7
@@ -92,9 +92,9 @@ lionagi/core/structure/graph.py,sha256=DkeLUlrb7rGx3nZ04aADU9HXXu5mZTf_DBwT0xhzI
92
92
  lionagi/core/structure/tree.py,sha256=DkeLUlrb7rGx3nZ04aADU9HXXu5mZTf_DBwT0xhzIv4,7
93
93
  lionagi/core/unit/__init__.py,sha256=cxASNHNw2wK-SO9a4FQTjKDOOpT3HRE_qFD5GEvHdbQ,88
94
94
  lionagi/core/unit/parallel_unit.py,sha256=DB5PjGMin2PkXc4qR7u6zEMxkj8WVgtSfdMoPhSby0A,9332
95
- lionagi/core/unit/unit.py,sha256=V-0qOUtW5v5XHNUGJl9aE1j8fxYVWwLulrxySkN814w,12986
95
+ lionagi/core/unit/unit.py,sha256=hnXSjHPc9TXOfPv-sUV1T8LIUhmjXODpIZr9Sj9cGwE,13364
96
96
  lionagi/core/unit/unit_form.py,sha256=1WDBXDprnsyz8OEbDH7LLRceldhvZHmswVoZb1CV80E,11580
97
- lionagi/core/unit/unit_mixin.py,sha256=E8GY7eAjtvlfYW4Thpd-XoOeAZMLYC13HMyC2erCueE,39314
97
+ lionagi/core/unit/unit_mixin.py,sha256=-Jy3KxhETyQYGUxo2xZQByHjGuckzeHLU1CaMknwu5k,39163
98
98
  lionagi/core/unit/util.py,sha256=GqErzoWlUeSBtl3qcjqMONJoNK7i1DYJ_S3JW6MnEp8,1994
99
99
  lionagi/core/unit/template/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
100
100
  lionagi/core/unit/template/action.py,sha256=AETiRQKDvjB-EEyi-i6u3UqQ8650HbDkUaSSNxQJ8P0,2791
@@ -104,7 +104,7 @@ lionagi/core/unit/template/predict.py,sha256=LdsKgoXs-yQIb6VfFD08CphAn33SJWUlLF8
104
104
  lionagi/core/unit/template/score.py,sha256=vTiSzL80YDQERVEQT-VNc_wKWbVJyLfvBa2DSexKyLg,4368
105
105
  lionagi/core/unit/template/select.py,sha256=n9u1Yer_fWPYZDzAnlYpSECo_hk7B0gTaEGSta6i8is,3604
106
106
  lionagi/core/validator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
107
- lionagi/core/validator/validator.py,sha256=ngThQTzNSOa6N0mKrAQuhwM_gb_IWhF58OefOyUjTK8,12012
107
+ lionagi/core/validator/validator.py,sha256=ohlaNxxoi7KCY_1BIyTt03JegpqmGIhuqnIdtHL2nDE,12618
108
108
  lionagi/core/work/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
109
109
  lionagi/core/work/work.py,sha256=oVbx0b8arvXSjDZa2Rs1s37_Fiue6gbR0Tt4oL7Dzkk,2532
110
110
  lionagi/core/work/work_edge.py,sha256=o6bCDjQIfBjnnpbd7ZVNLGuRQgmvLDwPah58TaTK0eU,3408
@@ -251,8 +251,8 @@ lionagi/tests/test_core/test_structure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JC
251
251
  lionagi/tests/test_core/test_structure/test_base_structure.py,sha256=qsaYP745fFIst5ZNiPFb9-ATScLyUFqQ5UQzyyBgJPM,9388
252
252
  lionagi/tests/test_core/test_structure/test_graph.py,sha256=hLsTZmZMs9vCZW-KiOwYY3npk6WxaVU6zZSA9-ltDvQ,2162
253
253
  lionagi/tests/test_core/test_structure/test_tree.py,sha256=PvMJXDsNPpJFgEQCan-5Q5JREgMrBOpYIaWcwHd-WDY,1944
254
- lionagi-0.2.5.dist-info/LICENSE,sha256=VXFWsdoN5AAknBCgFqQNgPWYx7OPp-PFEP961zGdOjc,11288
255
- lionagi-0.2.5.dist-info/METADATA,sha256=svScDN5_cqlfWuaNVwMnRnTUdf5Sx8MY4f1hk03HXjc,16276
256
- lionagi-0.2.5.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
257
- lionagi-0.2.5.dist-info/top_level.txt,sha256=szvch_d2jE1Lu9ZIKsl26Ll6BGfYfbOgt5lm-UpFSo4,8
258
- lionagi-0.2.5.dist-info/RECORD,,
254
+ lionagi-0.2.7.dist-info/LICENSE,sha256=VXFWsdoN5AAknBCgFqQNgPWYx7OPp-PFEP961zGdOjc,11288
255
+ lionagi-0.2.7.dist-info/METADATA,sha256=WI8pyy3AHxkvSBmxFFQKtYGoL-tCXEplXj6xU9rzcWs,16276
256
+ lionagi-0.2.7.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
257
+ lionagi-0.2.7.dist-info/top_level.txt,sha256=szvch_d2jE1Lu9ZIKsl26Ll6BGfYfbOgt5lm-UpFSo4,8
258
+ lionagi-0.2.7.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (72.1.0)
2
+ Generator: setuptools (74.1.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5