langfun 0.0.2.dev20240429__py3-none-any.whl → 0.1.2.dev202501150804__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.
- langfun/__init__.py +20 -2
- langfun/core/__init__.py +16 -5
- langfun/core/agentic/__init__.py +30 -0
- langfun/core/agentic/action.py +854 -0
- langfun/core/agentic/action_eval.py +150 -0
- langfun/core/agentic/action_eval_test.py +109 -0
- langfun/core/agentic/action_test.py +136 -0
- langfun/core/coding/python/__init__.py +5 -11
- langfun/core/coding/python/correction.py +37 -21
- langfun/core/coding/python/correction_test.py +29 -3
- langfun/core/coding/python/execution.py +40 -216
- langfun/core/coding/python/execution_test.py +29 -89
- langfun/core/coding/python/generation.py +21 -11
- langfun/core/coding/python/generation_test.py +2 -2
- langfun/core/coding/python/parsing.py +108 -193
- langfun/core/coding/python/parsing_test.py +2 -105
- langfun/core/component.py +63 -2
- langfun/core/component_test.py +53 -0
- langfun/core/concurrent.py +414 -117
- langfun/core/concurrent_test.py +111 -24
- langfun/core/console.py +17 -5
- langfun/core/console_test.py +17 -0
- langfun/core/eval/__init__.py +16 -1
- langfun/core/eval/base.py +622 -174
- langfun/core/eval/base_test.py +200 -54
- langfun/core/eval/matching.py +63 -76
- langfun/core/eval/matching_test.py +17 -8
- langfun/core/eval/patching.py +130 -0
- langfun/core/eval/patching_test.py +170 -0
- langfun/core/eval/scoring.py +26 -26
- langfun/core/eval/scoring_test.py +19 -2
- langfun/core/eval/v2/__init__.py +42 -0
- langfun/core/eval/v2/checkpointing.py +380 -0
- langfun/core/eval/v2/checkpointing_test.py +228 -0
- langfun/core/eval/v2/eval_test_helper.py +136 -0
- langfun/core/eval/v2/evaluation.py +725 -0
- langfun/core/eval/v2/evaluation_test.py +180 -0
- langfun/core/eval/v2/example.py +305 -0
- langfun/core/eval/v2/example_test.py +128 -0
- langfun/core/eval/v2/experiment.py +1048 -0
- langfun/core/eval/v2/experiment_test.py +433 -0
- langfun/core/eval/v2/metric_values.py +156 -0
- langfun/core/eval/v2/metric_values_test.py +80 -0
- langfun/core/eval/v2/metrics.py +357 -0
- langfun/core/eval/v2/metrics_test.py +203 -0
- langfun/core/eval/v2/progress.py +348 -0
- langfun/core/eval/v2/progress_test.py +82 -0
- langfun/core/eval/v2/progress_tracking.py +210 -0
- langfun/core/eval/v2/progress_tracking_test.py +66 -0
- langfun/core/eval/v2/reporting.py +270 -0
- langfun/core/eval/v2/reporting_test.py +158 -0
- langfun/core/eval/v2/runners.py +488 -0
- langfun/core/eval/v2/runners_test.py +334 -0
- langfun/core/langfunc.py +4 -17
- langfun/core/langfunc_test.py +22 -6
- langfun/core/language_model.py +577 -39
- langfun/core/language_model_test.py +470 -56
- langfun/core/llms/__init__.py +87 -16
- langfun/core/llms/anthropic.py +312 -87
- langfun/core/llms/anthropic_test.py +71 -3
- langfun/core/llms/cache/base.py +21 -2
- langfun/core/llms/cache/in_memory.py +13 -0
- langfun/core/llms/cache/in_memory_test.py +53 -2
- langfun/core/llms/compositional.py +101 -0
- langfun/core/llms/compositional_test.py +73 -0
- langfun/core/llms/deepseek.py +117 -0
- langfun/core/llms/deepseek_test.py +61 -0
- langfun/core/llms/fake.py +11 -7
- langfun/core/llms/fake_test.py +14 -0
- langfun/core/llms/gemini.py +507 -0
- langfun/core/llms/gemini_test.py +195 -0
- langfun/core/llms/google_genai.py +62 -218
- langfun/core/llms/google_genai_test.py +9 -202
- langfun/core/llms/groq.py +160 -144
- langfun/core/llms/groq_test.py +31 -137
- langfun/core/llms/llama_cpp.py +15 -42
- langfun/core/llms/llama_cpp_test.py +4 -30
- langfun/core/llms/openai.py +395 -203
- langfun/core/llms/openai_compatible.py +179 -0
- langfun/core/llms/openai_compatible_test.py +495 -0
- langfun/core/llms/openai_test.py +30 -395
- langfun/core/llms/rest.py +113 -0
- langfun/core/llms/rest_test.py +111 -0
- langfun/core/llms/vertexai.py +192 -0
- langfun/core/llms/vertexai_test.py +52 -0
- langfun/core/logging.py +284 -0
- langfun/core/logging_test.py +125 -0
- langfun/core/message.py +319 -9
- langfun/core/message_test.py +190 -13
- langfun/core/modalities/__init__.py +6 -2
- langfun/core/modalities/audio.py +30 -0
- langfun/core/modalities/audio_test.py +63 -0
- langfun/core/modalities/image.py +39 -20
- langfun/core/modalities/image_test.py +52 -9
- langfun/core/modalities/mime.py +206 -29
- langfun/core/modalities/mime_test.py +90 -9
- langfun/core/modalities/ms_office.py +117 -0
- langfun/core/modalities/ms_office_test.py +389 -0
- langfun/core/modalities/pdf.py +22 -0
- langfun/core/modalities/pdf_test.py +57 -0
- langfun/core/modalities/video.py +9 -26
- langfun/core/modalities/video_test.py +3 -3
- langfun/core/modality.py +26 -3
- langfun/core/modality_test.py +2 -2
- langfun/core/sampling.py +11 -11
- langfun/core/structured/__init__.py +12 -16
- langfun/core/structured/completion.py +32 -5
- langfun/core/structured/completion_test.py +7 -6
- langfun/core/structured/description.py +2 -2
- langfun/core/structured/description_test.py +3 -3
- langfun/core/structured/function_generation.py +60 -27
- langfun/core/structured/function_generation_test.py +72 -2
- langfun/core/structured/mapping.py +97 -47
- langfun/core/structured/mapping_test.py +90 -2
- langfun/core/structured/parsing.py +33 -21
- langfun/core/structured/parsing_test.py +53 -9
- langfun/core/structured/querying.py +746 -0
- langfun/core/structured/{prompting_test.py → querying_test.py} +469 -51
- langfun/core/structured/schema.py +204 -97
- langfun/core/structured/schema_generation.py +1 -1
- langfun/core/structured/schema_test.py +130 -29
- langfun/core/structured/scoring.py +125 -19
- langfun/core/structured/scoring_test.py +30 -0
- langfun/core/structured/tokenization.py +64 -0
- langfun/core/structured/tokenization_test.py +48 -0
- langfun/core/template.py +115 -1
- langfun/core/template_test.py +71 -1
- langfun/core/templates/conversation.py +9 -0
- langfun/core/templates/conversation_test.py +4 -3
- langfun/core/templates/selfplay_test.py +10 -2
- langfun-0.1.2.dev202501150804.dist-info/METADATA +225 -0
- langfun-0.1.2.dev202501150804.dist-info/RECORD +153 -0
- {langfun-0.0.2.dev20240429.dist-info → langfun-0.1.2.dev202501150804.dist-info}/WHEEL +1 -1
- langfun/core/coding/python/errors.py +0 -108
- langfun/core/coding/python/errors_test.py +0 -99
- langfun/core/coding/python/permissions.py +0 -90
- langfun/core/coding/python/permissions_test.py +0 -86
- langfun/core/structured/prompting.py +0 -238
- langfun/core/text_formatting.py +0 -162
- langfun/core/text_formatting_test.py +0 -47
- langfun-0.0.2.dev20240429.dist-info/METADATA +0 -100
- langfun-0.0.2.dev20240429.dist-info/RECORD +0 -108
- {langfun-0.0.2.dev20240429.dist-info → langfun-0.1.2.dev202501150804.dist-info}/LICENSE +0 -0
- {langfun-0.0.2.dev20240429.dist-info → langfun-0.1.2.dev202501150804.dist-info}/top_level.txt +0 -0
langfun/core/template.py
CHANGED
@@ -17,7 +17,7 @@ import contextlib
|
|
17
17
|
import dataclasses
|
18
18
|
import functools
|
19
19
|
import inspect
|
20
|
-
from typing import Annotated, Any, Callable, Iterator, Set, Tuple, Type
|
20
|
+
from typing import Annotated, Any, Callable, Iterator, Set, Tuple, Type, Union
|
21
21
|
|
22
22
|
import jinja2
|
23
23
|
from jinja2 import meta as jinja2_meta
|
@@ -47,6 +47,7 @@ class Template(
|
|
47
47
|
natural_language.NaturalLanguageFormattable,
|
48
48
|
component.Component,
|
49
49
|
pg.typing.CustomTyping,
|
50
|
+
pg.views.HtmlTreeView.Extension
|
50
51
|
):
|
51
52
|
"""Langfun string template.
|
52
53
|
|
@@ -231,6 +232,16 @@ class Template(
|
|
231
232
|
"""Returns the missing variable names."""
|
232
233
|
return self.vars(closure=True, specified=False)
|
233
234
|
|
235
|
+
@classmethod
|
236
|
+
def raw_str(cls, text: str) -> str:
|
237
|
+
"""Returns a template string that preserve the text as original."""
|
238
|
+
return '{% raw %}' + text + '{% endraw %}'
|
239
|
+
|
240
|
+
@classmethod
|
241
|
+
def from_raw_str(cls, text: str) -> 'Template':
|
242
|
+
"""Returns a template that preserve the text as original."""
|
243
|
+
return cls(cls.raw_str(text), clean=False)
|
244
|
+
|
234
245
|
def render(
|
235
246
|
self,
|
236
247
|
*,
|
@@ -495,6 +506,109 @@ class Template(
|
|
495
506
|
t.sym_setparent(self)
|
496
507
|
return t
|
497
508
|
|
509
|
+
@classmethod
|
510
|
+
def from_value(
|
511
|
+
cls,
|
512
|
+
value: Union[str, message_lib.Message, 'Template'],
|
513
|
+
**kwargs
|
514
|
+
) -> 'Template':
|
515
|
+
"""Create a template object from a string or template."""
|
516
|
+
if isinstance(value, cls):
|
517
|
+
return value.clone(override=kwargs) if kwargs else value # pylint: disable=no-value-for-parameter
|
518
|
+
if isinstance(value, str):
|
519
|
+
return cls(template_str=value, **kwargs)
|
520
|
+
if isinstance(value, message_lib.Message):
|
521
|
+
kwargs.update(value.metadata)
|
522
|
+
return cls(template_str=value.text, **kwargs)
|
523
|
+
if isinstance(value, Template):
|
524
|
+
lfun = cls(template_str=value.template_str, **kwargs)
|
525
|
+
# So lfun could acccess all attributes from value.
|
526
|
+
lfun.sym_setparent(value)
|
527
|
+
return lfun
|
528
|
+
return cls(template_str='{{input}}', input=value, **kwargs)
|
529
|
+
|
530
|
+
def _html_tree_view_content(
|
531
|
+
self,
|
532
|
+
*,
|
533
|
+
view: pg.views.HtmlTreeView,
|
534
|
+
root_path: pg.KeyPath | None = None,
|
535
|
+
collapse_level: int | None = None,
|
536
|
+
extra_flags: dict[str, Any] | None = None,
|
537
|
+
debug: bool = False,
|
538
|
+
**kwargs,
|
539
|
+
):
|
540
|
+
extra_flags = extra_flags if extra_flags is not None else {}
|
541
|
+
collapse_template_vars_level: int | None = extra_flags.get(
|
542
|
+
'collapse_template_vars_level', 1
|
543
|
+
)
|
544
|
+
|
545
|
+
def render_template_str():
|
546
|
+
return pg.Html.element(
|
547
|
+
'div',
|
548
|
+
[
|
549
|
+
pg.Html.element('span', [self.template_str])
|
550
|
+
],
|
551
|
+
css_classes=['template-str'],
|
552
|
+
)
|
553
|
+
|
554
|
+
def render_fields():
|
555
|
+
return view.complex_value(
|
556
|
+
{k: v for k, v in self.sym_items()},
|
557
|
+
name='fields',
|
558
|
+
root_path=root_path,
|
559
|
+
parent=self,
|
560
|
+
exclude_keys=['template_str', 'clean'],
|
561
|
+
collapse_level=max(
|
562
|
+
collapse_template_vars_level, collapse_level
|
563
|
+
) if collapse_level is not None else None,
|
564
|
+
extra_flags=extra_flags,
|
565
|
+
debug=debug,
|
566
|
+
**view.get_passthrough_kwargs(
|
567
|
+
remove=['exclude_keys'],
|
568
|
+
**kwargs,
|
569
|
+
)
|
570
|
+
)
|
571
|
+
|
572
|
+
return pg.views.html.controls.TabControl([
|
573
|
+
pg.views.html.controls.Tab(
|
574
|
+
'template_str',
|
575
|
+
render_template_str(),
|
576
|
+
),
|
577
|
+
pg.views.html.controls.Tab(
|
578
|
+
'variables',
|
579
|
+
render_fields(),
|
580
|
+
),
|
581
|
+
], selected=1)
|
582
|
+
|
583
|
+
@classmethod
|
584
|
+
def _html_tree_view_css_styles(cls) -> list[str]:
|
585
|
+
return super()._html_tree_view_css_styles() + [
|
586
|
+
"""
|
587
|
+
/* Langfun Template styles. */
|
588
|
+
.template-str {
|
589
|
+
padding: 10px;
|
590
|
+
margin: 10px 5px 10px 5px;
|
591
|
+
font-style: italic;
|
592
|
+
font-size: 1.1em;
|
593
|
+
white-space: pre-wrap;
|
594
|
+
border: 1px solid #EEE;
|
595
|
+
border-radius: 5px;
|
596
|
+
background-color: #EEE;
|
597
|
+
color: #cc2986;
|
598
|
+
}
|
599
|
+
"""
|
600
|
+
]
|
601
|
+
|
602
|
+
@classmethod
|
603
|
+
@functools.cache
|
604
|
+
def _html_tree_view_config(cls) -> dict[str, Any]:
|
605
|
+
return pg.views.HtmlTreeView.get_kwargs(
|
606
|
+
super()._html_tree_view_config(),
|
607
|
+
dict(
|
608
|
+
css_classes=['lf-template'],
|
609
|
+
)
|
610
|
+
)
|
611
|
+
|
498
612
|
|
499
613
|
# Register converter from str to LangFunc, therefore we can always
|
500
614
|
# pass strs to attributes that accept LangFunc.
|
langfun/core/template_test.py
CHANGED
@@ -13,6 +13,7 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
"""Template test."""
|
15
15
|
import inspect
|
16
|
+
from typing import Any
|
16
17
|
import unittest
|
17
18
|
|
18
19
|
from langfun.core import component
|
@@ -98,6 +99,21 @@ class BasicTest(unittest.TestCase):
|
|
98
99
|
self.assertEqual(d.z.render(), 'Bye, 1')
|
99
100
|
self.assertEqual(d.p.render(), 'Again Hello, 1')
|
100
101
|
|
102
|
+
def test_raw_text(self):
|
103
|
+
self.assertEqual(
|
104
|
+
Template(
|
105
|
+
'{{a}}' + Template.raw_str('\n{{d}}, {%x%}\n') + '{{b}}',
|
106
|
+
a='hi', b=1
|
107
|
+
).render().text,
|
108
|
+
'hi\n{{d}}, {%x%}\n1'
|
109
|
+
)
|
110
|
+
|
111
|
+
def test_from_raw_str(self):
|
112
|
+
self.assertEqual(
|
113
|
+
Template.from_raw_str('\n{{d}}, {%x%}\n').render().text,
|
114
|
+
'\n{{d}}, {%x%}\n'
|
115
|
+
)
|
116
|
+
|
101
117
|
|
102
118
|
class DefinitionTest(unittest.TestCase):
|
103
119
|
|
@@ -309,7 +325,7 @@ class RenderTest(unittest.TestCase):
|
|
309
325
|
Template(
|
310
326
|
'This is {{ x }} and {{ a }}', x=1, a=CustomModality('foo')
|
311
327
|
).render(),
|
312
|
-
'This is 1 and
|
328
|
+
'This is 1 and <<[[a]]>>',
|
313
329
|
)
|
314
330
|
|
315
331
|
def test_render_with_default(self):
|
@@ -537,5 +553,59 @@ class TemplateRenderEventTest(unittest.TestCase):
|
|
537
553
|
self.assertEqual(render_stacks, [[l]])
|
538
554
|
|
539
555
|
|
556
|
+
class HtmlTest(unittest.TestCase):
|
557
|
+
|
558
|
+
def test_html(self):
|
559
|
+
|
560
|
+
class Foo(Template):
|
561
|
+
"""Template Foo.
|
562
|
+
|
563
|
+
{{x}} + {{y}} = ?
|
564
|
+
"""
|
565
|
+
x: Any
|
566
|
+
y: Any
|
567
|
+
|
568
|
+
class Bar(Template):
|
569
|
+
"""Template Bar.
|
570
|
+
|
571
|
+
{{y}} + {{z}}
|
572
|
+
"""
|
573
|
+
y: Any
|
574
|
+
|
575
|
+
self.assertIn(
|
576
|
+
inspect.cleandoc(
|
577
|
+
"""
|
578
|
+
/* Langfun Template styles. */
|
579
|
+
.template-str {
|
580
|
+
padding: 10px;
|
581
|
+
margin: 10px 5px 10px 5px;
|
582
|
+
font-style: italic;
|
583
|
+
font-size: 1.1em;
|
584
|
+
white-space: pre-wrap;
|
585
|
+
border: 1px solid #EEE;
|
586
|
+
border-radius: 5px;
|
587
|
+
background-color: #EEE;
|
588
|
+
color: #cc2986;
|
589
|
+
}
|
590
|
+
"""
|
591
|
+
),
|
592
|
+
Foo(x=1, y=2).to_html().style_section,
|
593
|
+
)
|
594
|
+
self.assertIn(
|
595
|
+
'template-str',
|
596
|
+
Foo(x=Bar('{{y}} + {{z}}'), y=1).to_html(
|
597
|
+
enable_summary_tooltip=False,
|
598
|
+
).content,
|
599
|
+
)
|
600
|
+
self.assertIn(
|
601
|
+
'template-str',
|
602
|
+
Foo(x=Bar('{{y}} + {{z}}'), y=1).to_html(
|
603
|
+
enable_summary_tooltip=False,
|
604
|
+
collapse_level=0,
|
605
|
+
key_style='label',
|
606
|
+
).content,
|
607
|
+
)
|
608
|
+
|
609
|
+
|
540
610
|
if __name__ == '__main__':
|
541
611
|
unittest.main()
|
@@ -38,6 +38,11 @@ class Conversation(Completion):
|
|
38
38
|
'(Optional) Preamble before beginning the conversation.',
|
39
39
|
] = None
|
40
40
|
|
41
|
+
role: Annotated[
|
42
|
+
str | None,
|
43
|
+
'(Optional) User defined role for the AI response in the conversation.',
|
44
|
+
] = None
|
45
|
+
|
41
46
|
conversation_context: Annotated[
|
42
47
|
lf.LangFunc | None,
|
43
48
|
(
|
@@ -71,6 +76,10 @@ class Conversation(Completion):
|
|
71
76
|
with lf.context(**kwargs):
|
72
77
|
# Call LM based on the prompt generated from `input_message`.
|
73
78
|
lm_response = super().__call__()
|
79
|
+
if self.role is not None:
|
80
|
+
lm_response.rebind(
|
81
|
+
sender=self.role, skip_notification=True, raise_on_no_change=False
|
82
|
+
)
|
74
83
|
|
75
84
|
# Add current turn to memory.
|
76
85
|
self.add(self.input_message, lm_response)
|
@@ -83,6 +83,7 @@ class ConversationTest(unittest.TestCase):
|
|
83
83
|
def test_call(self):
|
84
84
|
c = Conversation(
|
85
85
|
lm=QuestionCounter(),
|
86
|
+
role='Agent',
|
86
87
|
preamble="You are a helpful and joyful AI bot. Now let's chat.",
|
87
88
|
)
|
88
89
|
# First round.
|
@@ -102,7 +103,7 @@ class ConversationTest(unittest.TestCase):
|
|
102
103
|
inspect.cleandoc("""
|
103
104
|
You are a helpful and joyful AI bot. Now let's chat.
|
104
105
|
User: Hello
|
105
|
-
|
106
|
+
Agent: Response 1.
|
106
107
|
User: How are you?
|
107
108
|
"""),
|
108
109
|
)
|
@@ -114,9 +115,9 @@ class ConversationTest(unittest.TestCase):
|
|
114
115
|
inspect.cleandoc("""
|
115
116
|
You are a helpful and joyful AI bot. Now let's chat.
|
116
117
|
User: Hello
|
117
|
-
|
118
|
+
Agent: Response 1.
|
118
119
|
User: How are you?
|
119
|
-
|
120
|
+
Agent: Response 2.
|
120
121
|
User: Okay, bye.
|
121
122
|
"""),
|
122
123
|
)
|
@@ -57,7 +57,11 @@ class SelfPlayTest(unittest.TestCase):
|
|
57
57
|
|
58
58
|
with lf.context(lm=NumberGuesser(guesses=[50, 20, 5, 10])):
|
59
59
|
self.assertEqual(
|
60
|
-
g(),
|
60
|
+
g(),
|
61
|
+
lf.AIMessage(
|
62
|
+
'10', score=0.0, logprobs=None, is_cached=False,
|
63
|
+
usage=lf.UsageNotAvailable()
|
64
|
+
)
|
61
65
|
)
|
62
66
|
|
63
67
|
self.assertEqual(g.num_turns, 4)
|
@@ -67,7 +71,11 @@ class SelfPlayTest(unittest.TestCase):
|
|
67
71
|
|
68
72
|
with lf.context(lm=NumberGuesser(guesses=[50, 20, 5, 2, 5, 4])):
|
69
73
|
self.assertEqual(
|
70
|
-
g(),
|
74
|
+
g(),
|
75
|
+
lf.AIMessage(
|
76
|
+
'2', score=0.0, logprobs=None, is_cached=False,
|
77
|
+
usage=lf.UsageNotAvailable()
|
78
|
+
)
|
71
79
|
)
|
72
80
|
|
73
81
|
self.assertEqual(g.num_turns, 10)
|
@@ -0,0 +1,225 @@
|
|
1
|
+
Metadata-Version: 2.2
|
2
|
+
Name: langfun
|
3
|
+
Version: 0.1.2.dev202501150804
|
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: pyglove>=0.4.5.dev202409110000
|
25
|
+
Requires-Dist: jinja2>=3.1.2
|
26
|
+
Requires-Dist: requests>=2.31.0
|
27
|
+
Provides-Extra: all
|
28
|
+
Requires-Dist: pyglove>=0.4.5.dev202409110000; 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-auth>=2.16.0; extra == "all"
|
34
|
+
Requires-Dist: python-magic>=0.4.27; extra == "all"
|
35
|
+
Requires-Dist: python-docx>=0.8.11; extra == "all"
|
36
|
+
Requires-Dist: pillow>=10.0.0; extra == "all"
|
37
|
+
Requires-Dist: openpyxl>=3.1.0; extra == "all"
|
38
|
+
Requires-Dist: pandas>=2.0.3; extra == "all"
|
39
|
+
Provides-Extra: ui
|
40
|
+
Requires-Dist: termcolor==1.1.0; extra == "ui"
|
41
|
+
Requires-Dist: tqdm>=4.64.1; extra == "ui"
|
42
|
+
Provides-Extra: vertexai
|
43
|
+
Requires-Dist: google-auth>=2.16.0; extra == "vertexai"
|
44
|
+
Provides-Extra: mime
|
45
|
+
Requires-Dist: python-magic>=0.4.27; extra == "mime"
|
46
|
+
Requires-Dist: python-docx>=0.8.11; extra == "mime"
|
47
|
+
Requires-Dist: pillow>=10.0.0; extra == "mime"
|
48
|
+
Requires-Dist: openpyxl>=3.1.0; extra == "mime"
|
49
|
+
Requires-Dist: pandas>=2.0.3; extra == "mime"
|
50
|
+
Provides-Extra: mime-auto
|
51
|
+
Requires-Dist: python-magic>=0.4.27; extra == "mime-auto"
|
52
|
+
Provides-Extra: mime-docx
|
53
|
+
Requires-Dist: python-docx>=0.8.11; extra == "mime-docx"
|
54
|
+
Provides-Extra: mime-pil
|
55
|
+
Requires-Dist: pillow>=10.0.0; extra == "mime-pil"
|
56
|
+
Provides-Extra: mime-xlsx
|
57
|
+
Requires-Dist: openpyxl>=3.1.0; extra == "mime-xlsx"
|
58
|
+
Requires-Dist: pandas>=2.0.3; extra == "mime-xlsx"
|
59
|
+
Dynamic: author
|
60
|
+
Dynamic: author-email
|
61
|
+
Dynamic: classifier
|
62
|
+
Dynamic: description
|
63
|
+
Dynamic: description-content-type
|
64
|
+
Dynamic: home-page
|
65
|
+
Dynamic: keywords
|
66
|
+
Dynamic: license
|
67
|
+
Dynamic: provides-extra
|
68
|
+
Dynamic: requires-dist
|
69
|
+
Dynamic: summary
|
70
|
+
|
71
|
+
<div align="center">
|
72
|
+
<img src="https://raw.githubusercontent.com/google/langfun/main/docs/_static/logo.svg" width="520px" alt="logo"></img>
|
73
|
+
</div>
|
74
|
+
|
75
|
+
# Langfun
|
76
|
+
|
77
|
+
[](https://badge.fury.io/py/langfun)
|
78
|
+
[](https://codecov.io/gh/google/langfun)
|
79
|
+

|
80
|
+
|
81
|
+
[**Installation**](#install) | [**Getting started**](#hello-langfun) | [**Tutorial**](https://colab.research.google.com/github/google/langfun/blob/main/docs/notebooks/langfun101.ipynb) | [**Discord community**](https://discord.gg/U6wPN9R68k)
|
82
|
+
|
83
|
+
## Introduction
|
84
|
+
|
85
|
+
Langfun is a [PyGlove](https://github.com/google/pyglove) powered library that
|
86
|
+
aims to *make language models (LM) fun to work with*. Its central principle is
|
87
|
+
to enable seamless integration between natural language and programming by
|
88
|
+
treating language as functions. Through the introduction of *Object-Oriented Prompting*,
|
89
|
+
Langfun empowers users to prompt LLMs using objects and types, offering enhanced
|
90
|
+
control and simplifying agent development.
|
91
|
+
|
92
|
+
To unlock the magic of Langfun, you can start with
|
93
|
+
[Langfun 101](https://colab.research.google.com/github/google/langfun/blob/main/docs/notebooks/langfun101.ipynb). Notably, Langfun is compatible with popular LLMs such as Gemini, GPT,
|
94
|
+
Claude, all without the need for additional fine-tuning.
|
95
|
+
|
96
|
+
## Why Langfun?
|
97
|
+
|
98
|
+
Langfun is *powerful and scalable*:
|
99
|
+
|
100
|
+
* Seamless integration between natural language and computer programs.
|
101
|
+
* Modular prompts, which allows a natural blend of texts and modalities;
|
102
|
+
* Efficient for both request-based workflows and batch jobs;
|
103
|
+
* A powerful eval framework that thrives dimension explosions.
|
104
|
+
|
105
|
+
Langfun is *simple and elegant*:
|
106
|
+
|
107
|
+
* An intuitive programming model, graspable in 5 minutes;
|
108
|
+
* Plug-and-play into any Python codebase, making an immediate difference;
|
109
|
+
* Comprehensive LLMs under a unified API: Gemini, GPT, Claude, Llama3, and more.
|
110
|
+
* Designed for agile developement: offering intellisense, easy debugging, with minimal overhead;
|
111
|
+
|
112
|
+
## Hello, Langfun
|
113
|
+
|
114
|
+
```python
|
115
|
+
import langfun as lf
|
116
|
+
import pyglove as pg
|
117
|
+
|
118
|
+
from IPython import display
|
119
|
+
|
120
|
+
class Item(pg.Object):
|
121
|
+
name: str
|
122
|
+
color: str
|
123
|
+
|
124
|
+
class ImageDescription(pg.Object):
|
125
|
+
items: list[Item]
|
126
|
+
|
127
|
+
image = lf.Image.from_uri('https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/Solar_system.jpg/1646px-Solar_system.jpg')
|
128
|
+
display.display(image)
|
129
|
+
|
130
|
+
desc = lf.query(
|
131
|
+
'Describe objects in {{my_image}} from top to bottom.',
|
132
|
+
ImageDescription,
|
133
|
+
lm=lf.llms.Gpt4o(api_key='<your-openai-api-key>'),
|
134
|
+
my_image=image,
|
135
|
+
)
|
136
|
+
print(desc)
|
137
|
+
```
|
138
|
+
*Output:*
|
139
|
+
|
140
|
+
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/Solar_system.jpg/1646px-Solar_system.jpg" width="520px" alt="my_image"></img>
|
141
|
+
|
142
|
+
```
|
143
|
+
ImageDescription(
|
144
|
+
items = [
|
145
|
+
0 : Item(
|
146
|
+
name = 'Mercury',
|
147
|
+
color = 'Gray'
|
148
|
+
),
|
149
|
+
1 : Item(
|
150
|
+
name = 'Venus',
|
151
|
+
color = 'Yellow'
|
152
|
+
),
|
153
|
+
2 : Item(
|
154
|
+
name = 'Earth',
|
155
|
+
color = 'Blue and white'
|
156
|
+
),
|
157
|
+
3 : Item(
|
158
|
+
name = 'Moon',
|
159
|
+
color = 'Gray'
|
160
|
+
),
|
161
|
+
4 : Item(
|
162
|
+
name = 'Mars',
|
163
|
+
color = 'Red'
|
164
|
+
),
|
165
|
+
5 : Item(
|
166
|
+
name = 'Jupiter',
|
167
|
+
color = 'Brown and white'
|
168
|
+
),
|
169
|
+
6 : Item(
|
170
|
+
name = 'Saturn',
|
171
|
+
color = 'Yellowish-brown with rings'
|
172
|
+
),
|
173
|
+
7 : Item(
|
174
|
+
name = 'Uranus',
|
175
|
+
color = 'Light blue'
|
176
|
+
),
|
177
|
+
8 : Item(
|
178
|
+
name = 'Neptune',
|
179
|
+
color = 'Dark blue'
|
180
|
+
)
|
181
|
+
]
|
182
|
+
)
|
183
|
+
```
|
184
|
+
See [Langfun 101](https://colab.research.google.com/github/google/langfun/blob/main/docs/notebooks/langfun101.ipynb) for more examples.
|
185
|
+
|
186
|
+
## Install
|
187
|
+
|
188
|
+
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:
|
189
|
+
|
190
|
+
```
|
191
|
+
pip install langfun
|
192
|
+
```
|
193
|
+
|
194
|
+
For a complete installation with all dependencies, use:
|
195
|
+
|
196
|
+
```
|
197
|
+
pip install langfun[all]
|
198
|
+
```
|
199
|
+
|
200
|
+
To install a nightly build, include the `--pre` flag, like this:
|
201
|
+
|
202
|
+
```
|
203
|
+
pip install langfun[all] --pre
|
204
|
+
```
|
205
|
+
|
206
|
+
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:
|
207
|
+
|
208
|
+
| Tag | Description |
|
209
|
+
| ------------------- | ---------------------------------------- |
|
210
|
+
| all | All Langfun features. |
|
211
|
+
| vertexai | VertexAI access. |
|
212
|
+
| mime | All MIME supports. |
|
213
|
+
| mime-auto | Automatic MIME type detection. |
|
214
|
+
| mime-docx | DocX format support. |
|
215
|
+
| mime-pil | Image support for PIL. |
|
216
|
+
| mime-xlsx | XlsX format support. |
|
217
|
+
| ui | UI enhancements |
|
218
|
+
|
219
|
+
|
220
|
+
For example, to install a nightly build that includes VertexAI access, full modality support, and UI enhancements, use:
|
221
|
+
```
|
222
|
+
pip install langfun[vertexai,mime,ui] --pre
|
223
|
+
```
|
224
|
+
|
225
|
+
*Disclaimer: this is not an officially supported Google product.*
|