Skip to content

Commit e33ca43

Browse files
committed
add example using object handles
1 parent 68d7645 commit e33ca43

1 file changed

Lines changed: 87 additions & 0 deletions

File tree

docs/source/image_tool.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
from pprint import pprint
2+
3+
from PIL import Image
4+
5+
from effectful.handlers.llm import Agent, Template, Tool
6+
from effectful.handlers.llm.completions import (
7+
LiteLLMProvider,
8+
RetryLLMHandler,
9+
completion,
10+
)
11+
from effectful.ops.semantics import fwd, handler
12+
13+
14+
class ImageTools(Agent):
15+
"""You are an image processing agent."""
16+
17+
def __init__(self):
18+
self._image_to_handle = {}
19+
self._handle_to_image = {}
20+
21+
def _encode(self, image: Image) -> int:
22+
image_id = id(image)
23+
handle = self._image_to_handle.get(image_id, None)
24+
if handle is not None:
25+
return handle
26+
27+
handle = len(self._image_to_handle)
28+
self._image_to_handle[image_id] = handle
29+
30+
assert handle not in self._handle_to_image
31+
self._handle_to_image[handle] = image
32+
return handle
33+
34+
def _decode(self, image_handle: int) -> Image:
35+
return self._handle_to_image[image_handle]
36+
37+
@Tool.define
38+
def rotate(self, image: int, angle: float) -> int:
39+
"""Returns a rotated copy of this image. The copy is rotated by `angle`
40+
degrees counterclockwise around the image center.
41+
42+
"""
43+
return self._encode(self._decode(image).rotate(angle))
44+
45+
@Tool.define
46+
def concat_horiz(self, i1_h: int, i2_h: int) -> int:
47+
"""Concatenates two images horizontally. The larger image will be
48+
cropped to the height of the smaller image.
49+
50+
"""
51+
i1 = self._decode(i1_h)
52+
i2 = self._decode(i2_h)
53+
i3 = Image.new("RGB", (i1.width + i2.width, min(i1.height, i2.height)))
54+
i3.paste(i1, (0, 0))
55+
i3.paste(i2, (i1.width, 0))
56+
return self._encode(i3)
57+
58+
@Template.define
59+
def _rotate_and_concat(self, i: int) -> int:
60+
"""Create an image consisting of four copies of the image {i}
61+
concatenated horizontally. Each copy should be rotated 90 degrees from
62+
the previous.
63+
64+
"""
65+
pass # type: ignore
66+
67+
def rotate_and_concat(self, i: Image) -> Image:
68+
return self._decode(self._rotate_and_concat(self._encode(i)))
69+
70+
71+
def log_completion(*args, **kwargs):
72+
pprint((args, kwargs))
73+
return fwd()
74+
75+
76+
if __name__ == "__main__":
77+
image_agent = ImageTools()
78+
img = Image.open("_static/img/chirho_logo_wide.png")
79+
80+
image_agent._rotate_and_concat.tools
81+
provider = LiteLLMProvider(model="gpt-5-mini")
82+
with (
83+
handler(provider),
84+
handler({completion: log_completion}),
85+
handler(RetryLLMHandler()),
86+
):
87+
image_agent.rotate_and_concat(img).show()

0 commit comments

Comments
 (0)