langfun 0.1.2.dev202505160805__py3-none-any.whl → 0.1.2.dev202505180804__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 langfun might be problematic. Click here for more details.

@@ -225,7 +225,7 @@ class Action(pg.Object):
225
225
  result = self.call(session=session, **kwargs)
226
226
  self._invocation.end(result)
227
227
  except BaseException as e:
228
- error = pg.utils.ErrorInfo.from_exception(e)
228
+ error = pg.ErrorInfo.from_exception(e)
229
229
  self._invocation.end(result=None, error=error)
230
230
  if self._session is not None:
231
231
  self._session.end(result=None, error=error)
@@ -819,7 +819,7 @@ class ActionInvocation(pg.Object, pg.views.html.HtmlTreeView.Extension):
819
819
  ] = {}
820
820
 
821
821
  error: Annotated[
822
- pg.utils.ErrorInfo | None,
822
+ pg.ErrorInfo | None,
823
823
  'Error from the action if failed.'
824
824
  ] = None
825
825
 
@@ -910,7 +910,7 @@ class ActionInvocation(pg.Object, pg.views.html.HtmlTreeView.Extension):
910
910
  def end(
911
911
  self,
912
912
  result: Any,
913
- error: pg.utils.ErrorInfo | None = None,
913
+ error: pg.ErrorInfo | None = None,
914
914
  metadata: dict[str, Any] | None = None,
915
915
  ) -> None:
916
916
  """Ends the execution of the action with result and metadata."""
@@ -1138,7 +1138,7 @@ class Session(pg.Object, pg.views.html.HtmlTreeView.Extension):
1138
1138
  return self.root.result
1139
1139
 
1140
1140
  @property
1141
- def final_error(self) -> pg.utils.ErrorInfo | None:
1141
+ def final_error(self) -> pg.ErrorInfo | None:
1142
1142
  """Returns the error of the session."""
1143
1143
  return self.root.error
1144
1144
 
@@ -1186,7 +1186,7 @@ class Session(pg.Object, pg.views.html.HtmlTreeView.Extension):
1186
1186
  def end(
1187
1187
  self,
1188
1188
  result: Any,
1189
- error: pg.utils.ErrorInfo | None = None,
1189
+ error: pg.ErrorInfo | None = None,
1190
1190
  metadata: dict[str, Any] | None = None,
1191
1191
  ) -> None:
1192
1192
  """Ends the session."""
@@ -1220,7 +1220,7 @@ class Session(pg.Object, pg.views.html.HtmlTreeView.Extension):
1220
1220
 
1221
1221
  if exc_val is not None:
1222
1222
  result, metadata = None, None
1223
- error = pg.utils.ErrorInfo.from_exception(exc_val)
1223
+ error = pg.ErrorInfo.from_exception(exc_val)
1224
1224
  else:
1225
1225
  actions = self.root.actions
1226
1226
  if actions:
@@ -308,7 +308,7 @@ class SessionTest(unittest.TestCase):
308
308
  self.assertTrue(session.has_started)
309
309
  self.assertTrue(session.has_stopped)
310
310
  self.assertTrue(session.has_error)
311
- self.assertIsInstance(session.final_error, pg.utils.ErrorInfo)
311
+ self.assertIsInstance(session.final_error, pg.ErrorInfo)
312
312
  self.assertIn('Bar error', str(session.root.error))
313
313
 
314
314
  def test_succeeded_with_explicit_session(self):
@@ -375,7 +375,7 @@ class SessionTest(unittest.TestCase):
375
375
  self.assertTrue(session.has_stopped)
376
376
  self.assertTrue(session.has_error)
377
377
  self.assertIsNone(session.final_result)
378
- self.assertIsInstance(session.root.error, pg.utils.ErrorInfo)
378
+ self.assertIsInstance(session.root.error, pg.ErrorInfo)
379
379
  self.assertIn('Bar error', str(session.root.error))
380
380
 
381
381
  def test_failed_with_explicit_session_without_start(self):
@@ -412,7 +412,7 @@ class SessionTest(unittest.TestCase):
412
412
  self.assertTrue(session.has_started)
413
413
  self.assertTrue(session.has_stopped)
414
414
  self.assertTrue(session.has_error)
415
- self.assertIsInstance(session.root.error, pg.utils.ErrorInfo)
415
+ self.assertIsInstance(session.root.error, pg.ErrorInfo)
416
416
  self.assertEqual(len(session.root.execution), 3)
417
417
  self.assertEqual(len(session.root.actions), 2)
418
418
  self.assertEqual(len(session.root.logs), 1)
@@ -31,10 +31,12 @@ class GeminiMessageConverter(lf.MessageConverter):
31
31
  'Chunk preprocessor for Langfun chunk to Gemini chunk conversion. '
32
32
  'It will be applied before each Langfun chunk is converted. '
33
33
  'If returns None, the chunk will be skipped.'
34
- )
34
+ ),
35
35
  ] = None
36
36
 
37
- def to_value(self, message: lf.Message) -> dict[str, Any]:
37
+ def to_value(
38
+ self, message: lf.Message, always_send_content: bool = True
39
+ ) -> dict[str, Any]:
38
40
  """Converts a Langfun message to Gemini API."""
39
41
  parts = []
40
42
  for chunk in message.chunk():
@@ -44,7 +46,7 @@ class GeminiMessageConverter(lf.MessageConverter):
44
46
  continue
45
47
 
46
48
  if isinstance(chunk, str):
47
- parts.append(self._convert_chunk(chunk))
49
+ parts.append(self._convert_chunk(chunk, always_send_content))
48
50
  else:
49
51
  if isinstance(chunk, lf_modalities.Mime):
50
52
  modalities = [chunk]
@@ -54,10 +56,14 @@ class GeminiMessageConverter(lf.MessageConverter):
54
56
  modalities = chunk
55
57
  else:
56
58
  raise ValueError(f'Unsupported content type: {chunk!r}.')
57
- parts.extend(self._convert_chunk(c) for c in modalities)
59
+ parts.extend(
60
+ self._convert_chunk(c, always_send_content) for c in modalities
61
+ )
58
62
  return dict(role=self.get_role(message), parts=parts)
59
63
 
60
- def _convert_chunk(self, chunk: str | lf.Modality) -> Any:
64
+ def _convert_chunk(
65
+ self, chunk: str | lf.Modality, always_send_content: bool = True
66
+ ) -> Any:
61
67
  """Converts a Langfun chunk to Gemini chunk."""
62
68
  if isinstance(chunk, str):
63
69
  return {'text': chunk}
@@ -73,8 +79,10 @@ class GeminiMessageConverter(lf.MessageConverter):
73
79
  }
74
80
  if chunk.is_text:
75
81
  return {'text': chunk.to_text()}
76
- if chunk.uri and chunk.uri.lower().startswith(
77
- ('http:', 'https:', 'ftp:')
82
+ if (
83
+ not always_send_content
84
+ and chunk.uri
85
+ and chunk.uri.lower().startswith(('http:', 'https:', 'ftp:'))
78
86
  ):
79
87
  return {
80
88
  'fileData': {
@@ -58,11 +58,8 @@ class GeminiConversionTest(unittest.TestCase):
58
58
  def test_as_format_with_image(self):
59
59
  self.assertEqual(
60
60
  lf.Template(
61
- 'What are the common words from {{image}}, {{pdf}} and {{video}}?',
61
+ 'What are the common words from {{image}} and {{video}}?',
62
62
  image=lf_modalities.Image.from_bytes(image_content),
63
- pdf=lf_modalities.Custom.from_uri(
64
- 'https://my.pdf', mime='application/pdf'
65
- ),
66
63
  video=lf_modalities.Custom.from_uri(
67
64
  'https://www.youtube.com/watch?v=abcd', mime='text/html'
68
65
  ),
@@ -79,15 +76,6 @@ class GeminiConversionTest(unittest.TestCase):
79
76
  'mimeType': 'image/png',
80
77
  }
81
78
  },
82
- {
83
- 'text': ','
84
- },
85
- {
86
- 'fileData': {
87
- 'fileUri': 'https://my.pdf',
88
- 'mimeType': 'application/pdf',
89
- }
90
- },
91
79
  {
92
80
  'text': 'and'
93
81
  },
@@ -255,7 +255,7 @@ class Evaluation(experiment_lib.Experiment):
255
255
  except BaseException as e: # pylint: disable=broad-except
256
256
  if raise_if_has_error:
257
257
  raise
258
- example.error = pg.object_utils.ErrorInfo.from_exception(e)
258
+ example.error = pg.ErrorInfo.from_exception(e)
259
259
 
260
260
  #
261
261
  # Handling evaluation scheduling.
@@ -39,7 +39,7 @@ class Example(pg.JSONConvertible, pg.views.HtmlTreeView.Extension):
39
39
  id: int
40
40
  input: Any = pg.MISSING_VALUE
41
41
  output: Any = pg.MISSING_VALUE
42
- error: pg.object_utils.ErrorInfo | None = None
42
+ error: pg.ErrorInfo | None = None
43
43
  metadata: dict[str, Any] = dataclasses.field(default_factory=dict)
44
44
  metric_metadata: dict[str, Any] | None = None
45
45
  # Execution information.
@@ -47,12 +47,13 @@ class Example(pg.JSONConvertible, pg.views.HtmlTreeView.Extension):
47
47
  start_time: float | None = None
48
48
  end_time: float | None = None
49
49
  usage_summary: lf.UsageSummary | None = None
50
- execution_status: dict[str, pg.object_utils.TimeIt.Status] | None = None
50
+ execution_status: dict[str, pg.utils.TimeIt.Status] | None = None
51
51
 
52
52
  def __post_init__(self):
53
53
  if self.execution_status is not None:
54
54
  for status in self.execution_status.values():
55
55
  if status.has_error:
56
+ assert isinstance(status.error, pg.ErrorInfo)
56
57
  self.error = status.error
57
58
  break
58
59
 
@@ -188,7 +189,7 @@ class Example(pg.JSONConvertible, pg.views.HtmlTreeView.Extension):
188
189
  text = f'{key}:{value}'
189
190
  return pg.views.html.controls.Badge(
190
191
  text,
191
- css_classes=[pg.object_utils.camel_to_snake(key, '-')],
192
+ css_classes=[pg.utils.camel_to_snake(key, '-')],
192
193
  )
193
194
 
194
195
  def _render_header():
@@ -22,13 +22,13 @@ Example = example_lib.Example
22
22
  class ExampleTest(unittest.TestCase):
23
23
 
24
24
  def test_basic(self):
25
- error = pg.object_utils.ErrorInfo(
25
+ error = pg.ErrorInfo(
26
26
  tag='ValueError',
27
27
  description='Bad input',
28
28
  stacktrace='...',
29
29
  )
30
30
  ex = Example(id=1, execution_status={
31
- 'evaluate': pg.object_utils.TimeIt.Status(
31
+ 'evaluate': pg.utils.TimeIt.Status(
32
32
  name='evaluation', elapse=1.0, error=error
33
33
  )
34
34
  })
@@ -649,7 +649,7 @@ def query(
649
649
  _mark_query_completed(output_message, None, usage_summary)
650
650
  except mapping.MappingError as e:
651
651
  _mark_query_completed(
652
- e.lm_response, pg.utils.ErrorInfo.from_exception(e), usage_summary
652
+ e.lm_response, pg.ErrorInfo.from_exception(e), usage_summary
653
653
  )
654
654
  if lf.RAISE_IF_HAS_ERROR == default:
655
655
  raise e
@@ -657,7 +657,7 @@ def query(
657
657
  output_message.result = default
658
658
  except BaseException as e:
659
659
  _mark_query_completed(
660
- None, pg.utils.ErrorInfo.from_exception(e), usage_summary
660
+ None, pg.ErrorInfo.from_exception(e), usage_summary
661
661
  )
662
662
  raise e
663
663
 
@@ -867,7 +867,7 @@ class QueryInvocation(pg.Object, pg.views.HtmlTreeView.Extension):
867
867
  ] = None
868
868
 
869
869
  error: Annotated[
870
- pg.utils.ErrorInfo | None,
870
+ pg.ErrorInfo | None,
871
871
  'Error info if the query failed.'
872
872
  ] = None
873
873
 
@@ -946,7 +946,7 @@ class QueryInvocation(pg.Object, pg.views.HtmlTreeView.Extension):
946
946
  def mark_completed(
947
947
  self,
948
948
  lm_response: lf.Message | None,
949
- error: pg.utils.ErrorInfo | None = None,
949
+ error: pg.ErrorInfo | None = None,
950
950
  usage_summary: lf.UsageSummary | None = None) -> None:
951
951
  """Marks the query as completed."""
952
952
  assert self.end_time is None, 'Query is already completed.'
@@ -965,7 +965,7 @@ class QueryInvocation(pg.Object, pg.views.HtmlTreeView.Extension):
965
965
  )
966
966
  except mapping.MappingError as e:
967
967
  output = None
968
- error = pg.utils.ErrorInfo.from_exception(e)
968
+ error = pg.ErrorInfo.from_exception(e)
969
969
  self._output = output
970
970
  else:
971
971
  assert lm_response is not None
@@ -1333,7 +1333,7 @@ class QueryInvocationTest(unittest.TestCase):
1333
1333
 
1334
1334
  self.assertEqual(queries[0].id, '123')
1335
1335
  self.assertTrue(queries[0].has_error)
1336
- self.assertIsInstance(queries[0].error, pg.utils.ErrorInfo)
1336
+ self.assertIsInstance(queries[0].error, pg.ErrorInfo)
1337
1337
  self.assertIn('MappingError', queries[0].error.tag)
1338
1338
  self.assertIsNone(queries[0].output)
1339
1339
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langfun
3
- Version: 0.1.2.dev202505160805
3
+ Version: 0.1.2.dev202505180804
4
4
  Summary: Langfun: Language as Functions.
5
5
  Home-page: https://github.com/google/langfun
6
6
  Author: Langfun Authors
@@ -26,10 +26,10 @@ langfun/core/subscription_test.py,sha256=Y4ZdbZEwm83YNZBxHff0QR4QUa4rdaNXA3_jfIc
26
26
  langfun/core/template.py,sha256=jNhYSrbLIn9kZOa03w5QZbyjgfnzJzE_ZrrMvvWY4t4,24929
27
27
  langfun/core/template_test.py,sha256=AQv_m9qE93WxhEhSlm1xaBgB4hu0UVtA53dljngkUW0,17090
28
28
  langfun/core/agentic/__init__.py,sha256=qR3jlfUO4rhIoYdRDLz-d22YZf3FvU4FW88vsjiGDQQ,1224
29
- langfun/core/agentic/action.py,sha256=WEKCaqtGVYKHARvY0Nqichc_hMKkJUYarrUky-DsfHk,50709
29
+ langfun/core/agentic/action.py,sha256=ngBN__OUjMrw4eg8ljHKQ7VY-EABW8T7gF1nw_ZkQmM,50673
30
30
  langfun/core/agentic/action_eval.py,sha256=YTilyUEkJl_8FVMgdfO17PurWWaEJ6oA15CuefJJRLk,4887
31
31
  langfun/core/agentic/action_eval_test.py,sha256=7AkOwNbUX-ZgR1R0a7bvUZ5abNTUV7blf_8Mnrwb-II,2811
32
- langfun/core/agentic/action_test.py,sha256=FO42Ab_riHHJxD6iJensskDCMx1-j7blzPr3fFaIfwc,15885
32
+ langfun/core/agentic/action_test.py,sha256=46piw5J7vGwmJGjmVG13HQRBmp5TLgkV_ymJ2EQVEIc,15867
33
33
  langfun/core/coding/__init__.py,sha256=5utju_fwEsImaiftx4oXKl9FAM8p281k8-Esdh_-m1w,835
34
34
  langfun/core/coding/python/__init__.py,sha256=4ByknuoNU-mOIHwHKnTtmo6oD64oMFtlqPlYWmA5Wic,1736
35
35
  langfun/core/coding/python/correction.py,sha256=4PD76Xfv36Xrm8Ji3-GgGDNImtcDqWfMw3z6ircJMlM,7285
@@ -46,8 +46,8 @@ langfun/core/data/__init__.py,sha256=qllw9ST1vveZv-1E0VM5hezn1YH-OcqGI-yFqQYnWgI
46
46
  langfun/core/data/conversion/__init__.py,sha256=ZcGntBruvvZSfESO-Tha1nzHfgWEK7I1u78Jw8gsoVU,883
47
47
  langfun/core/data/conversion/anthropic.py,sha256=0xf1sWt6WhmG8EsaeLY4Ee7S3FcDWKPOtn6caCBhtrQ,4431
48
48
  langfun/core/data/conversion/anthropic_test.py,sha256=R43PyveNUCHNCvfu6RFsTk0EIKK8M1Gzng0Kay8TlE8,8534
49
- langfun/core/data/conversion/gemini.py,sha256=k-BJFQ_xuYRTNH_k0cJlZlhN1VrQHiFjckSxRCyUGNY,5523
50
- langfun/core/data/conversion/gemini_test.py,sha256=KIaWdY8CIn0YMaSomxTizvwCrljvt7lbDi3WSEbb1FE,7637
49
+ langfun/core/data/conversion/gemini.py,sha256=fQ5yjwmQLTb-YJN1p6n3cxM9TQoniOkaLvT-p-jMoP8,5722
50
+ langfun/core/data/conversion/gemini_test.py,sha256=G-av2BUngBkxOkJz94CMpZRGq6DGDBvgLltoezuohm0,7239
51
51
  langfun/core/data/conversion/openai.py,sha256=sSpkDSxMJWJ3I1dNICBCzvLsJv4iiLg8FPYLtubBJUM,4181
52
52
  langfun/core/data/conversion/openai_test.py,sha256=38WV_3ofFZiUF10bTKnZp4VyuDP5-81aR3h3Q0HlBm0,5283
53
53
  langfun/core/eval/__init__.py,sha256=OEXr1ZRuvLuhJJfuQ1ZWQ-SvYzjyrtiAAEogYaB7E6o,1933
@@ -63,10 +63,10 @@ langfun/core/eval/v2/__init__.py,sha256=9lNKJwbvl0lcFblAXYT_OHI8fOubJsTOdSkxEqsP
63
63
  langfun/core/eval/v2/checkpointing.py,sha256=t47rBfzGZYgIqWW1N1Ak9yQnNtHd-IRbEO0cZjG2VRo,11755
64
64
  langfun/core/eval/v2/checkpointing_test.py,sha256=NggOSJ_6XSa4cNP6nGIu9wLsK59dUwe8SPWDiXtGGDE,9197
65
65
  langfun/core/eval/v2/eval_test_helper.py,sha256=sKFi_wPYCNmr96WyTduuXY0KnxjFxcJyEhXey-_nGX8,3962
66
- langfun/core/eval/v2/evaluation.py,sha256=BijbrYufnlRZLryxezDU32gHjFCCZvLAZMLF6kQ90eA,27050
66
+ langfun/core/eval/v2/evaluation.py,sha256=ihT5dljnUkHM97XS9OwE2wOnYC-oYnHYgG5KN1hmiaU,27037
67
67
  langfun/core/eval/v2/evaluation_test.py,sha256=QNp_HEvRTupvNuLEeYTvylykh1Ut2jpMqHQ-gCUZQ10,6919
68
- langfun/core/eval/v2/example.py,sha256=Jegt-viQSNYzPVkOZE_M19GON2TYGTct4Cp9HnJ7DGo,10861
69
- langfun/core/eval/v2/example_test.py,sha256=1DNm6EuyZOq827DKvf3oTRVFkMNM_qTnLUpvOjpgz5I,3419
68
+ langfun/core/eval/v2/example.py,sha256=v1dIz89pccIqujt7utrk0EbqMWM9kBn-2fYGRTKe358,10890
69
+ langfun/core/eval/v2/example_test.py,sha256=wsHQD6te7ghROmxe3Xg_NK4TU0xS2MkNfnpo-H0H8xM,3399
70
70
  langfun/core/eval/v2/experiment.py,sha256=fb3RHNOSRftV7ZTBfYVV50iEevqdPwRHCt3mgtLzuFw,33408
71
71
  langfun/core/eval/v2/experiment_test.py,sha256=UmCobeS6ifPcaGkTJp0WPISolXrVFbeFCBiyJeA0Lt4,13666
72
72
  langfun/core/eval/v2/metric_values.py,sha256=_B905bC-jxrYPLSEcP2M8MaHZOVMz_bVrUw8YC4arCE,4660
@@ -137,8 +137,8 @@ langfun/core/structured/mapping.py,sha256=iraHpcEeF_iuEX2eoTsLGwTHHvxqp2gNDjoMf9
137
137
  langfun/core/structured/mapping_test.py,sha256=OntYvfDitAf0tAnzQty3YS90vyEn6FY1Mi93r_ViEk8,9594
138
138
  langfun/core/structured/parsing.py,sha256=MGvI7ypXlwfzr5XB8_TFU9Ei0_5reYqkWkv64eAy0EA,12015
139
139
  langfun/core/structured/parsing_test.py,sha256=V8Cj1tJK4Lxv_b0YQj6-2hzXZgnYNBa2JR7rOLRBKoQ,22346
140
- langfun/core/structured/querying.py,sha256=7QvM4TS57O5kDCty6H8leWXfZxcN5ugWV-4bmdDABC0,38006
141
- langfun/core/structured/querying_test.py,sha256=AXIVamBeKvby10zogjZl_wqtBopbpud-NNEZlqfLyqY,49766
140
+ langfun/core/structured/querying.py,sha256=vE_NOLNlIe4A0DueQfyiBEUh3AsSD8Hhx2dSDHNYpYk,37976
141
+ langfun/core/structured/querying_test.py,sha256=pYWXqAnzp5eOCjU4yEPtE73iLNqxHISb3y3FaSbI7vs,49760
142
142
  langfun/core/structured/schema.py,sha256=r_ewdRMsALVOdnvGSeYBcz2-VJ_3_nMxY4GtzUHCYUU,29111
143
143
  langfun/core/structured/schema_generation.py,sha256=pEWeTd8tQWYnEHukas6GVl4uGerLsQ2aNybtnm4Qgxc,5352
144
144
  langfun/core/structured/schema_generation_test.py,sha256=RM9s71kMNg2jTePwInkiW9fK1ACN37eyPeF8OII-0zw,2950
@@ -156,8 +156,8 @@ langfun/core/templates/demonstration.py,sha256=vCrgYubdZM5Umqcgp8NUVGXgr4P_c-fik
156
156
  langfun/core/templates/demonstration_test.py,sha256=SafcDQ0WgI7pw05EmPI2S4v1t3ABKzup8jReCljHeK4,2162
157
157
  langfun/core/templates/selfplay.py,sha256=yhgrJbiYwq47TgzThmHrDQTF4nDrTI09CWGhuQPNv-s,2273
158
158
  langfun/core/templates/selfplay_test.py,sha256=Ot__1P1M8oJfoTp-M9-PQ6HUXqZKyMwvZ5f7yQ3yfyM,2326
159
- langfun-0.1.2.dev202505160805.dist-info/licenses/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
160
- langfun-0.1.2.dev202505160805.dist-info/METADATA,sha256=BClYluq7hbXEWsTxg73Tu4fYJ-PF4lUWBRtEM16UQwc,8178
161
- langfun-0.1.2.dev202505160805.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
162
- langfun-0.1.2.dev202505160805.dist-info/top_level.txt,sha256=RhlEkHxs1qtzmmtWSwYoLVJAc1YrbPtxQ52uh8Z9VvY,8
163
- langfun-0.1.2.dev202505160805.dist-info/RECORD,,
159
+ langfun-0.1.2.dev202505180804.dist-info/licenses/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
160
+ langfun-0.1.2.dev202505180804.dist-info/METADATA,sha256=DI4w_LawSCzpgClMnLKFSx8lKZrs98KY1EPtsjb0Ooo,8178
161
+ langfun-0.1.2.dev202505180804.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
162
+ langfun-0.1.2.dev202505180804.dist-info/top_level.txt,sha256=RhlEkHxs1qtzmmtWSwYoLVJAc1YrbPtxQ52uh8Z9VvY,8
163
+ langfun-0.1.2.dev202505180804.dist-info/RECORD,,