Announcing Griptape Framework 1.5

We’re pleased to announce that Griptape Framework 1.5 is now available. The 1.5 release brings enhancements to embeddings to add support for generating image embeddings and the addition of image search via the framework’s vector store drivers. We also have updates to the default models in several drivers, support for Perplexity with a new prompt driver and web search driver, and more. Let’s head down to the skatepark and explore some of the new features added in this release.

Updated Getting Started Guide & Improved Samples

First up, we have improved the Griptape Framework getting started guide on the Framework Overview documentation page. The new guide uses the uv python dependency manager, though of course we also provide instructions for pip users, and provides a tour of the key features in the framework. We  recommend that you check this out, even if you're already familiar with Griptape Framework, as it covers new features added over the last few releases. We have also updated all the code samples in the documentation to include a tab showing the output logs from running the sample, so you can see the results from each sample without having to run them yourself.

Support for Image Embeddings

Griptape Framework 1.5 includes support for generating embeddings from ImageArtifact objects, together with new embedding drivers for Amazon Bedrock with Amazon’s Titan Multimodal Embeddings G1 model, and for Voyage AI’s voyage-multimodal-3 model. 

In the example below, I generate embeddings for 4 images that I generated using FLUX.2 with the Black Forest Labs extension for Griptape. After generating and saving two snowboarding images and two skateboarding images, in the code sample I use Amazon’s amazon.titan-embed-image-v1 model to calculate embeddings for these images and a simple relatedness calculation to compare the vectors that the embedding model generated. 

from griptape.drivers.embedding.amazon_bedrock import AmazonBedrockTitanEmbeddingDriver
from griptape.loaders import ImageLoader
import numpy as np

def calc_relatedness(
   x, y
):  # using the same relatedness function as the localrerankdriver
   return np.dot(x, y) / (np.linalg.norm(x) * np.linalg.norm(y))

# create a driver for multi-modal embedding with Amazon Bedrock and Amazon Titan
multi_modal_embedding_driver = AmazonBedrockTitanEmbeddingDriver(
   model="amazon.titan-embed-image-v1"
)

# calculate embeddings for our four sample images
blue_snowboarder_embeddings = multi_modal_embedding_driver.embed(
   ImageLoader().load("images/blue_snowboarder.jpeg")
)
orange_snowboarder_embeddings = multi_modal_embedding_driver.embed(
   ImageLoader().load("images/orange_snowboarder.jpeg")
)
beach_skater_embeddings = multi_modal_embedding_driver.embed(
   ImageLoader().load("images/beach_skater.jpeg")
)
paris_skater_embeddings = multi_modal_embedding_driver.embed(
   ImageLoader().load("images/paris_skater.jpeg")
)

print(  # compare the two snowboarding images
   "blue_snowboarder vs orange_snowboarder: ",
   calc_relatedness(blue_snowboarder_embeddings, orange_snowboarder_embeddings),
)

print(  # compare a snowboarding image with a skateboarding image
   "blue_snowboarder vs beach_skater: ",
   calc_relatedness(blue_snowboarder_embeddings, beach_skater_embeddings),
)

print(  # compare the two skateboarding images
   "beach_skater vs paris_skater: ",
   calc_relatedness(beach_skater_embeddings, paris_skater_embeddings),
)

The results are that the two snowboarding images are very related with a score of greater than 0.9 (scores closer to 1 indicate higher levels of relatedness), while the comparison of the snowboarding and skateboarding images gives a score just over 0.55. Comparing the two skateboarding images generates a relatedness score of greater than 0.75, despite one being on Santa Monica beach and the other in the skatepark at the Paris Olympics.

Here are the images, together with the results for you to take a look at. I really like the results that I got with Black Forest Labs, and the results from the relatedness calculations.

Responsive Table
Blue Snowboarder Orange Snowboarder Relatedness score: 0.9366658250182979
Blue Snowboarder Beach Skater Relatedness score: 0.5564135045262181
Beach Skater Paris Skater Relatedness score: 0.7524210886871724

In addition to the changes to embedding drivers, vector store drivers have been updated to support upserting and querying with ImageArtifact objects, and the framework’s local vector store has been updated to support persisting multi-modal entries. These changes mean that you can store the embeddings generated for the images into a vector store and then you can query this to find the top x images nearest to the embeddings for a query image. These changes enable Griptape Framework to support image-based use cases such as image similarity search. 

Support for Perplexity

In this release we’ve added support for the popular AI-powered search and research engine, Perplexity, with the addition of PerplexityPromptDriver and PerplexityWebSearchDriver.

import os

from griptape.drivers.prompt.perplexity import PerplexityPromptDriver
from griptape.rules import Rule
from griptape.structures import Agent
from griptape.tasks import PromptTask

agent = Agent(
   tasks=[
       PromptTask(
           prompt_driver=PerplexityPromptDriver(
               model="sonar-pro", api_key=os.environ["PERPLEXITY_API_KEY"]
           ),
           rules=[
               Rule("Be precise and concise"),
           ],
       )
   ],
)

agent.run("tell me about the griptape framework 1.4 release")

print(agent.output.value)

If you experiment with the PerplexityPromptDriver using the code sample above, you will notice that the responses are generated using search as well as an LLM, meaning that you get up-to-date answers from the web. In this case, the model does a great job finding some of the highlights from the last release of the framework, using the blog post about that release as a source. This makes the PerplexityPromptDriver a little different to the other prompt drivers in Griptape Framework. We are excited to see what you build with this exciting new capability. 

Updates to Default Models

The default model in the AnthropicPromptDriver has been updated to claude-3-7-sonnet-latest.

If you're using Google models, the default model for the GooglePromptDriver has been updated to gemini-2.0-flash and the default model for the GoogleEmbeddingDriver has been updated to embedding-004.

For developers using Amazon Bedrock to access Anthropic’s model, the default model in the AmazonBedrockPromptDriver has been updated to anthropic.claude-3-7-sonnet-20250219-v1:0. In addition, the Amazon Titan model used for text embeddings has been updated to amazon.titan-embed-text-v2:0 and the default Amazon Titan model used in the AmazonBedrockImageGenerationDriver has been updated to amazon.titan-image-generator-v2:0.

As usual, you can continue to use previous generation models by setting the model keyword argument to the model that you wish to use when creating an instance of each driver.

Improved Control over Tool Use

If you’ve having trouble getting less powerful LLMs to function correctly when calling tools, the 1.5 release allows you to set reflect_on_tool_use to False and have the LLM return tool outputs directly. If you're using a less powerful LLM, you should consider using this setting so that you can make tool calls yourself rather than having the LLM coordinate them. In the very simple code sample below I run three tasks where I provide a DateTimeTool. The code is commented to provide details on the behavior that you should expect, and you can see the results from running this sample below the sample.

from griptape.tasks import PromptTask
from griptape.tools import DateTimeTool
from griptape.artifacts.list_artifact import ListArtifact

# When disabling `reflect_on_tool_use`, Task results will be returned as a ListArtifact.
# Each item in the ListArtifact will be the result of a single tool execution.

date_task = PromptTask(
    tools=[DateTimeTool()],
    reflect_on_tool_use=False,
)
results = date_task.run("How many days until it's 2026?")
# This will fail as the model will not reflect and figure out that an additional tool run is needed to calculate the date delta

if isinstance(results, ListArtifact):
    for result in results:
        print("Simple prompt output without reflection:", result)

date_task = PromptTask(
    tools=[DateTimeTool()],
    reflect_on_tool_use=False,
)
results = date_task.run("How many days from 12:44 on March 19th 2025 to Jan 1st 2026?")
# This will succeed as the prompt is more specific and the model can calculate the date delta using a single tool invocation
# Note that the output is the raw output from the tool

if isinstance(results, ListArtifact):
    for result in results:
        print("Detailed prompt output without reflection:", result)

date_task = PromptTask(
    tools=[DateTimeTool()],
    reflect_on_tool_use=True,
)
results = date_task.run("How many days until it's 2026?")
# This will succeed as the model will invoke the tool multiple times to get the current date & calculate the date delta
# Note that the output is more descriptive as the model has reflected on the final tool inovcation to generate the response

print("Simple prompt output with reflection:", results)
Simple prompt output without reflection: 2025-03-19 12:47:10.882934

Detailed prompt output without reflection: 287 days, 11:16:00

Simple prompt output with reflection: There are 287 days until it's 2026.

How to get started

Griptape Framework 1.5 is available now and you can download it with uv, poetry, pip or another Python package manager of your choice. As usual, we would love to hear your feedback on these changes, together with ideas and suggestions for future imrpovements to the framework. If you want to ask any questions about the other features in this release or discuss your image embedding use-cases, please head over to the Griptape Discord.