The latest 0.30.0
update is full of many improvements designed to streamline operations and enhance functionality across a broad spectrum of applications. In addition to introducing powerful new tools and extending the capabilities of our existing drivers, this release focuses heavily on refining the Griptape interface. We've implemented numerous refactors and breaking changes, including substantial configuration adjustments and renaming, in order to simplify and enhance user interactions with our platform. Here’s a detailed look at what’s new, how it works, and why it's beneficial for your projects.
Simplifying Configurations and Enhancing Flexibility
Our update simplifies the way configurations are managed across the platform. The introduction of griptape.configs.Defaults
allows developers to set default values for configurations in one centralized location, reducing redundancy and potential errors across multiple project setups. This change not only saves time but also ensures consistency across deployments, making it easier to manage and scale applications efficiently.
Previously you would configure a specific Structure with a provider configuration for that Structure. However, if you wanted to override all Structures with the same configuration, you would need to specify it multiple times. Now you can set the Default for all Structures and Drivers to pick up the global configuration.
from griptape.configs import Defaults
from griptape.configs.drivers import AnthropicDriversConfig
from griptape.structures import Agent, Workflow
Defaults.drivers_config = AnthropicDriversConfig()
agent = Agent()
workflow = Workflow()
Simplifying Event Configuration
The implementation of the global event bus
offers a streamlined approach to publishing and subscribing to events within applications. This centralized event management system simplifies communication between components, enhancing modularity and maintainability. Whether it’s a microservice architecture or a complex enterprise application, the global event bus ensures that all components can communicate effectively, reducing coupling and improving code clarity.
In the following example, you can configure the global EventBus
to count tokens used across all drivers in your application.
from griptape import utils
from griptape.events import BaseEvent, EventBus, EventListener, FinishPromptEvent
from griptape.structures import Agent
token_counter = utils.TokenCounter()
def count_tokens(e: BaseEvent) -> None:
if isinstance(e, FinishPromptEvent) and e.output_token_count is not None:
token_counter.add_tokens(e.output_token_count)
EventBus.add_event_listeners(
[
EventListener(
count_tokens,
event_types=[FinishPromptEvent],
)
]
)
agent = Agent()
agent.run("tell me about large language models")
print(f"total tokens: {token_counter.tokens}")
Refactored TaskMemory
A major enhancement in this release is also the restructuring of how TaskMemory
is managed, which involves decomposing the original TaskMemoryClient
into three distinct tools—each tailored to specific functionalities. This change aims to optimize task management within applications by providing more targeted, efficient tools:
PromptSummaryTool
: Designed to facilitate quick and efficient summarization of content, this tool helps in distilling extensive text into concise summaries, ideal for reporting or generating insights from large datasets.QueryTool
: This tool enhances the querying capabilities of applications, allowing for more precise and context-aware responses to user inquiries, improving the user experience and the application’s responsiveness.ExtractionTool
: Specialized in extracting structured data from unstructured inputs, this tool is crucial for applications that need to process and convert large volumes of text into actionable data.
These tools replace the previous one-size-fits-all TaskMemoryClient
, offering more specialized functionalities that cater to specific needs, thereby improving performance and usability. By segmenting the TaskMemory
functionalities, we enable developers to integrate and manage these tasks more effectively within their projects.
You can try out the following code examples to see how the different tools function with the same information.
PromptSummaryTool
from griptape.structures import Agent
from griptape.tools import PromptSummaryTool, WebScraperTool
agent = Agent(
tools=[
WebScraperTool(off_prompt=True),
PromptSummaryTool(off_prompt=False),
]
)
agent.run(
"According to this page https://en.wikipedia.org/wiki/Elden_Ring, how many copies of Elden Ring have been sold?"
)
In the output below you can see the Tool returns a summary of the information it found stored in TaskMemory
, from which the LLM then determines the final answer to the initial prompt.
[08/27/24 09:54:24] INFO Subtask b46ba554850740fab89aa15442fc3862
Response: "Elden Ring" is a 2022 action role-playing game developed by FromSoftware and directed by Hidetaka Miyazaki, with worldbuilding by George R. R. Martin. It was released
for PlayStation 4, PlayStation 5, Windows, Xbox One, and Xbox Series X/S. The game is set in an open world called the Lands Between, where players control a customizable
character on a quest to repair the Elden Ring and become the new Elden Lord. The gameplay includes exploration, combat, and magic, with a focus on environmental scale and player
freedom. Elden Ring received critical acclaim for its open world, gameplay, and setting, despite some technical issues. It sold 25 million copies, making it one of the
best-selling games of all time. The game won numerous Game of the Year awards and is considered one of the greatest games ever made. An expansion, "Shadow of the Erdtree," was
released in June 2024, also receiving acclaim and selling over five million copies.
INFO ToolkitTask c3d9bfc9928f4918bc770fc36ffa381a
Output: Elden Ring has sold 25 million copies.
QueryTool
from griptape.structures import Agent
from griptape.tools import QueryTool, WebScraperTool
agent = Agent(
tools=[
WebScraperTool(off_prompt=True),
QueryTool(off_prompt=False),
]
)
agent.run(
"According to this page https://en.wikipedia.org/wiki/Elden_Ring, how many copies of Elden Ring have been sold?"
)
Here we can see the output of the Tool is much more succinct than the summary as it specifically queried for a question vs. summarizing the entire contents.
[08/27/24 09:56:54] INFO Subtask 93cb6c16c0474f86a702f8d74ba186e3
Response: Elden Ring sold 13.4 million copies worldwide by the end of March 2022 and 25 million by June 2024. The downloadable content (DLC) Shadow of the Erdtree sold five
million copies within three days of its release.
[08/27/24 09:56:55] INFO ToolkitTask 8f9f6603dc1b427cb796af01b1e68339
Output: Elden Ring sold 13.4 million copies worldwide by the end of March 2022 and 25 million by June 2024.
ExtractionTool
Note: The ExtractionTool
requires an ExtractionEngine
to tell it which format you’d like to extract the information into. Griptape offers a few pre-baked extraction engines, but you can build a custom one as well.
from griptape.structures import Agent
from griptape.engines import JsonExtractionEngine
from griptape.tools import ExtractionTool, WebScraperTool
agent = Agent(
tools=[
WebScraperTool(off_prompt=True),
ExtractionTool(extraction_engine=JsonExtractionEngine(), off_prompt=False),
]
)
agent.run(
"According to this page https://en.wikipedia.org/wiki/Elden_Ring, how many copies of Elden Ring have been sold?"
)
These results differ from the previous two Tools as the ExtractionTool
will return the information it found in TaskMemory
in json format.
[08/27/24 09:49:14] INFO Subtask d03ed688f33346e895d495472c1982f1
Response: {"title": "Elden Ring", "developer": "FromSoftware", "publisher": "Bandai Namco Entertainment", "director": ["Hidetaka Miyazaki", "Yui Tanimura"], "producer": null,
"designer": ["Yosuke Kayugawa", "Ryu Matsumoto"], "programmer": ["Takeshi Suzuki", "Yuki Kido"], "artist": ["Hidenori Sato", "Ryo Fujimaki"], "writer": ["Hidetaka Miyazaki",
"George R. R. Martin"], "composer": ["Tsukasa Saitoh", "Shoi Miyazawa", "Tai Tomisawa", "Yuka Kitamura", "Yoshimi Kudo", "Soma Tanizaki"], "platforms": ["PlayStation 4",
"PlayStation 5", "Windows", "Xbox One", "Xbox Series X/S"], "release_date": "February 25, 2022", "genre": "Action role-playing", "modes": ["Single-player", "Multiplayer"],
"sales": {"initial_sales": "13.4 million copies by March 2022", "total_sales": "25 million copies by June 2024", "DLC_sales": "5 million copies within three days of release"},
"awards": [{"name": "Game of the Year", "organization": "The Game Awards", "year": 2022}, {"name": "Best Game", "organization": "British Academy Games Awards", "year": 2023},
{"name": "Game of the Year", "organization": "D.I.C.E. Awards", "year": 2023}, {"name": "Game of the Year", "organization": "Game Developers Choice Awards", "year": 2023},
{"name": "Ultimate Game of the Year", "organization": "Golden Joystick Awards", "year": 2022}, {"name": "Best Game Writing", "organization": "Nebula Awards", "year": 2022}],
"DLC": {"title": "Shadow of the Erdtree", "release_date": "June 20, 2024", "sales": "5 million copies within three days of release", "score": "95/100 on Metacritic"}}
[08/27/24 09:49:15] INFO ToolkitTask dd3e686aefe74f5394e434be32c2039f
Output: 25 million copies
Revolutionizing Data Management with AstraDbVectorStoreDriver
The new AstraDbVectorStoreDriver
marks a major advancement in our platform's ability to interact with DataStax Astra DB. This integration allows developers to leverage a scalable, cloud-native database solution for managing large datasets efficiently. Whether you're handling millions of data points for machine learning models or storing high volumes of transactional data, the AstraDbVectorStoreDriver
ensures your operations are smooth and scalable. This is especially useful for applications that require robust data retrieval capabilities and high availability.
Custom Schema Properties and Enhanced Query Functionality
With the introduction of the ability to set custom schema properties on Tool Activities
, developers can now tailor the functionality of tools to meet specific application requirements. This feature allows for the addition of extra schema properties that can dictate how tools validate, process, or handle data, providing a layer of customization that adapts to complex use cases.
In this example, we add a `sort` property to the `search` Activity which will be added as a Google custom search query parameter.
import os
import schema
from griptape.drivers import GoogleWebSearchDriver
from griptape.structures import Agent
from griptape.tools import WebSearchTool
agent = Agent(
tools=[
WebSearchTool(
web_search_driver=GoogleWebSearchDriver(
api_key=os.environ["GOOGLE_API_KEY"],
search_id=os.environ["GOOGLE_API_SEARCH_ID"],
),
extra_schema_properties={
"search": {
schema.Literal(
"sort",
description="Date range to search within. Format: date:r:YYYYMMDD:YYYYMMDD",
): str
}
},
)
],
)
agent.run("Search for articles about the history of the internet from 1990 to 2000")
Additionally, the TranslateQueryRagModule
enhances the RagEngine's ability to interact with a global user base by automatically translating input queries into multiple languages. This functionality is crucial for applications that serve diverse populations, ensuring that language barriers do not hinder user interaction.
The following example shows a simple RAG pipeline that translates incoming queries into English, retrieves data from a local vector store, and generates a response.
from griptape.artifacts import ErrorArtifact
from griptape.drivers import LocalVectorStoreDriver, OpenAiChatPromptDriver, OpenAiEmbeddingDriver
from griptape.engines.rag import RagContext, RagEngine
from griptape.engines.rag.modules import PromptResponseRagModule, TranslateQueryRagModule, VectorStoreRetrievalRagModule
from griptape.engines.rag.stages import QueryRagStage, ResponseRagStage, RetrievalRagStage
from griptape.loaders import WebLoader
from griptape.rules import Rule, Ruleset
prompt_driver = OpenAiChatPromptDriver(model="gpt-4o", temperature=0)
vector_store = LocalVectorStoreDriver(embedding_driver=OpenAiEmbeddingDriver())
artifacts = WebLoader(max_tokens=500).load("https://www.griptape.ai")
if isinstance(artifacts, ErrorArtifact):
raise Exception(artifacts.value)
vector_store.upsert_text_artifacts(
{
"griptape": artifacts,
}
)
rag_engine = RagEngine(
query_stage=QueryRagStage(query_modules=[TranslateQueryRagModule(prompt_driver=prompt_driver, language="english")]),
retrieval_stage=RetrievalRagStage(
max_chunks=5,
retrieval_modules=[
VectorStoreRetrievalRagModule(
name="MyAwesomeRetriever", vector_store_driver=vector_store, query_params={"top_n": 20}
)
],
),
response_stage=ResponseRagStage(
response_modules=[
PromptResponseRagModule(
prompt_driver=prompt_driver, rulesets=[Ruleset(name="persona", rules=[Rule("Talk like a pirate")])]
)
]
),
)
rag_context = RagContext(
query="¿Qué ofrecen los servicios en la nube de Griptape?",
module_configs={"MyAwesomeRetriever": {"query_params": {"namespace": "griptape"}}},
)
print(rag_engine.process(rag_context).outputs[0].to_text())
Advancements in Observability and Monitoring
Observability is key to maintaining the health and performance of applications. The update brings several new observability drivers, such as the DatadogObservabilityDriver
and OpenTelemetryObservabilityDriver
, which provide detailed insights into applications' workings. These tools are essential for real-time monitoring and can help pinpoint issues before they affect the user experience, ensuring your application remains reliable and performant under various conditions.
Conclusion
This release is designed to empower developers by providing more control, enhancing flexibility, and offering powerful tools for better data management, event handling, and observability. By integrating these new features, developers can build more robust, efficient, and scalable applications. Dive into these updates and explore how they can transform your projects, streamlining operations and boosting performance.