griptape-ai / griptape-trade-school

Griptape Trade School mkdocs
4 stars 5 forks source link

Course demonstrating bringing systems together #17

Open nulldiver opened 1 year ago

nulldiver commented 1 year ago

Is your course suggestion related to a problem? Please describe.

I'm doing a little mapping from experiences with other tools (as a user this space and making professional developer tools in other spaces), but a really common challenge that I've seen happens in the following scenario:

You've done the tutorials, you've read the docs, you've reviewed the code -- you can build a prompt task agent, and tookit agent, a pipeline, custom tools. And the pieces make sense -- you're a competent user. But now you want to put these pieces together into something where there is some flow control and logic around them... make them all work together. At this point, specific needs tend to be very application-specific, so there usually aren't any tutorials. But that is unfortunate because now you need to start making your own design decisions at sort of a macro level and you have no guidance.

My observation is that there are usually ways to approach this application-specific integration layer that have good synergy with your tools and ways that will result in a constant fight and struggle against them. And that a lot of community/user pain comes from people going with the latter -- and that it keeps happening until there is enough critical mass in the user base that people start publishing a lot of tutorials and sharing best practices and teaching courses on your software at university.

Describe the course you'd like I think it could be something simple. Maybe start with the Kiwi Chat Agent and add a Toolkit Agent that can respond with data about something (maybe there is something thematically relevant that could be pulled from the web -- All Blacks team stats, New Zealand economic data, idk). But show how you could build a system where you chat with the chat agent in a free-form way, but supplement that chat with the data from the other agent. Almost any real-world case is going to much more complex and maybe if this were all you were going to do, you're sort of over-engineering for the result. But you would demonstrate how to have systems communicating under-the-hood while providing the end-user with a cohesive experience. Most importantly for learning, the project would act as a framework to discuss the sort of design-thinking that a Griptape user would have when approaching their own application — it acts as a means to communicate best-practice as they apply to that more abstract design.

brustkern commented 1 year ago

I think you're saying, "show me some composability!" Right? I'm on board with that.

nulldiver commented 1 year ago

@brustkern - exactly! I was trying to acknowledge why that so often gets skipped (it really quickly becomes application-specific) and why it is still so important for learning resources, especially early on before there is general consensus on "best practices".

shhlife commented 1 year ago

Totally cool! Note - it is possible in your specific example to give the kiwi agent access to the WebScraper tool so it could scrape the web when it wants to.. so in this case you don't even need to create another agent, you just give the one you're working with access to a tool.

But, I do love the idea of giving agents the ability to work with other agents (and pipelines and workflows) so it can determine when it needs to use the skills of another agent (or agents) to do specific things.

I am working on a new tutorial where I go through the process of creating a custom tool to use the API of a specific SaaS service, and then give that tool to the agent, and then we talk with the agent which can use the tool when it's appropriate... not quite the example you're talking about, but hopefully still useful!

nulldiver commented 1 year ago

I agree, in the specific example, it wouldn't be the most effective way to do it, and multiple agents definitely over-engineers the problem. It was just the simplest example I could come up with where you could have meaningful coordination across agents. I think the challenge is probably finding a scenario where that is possible but where there isn't an entire tutorial work of content just explaining the parts without even getting to composability.

The new tutorial sounds really cool -- I'm looking forward to checking it out. It was actually when I wrote my first custom tool for griptape and realized how straightforward it was that I first thought "ok, yeah, I can see how we can use this."

shhlife commented 9 months ago

Just to get back to this - I've done a fun experiment with Griptape Tools where I create a Griptape Tool that can:

  1. Take a dictionary of Agents
  2. Send an Agent from that list a prompt
  3. Get a response back from the Agent

Then I provided that tool to another Agent, and that Agent was able to use those other Agents when needed. It could even send messages between them.. acting as a mediator for their conversations.

Each of those Agents could have their own tools (Image Generation, access to Google Sheets, whatever) and those could be used only by them.

Here's the tool (follow the ShotGrid Client tutorial for instructions on how to create your own tool: https://learn.griptape.ai/latest/courses/shotgrid-client/)

tool_chatbot/tool.py

from schema import Schema, Literal
from attr import define, field
from griptape.artifacts import TextArtifact, ErrorArtifact
from griptape.utils.decorators import activity
from griptape.tools import BaseTool
from griptape.utils import Stream

from rich import print as print

@define
class GriptapeChatbot(BaseTool):
    """
    Parameters:
        chatbot: The Griptape structure to chat with
    """

    chatbots: dict = field(default=dict, kw_only=True)

    @activity(
        config={
            "description": "Chat with the agent.",
            "schema": Schema(
                {
                    Literal(
                        "chatbot", description="The name of the chatbot to talk to"
                    ): str,
                    Literal("prompt", description="Prompt to send to the chatbot."): str,
                }
            ),
        }
    )
    def send_message(self, params: dict) -> TextArtifact | ErrorArtifact:
        try:
            chatbot = params["values"]["chatbot"].capitalize()
            agent = self.chatbots[chatbot]["agent"]
            color = self.chatbots[chatbot]["color"]

            agent_response = ""

            print("")
            for artifact in Stream(agent).run(params["values"]["prompt"]):
                agent_response += artifact.value
                print(f"[{color}]{artifact.value}[/{color}]", end="", flush=True),

            print("\n")

            return TextArtifact(agent_response)

        except Exception as e:
            return ErrorArtifact(f"Error retrieving projects: {e}")

And then here's the way I create the "mediator" agent that has access to the other agents. You can see that only one of the agents has access to the WebScraper tool.

app.py

from griptape.structures import Agent
from griptape.utils import Chat
from tool_chatbot import GriptapeChatbot
from griptape.rules import Rule
from griptape.tools import WebScraper, TaskMemoryClient

from rich import print as print
from textwrap import dedent

load_dotenv()

#
# AGENTS
#

sally = Agent(
    stream=True,
    rules=[
        Rule("You identify as a hard core Python developer."),
        Rule("Your objective is to deliver a simple, efficient, Python code."),
    ],
)

billy = Agent(
    stream=True,
    rules=[
        Rule("You identify as an extremely talented researcher."),
        Rule("You have a very strong southern drawl."),
    ],
    tools=[
        WebScraper(off_prompt=False),
        TaskMemoryClient(off_prompt=False),
    ],
)

# Create a dict of agents
# Each agent is identified by their name, and contains the agent object (sally, billy)
# and their color - used in the chatbot to identify their response
#
chatbot_agents = {
    "Sally": {"agent": sally, "color": "orchid"},
    "Billy": {"agent": billy, "color": "light_steel_blue3"},
}

chatbot_names = list(chatbot_agents.keys())

# CHATBOT CLIENT TOOL
chatbot_client_tool = GriptapeChatbot(
    chatbots=chatbot_agents,
    off_prompt=False,
)

# AGENT
agent = Agent(
    stream=True,
    rules=[
        Rule("You are an excellent mediator."),
        Rule(
            f"You are in a conversation with the following chatbots: {chatbot_names} "
        ),
        Rule(
            "When the user wants to chat with people, you always use the Chatbot Client tool to speak with one of the chatbots you have access to."
        ),
    ],
    tools=[chatbot_client_tool],
    logger_level=0,
)

# START CHATTING
Chat(agent, prompt_prefix="\nInput: ", response_prefix="\nAssistant: ").start()