From d20d7d28d9f0d5a9421c6146d8241d9e8ff4e6e5 Mon Sep 17 00:00:00 2001 From: Jeremiah Lowin <153965+jlowin@users.noreply.github.com> Date: Sat, 23 Mar 2024 19:22:49 -0400 Subject: [PATCH 1/3] Allow assistant instructions to be jinja and self-referential --- docs/docs/interactive/assistants.md | 3 +++ src/marvin/beta/assistants/assistants.py | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/docs/interactive/assistants.md b/docs/docs/interactive/assistants.md index c926f9ee4..c9ac9d3a9 100644 --- a/docs/docs/interactive/assistants.md +++ b/docs/docs/interactive/assistants.md @@ -171,6 +171,9 @@ Each assistant can be given `instructions` that describe its purpose, personalit !!! success "Result" ![](/assets/images/docs/assistants/instructions.png) +Instructions are rendered as a Jinja template, which means you can use variables and conditionals to customize the assistant's behavior. A special variable, `self_` is provided to the template, which represents the assistant object itself. This allows you to template the assistant's name, tools, or other attributes into the instructions. + + ### Tools Each assistant can be given a list of `tools` that it can use when responding to a message. Tools are a way to extend the assistant's capabilities beyond its default behavior, including giving it access to external systems like the internet, a database, your computer, or any API. diff --git a/src/marvin/beta/assistants/assistants.py b/src/marvin/beta/assistants/assistants.py index 85db5bd20..a52e618b5 100644 --- a/src/marvin/beta/assistants/assistants.py +++ b/src/marvin/beta/assistants/assistants.py @@ -13,6 +13,7 @@ expose_sync_method, run_sync, ) +from marvin.utilities.jinja import Environment as JinjaEnvironment from marvin.utilities.logging import get_logger from .threads import Thread @@ -85,7 +86,9 @@ def get_tools(self) -> list[AssistantTool]: ] def get_instructions(self, thread: Thread = None) -> str: - return self.instructions or "" + if self.instructions: + return JinjaEnvironment.render(self.instructions, self_=self) + return "" @expose_sync_method("say") async def say_async( From ae95a6debcee5b6d1efd3d279ca34d01b0d56d5b Mon Sep 17 00:00:00 2001 From: zzstoatzz Date: Sun, 24 Mar 2024 20:41:44 -0500 Subject: [PATCH 2/3] fix flaky test --- tests/ai/beta/vision/test_extract.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/ai/beta/vision/test_extract.py b/tests/ai/beta/vision/test_extract.py index d148a67da..33cd5cafe 100644 --- a/tests/ai/beta/vision/test_extract.py +++ b/tests/ai/beta/vision/test_extract.py @@ -7,8 +7,8 @@ class Location(BaseModel): - city: str - state: str = Field(description="The two letter abbreviation") + city: str = Field(description="Official city name, no boroughs or neighborhoods") + state: str = Field(description="The two letter abbreviation for the state") @pytest.mark.flaky(max_runs=2) @@ -18,10 +18,9 @@ def test_ny(self): "https://images.unsplash.com/photo-1568515387631-8b650bbcdb90" ) result = marvin.beta.extract(img, target=Location) - assert result in ( - [Location(city="New York", state="NY")], - [Location(city="New York City", state="NY")], - ) + + assert result.city.startswith("New York") + assert result.state == "NY" def test_ny_images_input(self): img = marvin.beta.Image( From d52c07b5d86dd9ee5225627e6ab9c513473fdee3 Mon Sep 17 00:00:00 2001 From: zzstoatzz Date: Sun, 24 Mar 2024 20:54:37 -0500 Subject: [PATCH 3/3] oops --- tests/ai/beta/vision/test_extract.py | 89 ++++++++++++++-------------- 1 file changed, 44 insertions(+), 45 deletions(-) diff --git a/tests/ai/beta/vision/test_extract.py b/tests/ai/beta/vision/test_extract.py index 33cd5cafe..b428af77c 100644 --- a/tests/ai/beta/vision/test_extract.py +++ b/tests/ai/beta/vision/test_extract.py @@ -7,7 +7,7 @@ class Location(BaseModel): - city: str = Field(description="Official city name, no boroughs or neighborhoods") + city: str state: str = Field(description="The two letter abbreviation for the state") @@ -17,44 +17,45 @@ def test_ny(self): img = marvin.beta.Image( "https://images.unsplash.com/photo-1568515387631-8b650bbcdb90" ) - result = marvin.beta.extract(img, target=Location) - - assert result.city.startswith("New York") - assert result.state == "NY" + locations = marvin.beta.extract(img, target=Location) + assert len(locations) == 1 + location = locations[0] + assert location.city.startswith("New York") or location.city == "Manhattan" + assert location.state == "NY" def test_ny_images_input(self): img = marvin.beta.Image( "https://images.unsplash.com/photo-1568515387631-8b650bbcdb90" ) - result = marvin.beta.extract(data=None, images=[img], target=Location) - assert result in ( - [Location(city="New York", state="NY")], - [Location(city="New York City", state="NY")], - ) + locations = marvin.beta.extract(data=None, images=[img], target=Location) + assert len(locations) == 1 + location = locations[0] + assert location.city.startswith("New York") or location.city == "Manhattan" + assert location.state == "NY" def test_ny_image_input(self): img = marvin.beta.Image( "https://images.unsplash.com/photo-1568515387631-8b650bbcdb90" ) - result = marvin.beta.extract(data=img, target=Location) - assert result in ( - [Location(city="New York", state="NY")], - [Location(city="New York City", state="NY")], - ) + locations = marvin.beta.extract(data=img, target=Location) + assert len(locations) == 1 + location = locations[0] + assert location.city.startswith("New York") or location.city == "Manhattan" + assert location.state == "NY" def test_ny_image_and_text(self): img = marvin.beta.Image( "https://images.unsplash.com/photo-1568515387631-8b650bbcdb90" ) - result = marvin.beta.extract( + locations = marvin.beta.extract( data="I see the empire state building", images=[img], target=Location, ) - assert result in ( - [Location(city="New York", state="NY")], - [Location(city="New York City", state="NY")], - ) + assert len(locations) == 1 + location = locations[0] + assert location.city.startswith("New York") or location.city == "Manhattan" + assert location.state == "NY" @pytest.mark.flaky(max_runs=3) def test_dog(self): @@ -89,11 +90,11 @@ async def test_ny(self): img = marvin.beta.Image( "https://images.unsplash.com/photo-1568515387631-8b650bbcdb90" ) - result = await marvin.beta.extract_async(img, target=Location) - assert result in ( - [Location(city="New York", state="NY")], - [Location(city="New York City", state="NY")], - ) + locations = await marvin.beta.extract_async(img, target=Location) + assert len(locations) == 1 + location = locations[0] + assert location.city.startswith("New York") or location.city == "Manhattan" + assert location.state == "NY" class TestMapping: @@ -104,16 +105,15 @@ def test_map(self): dc = marvin.beta.Image( "https://images.unsplash.com/photo-1617581629397-a72507c3de9e" ) - result = marvin.beta.extract.map([ny, dc], target=Location) - assert isinstance(result, list) - assert result[0][0] in ( - Location(city="New York", state="NY"), - Location(city="New York City", state="NY"), - ) - assert result[1][0] in ( - Location(city="Washington", state="DC"), - Location(city="Washington", state="D.C."), - ) + locations = marvin.beta.extract.map([ny, dc], target=Location) + assert len(locations) == 2 + ny_location, dc_location = locations + + assert ny_location[0].city.startswith("New York") + assert ny_location[0].state == "NY" + + assert dc_location[0].city == "Washington" + assert dc_location[0].state.index("D") < dc_location[0].state.index("C") async def test_async_map(self): ny = marvin.beta.Image( @@ -122,13 +122,12 @@ async def test_async_map(self): dc = marvin.beta.Image( "https://images.unsplash.com/photo-1617581629397-a72507c3de9e" ) - result = await marvin.beta.extract_async.map([ny, dc], target=Location) - assert isinstance(result, list) - assert result[0][0] in ( - Location(city="New York", state="NY"), - Location(city="New York City", state="NY"), - ) - assert result[1][0] in ( - Location(city="Washington", state="DC"), - Location(city="Washington", state="D.C."), - ) + locations = await marvin.beta.extract_async.map([ny, dc], target=Location) + assert len(locations) == 2 + ny_location, dc_location = locations + + assert ny_location[0].city.startswith("New York") + assert ny_location[0].state == "NY" + + assert dc_location[0].city == "Washington" + assert dc_location[0].state.index("D") < dc_location[0].state.index("C")