langfun 0.1.2.dev202410170804__py3-none-any.whl → 0.1.2.dev202410190803__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.
- langfun/core/component.py +48 -0
- langfun/core/component_test.py +48 -0
- langfun/core/concurrent.py +6 -0
- langfun/core/eval/base.py +11 -7
- langfun/core/eval/matching.py +9 -8
- langfun/core/eval/scoring.py +3 -1
- langfun/core/logging.py +39 -28
- langfun/core/logging_test.py +21 -5
- langfun/core/message.py +104 -64
- langfun/core/message_test.py +101 -11
- langfun/core/modalities/mime.py +32 -20
- langfun/core/modalities/mime_test.py +8 -4
- langfun/core/structured/mapping.py +46 -29
- langfun/core/structured/mapping_test.py +11 -5
- langfun/core/structured/schema.py +1 -1
- langfun/core/template.py +36 -49
- langfun/core/template_test.py +39 -1
- {langfun-0.1.2.dev202410170804.dist-info → langfun-0.1.2.dev202410190803.dist-info}/METADATA +1 -1
- {langfun-0.1.2.dev202410170804.dist-info → langfun-0.1.2.dev202410190803.dist-info}/RECORD +22 -22
- {langfun-0.1.2.dev202410170804.dist-info → langfun-0.1.2.dev202410190803.dist-info}/LICENSE +0 -0
- {langfun-0.1.2.dev202410170804.dist-info → langfun-0.1.2.dev202410190803.dist-info}/WHEEL +0 -0
- {langfun-0.1.2.dev202410170804.dist-info → langfun-0.1.2.dev202410190803.dist-info}/top_level.txt +0 -0
langfun/core/message.py
CHANGED
@@ -14,8 +14,9 @@
|
|
14
14
|
"""Messages that are exchanged between users and agents."""
|
15
15
|
|
16
16
|
import contextlib
|
17
|
+
import functools
|
17
18
|
import io
|
18
|
-
from typing import Annotated, Any, Optional,
|
19
|
+
from typing import Annotated, Any, Optional, Union
|
19
20
|
|
20
21
|
from langfun.core import modality
|
21
22
|
from langfun.core import natural_language
|
@@ -506,53 +507,70 @@ class Message(natural_language.NaturalLanguageFormattable, pg.Object):
|
|
506
507
|
v = self.metadata[key]
|
507
508
|
return v.value if isinstance(v, pg.Ref) else v
|
508
509
|
|
509
|
-
# pytype: disable=annotation-type-mismatch
|
510
510
|
def _html_tree_view_content(
|
511
511
|
self,
|
512
512
|
*,
|
513
513
|
view: pg.views.HtmlTreeView,
|
514
514
|
root_path: pg.KeyPath,
|
515
|
-
|
516
|
-
|
517
|
-
),
|
518
|
-
include_message_metadata: bool = pg.View.PresetArgValue(True),
|
519
|
-
collapse_modalities_in_text: bool = pg.View.PresetArgValue(True),
|
520
|
-
collapse_llm_usage: bool = pg.View.PresetArgValue(False),
|
521
|
-
collapse_message_result_level: int | None = pg.View.PresetArgValue(1),
|
522
|
-
collapse_message_metadata_level: int | None = pg.View.PresetArgValue(0),
|
523
|
-
collapse_source_message_level: int | None = pg.View.PresetArgValue(1),
|
524
|
-
collapse_level: int | None = pg.View.PresetArgValue(1),
|
515
|
+
collapse_level: int | None = None,
|
516
|
+
extra_flags: dict[str, Any] | None = None,
|
525
517
|
**kwargs,
|
526
518
|
) -> pg.Html:
|
527
|
-
# pytype: enable=annotation-type-mismatch
|
528
519
|
"""Returns the HTML representation of the message.
|
529
520
|
|
530
521
|
Args:
|
531
522
|
view: The HTML tree view.
|
532
523
|
root_path: The root path of the message.
|
533
|
-
source_tag: tags to filter source messages. If None, the entire
|
534
|
-
source chain will be included.
|
535
|
-
include_message_metadata: Whether to include the metadata of the message.
|
536
|
-
collapse_modalities_in_text: Whether to collapse the modalities in the
|
537
|
-
message text.
|
538
|
-
collapse_llm_usage: Whether to collapse the usage in the message.
|
539
|
-
collapse_message_result_level: The level to collapse the result in the
|
540
|
-
message.
|
541
|
-
collapse_message_metadata_level: The level to collapse the metadata in the
|
542
|
-
message.
|
543
|
-
collapse_source_message_level: The level to collapse the source in the
|
544
|
-
message.
|
545
524
|
collapse_level: The global collapse level.
|
546
|
-
|
525
|
+
extra_flags: Extra flags to control the rendering.
|
526
|
+
- source_tag: tags to filter source messages. If None, the entire
|
527
|
+
source chain will be included.
|
528
|
+
- include_message_metadata: Whether to include the metadata of the
|
529
|
+
message.
|
530
|
+
- collapse_modalities_in_text: Whether to collapse the modalities in the
|
531
|
+
message text.
|
532
|
+
- collapse_llm_usage: Whether to collapse the usage in the message.
|
533
|
+
- collapse_message_result_level: The level to collapse the result in the
|
534
|
+
message.
|
535
|
+
- collapse_message_metadata_level: The level to collapse the metadata in
|
536
|
+
the message.
|
537
|
+
- collapse_source_message_level: The level to collapse the source in the
|
538
|
+
message.
|
539
|
+
- collapse_level: The global collapse level.
|
540
|
+
**kwargs: Omitted keyword arguments.
|
547
541
|
|
548
542
|
Returns:
|
549
543
|
The HTML representation of the message content.
|
550
544
|
"""
|
545
|
+
extra_flags = extra_flags if extra_flags is not None else {}
|
546
|
+
|
547
|
+
include_message_metadata: bool = extra_flags.get(
|
548
|
+
'include_message_metadata', True
|
549
|
+
)
|
550
|
+
source_tag: str | tuple[str, ...] | None = extra_flags.get(
|
551
|
+
'source_tag', ('lm-input', 'lm-output')
|
552
|
+
)
|
553
|
+
collapse_modalities_in_text: bool = extra_flags.get(
|
554
|
+
'collapse_modalities_in_text', True
|
555
|
+
)
|
556
|
+
collapse_llm_usage: bool = extra_flags.get(
|
557
|
+
'collapse_llm_usage', False
|
558
|
+
)
|
559
|
+
collapse_message_result_level: int | None = extra_flags.get(
|
560
|
+
'collapse_message_result_level', 1
|
561
|
+
)
|
562
|
+
collapse_message_metadata_level: int | None = extra_flags.get(
|
563
|
+
'collapse_message_metadata_level', 1
|
564
|
+
)
|
565
|
+
collapse_source_message_level: int | None = extra_flags.get(
|
566
|
+
'collapse_source_message_level', 1
|
567
|
+
)
|
568
|
+
passthrough_kwargs = view.get_passthrough_kwargs(**kwargs)
|
551
569
|
def render_tags():
|
552
570
|
return pg.Html.element(
|
553
571
|
'div',
|
554
572
|
[pg.Html.element('span', [tag]) for tag in self.tags],
|
555
|
-
|
573
|
+
css_classes=['message-tags'],
|
556
574
|
)
|
557
575
|
|
558
576
|
def render_message_text():
|
@@ -573,12 +591,16 @@ class Message(natural_language.NaturalLanguageFormattable, pg.Object):
|
|
573
591
|
chunk,
|
574
592
|
name=chunk.referred_name,
|
575
593
|
root_path=child_path,
|
576
|
-
collapse_level=
|
594
|
+
collapse_level=(
|
577
595
|
0 if collapse_modalities_in_text else 1
|
578
|
-
)
|
596
|
+
),
|
597
|
+
extra_flags=dict(
|
598
|
+
display_modality_when_hover=True,
|
599
|
+
),
|
600
|
+
**passthrough_kwargs,
|
579
601
|
)
|
580
602
|
],
|
581
|
-
|
603
|
+
css_classes=['modality-in-text'],
|
582
604
|
)
|
583
605
|
)
|
584
606
|
referred_chunks[chunk.referred_name] = chunk
|
@@ -596,14 +618,15 @@ class Message(natural_language.NaturalLanguageFormattable, pg.Object):
|
|
596
618
|
self.result,
|
597
619
|
name='result',
|
598
620
|
root_path=child_path,
|
599
|
-
collapse_level=view.
|
600
|
-
collapse_level,
|
621
|
+
collapse_level=view.get_collapse_level(
|
622
|
+
(collapse_level, -1),
|
601
623
|
collapse_message_result_level,
|
602
|
-
|
603
|
-
|
624
|
+
),
|
625
|
+
extra_flags=extra_flags,
|
626
|
+
**passthrough_kwargs,
|
604
627
|
)
|
605
628
|
],
|
606
|
-
|
629
|
+
css_classes=['message-result'],
|
607
630
|
)
|
608
631
|
|
609
632
|
def render_usage():
|
@@ -616,15 +639,19 @@ class Message(natural_language.NaturalLanguageFormattable, pg.Object):
|
|
616
639
|
view.render(
|
617
640
|
self.usage,
|
618
641
|
name='llm usage',
|
642
|
+
key_style='label',
|
619
643
|
root_path=child_path,
|
620
|
-
collapse_level=view.
|
621
|
-
collapse_level,
|
644
|
+
collapse_level=view.get_collapse_level(
|
645
|
+
(collapse_level, -1),
|
622
646
|
0 if collapse_llm_usage else 1,
|
623
|
-
|
624
|
-
|
647
|
+
),
|
648
|
+
extra_flags=extra_flags,
|
649
|
+
**view.get_passthrough_kwargs(
|
650
|
+
remove=['key_style'], **kwargs
|
651
|
+
),
|
625
652
|
)
|
626
653
|
],
|
627
|
-
|
654
|
+
css_classes=['message-usage'],
|
628
655
|
)
|
629
656
|
|
630
657
|
def render_source_message():
|
@@ -635,21 +662,22 @@ class Message(natural_language.NaturalLanguageFormattable, pg.Object):
|
|
635
662
|
source = source.source
|
636
663
|
if source is not None:
|
637
664
|
child_path = root_path + 'source'
|
665
|
+
child_extra_flags = extra_flags.copy()
|
666
|
+
child_extra_flags['collapse_source_message_level'] = (
|
667
|
+
view.get_collapse_level(
|
668
|
+
(collapse_source_message_level, -1), 0,
|
669
|
+
)
|
670
|
+
)
|
638
671
|
return view.render(
|
639
672
|
self.source,
|
640
673
|
name='source',
|
641
674
|
root_path=child_path,
|
642
|
-
|
643
|
-
|
644
|
-
collapse_level,
|
675
|
+
collapse_level=view.get_collapse_level(
|
676
|
+
(collapse_level, -1),
|
645
677
|
collapse_source_message_level,
|
646
|
-
child_path
|
647
678
|
),
|
648
|
-
|
649
|
-
|
650
|
-
collapse_usage=collapse_llm_usage,
|
651
|
-
collapse_metadata_level=collapse_message_metadata_level,
|
652
|
-
collapse_result_level=collapse_message_result_level,
|
679
|
+
extra_flags=child_extra_flags,
|
680
|
+
**passthrough_kwargs,
|
653
681
|
)
|
654
682
|
return None
|
655
683
|
|
@@ -662,17 +690,20 @@ class Message(natural_language.NaturalLanguageFormattable, pg.Object):
|
|
662
690
|
[
|
663
691
|
view.render(
|
664
692
|
self.metadata,
|
665
|
-
|
693
|
+
css_classes=['message-metadata'],
|
694
|
+
exclude_keys=['usage', 'result'],
|
666
695
|
name='metadata',
|
667
696
|
root_path=child_path,
|
668
|
-
collapse_level=view.
|
669
|
-
collapse_level,
|
697
|
+
collapse_level=view.get_collapse_level(
|
698
|
+
(collapse_level, -1),
|
670
699
|
collapse_message_metadata_level,
|
671
|
-
|
672
|
-
|
700
|
+
),
|
701
|
+
**view.get_passthrough_kwargs(
|
702
|
+
remove=['exclude_keys'], **kwargs
|
703
|
+
),
|
673
704
|
)
|
674
705
|
],
|
675
|
-
|
706
|
+
css_classes=['message-metadata'],
|
676
707
|
)
|
677
708
|
|
678
709
|
return pg.Html.element(
|
@@ -685,18 +716,30 @@ class Message(natural_language.NaturalLanguageFormattable, pg.Object):
|
|
685
716
|
render_metadata(),
|
686
717
|
render_source_message(),
|
687
718
|
],
|
688
|
-
|
719
|
+
css_classes=['complex_value'],
|
720
|
+
)
|
721
|
+
|
722
|
+
@classmethod
|
723
|
+
@functools.cache
|
724
|
+
def _html_tree_view_config(cls) -> dict[str, Any]:
|
725
|
+
return pg.views.HtmlTreeView.get_kwargs(
|
726
|
+
super()._html_tree_view_config(),
|
727
|
+
dict(
|
728
|
+
css_classes=['lf-message'],
|
729
|
+
)
|
689
730
|
)
|
690
731
|
|
691
|
-
|
692
|
-
|
732
|
+
@classmethod
|
733
|
+
@functools.cache
|
734
|
+
def _html_tree_view_css_styles(cls) -> list[str]:
|
735
|
+
return super()._html_tree_view_css_styles() + [
|
693
736
|
"""
|
694
737
|
/* Langfun Message styles.*/
|
695
738
|
[class^="message-"] > details {
|
696
739
|
margin: 0px 0px 5px 0px;
|
697
740
|
border: 1px solid #EEE;
|
698
741
|
}
|
699
|
-
|
742
|
+
.lf-message.summary-title::after {
|
700
743
|
content: ' 💬';
|
701
744
|
}
|
702
745
|
details.pyglove.ai-message {
|
@@ -739,12 +782,12 @@ class Message(natural_language.NaturalLanguageFormattable, pg.Object):
|
|
739
782
|
margin: 0px 5px 0px 5px;
|
740
783
|
}
|
741
784
|
.message-result {
|
742
|
-
color:
|
785
|
+
color: dodgerblue;
|
743
786
|
}
|
744
787
|
.message-usage {
|
745
788
|
color: orange;
|
746
789
|
}
|
747
|
-
.message-usage .
|
790
|
+
.message-usage .object-key.str {
|
748
791
|
border: 1px solid orange;
|
749
792
|
background-color: orange;
|
750
793
|
color: white;
|
@@ -752,9 +795,6 @@ class Message(natural_language.NaturalLanguageFormattable, pg.Object):
|
|
752
795
|
"""
|
753
796
|
]
|
754
797
|
|
755
|
-
def _html_element_class(self) -> list[str]:
|
756
|
-
return super()._html_element_class() + ['lf-message']
|
757
|
-
|
758
798
|
|
759
799
|
#
|
760
800
|
# Messages of different roles.
|
langfun/core/message_test.py
CHANGED
@@ -345,13 +345,80 @@ class MessageTest(unittest.TestCase):
|
|
345
345
|
print(actual)
|
346
346
|
self.assertEqual(actual, expected)
|
347
347
|
|
348
|
+
def test_html_style(self):
|
349
|
+
self.assertIn(
|
350
|
+
inspect.cleandoc(
|
351
|
+
"""
|
352
|
+
/* Langfun Message styles.*/
|
353
|
+
[class^="message-"] > details {
|
354
|
+
margin: 0px 0px 5px 0px;
|
355
|
+
border: 1px solid #EEE;
|
356
|
+
}
|
357
|
+
.lf-message.summary-title::after {
|
358
|
+
content: ' 💬';
|
359
|
+
}
|
360
|
+
details.pyglove.ai-message {
|
361
|
+
border: 1px solid blue;
|
362
|
+
color: blue;
|
363
|
+
}
|
364
|
+
details.pyglove.user-message {
|
365
|
+
border: 1px solid green;
|
366
|
+
color: green;
|
367
|
+
}
|
368
|
+
.message-tags {
|
369
|
+
margin: 5px 0px 5px 0px;
|
370
|
+
font-size: .8em;
|
371
|
+
}
|
372
|
+
.message-tags > span {
|
373
|
+
border-radius: 5px;
|
374
|
+
background-color: #CCC;
|
375
|
+
padding: 3px;
|
376
|
+
margin: 0px 2px 0px 2px;
|
377
|
+
color: white;
|
378
|
+
}
|
379
|
+
.message-text {
|
380
|
+
padding: 20px;
|
381
|
+
margin: 10px 5px 10px 5px;
|
382
|
+
font-style: italic;
|
383
|
+
font-size: 1.1em;
|
384
|
+
white-space: pre-wrap;
|
385
|
+
border: 1px solid #EEE;
|
386
|
+
border-radius: 5px;
|
387
|
+
background-color: #EEE;
|
388
|
+
}
|
389
|
+
.modality-in-text {
|
390
|
+
display: inline-block;
|
391
|
+
}
|
392
|
+
.modality-in-text > details {
|
393
|
+
display: inline-block;
|
394
|
+
font-size: 0.8em;
|
395
|
+
border: 0;
|
396
|
+
background-color: #A6F1A6;
|
397
|
+
margin: 0px 5px 0px 5px;
|
398
|
+
}
|
399
|
+
.message-result {
|
400
|
+
color: dodgerblue;
|
401
|
+
}
|
402
|
+
.message-usage {
|
403
|
+
color: orange;
|
404
|
+
}
|
405
|
+
.message-usage .object-key.str {
|
406
|
+
border: 1px solid orange;
|
407
|
+
background-color: orange;
|
408
|
+
color: white;
|
409
|
+
}
|
410
|
+
"""
|
411
|
+
),
|
412
|
+
message.UserMessage('hi').to_html().style_section,
|
413
|
+
)
|
414
|
+
|
348
415
|
def test_html_user_message(self):
|
349
416
|
self.assert_html_content(
|
350
417
|
message.UserMessage(
|
351
418
|
'what is a <div>'
|
352
419
|
).to_html(enable_summary_tooltip=False),
|
353
420
|
"""
|
354
|
-
<details open class="pyglove user-message lf-message"><summary><div class="
|
421
|
+
<details open class="pyglove user-message lf-message"><summary><div class="summary-title lf-message">UserMessage(...)</div></summary><div class="complex_value"><div class="message-tags"></div><div class="message-text">what is a <div></div><div class="message-metadata"><details open class="pyglove dict message-metadata"><summary><div class="summary-name message-metadata">metadata<span class="tooltip message-metadata">metadata</span></div><div class="summary-title message-metadata">Dict(...)</div></summary><div class="complex-value dict"><span class="empty-container"></span></div></details></div></div></details>
|
355
422
|
"""
|
356
423
|
)
|
357
424
|
self.assert_html_content(
|
@@ -359,9 +426,12 @@ class MessageTest(unittest.TestCase):
|
|
359
426
|
'what is this <<[[image]]>>',
|
360
427
|
tags=['lm-input'],
|
361
428
|
image=CustomModality('bird')
|
362
|
-
).to_html(
|
429
|
+
).to_html(
|
430
|
+
enable_summary_tooltip=False,
|
431
|
+
extra_flags=dict(include_message_metadata=False)
|
432
|
+
),
|
363
433
|
"""
|
364
|
-
<details open class="pyglove user-message lf-message"><summary><div class="
|
434
|
+
<details open class="pyglove user-message lf-message"><summary><div class="summary-title lf-message">UserMessage(...)</div></summary><div class="complex_value"><div class="message-tags"><span>lm-input</span></div><div class="message-text">what is this<div class="modality-in-text"><details class="pyglove custom-modality"><summary><div class="summary-name">image<span class="tooltip">metadata.image</span></div><div class="summary-title">CustomModality(...)</div></summary><div class="complex-value custom-modality"><details open class="pyglove str"><summary><div class="summary-name">content<span class="tooltip">metadata.image.content</span></div><div class="summary-title">str</div></summary><span class="simple-value str">'bird'</span></details></div></details></div></div></div></details>
|
365
435
|
"""
|
366
436
|
)
|
367
437
|
|
@@ -385,21 +455,41 @@ class MessageTest(unittest.TestCase):
|
|
385
455
|
self.assert_html_content(
|
386
456
|
ai_message.to_html(enable_summary_tooltip=False),
|
387
457
|
"""
|
388
|
-
<details open class="pyglove ai-message lf-message"><summary><div class="
|
458
|
+
<details open class="pyglove ai-message lf-message"><summary><div class="summary-title lf-message">AIMessage(...)</div></summary><div class="complex_value"><div class="message-tags"><span>lm-response</span><span>lm-output</span></div><div class="message-text">My name is Gemini</div><div class="message-result"><details open class="pyglove dict"><summary><div class="summary-name">result<span class="tooltip">metadata.result</span></div><div class="summary-title">Dict(...)</div></summary><div class="complex-value dict"><details open class="pyglove int"><summary><div class="summary-name">x<span class="tooltip">metadata.result.x</span></div><div class="summary-title">int</div></summary><span class="simple-value int">1</span></details><details open class="pyglove int"><summary><div class="summary-name">y<span class="tooltip">metadata.result.y</span></div><div class="summary-title">int</div></summary><span class="simple-value int">2</span></details><details class="pyglove dict"><summary><div class="summary-name">z<span class="tooltip">metadata.result.z</span></div><div class="summary-title">Dict(...)</div></summary><div class="complex-value dict"><details class="pyglove list"><summary><div class="summary-name">a<span class="tooltip">metadata.result.z.a</span></div><div class="summary-title">List(...)</div></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">metadata.result.z.a[0]</span></td><td><span class="simple-value int">12</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">metadata.result.z.a[1]</span></td><td><span class="simple-value int">323</span></td></tr></table></div></details></div></details></div></details></div><div class="message-usage"><details open class="pyglove lm-sampling-usage"><summary><div class="summary-name">llm usage<span class="tooltip">metadata.usage</span></div><div class="summary-title">LMSamplingUsage(...)</div></summary><div class="complex-value lm-sampling-usage"><table><tr><td><span class="object-key str">prompt_tokens</span><span class="tooltip">metadata.usage.prompt_tokens</span></td><td><span class="simple-value int">10</span></td></tr><tr><td><span class="object-key str">completion_tokens</span><span class="tooltip">metadata.usage.completion_tokens</span></td><td><span class="simple-value int">2</span></td></tr><tr><td><span class="object-key str">total_tokens</span><span class="tooltip">metadata.usage.total_tokens</span></td><td><span class="simple-value int">12</span></td></tr><tr><td><span class="object-key str">num_requests</span><span class="tooltip">metadata.usage.num_requests</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key str">estimated_cost</span><span class="tooltip">metadata.usage.estimated_cost</span></td><td><span class="simple-value none-type">None</span></td></tr></table></div></details></div><div class="message-metadata"><details open class="pyglove dict message-metadata"><summary><div class="summary-name message-metadata">metadata<span class="tooltip message-metadata">metadata</span></div><div class="summary-title message-metadata">Dict(...)</div></summary><div class="complex-value dict"><span class="empty-container"></span></div></details></div><details open class="pyglove user-message lf-message"><summary><div class="summary-name lf-message">source<span class="tooltip lf-message">source</span></div><div class="summary-title lf-message">UserMessage(...)</div></summary><div class="complex_value"><div class="message-tags"><span>lm-input</span></div><div class="message-text">What is in this image?<div class="modality-in-text"><details class="pyglove custom-modality"><summary><div class="summary-name">image<span class="tooltip">source.metadata.image</span></div><div class="summary-title">CustomModality(...)</div></summary><div class="complex-value custom-modality"><details open class="pyglove str"><summary><div class="summary-name">content<span class="tooltip">source.metadata.image.content</span></div><div class="summary-title">str</div></summary><span class="simple-value str">'foo'</span></details></div></details></div>this is a test</div><div class="message-metadata"><details open class="pyglove dict message-metadata"><summary><div class="summary-name message-metadata">metadata<span class="tooltip message-metadata">source.metadata</span></div><div class="summary-title message-metadata">Dict(...)</div></summary><div class="complex-value dict"><details class="pyglove custom-modality"><summary><div class="summary-name">image<span class="tooltip">source.metadata.image</span></div><div class="summary-title">CustomModality(...)</div></summary><div class="complex-value custom-modality"><details open class="pyglove str"><summary><div class="summary-name">content<span class="tooltip">source.metadata.image.content</span></div><div class="summary-title">str</div></summary><span class="simple-value str">'foo'</span></details></div></details></div></details></div></div></details></div></details>
|
459
|
+
"""
|
460
|
+
)
|
461
|
+
self.assert_html_content(
|
462
|
+
ai_message.to_html(
|
463
|
+
key_style='label',
|
464
|
+
enable_summary_tooltip=False,
|
465
|
+
extra_flags=dict(
|
466
|
+
collapse_modalities_in_text=False,
|
467
|
+
collapse_llm_usage=True,
|
468
|
+
collapse_message_result_level=0,
|
469
|
+
collapse_message_metadata_level=0,
|
470
|
+
collapse_source_message_level=0,
|
471
|
+
source_tag=None,
|
472
|
+
),
|
473
|
+
),
|
474
|
+
"""
|
475
|
+
<details open class="pyglove ai-message lf-message"><summary><div class="summary-title lf-message">AIMessage(...)</div></summary><div class="complex_value"><div class="message-tags"><span>lm-response</span><span>lm-output</span></div><div class="message-text">My name is Gemini</div><div class="message-result"><details class="pyglove dict"><summary><div class="summary-name">result<span class="tooltip">metadata.result</span></div><div class="summary-title">Dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str">x</span><span class="tooltip">metadata.result.x</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key str">y</span><span class="tooltip">metadata.result.y</span></td><td><span class="simple-value int">2</span></td></tr><tr><td><span class="object-key str">z</span><span class="tooltip">metadata.result.z</span></td><td><details class="pyglove dict"><summary><div class="summary-title">Dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str">a</span><span class="tooltip">metadata.result.z.a</span></td><td><details class="pyglove list"><summary><div class="summary-title">List(...)</div></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">metadata.result.z.a[0]</span></td><td><span class="simple-value int">12</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">metadata.result.z.a[1]</span></td><td><span class="simple-value int">323</span></td></tr></table></div></details></td></tr></table></div></details></td></tr></table></div></details></div><div class="message-usage"><details class="pyglove lm-sampling-usage"><summary><div class="summary-name">llm usage<span class="tooltip">metadata.usage</span></div><div class="summary-title">LMSamplingUsage(...)</div></summary><div class="complex-value lm-sampling-usage"><table><tr><td><span class="object-key str">prompt_tokens</span><span class="tooltip">metadata.usage.prompt_tokens</span></td><td><span class="simple-value int">10</span></td></tr><tr><td><span class="object-key str">completion_tokens</span><span class="tooltip">metadata.usage.completion_tokens</span></td><td><span class="simple-value int">2</span></td></tr><tr><td><span class="object-key str">total_tokens</span><span class="tooltip">metadata.usage.total_tokens</span></td><td><span class="simple-value int">12</span></td></tr><tr><td><span class="object-key str">num_requests</span><span class="tooltip">metadata.usage.num_requests</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key str">estimated_cost</span><span class="tooltip">metadata.usage.estimated_cost</span></td><td><span class="simple-value none-type">None</span></td></tr></table></div></details></div><div class="message-metadata"><details class="pyglove dict message-metadata"><summary><div class="summary-name message-metadata">metadata<span class="tooltip message-metadata">metadata</span></div><div class="summary-title message-metadata">Dict(...)</div></summary><div class="complex-value dict"><span class="empty-container"></span></div></details></div><details class="pyglove user-message lf-message"><summary><div class="summary-name lf-message">source<span class="tooltip lf-message">source</span></div><div class="summary-title lf-message">UserMessage(...)</div></summary><div class="complex_value"><div class="message-tags"><span>lm-input</span></div><div class="message-text">What is in this image?<div class="modality-in-text"><details open class="pyglove custom-modality"><summary><div class="summary-name">image<span class="tooltip">source.metadata.image</span></div><div class="summary-title">CustomModality(...)</div></summary><div class="complex-value custom-modality"><table><tr><td><span class="object-key str">content</span><span class="tooltip">source.metadata.image.content</span></td><td><span class="simple-value str">'foo'</span></td></tr></table></div></details></div>this is a test</div><div class="message-metadata"><details class="pyglove dict message-metadata"><summary><div class="summary-name message-metadata">metadata<span class="tooltip message-metadata">source.metadata</span></div><div class="summary-title message-metadata">Dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str">image</span><span class="tooltip">source.metadata.image</span></td><td><details class="pyglove custom-modality"><summary><div class="summary-title">CustomModality(...)</div></summary><div class="complex-value custom-modality"><table><tr><td><span class="object-key str">content</span><span class="tooltip">source.metadata.image.content</span></td><td><span class="simple-value str">'foo'</span></td></tr></table></div></details></td></tr></table></div></details></div><details class="pyglove user-message lf-message"><summary><div class="summary-name lf-message">source<span class="tooltip lf-message">source.source</span></div><div class="summary-title lf-message">UserMessage(...)</div></summary><div class="complex_value"><div class="message-tags"></div><div class="message-text">User input</div><div class="message-metadata"><details class="pyglove dict message-metadata"><summary><div class="summary-name message-metadata">metadata<span class="tooltip message-metadata">source.source.metadata</span></div><div class="summary-title message-metadata">Dict(...)</div></summary><div class="complex-value dict"><span class="empty-container"></span></div></details></div></div></details></div></details></div></details>
|
389
476
|
"""
|
390
477
|
)
|
391
478
|
self.assert_html_content(
|
392
479
|
ai_message.to_html(
|
480
|
+
key_style='label',
|
393
481
|
enable_summary_tooltip=False,
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
482
|
+
extra_flags=dict(
|
483
|
+
collapse_modalities_in_text=True,
|
484
|
+
collapse_llm_usage=False,
|
485
|
+
collapse_message_result_level=1,
|
486
|
+
collapse_message_metadata_level=1,
|
487
|
+
collapse_source_message_level=2,
|
488
|
+
source_tag=None,
|
489
|
+
),
|
400
490
|
),
|
401
491
|
"""
|
402
|
-
<details open class="pyglove ai-message lf-message"><summary><div class="
|
492
|
+
<details open class="pyglove ai-message lf-message"><summary><div class="summary-title lf-message">AIMessage(...)</div></summary><div class="complex_value"><div class="message-tags"><span>lm-response</span><span>lm-output</span></div><div class="message-text">My name is Gemini</div><div class="message-result"><details open class="pyglove dict"><summary><div class="summary-name">result<span class="tooltip">metadata.result</span></div><div class="summary-title">Dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str">x</span><span class="tooltip">metadata.result.x</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key str">y</span><span class="tooltip">metadata.result.y</span></td><td><span class="simple-value int">2</span></td></tr><tr><td><span class="object-key str">z</span><span class="tooltip">metadata.result.z</span></td><td><details class="pyglove dict"><summary><div class="summary-title">Dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str">a</span><span class="tooltip">metadata.result.z.a</span></td><td><details class="pyglove list"><summary><div class="summary-title">List(...)</div></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">metadata.result.z.a[0]</span></td><td><span class="simple-value int">12</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">metadata.result.z.a[1]</span></td><td><span class="simple-value int">323</span></td></tr></table></div></details></td></tr></table></div></details></td></tr></table></div></details></div><div class="message-usage"><details open class="pyglove lm-sampling-usage"><summary><div class="summary-name">llm usage<span class="tooltip">metadata.usage</span></div><div class="summary-title">LMSamplingUsage(...)</div></summary><div class="complex-value lm-sampling-usage"><table><tr><td><span class="object-key str">prompt_tokens</span><span class="tooltip">metadata.usage.prompt_tokens</span></td><td><span class="simple-value int">10</span></td></tr><tr><td><span class="object-key str">completion_tokens</span><span class="tooltip">metadata.usage.completion_tokens</span></td><td><span class="simple-value int">2</span></td></tr><tr><td><span class="object-key str">total_tokens</span><span class="tooltip">metadata.usage.total_tokens</span></td><td><span class="simple-value int">12</span></td></tr><tr><td><span class="object-key str">num_requests</span><span class="tooltip">metadata.usage.num_requests</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key str">estimated_cost</span><span class="tooltip">metadata.usage.estimated_cost</span></td><td><span class="simple-value none-type">None</span></td></tr></table></div></details></div><div class="message-metadata"><details open class="pyglove dict message-metadata"><summary><div class="summary-name message-metadata">metadata<span class="tooltip message-metadata">metadata</span></div><div class="summary-title message-metadata">Dict(...)</div></summary><div class="complex-value dict"><span class="empty-container"></span></div></details></div><details open class="pyglove user-message lf-message"><summary><div class="summary-name lf-message">source<span class="tooltip lf-message">source</span></div><div class="summary-title lf-message">UserMessage(...)</div></summary><div class="complex_value"><div class="message-tags"><span>lm-input</span></div><div class="message-text">What is in this image?<div class="modality-in-text"><details class="pyglove custom-modality"><summary><div class="summary-name">image<span class="tooltip">source.metadata.image</span></div><div class="summary-title">CustomModality(...)</div></summary><div class="complex-value custom-modality"><table><tr><td><span class="object-key str">content</span><span class="tooltip">source.metadata.image.content</span></td><td><span class="simple-value str">'foo'</span></td></tr></table></div></details></div>this is a test</div><div class="message-metadata"><details open class="pyglove dict message-metadata"><summary><div class="summary-name message-metadata">metadata<span class="tooltip message-metadata">source.metadata</span></div><div class="summary-title message-metadata">Dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str">image</span><span class="tooltip">source.metadata.image</span></td><td><details class="pyglove custom-modality"><summary><div class="summary-title">CustomModality(...)</div></summary><div class="complex-value custom-modality"><table><tr><td><span class="object-key str">content</span><span class="tooltip">source.metadata.image.content</span></td><td><span class="simple-value str">'foo'</span></td></tr></table></div></details></td></tr></table></div></details></div><details open class="pyglove user-message lf-message"><summary><div class="summary-name lf-message">source<span class="tooltip lf-message">source.source</span></div><div class="summary-title lf-message">UserMessage(...)</div></summary><div class="complex_value"><div class="message-tags"></div><div class="message-text">User input</div><div class="message-metadata"><details open class="pyglove dict message-metadata"><summary><div class="summary-name message-metadata">metadata<span class="tooltip message-metadata">source.source.metadata</span></div><div class="summary-title message-metadata">Dict(...)</div></summary><div class="complex-value dict"><span class="empty-container"></span></div></details></div></div></details></div></details></div></details>
|
403
493
|
"""
|
404
494
|
)
|
405
495
|
|
langfun/core/modalities/mime.py
CHANGED
@@ -15,7 +15,7 @@
|
|
15
15
|
|
16
16
|
import base64
|
17
17
|
import functools
|
18
|
-
from typing import Annotated, Iterable, Type, Union
|
18
|
+
from typing import Annotated, Any, Iterable, Type, Union
|
19
19
|
import langfun.core as lf
|
20
20
|
import pyglove as pg
|
21
21
|
import requests
|
@@ -183,35 +183,47 @@ class Mime(lf.Modality):
|
|
183
183
|
**kwargs) -> str:
|
184
184
|
return self._raw_html()
|
185
185
|
|
186
|
-
def
|
186
|
+
def _html_tree_view(
|
187
187
|
self,
|
188
188
|
view: pg.views.HtmlTreeView,
|
189
|
-
|
190
|
-
display_modality_when_hover: bool = pg.View.PresetArgValue(False), # pytype: disable=annotation-type-mismatch
|
189
|
+
extra_flags: dict[str, Any] | None = None,
|
191
190
|
**kwargs
|
192
191
|
):
|
192
|
+
extra_flags = extra_flags if extra_flags is not None else {}
|
193
|
+
raw_mime_content = extra_flags.get('raw_mime_content', False)
|
194
|
+
display_modality_when_hover = extra_flags.get(
|
195
|
+
'display_modality_when_hover', False
|
196
|
+
)
|
193
197
|
if raw_mime_content:
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
198
|
+
kwargs['enable_summary'] = False
|
199
|
+
elif display_modality_when_hover:
|
200
|
+
kwargs.update(
|
201
|
+
enable_summary=True,
|
202
|
+
enable_summary_tooltip=True,
|
203
|
+
)
|
204
|
+
return super()._html_tree_view(
|
205
|
+
view=view, extra_flags=extra_flags, **kwargs
|
206
|
+
)
|
207
|
+
|
208
|
+
def _html_tree_view_summary(
|
204
209
|
self,
|
205
210
|
*,
|
206
211
|
view: pg.views.HtmlTreeView,
|
207
|
-
|
208
|
-
display_modality_when_hover: bool = pg.View.PresetArgValue(False), # pytype: disable=annotation-type-mismatch
|
212
|
+
extra_flags: dict[str, Any] | None = None,
|
209
213
|
**kwargs
|
210
214
|
):
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
+
extra_flags = extra_flags or {}
|
216
|
+
if extra_flags.get('display_modality_when_hover', False):
|
217
|
+
def summary_tooltip(*args, content: str | None = None, **kwargs):
|
218
|
+
del content
|
219
|
+
return view.tooltip(*args, content=self._raw_html(), **kwargs)
|
220
|
+
else:
|
221
|
+
summary_tooltip = None
|
222
|
+
return super()._html_tree_view_summary(
|
223
|
+
view=view,
|
224
|
+
summary_tooltip_fn=summary_tooltip,
|
225
|
+
extra_flags=extra_flags,
|
226
|
+
**kwargs
|
215
227
|
)
|
216
228
|
|
217
229
|
def _raw_html(self) -> str:
|