langfun 0.1.2.dev202508250805__py3-none-any.whl → 0.1.2.dev202511110805__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.

Potentially problematic release.


This version of langfun might be problematic. Click here for more details.

Files changed (133) hide show
  1. langfun/__init__.py +1 -1
  2. langfun/core/__init__.py +6 -1
  3. langfun/core/agentic/__init__.py +4 -0
  4. langfun/core/agentic/action.py +412 -103
  5. langfun/core/agentic/action_eval.py +9 -2
  6. langfun/core/agentic/action_test.py +68 -6
  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 +9 -2
  20. langfun/core/data/conversion/gemini_test.py +12 -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 +47 -43
  24. langfun/core/eval/base_test.py +4 -4
  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 +1 -0
  29. langfun/core/eval/v2/checkpointing.py +30 -4
  30. langfun/core/eval/v2/eval_test_helper.py +1 -1
  31. langfun/core/eval/v2/evaluation.py +60 -14
  32. langfun/core/eval/v2/example.py +22 -11
  33. langfun/core/eval/v2/experiment.py +51 -8
  34. langfun/core/eval/v2/metric_values.py +31 -3
  35. langfun/core/eval/v2/metric_values_test.py +32 -0
  36. langfun/core/eval/v2/metrics.py +39 -4
  37. langfun/core/eval/v2/metrics_test.py +14 -0
  38. langfun/core/eval/v2/progress.py +30 -1
  39. langfun/core/eval/v2/progress_test.py +27 -0
  40. langfun/core/eval/v2/progress_tracking_test.py +6 -0
  41. langfun/core/eval/v2/reporting.py +90 -71
  42. langfun/core/eval/v2/reporting_test.py +20 -6
  43. langfun/core/eval/v2/runners.py +27 -7
  44. langfun/core/eval/v2/runners_test.py +3 -0
  45. langfun/core/langfunc.py +45 -130
  46. langfun/core/langfunc_test.py +6 -4
  47. langfun/core/language_model.py +151 -31
  48. langfun/core/language_model_test.py +9 -3
  49. langfun/core/llms/__init__.py +12 -1
  50. langfun/core/llms/anthropic.py +157 -2
  51. langfun/core/llms/azure_openai.py +29 -17
  52. langfun/core/llms/cache/base.py +25 -3
  53. langfun/core/llms/cache/in_memory.py +48 -7
  54. langfun/core/llms/cache/in_memory_test.py +14 -4
  55. langfun/core/llms/compositional.py +25 -1
  56. langfun/core/llms/deepseek.py +30 -2
  57. langfun/core/llms/fake.py +39 -1
  58. langfun/core/llms/fake_test.py +9 -0
  59. langfun/core/llms/gemini.py +43 -7
  60. langfun/core/llms/google_genai.py +34 -1
  61. langfun/core/llms/groq.py +28 -3
  62. langfun/core/llms/llama_cpp.py +23 -4
  63. langfun/core/llms/openai.py +93 -3
  64. langfun/core/llms/openai_compatible.py +148 -27
  65. langfun/core/llms/openai_compatible_test.py +207 -20
  66. langfun/core/llms/openai_test.py +0 -2
  67. langfun/core/llms/rest.py +16 -1
  68. langfun/core/llms/vertexai.py +59 -8
  69. langfun/core/logging.py +1 -1
  70. langfun/core/mcp/__init__.py +10 -0
  71. langfun/core/mcp/client.py +177 -0
  72. langfun/core/mcp/client_test.py +71 -0
  73. langfun/core/mcp/session.py +241 -0
  74. langfun/core/mcp/session_test.py +54 -0
  75. langfun/core/mcp/testing/simple_mcp_client.py +33 -0
  76. langfun/core/mcp/testing/simple_mcp_server.py +33 -0
  77. langfun/core/mcp/tool.py +256 -0
  78. langfun/core/mcp/tool_test.py +197 -0
  79. langfun/core/memory.py +1 -0
  80. langfun/core/message.py +160 -55
  81. langfun/core/message_test.py +65 -81
  82. langfun/core/modalities/__init__.py +8 -0
  83. langfun/core/modalities/audio.py +21 -1
  84. langfun/core/modalities/image.py +19 -1
  85. langfun/core/modalities/mime.py +62 -3
  86. langfun/core/modalities/pdf.py +19 -1
  87. langfun/core/modalities/video.py +21 -1
  88. langfun/core/modality.py +167 -29
  89. langfun/core/modality_test.py +42 -12
  90. langfun/core/natural_language.py +1 -1
  91. langfun/core/sampling.py +4 -4
  92. langfun/core/sampling_test.py +20 -4
  93. langfun/core/structured/completion.py +34 -44
  94. langfun/core/structured/completion_test.py +23 -43
  95. langfun/core/structured/description.py +54 -50
  96. langfun/core/structured/function_generation.py +29 -12
  97. langfun/core/structured/mapping.py +74 -28
  98. langfun/core/structured/parsing.py +90 -74
  99. langfun/core/structured/parsing_test.py +0 -3
  100. langfun/core/structured/querying.py +242 -156
  101. langfun/core/structured/querying_test.py +95 -64
  102. langfun/core/structured/schema.py +70 -10
  103. langfun/core/structured/schema_generation.py +33 -14
  104. langfun/core/structured/scoring.py +45 -34
  105. langfun/core/structured/tokenization.py +24 -9
  106. langfun/core/subscription.py +2 -2
  107. langfun/core/template.py +175 -50
  108. langfun/core/template_test.py +123 -17
  109. langfun/env/__init__.py +43 -0
  110. langfun/env/base_environment.py +827 -0
  111. langfun/env/base_environment_test.py +473 -0
  112. langfun/env/base_feature.py +304 -0
  113. langfun/env/base_feature_test.py +228 -0
  114. langfun/env/base_sandbox.py +842 -0
  115. langfun/env/base_sandbox_test.py +1235 -0
  116. langfun/env/event_handlers/__init__.py +14 -0
  117. langfun/env/event_handlers/chain.py +233 -0
  118. langfun/env/event_handlers/chain_test.py +253 -0
  119. langfun/env/event_handlers/event_logger.py +472 -0
  120. langfun/env/event_handlers/event_logger_test.py +304 -0
  121. langfun/env/event_handlers/metric_writer.py +726 -0
  122. langfun/env/event_handlers/metric_writer_test.py +214 -0
  123. langfun/env/interface.py +1640 -0
  124. langfun/env/interface_test.py +151 -0
  125. langfun/env/load_balancers.py +59 -0
  126. langfun/env/load_balancers_test.py +139 -0
  127. langfun/env/test_utils.py +497 -0
  128. {langfun-0.1.2.dev202508250805.dist-info → langfun-0.1.2.dev202511110805.dist-info}/METADATA +7 -3
  129. langfun-0.1.2.dev202511110805.dist-info/RECORD +200 -0
  130. langfun-0.1.2.dev202508250805.dist-info/RECORD +0 -172
  131. {langfun-0.1.2.dev202508250805.dist-info → langfun-0.1.2.dev202511110805.dist-info}/WHEEL +0 -0
  132. {langfun-0.1.2.dev202508250805.dist-info → langfun-0.1.2.dev202511110805.dist-info}/licenses/LICENSE +0 -0
  133. {langfun-0.1.2.dev202508250805.dist-info → langfun-0.1.2.dev202511110805.dist-info}/top_level.txt +0 -0
@@ -24,7 +24,7 @@ import pyglove as pg
24
24
 
25
25
  @lf.use_init_args(['schema', 'default', 'examples'])
26
26
  class _ParseStructure(mapping.Mapping):
27
- """Parse an object out from a natural language text."""
27
+ """Parses an object out from a natural language text."""
28
28
 
29
29
  context_title = 'USER_REQUEST'
30
30
  input_title = 'LM_RESPONSE'
@@ -39,7 +39,7 @@ class _ParseStructure(mapping.Mapping):
39
39
 
40
40
 
41
41
  class _ParseStructureJson(_ParseStructure):
42
- """Parse an object out from a NL text using JSON as the protocol."""
42
+ """Parses an object out from a NL text using JSON as the protocol."""
43
43
 
44
44
  preamble = """
45
45
  Please help translate the last LM response into JSON based on the request and the schema:
@@ -55,7 +55,7 @@ class _ParseStructureJson(_ParseStructure):
55
55
 
56
56
 
57
57
  class _ParseStructurePython(_ParseStructure):
58
- """Parse an object out from a NL text using Python as the protocol."""
58
+ """Parses an object out from a NL text using Python as the protocol."""
59
59
 
60
60
  preamble = """
61
61
  Please help translate the last {{ input_title }} into {{ output_title}} based on {{ schema_title }}.
@@ -88,55 +88,55 @@ def parse(
88
88
  returns_message: bool = False,
89
89
  **kwargs,
90
90
  ) -> Any:
91
- """Parse a natural language message based on schema.
92
-
93
- Examples:
94
-
95
- ```
96
- class FlightDuration(pg.Object):
97
- hours: int
98
- minutes: int
99
-
100
- class Flight(pg.Object):
101
- airline: str
102
- flight_number: str
103
- departure_airport_code: str
104
- arrival_airport_code: str
105
- departure_time: str
106
- arrival_time: str
107
- duration: FlightDuration
108
- stops: int
109
- price: float
110
-
111
- input = '''
112
- The flight is operated by United Airlines, has the flight number UA2631,
113
- departs from San Francisco International Airport (SFO), arrives at John
114
- F. Kennedy International Airport (JFK), It departs at 2023-09-07T05:15:00,
115
- arrives at 2023-09-07T12:12:00, has a duration of 7 hours and 57 minutes,
116
- makes 1 stop, and costs $227.
117
- '''
118
-
119
- r = lf.parse(input, Flight)
120
- assert isinstance(r, Flight)
121
- assert r.airline == 'United Airlines'
122
- assert r.departure_airport_code == 'SFO'
123
- assert r.duration.hour = 7
124
- ```
91
+ """Parses a natural language message into a structured object using an LLM.
92
+
93
+ `lf.parse` extracts structured information from a natural language string
94
+ or message according to a provided schema. It is the inverse of
95
+ `lf.describe`.
96
+
97
+ **Example:**
98
+
99
+ ```python
100
+ import langfun as lf
101
+ import pyglove as pg
102
+
103
+ class FlightDuration(pg.Object):
104
+ hours: int
105
+ minutes: int
106
+
107
+ class Flight(pg.Object):
108
+ airline: str
109
+ flight_number: str
110
+ departure_airport_code: str
111
+ arrival_airport_code: str
112
+ duration: FlightDuration
113
+ price: float
114
+
115
+ text = '''
116
+ The flight is UA2631 of United Airlines, from SFO to JFK,
117
+ duration is 7 hours and 57 minutes, costing $227.
118
+ '''
119
+
120
+ flight = lf.parse(text, Flight, lm=lf.llms.Gemini25Flash())
121
+ assert flight.airline == 'United Airlines'
122
+ assert flight.duration.hours == 7
123
+ ```
125
124
 
126
125
  Args:
127
126
  message: A `lf.Message` object or a string as the natural language input.
128
127
  It provides the complete context for the parsing.
129
- schema: A `lf.transforms.ParsingSchema` object or equivalent annotations.
130
- default: The default value if parsing failed. If not specified, error will
131
- be raised.
128
+ schema: A `lf.Schema` object or equivalent annotations.
129
+ default: The default value to return if parsing fails. If
130
+ `lf.RAISE_IF_HAS_ERROR` is used (default), an error will be raised
131
+ instead.
132
132
  user_prompt: An optional user prompt as the description or ask for the
133
- message, which provide more context for parsing.
133
+ message, which provides more context for parsing.
134
134
  lm: The language model to use. If not specified, the language model from
135
135
  `lf.context` context manager will be used.
136
- examples: An optional list of fewshot examples for helping parsing. If None,
137
- the default one-shot example will be added.
136
+ examples: An optional list of fewshot examples for guiding parsing. If None,
137
+ default examples will be used.
138
138
  include_context: If True, include the request sent to LLM for obtaining the
139
- response to pares. Otherwise include only the response.
139
+ response to parse. Otherwise include only the response.
140
140
  cache_seed: Seed for computing cache key. The cache key is determined by a
141
141
  tuple of (lm, prompt, cache seed). If None, cache will be disabled for
142
142
  the query even cache is configured by the LM.
@@ -146,10 +146,10 @@ def parse(
146
146
  `autofix_lm` from `lf.context` context manager will be used. Otherwise it
147
147
  will use `lm`.
148
148
  protocol: The protocol for schema/value representation. Applicable values
149
- are 'json' and 'python'. By default 'python' will be used.`
149
+ are 'json' and 'python'. By default 'python' will be used.
150
150
  returns_message: If True, returns `lf.Message` as the output, instead of
151
151
  returning the structured `message.result`.
152
- **kwargs: Keyword arguments passed to the `lf.structured.ParseStructure`
152
+ **kwargs: Keyword arguments passed to the `_ParseStructure`
153
153
  transform.
154
154
 
155
155
  Returns:
@@ -223,7 +223,7 @@ async def aparse(
223
223
 
224
224
 
225
225
  def call(
226
- prompt: str | lf.Template,
226
+ prompt: Union[str, lf.Template, lf.Message],
227
227
  schema: Union[
228
228
  None, schema_lib.Schema, Type[Any], list[Type[Any]], dict[str, Any]
229
229
  ] = None,
@@ -240,27 +240,43 @@ def call(
240
240
  returns_message: bool = False,
241
241
  **kwargs,
242
242
  ) -> Any:
243
- """Call a language model with prompt and formulate response in return type.
244
-
245
- Examples::
246
-
247
- # Call with constant string-type prompt.
248
- lf.call('Compute one plus one', lm=lf.llms.Gpt35())
249
- >> "two"
250
-
251
- # Call with returning a structured (int) type.
252
- lf.call('Compute one plus one', int, lm=lf.llms.Gpt35())
253
- >> 2
254
-
255
- # Call with a template string with variables.
256
- lf.call('Compute {{x}} plus {{y}}', int,
257
- x='one', y='one', lm=lf.llms.Gpt35())
258
- >> 2
259
-
260
- # Call with an `lf.Template` object with variables.
261
- lf.call(lf.Template('Compute {{x}} plus {{y}}', x=1), int,
262
- y=1, lm=lf.llms.Gpt35())
263
- >> 2
243
+ """Calls a language model and parses the response according to a schema.
244
+
245
+ `lf.call` first calls a language model with a prompt to obtain a natural
246
+ language response, then calls the language model again to parse this
247
+ response into a structured format defined by `schema`. If `schema` is not
248
+ provided, it returns the raw natural language response.
249
+
250
+ **Example:**
251
+
252
+ 1. **Call with a Natural Language Prompt**:
253
+ By default, `lf.call` with a string prompt returns a natural language
254
+ response:
255
+ ```python
256
+ r = lf.call('Compute one plus one', lm=lf.llms.Gpt4())
257
+ print(r)
258
+ # Output: 2
259
+ ```
260
+
261
+ 2. **Call with Structured Output**:
262
+ If `schema` is provided, `lf.call` parses the LLM response into the
263
+ specified schema using a second LM call:
264
+ ```python
265
+ r = lf.call('Compute one plus one', int, lm=lf.llms.Gpt4())
266
+ print(r)
267
+ # Output: 2
268
+ ```
269
+
270
+ 3. **Call with Templated Prompt**:
271
+ The prompt can be a template string with placeholders (e.g., `{{x}}`,
272
+ `{{y}}`), whose values are provided as keyword arguments:
273
+ ```python
274
+ r = lf.call(
275
+ 'Compute {{x}} plus {{y}}',
276
+ int, x='one', y='one', lm=lf.llms.Gpt4())
277
+ print(r)
278
+ # Output: 2
279
+ ```
264
280
 
265
281
  Args:
266
282
  prompt: User prompt that will be sent to LM, which could be a string or a
@@ -272,10 +288,10 @@ def call(
272
288
  If not specified, `lm` from `lf.context` context manager will be used.
273
289
  parsing_lm: Language model that will be used for parsing. If None, the `lm`
274
290
  for prompting the LM will be used.
275
- parsing_examples: Examples for parsing the output. If None,
276
- `lf.structured.DEFAULT_PARSE_EXAMPLES` will be used.
291
+ parsing_examples: Examples for parsing the output. If None, no examples
292
+ will be used for parsing.
277
293
  parsing_include_context: If True, include the request sent to LLM for
278
- obtaining the response to pares. Otherwise include only the response.
294
+ obtaining the response to parse. Otherwise include only the response.
279
295
  cache_seed: Seed for computing cache key. The cache key is determined by a
280
296
  tuple of (lm, prompt, cache seed). If None, cache will be disabled for
281
297
  the query even cache is configured by the LM.
@@ -284,10 +300,10 @@ def call(
284
300
  autofix_lm: The language model to use for autofix. If not specified, the
285
301
  `autofix_lm` from `lf.context` context manager will be used. Otherwise it
286
302
  will use `parsing_lm`.
287
- response_postprocess: A callback function to post process the text response
303
+ response_postprocess: A callback function to post-process the text response
288
304
  before sending for parsing.
289
305
  protocol: The protocol for schema/value representation. Applicable values
290
- are 'json' and 'python'. By default 'python' will be used.`
306
+ are 'json' and 'python'. By default 'python' will be used.
291
307
  returns_message: If True, return a `lf.Message` object instead of its text
292
308
  or result.
293
309
  **kwargs: Keyword arguments. Including options that control the calling
@@ -387,7 +403,7 @@ def _parse_structure_cls(
387
403
 
388
404
 
389
405
  def default_parse_examples() -> list[mapping.MappingExample]:
390
- """Default parsing examples."""
406
+ """Returns default parsing examples."""
391
407
 
392
408
  class AdditionResults(pg.Object):
393
409
  one_plus_one_equals: int | None
@@ -745,9 +745,6 @@ class CallTest(unittest.TestCase):
745
745
  parsing.call('what is one plus two?', int, lm=lm, autofix=3), 3
746
746
  )
747
747
 
748
- def test_call_with_structured_input(self):
749
- self.assertEqual(parsing.call(1, lm=fake.StaticResponse('2')), '2')
750
-
751
748
  def test_call_with_response_postprocess(self):
752
749
  target_str = '@TARGET_STR@'
753
750
  random_str = '!RANDOM_STR!'