Skip to content

Commit 6fec67e

Browse files
authored
Revert "Implements Polymorphic Templates (#504)" (#507)
This reverts commit 0eaa6ef.
1 parent 0eaa6ef commit 6fec67e

7 files changed

Lines changed: 26 additions & 206 deletions

docs/source/agent.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,12 @@ def wrapper(self, *args, **kwargs):
4141

4242
def _format_model_input(self, template, other, *args, **kwargs):
4343
# update prompt with previous list of messages
44-
prompt, enc_ty = fwd()
44+
prompt = fwd()
4545
if Agent.current_agent() is self:
4646
assert self is other
4747
self.state.extend(prompt)
4848
prompt = self.state
49-
return (prompt, enc_ty)
49+
return prompt
5050

5151
def _compute_response(self, *args, **kwargs):
5252
# save response into persisted state

effectful/handlers/llm/completions.py

Lines changed: 22 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,7 @@
2121
from litellm.types.utils import ModelResponse
2222

2323
from effectful.handlers.llm import Template, Tool
24-
from effectful.handlers.llm.encoding import (
25-
Encodable,
26-
type_to_encodable_type,
27-
)
28-
from effectful.internals.unification import TypeExpression, nested_type
24+
from effectful.handlers.llm.encoding import type_to_encodable_type
2925
from effectful.ops.semantics import fwd, handler
3026
from effectful.ops.syntax import ObjectInterpretation, defop, implements
3127
from effectful.ops.types import Operation
@@ -217,18 +213,16 @@ def call_with_json_args(
217213

218214

219215
@defop
220-
def compute_response[**P, T](
221-
template: Template[P, T], model_input_pair: tuple[list[Any], Encodable[T]]
222-
) -> ModelResponse:
216+
def compute_response(template: Template, model_input: list[Any]) -> ModelResponse:
223217
"""Produce a complete model response for an input message sequence. This may
224218
involve multiple API requests if tools are invoked by the model.
225219
226220
"""
227-
model_input, ret_type_encoder = model_input_pair
221+
ret_type = template.__signature__.return_annotation
228222
tools = template.tools
229223

230224
tool_schemas = [function_definition(t) for t in tools.values()]
231-
response_encoding_type: type | None = ret_type_encoder.t
225+
response_encoding_type: type | None = type_to_encodable_type(ret_type).t
232226
if response_encoding_type == str:
233227
response_encoding_type = None
234228

@@ -268,12 +262,7 @@ def compute_response[**P, T](
268262
)
269263

270264

271-
type ModelInput[T] = tuple[list[Any], Encodable[T]]
272-
273-
274-
def decode_response[**P, T](
275-
template: Callable[P, T], model_input_pair: ModelInput[T], response: ModelResponse
276-
) -> T:
265+
def decode_response[**P, T](template: Callable[P, T], response: ModelResponse) -> T:
277266
"""Decode an LLM response into an instance of the template return type. This
278267
operation should raise if the output cannot be decoded.
279268
"""
@@ -284,7 +273,8 @@ def decode_response[**P, T](
284273
result_str = last_resp.content or last_resp.reasoning_content
285274
assert result_str
286275

287-
encodable_ty = model_input_pair[1]
276+
ret_type = template.__signature__.return_annotation
277+
encodable_ty = type_to_encodable_type(ret_type)
288278

289279
if encodable_ty.t == str:
290280
# if encoding as a type, value is just directly what the llm returned
@@ -301,29 +291,28 @@ def decode_response[**P, T](
301291
@defop
302292
def format_model_input[**P, T](
303293
template: Template[P, T], *args: P.args, **kwargs: P.kwargs
304-
) -> ModelInput[T]:
294+
) -> list[Any]:
305295
"""Format a template applied to arguments into a sequence of input
306296
messages.
307297
308298
"""
309-
signature = template.__signature__
310-
311-
bound_args = signature.bind(*args, **kwargs)
299+
bound_args = template.__signature__.bind(*args, **kwargs)
312300
bound_args.apply_defaults()
313301
# encode arguments
314302
arguments = {}
315-
for param, value in bound_args.arguments.items():
316-
ty: TypeExpression = nested_type(value).value
317-
encoder = type_to_encodable_type(ty) # type: ignore
318-
encoded = encoder.encode(value, template.__context__)
303+
for param in bound_args.arguments:
304+
encoder = type_to_encodable_type(
305+
template.__signature__.parameters[param].annotation
306+
)
307+
encoded = encoder.encode(bound_args.arguments[param], template.__context__)
319308
arguments[param] = encoder.serialize(encoded)
320309

321310
prompt = _OpenAIPromptFormatter().format_as_messages(
322311
template.__prompt_template__, **arguments
323312
)
324313

325314
# install prefix if the return type has a return annotation
326-
ret_type = template.__type_rule__(*args, **kwargs)
315+
ret_type = template.__signature__.return_annotation
327316
origin = typing.get_origin(ret_type)
328317
ret_type = ret_type if origin is None else origin
329318
ret_type_encoder = type_to_encodable_type(ret_type)
@@ -338,7 +327,7 @@ def format_model_input[**P, T](
338327
# Note: The OpenAI api only seems to accept images in the 'user' role. The
339328
# effect of different roles on the model's response is currently unclear.
340329
messages = [{"type": "message", "content": prompt, "role": "user"}]
341-
return (messages, ret_type_encoder)
330+
return messages
342331

343332

344333
class InstructionHandler(ObjectInterpretation):
@@ -358,16 +347,12 @@ def __init__(self, instruction: str):
358347
self.instruction = instruction
359348

360349
@implements(format_model_input)
361-
def _inject_instruction(
362-
self, template: Template, *args, **kwargs
363-
) -> tuple[list[Any], Any]:
350+
def _inject_instruction(self, template: Template, *args, **kwargs) -> list[Any]:
364351
"""Append instruction message to the formatted model input."""
365-
(messages, decode_ty) = fwd()
366-
return (
367-
messages
368-
+ [{"type": "message", "content": self.instruction, "role": "user"}],
369-
decode_ty,
370-
)
352+
messages = fwd()
353+
return messages + [
354+
{"type": "message", "content": self.instruction, "role": "user"}
355+
]
371356

372357

373358
class RetryLLMHandler(ObjectInterpretation):
@@ -436,4 +421,4 @@ def _call[**P, T](
436421
) -> T:
437422
model_input = format_model_input(template, *args, **kwargs)
438423
resp = compute_response(template, model_input)
439-
return decode_response(template, model_input, resp)
424+
return decode_response(template, resp)

tests/fixtures/tests_test_handlers_llm_provider.py__test_polymorphic_templates[model_input0].json

Lines changed: 0 additions & 44 deletions
This file was deleted.

tests/fixtures/tests_test_handlers_llm_provider.py__test_polymorphic_templates[model_input1].json

Lines changed: 0 additions & 44 deletions
This file was deleted.

tests/fixtures/tests_test_handlers_llm_provider.py__test_polymorphic_templates[model_input2].json

Lines changed: 0 additions & 44 deletions
This file was deleted.

tests/test_handlers_llm_provider.py

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import json
99
import logging
1010
import os
11-
from collections.abc import Callable, Sequence
11+
from collections.abc import Callable
1212
from enum import Enum
1313
from pathlib import Path
1414

@@ -346,39 +346,6 @@ def review_book(plot: str) -> BookReview:
346346
raise NotImplementedError
347347

348348

349-
@Template.define
350-
def generate_similar[T](examples: Sequence[T]) -> T:
351-
"Generate another instance of one of the items in {examples}"
352-
raise NotHandled
353-
354-
355-
@dataclass
356-
class Book:
357-
title: str
358-
author: str
359-
360-
361-
@requires_openai
362-
@pytest.mark.parametrize(
363-
"model_input",
364-
[
365-
[1, 2, 3, 4],
366-
["apple", "orange", "pear"],
367-
[
368-
Book("1984", "George Orwell"),
369-
Book("To Kill a Mockingbird", "Harper Lee"),
370-
Book("The Great Gatsby", "F. Scott Fitzgerald"),
371-
],
372-
],
373-
)
374-
def test_polymorphic_templates(request, model_input):
375-
with (
376-
handler(ReplayLiteLLMProvider(request, model_name="gpt-4o")),
377-
handler(LimitLLMCallsHandler(max_calls=5)),
378-
):
379-
assert isinstance(generate_similar(model_input), type(model_input[0]))
380-
381-
382349
class TestPydanticBaseModelReturn:
383350
@requires_openai
384351
def test_pydantic_basemodel_return(self, request):

tests/test_handlers_llm_template.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ class TemplateStringIntp(ObjectInterpretation):
155155
def _[**P, T](
156156
self, template: Template[P, T], *args: P.args, **kwargs: P.kwargs
157157
) -> T:
158-
model_input, _ = format_model_input(template, *args, **kwargs)
158+
model_input = format_model_input(template, *args, **kwargs)
159159
template_result = model_input[0]["content"]
160160
assert len(template_result) == 1
161161
return template_result[0]["text"]

0 commit comments

Comments
 (0)