langfun 0.1.2.dev202507250804__py3-none-any.whl → 0.1.2.dev202507260804__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.

langfun/core/__init__.py CHANGED
@@ -40,6 +40,9 @@ from langfun.core.component import context
40
40
  as_context = context
41
41
  use_context = context
42
42
 
43
+ # Invoke a callable object asynchronously.
44
+ from langfun.core.async_support import invoke_async
45
+
43
46
  # Shortcut function for overriding components attributes, usually for
44
47
  # override settings.
45
48
  from langfun.core.component import use_settings
@@ -199,6 +199,24 @@ class Action(pg.Object):
199
199
  """Returns last invocation. None if the action is not executed."""
200
200
  return self._invocation
201
201
 
202
+ async def acall(
203
+ self,
204
+ session: Optional['Session'] = None,
205
+ *,
206
+ show_progress: bool = True,
207
+ verbose: bool = False,
208
+ **kwargs
209
+ ) -> Any:
210
+ """Async version of `__call__`."""
211
+ # TODO(daiyip): implement native async calling.
212
+ return await lf.invoke_async(
213
+ self.__call__,
214
+ session,
215
+ show_progress=show_progress,
216
+ verbose=verbose,
217
+ **kwargs
218
+ )
219
+
202
220
  def __call__(
203
221
  self,
204
222
  session: Optional['Session'] = None,
@@ -13,6 +13,7 @@
13
13
  # limitations under the License.
14
14
  """Tests for base action."""
15
15
 
16
+ import asyncio
16
17
  import unittest
17
18
 
18
19
  import langfun.core as lf
@@ -32,7 +33,7 @@ class Bar(action_lib.Action):
32
33
  session.add_metadata(note='bar')
33
34
  if self.simulate_action_error:
34
35
  raise ValueError('Bar error')
35
- return 2
36
+ return 2 + pg.contextual_value('baz', 0)
36
37
 
37
38
 
38
39
  class Foo(action_lib.Action):
@@ -237,6 +238,12 @@ class SessionTest(unittest.TestCase):
237
238
  json_str = session.to_json_str(save_ref_value=True)
238
239
  self.assertIsInstance(pg.from_json_str(json_str), action_lib.Session)
239
240
 
241
+ def test_acall(self):
242
+ bar = Bar()
243
+ with lf.context(baz=1):
244
+ r = bar.acall(lm=fake.StaticResponse('lm response'))
245
+ self.assertEqual(asyncio.run(r), 3)
246
+
240
247
  def test_failed_action(self):
241
248
  lm = fake.StaticResponse('lm response')
242
249
  foo = Foo(1, simulate_action_error=True)
@@ -0,0 +1,28 @@
1
+ # Copyright 2025 The Langfun Authors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """Utility for async IO in Langfun."""
15
+
16
+ import asyncio
17
+ from typing import Any, Callable
18
+ import pyglove as pg
19
+
20
+
21
+ async def invoke_async(
22
+ callable_object: Callable[..., Any], *args, **kwargs
23
+ ) -> Any:
24
+ """Invokes a callable asynchronously with `lf.context` manager enabled."""
25
+ return await asyncio.to_thread(
26
+ # Enable `lf.context` manager for async calls.
27
+ pg.with_contextual_override(callable_object), *args, **kwargs
28
+ )
@@ -0,0 +1,39 @@
1
+ # Copyright 2025 The Langfun Authors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import asyncio
16
+ import time
17
+ import unittest
18
+
19
+ from langfun.core import async_support
20
+ import pyglove as pg
21
+
22
+
23
+ class AsyncSupportTest(unittest.TestCase):
24
+
25
+ def test_invoke_async(self):
26
+
27
+ def foo(x, *, y):
28
+ time.sleep(2)
29
+ return x + y + pg.contextual_value('z', 0)
30
+
31
+ t = time.time()
32
+ r = async_support.invoke_async(foo, 1, y=2)
33
+ self.assertLess(time.time() - t, 1)
34
+ with pg.contextual_override(z=3):
35
+ self.assertEqual(asyncio.run(r), 6)
36
+
37
+
38
+ if __name__ == '__main__':
39
+ unittest.main()
@@ -24,6 +24,7 @@ import re
24
24
  import threading
25
25
  import time
26
26
  from typing import Annotated, Any, Callable, ClassVar, Iterator, Literal, Optional, Sequence, Tuple, Type, Union, final
27
+ from langfun.core import async_support
27
28
  from langfun.core import component
28
29
  from langfun.core import concurrent
29
30
  from langfun.core import console
@@ -922,6 +923,59 @@ class LanguageModel(component.Component):
922
923
  # Language model operations.
923
924
  #
924
925
 
926
+ async def asample(
927
+ self,
928
+ prompts: list[str | message_lib.Message],
929
+ *,
930
+ cache_seed: int = 0,
931
+ **kwargs,
932
+ ) -> message_lib.Message:
933
+ """Async version of sample."""
934
+ # TODO(daiyip): implement native async sampling.
935
+ return await async_support.invoke_async(
936
+ self.sample, prompts, cache_seed=cache_seed, **kwargs
937
+ )
938
+
939
+ async def acall(
940
+ self,
941
+ prompt: str | message_lib.Message,
942
+ *,
943
+ cache_seed: int = 0,
944
+ **kwargs
945
+ ) -> message_lib.Message:
946
+ """Async version of __call__."""
947
+ # TODO(daiyip): implement native async calling.
948
+ return await async_support.invoke_async(
949
+ self.__call__,
950
+ prompt,
951
+ cache_seed=cache_seed,
952
+ **kwargs
953
+ )
954
+
955
+ async def ascore(
956
+ self,
957
+ prompt: str | message_lib.Message | list[message_lib.Message],
958
+ completions: list[str | message_lib.Message],
959
+ **kwargs,
960
+ ) -> float:
961
+ """Async version of score."""
962
+ # TODO(daiyip): implement native async scoring.
963
+ return await async_support.invoke_async(
964
+ self.score,
965
+ prompt,
966
+ completions=completions,
967
+ **kwargs
968
+ )
969
+
970
+ async def atokenize(
971
+ self,
972
+ prompt: str | message_lib.Message,
973
+ **kwargs
974
+ ) -> list[int]:
975
+ """Async version of tokenize."""
976
+ # TODO(daiyip): implement native async tokenization.
977
+ return await async_support.invoke_async(self.tokenize, prompt, **kwargs)
978
+
925
979
  def sample(
926
980
  self,
927
981
  prompts: list[str | message_lib.Message],
@@ -13,6 +13,7 @@
13
13
  # limitations under the License.
14
14
  """Tests for language model."""
15
15
 
16
+ import asyncio
16
17
  import contextlib
17
18
  import io
18
19
  import unittest
@@ -436,6 +437,14 @@ class LanguageModelTest(unittest.TestCase):
436
437
  ]
437
438
  )
438
439
 
440
+ def test_sample_async(self):
441
+ lm = MockModel(top_k=1)
442
+ response = asyncio.run(lm.asample(['foo', 'bar']))
443
+ self.assertIsInstance(response, list)
444
+ self.assertEqual(len(response), 2)
445
+ self.assertIsInstance(response[0], lm_lib.LMSamplingResult)
446
+ self.assertIsInstance(response[1], lm_lib.LMSamplingResult)
447
+
439
448
  def test_call(self):
440
449
  lm = MockModel(sampling_options=lm_lib.LMSamplingOptions(top_k=1))
441
450
  response = lm(prompt='foo')
@@ -453,6 +462,11 @@ class LanguageModelTest(unittest.TestCase):
453
462
  # Test override individual flags within sampling_options.
454
463
  self.assertEqual(lm('foo', top_k=2), 'foo' * 2)
455
464
 
465
+ def test_acall(self):
466
+ lm = MockModel(sampling_options=lm_lib.LMSamplingOptions(top_k=1))
467
+ response = asyncio.run(lm.acall(prompt='foo'))
468
+ self.assertEqual(response.text, 'foo')
469
+
456
470
  def test_using_cache(self):
457
471
  cache = in_memory.InMemory()
458
472
  lm = MockModel(cache=cache, top_k=1)
@@ -765,6 +779,21 @@ class LanguageModelTest(unittest.TestCase):
765
779
  if debug_mode & lm_lib.LMDebugMode.PROMPT:
766
780
  self.assertIn('[0] MODALITY OBJECTS SENT TO LM', debug_info)
767
781
 
782
+ def test_ascore(self):
783
+ lm = MockScoringModel()
784
+ self.assertEqual(
785
+ asyncio.run(
786
+ lm.ascore(
787
+ message_lib.UserMessage('hi'),
788
+ ['1', '2']
789
+ )
790
+ ),
791
+ [
792
+ lm_lib.LMScoringResult(score=-0.0),
793
+ lm_lib.LMScoringResult(score=-1.0),
794
+ ],
795
+ )
796
+
768
797
  def test_score_with_unmatched_prompt_and_completions(self):
769
798
  with self.assertRaises(ValueError):
770
799
  MockScoringModel().score(['hi',], ['1', '2', '3'])
@@ -828,6 +857,17 @@ class LanguageModelTest(unittest.TestCase):
828
857
  if debug_mode & lm_lib.LMDebugMode.PROMPT:
829
858
  self.assertIn('[0] MODALITY OBJECTS SENT TO LM', debug_info)
830
859
 
860
+ def test_atokenize(self):
861
+ lm = MockTokenizeModel()
862
+ self.assertEqual(
863
+ asyncio.run(
864
+ lm.atokenize(
865
+ message_lib.UserMessage('hi')
866
+ )
867
+ ),
868
+ [('hi', 0)],
869
+ )
870
+
831
871
  def test_tokenize_with_unsupported_model(self):
832
872
  with self.assertRaises(NotImplementedError):
833
873
  MockModel().tokenize('hi')
@@ -51,13 +51,16 @@ from langfun.core.structured.mapping import MappingError
51
51
  from langfun.core.structured.mapping import MappingExample
52
52
 
53
53
  from langfun.core.structured.parsing import parse
54
+ from langfun.core.structured.parsing import aparse
54
55
  from langfun.core.structured.parsing import call
56
+ from langfun.core.structured.parsing import acall
55
57
 
56
58
  from langfun.core.structured.querying import track_queries
57
59
  from langfun.core.structured.querying import QueryInvocation
58
60
 
59
61
  from langfun.core.structured.querying import LfQuery
60
62
  from langfun.core.structured.querying import query
63
+ from langfun.core.structured.querying import aquery
61
64
  from langfun.core.structured.querying import query_and_reduce
62
65
  from langfun.core.structured.querying import query_protocol
63
66
 
@@ -67,10 +70,14 @@ from langfun.core.structured.querying import query_reward
67
70
 
68
71
  from langfun.core.structured.description import describe
69
72
  from langfun.core.structured.completion import complete
73
+ from langfun.core.structured.completion import acomplete
70
74
 
71
75
  from langfun.core.structured.scoring import score
76
+ from langfun.core.structured.scoring import ascore
72
77
 
73
78
  from langfun.core.structured.tokenization import tokenize
79
+ from langfun.core.structured.tokenization import atokenize
80
+
74
81
 
75
82
  # Expose default examples for structured operations so users could refer to
76
83
  # them.
@@ -251,3 +251,31 @@ def complete(
251
251
 
252
252
  output = t(lm=lm, cache_seed=cache_seed, autofix_lm=autofix_lm or lm)
253
253
  return output if returns_message else output.result
254
+
255
+
256
+ async def acomplete(
257
+ input_value: pg.Symbolic,
258
+ default: Any = lf.RAISE_IF_HAS_ERROR,
259
+ *,
260
+ lm: lf.LanguageModel | None = None,
261
+ examples: list[mapping.MappingExample] | None = None,
262
+ cache_seed: int | None = 0,
263
+ autofix: int = 0,
264
+ autofix_lm: lf.LanguageModel | None = None,
265
+ returns_message: bool = False,
266
+ **kwargs,
267
+ ) -> Any:
268
+ """Async version of `lf.complete`."""
269
+ # TODO(daiyip): implement native async completion.
270
+ return await lf.invoke_async(
271
+ complete,
272
+ input_value,
273
+ default,
274
+ lm=lm,
275
+ examples=examples,
276
+ cache_seed=cache_seed,
277
+ autofix=autofix,
278
+ autofix_lm=autofix_lm,
279
+ returns_message=returns_message,
280
+ **kwargs
281
+ )
@@ -13,6 +13,7 @@
13
13
  # limitations under the License.
14
14
  """Tests for langfun.core.structured.completion."""
15
15
 
16
+ import asyncio
16
17
  import inspect
17
18
  import unittest
18
19
 
@@ -620,6 +621,41 @@ class CompleteStructureTest(unittest.TestCase):
620
621
  ):
621
622
  self.assertIsNone(completion.complete(Activity.partial(), None))
622
623
 
624
+ def test_acomplete(self):
625
+ response = """
626
+ ```python
627
+ TripPlan(
628
+ place='San Francisco',
629
+ itineraries=[
630
+ Itinerary(
631
+ day=1,
632
+ type='daytime',
633
+ activities=[
634
+ Activity(description='Arrive in San Francisco and check into your hotel.'),
635
+ Activity(description='Take a walk around Fisherman\\'s Wharf and have dinner at one of the many seafood restaurants.'),
636
+ Activity(description='Visit Pier 39 and see the sea lions.'),
637
+ ],
638
+ ),
639
+ ]
640
+ )
641
+ ```
642
+ """
643
+ with lf.context(
644
+ lm=fake.StaticSequence(
645
+ [response],
646
+ ),
647
+ override_attrs=True,
648
+ ):
649
+ r = completion.acomplete(
650
+ TripPlan.partial(
651
+ place='San Francisco',
652
+ itineraries=[
653
+ Itinerary.partial(day=1),
654
+ ],
655
+ )
656
+ )
657
+ self.assertIsInstance(asyncio.run(r), TripPlan)
658
+
623
659
 
624
660
  if __name__ == '__main__':
625
661
  unittest.main()
@@ -12,6 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
  """Symbolic parsing."""
15
+
15
16
  from typing import Any, Callable, Type, Union
16
17
 
17
18
  import langfun.core as lf
@@ -183,6 +184,44 @@ def parse(
183
184
  return output if returns_message else output.result
184
185
 
185
186
 
187
+ async def aparse(
188
+ message: Union[lf.Message, str],
189
+ schema: Union[
190
+ schema_lib.Schema, Type[Any], list[Type[Any]], dict[str, Any]
191
+ ],
192
+ default: Any = lf.RAISE_IF_HAS_ERROR,
193
+ *,
194
+ user_prompt: str | None = None,
195
+ lm: lf.LanguageModel | None = None,
196
+ examples: list[mapping.MappingExample] | None = None,
197
+ include_context: bool = False,
198
+ cache_seed: int | None = 0,
199
+ autofix: int = 0,
200
+ autofix_lm: lf.LanguageModel | None = None,
201
+ protocol: schema_lib.SchemaProtocol = 'python',
202
+ returns_message: bool = False,
203
+ **kwargs,
204
+ ) -> Any:
205
+ """Async version of `lf.parse`."""
206
+ # TODO(daiyip): implement native async parsing.
207
+ return await lf.invoke_async(
208
+ parse,
209
+ message,
210
+ schema,
211
+ default,
212
+ user_prompt=user_prompt,
213
+ lm=lm,
214
+ examples=examples,
215
+ include_context=include_context,
216
+ cache_seed=cache_seed,
217
+ autofix=autofix,
218
+ autofix_lm=autofix_lm,
219
+ protocol=protocol,
220
+ returns_message=returns_message,
221
+ **kwargs
222
+ )
223
+
224
+
186
225
  def call(
187
226
  prompt: str | lf.Template,
188
227
  schema: Union[
@@ -298,6 +337,44 @@ def call(
298
337
  return parsing_message if returns_message else parsing_message.result
299
338
 
300
339
 
340
+ async def acall(
341
+ prompt: str | lf.Template,
342
+ schema: Union[
343
+ None, schema_lib.Schema, Type[Any], list[Type[Any]], dict[str, Any]
344
+ ] = None,
345
+ *,
346
+ lm: lf.LanguageModel | None = None,
347
+ parsing_lm: lf.LanguageModel | None = None,
348
+ parsing_examples: list[mapping.MappingExample] | None = None,
349
+ parsing_include_context: bool = False,
350
+ cache_seed: int | None = 0,
351
+ autofix: int = 0,
352
+ autofix_lm: lf.LanguageModel | None = None,
353
+ response_postprocess: Callable[[str], str] | None = None,
354
+ protocol: schema_lib.SchemaProtocol = 'python',
355
+ returns_message: bool = False,
356
+ **kwargs,
357
+ ) -> Any:
358
+ """Async version of `lf.call`."""
359
+ # TODO(daiyip): implement native async calling.
360
+ return await lf.invoke_async(
361
+ call,
362
+ prompt,
363
+ schema,
364
+ lm=lm,
365
+ parsing_lm=parsing_lm,
366
+ parsing_examples=parsing_examples,
367
+ parsing_include_context=parsing_include_context,
368
+ cache_seed=cache_seed,
369
+ autofix=autofix,
370
+ autofix_lm=autofix_lm,
371
+ response_postprocess=response_postprocess,
372
+ protocol=protocol,
373
+ returns_message=returns_message,
374
+ **kwargs
375
+ )
376
+
377
+
301
378
  def _parse_structure_cls(
302
379
  protocol: schema_lib.SchemaProtocol,
303
380
  ) -> Type[_ParseStructure]:
@@ -13,6 +13,7 @@
13
13
  # limitations under the License.
14
14
  """Tests for structured parsing."""
15
15
 
16
+ import asyncio
16
17
  import inspect
17
18
  import unittest
18
19
 
@@ -291,6 +292,10 @@ class ParseStructurePythonTest(unittest.TestCase):
291
292
  ),
292
293
  )
293
294
 
295
+ def test_aparse(self):
296
+ with lf.context(lm=fake.StaticResponse('1')):
297
+ self.assertEqual(asyncio.run(parsing.aparse('the answer is 1', int)), 1)
298
+
294
299
 
295
300
  class ParseStructureJsonTest(unittest.TestCase):
296
301
 
@@ -583,6 +588,16 @@ class CallTest(unittest.TestCase):
583
588
  ):
584
589
  self.assertEqual(parsing.call('Compute 1 + 2'), 'three')
585
590
 
591
+ def test_acall(self):
592
+ with lf.context(
593
+ lm=fake.StaticMapping({
594
+ 'Compute 1 + 2': 'three',
595
+ })
596
+ ):
597
+ self.assertEqual(
598
+ asyncio.run(parsing.acall('Compute 1 + 2')), 'three'
599
+ )
600
+
586
601
  def test_call_with_template_str(self):
587
602
  with lf.context(
588
603
  lm=fake.StaticMapping({
@@ -666,6 +666,48 @@ def query(
666
666
  return output_message.text if schema in (None, str) else output_message.result
667
667
 
668
668
 
669
+ async def aquery(
670
+ prompt: Union[str, lf.Template, Any],
671
+ schema: schema_lib.SchemaType | None = None,
672
+ default: Any = lf.RAISE_IF_HAS_ERROR,
673
+ *,
674
+ lm: lf.LanguageModel | list[lf.LanguageModel] | None = None,
675
+ num_samples: int | list[int] = 1,
676
+ system_message: str | lf.Template | None = None,
677
+ examples: list[mapping.MappingExample] | None = None,
678
+ cache_seed: int | None = 0,
679
+ response_postprocess: Callable[[str], str] | None = None,
680
+ autofix: int = 0,
681
+ autofix_lm: lf.LanguageModel | None = None,
682
+ protocol: str | None = None,
683
+ returns_message: bool = False,
684
+ skip_lm: bool = False,
685
+ invocation_id: str | None = None,
686
+ **kwargs,
687
+ ) -> Any:
688
+ """Async version of `lf.query`."""
689
+ # TODO(daiyip): implement native async querying.
690
+ return await lf.invoke_async(
691
+ query,
692
+ prompt,
693
+ schema,
694
+ default,
695
+ lm=lm,
696
+ num_samples=num_samples,
697
+ system_message=system_message,
698
+ examples=examples,
699
+ cache_seed=cache_seed,
700
+ response_postprocess=response_postprocess,
701
+ autofix=autofix,
702
+ autofix_lm=autofix_lm,
703
+ protocol=protocol,
704
+ returns_message=returns_message,
705
+ skip_lm=skip_lm,
706
+ invocation_id=invocation_id,
707
+ **kwargs
708
+ )
709
+
710
+
669
711
  @contextlib.contextmanager
670
712
  def query_protocol(protocol: str) -> Iterator[None]:
671
713
  """Context manager for setting the query protocol for the scope."""
@@ -13,6 +13,7 @@
13
13
  # limitations under the License.
14
14
  """Tests for structured query."""
15
15
 
16
+ import asyncio
16
17
  import inspect
17
18
  import math
18
19
  import time
@@ -1336,6 +1337,15 @@ class LfQueryJsonV1Test(unittest.TestCase):
1336
1337
  querying.query('what is 1 + 0', int, lm=lm), 1
1337
1338
  )
1338
1339
 
1340
+ def test_aquery(self):
1341
+ with lf.context(lm=fake.StaticResponse('{"result": 1}')):
1342
+ self.assertEqual(
1343
+ asyncio.run(
1344
+ querying.aquery('what is 1 + 0', int, protocol='json')
1345
+ ),
1346
+ 1
1347
+ )
1348
+
1339
1349
 
1340
1350
  class QueryInvocationTest(unittest.TestCase):
1341
1351
 
@@ -179,3 +179,31 @@ def _get_first_oneof(value: Any) -> pg.hyper.OneOf:
179
179
  pg.traverse(value, select_oneofs)
180
180
  assert oneofs
181
181
  return oneofs[0]
182
+
183
+
184
+ async def ascore(
185
+ prompt: Union[str, pg.Symbolic] | list[str | pg.Symbolic],
186
+ completions: list[str | pg.Symbolic],
187
+ schema: Union[
188
+ schema_lib.Schema, Type[Any], list[Type[Any]], dict[str, Any], None
189
+ ] = None,
190
+ *,
191
+ lm: lf.LanguageModel | None = None,
192
+ examples: list[mapping.MappingExample] | None = None,
193
+ protocol: schema_lib.SchemaProtocol = 'python',
194
+ return_scoring_results: bool = False,
195
+ **kwargs,
196
+ ) -> list[float] | list[lf.LMScoringResult]:
197
+ """Async version of `lf.score`."""
198
+ # TODO(daiyip): implement native async scoring.
199
+ return await lf.invoke_async(
200
+ score,
201
+ prompt,
202
+ completions,
203
+ schema=schema,
204
+ lm=lm,
205
+ examples=examples,
206
+ protocol=protocol,
207
+ return_scoring_results=return_scoring_results,
208
+ **kwargs,
209
+ )
@@ -12,6 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ import asyncio
15
16
  import unittest
16
17
  import langfun.core as lf
17
18
  from langfun.core.llms import fake
@@ -50,6 +51,13 @@ class ScoringTest(unittest.TestCase):
50
51
  def test_score(self):
51
52
  self.assertEqual(scoring.score('hi', [1, 2], lm=fake.Echo()), [0.0, -1.0])
52
53
 
54
+ def test_ascore(self):
55
+ with lf.context(lm=fake.Echo()):
56
+ self.assertEqual(
57
+ asyncio.run(scoring.ascore('hi', [1, 2], lm=fake.Echo())),
58
+ [0.0, -1.0]
59
+ )
60
+
53
61
  def test_score_on_field_values(self):
54
62
  self.assertEqual(
55
63
  scoring.score(
@@ -62,3 +62,27 @@ def tokenize(
62
62
  lm = lm_override.value
63
63
 
64
64
  return lm.tokenize(input_message)
65
+
66
+
67
+ async def atokenize(
68
+ prompt: Union[str, pg.Symbolic] | list[str | pg.Symbolic],
69
+ schema: Union[
70
+ schema_lib.Schema, Type[Any], list[Type[Any]], dict[str, Any], None
71
+ ] = None,
72
+ *,
73
+ lm: lf.LanguageModel | None = None,
74
+ examples: list[mapping.MappingExample] | None = None,
75
+ protocol: schema_lib.SchemaProtocol = 'python',
76
+ **kwargs,
77
+ ) -> list[tuple[str | bytes, int]]:
78
+ """Async version of `lf.tokenize`."""
79
+ # TODO(daiyip): implement native async tokenization.
80
+ return await lf.invoke_async(
81
+ tokenize,
82
+ prompt,
83
+ schema,
84
+ lm=lm,
85
+ examples=examples,
86
+ protocol=protocol,
87
+ **kwargs,
88
+ )
@@ -12,6 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ import asyncio
15
16
  import unittest
16
17
  import langfun.core as lf
17
18
  from langfun.core.llms import fake
@@ -36,6 +37,13 @@ class TokenizationTest(unittest.TestCase):
36
37
  [('hi', 0)]
37
38
  )
38
39
 
40
+ def test_atokenize(self):
41
+ with lf.context(lm=fake.Echo()):
42
+ self.assertEqual(
43
+ asyncio.run(tokenization.atokenize('hi')),
44
+ [('hi', 0)]
45
+ )
46
+
39
47
  def test_tokenize_with_lm_from_the_context(self):
40
48
  with lf.context(lm=fake.Echo()):
41
49
  self.assertEqual(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langfun
3
- Version: 0.1.2.dev202507250804
3
+ Version: 0.1.2.dev202507260804
4
4
  Summary: Langfun: Language as Functions.
5
5
  Home-page: https://github.com/google/langfun
6
6
  Author: Langfun Authors
@@ -1,5 +1,7 @@
1
1
  langfun/__init__.py,sha256=krEJ1lyDkNARsacY6nBQpD3bQrFi4fifD-FwpwPbFPM,2635
2
- langfun/core/__init__.py,sha256=pW4prpiyWNkRbtWBGYF1thn7_0F_TgDVfAIZPvGn6HA,4758
2
+ langfun/core/__init__.py,sha256=lZQNVBzQa5d6kQFHRwRg9zZqPaEC_-PwAV-73k4fzR4,4854
3
+ langfun/core/async_support.py,sha256=Mzqze88WqWBRRcBVJEQ4H1jRgLwUP43acI0NZ7unZ7M,1022
4
+ langfun/core/async_support_test.py,sha256=lZ4rZ-kWlc94lezTajOVo2OQbxWiHfF6KhKOfMGzELQ,1094
3
5
  langfun/core/component.py,sha256=g1kQM0bryYYYWVDrSMnHfc74wIBbpfe5_B3s-UIP5GE,3028
4
6
  langfun/core/component_test.py,sha256=0CxTgjAud3aj8wBauFhG2FHDqrxCTl4OI4gzQTad-40,9254
5
7
  langfun/core/concurrent.py,sha256=zY-pXqlGqss_GI20tM1gXvyW8QepVPUuFNmutcIdhbI,32760
@@ -8,8 +10,8 @@ langfun/core/console.py,sha256=cLQEf84aDxItA9fStJV22xJch0TqFLNf9hLqwJ0RHmU,2652
8
10
  langfun/core/console_test.py,sha256=pBOcuNMJdVELywvroptfcRtJMsegMm3wSlHAL2TdxVk,1679
9
11
  langfun/core/langfunc.py,sha256=G50YgoVZ0y1GFw2ev41MlOqr6qa8YakbvNC0h_E0PiA,11140
10
12
  langfun/core/langfunc_test.py,sha256=CDn-gJCa5EnjN7cotAVCfSCbuzddq2o-HzEt7kV8HbY,8882
11
- langfun/core/language_model.py,sha256=5i0Je5526JO2YY6qExi6Yf7VQVgSVeZIKOjt3I8kxqQ,49573
12
- langfun/core/language_model_test.py,sha256=9EofP3_gTH28SNWiOKzTUYMHH0EYtbi9xGuT1KZT1XU,37330
13
+ langfun/core/language_model.py,sha256=T3Gyb0-S4uRunO9EotTN5-86Dc3Bw6tE4Db43qDMqOc,51042
14
+ langfun/core/language_model_test.py,sha256=aJWn3UJm_S6U7VhU7EVXdJHPe1xza5glngPkRGtx280,38426
13
15
  langfun/core/logging.py,sha256=7IGAhp7mGokZxxqtL-XZvFLKaZ5k3F5_Xp2NUtR4GwE,9136
14
16
  langfun/core/logging_test.py,sha256=vbVGOQxwMmVSiFfbt2897gUt-8nqDpV64jCAeUG_q5U,6924
15
17
  langfun/core/memory.py,sha256=vyXVvfvSdLLJAzdIupnbn3k26OgclCx-OJ7gddS5e1Y,2070
@@ -26,10 +28,10 @@ langfun/core/subscription_test.py,sha256=Y4ZdbZEwm83YNZBxHff0QR4QUa4rdaNXA3_jfIc
26
28
  langfun/core/template.py,sha256=jNhYSrbLIn9kZOa03w5QZbyjgfnzJzE_ZrrMvvWY4t4,24929
27
29
  langfun/core/template_test.py,sha256=AQv_m9qE93WxhEhSlm1xaBgB4hu0UVtA53dljngkUW0,17090
28
30
  langfun/core/agentic/__init__.py,sha256=qR3jlfUO4rhIoYdRDLz-d22YZf3FvU4FW88vsjiGDQQ,1224
29
- langfun/core/agentic/action.py,sha256=ngBN__OUjMrw4eg8ljHKQ7VY-EABW8T7gF1nw_ZkQmM,50673
31
+ langfun/core/agentic/action.py,sha256=HvCaYb3x9tpa0xhDuFtEGyZ9du_edDpIdaQYPPo87ts,51097
30
32
  langfun/core/agentic/action_eval.py,sha256=YTilyUEkJl_8FVMgdfO17PurWWaEJ6oA15CuefJJRLk,4887
31
33
  langfun/core/agentic/action_eval_test.py,sha256=7AkOwNbUX-ZgR1R0a7bvUZ5abNTUV7blf_8Mnrwb-II,2811
32
- langfun/core/agentic/action_test.py,sha256=46piw5J7vGwmJGjmVG13HQRBmp5TLgkV_ymJ2EQVEIc,15867
34
+ langfun/core/agentic/action_test.py,sha256=5ZUCbyuJDwNCUE_hl4qt5epzQQTRdZEYN5W8J2iKRQo,16084
33
35
  langfun/core/coding/__init__.py,sha256=5utju_fwEsImaiftx4oXKl9FAM8p281k8-Esdh_-m1w,835
34
36
  langfun/core/coding/python/__init__.py,sha256=yTXm92oLpQb4A-fZ2qy-bzfhPYND7B-oidtbv1PNaX0,1678
35
37
  langfun/core/coding/python/correction.py,sha256=4PD76Xfv36Xrm8Ji3-GgGDNImtcDqWfMw3z6ircJMlM,7285
@@ -126,27 +128,27 @@ langfun/core/modalities/pdf.py,sha256=mfaeCbUA4JslFVTARiJh8hW7imvL4tLVw9gUhO5bAZ
126
128
  langfun/core/modalities/pdf_test.py,sha256=ulZ0FbnlsU0wkrdckJ4ONZPTYRyMPO9Aob1UO6FXygk,1950
127
129
  langfun/core/modalities/video.py,sha256=vI9apcHIHGyp90i34Srg7S3G6IBDtDCk8qiXhwRQmkw,967
128
130
  langfun/core/modalities/video_test.py,sha256=7OXZoohKMYjt7vrJUdPb553HLyl1oBOKRgzBePFv68Q,2042
129
- langfun/core/structured/__init__.py,sha256=xWO1RO-gy12REgiPn4oWWALZxJhHtBOOdDsawKN_SfY,3334
130
- langfun/core/structured/completion.py,sha256=yW95Yd4wbt964I5wIyPUtIVeeqeZbA6HidLgN0ZpWm0,8110
131
- langfun/core/structured/completion_test.py,sha256=VtYfI3ciVSSWbi8x3l1WwpWK-Ofn2DMHYEEqm2uTzhw,19314
131
+ langfun/core/structured/__init__.py,sha256=uc9f2DaXcbPRU35CgTpObub6hsnxDCHx-4s149qnzJ0,3655
132
+ langfun/core/structured/completion.py,sha256=B0PHqBucu-keexJUa5g0F9fu57DlLtWDhZzJ-OD4VrE,8823
133
+ langfun/core/structured/completion_test.py,sha256=-SGcMgtLuS6RQB8gFh18dUkSMQMDWKZGmBkPsAYHApQ,20348
132
134
  langfun/core/structured/description.py,sha256=6BztYOiucPkF4CrTQtPLPJo1gN2dwnKmaJW83GBf4H0,5213
133
135
  langfun/core/structured/description_test.py,sha256=UxaXnKKP7TnyPDPUyf3U-zPE0TvLlIP6DGr8thjcePw,7365
134
136
  langfun/core/structured/function_generation.py,sha256=g7AOR_e8HxFU6n6Df750aGkgMgV1KExLZMAz0yd5Agg,8555
135
137
  langfun/core/structured/function_generation_test.py,sha256=LaXYDXf9GlqUrR6v_gtmK_H4kxzonmU7SYbn7XXMgjU,12128
136
138
  langfun/core/structured/mapping.py,sha256=1YBW8PKpJKXS7DKukfzKNioL84PrKUcB4KOUudrQ20w,14374
137
139
  langfun/core/structured/mapping_test.py,sha256=OntYvfDitAf0tAnzQty3YS90vyEn6FY1Mi93r_ViEk8,9594
138
- langfun/core/structured/parsing.py,sha256=MGvI7ypXlwfzr5XB8_TFU9Ei0_5reYqkWkv64eAy0EA,12015
139
- langfun/core/structured/parsing_test.py,sha256=V8Cj1tJK4Lxv_b0YQj6-2hzXZgnYNBa2JR7rOLRBKoQ,22346
140
- langfun/core/structured/querying.py,sha256=vE_NOLNlIe4A0DueQfyiBEUh3AsSD8Hhx2dSDHNYpYk,37976
141
- langfun/core/structured/querying_test.py,sha256=Q0HwmbUI9BqMaeN8vgn_EvX29CzfcomGIKVqKJ6dZyY,50212
140
+ langfun/core/structured/parsing.py,sha256=bLi7o1AdyDWc6TwxmYg70t_oTgmLkJWBafakdF8n2RI,14195
141
+ langfun/core/structured/parsing_test.py,sha256=vRfCSzA9q7C1cElkAnDvbRepULEa_vclqDIv-heypDw,22745
142
+ langfun/core/structured/querying.py,sha256=LV7ZCiVx2ef1Qx_ONwexzSvCSBSq1V41E8RdxHDGP-g,39225
143
+ langfun/core/structured/querying_test.py,sha256=klj9OmLKzJbsTYSil58Lex_PVaIlt3ngWQziibg9i4g,50464
142
144
  langfun/core/structured/schema.py,sha256=xtgrr3t5tcYQ2gi_fkTKz2IgDMf84gpiykmBdfnV6Io,29486
143
145
  langfun/core/structured/schema_generation.py,sha256=pEWeTd8tQWYnEHukas6GVl4uGerLsQ2aNybtnm4Qgxc,5352
144
146
  langfun/core/structured/schema_generation_test.py,sha256=RM9s71kMNg2jTePwInkiW9fK1ACN37eyPeF8OII-0zw,2950
145
147
  langfun/core/structured/schema_test.py,sha256=H42ZZdPi8CIv7WzrnXwMwQQaPQxlmDSY31pfqQs-Xqw,26567
146
- langfun/core/structured/scoring.py,sha256=Y7Jqs5VVjUQLF_9Z1uIY_dw5zasv2FF52Cz-cxGMsro,5857
147
- langfun/core/structured/scoring_test.py,sha256=QvlwDAzwuamKL5tCotm1L3Sx0cs3idoNK4aIEhaO4Yk,2272
148
- langfun/core/structured/tokenization.py,sha256=-b4_693quHeYn2AqndwucuXNmhd5NVXVTU3mmDane98,2189
149
- langfun/core/structured/tokenization_test.py,sha256=dVW30kGYkX2HNtiRZe1oTmXFP7iIK6PrlKCttZ3QXe4,1311
148
+ langfun/core/structured/scoring.py,sha256=59B6zJt190EtwT2aIgVvCL7X1k8Nk5d1m0OSI4qbBqk,6671
149
+ langfun/core/structured/scoring_test.py,sha256=msxtZX1MWgoLTWkmM-McbUo-qGev0uDdlXLm4kPiIiE,2473
150
+ langfun/core/structured/tokenization.py,sha256=zAfzS8OOjMEz_GqGiTs3GGplPEwvkdCb_EoGF96Lwz4,2845
151
+ langfun/core/structured/tokenization_test.py,sha256=8IXndRokZmlLPZD_jIitfhgcRxBjmG09PhT-WLHe9dw,1499
150
152
  langfun/core/templates/__init__.py,sha256=bO0eMsVJbi7sxEB2YlInKRQ2EVP-RyyKUwcD-8msuN4,927
151
153
  langfun/core/templates/completion.py,sha256=mUqZHOEV3ag6-A08XghpeEltcrBvCDxXP004eDDfeag,1931
152
154
  langfun/core/templates/completion_test.py,sha256=vGnjnM38UHyVDUyaUYtmp20s9KBGOdbPVsX-H-ET11E,1636
@@ -156,8 +158,8 @@ langfun/core/templates/demonstration.py,sha256=vCrgYubdZM5Umqcgp8NUVGXgr4P_c-fik
156
158
  langfun/core/templates/demonstration_test.py,sha256=SafcDQ0WgI7pw05EmPI2S4v1t3ABKzup8jReCljHeK4,2162
157
159
  langfun/core/templates/selfplay.py,sha256=yhgrJbiYwq47TgzThmHrDQTF4nDrTI09CWGhuQPNv-s,2273
158
160
  langfun/core/templates/selfplay_test.py,sha256=Ot__1P1M8oJfoTp-M9-PQ6HUXqZKyMwvZ5f7yQ3yfyM,2326
159
- langfun-0.1.2.dev202507250804.dist-info/licenses/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
160
- langfun-0.1.2.dev202507250804.dist-info/METADATA,sha256=OijvzDGb01eLWEje73bqNewaGsyvQVLL8E-QFoOF3GU,7380
161
- langfun-0.1.2.dev202507250804.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
162
- langfun-0.1.2.dev202507250804.dist-info/top_level.txt,sha256=RhlEkHxs1qtzmmtWSwYoLVJAc1YrbPtxQ52uh8Z9VvY,8
163
- langfun-0.1.2.dev202507250804.dist-info/RECORD,,
161
+ langfun-0.1.2.dev202507260804.dist-info/licenses/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
162
+ langfun-0.1.2.dev202507260804.dist-info/METADATA,sha256=9grI0Yk9pnRLTDke08_k9my8IkhFJsPY72qg2xGRxPA,7380
163
+ langfun-0.1.2.dev202507260804.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
164
+ langfun-0.1.2.dev202507260804.dist-info/top_level.txt,sha256=RhlEkHxs1qtzmmtWSwYoLVJAc1YrbPtxQ52uh8Z9VvY,8
165
+ langfun-0.1.2.dev202507260804.dist-info/RECORD,,