langfun 0.1.2.dev202504290805__py3-none-any.whl → 0.1.2.dev202504300804__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.
- langfun/__init__.py +3 -0
- langfun/core/agentic/action_eval.py +6 -1
- langfun/core/eval/base_test.py +4 -4
- langfun/core/eval/v2/evaluation.py +78 -12
- langfun/core/eval/v2/evaluation_test.py +2 -0
- langfun/core/structured/__init__.py +3 -0
- langfun/core/structured/mapping.py +5 -2
- langfun/core/structured/parsing_test.py +1 -1
- langfun/core/structured/querying.py +205 -18
- langfun/core/structured/querying_test.py +286 -47
- {langfun-0.1.2.dev202504290805.dist-info → langfun-0.1.2.dev202504300804.dist-info}/METADATA +1 -1
- {langfun-0.1.2.dev202504290805.dist-info → langfun-0.1.2.dev202504300804.dist-info}/RECORD +15 -15
- {langfun-0.1.2.dev202504290805.dist-info → langfun-0.1.2.dev202504300804.dist-info}/WHEEL +1 -1
- {langfun-0.1.2.dev202504290805.dist-info → langfun-0.1.2.dev202504300804.dist-info}/licenses/LICENSE +0 -0
- {langfun-0.1.2.dev202504290805.dist-info → langfun-0.1.2.dev202504300804.dist-info}/top_level.txt +0 -0
langfun/__init__.py
CHANGED
@@ -37,6 +37,9 @@ generate_class = structured.generate_class
|
|
37
37
|
|
38
38
|
track_queries = structured.track_queries
|
39
39
|
|
40
|
+
# Context manager for setting the query protocol for the scope.
|
41
|
+
query_protocol = structured.query_protocol
|
42
|
+
|
40
43
|
# Helper function for map-reduce style querying.
|
41
44
|
query_and_reduce = structured.query_and_reduce
|
42
45
|
|
@@ -35,13 +35,18 @@ class ActionEval(lf.eval.v2.Evaluation):
|
|
35
35
|
example_input = example.input
|
36
36
|
action = example_input.action
|
37
37
|
session = action_lib.Session(id=f'{self.id}#example-{example.id}')
|
38
|
+
|
39
|
+
# NOTE(daiyip): Setting session as metadata before action execution, so we
|
40
|
+
# could use `Evaluation.state.in_progress_examples` to access the session
|
41
|
+
# for status reporting from other threads.
|
42
|
+
example.metadata['session'] = session
|
43
|
+
|
38
44
|
with lf.logging.use_log_level('fatal'):
|
39
45
|
kwargs = self.action_args.copy()
|
40
46
|
kwargs.update(verbose=True)
|
41
47
|
action(session=session, **kwargs)
|
42
48
|
return session.final_result, dict(session=session)
|
43
49
|
|
44
|
-
|
45
50
|
#
|
46
51
|
# TODO(daiyip): Remove V1 once V2 is fully launched.
|
47
52
|
#
|
langfun/core/eval/base_test.py
CHANGED
@@ -195,7 +195,7 @@ class EvaluationTest(unittest.TestCase):
|
|
195
195
|
score=1.0,
|
196
196
|
logprobs=None,
|
197
197
|
is_cached=False,
|
198
|
-
usage=lf.LMSamplingUsage(
|
198
|
+
usage=lf.LMSamplingUsage(428, 24, 452),
|
199
199
|
tags=['lm-response', 'lm-output', 'transformed'],
|
200
200
|
),
|
201
201
|
)
|
@@ -234,12 +234,12 @@ class EvaluationTest(unittest.TestCase):
|
|
234
234
|
}
|
235
235
|
),
|
236
236
|
usage=dict(
|
237
|
-
total_prompt_tokens=
|
237
|
+
total_prompt_tokens=856,
|
238
238
|
total_completion_tokens=25,
|
239
239
|
num_usages=2,
|
240
|
-
average_prompt_tokens=
|
240
|
+
average_prompt_tokens=428,
|
241
241
|
average_completion_tokens=12,
|
242
|
-
average_total_tokens=
|
242
|
+
average_total_tokens=440,
|
243
243
|
),
|
244
244
|
),
|
245
245
|
)
|
@@ -167,6 +167,8 @@ class Evaluation(experiment_lib.Experiment):
|
|
167
167
|
example.input = self.example_input_by_id(example.id)
|
168
168
|
|
169
169
|
checkpointed = self._state.ckpt_example(example.id)
|
170
|
+
self._state.update(example, in_progress=True)
|
171
|
+
|
170
172
|
with pg.timeit('evaluate') as timeit, lf.track_usages() as usage_summary:
|
171
173
|
if checkpointed is None or checkpointed.has_error:
|
172
174
|
if checkpointed is None:
|
@@ -221,7 +223,7 @@ class Evaluation(experiment_lib.Experiment):
|
|
221
223
|
if example.newly_processed:
|
222
224
|
example.end_time = time.time()
|
223
225
|
|
224
|
-
self._state.update(example)
|
226
|
+
self._state.update(example, in_progress=False)
|
225
227
|
return example
|
226
228
|
|
227
229
|
def _process(
|
@@ -501,6 +503,21 @@ class Evaluation(experiment_lib.Experiment):
|
|
501
503
|
)
|
502
504
|
)
|
503
505
|
|
506
|
+
def _in_progress_tab() -> pg.views.html.controls.Tab | None:
|
507
|
+
"""Renders a tab for the in progress examples."""
|
508
|
+
if not self.state.in_progress_examples:
|
509
|
+
return None
|
510
|
+
return pg.views.html.controls.Tab(
|
511
|
+
label='In Progress',
|
512
|
+
content=pg.Html.element(
|
513
|
+
'div', [
|
514
|
+
self._in_progress_view(
|
515
|
+
list(self.state.in_progress_examples.values())
|
516
|
+
)
|
517
|
+
]
|
518
|
+
)
|
519
|
+
)
|
520
|
+
|
504
521
|
def _metric_tab(metric: metrics_lib.Metric) -> pg.views.html.controls.Tab:
|
505
522
|
"""Renders a tab for a metric (group)."""
|
506
523
|
return pg.views.html.controls.Tab(
|
@@ -571,10 +588,9 @@ class Evaluation(experiment_lib.Experiment):
|
|
571
588
|
pg.views.html.controls.TabControl(
|
572
589
|
[
|
573
590
|
_definition_tab(),
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
_logs_tab()
|
591
|
+
[_metric_tab(m) for m in self.metrics],
|
592
|
+
_in_progress_tab(),
|
593
|
+
_logs_tab(),
|
578
594
|
],
|
579
595
|
selected=1,
|
580
596
|
)
|
@@ -598,6 +614,27 @@ class Evaluation(experiment_lib.Experiment):
|
|
598
614
|
css_classes=['eval-details'],
|
599
615
|
)
|
600
616
|
|
617
|
+
def _in_progress_view(
|
618
|
+
self, in_progress_examples: list[example_lib.Example]
|
619
|
+
) -> pg.Html:
|
620
|
+
"""Renders a HTML view for the in-progress examples."""
|
621
|
+
current_time = time.time()
|
622
|
+
logs = [f'(Total {len(in_progress_examples)} examples in progress)']
|
623
|
+
for example in in_progress_examples:
|
624
|
+
if example.newly_processed:
|
625
|
+
logs.append(
|
626
|
+
f'Example {example.id}: In progress for '
|
627
|
+
f'{current_time - example.start_time:.2f} seconds.'
|
628
|
+
)
|
629
|
+
else:
|
630
|
+
logs.append(f'Example {example.id}: Recomputing metrics...')
|
631
|
+
return pg.Html.element(
|
632
|
+
'textarea',
|
633
|
+
[pg.Html.escape('\n'.join(logs))],
|
634
|
+
readonly=True,
|
635
|
+
css_classes=['logs-textarea'],
|
636
|
+
)
|
637
|
+
|
601
638
|
def _html_tree_view_config(self) -> dict[str, Any]:
|
602
639
|
return dict(
|
603
640
|
css_classes=['eval-card'] if self.is_leaf else None
|
@@ -716,14 +753,27 @@ class EvaluationState:
|
|
716
753
|
'Whether the example is evaluated.'
|
717
754
|
] = False
|
718
755
|
|
756
|
+
in_progress: Annotated[
|
757
|
+
bool,
|
758
|
+
(
|
759
|
+
'Whether the example is in progress. '
|
760
|
+
)
|
761
|
+
] = False
|
762
|
+
|
719
763
|
newly_processed: Annotated[
|
720
764
|
bool,
|
721
|
-
|
765
|
+
(
|
766
|
+
'Whether the example is newly processed. '
|
767
|
+
'Applicable only when evaluated is True.'
|
768
|
+
)
|
722
769
|
] = False
|
723
770
|
|
724
771
|
has_error: Annotated[
|
725
772
|
bool,
|
726
|
-
|
773
|
+
(
|
774
|
+
'Whether the example has error. '
|
775
|
+
'Applicable only when evaluated is True.'
|
776
|
+
)
|
727
777
|
] = False
|
728
778
|
|
729
779
|
def __init__(self):
|
@@ -732,6 +782,7 @@ class EvaluationState:
|
|
732
782
|
self._evaluation_status: dict[
|
733
783
|
int, EvaluationState.ExampleStatus
|
734
784
|
] = {}
|
785
|
+
self._in_progress_examples: dict[int, example_lib.Example] = {}
|
735
786
|
|
736
787
|
def load(
|
737
788
|
self,
|
@@ -758,6 +809,11 @@ class EvaluationState:
|
|
758
809
|
"""Returns the evaluation status of the examples."""
|
759
810
|
return self._evaluation_status
|
760
811
|
|
812
|
+
@property
|
813
|
+
def in_progress_examples(self) -> dict[int, example_lib.Example]:
|
814
|
+
"""Returns the in-progress examples."""
|
815
|
+
return self._in_progress_examples
|
816
|
+
|
761
817
|
@property
|
762
818
|
def ckpt_examples(self) -> dict[int, example_lib.Example]:
|
763
819
|
"""Returns the unevaluated examples from checkpoints."""
|
@@ -773,17 +829,27 @@ class EvaluationState:
|
|
773
829
|
example_id, EvaluationState.ExampleStatus()
|
774
830
|
)
|
775
831
|
|
776
|
-
def update(self, example: example_lib.Example) -> None:
|
832
|
+
def update(self, example: example_lib.Example, in_progress: bool) -> None:
|
777
833
|
"""Updates the state with the given example."""
|
778
|
-
self._update_status(example)
|
779
|
-
|
780
|
-
|
834
|
+
self._update_status(example, in_progress)
|
835
|
+
|
836
|
+
if in_progress:
|
837
|
+
self._in_progress_examples[example.id] = example
|
838
|
+
else:
|
839
|
+
self._in_progress_examples.pop(example.id, None)
|
840
|
+
# Processed examples will be removed once it's done.
|
841
|
+
self._ckpt_examples.pop(example.id, None)
|
781
842
|
|
782
|
-
def _update_status(
|
843
|
+
def _update_status(
|
844
|
+
self,
|
845
|
+
example: example_lib.Example,
|
846
|
+
in_progress: bool
|
847
|
+
) -> None:
|
783
848
|
"""Updates the evaluation status of the example."""
|
784
849
|
self._evaluation_status[example.id] = (
|
785
850
|
EvaluationState.ExampleStatus(
|
786
851
|
evaluated=example.output != pg.MISSING_VALUE,
|
852
|
+
in_progress=in_progress,
|
787
853
|
newly_processed=example.newly_processed,
|
788
854
|
has_error=example.has_error,
|
789
855
|
)
|
@@ -79,8 +79,10 @@ class EvaluationTest(unittest.TestCase):
|
|
79
79
|
exp = eval_test_helper.TestEvaluation()
|
80
80
|
example = exp.evaluate(Example(id=3))
|
81
81
|
self.assertTrue(exp.state.get_status(3).evaluated)
|
82
|
+
self.assertFalse(exp.state.get_status(3).in_progress)
|
82
83
|
self.assertTrue(exp.state.get_status(3).newly_processed)
|
83
84
|
self.assertFalse(exp.state.get_status(3).has_error)
|
85
|
+
self.assertEqual(exp.state.in_progress_examples, {})
|
84
86
|
self.assertTrue(example.newly_processed)
|
85
87
|
self.assertEqual(example.input, pg.Dict(x=2, y=4, groundtruth=6))
|
86
88
|
self.assertEqual(example.output, 6)
|
@@ -55,8 +55,11 @@ from langfun.core.structured.parsing import call
|
|
55
55
|
|
56
56
|
from langfun.core.structured.querying import track_queries
|
57
57
|
from langfun.core.structured.querying import QueryInvocation
|
58
|
+
|
59
|
+
from langfun.core.structured.querying import LfQuery
|
58
60
|
from langfun.core.structured.querying import query
|
59
61
|
from langfun.core.structured.querying import query_and_reduce
|
62
|
+
from langfun.core.structured.querying import query_protocol
|
60
63
|
|
61
64
|
from langfun.core.structured.querying import query_prompt
|
62
65
|
from langfun.core.structured.querying import query_output
|
@@ -340,8 +340,11 @@ class Mapping(lf.LangFunc):
|
|
340
340
|
schema_title: Annotated[str, 'The section title for schema.'] = 'SCHEMA'
|
341
341
|
|
342
342
|
protocol: Annotated[
|
343
|
-
|
344
|
-
|
343
|
+
str,
|
344
|
+
(
|
345
|
+
'A string representing the protocol for formatting the prompt. '
|
346
|
+
'Built-in Langfun protocols are: `python` and `json`.'
|
347
|
+
),
|
345
348
|
] = 'python'
|
346
349
|
|
347
350
|
#
|
@@ -15,8 +15,9 @@
|
|
15
15
|
|
16
16
|
import contextlib
|
17
17
|
import functools
|
18
|
+
import inspect
|
18
19
|
import time
|
19
|
-
from typing import Annotated, Any, Callable, Iterator, Type, Union
|
20
|
+
from typing import Annotated, Any, Callable, ClassVar, Iterator, Type, Union
|
20
21
|
import uuid
|
21
22
|
|
22
23
|
import langfun.core as lf
|
@@ -26,8 +27,35 @@ import pyglove as pg
|
|
26
27
|
|
27
28
|
|
28
29
|
@lf.use_init_args(['schema', 'default', 'examples'])
|
29
|
-
class
|
30
|
-
"""
|
30
|
+
class LfQuery(mapping.Mapping):
|
31
|
+
"""Base class for different implementations of `lf.query`.
|
32
|
+
|
33
|
+
By subclassing this class, users could create variations of prompts for
|
34
|
+
`lf.query` and associated them with specific protocols and versions.
|
35
|
+
|
36
|
+
For example:
|
37
|
+
|
38
|
+
```
|
39
|
+
class _MyLfQuery(LFQuery):
|
40
|
+
protocol = 'my_format'
|
41
|
+
version = '1.0'
|
42
|
+
|
43
|
+
template_str = inspect.cleandoc(
|
44
|
+
'''
|
45
|
+
...
|
46
|
+
'''
|
47
|
+
)
|
48
|
+
mapping_template = lf.Template(
|
49
|
+
'''
|
50
|
+
...
|
51
|
+
'''
|
52
|
+
)
|
53
|
+
|
54
|
+
lf.query(..., protocol='my_format:1.0')
|
55
|
+
```
|
56
|
+
|
57
|
+
(THIS IS NOT A TEMPLATE)
|
58
|
+
"""
|
31
59
|
|
32
60
|
context_title = 'CONTEXT'
|
33
61
|
input_title = 'INPUT_OBJECT'
|
@@ -37,8 +65,81 @@ class _QueryStructure(mapping.Mapping):
|
|
37
65
|
schema_lib.schema_spec(), 'Required schema for parsing.'
|
38
66
|
]
|
39
67
|
|
68
|
+
# A map from (protocol, version) to the query structure class.
|
69
|
+
# This is used to map different protocols/versions to different templates.
|
70
|
+
# So users can use `lf.query(..., protocol='<protocol>:<version>')` to use
|
71
|
+
# a specific version of the prompt. We use this feature to support variations
|
72
|
+
# of prompts and maintain backward compatibility.
|
73
|
+
_OOP_PROMPT_MAP: ClassVar[
|
74
|
+
dict[
|
75
|
+
str, # protocol.
|
76
|
+
dict[
|
77
|
+
str, # version.
|
78
|
+
Type['LfQuery']
|
79
|
+
]
|
80
|
+
]
|
81
|
+
] = {}
|
82
|
+
|
83
|
+
# This the flag to update default protocol version.
|
84
|
+
_DEFAULT_PROTOCOL_VERSIONS: ClassVar[dict[str, str]] = {
|
85
|
+
'python': '2.0',
|
86
|
+
'json': '1.0',
|
87
|
+
}
|
88
|
+
|
89
|
+
def __init_subclass__(cls) -> Any:
|
90
|
+
super().__init_subclass__()
|
91
|
+
if not inspect.isabstract(cls):
|
92
|
+
protocol = cls.__schema__['protocol'].default_value
|
93
|
+
version_dict = cls._OOP_PROMPT_MAP.get(protocol)
|
94
|
+
if version_dict is None:
|
95
|
+
version_dict = {}
|
96
|
+
cls._OOP_PROMPT_MAP[protocol] = version_dict
|
97
|
+
dest_cls = version_dict.get(cls.version)
|
98
|
+
if dest_cls is not None and dest_cls.__type_name__ != cls.__type_name__:
|
99
|
+
raise ValueError(
|
100
|
+
f'Version {cls.version} is already registered for {dest_cls!r} '
|
101
|
+
f'under protocol {protocol!r}. Please use a different version.'
|
102
|
+
)
|
103
|
+
version_dict[cls.version] = cls
|
104
|
+
|
105
|
+
@classmethod
|
106
|
+
def from_protocol(cls, protocol: str) -> Type['LfQuery']:
|
107
|
+
"""Returns a query structure from the given protocol and version."""
|
108
|
+
if ':' in protocol:
|
109
|
+
protocol, version = protocol.split(':')
|
110
|
+
else:
|
111
|
+
version = cls._DEFAULT_PROTOCOL_VERSIONS.get(protocol)
|
112
|
+
if version is None:
|
113
|
+
version_dict = cls._OOP_PROMPT_MAP.get(protocol)
|
114
|
+
if version_dict is None:
|
115
|
+
raise ValueError(
|
116
|
+
f'Protocol {protocol!r} is not supported. Available protocols: '
|
117
|
+
f'{sorted(cls._OOP_PROMPT_MAP.keys())}.'
|
118
|
+
)
|
119
|
+
elif len(version_dict) == 1:
|
120
|
+
version = list(version_dict.keys())[0]
|
121
|
+
else:
|
122
|
+
raise ValueError(
|
123
|
+
f'Multiple versions found for protocol {protocol!r}, please '
|
124
|
+
f'specify a version with "{protocol}:<version>".'
|
125
|
+
)
|
126
|
+
|
127
|
+
version_dict = cls._OOP_PROMPT_MAP.get(protocol)
|
128
|
+
if version_dict is None:
|
129
|
+
raise ValueError(
|
130
|
+
f'Protocol {protocol!r} is not supported. Available protocols: '
|
131
|
+
f'{sorted(cls._OOP_PROMPT_MAP.keys())}.'
|
132
|
+
)
|
133
|
+
dest_cls = version_dict.get(version)
|
134
|
+
if dest_cls is None:
|
135
|
+
raise ValueError(
|
136
|
+
f'Version {version!r} is not supported for protocol {protocol!r}. '
|
137
|
+
f'Available versions: {sorted(version_dict.keys())}.'
|
138
|
+
)
|
139
|
+
return dest_cls
|
40
140
|
|
41
|
-
|
141
|
+
|
142
|
+
class _LfQueryJsonV1(LfQuery):
|
42
143
|
"""Query a structured value using JSON as the protocol."""
|
43
144
|
|
44
145
|
preamble = """
|
@@ -58,12 +159,13 @@ class _QueryStructureJson(_QueryStructure):
|
|
58
159
|
{"result": {"_type": "langfun.core.structured.query.Answer", "final_answer": 2}}
|
59
160
|
"""
|
60
161
|
|
162
|
+
version = '1.0'
|
61
163
|
protocol = 'json'
|
62
164
|
schema_title = 'SCHEMA'
|
63
165
|
output_title = 'JSON'
|
64
166
|
|
65
167
|
|
66
|
-
class
|
168
|
+
class _LfQueryPythonV1(LfQuery):
|
67
169
|
"""Query a structured value using Python as the protocol."""
|
68
170
|
|
69
171
|
preamble = """
|
@@ -87,20 +189,87 @@ class _QueryStructurePython(_QueryStructure):
|
|
87
189
|
)
|
88
190
|
```
|
89
191
|
"""
|
192
|
+
version = '1.0'
|
90
193
|
protocol = 'python'
|
91
194
|
schema_title = 'OUTPUT_TYPE'
|
92
195
|
output_title = 'OUTPUT_OBJECT'
|
196
|
+
mapping_template = lf.Template(
|
197
|
+
"""
|
198
|
+
{%- if example.context -%}
|
199
|
+
{{ context_title}}:
|
200
|
+
{{ example.context | indent(2, True)}}
|
93
201
|
|
202
|
+
{% endif -%}
|
94
203
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
204
|
+
{{ input_title }}:
|
205
|
+
{{ example.input_repr(protocol, compact=False) | indent(2, True) }}
|
206
|
+
|
207
|
+
{% if example.schema -%}
|
208
|
+
{{ schema_title }}:
|
209
|
+
{{ example.schema_repr(protocol) | indent(2, True) }}
|
210
|
+
|
211
|
+
{% endif -%}
|
212
|
+
|
213
|
+
{{ output_title }}:
|
214
|
+
{%- if example.has_output %}
|
215
|
+
{{ example.output_repr(protocol, compact=False) | indent(2, True) }}
|
216
|
+
{% endif -%}
|
217
|
+
"""
|
218
|
+
)
|
219
|
+
|
220
|
+
|
221
|
+
class _LfQueryPythonV2(LfQuery):
|
222
|
+
"""Query a structured value using Python as the protocol."""
|
223
|
+
|
224
|
+
preamble = """
|
225
|
+
Please respond to the last {{ input_title }} with {{ output_title }} only according to {{ schema_title }}.
|
226
|
+
|
227
|
+
{{ input_title }}:
|
228
|
+
1 + 1 =
|
229
|
+
|
230
|
+
{{ schema_title }}:
|
231
|
+
Answer
|
232
|
+
|
233
|
+
```python
|
234
|
+
class Answer:
|
235
|
+
final_answer: int
|
236
|
+
```
|
237
|
+
|
238
|
+
{{ output_title }}:
|
239
|
+
```python
|
240
|
+
output = Answer(
|
241
|
+
final_answer=2
|
242
|
+
)
|
243
|
+
```
|
244
|
+
"""
|
245
|
+
version = '2.0'
|
246
|
+
protocol = 'python'
|
247
|
+
input_title = 'REQUEST'
|
248
|
+
schema_title = 'OUTPUT PYTHON TYPE'
|
249
|
+
output_title = 'OUTPUT PYTHON OBJECT'
|
250
|
+
mapping_template = lf.Template(
|
251
|
+
"""
|
252
|
+
{%- if example.context -%}
|
253
|
+
{{ context_title}}:
|
254
|
+
{{ example.context | indent(2, True)}}
|
255
|
+
|
256
|
+
{% endif -%}
|
257
|
+
|
258
|
+
{{ input_title }}:
|
259
|
+
{{ example.input_repr(protocol, compact=False) | indent(2, True) }}
|
260
|
+
|
261
|
+
{% if example.schema -%}
|
262
|
+
{{ schema_title }}:
|
263
|
+
{{ example.schema_repr(protocol) | indent(2, True) }}
|
264
|
+
|
265
|
+
{% endif -%}
|
266
|
+
|
267
|
+
{{ output_title }}:
|
268
|
+
{%- if example.has_output %}
|
269
|
+
{{ example.output_repr(protocol, compact=False, assign_to_var='output') | indent(2, True) }}
|
270
|
+
{% endif -%}
|
271
|
+
"""
|
272
|
+
)
|
104
273
|
|
105
274
|
|
106
275
|
def query(
|
@@ -116,7 +285,7 @@ def query(
|
|
116
285
|
response_postprocess: Callable[[str], str] | None = None,
|
117
286
|
autofix: int = 0,
|
118
287
|
autofix_lm: lf.LanguageModel | None = None,
|
119
|
-
protocol:
|
288
|
+
protocol: str | None = None,
|
120
289
|
returns_message: bool = False,
|
121
290
|
skip_lm: bool = False,
|
122
291
|
invocation_id: str | None = None,
|
@@ -259,8 +428,14 @@ def query(
|
|
259
428
|
disable auto-fixing. Not supported with the `'json'` protocol.
|
260
429
|
autofix_lm: The LM to use for auto-fixing. Defaults to the `autofix_lm`
|
261
430
|
from `lf.context` or the main `lm`.
|
262
|
-
protocol: Format for schema representation.
|
263
|
-
`'python'
|
431
|
+
protocol: Format for schema representation. Builtin choices are `'json'` or
|
432
|
+
`'python'`, users could extend with their own protocols by subclassing
|
433
|
+
`lf.structured.LfQuery'. Also protocol could be specified with a version
|
434
|
+
in the format of 'protocol:version', e.g., 'python:1.0', so users could
|
435
|
+
use a specific version of the prompt based on the protocol. Please see the
|
436
|
+
documentation of `LfQuery` for more details. If None, the protocol from
|
437
|
+
context manager `lf.query_protocol` will be used, or 'python' if not
|
438
|
+
specified.
|
264
439
|
returns_message: If `True`, returns an `lf.Message` object instead of
|
265
440
|
the final parsed result.
|
266
441
|
skip_lm: If `True`, skips the LLM call and returns the rendered
|
@@ -280,6 +455,9 @@ def query(
|
|
280
455
|
"""
|
281
456
|
# Internal usage logging.
|
282
457
|
|
458
|
+
if protocol is None:
|
459
|
+
protocol = lf.context_value('__query_protocol__', 'python')
|
460
|
+
|
283
461
|
invocation_id = invocation_id or f'query@{uuid.uuid4().hex[-7:]}'
|
284
462
|
# Multiple quries will be issued when `lm` is a list or `num_samples` is
|
285
463
|
# greater than 1.
|
@@ -382,7 +560,7 @@ def query(
|
|
382
560
|
output_message = lf.AIMessage(processed_text, source=output_message)
|
383
561
|
else:
|
384
562
|
# Query with structured output.
|
385
|
-
output_message =
|
563
|
+
output_message = LfQuery.from_protocol(protocol)(
|
386
564
|
input=(
|
387
565
|
query_input.render(lm=lm)
|
388
566
|
if isinstance(query_input, lf.Template)
|
@@ -436,6 +614,15 @@ def query(
|
|
436
614
|
return output_message if returns_message else _result(output_message)
|
437
615
|
|
438
616
|
|
617
|
+
@contextlib.contextmanager
|
618
|
+
def query_protocol(protocol: str) -> Iterator[None]:
|
619
|
+
"""Context manager for setting the query protocol for the scope."""
|
620
|
+
with lf.context(__query_protocol__=protocol):
|
621
|
+
try:
|
622
|
+
yield
|
623
|
+
finally:
|
624
|
+
pass
|
625
|
+
|
439
626
|
#
|
440
627
|
# Helper function for map-reduce style querying.
|
441
628
|
#
|
@@ -90,7 +90,7 @@ class QueryTest(unittest.TestCase):
|
|
90
90
|
score=1.0,
|
91
91
|
logprobs=None,
|
92
92
|
is_cached=False,
|
93
|
-
usage=lf.LMSamplingUsage(
|
93
|
+
usage=lf.LMSamplingUsage(364, 1, 365),
|
94
94
|
tags=['lm-response', 'lm-output', 'transformed'],
|
95
95
|
),
|
96
96
|
)
|
@@ -143,26 +143,26 @@ class QueryTest(unittest.TestCase):
|
|
143
143
|
y=2,
|
144
144
|
lm=lm.clone(),
|
145
145
|
expected_snippet=(
|
146
|
-
'Please respond to the last
|
147
|
-
'according to
|
148
|
-
'
|
149
|
-
'
|
146
|
+
'Please respond to the last REQUEST with OUTPUT PYTHON OBJECT '
|
147
|
+
'only according to OUTPUT PYTHON TYPE.\n\n'
|
148
|
+
'REQUEST:\n 1 + 1 =\n\n'
|
149
|
+
'OUTPUT PYTHON TYPE:\n'
|
150
150
|
' Answer\n\n'
|
151
151
|
' ```python\n'
|
152
152
|
' class Answer:\n'
|
153
153
|
' final_answer: int\n'
|
154
154
|
' ```\n\n'
|
155
|
-
'
|
155
|
+
'OUTPUT PYTHON OBJECT:\n'
|
156
156
|
' ```python\n'
|
157
|
-
' Answer(\n'
|
157
|
+
' output = Answer(\n'
|
158
158
|
' final_answer=2\n'
|
159
159
|
' )\n'
|
160
160
|
' ```\n\n'
|
161
|
-
'
|
161
|
+
'REQUEST:\n'
|
162
162
|
' What is 1 + 2?\n\n'
|
163
|
-
'
|
163
|
+
'OUTPUT PYTHON TYPE:\n'
|
164
164
|
' int\n\n'
|
165
|
-
'
|
165
|
+
'OUTPUT PYTHON OBJECT:'
|
166
166
|
),
|
167
167
|
)
|
168
168
|
|
@@ -176,26 +176,26 @@ class QueryTest(unittest.TestCase):
|
|
176
176
|
lm=lm.clone(),
|
177
177
|
template_str='!!{{ DEFAULT }}!!',
|
178
178
|
expected_snippet=(
|
179
|
-
'!!Please respond to the last
|
180
|
-
'according to
|
181
|
-
'
|
182
|
-
'
|
179
|
+
'!!Please respond to the last REQUEST with OUTPUT PYTHON OBJECT '
|
180
|
+
'only according to OUTPUT PYTHON TYPE.\n\n'
|
181
|
+
'REQUEST:\n 1 + 1 =\n\n'
|
182
|
+
'OUTPUT PYTHON TYPE:\n'
|
183
183
|
' Answer\n\n'
|
184
184
|
' ```python\n'
|
185
185
|
' class Answer:\n'
|
186
186
|
' final_answer: int\n'
|
187
187
|
' ```\n\n'
|
188
|
-
'
|
188
|
+
'OUTPUT PYTHON OBJECT:\n'
|
189
189
|
' ```python\n'
|
190
|
-
' Answer(\n'
|
190
|
+
' output = Answer(\n'
|
191
191
|
' final_answer=2\n'
|
192
192
|
' )\n'
|
193
193
|
' ```\n\n'
|
194
|
-
'
|
194
|
+
'REQUEST:\n'
|
195
195
|
' What is 1 + 2?\n\n'
|
196
|
-
'
|
196
|
+
'OUTPUT PYTHON TYPE:\n'
|
197
197
|
' int\n\n'
|
198
|
-
'
|
198
|
+
'OUTPUT PYTHON OBJECT:!!'
|
199
199
|
),
|
200
200
|
)
|
201
201
|
|
@@ -220,7 +220,7 @@ class QueryTest(unittest.TestCase):
|
|
220
220
|
y=2,
|
221
221
|
lm=lm.clone(),
|
222
222
|
expected_snippet=(
|
223
|
-
'\n\
|
223
|
+
'\n\nREQUEST:\n ```python\n [\n 1\n ]\n ```\n\n'
|
224
224
|
),
|
225
225
|
)
|
226
226
|
|
@@ -236,7 +236,7 @@ class QueryTest(unittest.TestCase):
|
|
236
236
|
modalities.Image.from_bytes(b'mock_image'),
|
237
237
|
int,
|
238
238
|
lm=lm,
|
239
|
-
expected_snippet='\n\
|
239
|
+
expected_snippet='\n\nREQUEST:\n <<[[input]]>>\n\n',
|
240
240
|
expected_modalities=1,
|
241
241
|
)
|
242
242
|
|
@@ -290,7 +290,7 @@ class QueryTest(unittest.TestCase):
|
|
290
290
|
list[str],
|
291
291
|
lm=lm,
|
292
292
|
expected_snippet=inspect.cleandoc("""
|
293
|
-
|
293
|
+
REQUEST:
|
294
294
|
```python
|
295
295
|
[
|
296
296
|
<<[[input[0]]]>>,
|
@@ -318,31 +318,36 @@ class QueryTest(unittest.TestCase):
|
|
318
318
|
],
|
319
319
|
lm=lm,
|
320
320
|
expected_snippet=inspect.cleandoc("""
|
321
|
-
|
321
|
+
REQUEST:
|
322
322
|
```python
|
323
323
|
[
|
324
324
|
<<[[examples[0].input[0]]]>>
|
325
325
|
]
|
326
326
|
```
|
327
327
|
|
328
|
-
|
328
|
+
OUTPUT PYTHON TYPE:
|
329
329
|
list[str]
|
330
330
|
|
331
|
-
|
331
|
+
OUTPUT PYTHON OBJECT:
|
332
332
|
```python
|
333
|
-
[
|
333
|
+
output = [
|
334
334
|
'dog'
|
335
335
|
]
|
336
336
|
```
|
337
337
|
|
338
338
|
|
339
|
-
|
339
|
+
REQUEST:
|
340
340
|
```python
|
341
341
|
[
|
342
342
|
<<[[input[0]]]>>,
|
343
343
|
<<[[input[1]]]>>
|
344
344
|
]
|
345
345
|
```
|
346
|
+
|
347
|
+
OUTPUT PYTHON TYPE:
|
348
|
+
list[str]
|
349
|
+
|
350
|
+
OUTPUT PYTHON OBJECT:
|
346
351
|
"""),
|
347
352
|
expected_modalities=3,
|
348
353
|
)
|
@@ -410,20 +415,69 @@ class QueryTest(unittest.TestCase):
|
|
410
415
|
self.assertEqual([r.text for r in results], ['1', 'abc'])
|
411
416
|
self.assertEqual([r.result for r in results], [1, 0])
|
412
417
|
|
413
|
-
def
|
414
|
-
|
415
|
-
|
418
|
+
def test_from_protocol(self):
|
419
|
+
self.assertIs(
|
420
|
+
querying.LfQuery.from_protocol('python'), querying._LfQueryPythonV2
|
421
|
+
)
|
422
|
+
self.assertIs(
|
423
|
+
querying.LfQuery.from_protocol('python:1.0'),
|
424
|
+
querying._LfQueryPythonV1
|
425
|
+
)
|
426
|
+
|
427
|
+
class MyLfQuery(querying.LfQuery):
|
428
|
+
protocol = 'yaml'
|
429
|
+
version = '1.0'
|
430
|
+
|
431
|
+
self.assertIs(
|
432
|
+
querying.LfQuery.from_protocol('yaml:1.0'),
|
433
|
+
MyLfQuery
|
434
|
+
)
|
435
|
+
self.assertIs(
|
436
|
+
querying.LfQuery.from_protocol('yaml'),
|
437
|
+
MyLfQuery
|
438
|
+
)
|
439
|
+
|
440
|
+
with self.assertRaisesRegex(
|
441
|
+
ValueError, 'Version .* is already registered'
|
442
|
+
):
|
443
|
+
class MyLfQuery2(querying.LfQuery): # pylint: disable=unused-variable
|
444
|
+
protocol = 'yaml'
|
445
|
+
version = '1.0'
|
446
|
+
|
447
|
+
with self.assertRaisesRegex(
|
448
|
+
ValueError, 'Version \'2.0\' is not supported for protocol \'yaml\''
|
449
|
+
):
|
450
|
+
querying.LfQuery.from_protocol('yaml:2.0')
|
451
|
+
|
452
|
+
class MyLfQuery3(querying.LfQuery): # pylint: disable=unused-variable
|
453
|
+
protocol = 'yaml'
|
454
|
+
version = '3.0'
|
455
|
+
|
456
|
+
with self.assertRaisesRegex(
|
457
|
+
ValueError, 'Multiple versions found for protocol \'yaml\''
|
458
|
+
):
|
459
|
+
querying.LfQuery.from_protocol('yaml')
|
460
|
+
|
461
|
+
with self.assertRaisesRegex(
|
462
|
+
ValueError, 'Protocol \'text\' is not supported'
|
463
|
+
):
|
464
|
+
querying.LfQuery.from_protocol('text')
|
465
|
+
|
466
|
+
with self.assertRaisesRegex(
|
467
|
+
ValueError, 'Protocol \'text\' is not supported'
|
468
|
+
):
|
469
|
+
querying.LfQuery.from_protocol('text:1.0')
|
416
470
|
|
417
471
|
def test_query_prompt(self):
|
418
472
|
self.assertEqual(
|
419
473
|
querying.query_prompt('what is this?', int),
|
420
474
|
inspect.cleandoc("""
|
421
|
-
Please respond to the last
|
475
|
+
Please respond to the last REQUEST with OUTPUT PYTHON OBJECT only according to OUTPUT PYTHON TYPE.
|
422
476
|
|
423
|
-
|
477
|
+
REQUEST:
|
424
478
|
1 + 1 =
|
425
479
|
|
426
|
-
|
480
|
+
OUTPUT PYTHON TYPE:
|
427
481
|
Answer
|
428
482
|
|
429
483
|
```python
|
@@ -431,20 +485,20 @@ class QueryTest(unittest.TestCase):
|
|
431
485
|
final_answer: int
|
432
486
|
```
|
433
487
|
|
434
|
-
|
488
|
+
OUTPUT PYTHON OBJECT:
|
435
489
|
```python
|
436
|
-
Answer(
|
490
|
+
output = Answer(
|
437
491
|
final_answer=2
|
438
492
|
)
|
439
493
|
```
|
440
494
|
|
441
|
-
|
495
|
+
REQUEST:
|
442
496
|
what is this?
|
443
497
|
|
444
|
-
|
498
|
+
OUTPUT PYTHON TYPE:
|
445
499
|
int
|
446
500
|
|
447
|
-
|
501
|
+
OUTPUT PYTHON OBJECT:
|
448
502
|
"""),
|
449
503
|
)
|
450
504
|
|
@@ -632,10 +686,10 @@ class QueryTest(unittest.TestCase):
|
|
632
686
|
)
|
633
687
|
|
634
688
|
|
635
|
-
class
|
689
|
+
class LfQueryPythonV1Test(unittest.TestCase):
|
636
690
|
|
637
691
|
def test_render_no_examples(self):
|
638
|
-
l = querying.
|
692
|
+
l = querying.LfQuery.from_protocol('python:1.0')(
|
639
693
|
input=lf.AIMessage('Compute 12 / 6 + 2.'), schema=int
|
640
694
|
)
|
641
695
|
self.assertEqual(
|
@@ -672,7 +726,7 @@ class QueryStructurePythonTest(unittest.TestCase):
|
|
672
726
|
)
|
673
727
|
|
674
728
|
def test_render(self):
|
675
|
-
l = querying.
|
729
|
+
l = querying.LfQuery.from_protocol('python:1.0')(
|
676
730
|
input=lf.AIMessage('Compute 12 / 6 + 2.'),
|
677
731
|
schema=int,
|
678
732
|
examples=[
|
@@ -782,7 +836,7 @@ class QueryStructurePythonTest(unittest.TestCase):
|
|
782
836
|
),
|
783
837
|
override_attrs=True,
|
784
838
|
):
|
785
|
-
l = querying.
|
839
|
+
l = querying.LfQuery.from_protocol('python:1.0')(
|
786
840
|
input=lm_input,
|
787
841
|
schema=[Itinerary],
|
788
842
|
examples=[
|
@@ -810,6 +864,115 @@ class QueryStructurePythonTest(unittest.TestCase):
|
|
810
864
|
self.assertEqual(len(r.result[0].activities), 3)
|
811
865
|
self.assertIsNone(r.result[0].hotel)
|
812
866
|
|
867
|
+
|
868
|
+
class LfQueryPythonV2Test(unittest.TestCase):
|
869
|
+
|
870
|
+
def test_render_no_examples(self):
|
871
|
+
l = querying.LfQuery.from_protocol('python:2.0')(
|
872
|
+
input=lf.AIMessage('Compute 12 / 6 + 2.'), schema=int
|
873
|
+
)
|
874
|
+
self.assertEqual(
|
875
|
+
l.render().text,
|
876
|
+
inspect.cleandoc("""
|
877
|
+
Please respond to the last REQUEST with OUTPUT PYTHON OBJECT only according to OUTPUT PYTHON TYPE.
|
878
|
+
|
879
|
+
REQUEST:
|
880
|
+
1 + 1 =
|
881
|
+
|
882
|
+
OUTPUT PYTHON TYPE:
|
883
|
+
Answer
|
884
|
+
|
885
|
+
```python
|
886
|
+
class Answer:
|
887
|
+
final_answer: int
|
888
|
+
```
|
889
|
+
|
890
|
+
OUTPUT PYTHON OBJECT:
|
891
|
+
```python
|
892
|
+
output = Answer(
|
893
|
+
final_answer=2
|
894
|
+
)
|
895
|
+
```
|
896
|
+
|
897
|
+
REQUEST:
|
898
|
+
Compute 12 / 6 + 2.
|
899
|
+
|
900
|
+
OUTPUT PYTHON TYPE:
|
901
|
+
int
|
902
|
+
|
903
|
+
OUTPUT PYTHON OBJECT:
|
904
|
+
"""),
|
905
|
+
)
|
906
|
+
|
907
|
+
def test_render_with_examples(self):
|
908
|
+
l = querying.LfQuery.from_protocol('python:2.0')(
|
909
|
+
input=lf.AIMessage('Compute 12 / 6 + 2.'),
|
910
|
+
schema=int,
|
911
|
+
examples=[
|
912
|
+
mapping.MappingExample(
|
913
|
+
input='What is the answer of 1 plus 1?', output=2
|
914
|
+
),
|
915
|
+
mapping.MappingExample(
|
916
|
+
input='Compute the value of 3 + (2 * 6).', output=15
|
917
|
+
),
|
918
|
+
],
|
919
|
+
)
|
920
|
+
self.assertEqual(
|
921
|
+
l.render().text,
|
922
|
+
inspect.cleandoc("""
|
923
|
+
Please respond to the last REQUEST with OUTPUT PYTHON OBJECT only according to OUTPUT PYTHON TYPE.
|
924
|
+
|
925
|
+
REQUEST:
|
926
|
+
1 + 1 =
|
927
|
+
|
928
|
+
OUTPUT PYTHON TYPE:
|
929
|
+
Answer
|
930
|
+
|
931
|
+
```python
|
932
|
+
class Answer:
|
933
|
+
final_answer: int
|
934
|
+
```
|
935
|
+
|
936
|
+
OUTPUT PYTHON OBJECT:
|
937
|
+
```python
|
938
|
+
output = Answer(
|
939
|
+
final_answer=2
|
940
|
+
)
|
941
|
+
```
|
942
|
+
|
943
|
+
REQUEST:
|
944
|
+
What is the answer of 1 plus 1?
|
945
|
+
|
946
|
+
OUTPUT PYTHON TYPE:
|
947
|
+
int
|
948
|
+
|
949
|
+
OUTPUT PYTHON OBJECT:
|
950
|
+
```python
|
951
|
+
output = 2
|
952
|
+
```
|
953
|
+
|
954
|
+
REQUEST:
|
955
|
+
Compute the value of 3 + (2 * 6).
|
956
|
+
|
957
|
+
OUTPUT PYTHON TYPE:
|
958
|
+
int
|
959
|
+
|
960
|
+
OUTPUT PYTHON OBJECT:
|
961
|
+
```python
|
962
|
+
output = 15
|
963
|
+
```
|
964
|
+
|
965
|
+
|
966
|
+
REQUEST:
|
967
|
+
Compute 12 / 6 + 2.
|
968
|
+
|
969
|
+
OUTPUT PYTHON TYPE:
|
970
|
+
int
|
971
|
+
|
972
|
+
OUTPUT PYTHON OBJECT:
|
973
|
+
"""),
|
974
|
+
)
|
975
|
+
|
813
976
|
def test_bad_response(self):
|
814
977
|
with lf.context(
|
815
978
|
lm=fake.StaticSequence(['a2']),
|
@@ -849,11 +1012,80 @@ class QueryStructurePythonTest(unittest.TestCase):
|
|
849
1012
|
3
|
850
1013
|
)
|
851
1014
|
|
1015
|
+
def test_render(self):
|
1016
|
+
l = querying.LfQuery.from_protocol('python:2.0')(
|
1017
|
+
input=lf.AIMessage('Compute 12 / 6 + 2.'),
|
1018
|
+
schema=int,
|
1019
|
+
examples=[
|
1020
|
+
mapping.MappingExample(
|
1021
|
+
input='What is the answer of 1 plus 1?', output=2
|
1022
|
+
),
|
1023
|
+
mapping.MappingExample(
|
1024
|
+
input='Compute the value of 3 + (2 * 6).', output=15
|
1025
|
+
),
|
1026
|
+
],
|
1027
|
+
)
|
1028
|
+
self.assertEqual(
|
1029
|
+
l.render().text,
|
1030
|
+
inspect.cleandoc("""
|
1031
|
+
Please respond to the last REQUEST with OUTPUT PYTHON OBJECT only according to OUTPUT PYTHON TYPE.
|
1032
|
+
|
1033
|
+
REQUEST:
|
1034
|
+
1 + 1 =
|
1035
|
+
|
1036
|
+
OUTPUT PYTHON TYPE:
|
1037
|
+
Answer
|
1038
|
+
|
1039
|
+
```python
|
1040
|
+
class Answer:
|
1041
|
+
final_answer: int
|
1042
|
+
```
|
1043
|
+
|
1044
|
+
OUTPUT PYTHON OBJECT:
|
1045
|
+
```python
|
1046
|
+
output = Answer(
|
1047
|
+
final_answer=2
|
1048
|
+
)
|
1049
|
+
```
|
1050
|
+
|
1051
|
+
REQUEST:
|
1052
|
+
What is the answer of 1 plus 1?
|
1053
|
+
|
1054
|
+
OUTPUT PYTHON TYPE:
|
1055
|
+
int
|
1056
|
+
|
1057
|
+
OUTPUT PYTHON OBJECT:
|
1058
|
+
```python
|
1059
|
+
output = 2
|
1060
|
+
```
|
1061
|
+
|
1062
|
+
REQUEST:
|
1063
|
+
Compute the value of 3 + (2 * 6).
|
1064
|
+
|
1065
|
+
OUTPUT PYTHON TYPE:
|
1066
|
+
int
|
1067
|
+
|
1068
|
+
OUTPUT PYTHON OBJECT:
|
1069
|
+
```python
|
1070
|
+
output = 15
|
1071
|
+
```
|
1072
|
+
|
1073
|
+
|
1074
|
+
REQUEST:
|
1075
|
+
Compute 12 / 6 + 2.
|
1076
|
+
|
1077
|
+
OUTPUT PYTHON TYPE:
|
1078
|
+
int
|
1079
|
+
|
1080
|
+
OUTPUT PYTHON OBJECT:
|
1081
|
+
"""),
|
1082
|
+
)
|
852
1083
|
|
853
|
-
|
1084
|
+
|
1085
|
+
class LfQueryJsonV1Test(unittest.TestCase):
|
854
1086
|
|
855
1087
|
def test_render_no_examples(self):
|
856
|
-
l = querying.
|
1088
|
+
l = querying.LfQuery.from_protocol('json:1.0')(
|
857
1089
|
input=lf.AIMessage('Compute 12 / 6 + 2.'), schema=int
|
858
1090
|
)
|
859
1091
|
self.assertEqual(
|
@@ -885,7 +1117,7 @@ class QueryStructureJsonTest(unittest.TestCase):
|
|
885
1117
|
)
|
886
1118
|
|
887
1119
|
def test_render(self):
|
888
|
-
l = querying.
|
1120
|
+
l = querying.LfQuery.from_protocol('json:1.0')(
|
889
1121
|
input=lf.AIMessage('Compute 12 / 6 + 2.'),
|
890
1122
|
schema=int,
|
891
1123
|
examples=[
|
@@ -1020,7 +1252,7 @@ class QueryStructureJsonTest(unittest.TestCase):
|
|
1020
1252
|
),
|
1021
1253
|
override_attrs=True,
|
1022
1254
|
):
|
1023
|
-
l = querying.
|
1255
|
+
l = querying.LfQuery.from_protocol('json:1.0')(
|
1024
1256
|
input=lm_input,
|
1025
1257
|
schema=[Itinerary],
|
1026
1258
|
examples=[
|
@@ -1063,10 +1295,17 @@ class QueryStructureJsonTest(unittest.TestCase):
|
|
1063
1295
|
self.assertEqual(len(cache), 0)
|
1064
1296
|
|
1065
1297
|
def test_query(self):
|
1066
|
-
lm = fake.
|
1298
|
+
lm = fake.StaticResponse('{"result": 1}')
|
1067
1299
|
self.assertEqual(
|
1068
1300
|
querying.query('what is 1 + 0', int, lm=lm, protocol='json'), 1
|
1069
1301
|
)
|
1302
|
+
self.assertEqual(
|
1303
|
+
querying.query('what is 1 + 0', int, lm=lm, protocol='json:1.0'), 1
|
1304
|
+
)
|
1305
|
+
with querying.query_protocol('json'):
|
1306
|
+
self.assertEqual(
|
1307
|
+
querying.query('what is 1 + 0', int, lm=lm), 1
|
1308
|
+
)
|
1070
1309
|
|
1071
1310
|
|
1072
1311
|
class QueryInvocationTest(unittest.TestCase):
|
@@ -1,4 +1,4 @@
|
|
1
|
-
langfun/__init__.py,sha256=
|
1
|
+
langfun/__init__.py,sha256=krEJ1lyDkNARsacY6nBQpD3bQrFi4fifD-FwpwPbFPM,2635
|
2
2
|
langfun/core/__init__.py,sha256=pW4prpiyWNkRbtWBGYF1thn7_0F_TgDVfAIZPvGn6HA,4758
|
3
3
|
langfun/core/component.py,sha256=g1kQM0bryYYYWVDrSMnHfc74wIBbpfe5_B3s-UIP5GE,3028
|
4
4
|
langfun/core/component_test.py,sha256=0CxTgjAud3aj8wBauFhG2FHDqrxCTl4OI4gzQTad-40,9254
|
@@ -27,7 +27,7 @@ langfun/core/template.py,sha256=jNhYSrbLIn9kZOa03w5QZbyjgfnzJzE_ZrrMvvWY4t4,2492
|
|
27
27
|
langfun/core/template_test.py,sha256=AQv_m9qE93WxhEhSlm1xaBgB4hu0UVtA53dljngkUW0,17090
|
28
28
|
langfun/core/agentic/__init__.py,sha256=qR3jlfUO4rhIoYdRDLz-d22YZf3FvU4FW88vsjiGDQQ,1224
|
29
29
|
langfun/core/agentic/action.py,sha256=9P7xDiZVUV9MvJDfuAfLx-xa7qvS5F0EOGWDQnjAZBw,38931
|
30
|
-
langfun/core/agentic/action_eval.py,sha256=
|
30
|
+
langfun/core/agentic/action_eval.py,sha256=NwjQ5hR-7YT6mo2q0mbDOgmNCKzTMpEzslYtR3fjXJY,4862
|
31
31
|
langfun/core/agentic/action_eval_test.py,sha256=tRUkWmOE9p0rpNOq19xAY2oDEnYsEEykjg6sUpAwJk0,2832
|
32
32
|
langfun/core/agentic/action_test.py,sha256=9EZKgLaBrqTErSRoxtrSlzmCz_cbnwWu0ZqpwKLst-s,10224
|
33
33
|
langfun/core/coding/__init__.py,sha256=5utju_fwEsImaiftx4oXKl9FAM8p281k8-Esdh_-m1w,835
|
@@ -52,7 +52,7 @@ langfun/core/data/conversion/openai.py,sha256=sSpkDSxMJWJ3I1dNICBCzvLsJv4iiLg8FP
|
|
52
52
|
langfun/core/data/conversion/openai_test.py,sha256=38WV_3ofFZiUF10bTKnZp4VyuDP5-81aR3h3Q0HlBm0,5283
|
53
53
|
langfun/core/eval/__init__.py,sha256=OEXr1ZRuvLuhJJfuQ1ZWQ-SvYzjyrtiAAEogYaB7E6o,1933
|
54
54
|
langfun/core/eval/base.py,sha256=qIJnrO1jX5pzY8yoQTtcTn5lGdD9adz5U6C_jla1BV4,75806
|
55
|
-
langfun/core/eval/base_test.py,sha256=
|
55
|
+
langfun/core/eval/base_test.py,sha256=q4wEd2KDUxzUkeELwof0HXBKe9TMQYUq84ddA043VPg,27191
|
56
56
|
langfun/core/eval/matching.py,sha256=AVKkGoc-BaHEzgSBamaAk3194TgqckDe_dinpS6LrXI,9323
|
57
57
|
langfun/core/eval/matching_test.py,sha256=2xtwsTi-UzLTt0QnXl3u_eAG3fFjCG2tsae7YkcQTB0,5312
|
58
58
|
langfun/core/eval/patching.py,sha256=R0s2eAd1m97exQt06dmUL0V_MBG0W2Hxg7fhNB7cXW0,3866
|
@@ -63,8 +63,8 @@ langfun/core/eval/v2/__init__.py,sha256=9lNKJwbvl0lcFblAXYT_OHI8fOubJsTOdSkxEqsP
|
|
63
63
|
langfun/core/eval/v2/checkpointing.py,sha256=t47rBfzGZYgIqWW1N1Ak9yQnNtHd-IRbEO0cZjG2VRo,11755
|
64
64
|
langfun/core/eval/v2/checkpointing_test.py,sha256=NggOSJ_6XSa4cNP6nGIu9wLsK59dUwe8SPWDiXtGGDE,9197
|
65
65
|
langfun/core/eval/v2/eval_test_helper.py,sha256=sKFi_wPYCNmr96WyTduuXY0KnxjFxcJyEhXey-_nGX8,3962
|
66
|
-
langfun/core/eval/v2/evaluation.py,sha256=
|
67
|
-
langfun/core/eval/v2/evaluation_test.py,sha256=
|
66
|
+
langfun/core/eval/v2/evaluation.py,sha256=4Kcpve_dlti3FWxd7KtZaapsva_C7sOGjyJ69xsXLY4,26992
|
67
|
+
langfun/core/eval/v2/evaluation_test.py,sha256=QNp_HEvRTupvNuLEeYTvylykh1Ut2jpMqHQ-gCUZQ10,6919
|
68
68
|
langfun/core/eval/v2/example.py,sha256=Jegt-viQSNYzPVkOZE_M19GON2TYGTct4Cp9HnJ7DGo,10861
|
69
69
|
langfun/core/eval/v2/example_test.py,sha256=1DNm6EuyZOq827DKvf3oTRVFkMNM_qTnLUpvOjpgz5I,3419
|
70
70
|
langfun/core/eval/v2/experiment.py,sha256=xlQvx-AgPCgHNaBoW1HxddA9wby-odADF0VJ3rQjw_M,32978
|
@@ -126,19 +126,19 @@ langfun/core/modalities/pdf.py,sha256=mfaeCbUA4JslFVTARiJh8hW7imvL4tLVw9gUhO5bAZ
|
|
126
126
|
langfun/core/modalities/pdf_test.py,sha256=ulZ0FbnlsU0wkrdckJ4ONZPTYRyMPO9Aob1UO6FXygk,1950
|
127
127
|
langfun/core/modalities/video.py,sha256=vI9apcHIHGyp90i34Srg7S3G6IBDtDCk8qiXhwRQmkw,967
|
128
128
|
langfun/core/modalities/video_test.py,sha256=7OXZoohKMYjt7vrJUdPb553HLyl1oBOKRgzBePFv68Q,2042
|
129
|
-
langfun/core/structured/__init__.py,sha256=
|
129
|
+
langfun/core/structured/__init__.py,sha256=xWO1RO-gy12REgiPn4oWWALZxJhHtBOOdDsawKN_SfY,3334
|
130
130
|
langfun/core/structured/completion.py,sha256=yW95Yd4wbt964I5wIyPUtIVeeqeZbA6HidLgN0ZpWm0,8110
|
131
131
|
langfun/core/structured/completion_test.py,sha256=VtYfI3ciVSSWbi8x3l1WwpWK-Ofn2DMHYEEqm2uTzhw,19314
|
132
132
|
langfun/core/structured/description.py,sha256=6BztYOiucPkF4CrTQtPLPJo1gN2dwnKmaJW83GBf4H0,5213
|
133
133
|
langfun/core/structured/description_test.py,sha256=UxaXnKKP7TnyPDPUyf3U-zPE0TvLlIP6DGr8thjcePw,7365
|
134
134
|
langfun/core/structured/function_generation.py,sha256=g7AOR_e8HxFU6n6Df750aGkgMgV1KExLZMAz0yd5Agg,8555
|
135
135
|
langfun/core/structured/function_generation_test.py,sha256=LaXYDXf9GlqUrR6v_gtmK_H4kxzonmU7SYbn7XXMgjU,12128
|
136
|
-
langfun/core/structured/mapping.py,sha256=
|
136
|
+
langfun/core/structured/mapping.py,sha256=gxdcYQP9yqbDRtiJQ1RRAOrKHiCr0h6xBYLCRKE4I3c,13723
|
137
137
|
langfun/core/structured/mapping_test.py,sha256=OntYvfDitAf0tAnzQty3YS90vyEn6FY1Mi93r_ViEk8,9594
|
138
138
|
langfun/core/structured/parsing.py,sha256=MGvI7ypXlwfzr5XB8_TFU9Ei0_5reYqkWkv64eAy0EA,12015
|
139
|
-
langfun/core/structured/parsing_test.py,sha256=
|
140
|
-
langfun/core/structured/querying.py,sha256=
|
141
|
-
langfun/core/structured/querying_test.py,sha256=
|
139
|
+
langfun/core/structured/parsing_test.py,sha256=V8Cj1tJK4Lxv_b0YQj6-2hzXZgnYNBa2JR7rOLRBKoQ,22346
|
140
|
+
langfun/core/structured/querying.py,sha256=NA5LL97ny9aIml3wz4GPzFsvAH2XafZIGoZbIhuV8nA,30456
|
141
|
+
langfun/core/structured/querying_test.py,sha256=_npZ3ztaZc6VerP7nU_QTJscWGgBqiwTE02z_S3Ahd4,40197
|
142
142
|
langfun/core/structured/schema.py,sha256=pGiAjez-ON2nKLUSeAls27gJsMto5aJnCXLVwH3pUKM,28296
|
143
143
|
langfun/core/structured/schema_generation.py,sha256=3AcuKvv3VOtKY5zMVqODrxfOuDxzoZtGeBxHlOWDOWw,5308
|
144
144
|
langfun/core/structured/schema_generation_test.py,sha256=RM9s71kMNg2jTePwInkiW9fK1ACN37eyPeF8OII-0zw,2950
|
@@ -156,8 +156,8 @@ langfun/core/templates/demonstration.py,sha256=vCrgYubdZM5Umqcgp8NUVGXgr4P_c-fik
|
|
156
156
|
langfun/core/templates/demonstration_test.py,sha256=SafcDQ0WgI7pw05EmPI2S4v1t3ABKzup8jReCljHeK4,2162
|
157
157
|
langfun/core/templates/selfplay.py,sha256=yhgrJbiYwq47TgzThmHrDQTF4nDrTI09CWGhuQPNv-s,2273
|
158
158
|
langfun/core/templates/selfplay_test.py,sha256=Ot__1P1M8oJfoTp-M9-PQ6HUXqZKyMwvZ5f7yQ3yfyM,2326
|
159
|
-
langfun-0.1.2.
|
160
|
-
langfun-0.1.2.
|
161
|
-
langfun-0.1.2.
|
162
|
-
langfun-0.1.2.
|
163
|
-
langfun-0.1.2.
|
159
|
+
langfun-0.1.2.dev202504300804.dist-info/licenses/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
|
160
|
+
langfun-0.1.2.dev202504300804.dist-info/METADATA,sha256=rlaBu8x--oQz7DAbnG3snNBBk7ltVc1RFvtOcE9cW3Q,8178
|
161
|
+
langfun-0.1.2.dev202504300804.dist-info/WHEEL,sha256=ooBFpIzZCPdw3uqIQsOo4qqbA4ZRPxHnOH7peeONza0,91
|
162
|
+
langfun-0.1.2.dev202504300804.dist-info/top_level.txt,sha256=RhlEkHxs1qtzmmtWSwYoLVJAc1YrbPtxQ52uh8Z9VvY,8
|
163
|
+
langfun-0.1.2.dev202504300804.dist-info/RECORD,,
|
{langfun-0.1.2.dev202504290805.dist-info → langfun-0.1.2.dev202504300804.dist-info}/licenses/LICENSE
RENAMED
File without changes
|
{langfun-0.1.2.dev202504290805.dist-info → langfun-0.1.2.dev202504300804.dist-info}/top_level.txt
RENAMED
File without changes
|