langfun 0.1.2.dev202412110804__tar.gz → 0.1.2.dev202412130804__tar.gz

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 (160) hide show
  1. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/PKG-INFO +1 -1
  2. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/agentic/action.py +169 -199
  3. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/agentic/action_test.py +3 -3
  4. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/v2/experiment.py +27 -0
  5. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/v2/experiment_test.py +11 -0
  6. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/llms/__init__.py +4 -1
  7. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/llms/google_genai.py +17 -4
  8. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/llms/vertexai.py +28 -2
  9. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/structured/prompting.py +48 -13
  10. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/structured/prompting_test.py +1 -0
  11. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/template.py +23 -37
  12. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/template_test.py +6 -26
  13. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun.egg-info/PKG-INFO +1 -1
  14. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/LICENSE +0 -0
  15. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/README.md +0 -0
  16. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/__init__.py +0 -0
  17. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/__init__.py +0 -0
  18. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/agentic/__init__.py +0 -0
  19. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/agentic/action_eval.py +0 -0
  20. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/agentic/action_eval_test.py +0 -0
  21. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/coding/__init__.py +0 -0
  22. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/coding/python/__init__.py +0 -0
  23. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/coding/python/correction.py +0 -0
  24. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/coding/python/correction_test.py +0 -0
  25. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/coding/python/errors.py +0 -0
  26. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/coding/python/errors_test.py +0 -0
  27. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/coding/python/execution.py +0 -0
  28. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/coding/python/execution_test.py +0 -0
  29. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/coding/python/generation.py +0 -0
  30. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/coding/python/generation_test.py +0 -0
  31. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/coding/python/parsing.py +0 -0
  32. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/coding/python/parsing_test.py +0 -0
  33. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/coding/python/permissions.py +0 -0
  34. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/coding/python/permissions_test.py +0 -0
  35. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/component.py +0 -0
  36. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/component_test.py +0 -0
  37. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/concurrent.py +0 -0
  38. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/concurrent_test.py +0 -0
  39. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/console.py +0 -0
  40. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/console_test.py +0 -0
  41. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/__init__.py +0 -0
  42. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/base.py +0 -0
  43. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/base_test.py +0 -0
  44. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/matching.py +0 -0
  45. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/matching_test.py +0 -0
  46. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/patching.py +0 -0
  47. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/patching_test.py +0 -0
  48. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/scoring.py +0 -0
  49. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/scoring_test.py +0 -0
  50. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/v2/__init__.py +0 -0
  51. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/v2/checkpointing.py +0 -0
  52. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/v2/checkpointing_test.py +0 -0
  53. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/v2/evaluation.py +0 -0
  54. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/v2/evaluation_test.py +0 -0
  55. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/v2/example.py +0 -0
  56. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/v2/example_test.py +0 -0
  57. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/v2/metric_values.py +0 -0
  58. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/v2/metric_values_test.py +0 -0
  59. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/v2/metrics.py +0 -0
  60. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/v2/metrics_test.py +0 -0
  61. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/v2/progress.py +0 -0
  62. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/v2/progress_test.py +0 -0
  63. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/v2/progress_tracking.py +0 -0
  64. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/v2/progress_tracking_test.py +0 -0
  65. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/v2/reporting.py +0 -0
  66. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/v2/reporting_test.py +0 -0
  67. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/v2/runners.py +0 -0
  68. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/v2/runners_test.py +0 -0
  69. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/eval/v2/test_helper.py +0 -0
  70. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/langfunc.py +0 -0
  71. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/langfunc_test.py +0 -0
  72. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/language_model.py +0 -0
  73. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/language_model_test.py +0 -0
  74. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/llms/anthropic.py +0 -0
  75. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/llms/anthropic_test.py +0 -0
  76. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/llms/cache/__init__.py +0 -0
  77. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/llms/cache/base.py +0 -0
  78. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/llms/cache/in_memory.py +0 -0
  79. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/llms/cache/in_memory_test.py +0 -0
  80. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/llms/compositional.py +0 -0
  81. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/llms/compositional_test.py +0 -0
  82. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/llms/fake.py +0 -0
  83. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/llms/fake_test.py +0 -0
  84. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/llms/google_genai_test.py +0 -0
  85. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/llms/groq.py +0 -0
  86. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/llms/groq_test.py +0 -0
  87. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/llms/llama_cpp.py +0 -0
  88. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/llms/llama_cpp_test.py +0 -0
  89. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/llms/openai.py +0 -0
  90. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/llms/openai_test.py +0 -0
  91. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/llms/rest.py +0 -0
  92. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/llms/rest_test.py +0 -0
  93. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/llms/vertexai_test.py +0 -0
  94. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/logging.py +0 -0
  95. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/logging_test.py +0 -0
  96. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/memories/__init__.py +0 -0
  97. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/memories/conversation_history.py +0 -0
  98. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/memories/conversation_history_test.py +0 -0
  99. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/memory.py +0 -0
  100. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/message.py +0 -0
  101. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/message_test.py +0 -0
  102. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/modalities/__init__.py +0 -0
  103. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/modalities/audio.py +0 -0
  104. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/modalities/audio_test.py +0 -0
  105. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/modalities/image.py +0 -0
  106. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/modalities/image_test.py +0 -0
  107. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/modalities/mime.py +0 -0
  108. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/modalities/mime_test.py +0 -0
  109. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/modalities/ms_office.py +0 -0
  110. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/modalities/ms_office_test.py +0 -0
  111. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/modalities/pdf.py +0 -0
  112. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/modalities/pdf_test.py +0 -0
  113. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/modalities/video.py +0 -0
  114. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/modalities/video_test.py +0 -0
  115. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/modality.py +0 -0
  116. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/modality_test.py +0 -0
  117. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/natural_language.py +0 -0
  118. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/natural_language_test.py +0 -0
  119. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/repr_utils.py +0 -0
  120. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/repr_utils_test.py +0 -0
  121. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/sampling.py +0 -0
  122. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/sampling_test.py +0 -0
  123. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/structured/__init__.py +0 -0
  124. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/structured/completion.py +0 -0
  125. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/structured/completion_test.py +0 -0
  126. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/structured/description.py +0 -0
  127. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/structured/description_test.py +0 -0
  128. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/structured/function_generation.py +0 -0
  129. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/structured/function_generation_test.py +0 -0
  130. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/structured/mapping.py +0 -0
  131. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/structured/mapping_test.py +0 -0
  132. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/structured/parsing.py +0 -0
  133. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/structured/parsing_test.py +0 -0
  134. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/structured/schema.py +0 -0
  135. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/structured/schema_generation.py +0 -0
  136. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/structured/schema_generation_test.py +0 -0
  137. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/structured/schema_test.py +0 -0
  138. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/structured/scoring.py +0 -0
  139. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/structured/scoring_test.py +0 -0
  140. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/structured/tokenization.py +0 -0
  141. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/structured/tokenization_test.py +0 -0
  142. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/subscription.py +0 -0
  143. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/subscription_test.py +0 -0
  144. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/templates/__init__.py +0 -0
  145. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/templates/completion.py +0 -0
  146. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/templates/completion_test.py +0 -0
  147. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/templates/conversation.py +0 -0
  148. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/templates/conversation_test.py +0 -0
  149. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/templates/demonstration.py +0 -0
  150. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/templates/demonstration_test.py +0 -0
  151. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/templates/selfplay.py +0 -0
  152. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/templates/selfplay_test.py +0 -0
  153. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/text_formatting.py +0 -0
  154. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun/core/text_formatting_test.py +0 -0
  155. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun.egg-info/SOURCES.txt +0 -0
  156. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun.egg-info/dependency_links.txt +0 -0
  157. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun.egg-info/requires.txt +0 -0
  158. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/langfun.egg-info/top_level.txt +0 -0
  159. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/setup.cfg +0 -0
  160. {langfun-0.1.2.dev202412110804 → langfun-0.1.2.dev202412130804}/setup.py +0 -0
@@ -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.dev202412130804
4
4
  Summary: Langfun: Language as Functions.
5
5
  Home-page: https://github.com/google/langfun
6
6
  Author: Langfun Authors
@@ -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