langfun 0.1.2.dev202505050805__py3-none-any.whl → 0.1.2.dev202505070805__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/core/agentic/action.py +84 -14
- langfun/core/agentic/action_test.py +4 -2
- langfun/core/llms/__init__.py +3 -0
- langfun/core/llms/gemini.py +24 -1
- langfun/core/llms/google_genai.py +4 -0
- langfun/core/llms/openai.py +29 -0
- langfun/core/llms/vertexai.py +4 -0
- langfun/core/memories/conversation_history.py +6 -6
- langfun/core/memories/conversation_history_test.py +31 -27
- langfun/core/memory.py +12 -21
- langfun/core/structured/schema.py +13 -3
- langfun/core/structured/schema_test.py +16 -0
- langfun/core/templates/conversation.py +1 -1
- {langfun-0.1.2.dev202505050805.dist-info → langfun-0.1.2.dev202505070805.dist-info}/METADATA +1 -1
- {langfun-0.1.2.dev202505050805.dist-info → langfun-0.1.2.dev202505070805.dist-info}/RECORD +18 -18
- {langfun-0.1.2.dev202505050805.dist-info → langfun-0.1.2.dev202505070805.dist-info}/WHEEL +0 -0
- {langfun-0.1.2.dev202505050805.dist-info → langfun-0.1.2.dev202505070805.dist-info}/licenses/LICENSE +0 -0
- {langfun-0.1.2.dev202505050805.dist-info → langfun-0.1.2.dev202505070805.dist-info}/top_level.txt +0 -0
langfun/core/agentic/action.py
CHANGED
@@ -194,6 +194,11 @@ class Action(pg.Object):
|
|
194
194
|
"""Returns the metadata associated with the result from previous call."""
|
195
195
|
return self._invocation.metadata if self._invocation else None
|
196
196
|
|
197
|
+
@property
|
198
|
+
def invocation(self) -> Optional['ActionInvocation']:
|
199
|
+
"""Returns last invocation. None if the action is not executed."""
|
200
|
+
return self._invocation
|
201
|
+
|
197
202
|
def __call__(
|
198
203
|
self,
|
199
204
|
session: Optional['Session'] = None,
|
@@ -825,6 +830,7 @@ class ActionInvocation(pg.Object, pg.views.html.HtmlTreeView.Extension):
|
|
825
830
|
def _on_bound(self):
|
826
831
|
super()._on_bound()
|
827
832
|
self._tab_control = None
|
833
|
+
self.action._invocation = self # pylint: disable=protected-access
|
828
834
|
|
829
835
|
def _on_parent_change(self, *args, **kwargs):
|
830
836
|
super()._on_parent_change(*args, **kwargs)
|
@@ -1154,7 +1160,6 @@ class Session(pg.Object, pg.views.html.HtmlTreeView.Extension):
|
|
1154
1160
|
)
|
1155
1161
|
|
1156
1162
|
invocation = ActionInvocation(pg.maybe_ref(action))
|
1157
|
-
action._invocation = invocation # pylint: disable=protected-access
|
1158
1163
|
parent_action = self._current_action
|
1159
1164
|
parent_execution = self._current_execution
|
1160
1165
|
parent_execution.append(invocation)
|
@@ -1412,38 +1417,103 @@ class Session(pg.Object, pg.views.html.HtmlTreeView.Extension):
|
|
1412
1417
|
level: lf.logging.LogLevel,
|
1413
1418
|
message: str,
|
1414
1419
|
keep: bool,
|
1420
|
+
*,
|
1421
|
+
for_action: Action | ActionInvocation | None = None,
|
1415
1422
|
**kwargs
|
1416
1423
|
) -> None:
|
1417
|
-
"""Logs a message to the session.
|
1418
|
-
|
1424
|
+
"""Logs a message to the session.
|
1425
|
+
|
1426
|
+
Args:
|
1427
|
+
level: The logging level.
|
1428
|
+
message: The message to log.
|
1429
|
+
keep: Whether to keep the log entry in the execution trace.
|
1430
|
+
for_action: The action to log the message for. If not provided, the
|
1431
|
+
current action will be used.
|
1432
|
+
**kwargs: Additional keyword arguments to pass to `lf.logging.log` as
|
1433
|
+
metadata to show.
|
1434
|
+
"""
|
1419
1435
|
execution = self._current_execution
|
1436
|
+
if for_action is None:
|
1437
|
+
for_action = self._current_action
|
1438
|
+
elif isinstance(for_action, Action):
|
1439
|
+
for_action = for_action.invocation
|
1440
|
+
assert for_action is not None
|
1441
|
+
|
1420
1442
|
log_entry = lf.logging.log(
|
1421
1443
|
level,
|
1422
|
-
|
1444
|
+
(
|
1445
|
+
f'[{for_action.id} ({for_action.action.__class__.__name__})]: '
|
1446
|
+
f'{message}'
|
1447
|
+
),
|
1423
1448
|
**kwargs
|
1424
1449
|
)
|
1425
1450
|
if keep:
|
1426
1451
|
execution.append(log_entry)
|
1427
1452
|
|
1428
|
-
def debug(
|
1453
|
+
def debug(
|
1454
|
+
self,
|
1455
|
+
message: str,
|
1456
|
+
keep: bool = True,
|
1457
|
+
*,
|
1458
|
+
for_action: Action | ActionInvocation | None = None,
|
1459
|
+
**kwargs
|
1460
|
+
) -> None:
|
1429
1461
|
"""Logs a debug message to the session."""
|
1430
|
-
self._log(
|
1462
|
+
self._log(
|
1463
|
+
'debug', message, keep=keep, for_action=for_action, **kwargs
|
1464
|
+
)
|
1431
1465
|
|
1432
|
-
def info(
|
1466
|
+
def info(
|
1467
|
+
self,
|
1468
|
+
message: str,
|
1469
|
+
keep: bool = True,
|
1470
|
+
*,
|
1471
|
+
for_action: Action | ActionInvocation | None = None,
|
1472
|
+
**kwargs
|
1473
|
+
) -> None:
|
1433
1474
|
"""Logs an info message to the session."""
|
1434
|
-
self._log(
|
1475
|
+
self._log(
|
1476
|
+
'info', message, keep=keep, for_action=for_action, **kwargs
|
1477
|
+
)
|
1435
1478
|
|
1436
|
-
def warning(
|
1479
|
+
def warning(
|
1480
|
+
self,
|
1481
|
+
message: str,
|
1482
|
+
keep: bool = True,
|
1483
|
+
*,
|
1484
|
+
for_action: Action | ActionInvocation | None = None,
|
1485
|
+
**kwargs
|
1486
|
+
) -> None:
|
1437
1487
|
"""Logs a warning message to the session."""
|
1438
|
-
self._log(
|
1488
|
+
self._log(
|
1489
|
+
'warning', message, keep=keep, for_action=for_action, **kwargs
|
1490
|
+
)
|
1439
1491
|
|
1440
|
-
def error(
|
1492
|
+
def error(
|
1493
|
+
self,
|
1494
|
+
message: str,
|
1495
|
+
keep: bool = True,
|
1496
|
+
*,
|
1497
|
+
for_action: Action | ActionInvocation | None = None,
|
1498
|
+
**kwargs
|
1499
|
+
):
|
1441
1500
|
"""Logs an error message to the session."""
|
1442
|
-
self._log(
|
1501
|
+
self._log(
|
1502
|
+
'error', message, keep=keep, for_action=for_action, **kwargs
|
1503
|
+
)
|
1443
1504
|
|
1444
|
-
def fatal(
|
1505
|
+
def fatal(
|
1506
|
+
self,
|
1507
|
+
message: str,
|
1508
|
+
keep: bool = True,
|
1509
|
+
*,
|
1510
|
+
for_action: Action | ActionInvocation | None = None,
|
1511
|
+
**kwargs
|
1512
|
+
):
|
1445
1513
|
"""Logs a fatal message to the session."""
|
1446
|
-
self._log(
|
1514
|
+
self._log(
|
1515
|
+
'fatal', message, keep=keep, for_action=for_action, **kwargs
|
1516
|
+
)
|
1447
1517
|
|
1448
1518
|
def as_message(self) -> lf.AIMessage:
|
1449
1519
|
"""Returns the session as a message."""
|
@@ -107,6 +107,7 @@ class SessionTest(unittest.TestCase):
|
|
107
107
|
lm = fake.StaticResponse('lm response')
|
108
108
|
foo = Foo(1)
|
109
109
|
self.assertIsNone(foo.session)
|
110
|
+
self.assertIsNone(foo.invocation)
|
110
111
|
self.assertIsNone(foo.result)
|
111
112
|
self.assertIsNone(foo.metadata)
|
112
113
|
|
@@ -167,6 +168,7 @@ class SessionTest(unittest.TestCase):
|
|
167
168
|
|
168
169
|
# Inspecting the top-level action (Foo)
|
169
170
|
foo_invocation = root.execution[0]
|
171
|
+
self.assertIs(foo.invocation, foo_invocation)
|
170
172
|
self.assertIs(foo_invocation.parent_action, root)
|
171
173
|
self.assertEqual(foo_invocation.id, 'agent@1:/a1')
|
172
174
|
self.assertEqual(foo_invocation.execution.id, 'agent@1:/a1')
|
@@ -414,8 +416,8 @@ class SessionTest(unittest.TestCase):
|
|
414
416
|
def test_log(self):
|
415
417
|
session = action_lib.Session()
|
416
418
|
session.debug('hi', x=1, y=2)
|
417
|
-
session.info('hi', x=1, y=2)
|
418
|
-
session.warning('hi', x=1, y=2)
|
419
|
+
session.info('hi', x=1, y=2, for_action=session.root)
|
420
|
+
session.warning('hi', x=1, y=2, for_action=session.root.action)
|
419
421
|
session.error('hi', x=1, y=2)
|
420
422
|
session.fatal('hi', x=1, y=2)
|
421
423
|
|
langfun/core/llms/__init__.py
CHANGED
@@ -40,6 +40,7 @@ from langfun.core.llms.azure_openai import AzureOpenAI
|
|
40
40
|
|
41
41
|
# Gemini models.
|
42
42
|
from langfun.core.llms.google_genai import GenAI
|
43
|
+
from langfun.core.llms.google_genai import Gemini25ProPreview_20250506
|
43
44
|
from langfun.core.llms.google_genai import Gemini25FlashPreview_20250417
|
44
45
|
from langfun.core.llms.google_genai import Gemini25ProPreview_20250325
|
45
46
|
from langfun.core.llms.google_genai import Gemini2Flash
|
@@ -77,6 +78,7 @@ from langfun.core.llms.vertexai import VertexAIGeminiExp_20241206
|
|
77
78
|
from langfun.core.llms.vertexai import VertexAIGemini25ProExp_20250325
|
78
79
|
from langfun.core.llms.vertexai import VertexAIGemini25ProPreview_20250325
|
79
80
|
from langfun.core.llms.vertexai import VertexAIGemini25FlashPreview_20250417
|
81
|
+
from langfun.core.llms.vertexai import VertexAIGemini25ProPreview_20250506
|
80
82
|
|
81
83
|
# For backward compatibility.
|
82
84
|
GeminiPro1_5 = Gemini15Pro
|
@@ -87,6 +89,7 @@ VertexAIGeminiFlash1_5 = VertexAIGemini15Flash
|
|
87
89
|
# OpenAI models.
|
88
90
|
from langfun.core.llms.openai import OpenAI
|
89
91
|
|
92
|
+
from langfun.core.llms.openai import Gpt41
|
90
93
|
from langfun.core.llms.openai import GptO3
|
91
94
|
from langfun.core.llms.openai import GptO4Mini
|
92
95
|
from langfun.core.llms.openai import Gpt45Preview_20250227
|
langfun/core/llms/gemini.py
CHANGED
@@ -151,6 +151,29 @@ SUPPORTED_MODELS = [
|
|
151
151
|
#
|
152
152
|
# Production models.
|
153
153
|
#
|
154
|
+
# Gemini 2.5 Pro Preview
|
155
|
+
GeminiModelInfo(
|
156
|
+
model_id='gemini-2.5-pro-preview-05-06',
|
157
|
+
in_service=True,
|
158
|
+
provider=pg.oneof(['Google GenAI', ' VertexAI']),
|
159
|
+
model_type='instruction-tuned',
|
160
|
+
description='Gemini 2.5 Pro.',
|
161
|
+
release_date=datetime.datetime(2025, 5, 6),
|
162
|
+
input_modalities=GeminiModelInfo.ALL_SUPPORTED_INPUT_TYPES,
|
163
|
+
context_length=lf.ModelInfo.ContextLength(
|
164
|
+
max_input_tokens=1_048_576,
|
165
|
+
max_output_tokens=65_536,
|
166
|
+
),
|
167
|
+
pricing=GeminiModelInfo.Pricing(
|
168
|
+
cost_per_1m_cached_input_tokens=1.25,
|
169
|
+
cost_per_1m_input_tokens=1.25,
|
170
|
+
cost_per_1m_output_tokens=10.0,
|
171
|
+
),
|
172
|
+
rate_limits=lf.ModelInfo.RateLimits(
|
173
|
+
max_requests_per_minute=2000,
|
174
|
+
max_tokens_per_minute=4_000_000,
|
175
|
+
)
|
176
|
+
),
|
154
177
|
# Gemini 2.5 Flash Preview
|
155
178
|
GeminiModelInfo(
|
156
179
|
model_id='gemini-2.5-flash-preview-04-17',
|
@@ -657,7 +680,7 @@ class Gemini(rest.REST):
|
|
657
680
|
def result(self, json: dict[str, Any]) -> lf.LMSamplingResult:
|
658
681
|
messages = [
|
659
682
|
lf.Message.from_value(candidate['content'], format='gemini')
|
660
|
-
for candidate in json
|
683
|
+
for candidate in json.get('candidates', [])
|
661
684
|
]
|
662
685
|
usage = json['usageMetadata']
|
663
686
|
input_tokens = usage['promptTokenCount']
|
@@ -106,6 +106,10 @@ class GeminiExp_20241206(GenAI):
|
|
106
106
|
#
|
107
107
|
# Production models.
|
108
108
|
#
|
109
|
+
class Gemini25ProPreview_20250506(GenAI):
|
110
|
+
"""Gemini 2.5 Pro model launched on 05/06/2025."""
|
111
|
+
|
112
|
+
model = 'gemini-2.5-pro-preview-05-06'
|
109
113
|
|
110
114
|
|
111
115
|
class Gemini25FlashPreview_20250417(GenAI):
|
langfun/core/llms/openai.py
CHANGED
@@ -49,6 +49,30 @@ class OpenAIModelInfo(lf.ModelInfo):
|
|
49
49
|
#
|
50
50
|
|
51
51
|
SUPPORTED_MODELS = [
|
52
|
+
# GPT-4.1 models
|
53
|
+
OpenAIModelInfo(
|
54
|
+
model_id='gpt-4.1',
|
55
|
+
alias_for='gpt-4.1-2025-04-14',
|
56
|
+
in_service=True,
|
57
|
+
model_type='instruction-tuned',
|
58
|
+
description='GPT 4.1 model (latest stable).',
|
59
|
+
url='https://platform.openai.com/docs/models/gpt-4.1',
|
60
|
+
input_modalities=OpenAIModelInfo.INPUT_IMAGE_TYPES,
|
61
|
+
context_length=lf.ModelInfo.ContextLength(
|
62
|
+
max_input_tokens=1_047_576,
|
63
|
+
max_output_tokens=32_768,
|
64
|
+
),
|
65
|
+
pricing=lf.ModelInfo.Pricing(
|
66
|
+
cost_per_1m_cached_input_tokens=0.50,
|
67
|
+
cost_per_1m_input_tokens=2.0,
|
68
|
+
cost_per_1m_output_tokens=8.0,
|
69
|
+
),
|
70
|
+
# Tier 5 rate limits.
|
71
|
+
rate_limits=lf.ModelInfo.RateLimits(
|
72
|
+
max_requests_per_minute=10_000,
|
73
|
+
max_tokens_per_minute=30_000_000,
|
74
|
+
),
|
75
|
+
),
|
52
76
|
# o3 models.
|
53
77
|
OpenAIModelInfo(
|
54
78
|
model_id='o3',
|
@@ -1045,6 +1069,11 @@ class OpenAI(openai_compatible.OpenAICompatible):
|
|
1045
1069
|
return super()._request_args(options)
|
1046
1070
|
|
1047
1071
|
|
1072
|
+
class Gpt41(OpenAI):
|
1073
|
+
"""GPT-4.1."""
|
1074
|
+
model = 'gpt-4.1'
|
1075
|
+
|
1076
|
+
|
1048
1077
|
class GptO4Mini(OpenAI):
|
1049
1078
|
"""GPT O4 mini."""
|
1050
1079
|
|
langfun/core/llms/vertexai.py
CHANGED
@@ -173,9 +173,13 @@ class VertexAIGemini(VertexAI, gemini.Gemini):
|
|
173
173
|
def model_info(self) -> gemini.GeminiModelInfo:
|
174
174
|
return super().model_info.clone(override=dict(provider='VertexAI'))
|
175
175
|
|
176
|
+
|
176
177
|
#
|
177
178
|
# Production models.
|
178
179
|
#
|
180
|
+
class VertexAIGemini25ProPreview_20250506(VertexAIGemini): # pylint: disable=invalid-name
|
181
|
+
"""Gemini 2.5 Pro model launched on 05/06/2025."""
|
182
|
+
model = 'gemini-2.5-pro-preview-05-06'
|
179
183
|
|
180
184
|
|
181
185
|
class VertexAIGemini25FlashPreview_20250417(VertexAIGemini): # pylint: disable=invalid-name
|
@@ -43,19 +43,19 @@ class ConversationHistory(lf.Memory):
|
|
43
43
|
messages.append(r[1])
|
44
44
|
return messages
|
45
45
|
|
46
|
-
def _recollect(self, **kwargs) ->
|
47
|
-
return
|
48
|
-
'\n'.join([f'{m.sender}: {m.text}' for m in self.messages]))
|
46
|
+
def _recollect(self, **kwargs) -> str:
|
47
|
+
return '\n'.join([f'{m.sender}: {m.text}' for m in self.messages])
|
49
48
|
|
50
49
|
def _remember(
|
51
50
|
self,
|
52
|
-
|
53
|
-
output_message: lf.Message | None = None,
|
51
|
+
value: tuple[str | lf.Message, str | lf.Message],
|
54
52
|
**kwargs
|
55
53
|
) -> None:
|
56
54
|
if self.max_turns and self.max_turns == len(self._turns):
|
57
55
|
self._turns.pop(0)
|
58
|
-
self._turns.append(
|
56
|
+
self._turns.append(
|
57
|
+
(lf.UserMessage.from_value(value[0]), lf.AIMessage.from_value(value[1]))
|
58
|
+
)
|
59
59
|
|
60
60
|
def _reset(self, **kwargs) -> None:
|
61
61
|
self._turns = []
|
@@ -13,58 +13,62 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
"""Base memory test."""
|
15
15
|
|
16
|
-
import inspect
|
17
16
|
import unittest
|
18
17
|
import langfun.core as lf
|
19
18
|
from langfun.core.memories.conversation_history import ConversationHistory
|
19
|
+
import pyglove as pg
|
20
20
|
|
21
21
|
|
22
22
|
class ConversationHistoryTest(unittest.TestCase):
|
23
23
|
|
24
24
|
def test_history_with_no_round_limit(self):
|
25
25
|
m = ConversationHistory()
|
26
|
-
m.remember('hi', 'hello')
|
26
|
+
m.remember(('hi', 'hello'))
|
27
27
|
m.remember(
|
28
|
-
'how are you',
|
29
|
-
'Fine, thank you. Anything I can help with?',
|
28
|
+
('how are you', 'Fine, thank you. Anything I can help with?'),
|
30
29
|
)
|
31
30
|
m.remember(
|
32
|
-
'Not for now, bye.',
|
33
|
-
'Okay, bye!',
|
31
|
+
('Not for now, bye.', 'Okay, bye!'),
|
34
32
|
)
|
35
33
|
self.assertEqual(len(m.turns), 3)
|
36
34
|
self.assertEqual(len(m.messages), 6)
|
37
|
-
self.
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
35
|
+
self.assertTrue(
|
36
|
+
pg.eq(
|
37
|
+
m.recollect(),
|
38
|
+
lf.Template(
|
39
|
+
"""
|
40
|
+
User: hi
|
41
|
+
AI: hello
|
42
|
+
User: how are you
|
43
|
+
AI: Fine, thank you. Anything I can help with?
|
44
|
+
User: Not for now, bye.
|
45
|
+
AI: Okay, bye!
|
46
|
+
"""
|
47
|
+
)
|
48
|
+
)
|
47
49
|
)
|
48
50
|
|
49
51
|
def test_history_with_round_limit(self):
|
50
52
|
m = ConversationHistory(max_turns=1)
|
51
|
-
m.remember('hi', 'hello')
|
53
|
+
m.remember(('hi', 'hello'))
|
52
54
|
m.remember(
|
53
|
-
'how are you',
|
54
|
-
'Fine, thank you. Anything I can help with?',
|
55
|
+
('how are you', 'Fine, thank you. Anything I can help with?'),
|
55
56
|
)
|
56
57
|
m.remember(
|
57
|
-
'Not for now, bye.',
|
58
|
-
'Okay, bye!',
|
58
|
+
('Not for now, bye.', 'Okay, bye!'),
|
59
59
|
)
|
60
60
|
self.assertEqual(len(m.turns), 1)
|
61
61
|
self.assertEqual(len(m.messages), 2)
|
62
|
-
self.
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
62
|
+
self.assertTrue(
|
63
|
+
pg.eq(
|
64
|
+
m.recollect(),
|
65
|
+
lf.Template(
|
66
|
+
"""
|
67
|
+
User: Not for now, bye.
|
68
|
+
AI: Okay, bye!
|
69
|
+
"""
|
70
|
+
)
|
71
|
+
)
|
68
72
|
)
|
69
73
|
|
70
74
|
|
langfun/core/memory.py
CHANGED
@@ -14,7 +14,9 @@
|
|
14
14
|
"""Interface for memories."""
|
15
15
|
|
16
16
|
import abc
|
17
|
-
from
|
17
|
+
from typing import Any
|
18
|
+
|
19
|
+
from langfun.core import template as template_lib
|
18
20
|
from langfun.core.component import Component
|
19
21
|
from langfun.core.natural_language import NaturalLanguageFormattable
|
20
22
|
|
@@ -30,40 +32,29 @@ class Memory(NaturalLanguageFormattable, Component):
|
|
30
32
|
"""
|
31
33
|
|
32
34
|
def natural_language_format(self) -> str:
|
33
|
-
return self.recollect().text
|
35
|
+
return self.recollect().render().text
|
34
36
|
|
35
|
-
def recollect(self, **kwargs) ->
|
37
|
+
def recollect(self, **kwargs) -> template_lib.Template:
|
36
38
|
"""Recollects a message from the memory."""
|
37
|
-
return self._recollect(**kwargs)
|
39
|
+
return template_lib.Template.from_value(self._recollect(**kwargs))
|
38
40
|
|
39
41
|
def remember(
|
40
42
|
self,
|
41
|
-
|
42
|
-
output_message: str | message_lib.Message,
|
43
|
+
value: Any,
|
43
44
|
**kwargs
|
44
|
-
) ->
|
45
|
-
|
46
|
-
input_message = message_lib.UserMessage(input_message)
|
47
|
-
if isinstance(output_message, str):
|
48
|
-
output_message = message_lib.AIMessage(output_message)
|
49
|
-
self._remember(input_message, output_message, **kwargs)
|
50
|
-
return output_message.text
|
45
|
+
) -> None:
|
46
|
+
self._remember(value, **kwargs)
|
51
47
|
|
52
48
|
def reset(self, **kwargs) -> None:
|
53
49
|
"""Resets the memory."""
|
54
|
-
self._reset()
|
50
|
+
self._reset(**kwargs)
|
55
51
|
|
56
52
|
@abc.abstractmethod
|
57
|
-
def _recollect(self, **kwargs) ->
|
53
|
+
def _recollect(self, **kwargs) -> str | template_lib.Template:
|
58
54
|
"""Recollects a message from the memory."""
|
59
55
|
|
60
56
|
@abc.abstractmethod
|
61
|
-
def _remember(
|
62
|
-
self,
|
63
|
-
input_message: message_lib.Message,
|
64
|
-
output_message: message_lib.Message,
|
65
|
-
**kwargs
|
66
|
-
) -> None:
|
57
|
+
def _remember(self, value: Any, **kwargs) -> None:
|
67
58
|
"""Remembers the input message and the output message."""
|
68
59
|
|
69
60
|
@abc.abstractmethod
|
@@ -185,10 +185,14 @@ class Schema(
|
|
185
185
|
def class_dependencies(
|
186
186
|
self,
|
187
187
|
include_base_classes: bool = True,
|
188
|
-
include_subclasses: bool = True
|
188
|
+
include_subclasses: bool = True,
|
189
|
+
include_generated_subclasses: bool = False) -> list[Type[Any]]:
|
189
190
|
"""Returns a list of class dependencies for current schema."""
|
190
191
|
return class_dependencies(
|
191
|
-
self.spec,
|
192
|
+
self.spec,
|
193
|
+
include_base_classes,
|
194
|
+
include_subclasses,
|
195
|
+
include_generated_subclasses
|
192
196
|
)
|
193
197
|
|
194
198
|
@classmethod
|
@@ -247,6 +251,7 @@ def class_dependencies(
|
|
247
251
|
],
|
248
252
|
include_base_classes: bool = True,
|
249
253
|
include_subclasses: bool = True,
|
254
|
+
include_generated_subclasses: bool = False,
|
250
255
|
) -> list[Type[Any]]:
|
251
256
|
"""Returns a list of class dependencies from a value or specs."""
|
252
257
|
if isinstance(value_or_spec, Schema):
|
@@ -301,7 +306,12 @@ def class_dependencies(
|
|
301
306
|
# Check subclasses if available.
|
302
307
|
if include_subclasses:
|
303
308
|
for cls in vs.cls.__subclasses__():
|
304
|
-
|
309
|
+
# NOTE(daiyip): To prevent LLM-generated "hallucinated" classes from
|
310
|
+
# polluting the generation space, classes dynamically created by
|
311
|
+
# 'eval' (which have __module__ == 'builtins') are excluded from
|
312
|
+
# dependencies by default.
|
313
|
+
if ((include_generated_subclasses or cls.__module__ != 'builtins')
|
314
|
+
and cls not in dependencies):
|
305
315
|
_fill_dependencies(pg.typing.Object(cls), include_subclasses=True)
|
306
316
|
|
307
317
|
if isinstance(vs, pg.typing.List):
|
@@ -144,6 +144,14 @@ class SchemaTest(unittest.TestCase):
|
|
144
144
|
foo2: Foo | X
|
145
145
|
|
146
146
|
schema = schema_lib.Schema([B])
|
147
|
+
v = schema_lib.structure_from_python(
|
148
|
+
"""
|
149
|
+
class C(B):
|
150
|
+
pass
|
151
|
+
""",
|
152
|
+
global_vars=dict(B=B)
|
153
|
+
)
|
154
|
+
self.assertEqual(v.__module__, 'builtins')
|
147
155
|
self.assertEqual(schema.class_dependencies(), [Foo, A, Bar, X, B])
|
148
156
|
|
149
157
|
def test_class_dependencies_non_pyglove(self):
|
@@ -162,6 +170,14 @@ class SchemaTest(unittest.TestCase):
|
|
162
170
|
class BB(AA):
|
163
171
|
foo2: Baz | XX
|
164
172
|
|
173
|
+
v = schema_lib.structure_from_python(
|
174
|
+
"""
|
175
|
+
class CC(BB):
|
176
|
+
pass
|
177
|
+
""",
|
178
|
+
global_vars=dict(BB=BB)
|
179
|
+
)
|
180
|
+
self.assertEqual(v.__module__, 'builtins')
|
165
181
|
schema = schema_lib.Schema([AA])
|
166
182
|
self.assertEqual(schema.class_dependencies(), [Baz, AA, XX, BB])
|
167
183
|
|
@@ -90,7 +90,7 @@ class Conversation(Completion):
|
|
90
90
|
self, input_message: lf.Message | str, lm_response: lf.Message | str
|
91
91
|
) -> None:
|
92
92
|
"""Adds a turn."""
|
93
|
-
self.memory.remember(input_message, lm_response)
|
93
|
+
self.memory.remember((input_message, lm_response))
|
94
94
|
|
95
95
|
def reset(self) -> None:
|
96
96
|
"""Resets current conversation."""
|
@@ -12,7 +12,7 @@ langfun/core/language_model.py,sha256=c6Vds9qXuC0BiHeZstxCTTsoU8ZL9K4w4co_hXA3-R
|
|
12
12
|
langfun/core/language_model_test.py,sha256=iA5uo7rIj2jAtCYzMzhyNg1fWqE2Onn60bOO58q72C0,36454
|
13
13
|
langfun/core/logging.py,sha256=ypjSwGzQpIhadewEKkIH5VWS55rfU4e6mlni41PMHlw,9116
|
14
14
|
langfun/core/logging_test.py,sha256=vbVGOQxwMmVSiFfbt2897gUt-8nqDpV64jCAeUG_q5U,6924
|
15
|
-
langfun/core/memory.py,sha256=
|
15
|
+
langfun/core/memory.py,sha256=vyXVvfvSdLLJAzdIupnbn3k26OgclCx-OJ7gddS5e1Y,2070
|
16
16
|
langfun/core/message.py,sha256=qUJZ9NfrlYG3aU_K2ud236gdTnvZ7Qw2T4pv4hI9ivg,32817
|
17
17
|
langfun/core/message_test.py,sha256=XE7SaYJUK8TCJBdih4XtnpnB6NhcU-vLxJoaP67WbSU,40793
|
18
18
|
langfun/core/modality.py,sha256=K8pUGuMpfWcOtVcXC_OqVjro1-RhHF6ddQni61DuYzM,4166
|
@@ -26,10 +26,10 @@ langfun/core/subscription_test.py,sha256=Y4ZdbZEwm83YNZBxHff0QR4QUa4rdaNXA3_jfIc
|
|
26
26
|
langfun/core/template.py,sha256=jNhYSrbLIn9kZOa03w5QZbyjgfnzJzE_ZrrMvvWY4t4,24929
|
27
27
|
langfun/core/template_test.py,sha256=AQv_m9qE93WxhEhSlm1xaBgB4hu0UVtA53dljngkUW0,17090
|
28
28
|
langfun/core/agentic/__init__.py,sha256=qR3jlfUO4rhIoYdRDLz-d22YZf3FvU4FW88vsjiGDQQ,1224
|
29
|
-
langfun/core/agentic/action.py,sha256=
|
29
|
+
langfun/core/agentic/action.py,sha256=jxjW4vkJs3p-AYb83P0AVnmE93Vx7z0QoFsm40NQ65k,46853
|
30
30
|
langfun/core/agentic/action_eval.py,sha256=JXhS5qEjWu9EZ0chDsjWxCqPAV26PUCBijtUYxiDeO4,4975
|
31
31
|
langfun/core/agentic/action_eval_test.py,sha256=7AkOwNbUX-ZgR1R0a7bvUZ5abNTUV7blf_8Mnrwb-II,2811
|
32
|
-
langfun/core/agentic/action_test.py,sha256=
|
32
|
+
langfun/core/agentic/action_test.py,sha256=wrx7_JUyL6EXhJeUqmPkPyIwOAh_KwTOWhSRgv2wYWo,15613
|
33
33
|
langfun/core/coding/__init__.py,sha256=5utju_fwEsImaiftx4oXKl9FAM8p281k8-Esdh_-m1w,835
|
34
34
|
langfun/core/coding/python/__init__.py,sha256=4ByknuoNU-mOIHwHKnTtmo6oD64oMFtlqPlYWmA5Wic,1736
|
35
35
|
langfun/core/coding/python/correction.py,sha256=7zBedlhQKMPA4cfchUMxAOFl6Zl5RqCyllRHGWys40s,7092
|
@@ -81,7 +81,7 @@ langfun/core/eval/v2/reporting.py,sha256=yUIPCAMnp7InIzpv1DDWrcLO-75iiOUTpscj7sm
|
|
81
81
|
langfun/core/eval/v2/reporting_test.py,sha256=hcPJJaMtPulqERvHYTpId83WXdqDKnnexmULtK7WKwk,5686
|
82
82
|
langfun/core/eval/v2/runners.py,sha256=8PGNlpqSGCW4O-z0E9SHcLklZNceAzwbS7letstljPE,16652
|
83
83
|
langfun/core/eval/v2/runners_test.py,sha256=A37fKK2MvAVTiShsg_laluJzJ9AuAQn52k7HPbfD0Ks,11666
|
84
|
-
langfun/core/llms/__init__.py,sha256=
|
84
|
+
langfun/core/llms/__init__.py,sha256=QWxRhzVn_vgJvdmW_xs5PcPuDbHsUxTU94YyV4Ofl34,8684
|
85
85
|
langfun/core/llms/anthropic.py,sha256=qaclpfX3qeHoZMDxU3Gn-638Vi4IyCbxdow3zgGUHK4,22195
|
86
86
|
langfun/core/llms/anthropic_test.py,sha256=dFnNvrgwCYUseDuiuWCBoQ5jloYX9RIlZQf7cCLPNU4,8282
|
87
87
|
langfun/core/llms/azure_openai.py,sha256=-KkSLaR54MlsIqz_XIwv0TnsBnvNTAxnjA2Q2O2u5KM,2733
|
@@ -92,29 +92,29 @@ langfun/core/llms/deepseek.py,sha256=jvTxdXPr-vH6HNakn_Ootx1heDg8Fen2FUkUW36bpCs
|
|
92
92
|
langfun/core/llms/deepseek_test.py,sha256=DvROWPlDuow5E1lfoSkhyGt_ELA19JoQoDsTnRgDtTg,1847
|
93
93
|
langfun/core/llms/fake.py,sha256=xmgCkk9y0I4x0IT32SZ9_OT27aLadXH8PRiYNo5VTd4,3265
|
94
94
|
langfun/core/llms/fake_test.py,sha256=2h13qkwEz_JR0mtUDPxdAhQo7MueXaFSwsD2DIRDW9g,7653
|
95
|
-
langfun/core/llms/gemini.py,sha256=
|
95
|
+
langfun/core/llms/gemini.py,sha256=UGI89WjBTZHBAmWbGh4FUCryw6OW3yuiN7htY-Xv_zM,25358
|
96
96
|
langfun/core/llms/gemini_test.py,sha256=Ve9X2Wvwu9wVFHpKZDP-qoM1_hzB4kgt6_HR9wxtNkg,7592
|
97
|
-
langfun/core/llms/google_genai.py,sha256=
|
97
|
+
langfun/core/llms/google_genai.py,sha256=YjvyasibmXYPFr_sxdrIdHDPHfaNzMCiJjWJs0iQyms,5188
|
98
98
|
langfun/core/llms/google_genai_test.py,sha256=NKNtpebArQ9ZR7Qsnhd2prFIpMjleojy6o6VMXkJ1zY,1502
|
99
99
|
langfun/core/llms/groq.py,sha256=S9V10kFo3cgX89qPgt_umq-SpRnxEDLTt_hJmpERfbo,12066
|
100
100
|
langfun/core/llms/groq_test.py,sha256=P4EgexCqsh4K2x11w0UL_vz-YYNaPdQU0WsDAdnTRQ8,2045
|
101
101
|
langfun/core/llms/llama_cpp.py,sha256=Z7P3gc4xeIjc2bX0Ey1y5EUYJVMnMa2Q67PZ9iye9sE,1409
|
102
102
|
langfun/core/llms/llama_cpp_test.py,sha256=wfTO7nmUwL65U2kK9P9fcMt92JjNDuVia4G1E7znf_4,1086
|
103
|
-
langfun/core/llms/openai.py,sha256=
|
103
|
+
langfun/core/llms/openai.py,sha256=LxENwsuGh-h1LXMu2Ub8Rjp1g1WNpm1NHBrwhkD-M4Q,42333
|
104
104
|
langfun/core/llms/openai_compatible.py,sha256=JlFUTiK4e3ox2DGeGBcAD-cXkxmBdx5g6LrYkyMIaps,5777
|
105
105
|
langfun/core/llms/openai_compatible_test.py,sha256=KwOMA7tsmOxFBjezltkBDSU77AvOQkI23dO2nHLAlB4,17689
|
106
106
|
langfun/core/llms/openai_test.py,sha256=gwuO6aoa296iM2welWV9ua4KF8gEVGsEPakgbtkWkFQ,2687
|
107
107
|
langfun/core/llms/rest.py,sha256=MCybcHApJcf49lubLnDzScN9Oc2IWY_JnMHIGdbDOuU,4474
|
108
108
|
langfun/core/llms/rest_test.py,sha256=_zM7nV8DEVyoXNiQOnuwJ917mWjki0614H88rNmDboE,5020
|
109
|
-
langfun/core/llms/vertexai.py,sha256=
|
109
|
+
langfun/core/llms/vertexai.py,sha256=nPWwv1C-wVpWpE4Vyl4vJoAEMB519-XNzPjyLY4N3tM,18816
|
110
110
|
langfun/core/llms/vertexai_test.py,sha256=0M4jsPOXGagdzPfEdJixmyLdhmmERePZWSFfTwnaYCQ,4875
|
111
111
|
langfun/core/llms/cache/__init__.py,sha256=QAo3InUMDM_YpteNnVCSejI4zOsnjSMWKJKzkb3VY64,993
|
112
112
|
langfun/core/llms/cache/base.py,sha256=rt3zwmyw0y9jsSGW-ZbV1vAfLxQ7_3AVk0l2EySlse4,3918
|
113
113
|
langfun/core/llms/cache/in_memory.py,sha256=i58oiQL28RDsq37dwqgVpC2mBETJjIEFS20yHiV5MKU,5185
|
114
114
|
langfun/core/llms/cache/in_memory_test.py,sha256=V2UPeu5co5vUwSkjekCH1B1iLm9qQKPaacvP6VW3GTg,10388
|
115
115
|
langfun/core/memories/__init__.py,sha256=HpghfZ-w1NQqzJXBx8Lz0daRhB2rcy2r9Xm491SBhC4,773
|
116
|
-
langfun/core/memories/conversation_history.py,sha256=
|
117
|
-
langfun/core/memories/conversation_history_test.py,sha256=
|
116
|
+
langfun/core/memories/conversation_history.py,sha256=KR78PurXTSeqsRK9QG9xM7-f245rs20EvWO7Mm2n2Vw,1827
|
117
|
+
langfun/core/memories/conversation_history_test.py,sha256=2kzAq2pUrbR01Z9jhxviIao52JK4JVjr5iGP8pwGxlU,2156
|
118
118
|
langfun/core/modalities/__init__.py,sha256=rh74vS_oL3XzD83ZJrDzwmW-8jnJHJ3s2_Prmp3ndYQ,1116
|
119
119
|
langfun/core/modalities/audio.py,sha256=qCrVCX690SG0ps-ZfOtNWvHn_CmdJsmxF7GySScWUqY,964
|
120
120
|
langfun/core/modalities/audio_test.py,sha256=yyGEBYqMXmNs_F2dEtj-PX8HE040vqh-YQppsvdxPw4,2025
|
@@ -139,10 +139,10 @@ langfun/core/structured/parsing.py,sha256=MGvI7ypXlwfzr5XB8_TFU9Ei0_5reYqkWkv64e
|
|
139
139
|
langfun/core/structured/parsing_test.py,sha256=V8Cj1tJK4Lxv_b0YQj6-2hzXZgnYNBa2JR7rOLRBKoQ,22346
|
140
140
|
langfun/core/structured/querying.py,sha256=lHSPQ4UKRfhLXRjofG1geIGpQ_ImZf0dIvjXIwr_jNk,30480
|
141
141
|
langfun/core/structured/querying_test.py,sha256=_npZ3ztaZc6VerP7nU_QTJscWGgBqiwTE02z_S3Ahd4,40197
|
142
|
-
langfun/core/structured/schema.py,sha256=
|
142
|
+
langfun/core/structured/schema.py,sha256=UTonddBx3hVr0Zhm_38jqd8khTSXWy-bkk8l1YOUdLA,28797
|
143
143
|
langfun/core/structured/schema_generation.py,sha256=3AcuKvv3VOtKY5zMVqODrxfOuDxzoZtGeBxHlOWDOWw,5308
|
144
144
|
langfun/core/structured/schema_generation_test.py,sha256=RM9s71kMNg2jTePwInkiW9fK1ACN37eyPeF8OII-0zw,2950
|
145
|
-
langfun/core/structured/schema_test.py,sha256=
|
145
|
+
langfun/core/structured/schema_test.py,sha256=pW0uoriwE_F6VH2DlAopeXlltcLBP_xnf8DA7QhVroc,26409
|
146
146
|
langfun/core/structured/scoring.py,sha256=Y7Jqs5VVjUQLF_9Z1uIY_dw5zasv2FF52Cz-cxGMsro,5857
|
147
147
|
langfun/core/structured/scoring_test.py,sha256=QvlwDAzwuamKL5tCotm1L3Sx0cs3idoNK4aIEhaO4Yk,2272
|
148
148
|
langfun/core/structured/tokenization.py,sha256=-b4_693quHeYn2AqndwucuXNmhd5NVXVTU3mmDane98,2189
|
@@ -150,14 +150,14 @@ langfun/core/structured/tokenization_test.py,sha256=dVW30kGYkX2HNtiRZe1oTmXFP7iI
|
|
150
150
|
langfun/core/templates/__init__.py,sha256=bO0eMsVJbi7sxEB2YlInKRQ2EVP-RyyKUwcD-8msuN4,927
|
151
151
|
langfun/core/templates/completion.py,sha256=mUqZHOEV3ag6-A08XghpeEltcrBvCDxXP004eDDfeag,1931
|
152
152
|
langfun/core/templates/completion_test.py,sha256=vGnjnM38UHyVDUyaUYtmp20s9KBGOdbPVsX-H-ET11E,1636
|
153
|
-
langfun/core/templates/conversation.py,sha256=
|
153
|
+
langfun/core/templates/conversation.py,sha256=iURikG7JEvXGsFSZfdzj6PyGQCAPAEejrs8hXEh7Sc0,2868
|
154
154
|
langfun/core/templates/conversation_test.py,sha256=HCD5f1sgmSGqL3OGe7hEctjRdcFjcmkz3NV1ArexNYI,3942
|
155
155
|
langfun/core/templates/demonstration.py,sha256=vCrgYubdZM5Umqcgp8NUVGXgr4P_c-fikKhwhzwhpKI,1460
|
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.dev202505070805.dist-info/licenses/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
|
160
|
+
langfun-0.1.2.dev202505070805.dist-info/METADATA,sha256=AaKPpm66YjxOfH--Ct9d_I3L_0h5ngugLiU2RwI1CRE,8178
|
161
|
+
langfun-0.1.2.dev202505070805.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
162
|
+
langfun-0.1.2.dev202505070805.dist-info/top_level.txt,sha256=RhlEkHxs1qtzmmtWSwYoLVJAc1YrbPtxQ52uh8Z9VvY,8
|
163
|
+
langfun-0.1.2.dev202505070805.dist-info/RECORD,,
|
File without changes
|
{langfun-0.1.2.dev202505050805.dist-info → langfun-0.1.2.dev202505070805.dist-info}/licenses/LICENSE
RENAMED
File without changes
|
{langfun-0.1.2.dev202505050805.dist-info → langfun-0.1.2.dev202505070805.dist-info}/top_level.txt
RENAMED
File without changes
|