langfun 0.1.2.dev202509120804__py3-none-any.whl → 0.1.2.dev202512150805__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.
Files changed (162) hide show
  1. langfun/__init__.py +1 -1
  2. langfun/core/__init__.py +7 -1
  3. langfun/core/agentic/__init__.py +8 -1
  4. langfun/core/agentic/action.py +740 -112
  5. langfun/core/agentic/action_eval.py +9 -2
  6. langfun/core/agentic/action_test.py +189 -24
  7. langfun/core/async_support.py +104 -5
  8. langfun/core/async_support_test.py +23 -0
  9. langfun/core/coding/python/correction.py +19 -9
  10. langfun/core/coding/python/execution.py +14 -12
  11. langfun/core/coding/python/generation.py +21 -16
  12. langfun/core/coding/python/sandboxing.py +23 -3
  13. langfun/core/component.py +42 -3
  14. langfun/core/concurrent.py +70 -6
  15. langfun/core/concurrent_test.py +9 -2
  16. langfun/core/console.py +1 -1
  17. langfun/core/data/conversion/anthropic.py +12 -3
  18. langfun/core/data/conversion/anthropic_test.py +8 -6
  19. langfun/core/data/conversion/gemini.py +11 -2
  20. langfun/core/data/conversion/gemini_test.py +48 -9
  21. langfun/core/data/conversion/openai.py +145 -31
  22. langfun/core/data/conversion/openai_test.py +161 -17
  23. langfun/core/eval/base.py +48 -44
  24. langfun/core/eval/base_test.py +5 -5
  25. langfun/core/eval/matching.py +5 -2
  26. langfun/core/eval/patching.py +3 -3
  27. langfun/core/eval/scoring.py +4 -3
  28. langfun/core/eval/v2/__init__.py +3 -0
  29. langfun/core/eval/v2/checkpointing.py +148 -46
  30. langfun/core/eval/v2/checkpointing_test.py +9 -2
  31. langfun/core/eval/v2/config_saver.py +37 -0
  32. langfun/core/eval/v2/config_saver_test.py +36 -0
  33. langfun/core/eval/v2/eval_test_helper.py +104 -3
  34. langfun/core/eval/v2/evaluation.py +102 -19
  35. langfun/core/eval/v2/evaluation_test.py +9 -3
  36. langfun/core/eval/v2/example.py +50 -40
  37. langfun/core/eval/v2/example_test.py +16 -8
  38. langfun/core/eval/v2/experiment.py +95 -20
  39. langfun/core/eval/v2/experiment_test.py +19 -0
  40. langfun/core/eval/v2/metric_values.py +31 -3
  41. langfun/core/eval/v2/metric_values_test.py +32 -0
  42. langfun/core/eval/v2/metrics.py +157 -44
  43. langfun/core/eval/v2/metrics_test.py +39 -18
  44. langfun/core/eval/v2/progress.py +31 -1
  45. langfun/core/eval/v2/progress_test.py +27 -0
  46. langfun/core/eval/v2/progress_tracking.py +13 -5
  47. langfun/core/eval/v2/progress_tracking_test.py +9 -1
  48. langfun/core/eval/v2/reporting.py +88 -71
  49. langfun/core/eval/v2/reporting_test.py +24 -6
  50. langfun/core/eval/v2/runners/__init__.py +30 -0
  51. langfun/core/eval/v2/{runners.py → runners/base.py} +73 -180
  52. langfun/core/eval/v2/runners/beam.py +354 -0
  53. langfun/core/eval/v2/runners/beam_test.py +153 -0
  54. langfun/core/eval/v2/runners/ckpt_monitor.py +350 -0
  55. langfun/core/eval/v2/runners/ckpt_monitor_test.py +213 -0
  56. langfun/core/eval/v2/runners/debug.py +40 -0
  57. langfun/core/eval/v2/runners/debug_test.py +76 -0
  58. langfun/core/eval/v2/runners/parallel.py +243 -0
  59. langfun/core/eval/v2/runners/parallel_test.py +182 -0
  60. langfun/core/eval/v2/runners/sequential.py +47 -0
  61. langfun/core/eval/v2/runners/sequential_test.py +169 -0
  62. langfun/core/langfunc.py +45 -130
  63. langfun/core/langfunc_test.py +7 -5
  64. langfun/core/language_model.py +189 -36
  65. langfun/core/language_model_test.py +54 -3
  66. langfun/core/llms/__init__.py +14 -1
  67. langfun/core/llms/anthropic.py +157 -2
  68. langfun/core/llms/azure_openai.py +29 -17
  69. langfun/core/llms/cache/base.py +25 -3
  70. langfun/core/llms/cache/in_memory.py +48 -7
  71. langfun/core/llms/cache/in_memory_test.py +14 -4
  72. langfun/core/llms/compositional.py +25 -1
  73. langfun/core/llms/deepseek.py +30 -2
  74. langfun/core/llms/fake.py +32 -1
  75. langfun/core/llms/gemini.py +90 -12
  76. langfun/core/llms/gemini_test.py +110 -0
  77. langfun/core/llms/google_genai.py +52 -1
  78. langfun/core/llms/groq.py +28 -3
  79. langfun/core/llms/llama_cpp.py +23 -4
  80. langfun/core/llms/openai.py +120 -3
  81. langfun/core/llms/openai_compatible.py +148 -27
  82. langfun/core/llms/openai_compatible_test.py +207 -20
  83. langfun/core/llms/openai_test.py +0 -2
  84. langfun/core/llms/rest.py +16 -1
  85. langfun/core/llms/vertexai.py +78 -8
  86. langfun/core/logging.py +1 -1
  87. langfun/core/mcp/__init__.py +10 -0
  88. langfun/core/mcp/client.py +177 -0
  89. langfun/core/mcp/client_test.py +71 -0
  90. langfun/core/mcp/session.py +241 -0
  91. langfun/core/mcp/session_test.py +54 -0
  92. langfun/core/mcp/testing/simple_mcp_client.py +33 -0
  93. langfun/core/mcp/testing/simple_mcp_server.py +33 -0
  94. langfun/core/mcp/tool.py +254 -0
  95. langfun/core/mcp/tool_test.py +197 -0
  96. langfun/core/memory.py +1 -0
  97. langfun/core/message.py +160 -55
  98. langfun/core/message_test.py +65 -81
  99. langfun/core/modalities/__init__.py +8 -0
  100. langfun/core/modalities/audio.py +21 -1
  101. langfun/core/modalities/image.py +73 -3
  102. langfun/core/modalities/image_test.py +116 -0
  103. langfun/core/modalities/mime.py +78 -4
  104. langfun/core/modalities/mime_test.py +59 -0
  105. langfun/core/modalities/pdf.py +19 -1
  106. langfun/core/modalities/video.py +21 -1
  107. langfun/core/modality.py +167 -29
  108. langfun/core/modality_test.py +42 -12
  109. langfun/core/natural_language.py +1 -1
  110. langfun/core/sampling.py +4 -4
  111. langfun/core/sampling_test.py +20 -4
  112. langfun/core/structured/__init__.py +2 -24
  113. langfun/core/structured/completion.py +34 -44
  114. langfun/core/structured/completion_test.py +23 -43
  115. langfun/core/structured/description.py +54 -50
  116. langfun/core/structured/function_generation.py +29 -12
  117. langfun/core/structured/mapping.py +81 -37
  118. langfun/core/structured/parsing.py +95 -79
  119. langfun/core/structured/parsing_test.py +0 -3
  120. langfun/core/structured/querying.py +230 -154
  121. langfun/core/structured/querying_test.py +69 -33
  122. langfun/core/structured/schema/__init__.py +49 -0
  123. langfun/core/structured/schema/base.py +664 -0
  124. langfun/core/structured/schema/base_test.py +531 -0
  125. langfun/core/structured/schema/json.py +174 -0
  126. langfun/core/structured/schema/json_test.py +121 -0
  127. langfun/core/structured/schema/python.py +316 -0
  128. langfun/core/structured/schema/python_test.py +410 -0
  129. langfun/core/structured/schema_generation.py +33 -14
  130. langfun/core/structured/scoring.py +47 -36
  131. langfun/core/structured/tokenization.py +26 -11
  132. langfun/core/subscription.py +2 -2
  133. langfun/core/template.py +175 -50
  134. langfun/core/template_test.py +123 -17
  135. langfun/env/__init__.py +43 -0
  136. langfun/env/base_environment.py +827 -0
  137. langfun/env/base_environment_test.py +473 -0
  138. langfun/env/base_feature.py +304 -0
  139. langfun/env/base_feature_test.py +228 -0
  140. langfun/env/base_sandbox.py +842 -0
  141. langfun/env/base_sandbox_test.py +1235 -0
  142. langfun/env/event_handlers/__init__.py +14 -0
  143. langfun/env/event_handlers/chain.py +233 -0
  144. langfun/env/event_handlers/chain_test.py +253 -0
  145. langfun/env/event_handlers/event_logger.py +472 -0
  146. langfun/env/event_handlers/event_logger_test.py +304 -0
  147. langfun/env/event_handlers/metric_writer.py +726 -0
  148. langfun/env/event_handlers/metric_writer_test.py +214 -0
  149. langfun/env/interface.py +1640 -0
  150. langfun/env/interface_test.py +153 -0
  151. langfun/env/load_balancers.py +59 -0
  152. langfun/env/load_balancers_test.py +141 -0
  153. langfun/env/test_utils.py +507 -0
  154. {langfun-0.1.2.dev202509120804.dist-info → langfun-0.1.2.dev202512150805.dist-info}/METADATA +7 -3
  155. langfun-0.1.2.dev202512150805.dist-info/RECORD +217 -0
  156. langfun/core/eval/v2/runners_test.py +0 -343
  157. langfun/core/structured/schema.py +0 -987
  158. langfun/core/structured/schema_test.py +0 -982
  159. langfun-0.1.2.dev202509120804.dist-info/RECORD +0 -172
  160. {langfun-0.1.2.dev202509120804.dist-info → langfun-0.1.2.dev202512150805.dist-info}/WHEEL +0 -0
  161. {langfun-0.1.2.dev202509120804.dist-info → langfun-0.1.2.dev202512150805.dist-info}/licenses/LICENSE +0 -0
  162. {langfun-0.1.2.dev202509120804.dist-info → langfun-0.1.2.dev202512150805.dist-info}/top_level.txt +0 -0
@@ -249,35 +249,60 @@ class QueryTest(unittest.TestCase):
249
249
 
250
250
  def test_root_modality_to_structure_render(self):
251
251
  lm = fake.StaticResponse('1')
252
+ image = modalities.Image.from_bytes(b'mock_image')
252
253
  self.assert_render(
253
- modalities.Image.from_bytes(b'mock_image'),
254
+ image,
254
255
  int,
255
256
  lm=lm,
256
- expected_snippet='\n\nREQUEST:\n <<[[input]]>>\n\n',
257
+ expected_snippet=f'\n\nREQUEST:\n <<[[{image.id}]]>>\n\n',
257
258
  expected_modalities=1,
258
259
  )
259
260
 
260
261
  def test_root_modality_to_str_render(self):
261
262
  lm = fake.StaticResponse('1')
263
+ modality = modalities.Image.from_bytes(b'mock_image')
262
264
  self.assert_render(
263
- modalities.Image.from_bytes(b'mock_image'),
265
+ modality,
264
266
  None,
265
267
  lm=lm,
266
- expected_snippet='<<[[input]]>>',
268
+ expected_snippet=f'<<[[{modality.id}]]>>',
267
269
  exact_match=True,
268
270
  expected_modalities=1,
269
271
  )
270
272
 
271
273
  def test_str_with_modality_to_str_render(self):
272
274
  lm = fake.StaticResponse('A cat and a mouse.')
275
+ cat_image = modalities.Image.from_bytes(b'cat_image')
276
+ mouse_image = modalities.Image.from_bytes(b'mouse_image')
273
277
  self.assert_render(
274
278
  'What are these? {{this_image}} and {{that_image}}',
275
279
  None,
276
- this_image=modalities.Image.from_bytes(b'cat_image'),
277
- that_image=modalities.Image.from_bytes(b'mouse_image'),
280
+ this_image=cat_image,
281
+ that_image=mouse_image,
278
282
  lm=lm,
279
283
  expected_snippet=(
280
- 'What are these? <<[[this_image]]>> and <<[[that_image]]>>'
284
+ f'What are these? <<[[{cat_image.id}]]>> and '
285
+ f'<<[[{mouse_image.id}]]>>'
286
+ ),
287
+ exact_match=True,
288
+ expected_modalities=2,
289
+ )
290
+
291
+ def test_message_with_modality_to_str_render(self):
292
+ lm = fake.StaticResponse('A cat and a mouse.')
293
+ cat_image = modalities.Image.from_bytes(b'cat_image')
294
+ mouse_image = modalities.Image.from_bytes(b'mouse_image')
295
+ self.assert_render(
296
+ lf.Template(
297
+ 'What are these? {{this_image}} and {{that_image}}',
298
+ this_image=cat_image,
299
+ that_image=mouse_image,
300
+ ).render(),
301
+ None,
302
+ lm=lm,
303
+ expected_snippet=(
304
+ f'What are these? <<[[{cat_image.id}]]>> and '
305
+ f'<<[[{mouse_image.id}]]>>'
281
306
  ),
282
307
  exact_match=True,
283
308
  expected_modalities=2,
@@ -285,33 +310,33 @@ class QueryTest(unittest.TestCase):
285
310
 
286
311
  def test_structure_with_modality_to_str_render(self):
287
312
  lm = fake.StaticResponse('A cat and a mouse.')
313
+ cat_image = modalities.Image.from_bytes(b'cat_image')
314
+ mouse_image = modalities.Image.from_bytes(b'mouse_image')
288
315
  self.assert_render(
289
- [
290
- modalities.Image.from_bytes(b'cat_image'),
291
- modalities.Image.from_bytes(b'mouse_image'),
292
- ],
316
+ [cat_image, mouse_image],
293
317
  None,
294
318
  lm=lm,
295
- expected_snippet='`[<<[[input[0]]]>>, <<[[input[1]]]>>]`',
319
+ expected_snippet=(
320
+ f'`[<<[[{cat_image.id}]]>>, <<[[{mouse_image.id}]]>>]`'
321
+ ),
296
322
  exact_match=True,
297
323
  expected_modalities=2,
298
324
  )
299
325
 
300
326
  def test_structure_with_modality_to_structure_render(self):
301
327
  lm = fake.StaticResponse('["cat", "mouse"]')
328
+ cat_image = modalities.Image.from_bytes(b'cat_image')
329
+ mouse_image = modalities.Image.from_bytes(b'mouse_image')
302
330
  self.assert_render(
303
- [
304
- modalities.Image.from_bytes(b'cat_image'),
305
- modalities.Image.from_bytes(b'mouse_image'),
306
- ],
331
+ [cat_image, mouse_image],
307
332
  list[str],
308
333
  lm=lm,
309
- expected_snippet=inspect.cleandoc("""
334
+ expected_snippet=inspect.cleandoc(f"""
310
335
  REQUEST:
311
336
  ```python
312
337
  [
313
- <<[[input[0]]]>>,
314
- <<[[input[1]]]>>
338
+ <<[[{cat_image.id}]]>>,
339
+ <<[[{mouse_image.id}]]>>
315
340
  ]
316
341
  ```
317
342
  """),
@@ -320,25 +345,25 @@ class QueryTest(unittest.TestCase):
320
345
 
321
346
  def test_structure_with_modality_and_examples_to_structure_render(self):
322
347
  lm = fake.StaticResponse('["cat", "mouse"]')
348
+ cat_image = modalities.Image.from_bytes(b'cat_image')
349
+ mouse_image = modalities.Image.from_bytes(b'mouse_image')
350
+ dog_image = modalities.Image.from_bytes(b'dog_image')
323
351
  self.assert_render(
324
- [
325
- modalities.Image.from_bytes(b'cat_image'),
326
- modalities.Image.from_bytes(b'mouse_image'),
327
- ],
352
+ [cat_image, mouse_image],
328
353
  list[str],
329
354
  examples=[
330
355
  mapping.MappingExample(
331
- input=[modalities.Image.from_bytes(b'dog_image')],
356
+ input=[dog_image],
332
357
  schema=list[str],
333
358
  output=['dog'],
334
359
  ),
335
360
  ],
336
361
  lm=lm,
337
- expected_snippet=inspect.cleandoc("""
362
+ expected_snippet=inspect.cleandoc(f"""
338
363
  REQUEST:
339
364
  ```python
340
365
  [
341
- <<[[examples[0].input[0]]]>>
366
+ <<[[{dog_image.id}]]>>
342
367
  ]
343
368
  ```
344
369
 
@@ -356,8 +381,8 @@ class QueryTest(unittest.TestCase):
356
381
  REQUEST:
357
382
  ```python
358
383
  [
359
- <<[[input[0]]]>>,
360
- <<[[input[1]]]>>
384
+ <<[[{cat_image.id}]]>>,
385
+ <<[[{mouse_image.id}]]>>
361
386
  ]
362
387
  ```
363
388
 
@@ -369,6 +394,17 @@ class QueryTest(unittest.TestCase):
369
394
  expected_modalities=3,
370
395
  )
371
396
 
397
+ def test_query_with_modality_output(self):
398
+ cat_image = modalities.Image.from_bytes(b'cat_image')
399
+ lm = fake.StaticResponse(
400
+ lf.Template('Here you go: {{image}}', image=cat_image).render(
401
+ message_cls=lf.AIMessage
402
+ )
403
+ )
404
+ response = querying.query('Generate a cat image', lm=lm)
405
+ self.assertIsInstance(response, lf.AIMessage)
406
+ self.assertEqual(response.modalities(), [cat_image])
407
+
372
408
  def test_multiple_queries(self):
373
409
  self.assertEqual(
374
410
  querying.query(
@@ -545,7 +581,7 @@ class QueryTest(unittest.TestCase):
545
581
  )
546
582
  ).input,
547
583
  )
548
- self.assertIsNotNone(output.get_modality('image'))
584
+ self.assertEqual(len(output.referred_modalities), 1)
549
585
 
550
586
  def test_query_and_reduce(self):
551
587
  self.assertEqual(
@@ -1590,7 +1626,7 @@ class TrackQueriesTest(unittest.TestCase):
1590
1626
  'bar',
1591
1627
  ])
1592
1628
  state = {}
1593
- def start_callabck(query):
1629
+ def start_callback(query):
1594
1630
  self.assertFalse(query.is_completed)
1595
1631
  self.assertIsNone(query.end_time)
1596
1632
  elapse1 = query.elapse
@@ -1615,7 +1651,7 @@ class TrackQueriesTest(unittest.TestCase):
1615
1651
  state['end'] = query
1616
1652
 
1617
1653
  with querying.track_queries(
1618
- start_callabck=start_callabck, end_callabck=end_callback
1654
+ start_callback=start_callback, end_callback=end_callback
1619
1655
  ) as queries:
1620
1656
  querying.query('foo', lm=lm)
1621
1657
  self.assertIs(state['start'], queries[0])
@@ -1626,7 +1662,7 @@ class TrackQueriesTest(unittest.TestCase):
1626
1662
  'bar',
1627
1663
  ])
1628
1664
  state = {}
1629
- def start_callabck(query):
1665
+ def start_callback(query):
1630
1666
  self.assertFalse(query.is_completed)
1631
1667
  self.assertIsNone(query.end_time)
1632
1668
  self.assertIsNotNone(query.usage_summary)
@@ -1648,7 +1684,7 @@ class TrackQueriesTest(unittest.TestCase):
1648
1684
 
1649
1685
  with self.assertRaises(mapping.MappingError):
1650
1686
  with querying.track_queries(
1651
- start_callabck=start_callabck, end_callabck=end_callback
1687
+ start_callback=start_callback, end_callback=end_callback
1652
1688
  ) as queries:
1653
1689
  querying.query('foo', int, lm=lm)
1654
1690
  self.assertIs(state['start'], queries[0])
@@ -0,0 +1,49 @@
1
+ # Copyright 2025 The Langfun Authors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """Schema and prompting protocols for structured data."""
15
+
16
+ # pylint: disable=g-bad-import-order
17
+ # pylint: disable=g-importing-member
18
+ from langfun.core.structured.schema.base import Schema
19
+ from langfun.core.structured.schema.base import SchemaError
20
+ from langfun.core.structured.schema.base import SchemaType
21
+
22
+ from langfun.core.structured.schema.base import class_dependencies
23
+ from langfun.core.structured.schema.base import schema_spec
24
+ from langfun.core.structured.schema.base import annotation
25
+
26
+ from langfun.core.structured.schema.base import PromptingProtocol
27
+ from langfun.core.structured.schema.base import schema_repr
28
+ from langfun.core.structured.schema.base import value_repr
29
+ from langfun.core.structured.schema.base import parse_value
30
+
31
+ from langfun.core.structured.schema.base import mark_missing
32
+ from langfun.core.structured.schema.base import Missing
33
+ from langfun.core.structured.schema.base import MISSING
34
+ from langfun.core.structured.schema.base import Unknown
35
+ from langfun.core.structured.schema.base import UNKNOWN
36
+
37
+ # JSON protocol.
38
+ from langfun.core.structured.schema.json import JsonError
39
+ from langfun.core.structured.schema.json import JsonPromptingProtocol
40
+ from langfun.core.structured.schema.json import cleanup_json
41
+
42
+ # Python protocol.
43
+ from langfun.core.structured.schema.python import PythonPromptingProtocol
44
+ from langfun.core.structured.schema.python import source_form
45
+ from langfun.core.structured.schema.python import structure_from_python
46
+
47
+ from langfun.core.structured.schema.python import class_definition
48
+ from langfun.core.structured.schema.python import class_definitions
49
+ from langfun.core.structured.schema.python import include_method_in_prompt