langfun 0.1.2.dev202411150804__py3-none-any.whl → 0.1.2.dev202411170804__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.
@@ -15,6 +15,9 @@
15
15
  import abc
16
16
  import collections
17
17
  import concurrent.futures
18
+ import random
19
+ import threading
20
+ import time
18
21
  from typing import Any, Annotated, Callable, Iterator
19
22
 
20
23
  from langfun import core as lf
@@ -373,6 +376,15 @@ class ParallelRunner(RunnerBase):
373
376
  'Timeout for each evaluation example.'
374
377
  ] = None
375
378
 
379
+ concurrent_startup_delay: Annotated[
380
+ tuple[int, int] | None,
381
+ (
382
+ 'A range of seconds to delay the initial evaluation of each thread '
383
+ 'in the thread pool, helping to prevent a burst in LLM QPS at '
384
+ 'startup. If set to None, no delay will be applied.'
385
+ )
386
+ ] = None
387
+
376
388
  def _run(self, evaluations: list[Evaluation]) -> None:
377
389
  """Runs the evaluations in parallel."""
378
390
  def _run_group(evaluation_group: list[Evaluation]):
@@ -405,8 +417,20 @@ class ParallelRunner(RunnerBase):
405
417
  self, evaluation: Evaluation, items: Iterator[Example]
406
418
  ) -> None:
407
419
  """Override run items to run in parallel."""
420
+ if self.concurrent_startup_delay is not None:
421
+ thread_delayed = {}
422
+ def _evaluate_item(item: Example):
423
+ thread_id = threading.current_thread().ident
424
+ if thread_id not in thread_delayed:
425
+ thread_delayed[thread_id] = True
426
+ time.sleep(random.randint(*self.concurrent_startup_delay))
427
+ return self.evaluate_item(evaluation, item)
428
+ else:
429
+ def _evaluate_item(item: Example):
430
+ return self.evaluate_item(evaluation, item)
431
+
408
432
  for _, _, _ in lf.concurrent_map(
409
- lambda item: self.evaluate_item(evaluation, item),
433
+ _evaluate_item,
410
434
  items,
411
435
  max_workers=evaluation.max_workers,
412
436
  timeout=self.timeout,
@@ -198,7 +198,9 @@ class RunnerTest(unittest.TestCase):
198
198
  )
199
199
  # Global cache.
200
200
  root_dir = os.path.join(tempfile.gettempdir(), 'global_cache')
201
- run = exp.run(root_dir, runner='sequential', use_cache='global', plugins=[])
201
+ run = exp.run(
202
+ root_dir, 'new', runner='sequential', use_cache='global', plugins=[]
203
+ )
202
204
  self.assertTrue(pg.io.path_exists(run.output_path_for(exp, 'cache.json')))
203
205
  self.assertEqual(exp.usage_summary.cached.total.num_requests, 4)
204
206
  self.assertEqual(exp.usage_summary.uncached.total.num_requests, 2)
@@ -206,7 +208,8 @@ class RunnerTest(unittest.TestCase):
206
208
  # Per-dataset cache.
207
209
  root_dir = os.path.join(tempfile.gettempdir(), 'per_dataset')
208
210
  run = exp.run(
209
- root_dir, runner='sequential', use_cache='per_dataset', plugins=[]
211
+ root_dir, 'new', runner='sequential',
212
+ use_cache='per_dataset', plugins=[]
210
213
  )
211
214
  for leaf in exp.leaf_nodes:
212
215
  self.assertTrue(
@@ -226,6 +229,9 @@ class RunnerTest(unittest.TestCase):
226
229
  self.assertEqual(exp.usage_summary.cached.total.num_requests, 0)
227
230
  self.assertEqual(exp.usage_summary.uncached.total.num_requests, 6)
228
231
 
232
+
233
+ class ParallelRunnerTest(RunnerTest):
234
+
229
235
  def test_parallel_runner(self):
230
236
  plugin = TestPlugin()
231
237
  exp = test_helper.test_experiment()
@@ -266,6 +272,22 @@ class RunnerTest(unittest.TestCase):
266
272
  self.assertEqual(node.progress.num_failed, 0)
267
273
  self.assertEqual(node.progress.num_processed, node.progress.num_total)
268
274
 
275
+ def test_concurrent_startup_delay(self):
276
+ plugin = TestPlugin()
277
+ exp = test_helper.test_experiment()
278
+ root_dir = os.path.join(
279
+ tempfile.gettempdir(), 'test_concurrent_startup_delay'
280
+ )
281
+ _ = exp.run(
282
+ root_dir,
283
+ runner='parallel',
284
+ plugins=[plugin],
285
+ concurrent_startup_delay=(0, 5),
286
+ )
287
+
288
+
289
+ class DebugRunnerTest(RunnerTest):
290
+
269
291
  def test_debug_runner(self):
270
292
  plugin = TestPlugin()
271
293
  exp = test_helper.test_experiment()
@@ -124,17 +124,18 @@ class LMSamplingUsage(pg.Object):
124
124
  def __add__(self, other: Optional['LMSamplingUsage']) -> 'LMSamplingUsage':
125
125
  if other is None:
126
126
  return self
127
+ if self.estimated_cost is None:
128
+ estimated_cost = other.estimated_cost
129
+ elif other.estimated_cost is None:
130
+ estimated_cost = self.estimated_cost
131
+ else:
132
+ estimated_cost = self.estimated_cost + other.estimated_cost
127
133
  return LMSamplingUsage(
128
134
  prompt_tokens=self.prompt_tokens + other.prompt_tokens,
129
135
  completion_tokens=self.completion_tokens + other.completion_tokens,
130
136
  total_tokens=self.total_tokens + other.total_tokens,
131
137
  num_requests=self.num_requests + other.num_requests,
132
- estimated_cost=(
133
- self.estimated_cost + other.estimated_cost # pylint: disable=g-long-ternary
134
- if (self.estimated_cost is not None
135
- and other.estimated_cost is not None)
136
- else None
137
- )
138
+ estimated_cost=estimated_cost,
138
139
  )
139
140
 
140
141
  def __radd__(self, other: Optional['LMSamplingUsage']) -> 'LMSamplingUsage':
@@ -956,7 +957,9 @@ class UsageSummary(pg.Object, pg.views.HtmlTreeView.Extension):
956
957
  if self._usage_badge is not None:
957
958
  self._usage_badge.update(
958
959
  self._badge_text(),
959
- tooltip=pg.format(self.total, verbose=False),
960
+ tooltip=pg.format(
961
+ self, verbose=False, custom_format=self._tooltip_format
962
+ ),
960
963
  styles=dict(color=self._badge_color()),
961
964
  )
962
965
 
@@ -978,6 +981,14 @@ class UsageSummary(pg.Object, pg.views.HtmlTreeView.Extension):
978
981
  green = int(255 * (1 - normalized_value))
979
982
  return f'rgb({red}, {green}, 0)'
980
983
 
984
+ def _tooltip_format(self, v, root_indent):
985
+ del root_indent
986
+ if isinstance(v, int):
987
+ return f'{v:,}'
988
+ if isinstance(v, float):
989
+ return f'{v:,.3f}'
990
+ return None
991
+
981
992
  def _html_tree_view(
982
993
  self,
983
994
  *,
@@ -993,7 +1004,9 @@ class UsageSummary(pg.Object, pg.views.HtmlTreeView.Extension):
993
1004
  if usage_badge is None:
994
1005
  usage_badge = pg.views.html.controls.Badge(
995
1006
  self._badge_text(),
996
- tooltip=pg.format(self.total, verbose=False),
1007
+ tooltip=pg.format(
1008
+ self, custom_format=self._tooltip_format, verbose=False
1009
+ ),
997
1010
  css_classes=['usage-summary'],
998
1011
  styles=dict(color=self._badge_color()),
999
1012
  interactive=True,
@@ -744,6 +744,13 @@ class LMSamplingUsageTest(unittest.TestCase):
744
744
  self.assertEqual(usage1 + usage2, usage1 + usage2)
745
745
  self.assertIs(usage1 + None, usage1)
746
746
  self.assertIs(None + usage1, usage1)
747
+ usage3 = lm_lib.LMSamplingUsage(100, 200, 300, 4, None)
748
+ self.assertEqual(
749
+ usage1 + usage3, lm_lib.LMSamplingUsage(200, 400, 600, 8, 5.0)
750
+ )
751
+ self.assertEqual(
752
+ usage3 + usage1, lm_lib.LMSamplingUsage(200, 400, 600, 8, 5.0)
753
+ )
747
754
 
748
755
  def test_usage_not_available(self):
749
756
  usage_not_available = lm_lib.UsageNotAvailable()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: langfun
3
- Version: 0.1.2.dev202411150804
3
+ Version: 0.1.2.dev202411170804
4
4
  Summary: Langfun: Language as Functions.
5
5
  Home-page: https://github.com/google/langfun
6
6
  Author: Langfun Authors
@@ -8,8 +8,8 @@ langfun/core/console.py,sha256=Fra2_MSWZbFh6rY8HZoYgpGLsrNvhaGuL03znOwQbhM,2529
8
8
  langfun/core/console_test.py,sha256=pBOcuNMJdVELywvroptfcRtJMsegMm3wSlHAL2TdxVk,1679
9
9
  langfun/core/langfunc.py,sha256=G50YgoVZ0y1GFw2ev41MlOqr6qa8YakbvNC0h_E0PiA,11140
10
10
  langfun/core/langfunc_test.py,sha256=fKIAqcSNI_7M6nwoZW77HEam8Oa6vcWhsCNgVJanzb4,8822
11
- langfun/core/language_model.py,sha256=UtLvclKx55_SAKZ-ajaquudLxKorTARAeZFme5IaPi8,33499
12
- langfun/core/language_model_test.py,sha256=td81wm4zFPeMb16nmIuIZ6eHtpYhH0k6IeiYLfGgR0o,31525
11
+ langfun/core/language_model.py,sha256=b15MZ_qbydnz5vQ09t7sf9tc3C7qWvMSxUrGfT0p99I,33827
12
+ langfun/core/language_model_test.py,sha256=hnYhtw7GM_TbhgsJzHNYTaoDewUlPHpOVlI7xEkCFuI,31783
13
13
  langfun/core/logging.py,sha256=uslllP0RTGN223oro1m4nZZ0bFppcL07OwbFKm2iG6k,7519
14
14
  langfun/core/logging_test.py,sha256=b5bPTSUoYeICATaO6I8dOVumodwRbxSp1Oz96Sf3KcE,6104
15
15
  langfun/core/memory.py,sha256=f-asN1F7Vehgdn_fK84v73GrEUOxRtaW934keutTKjk,2416
@@ -76,8 +76,8 @@ langfun/core/eval/v2/progress_tracking.py,sha256=1imwSbllxHWG3zYrzo2NvytBZsVtjqu
76
76
  langfun/core/eval/v2/progress_tracking_test.py,sha256=eY2HvZeEXDA5Zyfi2m5NDWO_9kSfQsaAOEcIhkSbWCY,1874
77
77
  langfun/core/eval/v2/reporting.py,sha256=TGkli1IDwqfqsCJ_WslOMGk_24JDg7oRRTGXlAJlWpc,4361
78
78
  langfun/core/eval/v2/reporting_test.py,sha256=JxffbUPWInUyLjo-AQVFrllga884Mdfm05R86FtxSss,1482
79
- langfun/core/eval/v2/runners.py,sha256=2OHAVTbqq9hZ3qZpUEvQ--9X-Cr_z8Ghc3MRXCfclpk,13442
80
- langfun/core/eval/v2/runners_test.py,sha256=s3GgWA-H9x0JyPhPZq2s9-5GXGHo5dSbDD-4faX0h_E,11164
79
+ langfun/core/eval/v2/runners.py,sha256=zJmu-amUiYv1g0Ek4c3mXkBgp-AFvSF7WpXVZCCf7Y4,14245
80
+ langfun/core/eval/v2/runners_test.py,sha256=UeiUNygux_U6iGVG18rhp68ZE4hoWeoT6XsXvSjxNQg,11620
81
81
  langfun/core/eval/v2/test_helper.py,sha256=pDpZTBnWRR5xjJv3Uy3NWEzArqlL8FTMOgeR4C53F5M,2348
82
82
  langfun/core/llms/__init__.py,sha256=uR2vLghsnZqY6OjZKAs9Lo-YFNxZNunf3A0q6-1GYlc,6346
83
83
  langfun/core/llms/anthropic.py,sha256=uJXVgaFONL8okOSVQ4VGMGht_VZ30m1hoLzmDbIjmks,13990
@@ -148,8 +148,8 @@ langfun/core/templates/demonstration.py,sha256=vCrgYubdZM5Umqcgp8NUVGXgr4P_c-fik
148
148
  langfun/core/templates/demonstration_test.py,sha256=SafcDQ0WgI7pw05EmPI2S4v1t3ABKzup8jReCljHeK4,2162
149
149
  langfun/core/templates/selfplay.py,sha256=yhgrJbiYwq47TgzThmHrDQTF4nDrTI09CWGhuQPNv-s,2273
150
150
  langfun/core/templates/selfplay_test.py,sha256=Ot__1P1M8oJfoTp-M9-PQ6HUXqZKyMwvZ5f7yQ3yfyM,2326
151
- langfun-0.1.2.dev202411150804.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
152
- langfun-0.1.2.dev202411150804.dist-info/METADATA,sha256=1RftsAD_qubksdeWSmhbcR35HGkcT7opT3L1c1EO5Ok,8890
153
- langfun-0.1.2.dev202411150804.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
154
- langfun-0.1.2.dev202411150804.dist-info/top_level.txt,sha256=RhlEkHxs1qtzmmtWSwYoLVJAc1YrbPtxQ52uh8Z9VvY,8
155
- langfun-0.1.2.dev202411150804.dist-info/RECORD,,
151
+ langfun-0.1.2.dev202411170804.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
152
+ langfun-0.1.2.dev202411170804.dist-info/METADATA,sha256=Sr1olxW-wSjImKrZFtjVkrCe-_-uqVWkPa20-axQGPQ,8890
153
+ langfun-0.1.2.dev202411170804.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
154
+ langfun-0.1.2.dev202411170804.dist-info/top_level.txt,sha256=RhlEkHxs1qtzmmtWSwYoLVJAc1YrbPtxQ52uh8Z9VvY,8
155
+ langfun-0.1.2.dev202411170804.dist-info/RECORD,,