langfun 0.0.2.dev20240429__py3-none-any.whl → 0.1.2.dev202501150804__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.
Files changed (144) hide show
  1. langfun/__init__.py +20 -2
  2. langfun/core/__init__.py +16 -5
  3. langfun/core/agentic/__init__.py +30 -0
  4. langfun/core/agentic/action.py +854 -0
  5. langfun/core/agentic/action_eval.py +150 -0
  6. langfun/core/agentic/action_eval_test.py +109 -0
  7. langfun/core/agentic/action_test.py +136 -0
  8. langfun/core/coding/python/__init__.py +5 -11
  9. langfun/core/coding/python/correction.py +37 -21
  10. langfun/core/coding/python/correction_test.py +29 -3
  11. langfun/core/coding/python/execution.py +40 -216
  12. langfun/core/coding/python/execution_test.py +29 -89
  13. langfun/core/coding/python/generation.py +21 -11
  14. langfun/core/coding/python/generation_test.py +2 -2
  15. langfun/core/coding/python/parsing.py +108 -193
  16. langfun/core/coding/python/parsing_test.py +2 -105
  17. langfun/core/component.py +63 -2
  18. langfun/core/component_test.py +53 -0
  19. langfun/core/concurrent.py +414 -117
  20. langfun/core/concurrent_test.py +111 -24
  21. langfun/core/console.py +17 -5
  22. langfun/core/console_test.py +17 -0
  23. langfun/core/eval/__init__.py +16 -1
  24. langfun/core/eval/base.py +622 -174
  25. langfun/core/eval/base_test.py +200 -54
  26. langfun/core/eval/matching.py +63 -76
  27. langfun/core/eval/matching_test.py +17 -8
  28. langfun/core/eval/patching.py +130 -0
  29. langfun/core/eval/patching_test.py +170 -0
  30. langfun/core/eval/scoring.py +26 -26
  31. langfun/core/eval/scoring_test.py +19 -2
  32. langfun/core/eval/v2/__init__.py +42 -0
  33. langfun/core/eval/v2/checkpointing.py +380 -0
  34. langfun/core/eval/v2/checkpointing_test.py +228 -0
  35. langfun/core/eval/v2/eval_test_helper.py +136 -0
  36. langfun/core/eval/v2/evaluation.py +725 -0
  37. langfun/core/eval/v2/evaluation_test.py +180 -0
  38. langfun/core/eval/v2/example.py +305 -0
  39. langfun/core/eval/v2/example_test.py +128 -0
  40. langfun/core/eval/v2/experiment.py +1048 -0
  41. langfun/core/eval/v2/experiment_test.py +433 -0
  42. langfun/core/eval/v2/metric_values.py +156 -0
  43. langfun/core/eval/v2/metric_values_test.py +80 -0
  44. langfun/core/eval/v2/metrics.py +357 -0
  45. langfun/core/eval/v2/metrics_test.py +203 -0
  46. langfun/core/eval/v2/progress.py +348 -0
  47. langfun/core/eval/v2/progress_test.py +82 -0
  48. langfun/core/eval/v2/progress_tracking.py +210 -0
  49. langfun/core/eval/v2/progress_tracking_test.py +66 -0
  50. langfun/core/eval/v2/reporting.py +270 -0
  51. langfun/core/eval/v2/reporting_test.py +158 -0
  52. langfun/core/eval/v2/runners.py +488 -0
  53. langfun/core/eval/v2/runners_test.py +334 -0
  54. langfun/core/langfunc.py +4 -17
  55. langfun/core/langfunc_test.py +22 -6
  56. langfun/core/language_model.py +577 -39
  57. langfun/core/language_model_test.py +470 -56
  58. langfun/core/llms/__init__.py +87 -16
  59. langfun/core/llms/anthropic.py +312 -87
  60. langfun/core/llms/anthropic_test.py +71 -3
  61. langfun/core/llms/cache/base.py +21 -2
  62. langfun/core/llms/cache/in_memory.py +13 -0
  63. langfun/core/llms/cache/in_memory_test.py +53 -2
  64. langfun/core/llms/compositional.py +101 -0
  65. langfun/core/llms/compositional_test.py +73 -0
  66. langfun/core/llms/deepseek.py +117 -0
  67. langfun/core/llms/deepseek_test.py +61 -0
  68. langfun/core/llms/fake.py +11 -7
  69. langfun/core/llms/fake_test.py +14 -0
  70. langfun/core/llms/gemini.py +507 -0
  71. langfun/core/llms/gemini_test.py +195 -0
  72. langfun/core/llms/google_genai.py +62 -218
  73. langfun/core/llms/google_genai_test.py +9 -202
  74. langfun/core/llms/groq.py +160 -144
  75. langfun/core/llms/groq_test.py +31 -137
  76. langfun/core/llms/llama_cpp.py +15 -42
  77. langfun/core/llms/llama_cpp_test.py +4 -30
  78. langfun/core/llms/openai.py +395 -203
  79. langfun/core/llms/openai_compatible.py +179 -0
  80. langfun/core/llms/openai_compatible_test.py +495 -0
  81. langfun/core/llms/openai_test.py +30 -395
  82. langfun/core/llms/rest.py +113 -0
  83. langfun/core/llms/rest_test.py +111 -0
  84. langfun/core/llms/vertexai.py +192 -0
  85. langfun/core/llms/vertexai_test.py +52 -0
  86. langfun/core/logging.py +284 -0
  87. langfun/core/logging_test.py +125 -0
  88. langfun/core/message.py +319 -9
  89. langfun/core/message_test.py +190 -13
  90. langfun/core/modalities/__init__.py +6 -2
  91. langfun/core/modalities/audio.py +30 -0
  92. langfun/core/modalities/audio_test.py +63 -0
  93. langfun/core/modalities/image.py +39 -20
  94. langfun/core/modalities/image_test.py +52 -9
  95. langfun/core/modalities/mime.py +206 -29
  96. langfun/core/modalities/mime_test.py +90 -9
  97. langfun/core/modalities/ms_office.py +117 -0
  98. langfun/core/modalities/ms_office_test.py +389 -0
  99. langfun/core/modalities/pdf.py +22 -0
  100. langfun/core/modalities/pdf_test.py +57 -0
  101. langfun/core/modalities/video.py +9 -26
  102. langfun/core/modalities/video_test.py +3 -3
  103. langfun/core/modality.py +26 -3
  104. langfun/core/modality_test.py +2 -2
  105. langfun/core/sampling.py +11 -11
  106. langfun/core/structured/__init__.py +12 -16
  107. langfun/core/structured/completion.py +32 -5
  108. langfun/core/structured/completion_test.py +7 -6
  109. langfun/core/structured/description.py +2 -2
  110. langfun/core/structured/description_test.py +3 -3
  111. langfun/core/structured/function_generation.py +60 -27
  112. langfun/core/structured/function_generation_test.py +72 -2
  113. langfun/core/structured/mapping.py +97 -47
  114. langfun/core/structured/mapping_test.py +90 -2
  115. langfun/core/structured/parsing.py +33 -21
  116. langfun/core/structured/parsing_test.py +53 -9
  117. langfun/core/structured/querying.py +746 -0
  118. langfun/core/structured/{prompting_test.py → querying_test.py} +469 -51
  119. langfun/core/structured/schema.py +204 -97
  120. langfun/core/structured/schema_generation.py +1 -1
  121. langfun/core/structured/schema_test.py +130 -29
  122. langfun/core/structured/scoring.py +125 -19
  123. langfun/core/structured/scoring_test.py +30 -0
  124. langfun/core/structured/tokenization.py +64 -0
  125. langfun/core/structured/tokenization_test.py +48 -0
  126. langfun/core/template.py +115 -1
  127. langfun/core/template_test.py +71 -1
  128. langfun/core/templates/conversation.py +9 -0
  129. langfun/core/templates/conversation_test.py +4 -3
  130. langfun/core/templates/selfplay_test.py +10 -2
  131. langfun-0.1.2.dev202501150804.dist-info/METADATA +225 -0
  132. langfun-0.1.2.dev202501150804.dist-info/RECORD +153 -0
  133. {langfun-0.0.2.dev20240429.dist-info → langfun-0.1.2.dev202501150804.dist-info}/WHEEL +1 -1
  134. langfun/core/coding/python/errors.py +0 -108
  135. langfun/core/coding/python/errors_test.py +0 -99
  136. langfun/core/coding/python/permissions.py +0 -90
  137. langfun/core/coding/python/permissions_test.py +0 -86
  138. langfun/core/structured/prompting.py +0 -238
  139. langfun/core/text_formatting.py +0 -162
  140. langfun/core/text_formatting_test.py +0 -47
  141. langfun-0.0.2.dev20240429.dist-info/METADATA +0 -100
  142. langfun-0.0.2.dev20240429.dist-info/RECORD +0 -108
  143. {langfun-0.0.2.dev20240429.dist-info → langfun-0.1.2.dev202501150804.dist-info}/LICENSE +0 -0
  144. {langfun-0.0.2.dev20240429.dist-info → langfun-0.1.2.dev202501150804.dist-info}/top_level.txt +0 -0
@@ -94,7 +94,7 @@ class RetryErrorTest(unittest.TestCase):
94
94
  )
95
95
 
96
96
 
97
- class WithRetryTest(unittest.TestCase):
97
+ class RetryTest(unittest.TestCase):
98
98
 
99
99
  def assert_retry(self, func, expected_attempts, expected_wait_intervals):
100
100
  with pg.catch_errors(concurrent.RetryError) as error_context:
@@ -138,10 +138,19 @@ class WithRetryTest(unittest.TestCase):
138
138
  raise ValueError('Intentional error.')
139
139
 
140
140
  foo_with_retry = concurrent.with_retry(
141
- foo, ValueError, max_attempts=4, retry_interval=1
141
+ foo, ValueError, max_attempts=4, retry_interval=1,
142
142
  )
143
143
  self.assert_retry(foo_with_retry, 4, [1, 2, 4])
144
144
 
145
+ def test_retry_with_max_retry_interval(self):
146
+ def foo():
147
+ raise ValueError('Intentional error.')
148
+
149
+ foo_with_retry = concurrent.with_retry(
150
+ foo, ValueError, max_attempts=4, retry_interval=1, max_retry_interval=3,
151
+ )
152
+ self.assert_retry(foo_with_retry, 4, [1, 2, 3])
153
+
145
154
  def test_retry_with_uncaught_exception(self):
146
155
  def foo():
147
156
  raise ValueError('Intentional error.')
@@ -153,6 +162,31 @@ class WithRetryTest(unittest.TestCase):
153
162
  with self.assertRaises(ValueError):
154
163
  foo_with_retry()
155
164
 
165
+ def test_retry_with_job(self):
166
+ count = 0
167
+
168
+ def foo():
169
+ nonlocal count
170
+ count += 1
171
+ if count < 3:
172
+ raise ValueError('Foo temporary error.')
173
+ return 'Success'
174
+
175
+ job = concurrent.Job(
176
+ foo,
177
+ retry_on_errors=ValueError,
178
+ retry_interval=1,
179
+ )
180
+ job()
181
+ self.assertEqual(job.result, 'Success')
182
+ self.assertEqual(
183
+ [retry_entry.wait_interval for retry_entry in job.retry_entries],
184
+ [0, 1, 2],
185
+ )
186
+ self.assertIsInstance(job.retry_entries[0].error, ValueError)
187
+ self.assertIsInstance(job.retry_entries[1].error, ValueError)
188
+ self.assertIsNone(job.retry_entries[2].error)
189
+
156
190
 
157
191
  class ConcurrentExecuteTest(unittest.TestCase):
158
192
 
@@ -208,8 +242,8 @@ class ProgressTest(unittest.TestCase):
208
242
  def fun2(unused_x):
209
243
  raise ValueError('Intentional error.')
210
244
 
211
- job1 = concurrent.Job(fun, 1)
212
- job2 = concurrent.Job(fun2, 2)
245
+ job1 = concurrent.Job(fun, (1,))
246
+ job2 = concurrent.Job(fun2, (2,))
213
247
  job1()
214
248
  job2()
215
249
 
@@ -233,6 +267,57 @@ class ProgressTest(unittest.TestCase):
233
267
  self.assertIs(p.last_error, job2.error)
234
268
 
235
269
 
270
+ class ProgressControlTest(unittest.TestCase):
271
+
272
+ def test_noop(self):
273
+ concurrent.progress_bar = None
274
+ ctrl = concurrent._progress_control(100, 'noop', 'blue', None)
275
+ self.assertIsInstance(ctrl, concurrent._NoopProgressControl)
276
+ string_io = io.StringIO()
277
+ with contextlib.redirect_stderr(string_io):
278
+ ctrl.update(1)
279
+ ctrl.refresh()
280
+ self.assertEqual(string_io.getvalue(), '')
281
+ concurrent.progress_bar = 'tqdm'
282
+
283
+ def test_console(self):
284
+ concurrent.progress_bar = 'console'
285
+ ctrl = concurrent._progress_control(100, 'foo', 'blue', None)
286
+ self.assertIsInstance(ctrl, concurrent._ConsoleProgressControl)
287
+ string_io = io.StringIO()
288
+ with contextlib.redirect_stderr(string_io):
289
+ ctrl.set_status('bar')
290
+ ctrl.update(10)
291
+ ctrl.refresh()
292
+ self.assertEqual(
293
+ string_io.getvalue(),
294
+ '\x1b[1m\x1b[31mfoo\x1b[0m: \x1b[34m10% (10/100)\x1b[0m : bar\n'
295
+ )
296
+ concurrent.progress_bar = 'tqdm'
297
+
298
+ def test_tqdm(self):
299
+ concurrent.progress_bar = 'tqdm'
300
+ string_io = io.StringIO()
301
+ with contextlib.redirect_stderr(string_io):
302
+ ctrl = concurrent._progress_control(100, 'foo', 'blue', None)
303
+ self.assertIsInstance(ctrl, concurrent._TqdmProgressControl)
304
+ ctrl.update(10)
305
+ ctrl.refresh()
306
+ self.assertIn('10/100', string_io.getvalue())
307
+
308
+ tqdm = concurrent.tqdm
309
+ concurrent.tqdm = None
310
+ with self.assertRaisesRegex(RuntimeError, 'install package "tqdm"'):
311
+ _ = concurrent._progress_control(100, 'foo', 'blue', None)
312
+ concurrent.tqdm = tqdm
313
+
314
+ def test_unsupported(self):
315
+ concurrent.progress_bar = 'unknown'
316
+ with self.assertRaisesRegex(ValueError, 'Unsupported progress bar type'):
317
+ _ = concurrent._progress_control(100, 'foo', 'blue', None)
318
+ concurrent.progress_bar = 'tqdm'
319
+
320
+
236
321
  class ProgressBarTest(unittest.TestCase):
237
322
 
238
323
  def test_multithread_support(self):
@@ -241,13 +326,12 @@ class ProgressBarTest(unittest.TestCase):
241
326
  bar_id = concurrent.ProgressBar.install(None, 5)
242
327
  def fun(x):
243
328
  del x
244
- concurrent.ProgressBar.update(bar_id, 1, postfix=None)
329
+ concurrent.ProgressBar.update(bar_id, 1, status=None)
245
330
 
246
331
  for _ in concurrent.concurrent_execute(fun, range(5)):
247
332
  concurrent.ProgressBar.refresh()
248
333
  concurrent.ProgressBar.uninstall(bar_id)
249
334
  output_str = string_io.getvalue()
250
- print(output_str)
251
335
  self.assertIn('100%', output_str)
252
336
  self.assertIn('5/5', output_str)
253
337
 
@@ -255,19 +339,19 @@ class ProgressBarTest(unittest.TestCase):
255
339
  string_io = io.StringIO()
256
340
  with contextlib.redirect_stderr(string_io):
257
341
  bar_id = concurrent.ProgressBar.install(None, 4)
258
- concurrent.ProgressBar.update(bar_id, 1, postfix=None)
259
- self.assertIn('1/4', string_io.getvalue())
260
- concurrent.ProgressBar.update(bar_id, 1, postfix='hello')
261
- self.assertIn('2/4', string_io.getvalue())
262
- self.assertIn('hello', string_io.getvalue())
263
- concurrent.ProgressBar.update(bar_id, color='lightgreen')
264
- self.assertIn('2/4', string_io.getvalue())
265
- concurrent.ProgressBar.update(bar_id, 2, postfix=dict(x=1))
266
- self.assertIn('4/4', string_io.getvalue())
267
- self.assertIn('x=1', string_io.getvalue())
268
- with self.assertRaisesRegex(ValueError, 'Unsupported postfix'):
269
- concurrent.ProgressBar.update(bar_id, 0, postfix=1)
342
+ concurrent.ProgressBar.update(bar_id, 1, status=None)
343
+ concurrent.ProgressBar.update(bar_id, 1, status='hello')
344
+ concurrent.ProgressBar.update(bar_id, color='green')
345
+ concurrent.ProgressBar.update(bar_id, 2, status=dict(x=1))
346
+ with self.assertRaisesRegex(ValueError, 'Unsupported status'):
347
+ concurrent.ProgressBar.update(bar_id, 0, status=1)
270
348
  concurrent.ProgressBar.uninstall(bar_id)
349
+ self.assertIn('1/4', string_io.getvalue())
350
+ self.assertIn('2/4', string_io.getvalue())
351
+ self.assertIn('hello', string_io.getvalue())
352
+ self.assertNotIn('3/4', string_io.getvalue())
353
+ self.assertIn('4/4', string_io.getvalue())
354
+ self.assertIn('x=1', string_io.getvalue())
271
355
 
272
356
 
273
357
  class ConcurrentMapTest(unittest.TestCase):
@@ -479,10 +563,11 @@ class ConcurrentMapTest(unittest.TestCase):
479
563
 
480
564
  def test_concurrent_map_with_showing_progress(self):
481
565
  def fun(x):
482
- if x == 2:
483
- raise ValueError('Intentional error.')
484
- time.sleep(x)
485
- return x
566
+ with pg.timeit('foo'):
567
+ if x == 2:
568
+ raise ValueError('Intentional error.')
569
+ time.sleep(x)
570
+ return x
486
571
 
487
572
  string_io = io.StringIO()
488
573
  with contextlib.redirect_stderr(string_io):
@@ -499,7 +584,9 @@ class ConcurrentMapTest(unittest.TestCase):
499
584
  (3, pg.MISSING_VALUE),
500
585
  ],
501
586
  )
502
- self.assertIn('100%', string_io.getvalue())
587
+ output = string_io.getvalue()
588
+ self.assertIn('100%', output)
589
+ self.assertIn('TimeIt=foo (', output)
503
590
 
504
591
  def test_concurrent_map_with_showing_progress_and_status_fn(self):
505
592
  def fun(x):
@@ -526,8 +613,8 @@ class ConcurrentMapTest(unittest.TestCase):
526
613
  (3, pg.MISSING_VALUE),
527
614
  ],
528
615
  )
529
- self.assertIn('100%', string_io.getvalue())
530
616
  concurrent.ProgressBar.uninstall(bar_id)
617
+ self.assertIn('100%', string_io.getvalue())
531
618
 
532
619
 
533
620
  class ExecutorPoolTest(unittest.TestCase):
langfun/core/console.py CHANGED
@@ -15,7 +15,7 @@
15
15
 
16
16
  import sys
17
17
  from typing import Any
18
- from langfun.core.text_formatting import colored
18
+ import pyglove as pg
19
19
 
20
20
 
21
21
  def write(
@@ -42,10 +42,14 @@ def write(
42
42
  """
43
43
  # Print title if present.
44
44
  if title is not None:
45
- print(colored(title, styles=['bold']))
45
+ print(pg.colored(title, styles=['bold']))
46
46
 
47
47
  # Print body.
48
- print(colored(str(value), color=color, background=background, styles=styles))
48
+ print(
49
+ pg.colored(
50
+ str(value), color=color, background=background, styles=styles
51
+ )
52
+ )
49
53
 
50
54
 
51
55
  try:
@@ -59,12 +63,20 @@ def under_notebook() -> bool:
59
63
  return bool(_notebook)
60
64
 
61
65
 
62
- def display(value: Any, clear: bool = False) -> None: # pylint: disable=redefined-outer-name
66
+ def display(value: Any, clear: bool = False) -> Any: # pylint: disable=redefined-outer-name
63
67
  """Displays object in current notebook cell."""
64
68
  if _notebook is not None:
65
69
  if clear:
66
70
  _notebook.clear_output()
67
- _notebook.display(value)
71
+ return _notebook.display(value)
72
+ return None
73
+
74
+
75
+ def run_script(javascript: str) -> Any:
76
+ """Runs JavaScript in current notebook cell."""
77
+ if _notebook is not None:
78
+ return _notebook.display(_notebook.Javascript(javascript))
79
+ return
68
80
 
69
81
 
70
82
  def clear() -> None:
@@ -18,6 +18,7 @@ import io
18
18
  import unittest
19
19
 
20
20
  from langfun.core import console
21
+ import pyglove as pg
21
22
 
22
23
 
23
24
  class ConsoleTest(unittest.TestCase):
@@ -32,6 +33,22 @@ class ConsoleTest(unittest.TestCase):
32
33
 
33
34
  def test_under_notebook(self):
34
35
  self.assertFalse(console.under_notebook())
36
+ console._notebook = True
37
+ self.assertTrue(console.under_notebook())
38
+ console._notebook = None
39
+
40
+ def test_notebook_interaction(self):
41
+ console._notebook = pg.Dict(
42
+ display=lambda x: x, Javascript=lambda x: x, clear_output=lambda: None)
43
+ self.assertEqual(console.display('hi', clear=True), 'hi')
44
+ self.assertEqual(
45
+ console.run_script('console.log("hi")'),
46
+ 'console.log("hi")'
47
+ )
48
+ console.clear()
49
+ console._notebook = None
50
+ self.assertIsNone(console.display('hi'))
51
+ self.assertIsNone(console.run_script('console.log("hi")'))
35
52
 
36
53
 
37
54
  if __name__ == '__main__':
@@ -16,7 +16,13 @@
16
16
  # pylint: disable=g-importing-member
17
17
  # pylint: disable=g-bad-import-order
18
18
 
19
- from langfun.core.eval.base import app_run
19
+ from langfun.core.eval import v2
20
+
21
+ from langfun.core.eval.base import register
22
+ from langfun.core.eval.base import registered_names
23
+ from langfun.core.eval.base import get_evaluations
24
+ from langfun.core.eval.base import get
25
+ from langfun.core.eval.base import run
20
26
 
21
27
  from langfun.core.eval.base import Evaluable
22
28
  from langfun.core.eval.base import Evaluation
@@ -34,6 +40,15 @@ from langfun.core.eval.base import as_inputs
34
40
  from langfun.core.eval.matching import Matching
35
41
  from langfun.core.eval.scoring import Scoring
36
42
 
43
+ # Experiment patching.
44
+ from langfun.core.eval.patching import patch_member
45
+
46
+ from langfun.core.eval.patching import patch_lm
47
+ from langfun.core.eval.patching import patch_parsing_lm
48
+ from langfun.core.eval.patching import patch_inputs
49
+ from langfun.core.eval.patching import patch_prompt
50
+ from langfun.core.eval.patching import patch_schema_fn
37
51
 
52
+ # Placeholder for Google-internal imports.
38
53
  # pylint: enable=g-bad-import-order
39
54
  # pylint: enable=g-importing-member