langfun 0.1.2.dev202412110804__py3-none-any.whl → 0.1.2.dev202412140804__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.
@@ -32,7 +32,7 @@ class Action(pg.Object):
32
32
  super()._on_bound()
33
33
  self._session = None
34
34
  self._result = None
35
- self._result_metadata = {}
35
+ self._metadata = {}
36
36
 
37
37
  @property
38
38
  def session(self) -> Optional['Session']:
@@ -45,9 +45,9 @@ class Action(pg.Object):
45
45
  return self._result
46
46
 
47
47
  @property
48
- def result_metadata(self) -> dict[str, Any] | None:
48
+ def metadata(self) -> dict[str, Any] | None:
49
49
  """Returns the metadata associated with the result from previous call."""
50
- return self._result_metadata
50
+ return self._metadata
51
51
 
52
52
  def __call__(
53
53
  self,
@@ -69,7 +69,7 @@ class Action(pg.Object):
69
69
  if new_session:
70
70
  self._session = session
71
71
  self._result = result
72
- self._result_metadata = session.current_action.result_metadata
72
+ self._metadata = session.current_action.metadata
73
73
  return self._result
74
74
 
75
75
  @abc.abstractmethod
@@ -139,7 +139,7 @@ class ExecutionTrace(pg.Object, pg.views.html.HtmlTreeView.Extension):
139
139
  if self._time_badge is not None:
140
140
  self._time_badge.update(
141
141
  'Starting',
142
- add_class=['running'],
142
+ add_class=['starting'],
143
143
  remove_class=['not-started'],
144
144
  )
145
145
 
@@ -149,10 +149,14 @@ class ExecutionTrace(pg.Object, pg.views.html.HtmlTreeView.Extension):
149
149
  if self._time_badge is not None:
150
150
  self._time_badge.update(
151
151
  f'{int(self.elapse)} seconds',
152
+ tooltip=pg.format(self.execution_summary(), verbose=False),
152
153
  add_class=['finished'],
153
154
  remove_class=['running'],
154
155
  )
155
156
 
157
+ def __len__(self) -> int:
158
+ return len(self.items)
159
+
156
160
  @property
157
161
  def has_started(self) -> bool:
158
162
  return self.start_time is not None
@@ -238,17 +242,8 @@ class ExecutionTrace(pg.Object, pg.views.html.HtmlTreeView.Extension):
238
242
  and not isinstance(item, lf.logging.LogEntry)):
239
243
  sub_task_label = self._execution_item_label(item)
240
244
  self._time_badge.update(
241
- pg.Html.element(
242
- 'span',
243
- [
244
- 'Running',
245
- pg.views.html.controls.Badge(
246
- sub_task_label.text,
247
- tooltip=sub_task_label.tooltip,
248
- css_classes=['task-in-progress']
249
- )
250
- ]
251
- ),
245
+ text=sub_task_label.text,
246
+ tooltip=sub_task_label.tooltip.content,
252
247
  add_class=['running'],
253
248
  remove_class=['not-started'],
254
249
  )
@@ -263,6 +258,20 @@ class ExecutionTrace(pg.Object, pg.views.html.HtmlTreeView.Extension):
263
258
  """Returns the usage summary of the action."""
264
259
  return self._usage_summary
265
260
 
261
+ def execution_summary(self) -> dict[str, Any]:
262
+ """Execution summary string."""
263
+ return pg.Dict(
264
+ num_queries=len(self.queries),
265
+ execution_breakdown=[
266
+ dict(
267
+ action=action.action.__class__.__name__,
268
+ usage=action.usage_summary.total,
269
+ execution_time=action.execution.elapse,
270
+ )
271
+ for action in self.actions
272
+ ]
273
+ )
274
+
266
275
  #
267
276
  # HTML views.
268
277
  #
@@ -274,57 +283,47 @@ class ExecutionTrace(pg.Object, pg.views.html.HtmlTreeView.Extension):
274
283
  extra_flags: dict[str, Any] | None = None,
275
284
  view: pg.views.html.HtmlTreeView, **kwargs
276
285
  ):
277
- extra_flags = extra_flags or {}
278
- interactive = extra_flags.get('interactive', True)
279
- def time_badge():
280
- if not self.has_started:
281
- label = '(Not started)'
282
- css_class = 'not-started'
283
- elif not self.has_stopped:
284
- label = 'Starting'
285
- css_class = 'running'
286
- else:
287
- label = f'{int(self.elapse)} seconds'
288
- css_class = 'finished'
289
- return pg.views.html.controls.Badge(
290
- label,
291
- css_classes=['execution-time', css_class],
292
- interactive=interactive,
293
- )
294
- time_badge = time_badge()
286
+ return None
287
+
288
+ def _execution_badge(self, interactive: bool = True):
289
+ if not self.has_started:
290
+ label = '(Not started)'
291
+ tooltip = 'Execution not started.'
292
+ css_class = 'not-started'
293
+ elif not self.has_stopped:
294
+ label = 'Starting'
295
+ tooltip = 'Execution starting.'
296
+ css_class = 'running'
297
+ else:
298
+ label = f'{int(self.elapse)} seconds'
299
+ tooltip = pg.format(self.execution_summary(), verbose=False)
300
+ css_class = 'finished'
301
+ time_badge = pg.views.html.controls.Badge(
302
+ label,
303
+ tooltip=tooltip,
304
+ css_classes=['execution-time', css_class],
305
+ interactive=interactive,
306
+ )
295
307
  if interactive:
296
308
  self._time_badge = time_badge
297
- title = pg.Html.element(
298
- 'div',
299
- [
300
- 'ExecutionTrace',
301
- time_badge,
302
- ],
303
- css_classes=['execution-trace-title'],
304
- )
305
- kwargs.pop('title', None)
306
- kwargs['enable_summary_tooltip'] = False
307
- kwargs['enable_key_tooltip'] = False
308
- return view.summary(
309
- self,
310
- name=name,
311
- title=title,
312
- extra_flags=extra_flags,
313
- **kwargs
314
- )
309
+ return time_badge
315
310
 
316
- def _html_tree_view_content(self, **kwargs):
311
+ def _html_tree_view_content(
312
+ self,
313
+ *,
314
+ extra_flags: dict[str, Any] | None = None,
315
+ **kwargs
316
+ ):
317
317
  del kwargs
318
- self._tab_control = pg.views.html.controls.TabControl(
319
- [self._execution_item_tab(item) for item in self.items],
320
- tab_position='left'
321
- )
322
- return pg.Html.element(
323
- 'div',
324
- [
325
- self._tab_control
326
- ]
327
- )
318
+ extra_flags = extra_flags or {}
319
+ interactive = extra_flags.get('interactive', True)
320
+ if interactive or self.items:
321
+ self._tab_control = pg.views.html.controls.TabControl(
322
+ [self._execution_item_tab(item) for item in self.items],
323
+ tab_position='left'
324
+ )
325
+ return self._tab_control.to_html()
326
+ return '(no tracked items)'
328
327
 
329
328
  def _execution_item_tab(self, item: TracedItem) -> pg.views.html.controls.Tab:
330
329
  if isinstance(item, ActionInvocation):
@@ -381,7 +380,8 @@ class ExecutionTrace(pg.Object, pg.views.html.HtmlTreeView.Extension):
381
380
  )
382
381
  elif isinstance(item, ExecutionTrace):
383
382
  return pg.views.html.controls.Label(
384
- item.name or 'Phase'
383
+ item.name or 'Phase',
384
+ tooltip=f'Execution phase {item.name!r}.'
385
385
  )
386
386
  else:
387
387
  raise ValueError(f'Unsupported item type: {type(item)}')
@@ -420,21 +420,21 @@ class ExecutionTrace(pg.Object, pg.views.html.HtmlTreeView.Extension):
420
420
  display: inline-block;
421
421
  }
422
422
  .badge.execution-time {
423
- margin-left: 5px;
423
+ margin-left: 4px;
424
+ border-radius: 0px;
425
+ }
426
+ .execution-time.starting {
427
+ background-color: ghostwhite;
428
+ font-weight: normal;
424
429
  }
425
430
  .execution-time.running {
426
- background-color: lavender;
431
+ background-color: ghostwhite;
427
432
  font-weight: normal;
428
433
  }
429
434
  .execution-time.finished {
430
435
  background-color: aliceblue;
431
436
  font-weight: bold;
432
437
  }
433
- .badge.task-in-progress {
434
- margin-left: 5px;
435
- background-color: azure;
436
- font-weight: bold;
437
- }
438
438
  """
439
439
  ]
440
440
 
@@ -448,7 +448,7 @@ class ActionInvocation(pg.Object, pg.views.html.HtmlTreeView.Extension):
448
448
  'The result of the action.'
449
449
  ] = None
450
450
 
451
- result_metadata: Annotated[
451
+ metadata: Annotated[
452
452
  dict[str, Any],
453
453
  'The metadata returned by the action.'
454
454
  ] = {}
@@ -464,8 +464,7 @@ class ActionInvocation(pg.Object, pg.views.html.HtmlTreeView.Extension):
464
464
  def _on_bound(self):
465
465
  super()._on_bound()
466
466
  self._current_phase = self.execution
467
- self._result_badge = None
468
- self._result_metadata_badge = None
467
+ self._tab_control = None
469
468
 
470
469
  @property
471
470
  def current_phase(self) -> ExecutionTrace:
@@ -520,31 +519,42 @@ class ActionInvocation(pg.Object, pg.views.html.HtmlTreeView.Extension):
520
519
  """Starts the execution of the action."""
521
520
  self.execution.start()
522
521
 
523
- def end(self, result: Any, result_metadata: dict[str, Any]) -> None:
522
+ def end(self, result: Any, metadata: dict[str, Any]) -> None:
524
523
  """Ends the execution of the action with result and metadata."""
525
- self.execution.stop()
526
524
  self.rebind(
527
525
  result=result,
528
- result_metadata=result_metadata,
526
+ metadata=metadata,
529
527
  skip_notification=True,
530
528
  raise_on_no_change=False
531
529
  )
532
- if self._result_badge is not None:
533
- self._result_badge.update(
534
- self._result_badge_label(result),
535
- tooltip=self._result_badge_tooltip(result),
536
- add_class=['ready'],
537
- remove_class=['not-ready'],
538
- )
539
- if self._result_metadata_badge is not None:
540
- result_metadata = dict(result_metadata)
541
- result_metadata.pop('session', None)
542
- self._result_metadata_badge.update(
543
- '{...}',
544
- tooltip=self._result_metadata_badge_tooltip(result_metadata),
545
- add_class=['ready'],
546
- remove_class=['not-ready'],
530
+ self.execution.stop()
531
+ if self._tab_control is not None:
532
+ if self.metadata:
533
+ self._tab_control.insert(
534
+ 1,
535
+ pg.views.html.controls.Tab(
536
+ 'metadata',
537
+ pg.view(
538
+ self.metadata,
539
+ collapse_level=None,
540
+ enable_summary_tooltip=False
541
+ ),
542
+ name='metadata',
543
+ )
544
+ )
545
+ self._tab_control.insert(
546
+ 1,
547
+ pg.views.html.controls.Tab(
548
+ 'result',
549
+ pg.view(
550
+ self.result,
551
+ collapse_level=None,
552
+ enable_summary_tooltip=False
553
+ ),
554
+ name='result',
555
+ ),
547
556
  )
557
+ self._tab_control.select(['metadata', 'result'])
548
558
 
549
559
  #
550
560
  # HTML views.
@@ -566,128 +576,88 @@ class ActionInvocation(pg.Object, pg.views.html.HtmlTreeView.Extension):
566
576
  interactive = extra_flags.get('interactive', True)
567
577
  if (isinstance(self.action, RootAction)
568
578
  and self.execution.has_stopped
569
- and len(self.execution.items) == 1):
579
+ and len(self.execution) == 1):
570
580
  return view.content(self.execution.items[0], extra_flags=extra_flags)
571
581
 
572
- def _result_badge():
573
- if not self.execution.has_stopped:
574
- label = '(n/a)'
575
- tooltip = 'Result is not available yet.'
576
- css_class = 'not-ready'
577
- else:
578
- label = self._result_badge_label(self.result)
579
- tooltip = self._result_badge_tooltip(self.result)
580
- css_class = 'ready'
581
- return pg.views.html.controls.Badge(
582
- label,
583
- tooltip=tooltip,
584
- css_classes=['invocation-result', css_class],
585
- interactive=interactive,
582
+ tabs = []
583
+ if not isinstance(self.action, RootAction):
584
+ tabs.append(
585
+ pg.views.html.controls.Tab(
586
+ 'action',
587
+ view.render( # pylint: disable=g-long-ternary
588
+ self.action,
589
+ collapse_level=None,
590
+ root_path=self.action.sym_path,
591
+ enable_summary_tooltip=False,
592
+ ),
593
+ name='action',
594
+ )
586
595
  )
587
-
588
- def _result_metadata_badge():
589
- if not self.execution.has_stopped:
590
- label = '(n/a)'
591
- tooltip = 'Result metadata is not available yet.'
592
- css_class = 'not-ready'
593
- else:
594
- label = '{...}' if self.result_metadata else '(empty)'
595
- tooltip = self._result_metadata_badge_tooltip(self.result_metadata)
596
- css_class = 'ready'
597
- return pg.views.html.controls.Badge(
598
- label,
599
- tooltip=tooltip,
600
- css_classes=['invocation-result-metadata', css_class],
601
- interactive=interactive,
596
+ if self.execution.has_stopped:
597
+ tabs.append(
598
+ pg.views.html.controls.Tab(
599
+ 'result',
600
+ view.render(
601
+ self.result,
602
+ collapse_level=None,
603
+ enable_summary_tooltip=False
604
+ ),
605
+ name='result'
606
+ )
602
607
  )
608
+ if self.metadata:
609
+ tabs.append(
610
+ pg.views.html.controls.Tab(
611
+ 'metadata',
612
+ view.render(
613
+ self.metadata,
614
+ collapse_level=None,
615
+ enable_summary_tooltip=False
616
+ ),
617
+ name='metadata'
618
+ )
619
+ )
603
620
 
604
- result_badge = _result_badge()
605
- result_metadata_badge = _result_metadata_badge()
606
- if interactive:
607
- self._result_badge = result_badge
608
- self._result_metadata_badge = result_metadata_badge
609
-
610
- return pg.Html.element(
611
- 'div',
612
- [
621
+ tabs.append(
622
+ pg.views.html.controls.Tab(
613
623
  pg.Html.element(
614
- 'div',
624
+ 'span',
615
625
  [
616
- view.render(
617
- self.usage_summary, extra_flags=dict(as_badge=True)
626
+ 'execution',
627
+ self.execution._execution_badge(interactive), # pylint: disable=protected-access
628
+ (
629
+ self.usage_summary.to_html( # pylint: disable=g-long-ternary
630
+ extra_flags=dict(as_badge=True)
631
+ )
632
+ if (interactive
633
+ or self.usage_summary.total.num_requests > 0)
634
+ else None
618
635
  ),
619
- result_badge,
620
- result_metadata_badge,
621
636
  ],
622
- css_classes=['invocation-badge-container'],
637
+ css_classes=['execution-tab-title']
623
638
  ),
624
- view.render( # pylint: disable=g-long-ternary
625
- self.action,
626
- name='action',
627
- collapse_level=None,
628
- root_path=self.action.sym_path,
629
- css_classes='invocation-title',
630
- enable_summary_tooltip=False,
631
- ) if not isinstance(self.action, RootAction) else None,
632
- view.render(self.execution, name='execution'),
633
- ]
634
- )
635
-
636
- def _result_badge_label(self, result: Any) -> str:
637
- label = pg.format(
638
- result, python_format=True, verbose=False
639
- )
640
- if len(label) > 40:
641
- if isinstance(result, str):
642
- label = label[:40] + '...'
643
- else:
644
- label = f'{result.__class__.__name__}(...)'
645
- return label
646
-
647
- def _result_badge_tooltip(self, result: Any) -> pg.Html:
648
- return typing.cast(
649
- pg.Html,
650
- pg.view(
651
- result, name='result',
652
- collapse_level=None,
653
- enable_summary_tooltip=False,
654
- enable_key_tooltip=False,
655
- )
656
- )
657
-
658
- def _result_metadata_badge_tooltip(
659
- self, result_metadata: dict[str, Any]
660
- ) -> pg.Html:
661
- return typing.cast(
662
- pg.Html,
663
- pg.view(
664
- result_metadata,
665
- name='result_metadata',
666
- collapse_level=None,
667
- enable_summary_tooltip=False,
639
+ view.render(self.execution, extra_flags=extra_flags),
640
+ name='execution',
668
641
  )
669
642
  )
643
+ tab_control = pg.views.html.controls.TabControl(tabs)
644
+ # Select the tab following a priority: metadata, result, action, execution.
645
+ tab_control.select(['metadata', 'result', 'action', 'execution'])
646
+ if interactive:
647
+ self._tab_control = tab_control
648
+ return tab_control
670
649
 
671
650
  @classmethod
672
651
  def _html_tree_view_css_styles(cls) -> list[str]:
673
652
  return super()._html_tree_view_css_styles() + [
674
653
  """
675
- .invocation-badge-container {
676
- display: flex;
677
- padding-bottom: 5px;
678
- }
679
- .invocation-badge-container > .label-container {
680
- margin-right: 3px;
681
- }
682
- .invocation-result.ready {
683
- background-color: lightcyan;
654
+ .execution-tab-title {
655
+ text-align: left;
684
656
  }
685
- .invocation-result-metadata.ready {
686
- background-color: lightyellow;
687
- }
688
- details.pyglove.invocation-title {
689
- background-color: aliceblue;
690
- border: 0px solid white;
657
+ .execution-tab-title .usage-summary.label {
658
+ border-radius: 0px;
659
+ font-weight: normal;
660
+ color: #AAA;
691
661
  }
692
662
  """
693
663
  ]
@@ -722,7 +692,7 @@ class Session(pg.Object, pg.views.html.HtmlTreeView.Extension):
722
692
  def add_metadata(self, **kwargs: Any) -> None:
723
693
  """Adds metadata to the current invocation."""
724
694
  with pg.notify_on_change(False):
725
- self._current_action.result_metadata.update(kwargs)
695
+ self._current_action.metadata.update(kwargs)
726
696
 
727
697
  def phase(self, name: str) -> ContextManager[ExecutionTrace]:
728
698
  """Context manager for starting a new execution phase."""
@@ -745,11 +715,11 @@ class Session(pg.Object, pg.views.html.HtmlTreeView.Extension):
745
715
  yield invocation
746
716
  finally:
747
717
  # Stop the execution of the current action.
748
- self._current_action.end(action.result, action.result_metadata)
718
+ self._current_action.end(action.result, action.metadata)
749
719
  self._current_action = parent_action
750
720
  if parent_action is self.root:
751
721
  parent_action.end(
752
- result=action.result, result_metadata=action.result_metadata,
722
+ result=action.result, metadata=action.metadata,
753
723
  )
754
724
 
755
725
  @contextlib.contextmanager
@@ -73,7 +73,7 @@ class SessionTest(unittest.TestCase):
73
73
  self.assertTrue(root.execution.has_stopped)
74
74
  self.assertGreater(root.execution.elapse, 0)
75
75
  self.assertEqual(root.result, 3)
76
- self.assertEqual(root.result_metadata, dict(note='foo'))
76
+ self.assertEqual(root.metadata, dict(note='foo'))
77
77
 
78
78
  # The root space should have one action (foo), no queries, and no logs.
79
79
  self.assertEqual(len(list(root.actions)), 1)
@@ -109,11 +109,11 @@ class SessionTest(unittest.TestCase):
109
109
  self.assertIsInstance(bar_invocation, action_lib.ActionInvocation)
110
110
  self.assertIsInstance(bar_invocation.action, Bar)
111
111
  self.assertEqual(bar_invocation.result, 2)
112
- self.assertEqual(bar_invocation.result_metadata, dict(note='bar'))
112
+ self.assertEqual(bar_invocation.metadata, dict(note='bar'))
113
113
  self.assertEqual(len(bar_invocation.execution.items), 2)
114
114
 
115
115
  # Save to HTML
116
- self.assertIn('invocation-result', session.to_html().content)
116
+ self.assertIn('result', session.to_html().content)
117
117
 
118
118
  # Save session to JSON
119
119
  json_str = session.to_json_str(save_ref_value=True)
@@ -465,6 +465,33 @@ class Experiment(lf.Component, pg.views.HtmlTreeView.Extension):
465
465
  runner.run()
466
466
  return runner.current_run
467
467
 
468
+ def run_preconfigured(
469
+ self,
470
+ root_dir: str | None = None,
471
+ id: str | None = None, # pylint: disable=redefined-builtin
472
+ **kwargs
473
+ ) -> 'Run':
474
+ """Runs the experiment with pre-configured kwargs from `cls.RUN_ARGS`.
475
+
476
+ This helper method allows users to config running arguments as a part of
477
+ the class.
478
+
479
+ Args:
480
+ root_dir: root directory of the experiment.
481
+ id: ID of the current run.
482
+ **kwargs: Keyword arguments to override the RUN_CONFIG.
483
+
484
+ Returns:
485
+ The current run.
486
+ """
487
+ run_config = getattr(self, 'RUN_ARGS', {})
488
+ run_config.update(kwargs)
489
+ if root_dir is not None:
490
+ run_config['root_dir'] = root_dir
491
+ if id is not None:
492
+ run_config['id'] = id
493
+ return self.run(**run_config)
494
+
468
495
  #
469
496
  # HTML views.
470
497
  #
@@ -39,6 +39,10 @@ def sample_inputs():
39
39
 
40
40
  class MyEvaluation(Evaluation):
41
41
  NAME = 'my_eval'
42
+ RUN_ARGS = dict(
43
+ runner='test'
44
+ )
45
+
42
46
  replica_id: int = 0
43
47
  inputs = sample_inputs()
44
48
  metrics = [metrics_lib.Match()]
@@ -288,10 +292,17 @@ class RunnerTest(unittest.TestCase):
288
292
  TestRunner
289
293
  )
290
294
  root_dir = os.path.join(tempfile.gettempdir(), 'my_eval')
295
+
296
+ # Test standard run.
291
297
  MyEvaluation(replica_id=0).run(
292
298
  root_dir, id='20241101_0', runner='test'
293
299
  )
294
300
 
301
+ # Test run preconfigured.
302
+ MyEvaluation(replica_id=0).run_preconfigured(
303
+ root_dir=root_dir, id='20241101_1'
304
+ )
305
+
295
306
  with self.assertRaisesRegex(
296
307
  ValueError, 'Runner class must define a NAME constant'
297
308
  ):
@@ -32,11 +32,12 @@ from langfun.core.llms.rest import REST
32
32
 
33
33
  # Gemini models.
34
34
  from langfun.core.llms.google_genai import GenAI
35
+ from langfun.core.llms.google_genai import GeminiFlash2_0Exp
35
36
  from langfun.core.llms.google_genai import GeminiExp_20241114
36
37
  from langfun.core.llms.google_genai import GeminiExp_20241206
37
38
  from langfun.core.llms.google_genai import GeminiFlash1_5
38
- from langfun.core.llms.google_genai import GeminiPro
39
39
  from langfun.core.llms.google_genai import GeminiPro1_5
40
+ from langfun.core.llms.google_genai import GeminiPro
40
41
  from langfun.core.llms.google_genai import GeminiProVision
41
42
  from langfun.core.llms.google_genai import Palm2
42
43
  from langfun.core.llms.google_genai import Palm2_IT
@@ -121,6 +122,8 @@ from langfun.core.llms.groq import GroqWhisper_Large_v3
121
122
  from langfun.core.llms.groq import GroqWhisper_Large_v3Turbo
122
123
 
123
124
  from langfun.core.llms.vertexai import VertexAI
125
+ from langfun.core.llms.vertexai import VertexAIGemini2_0
126
+ from langfun.core.llms.vertexai import VertexAIGeminiFlash2_0Exp
124
127
  from langfun.core.llms.vertexai import VertexAIGemini1_5
125
128
  from langfun.core.llms.vertexai import VertexAIGeminiPro1_5
126
129
  from langfun.core.llms.vertexai import VertexAIGeminiPro1_5_001
@@ -48,14 +48,15 @@ class GenAI(lf.LanguageModel):
48
48
 
49
49
  model: Annotated[
50
50
  Literal[
51
+ 'gemini-2.0-flash-exp',
52
+ 'gemini-exp-1206',
53
+ 'gemini-exp-1114',
54
+ 'gemini-1.5-pro-latest',
55
+ 'gemini-1.5-flash-latest',
51
56
  'gemini-pro',
52
57
  'gemini-pro-vision',
53
58
  'text-bison-001',
54
59
  'chat-bison-001',
55
- 'gemini-1.5-pro-latest',
56
- 'gemini-1.5-flash-latest',
57
- 'gemini-exp-1114',
58
- 'gemini-exp-1206',
59
60
  ],
60
61
  'Model name.',
61
62
  ]
@@ -308,6 +309,18 @@ _GOOGLE_GENAI_MODEL_HUB = _ModelHub()
308
309
  #
309
310
 
310
311
 
312
+ class GeminiFlash2_0Exp(GenAI): # pylint: disable=invalid-name
313
+ """Gemini Experimental model launched on 12/06/2024."""
314
+
315
+ model = 'gemini-2.0-flash-exp'
316
+ supported_modalities = (
317
+ vertexai.DOCUMENT_TYPES
318
+ + vertexai.IMAGE_TYPES
319
+ + vertexai.AUDIO_TYPES
320
+ + vertexai.VIDEO_TYPES
321
+ )
322
+
323
+
311
324
  class GeminiExp_20241206(GenAI): # pylint: disable=invalid-name
312
325
  """Gemini Experimental model launched on 12/06/2024."""
313
326
 
@@ -40,7 +40,7 @@ except ImportError:
40
40
 
41
41
  # https://cloud.google.com/vertex-ai/generative-ai/pricing
42
42
  # describes that the average number of characters per token is about 4.
43
- AVGERAGE_CHARS_PER_TOEKN = 4
43
+ AVGERAGE_CHARS_PER_TOKEN = 4
44
44
 
45
45
 
46
46
  # Price in US dollars,
@@ -102,6 +102,18 @@ SUPPORTED_MODELS_AND_SETTINGS = {
102
102
  cost_per_1k_input_chars=0.000125,
103
103
  cost_per_1k_output_chars=0.000375,
104
104
  ),
105
+ # TODO(sharatsharat): Update costs when published
106
+ 'gemini-exp-1206': pg.Dict(
107
+ rpm=20,
108
+ cost_per_1k_input_chars=0.000,
109
+ cost_per_1k_output_chars=0.000,
110
+ ),
111
+ # TODO(sharatsharat): Update costs when published
112
+ 'gemini-2.0-flash-exp': pg.Dict(
113
+ rpm=20,
114
+ cost_per_1k_input_chars=0.000,
115
+ cost_per_1k_output_chars=0.000,
116
+ ),
105
117
  # TODO(chengrun): Set a more appropriate rpm for endpoint.
106
118
  'vertexai-endpoint': pg.Dict(
107
119
  rpm=20,
@@ -215,7 +227,7 @@ class VertexAI(rest.REST):
215
227
  return (
216
228
  cost_per_1k_input_chars * num_input_tokens
217
229
  + cost_per_1k_output_chars * num_output_tokens
218
- ) * AVGERAGE_CHARS_PER_TOEKN / 1000
230
+ ) * AVGERAGE_CHARS_PER_TOKEN / 1000
219
231
 
220
232
  @functools.cached_property
221
233
  def _session(self):
@@ -389,6 +401,20 @@ DOCUMENT_TYPES = [
389
401
  ]
390
402
 
391
403
 
404
+ class VertexAIGemini2_0(VertexAI): # pylint: disable=invalid-name
405
+ """Vertex AI Gemini 2.0 model."""
406
+
407
+ supported_modalities: pg.typing.List(str).freeze( # pytype: disable=invalid-annotation
408
+ DOCUMENT_TYPES + IMAGE_TYPES + AUDIO_TYPES + VIDEO_TYPES
409
+ )
410
+
411
+
412
+ class VertexAIGeminiFlash2_0Exp(VertexAI): # pylint: disable=invalid-name
413
+ """Vertex AI Gemini 2.0 Flash model."""
414
+
415
+ model = 'gemini-2.0-flash-exp'
416
+
417
+
392
418
  class VertexAIGemini1_5(VertexAI): # pylint: disable=invalid-name
393
419
  """Vertex AI Gemini 1.5 model."""
394
420
 
@@ -15,6 +15,7 @@
15
15
 
16
16
  import contextlib
17
17
  import functools
18
+ import time
18
19
  from typing import Annotated, Any, Callable, Iterator, Type, Union
19
20
 
20
21
  import langfun.core as lf
@@ -221,6 +222,7 @@ def query(
221
222
  query_input = schema_lib.mark_missing(prompt)
222
223
 
223
224
  with lf.track_usages() as usage_summary:
225
+ start_time = time.time()
224
226
  if schema in (None, str):
225
227
  # Query with natural language output.
226
228
  output_message = lf.LangFunc.from_value(query_input, **kwargs)(
@@ -250,6 +252,7 @@ def query(
250
252
  cache_seed=cache_seed,
251
253
  skip_lm=skip_lm,
252
254
  )
255
+ end_time = time.time()
253
256
 
254
257
  def _result(message: lf.Message):
255
258
  return message.text if schema in (None, str) else message.result
@@ -268,6 +271,8 @@ def query(
268
271
  examples=pg.Ref(examples) if examples else [],
269
272
  lm_response=lf.AIMessage(output_message.text),
270
273
  usage_summary=usage_summary,
274
+ start_time=start_time,
275
+ end_time=end_time,
271
276
  )
272
277
  for i, (tracker, include_child_scopes) in enumerate(trackers):
273
278
  if i == 0 or include_child_scopes:
@@ -384,6 +389,14 @@ class QueryInvocation(pg.Object, pg.views.HtmlTreeView.Extension):
384
389
  lf.UsageSummary,
385
390
  'Usage summary for `lf.query`.'
386
391
  ]
392
+ start_time: Annotated[
393
+ float,
394
+ 'Start time of query.'
395
+ ]
396
+ end_time: Annotated[
397
+ float,
398
+ 'End time of query.'
399
+ ]
387
400
 
388
401
  @functools.cached_property
389
402
  def lm_request(self) -> lf.Message:
@@ -393,6 +406,11 @@ class QueryInvocation(pg.Object, pg.views.HtmlTreeView.Extension):
393
406
  def output(self) -> Any:
394
407
  return query_output(self.lm_response, self.schema)
395
408
 
409
+ @property
410
+ def elapse(self) -> float:
411
+ """Returns query elapse in seconds."""
412
+ return self.end_time - self.start_time
413
+
396
414
  def _on_bound(self):
397
415
  super()._on_bound()
398
416
  self.__dict__.pop('lm_request', None)
@@ -404,6 +422,8 @@ class QueryInvocation(pg.Object, pg.views.HtmlTreeView.Extension):
404
422
  view: pg.views.HtmlTreeView,
405
423
  **kwargs: Any
406
424
  ) -> pg.Html | None:
425
+ kwargs.pop('title', None)
426
+ kwargs.pop('enable_summary_tooltip', None)
407
427
  return view.summary(
408
428
  value=self,
409
429
  title=pg.Html.element(
@@ -423,11 +443,16 @@ class QueryInvocation(pg.Object, pg.views.HtmlTreeView.Extension):
423
443
  ),
424
444
  css_classes=['query-invocation-lm']
425
445
  ),
446
+ pg.views.html.controls.Badge(
447
+ f'{int(self.elapse)} seconds',
448
+ css_classes=['query-invocation-time']
449
+ ),
426
450
  self.usage_summary.to_html(extra_flags=dict(as_badge=True))
427
451
  ],
428
452
  css_classes=['query-invocation-title']
429
453
  ),
430
- enable_summary_tooltip=False
454
+ enable_summary_tooltip=False,
455
+ **kwargs
431
456
  )
432
457
 
433
458
  def _html_tree_view_content(
@@ -441,14 +466,14 @@ class QueryInvocation(pg.Object, pg.views.HtmlTreeView.Extension):
441
466
  'input',
442
467
  pg.view(self.input, collapse_level=None),
443
468
  ),
444
- pg.views.html.controls.Tab(
445
- 'schema',
446
- pg.view(self.schema),
447
- ),
448
469
  pg.views.html.controls.Tab(
449
470
  'output',
450
471
  pg.view(self.output, collapse_level=None),
451
472
  ),
473
+ pg.views.html.controls.Tab(
474
+ 'schema',
475
+ pg.view(self.schema),
476
+ ),
452
477
  pg.views.html.controls.Tab(
453
478
  'lm_request',
454
479
  pg.view(
@@ -463,24 +488,34 @@ class QueryInvocation(pg.Object, pg.views.HtmlTreeView.Extension):
463
488
  extra_flags=dict(include_message_metadata=False)
464
489
  ),
465
490
  ),
466
- ], tab_position='top').to_html()
491
+ ], tab_position='top', selected=1).to_html()
467
492
 
468
493
  @classmethod
469
494
  def _html_tree_view_css_styles(cls) -> list[str]:
470
495
  return super()._html_tree_view_css_styles() + [
471
496
  """
472
497
  .query-invocation-title {
473
- display: inline-block;
474
- font-weight: normal;
498
+ display: inline-block;
499
+ font-weight: normal;
475
500
  }
476
501
  .query-invocation-type-name {
477
- font-style: italic;
478
- color: #888;
502
+ color: #888;
479
503
  }
480
504
  .query-invocation-lm.badge {
481
- margin-left: 5px;
482
- margin-right: 5px;
483
- background-color: #fff0d6;
505
+ margin-left: 5px;
506
+ margin-right: 5px;
507
+ color: white;
508
+ background-color: mediumslateblue;
509
+ }
510
+ .query-invocation-time.badge {
511
+ margin-left: 5px;
512
+ border-radius: 0px;
513
+ font-weight: bold;
514
+ background-color: aliceblue;
515
+ }
516
+ .query-invocation-title .usage-summary.label {
517
+ border-radius: 0px;
518
+ color: #AAA;
484
519
  }
485
520
  """
486
521
  ]
@@ -996,6 +996,7 @@ class TrackQueriesTest(unittest.TestCase):
996
996
  self.assertEqual(queries[1].schema.spec.cls, Activity)
997
997
  self.assertTrue(pg.eq(queries[1].output, Activity(description='hi')))
998
998
  self.assertIs(queries[1].lm, lm)
999
+ self.assertGreater(queries[0].elapse, 0)
999
1000
  self.assertGreater(queries[0].usage_summary.total.total_tokens, 0)
1000
1001
  self.assertGreater(queries[1].usage_summary.total.total_tokens, 0)
1001
1002
 
langfun/core/template.py CHANGED
@@ -552,38 +552,33 @@ class Template(
552
552
  )
553
553
 
554
554
  def render_fields():
555
- return pg.Html.element(
556
- 'fieldset',
557
- [
558
- pg.Html.element('legend', ['Template Variables']),
559
- view.complex_value(
560
- {k: v for k, v in self.sym_items()},
561
- name='fields',
562
- root_path=root_path,
563
- parent=self,
564
- exclude_keys=['template_str', 'clean'],
565
- collapse_level=max(
566
- collapse_template_vars_level, collapse_level
567
- ) if collapse_level is not None else None,
568
- extra_flags=extra_flags,
569
- debug=debug,
570
- **view.get_passthrough_kwargs(
571
- remove=['exclude_keys'],
572
- **kwargs,
573
- )
574
- ),
575
- ],
576
- css_classes=['template-fields'],
555
+ return view.complex_value(
556
+ {k: v for k, v in self.sym_items()},
557
+ name='fields',
558
+ root_path=root_path,
559
+ parent=self,
560
+ exclude_keys=['template_str', 'clean'],
561
+ collapse_level=max(
562
+ collapse_template_vars_level, collapse_level
563
+ ) if collapse_level is not None else None,
564
+ extra_flags=extra_flags,
565
+ debug=debug,
566
+ **view.get_passthrough_kwargs(
567
+ remove=['exclude_keys'],
568
+ **kwargs,
569
+ )
577
570
  )
578
571
 
579
- return pg.Html.element(
580
- 'div',
581
- [
572
+ return pg.views.html.controls.TabControl([
573
+ pg.views.html.controls.Tab(
574
+ 'template_str',
582
575
  render_template_str(),
576
+ ),
577
+ pg.views.html.controls.Tab(
578
+ 'variables',
583
579
  render_fields(),
584
- ],
585
- css_classes=['complex_value'],
586
- )
580
+ ),
581
+ ], selected=1)
587
582
 
588
583
  @classmethod
589
584
  def _html_tree_view_css_styles(cls) -> list[str]:
@@ -601,15 +596,6 @@ class Template(
601
596
  background-color: #EEE;
602
597
  color: #cc2986;
603
598
  }
604
- .template-fields {
605
- margin: 0px 0px 5px 0px;
606
- border: 1px solid #EEE;
607
- padding: 5px;
608
- }
609
- .template-fields > legend {
610
- font-size: 0.8em;
611
- margin: 5px 0px 5px 0px;
612
- }
613
599
  """
614
600
  ]
615
601
 
@@ -555,13 +555,6 @@ class TemplateRenderEventTest(unittest.TestCase):
555
555
 
556
556
  class HtmlTest(unittest.TestCase):
557
557
 
558
- def assert_html_content(self, html, expected):
559
- expected = inspect.cleandoc(expected).strip()
560
- actual = html.content.strip()
561
- if actual != expected:
562
- print(actual)
563
- self.assertEqual(actual, expected)
564
-
565
558
  def test_html(self):
566
559
 
567
560
  class Foo(Template):
@@ -594,36 +587,23 @@ class HtmlTest(unittest.TestCase):
594
587
  background-color: #EEE;
595
588
  color: #cc2986;
596
589
  }
597
- .template-fields {
598
- margin: 0px 0px 5px 0px;
599
- border: 1px solid #EEE;
600
- padding: 5px;
601
- }
602
- .template-fields > legend {
603
- font-size: 0.8em;
604
- margin: 5px 0px 5px 0px;
605
- }
606
590
  """
607
591
  ),
608
592
  Foo(x=1, y=2).to_html().style_section,
609
593
  )
610
- self.assert_html_content(
594
+ self.assertIn(
595
+ 'template-str',
611
596
  Foo(x=Bar('{{y}} + {{z}}'), y=1).to_html(
612
597
  enable_summary_tooltip=False,
613
- ),
614
- """
615
- <details open class="pyglove foo lf-template"><summary><div class="summary-title lf-template">Foo(...)</div></summary><div class="complex_value"><div class="template-str"><span>{{x}} + {{y}} = ?</span></div><fieldset class="template-fields"><legend>Template Variables</legend><div class="complex-value foo"><details class="pyglove bar lf-template"><summary><div class="summary-name lf-template">x<span class="tooltip lf-template">x</span></div><div class="summary-title lf-template">Bar(...)</div></summary><div class="complex_value"><div class="template-str"><span>{{y}} + {{z}}</span></div><fieldset class="template-fields"><legend>Template Variables</legend><div class="complex-value bar"><details open class="pyglove contextual-attribute"><summary><div class="summary-name">y<span class="tooltip">x.y</span></div><div class="summary-title">ContextualAttribute(...)</div></summary><span class="simple-value int">1</span></details><details open class="pyglove contextual-attribute"><summary><div class="summary-name">z<span class="tooltip">x.z</span></div><div class="summary-title">ContextualAttribute(...)</div></summary><div class="unavailable-contextual">(not available)</div></details></div></fieldset></div></details><details open class="pyglove int"><summary><div class="summary-name">y<span class="tooltip">y</span></div><div class="summary-title">int</div></summary><span class="simple-value int">1</span></details></div></fieldset></div></details>
616
- """
598
+ ).content,
617
599
  )
618
- self.assert_html_content(
600
+ self.assertIn(
601
+ 'template-str',
619
602
  Foo(x=Bar('{{y}} + {{z}}'), y=1).to_html(
620
603
  enable_summary_tooltip=False,
621
604
  collapse_level=0,
622
605
  key_style='label',
623
- ),
624
- """
625
- <details class="pyglove foo lf-template"><summary><div class="summary-title lf-template">Foo(...)</div></summary><div class="complex_value"><div class="template-str"><span>{{x}} + {{y}} = ?</span></div><fieldset class="template-fields"><legend>Template Variables</legend><div class="complex-value foo"><table><tr><td><span class="object-key str">x</span><span class="tooltip">x</span></td><td><details class="pyglove bar lf-template"><summary><div class="summary-title lf-template">Bar(...)</div></summary><div class="complex_value"><div class="template-str"><span>{{y}} + {{z}}</span></div><fieldset class="template-fields"><legend>Template Variables</legend><div class="complex-value bar"><table><tr><td><span class="object-key str">y</span><span class="tooltip">x.y</span></td><td><details open class="pyglove contextual-attribute"><summary><div class="summary-title">ContextualAttribute(...)</div></summary><span class="simple-value int">1</span></details></td></tr><tr><td><span class="object-key str">z</span><span class="tooltip">x.z</span></td><td><details open class="pyglove contextual-attribute"><summary><div class="summary-title">ContextualAttribute(...)</div></summary><div class="unavailable-contextual">(not available)</div></details></td></tr></table></div></fieldset></div></details></td></tr><tr><td><span class="object-key str">y</span><span class="tooltip">y</span></td><td><span class="simple-value int">1</span></td></tr></table></div></fieldset></div></details>
626
- """
606
+ ).content,
627
607
  )
628
608
 
629
609
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: langfun
3
- Version: 0.1.2.dev202412110804
3
+ Version: 0.1.2.dev202412140804
4
4
  Summary: Langfun: Language as Functions.
5
5
  Home-page: https://github.com/google/langfun
6
6
  Author: Langfun Authors
@@ -25,15 +25,15 @@ langfun/core/sampling.py,sha256=SCnS5PFJWNVxSKvSkSCNRUmruvScun8UcNN4gafuXcw,5866
25
25
  langfun/core/sampling_test.py,sha256=U7PANpMsl9E_pa4_Y4FzesSjcwg-u-LKHGCWSgv-8FY,3663
26
26
  langfun/core/subscription.py,sha256=euawEuSZP-BHydaT-AQpfYFL0m5pWPGcW0upFhrojqc,10930
27
27
  langfun/core/subscription_test.py,sha256=Y4ZdbZEwm83YNZBxHff0QR4QUa4rdaNXA3_jfIcArBo,8717
28
- langfun/core/template.py,sha256=_Sae_WsRo_yvwul0nqAPTOa0NOjW1zNYbW0CQpvg7l0,25389
29
- langfun/core/template_test.py,sha256=Qokz1hQFhRYaTZWBWGqvPJ0NXC9B9ennUpnRYHEf0hE,20542
28
+ langfun/core/template.py,sha256=jNhYSrbLIn9kZOa03w5QZbyjgfnzJzE_ZrrMvvWY4t4,24929
29
+ langfun/core/template_test.py,sha256=g7x4mgNIAXEEj-4W1D5whGfl5YikLEQoylKPzaeDomk,17069
30
30
  langfun/core/text_formatting.py,sha256=d7t9vaY6aCn1dkfkikpNYnBy5E_i93vHbfyDWFclGZU,5284
31
31
  langfun/core/text_formatting_test.py,sha256=ck0Xzdd4YF4CtCUj7VE0GybfbAyKQ8p3xkM1FBGrqIk,2096
32
32
  langfun/core/agentic/__init__.py,sha256=ndoDX0sAYsa3eVdXuu6nB-a-BH5TaK3urW6zAaFiyVs,1110
33
- langfun/core/agentic/action.py,sha256=QZPKRU31m0qr7R7LBtx0B7I1ZOgqf-CSrXf9Mf11CTo,26253
33
+ langfun/core/agentic/action.py,sha256=yW5-2NRHIrQmmQEYmL83aIdSwaRfUez9mqCbME_aBWQ,25391
34
34
  langfun/core/agentic/action_eval.py,sha256=ZtjTh34S7XPIUqandQ0YwAtzw-S7ofuZ7rRXnRbUMdQ,4424
35
35
  langfun/core/agentic/action_eval_test.py,sha256=tRUkWmOE9p0rpNOq19xAY2oDEnYsEEykjg6sUpAwJk0,2832
36
- langfun/core/agentic/action_test.py,sha256=LkRTAa1zv8zavnkvCQEovKbKilVN5VNcqpK4shAcc1E,4637
36
+ langfun/core/agentic/action_test.py,sha256=Gu7P5XQvzqbKawn2jjyTpWaARzzhzO04KkC1TuBnUnw,4612
37
37
  langfun/core/coding/__init__.py,sha256=5utju_fwEsImaiftx4oXKl9FAM8p281k8-Esdh_-m1w,835
38
38
  langfun/core/coding/python/__init__.py,sha256=MJ-vubliz-ebrZH3OBRKBwMi0S9-FrhGCp8YQLR6_I4,1776
39
39
  langfun/core/coding/python/correction.py,sha256=WiBdoScL-6C___iA3Tg3vizuYtJWI-_4wy9zcMfVpj8,7020
@@ -64,8 +64,8 @@ langfun/core/eval/v2/evaluation.py,sha256=h_AWRUSKhEs-bHLBgqo-GeBYXluD5bPbAqypRW
64
64
  langfun/core/eval/v2/evaluation_test.py,sha256=hh6L2HhQPQ6NBv1pXKcNkYraNcV9MLuJ--69t9jbmaI,5846
65
65
  langfun/core/eval/v2/example.py,sha256=fURrvdNmMsVMqoEErcsmLmC6Xq3ny16dYsnLH8HVlcY,9626
66
66
  langfun/core/eval/v2/example_test.py,sha256=WcJmU7IQQXvjFia63mokySC4CqxzVL9Wso1sC5F0YK8,3032
67
- langfun/core/eval/v2/experiment.py,sha256=xkROLFYj2Nf6G9wunfVx6nEhdMX_560hRSsB8qT3S_Q,28787
68
- langfun/core/eval/v2/experiment_test.py,sha256=R0ujPSluvDu5gwxGpiSWJ3eTiVpfleJDwwT1pXN8Nvg,8933
67
+ langfun/core/eval/v2/experiment.py,sha256=0JBGckJ93aqSdffpJPDVPy_I5T2BXscghTxiglHzJWo,29556
68
+ langfun/core/eval/v2/experiment_test.py,sha256=zSMHYqC9cA0k61U71pCSYTAJ6yK2_b6Dml5btc-bKzQ,9133
69
69
  langfun/core/eval/v2/metric_values.py,sha256=_B905bC-jxrYPLSEcP2M8MaHZOVMz_bVrUw8YC4arCE,4660
70
70
  langfun/core/eval/v2/metric_values_test.py,sha256=ab2oF_HsIwrSy459108ggyjgefHSPn8UVILR4dRwx14,2634
71
71
  langfun/core/eval/v2/metrics.py,sha256=bl8i6u-ZHRBz4hAc3LzsZ2Dc7ZRQcuTYeUhhH-GxfF0,10628
@@ -79,14 +79,14 @@ langfun/core/eval/v2/reporting_test.py,sha256=JxffbUPWInUyLjo-AQVFrllga884Mdfm05
79
79
  langfun/core/eval/v2/runners.py,sha256=kP6ZEg9L8M7fK03tOZYGqIjTKUzoJn8Hz_LXS7btFPQ,14335
80
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
- langfun/core/llms/__init__.py,sha256=Y3sTFM_V3l09WiRmjb-kQFHfqBAV23KH2JWJKMhZvMc,6278
82
+ langfun/core/llms/__init__.py,sha256=lWXKjGHv66ShG7AE_Bc4QM7SDTxJdfoQMn3PF0lr0sU,6461
83
83
  langfun/core/llms/anthropic.py,sha256=afKZmdiLcosS_UEBlB8WKyf1K-zeXgwtPAx6ofg2Gww,13989
84
84
  langfun/core/llms/anthropic_test.py,sha256=-2U4kc_pgBM7wqxu8RuxzyHPGww1EAWqKUvN4PW8Btw,8058
85
85
  langfun/core/llms/compositional.py,sha256=csW_FLlgL-tpeyCOTVvfUQkMa_zCN5Y2I-YbSNuK27U,2872
86
86
  langfun/core/llms/compositional_test.py,sha256=4eTnOer-DncRKGaIJW2ZQQMLnt5r2R0UIx_DYOvGAQo,2027
87
87
  langfun/core/llms/fake.py,sha256=gCHBYBLvBCsC78HI1hpoqXCS-p1FMTgY1P1qh_sGBPk,3070
88
88
  langfun/core/llms/fake_test.py,sha256=2h13qkwEz_JR0mtUDPxdAhQo7MueXaFSwsD2DIRDW9g,7653
89
- langfun/core/llms/google_genai.py,sha256=8gLOJ_o2T1uu84QU8RWDPzSlDNtidGkYQHWb1voKwCU,11263
89
+ langfun/core/llms/google_genai.py,sha256=AAYOsSyeNIfHduIL9ZBzLhA8_acZUDMzHhS7AwUbOlM,11603
90
90
  langfun/core/llms/google_genai_test.py,sha256=zw14sgWmk0P_irHyb7vpPy1WAuLEE0PmyfiFElu03sA,7686
91
91
  langfun/core/llms/groq.py,sha256=dCnR3eAECEKuKKAAj-PDTs8NRHl6CQPdf57m1f6a79U,10312
92
92
  langfun/core/llms/groq_test.py,sha256=GYF_Qtq5S1H1TrKH38t6_lkdroqT7v-joYLDKnmS9e0,5274
@@ -96,7 +96,7 @@ langfun/core/llms/openai.py,sha256=l49v6RubfInvV0iG114AymTKNogTX4u4N-UFCeSgIxw,2
96
96
  langfun/core/llms/openai_test.py,sha256=kOWa1nf-nJvtYY10REUw5wojh3ZgfU8tRaCZ8wUgJbA,16623
97
97
  langfun/core/llms/rest.py,sha256=sWbYUV8S3SuOg9giq7xwD-xDRfaF7NP_ig7bI52-Rj4,3442
98
98
  langfun/core/llms/rest_test.py,sha256=NZ3Nf0XQVpT9kLP5cBVo_yBHLI7vWTYhWQxYEJVMGs4,3472
99
- langfun/core/llms/vertexai.py,sha256=BkhRKnr20gIJvRL8G-KwTT7EM7v7L-pXkBkPeRkEFFY,14184
99
+ langfun/core/llms/vertexai.py,sha256=adUTByiuiTHBQ31tM_EXPUWIyUwo3zqyYIe9UILAFDE,14981
100
100
  langfun/core/llms/vertexai_test.py,sha256=ffcA5yPecnQy_rhkuYAw_6o1iLW8AR8FgswmHt6aAys,6725
101
101
  langfun/core/llms/cache/__init__.py,sha256=QAo3InUMDM_YpteNnVCSejI4zOsnjSMWKJKzkb3VY64,993
102
102
  langfun/core/llms/cache/base.py,sha256=rt3zwmyw0y9jsSGW-ZbV1vAfLxQ7_3AVk0l2EySlse4,3918
@@ -129,8 +129,8 @@ langfun/core/structured/mapping.py,sha256=vLKH79UT-j0qkQdvqlQBO7SkXXuM-yr2Idm8_H
129
129
  langfun/core/structured/mapping_test.py,sha256=bHm2ZCXBITq_G8Lvw_olFHeUUc4s_lGXZm9v9JhoPB4,9630
130
130
  langfun/core/structured/parsing.py,sha256=D58wBWOC6r6DCJNychCDkiHPrsy1XJfBDCDDZtug00k,11765
131
131
  langfun/core/structured/parsing_test.py,sha256=i0i090FVgM8ngGqYjds0hjEm1v7q4gv18k-z1kaNr7E,21467
132
- langfun/core/structured/prompting.py,sha256=vvPZcB0OL_kQMwyCUe4r4Q77luHT_OwVX3DeILN0hNw,16564
133
- langfun/core/structured/prompting_test.py,sha256=TFqerzK5RFlYyNL-X4wrhY-vOjF_XEpHX3nbSNuNKxg,29720
132
+ langfun/core/structured/prompting.py,sha256=ceZQgK00rlnDxFEPKq4O61zJs6u-W_mggT02bODqBSg,17522
133
+ langfun/core/structured/prompting_test.py,sha256=fHJuBli4dryQIrg_HmU7gMWSIOzHuYM_4xT3m84haGs,29765
134
134
  langfun/core/structured/schema.py,sha256=_T8WIDdpvWXlZVPLVgKYH9TvoM9gK11m3f0b2nImQRM,28190
135
135
  langfun/core/structured/schema_generation.py,sha256=U3nRQsqmMZg_qIVDh2fiY3K4JLfsAL1LcKzIFP1iXFg,5316
136
136
  langfun/core/structured/schema_generation_test.py,sha256=RM9s71kMNg2jTePwInkiW9fK1ACN37eyPeF8OII-0zw,2950
@@ -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.dev202412110804.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
152
- langfun-0.1.2.dev202412110804.dist-info/METADATA,sha256=q4fWRzn0BflL8Z9pe8gzxyew2F4NyjczuTkV4Tw7f30,8281
153
- langfun-0.1.2.dev202412110804.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
154
- langfun-0.1.2.dev202412110804.dist-info/top_level.txt,sha256=RhlEkHxs1qtzmmtWSwYoLVJAc1YrbPtxQ52uh8Z9VvY,8
155
- langfun-0.1.2.dev202412110804.dist-info/RECORD,,
151
+ langfun-0.1.2.dev202412140804.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
152
+ langfun-0.1.2.dev202412140804.dist-info/METADATA,sha256=q58cOyfw1yxxacgXgp5nPwnh4cUHuPzJmgD33YE1Ro4,8281
153
+ langfun-0.1.2.dev202412140804.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
154
+ langfun-0.1.2.dev202412140804.dist-info/top_level.txt,sha256=RhlEkHxs1qtzmmtWSwYoLVJAc1YrbPtxQ52uh8Z9VvY,8
155
+ langfun-0.1.2.dev202412140804.dist-info/RECORD,,