langfun 0.1.1.dev20240826__tar.gz → 0.1.1.dev202408282153__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 (133) hide show
  1. {langfun-0.1.1.dev20240826/langfun.egg-info → langfun-0.1.1.dev202408282153}/PKG-INFO +78 -14
  2. langfun-0.1.1.dev20240826/PKG-INFO → langfun-0.1.1.dev202408282153/README.md +31 -39
  3. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/concurrent.py +148 -21
  4. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/concurrent_test.py +58 -8
  5. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/eval/base.py +8 -8
  6. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/eval/base_test.py +1 -1
  7. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/langfunc.py +3 -0
  8. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/langfunc_test.py +6 -3
  9. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/language_model.py +10 -0
  10. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/llms/cache/base.py +21 -2
  11. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/llms/cache/in_memory.py +7 -0
  12. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/llms/cache/in_memory_test.py +45 -0
  13. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/llms/google_genai.py +40 -13
  14. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/llms/openai.py +34 -17
  15. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/llms/vertexai.py +30 -9
  16. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/message.py +10 -0
  17. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/message_test.py +14 -0
  18. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/modalities/image.py +17 -5
  19. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/modalities/mime.py +13 -4
  20. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/modalities/ms_office.py +17 -8
  21. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/modality.py +12 -0
  22. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/modality_test.py +1 -0
  23. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/structured/mapping.py +6 -0
  24. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/structured/prompting_test.py +12 -8
  25. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/text_formatting.py +7 -1
  26. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/text_formatting_test.py +18 -0
  27. langfun-0.1.1.dev202408282153/langfun.egg-info/PKG-INFO +231 -0
  28. langfun-0.1.1.dev202408282153/langfun.egg-info/requires.txt +60 -0
  29. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/setup.py +37 -15
  30. langfun-0.1.1.dev20240826/README.md +0 -130
  31. langfun-0.1.1.dev20240826/langfun.egg-info/requires.txt +0 -13
  32. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/LICENSE +0 -0
  33. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/__init__.py +0 -0
  34. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/__init__.py +0 -0
  35. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/coding/__init__.py +0 -0
  36. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/coding/python/__init__.py +0 -0
  37. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/coding/python/correction.py +0 -0
  38. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/coding/python/correction_test.py +0 -0
  39. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/coding/python/errors.py +0 -0
  40. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/coding/python/errors_test.py +0 -0
  41. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/coding/python/execution.py +0 -0
  42. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/coding/python/execution_test.py +0 -0
  43. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/coding/python/generation.py +0 -0
  44. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/coding/python/generation_test.py +0 -0
  45. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/coding/python/parsing.py +0 -0
  46. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/coding/python/parsing_test.py +0 -0
  47. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/coding/python/permissions.py +0 -0
  48. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/coding/python/permissions_test.py +0 -0
  49. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/component.py +0 -0
  50. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/component_test.py +0 -0
  51. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/console.py +0 -0
  52. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/console_test.py +0 -0
  53. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/eval/__init__.py +0 -0
  54. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/eval/matching.py +0 -0
  55. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/eval/matching_test.py +0 -0
  56. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/eval/patching.py +0 -0
  57. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/eval/patching_test.py +0 -0
  58. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/eval/scoring.py +0 -0
  59. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/eval/scoring_test.py +0 -0
  60. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/language_model_test.py +0 -0
  61. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/llms/__init__.py +0 -0
  62. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/llms/anthropic.py +0 -0
  63. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/llms/anthropic_test.py +0 -0
  64. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/llms/cache/__init__.py +0 -0
  65. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/llms/fake.py +0 -0
  66. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/llms/fake_test.py +0 -0
  67. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/llms/google_genai_test.py +0 -0
  68. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/llms/groq.py +0 -0
  69. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/llms/groq_test.py +0 -0
  70. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/llms/llama_cpp.py +0 -0
  71. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/llms/llama_cpp_test.py +0 -0
  72. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/llms/openai_test.py +0 -0
  73. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/llms/rest.py +0 -0
  74. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/llms/rest_test.py +0 -0
  75. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/llms/vertexai_test.py +0 -0
  76. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/logging.py +0 -0
  77. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/logging_test.py +0 -0
  78. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/memories/__init__.py +0 -0
  79. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/memories/conversation_history.py +0 -0
  80. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/memories/conversation_history_test.py +0 -0
  81. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/memory.py +0 -0
  82. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/modalities/__init__.py +0 -0
  83. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/modalities/audio.py +0 -0
  84. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/modalities/audio_test.py +0 -0
  85. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/modalities/image_test.py +0 -0
  86. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/modalities/mime_test.py +0 -0
  87. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/modalities/ms_office_test.py +0 -0
  88. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/modalities/pdf.py +0 -0
  89. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/modalities/pdf_test.py +0 -0
  90. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/modalities/video.py +0 -0
  91. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/modalities/video_test.py +0 -0
  92. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/natural_language.py +0 -0
  93. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/natural_language_test.py +0 -0
  94. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/repr_utils.py +0 -0
  95. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/repr_utils_test.py +0 -0
  96. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/sampling.py +0 -0
  97. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/sampling_test.py +0 -0
  98. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/structured/__init__.py +0 -0
  99. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/structured/completion.py +0 -0
  100. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/structured/completion_test.py +0 -0
  101. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/structured/description.py +0 -0
  102. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/structured/description_test.py +0 -0
  103. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/structured/function_generation.py +0 -0
  104. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/structured/function_generation_test.py +0 -0
  105. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/structured/mapping_test.py +0 -0
  106. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/structured/parsing.py +0 -0
  107. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/structured/parsing_test.py +0 -0
  108. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/structured/prompting.py +0 -0
  109. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/structured/schema.py +0 -0
  110. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/structured/schema_generation.py +0 -0
  111. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/structured/schema_generation_test.py +0 -0
  112. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/structured/schema_test.py +0 -0
  113. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/structured/scoring.py +0 -0
  114. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/structured/scoring_test.py +0 -0
  115. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/structured/tokenization.py +0 -0
  116. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/structured/tokenization_test.py +0 -0
  117. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/subscription.py +0 -0
  118. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/subscription_test.py +0 -0
  119. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/template.py +0 -0
  120. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/template_test.py +0 -0
  121. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/templates/__init__.py +0 -0
  122. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/templates/completion.py +0 -0
  123. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/templates/completion_test.py +0 -0
  124. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/templates/conversation.py +0 -0
  125. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/templates/conversation_test.py +0 -0
  126. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/templates/demonstration.py +0 -0
  127. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/templates/demonstration_test.py +0 -0
  128. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/templates/selfplay.py +0 -0
  129. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun/core/templates/selfplay_test.py +0 -0
  130. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun.egg-info/SOURCES.txt +0 -0
  131. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun.egg-info/dependency_links.txt +0 -0
  132. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/langfun.egg-info/top_level.txt +0 -0
  133. {langfun-0.1.1.dev20240826 → langfun-0.1.1.dev202408282153}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: langfun
3
- Version: 0.1.1.dev20240826
3
+ Version: 0.1.1.dev202408282153
4
4
  Summary: Langfun: Language as Functions.
5
5
  Home-page: https://github.com/google/langfun
6
6
  Author: Langfun Authors
@@ -21,19 +21,54 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
21
  Classifier: Topic :: Software Development :: Libraries
22
22
  Description-Content-Type: text/markdown
23
23
  License-File: LICENSE
24
- Requires-Dist: google-cloud-aiplatform>=1.5.0
25
- Requires-Dist: google-generativeai>=0.3.2
24
+ Requires-Dist: pyglove>=0.4.5.dev20240824
26
25
  Requires-Dist: jinja2>=3.1.2
27
- Requires-Dist: openai==0.27.2
28
- Requires-Dist: openpyxl>=3.1.0
29
- Requires-Dist: pandas>=2.0.3
30
- Requires-Dist: pyglove>=0.4.5.dev20240423
31
- Requires-Dist: python-docx>=0.8.11
32
- Requires-Dist: python-magic>=0.4.27
33
26
  Requires-Dist: requests>=2.31.0
34
- Requires-Dist: termcolor==1.1.0
35
- Requires-Dist: tqdm>=4.64.1
36
- Requires-Dist: pillow>=10.0.0
27
+ Provides-Extra: all
28
+ Requires-Dist: pyglove>=0.4.5.dev20240824; extra == "all"
29
+ Requires-Dist: jinja2>=3.1.2; extra == "all"
30
+ Requires-Dist: requests>=2.31.0; extra == "all"
31
+ Requires-Dist: termcolor==1.1.0; extra == "all"
32
+ Requires-Dist: tqdm>=4.64.1; extra == "all"
33
+ Requires-Dist: google-cloud-aiplatform>=1.5.0; extra == "all"
34
+ Requires-Dist: google-generativeai>=0.3.2; extra == "all"
35
+ Requires-Dist: openai>=0.27.2; extra == "all"
36
+ Requires-Dist: python-magic>=0.4.27; extra == "all"
37
+ Requires-Dist: python-docx>=0.8.11; extra == "all"
38
+ Requires-Dist: pillow>=10.0.0; extra == "all"
39
+ Requires-Dist: openpyxl>=3.1.0; extra == "all"
40
+ Requires-Dist: pandas>=2.0.3; extra == "all"
41
+ Provides-Extra: ui
42
+ Requires-Dist: termcolor==1.1.0; extra == "ui"
43
+ Requires-Dist: tqdm>=4.64.1; extra == "ui"
44
+ Provides-Extra: llm
45
+ Requires-Dist: google-cloud-aiplatform>=1.5.0; extra == "llm"
46
+ Requires-Dist: google-generativeai>=0.3.2; extra == "llm"
47
+ Requires-Dist: openai>=0.27.2; extra == "llm"
48
+ Provides-Extra: llm-google
49
+ Requires-Dist: google-cloud-aiplatform>=1.5.0; extra == "llm-google"
50
+ Requires-Dist: google-generativeai>=0.3.2; extra == "llm-google"
51
+ Provides-Extra: llm-google-vertex
52
+ Requires-Dist: google-cloud-aiplatform>=1.5.0; extra == "llm-google-vertex"
53
+ Provides-Extra: llm-google-genai
54
+ Requires-Dist: google-generativeai>=0.3.2; extra == "llm-google-genai"
55
+ Provides-Extra: llm-openai
56
+ Requires-Dist: openai>=0.27.2; extra == "llm-openai"
57
+ Provides-Extra: mime
58
+ Requires-Dist: python-magic>=0.4.27; extra == "mime"
59
+ Requires-Dist: python-docx>=0.8.11; extra == "mime"
60
+ Requires-Dist: pillow>=10.0.0; extra == "mime"
61
+ Requires-Dist: openpyxl>=3.1.0; extra == "mime"
62
+ Requires-Dist: pandas>=2.0.3; extra == "mime"
63
+ Provides-Extra: mime-auto
64
+ Requires-Dist: python-magic>=0.4.27; extra == "mime-auto"
65
+ Provides-Extra: mime-docx
66
+ Requires-Dist: python-docx>=0.8.11; extra == "mime-docx"
67
+ Provides-Extra: mime-pil
68
+ Requires-Dist: pillow>=10.0.0; extra == "mime-pil"
69
+ Provides-Extra: mime-xlsx
70
+ Requires-Dist: openpyxl>=3.1.0; extra == "mime-xlsx"
71
+ Requires-Dist: pandas>=2.0.3; extra == "mime-xlsx"
37
72
 
38
73
  <div align="center">
39
74
  <img src="https://raw.githubusercontent.com/google/langfun/main/docs/_static/logo.svg" width="520px" alt="logo"></img>
@@ -152,16 +187,45 @@ See [Langfun 101](https://colab.research.google.com/github/google/langfun/blob/m
152
187
 
153
188
  ## Install
154
189
 
190
+ Langfun offers a range of features through [Extras](https://packaging.python.org/en/latest/tutorials/installing-packages/#installing-extras), allowing users to install only what they need. The minimal installation of Langfun requires only [PyGlove](https://github.com/google/pyglove), [Jinja2](https://github.com/pallets/jinja/), and [requests](https://github.com/psf/requests). To install Langfun with its minimal dependencies, use:
191
+
155
192
  ```
156
193
  pip install langfun
157
194
  ```
158
195
 
159
- Or install nightly build with:
196
+ For a complete installation with all dependencies, use:
160
197
 
161
198
  ```
162
- pip install langfun --pre
199
+ pip install langfun[all]
163
200
  ```
164
201
 
202
+ To install a nightly build, include the `--pre` flag, like this:
203
+
204
+ ```
205
+ pip install langfun[all] --pre
206
+ ```
165
207
 
208
+ If you want to customize your installation, you can select specific features using package names like `langfun[X1, X2, ..., Xn]`, where `Xi` corresponds to a tag from the list below:
209
+
210
+ | Tag | Description |
211
+ | ------------------- | ---------------------------------------- |
212
+ | all | All Langfun features. |
213
+ | llm | All supported LLMs. |
214
+ | llm-google | All supported Google-powered LLMs. |
215
+ | llm-google-vertexai | LLMs powered by Google Cloud VertexAI |
216
+ | llm-google-genai | LLMs powered by Google Generative AI API |
217
+ | llm-openai | LLMs powered by OpenAI |
218
+ | mime | All MIME supports. |
219
+ | mime-auto | Automatic MIME type detection. |
220
+ | mime-docx | DocX format support. |
221
+ | mime-pil | Image support for PIL. |
222
+ | mime-xlsx | XlsX format support. |
223
+ | ui | UI enhancements |
224
+
225
+
226
+ For example, to install a nightly build that includes Google-powered LLMs, full modality support, and UI enhancements, use:
227
+ ```
228
+ pip install langfun[llm-google,mime,ui] --pre
229
+ ```
166
230
 
167
231
  *Disclaimer: this is not an officially supported Google product.*
@@ -1,40 +1,3 @@
1
- Metadata-Version: 2.1
2
- Name: langfun
3
- Version: 0.1.1.dev20240826
4
- Summary: Langfun: Language as Functions.
5
- Home-page: https://github.com/google/langfun
6
- Author: Langfun Authors
7
- Author-email: langfun-authors@google.com
8
- License: Apache License 2.0
9
- Keywords: llm generative-ai machine-learning
10
- Classifier: Development Status :: 3 - Alpha
11
- Classifier: Intended Audience :: Developers
12
- Classifier: Intended Audience :: Education
13
- Classifier: Intended Audience :: Science/Research
14
- Classifier: License :: OSI Approved :: Apache Software License
15
- Classifier: Programming Language :: Python :: 3
16
- Classifier: Programming Language :: Python :: 3.10
17
- Classifier: Programming Language :: Python :: 3.11
18
- Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
19
- Classifier: Topic :: Scientific/Engineering :: Human Machine Interfaces
20
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
- Classifier: Topic :: Software Development :: Libraries
22
- Description-Content-Type: text/markdown
23
- License-File: LICENSE
24
- Requires-Dist: google-cloud-aiplatform>=1.5.0
25
- Requires-Dist: google-generativeai>=0.3.2
26
- Requires-Dist: jinja2>=3.1.2
27
- Requires-Dist: openai==0.27.2
28
- Requires-Dist: openpyxl>=3.1.0
29
- Requires-Dist: pandas>=2.0.3
30
- Requires-Dist: pyglove>=0.4.5.dev20240423
31
- Requires-Dist: python-docx>=0.8.11
32
- Requires-Dist: python-magic>=0.4.27
33
- Requires-Dist: requests>=2.31.0
34
- Requires-Dist: termcolor==1.1.0
35
- Requires-Dist: tqdm>=4.64.1
36
- Requires-Dist: pillow>=10.0.0
37
-
38
1
  <div align="center">
39
2
  <img src="https://raw.githubusercontent.com/google/langfun/main/docs/_static/logo.svg" width="520px" alt="logo"></img>
40
3
  </div>
@@ -152,16 +115,45 @@ See [Langfun 101](https://colab.research.google.com/github/google/langfun/blob/m
152
115
 
153
116
  ## Install
154
117
 
118
+ Langfun offers a range of features through [Extras](https://packaging.python.org/en/latest/tutorials/installing-packages/#installing-extras), allowing users to install only what they need. The minimal installation of Langfun requires only [PyGlove](https://github.com/google/pyglove), [Jinja2](https://github.com/pallets/jinja/), and [requests](https://github.com/psf/requests). To install Langfun with its minimal dependencies, use:
119
+
155
120
  ```
156
121
  pip install langfun
157
122
  ```
158
123
 
159
- Or install nightly build with:
124
+ For a complete installation with all dependencies, use:
160
125
 
161
126
  ```
162
- pip install langfun --pre
127
+ pip install langfun[all]
163
128
  ```
164
129
 
130
+ To install a nightly build, include the `--pre` flag, like this:
165
131
 
132
+ ```
133
+ pip install langfun[all] --pre
134
+ ```
135
+
136
+ If you want to customize your installation, you can select specific features using package names like `langfun[X1, X2, ..., Xn]`, where `Xi` corresponds to a tag from the list below:
137
+
138
+ | Tag | Description |
139
+ | ------------------- | ---------------------------------------- |
140
+ | all | All Langfun features. |
141
+ | llm | All supported LLMs. |
142
+ | llm-google | All supported Google-powered LLMs. |
143
+ | llm-google-vertexai | LLMs powered by Google Cloud VertexAI |
144
+ | llm-google-genai | LLMs powered by Google Generative AI API |
145
+ | llm-openai | LLMs powered by OpenAI |
146
+ | mime | All MIME supports. |
147
+ | mime-auto | Automatic MIME type detection. |
148
+ | mime-docx | DocX format support. |
149
+ | mime-pil | Image support for PIL. |
150
+ | mime-xlsx | XlsX format support. |
151
+ | ui | UI enhancements |
152
+
153
+
154
+ For example, to install a nightly build that includes Google-powered LLMs, full modality support, and UI enhancements, use:
155
+ ```
156
+ pip install langfun[llm-google,mime,ui] --pre
157
+ ```
166
158
 
167
159
  *Disclaimer: this is not an officially supported Google product.*
@@ -13,17 +13,30 @@
13
13
  # limitations under the License.
14
14
  """Utility library for handling concurrency in langfun."""
15
15
 
16
+ import abc
16
17
  import collections
17
18
  import concurrent.futures
18
19
  import dataclasses
20
+ import io
19
21
  import random
22
+ import sys
20
23
  import threading
21
24
  import time
22
25
  from typing import Any, Callable, Iterable, Iterator, Literal, Sequence, Tuple, Type, Union
23
26
 
24
27
  from langfun.core import component
28
+ from langfun.core import text_formatting
25
29
  import pyglove as pg
26
- from tqdm import auto as tqdm
30
+
31
+
32
+ progress_bar: Literal['tqdm', 'console', None] = None
33
+
34
+ try:
35
+ from tqdm import auto as tqdm # pylint: disable=g-import-not-at-top
36
+ progress_bar = 'tqdm'
37
+ except ImportError as e:
38
+ progress_bar = 'console'
39
+ tqdm = None
27
40
 
28
41
 
29
42
  def with_context_access(func: Callable[..., Any]) -> Callable[..., Any]:
@@ -142,7 +155,6 @@ def with_retry(
142
155
  attempt = 1
143
156
  return base_interval() * (2 ** (attempt - 1))
144
157
 
145
- wait_interval = None
146
158
  wait_intervals = []
147
159
  errors = []
148
160
  while True:
@@ -356,17 +368,17 @@ class ProgressBar:
356
368
  label: str | None
357
369
  total: int
358
370
  color: str | None = None
359
- postfix: dict[str, str] | None = None
371
+ status: dict[str, Any] | None = None
360
372
 
361
373
  @dataclasses.dataclass
362
374
  class Update:
363
375
  """Progress bar update."""
364
376
  bar_id: int
365
377
  delta: int
366
- postfix: Union[dict[str, str], str, None] = None
378
+ status: Union[dict[str, Any], str, None] = None
367
379
  color: str | None = None
368
380
 
369
- _progress_bars: dict[int, tqdm.tqdm] = {}
381
+ _progress_bars: dict[int, '_ProgressControl'] = {}
370
382
  _install_requests: list[tuple[int, Settings]] = []
371
383
  _updates: collections.deque[Update] = collections.deque()
372
384
  _uninstall_requests: list[int] = []
@@ -378,11 +390,11 @@ class ProgressBar:
378
390
  label: str | None,
379
391
  total: int,
380
392
  color: str | None = None,
381
- postfix: dict[str, str] | None = None,
393
+ status: dict[str, Any] | None = None,
382
394
  ) -> int:
383
395
  """Installs a progress bar and returns a reference id."""
384
396
  with cls._lock:
385
- settings = ProgressBar.Settings(label, total, color, postfix)
397
+ settings = ProgressBar.Settings(label, total, color, status)
386
398
  bar_id = id(settings)
387
399
  cls._install_requests.append((bar_id, settings))
388
400
  return bar_id
@@ -392,15 +404,17 @@ class ProgressBar:
392
404
  cls,
393
405
  bar_id: int,
394
406
  delta: int = 0,
395
- postfix: Union[dict[str, str], str, None] = None,
407
+ status: Union[dict[str, Any], str, None] = None,
396
408
  color: str | None = None,
397
409
  refresh: bool = True,
398
410
  ) -> None:
399
411
  """Report the progress for a label."""
412
+ if status is not None and not isinstance(status, (str, dict)):
413
+ raise ValueError(f'Unsupported status: {status}')
400
414
  with cls._lock:
401
415
  cls._updates.append(
402
416
  ProgressBar.Update(
403
- bar_id=bar_id, delta=delta, postfix=postfix, color=color,
417
+ bar_id=bar_id, delta=delta, status=status, color=color,
404
418
  )
405
419
  )
406
420
  if refresh:
@@ -422,11 +436,11 @@ class ProgressBar:
422
436
  # Process install requests.
423
437
  if cls._install_requests:
424
438
  for bar_id, settings in cls._install_requests:
425
- cls._progress_bars[bar_id] = tqdm.tqdm(
439
+ cls._progress_bars[bar_id] = _progress_control(
426
440
  total=settings.total,
427
- desc=settings.label,
428
- colour=settings.color,
429
- postfix=settings.postfix)
441
+ label=settings.label,
442
+ color=settings.color,
443
+ status=settings.status)
430
444
  cls._install_requests.clear()
431
445
 
432
446
  # Process updates.
@@ -441,15 +455,11 @@ class ProgressBar:
441
455
  if update.delta > 0:
442
456
  bar.update(update.delta)
443
457
 
444
- if isinstance(update.postfix, str):
445
- bar.set_postfix_str(update.postfix, refresh=False)
446
- elif isinstance(update.postfix, dict):
447
- bar.set_postfix(update.postfix, refresh=False)
448
- elif update.postfix is not None:
449
- raise ValueError(f'Unsupported postfix: {update.postfix}')
458
+ if update.status is not None:
459
+ bar.set_status(update.status)
450
460
 
451
461
  if update.color is not None:
452
- bar.colour = update.color
462
+ bar.set_color(update.color)
453
463
  updated_bars.add(bar)
454
464
 
455
465
  # Refresh each updated bar just once.
@@ -603,7 +613,7 @@ def concurrent_map(
603
613
  if len(error_text) >= 64:
604
614
  error_text = error_text[:64] + '...'
605
615
  status['LastError'] = error_text
606
- ProgressBar.update(bar_id, delta=1, postfix=status)
616
+ ProgressBar.update(bar_id, delta=1, status=status)
607
617
 
608
618
  try:
609
619
  if ordered:
@@ -729,5 +739,122 @@ class ExecutorPool:
729
739
  raise ValueError(f'Unsupported value: {maybe_executor}.')
730
740
 
731
741
 
742
+ class _ProgressControl(pg.Object):
743
+ """Abstract progress control."""
744
+ # Disable symbolic comparison so the hash is based on object address.
745
+ use_symbolic_comparison = False
746
+
747
+ total: int
748
+ label: str | None
749
+ color: str | None
750
+ status: str | dict[str, Any] | None
751
+
752
+ def set_color(self, color: str | None):
753
+ with pg.notify_on_change(False):
754
+ self.rebind(color=color)
755
+
756
+ def set_status(self, status: str | dict[str, Any] | None):
757
+ with pg.notify_on_change(False):
758
+ self.rebind(status=status)
759
+
760
+ @abc.abstractmethod
761
+ def update(self, delta):
762
+ """Update progress."""
763
+
764
+ @abc.abstractmethod
765
+ def refresh(self) -> None:
766
+ """Refresh progress bar."""
767
+
768
+
769
+ class _TqdmProgressControl(_ProgressControl):
770
+ """Tqdm-based progress control."""
771
+
772
+ def _on_bound(self):
773
+ super()._on_bound()
774
+ assert tqdm is not None
775
+ self._tqdm = tqdm.tqdm(
776
+ total=self.total,
777
+ desc=self.label,
778
+ colour=self.color,
779
+ postfix=self.status,
780
+ )
781
+
782
+ def update(self, delta: int) -> None:
783
+ self._tqdm.update(delta)
784
+
785
+ def refresh(self):
786
+ self._tqdm.set_description(self.label, refresh=False)
787
+ if isinstance(self.status, str):
788
+ self._tqdm.set_postfix_str(self.status, refresh=False)
789
+ else:
790
+ self._tqdm.set_postfix(self.status, refresh=False)
791
+ self._tqdm.colour = self.color
792
+ self._tqdm.refresh()
793
+
794
+
795
+ class _ConsoleProgressControl(_ProgressControl):
796
+ """Simple progress control by printing the status to the console."""
797
+
798
+ def _on_bound(self):
799
+ super()._on_bound()
800
+ self._progress = 0
801
+
802
+ def update(self, delta: int) -> None:
803
+ self._progress += delta
804
+
805
+ def refresh(self):
806
+ s = io.StringIO()
807
+ if self.label is not None:
808
+ s.write(text_formatting.colored(self.label, 'red', styles=['bold']))
809
+ s.write(': ')
810
+ s.write(
811
+ text_formatting.colored(
812
+ '%d%% (%d/%d)' %
813
+ (
814
+ self._progress * 100 // self.total,
815
+ self._progress,
816
+ self.total,
817
+ ),
818
+ color=self.color or 'green'
819
+ )
820
+ )
821
+ if self.status is not None:
822
+ status = repr(self.status) if isinstance(
823
+ self.status, dict) else self.status
824
+ s.write(f' : {status}')
825
+ sys.stderr.write(s.getvalue() + '\n')
826
+
827
+
828
+ class _NoopProgressControl(_ProgressControl):
829
+ """No-op progress control."""
830
+
831
+ def update(self, delta: int) -> None:
832
+ pass
833
+
834
+ def refresh(self) -> None:
835
+ pass
836
+
837
+
838
+ def _progress_control(
839
+ total: int,
840
+ label: str | None,
841
+ color: str | None,
842
+ status: str | dict[str, Any] | None,
843
+ ) -> _ProgressControl:
844
+ """Creates a process control."""
845
+ if progress_bar == 'tqdm':
846
+ if not tqdm:
847
+ raise RuntimeError(
848
+ 'Please install package "tqdm" to use `tqdm` progress bar.'
849
+ )
850
+ return _TqdmProgressControl(total, label, color, status)
851
+ elif progress_bar == 'console':
852
+ return _ConsoleProgressControl(total, label, color, status)
853
+ elif progress_bar is None:
854
+ return _NoopProgressControl(total, label, color, status)
855
+ else:
856
+ raise ValueError(f'Unsupported progress bar type: {progress_bar}')
857
+
858
+
732
859
  # The global executor pool based on resource IDs.
733
860
  _executor_pool = ExecutorPool()
@@ -233,6 +233,57 @@ class ProgressTest(unittest.TestCase):
233
233
  self.assertIs(p.last_error, job2.error)
234
234
 
235
235
 
236
+ class ProgressControlTest(unittest.TestCase):
237
+
238
+ def test_noop(self):
239
+ concurrent.progress_bar = None
240
+ ctrl = concurrent._progress_control(100, 'noop', 'blue', None)
241
+ self.assertIsInstance(ctrl, concurrent._NoopProgressControl)
242
+ string_io = io.StringIO()
243
+ with contextlib.redirect_stderr(string_io):
244
+ ctrl.update(1)
245
+ ctrl.refresh()
246
+ self.assertEqual(string_io.getvalue(), '')
247
+ concurrent.progress_bar = 'tqdm'
248
+
249
+ def test_console(self):
250
+ concurrent.progress_bar = 'console'
251
+ ctrl = concurrent._progress_control(100, 'foo', 'blue', None)
252
+ self.assertIsInstance(ctrl, concurrent._ConsoleProgressControl)
253
+ string_io = io.StringIO()
254
+ with contextlib.redirect_stderr(string_io):
255
+ ctrl.set_status('bar')
256
+ ctrl.update(10)
257
+ ctrl.refresh()
258
+ self.assertEqual(
259
+ string_io.getvalue(),
260
+ '\x1b[1m\x1b[31mfoo\x1b[0m: \x1b[34m10% (10/100)\x1b[0m : bar\n'
261
+ )
262
+ concurrent.progress_bar = 'tqdm'
263
+
264
+ def test_tqdm(self):
265
+ concurrent.progress_bar = 'tqdm'
266
+ string_io = io.StringIO()
267
+ with contextlib.redirect_stderr(string_io):
268
+ ctrl = concurrent._progress_control(100, 'foo', 'blue', None)
269
+ self.assertIsInstance(ctrl, concurrent._TqdmProgressControl)
270
+ ctrl.update(10)
271
+ ctrl.refresh()
272
+ self.assertIn('10/100', string_io.getvalue())
273
+
274
+ tqdm = concurrent.tqdm
275
+ concurrent.tqdm = None
276
+ with self.assertRaisesRegex(RuntimeError, 'install package "tqdm"'):
277
+ _ = concurrent._progress_control(100, 'foo', 'blue', None)
278
+ concurrent.tqdm = tqdm
279
+
280
+ def test_unsupported(self):
281
+ concurrent.progress_bar = 'unknown'
282
+ with self.assertRaisesRegex(ValueError, 'Unsupported progress bar type'):
283
+ _ = concurrent._progress_control(100, 'foo', 'blue', None)
284
+ concurrent.progress_bar = 'tqdm'
285
+
286
+
236
287
  class ProgressBarTest(unittest.TestCase):
237
288
 
238
289
  def test_multithread_support(self):
@@ -241,13 +292,12 @@ class ProgressBarTest(unittest.TestCase):
241
292
  bar_id = concurrent.ProgressBar.install(None, 5)
242
293
  def fun(x):
243
294
  del x
244
- concurrent.ProgressBar.update(bar_id, 1, postfix=None)
295
+ concurrent.ProgressBar.update(bar_id, 1, status=None)
245
296
 
246
297
  for _ in concurrent.concurrent_execute(fun, range(5)):
247
298
  concurrent.ProgressBar.refresh()
248
299
  concurrent.ProgressBar.uninstall(bar_id)
249
300
  output_str = string_io.getvalue()
250
- print(output_str)
251
301
  self.assertIn('100%', output_str)
252
302
  self.assertIn('5/5', output_str)
253
303
 
@@ -255,12 +305,12 @@ class ProgressBarTest(unittest.TestCase):
255
305
  string_io = io.StringIO()
256
306
  with contextlib.redirect_stderr(string_io):
257
307
  bar_id = concurrent.ProgressBar.install(None, 4)
258
- concurrent.ProgressBar.update(bar_id, 1, postfix=None)
259
- concurrent.ProgressBar.update(bar_id, 1, postfix='hello')
260
- concurrent.ProgressBar.update(bar_id, color='lightgreen')
261
- concurrent.ProgressBar.update(bar_id, 2, postfix=dict(x=1))
262
- with self.assertRaisesRegex(ValueError, 'Unsupported postfix'):
263
- concurrent.ProgressBar.update(bar_id, 0, postfix=1)
308
+ concurrent.ProgressBar.update(bar_id, 1, status=None)
309
+ concurrent.ProgressBar.update(bar_id, 1, status='hello')
310
+ concurrent.ProgressBar.update(bar_id, color='green')
311
+ concurrent.ProgressBar.update(bar_id, 2, status=dict(x=1))
312
+ with self.assertRaisesRegex(ValueError, 'Unsupported status'):
313
+ concurrent.ProgressBar.update(bar_id, 0, status=1)
264
314
  concurrent.ProgressBar.uninstall(bar_id)
265
315
  self.assertIn('1/4', string_io.getvalue())
266
316
  self.assertIn('2/4', string_io.getvalue())
@@ -242,7 +242,7 @@ class Evaluable(lf.Component):
242
242
  ):
243
243
  if show_progress:
244
244
  lf.concurrent.ProgressBar.update(
245
- progress_bar, postfix='LOADING SAVED RESULTS...', color='yellow'
245
+ progress_bar, status='LOADING SAVED RESULTS...', color='yellow'
246
246
  )
247
247
  if self.try_load_result():
248
248
  run_status = 'CACHED'
@@ -271,7 +271,7 @@ class Evaluable(lf.Component):
271
271
  if should_save:
272
272
  if show_progress:
273
273
  lf.concurrent.ProgressBar.update(
274
- progress_bar, postfix='SAVING RESULTS...', color='yellow'
274
+ progress_bar, status='SAVING RESULTS...', color='yellow'
275
275
  )
276
276
 
277
277
  # Save evaluation results.
@@ -284,7 +284,7 @@ class Evaluable(lf.Component):
284
284
  if show_progress:
285
285
  lf.concurrent.ProgressBar.update(
286
286
  progress_bar,
287
- postfix=self._completion_status(run_status),
287
+ status=self._completion_status(run_status),
288
288
  color='green',
289
289
  )
290
290
  else:
@@ -340,7 +340,7 @@ class Evaluable(lf.Component):
340
340
  f'[#{leaf.index} - {leaf.node.id}]',
341
341
  total=leaf.node.num_examples if leaf.enabled else 0,
342
342
  color='cyan' if leaf.enabled else 'yellow',
343
- postfix=None if leaf.enabled else 'SKIPPED.')
343
+ status=None if leaf.enabled else 'SKIPPED.')
344
344
 
345
345
  # Run leaf groups in parallel.
346
346
  try:
@@ -354,7 +354,7 @@ class Evaluable(lf.Component):
354
354
  # Save results for non-leaf nodes.
355
355
  lf.concurrent.ProgressBar.update(
356
356
  overview_bar,
357
- postfix='SAVING RESULTS...',
357
+ status='SAVING RESULTS...',
358
358
  color='yellow')
359
359
 
360
360
  for node in self.nonleaf_nodes:
@@ -364,7 +364,7 @@ class Evaluable(lf.Component):
364
364
 
365
365
  if should_save and summary:
366
366
  lf.concurrent.ProgressBar.update(
367
- overview_bar, postfix='FINALIZING SUMMARY...'
367
+ overview_bar, status='FINALIZING SUMMARY...'
368
368
  )
369
369
 
370
370
  summary.save(os.path.join(self.root_dir, Evaluable.SUMMARY_HTML))
@@ -378,7 +378,7 @@ class Evaluable(lf.Component):
378
378
  # Signal all task completed by making the bar green.
379
379
  lf.concurrent.ProgressBar.update(
380
380
  overview_bar,
381
- postfix='COMPLETED',
381
+ status='COMPLETED',
382
382
  color='green')
383
383
 
384
384
  finally:
@@ -1261,7 +1261,7 @@ class Evaluation(Evaluable):
1261
1261
 
1262
1262
  def finalize(self) -> pg.Dict:
1263
1263
  """Finalizes the evaluation result."""
1264
- if self.cache:
1264
+ if self.cache is not None:
1265
1265
  cache_stats = dict(
1266
1266
  use_cache=True,
1267
1267
  num_queries=self.cache.stats.num_queries,
@@ -564,7 +564,7 @@ class SuiteTest(unittest.TestCase):
564
564
  schema_fn='answer_schema()',
565
565
  ),
566
566
  cache_stats=dict(
567
- use_cache=True, num_queries=4, num_hits=1, num_updates=3
567
+ use_cache=True, num_queries=4, num_hits=0, num_updates=4
568
568
  ),
569
569
  metrics=dict(
570
570
  total=2,
@@ -269,6 +269,9 @@ class LangFunc(
269
269
  # Send rendered text to LM.
270
270
  lm_output = self.lm(lm_input, cache_seed=cache_seed)
271
271
 
272
+ # Attach cache seed.
273
+ lm_input.metadata.cache_seed = cache_seed
274
+
272
275
  # Transform the output message.
273
276
  lm_output = self.transform_output(lm_output)
274
277
  lm_output.tag(message_lib.Message.TAG_LM_OUTPUT)
@@ -94,11 +94,13 @@ class LangFuncCallTest(unittest.TestCase):
94
94
  )
95
95
  )
96
96
  self.assertEqual(r.tags, ['lm-response', 'lm-output'])
97
- self.assertEqual(r.source, message.UserMessage('Hello'))
97
+ self.assertEqual(
98
+ r.source,
99
+ message.UserMessage('Hello', metadata=dict(cache_seed=0))
100
+ )
98
101
  self.assertEqual(r.source.tags, ['rendered', 'lm-input'])
99
102
 
100
103
  self.assertEqual(str(l), 'Hello')
101
- print(repr(l))
102
104
  self.assertEqual(
103
105
  repr(l),
104
106
  "LangFunc(template_str='Hello', clean=True,"
@@ -114,7 +116,7 @@ class LangFuncCallTest(unittest.TestCase):
114
116
  self.assertEqual(l, 'Hello')
115
117
  self.assertEqual(l.natural_language_format(), 'Hello')
116
118
  self.assertEqual(l.render(), 'Hello')
117
- r = l()
119
+ r = l(cache_seed=1)
118
120
  self.assertEqual(
119
121
  r,
120
122
  message.AIMessage(
@@ -123,6 +125,7 @@ class LangFuncCallTest(unittest.TestCase):
123
125
  )
124
126
  )
125
127
  self.assertEqual(r.tags, ['lm-response', 'lm-output'])
128
+ self.assertEqual(r.source.metadata.cache_seed, 1)
126
129
 
127
130
  self.assertEqual(str(l), 'Hello')
128
131