Skip to main content

A framework to build Tools for AI Agents, a GUI-like solution to enhance Function Calling.

Project description

logo.png

Example.gif

What is Acte?

Acte is a framework to build GUI-like tools for AI Agents.

Why GUI-like?

The current tool solution, as known as Function Calling, is based on API calling, like weather API, Google API, etc. It has two main problems in complex scenarios:

  1. Multiple APIs increase the cognitive load for AI Agents, potentially leading to reasoning errors, especially when the APIs have a strict calling order.
  2. Directly calling APIs is a way with too much freedom degrees, lacking constraints, potentially resulting in data errors.

The way Agents interact with APIs reminds me of how human interacts with computers in old days. A guy faces a black and thick screen and types the keyboard, while looking up commands in a manual. Not just Agent, we also faces these two problems.

Then a technique that surprised Steve Jobs comes up: Graphical User Interface (GUI).

Since then, most of us no longer directly interact with command lines (a kind of API). We interact with API through GUI. GUI generally solved these two problems by constraining interaction to reduce cognitive load and degrees of freedom.

This is why Agents also need GUI-like tools. I prefer calling it Agentic User Interface (AUI).

Quick Start

Installation

pip install acte

Example1: Hello World

from acte import Component, v
from acte.chatbot import OpenaiChatbot
from acte.server import Server
from acte.session import SessionManager


class HelloWorld(Component):
    def view(self) -> None:
        v.text("Hello World")


server = Server(
    session_manager=SessionManager(HelloWorld, debug=True),
    chatbot=OpenaiChatbot(  # default model is gpt-4o
        api_key="YOUR OPENAI API KEY",
    )
)

if __name__ == '__main__':
    server.run()
  1. Copy the code to a Python file, and set OpenAI Api Key.

  2. Run the code, and visit the playground: http://127.0.0.1:8000. Example_00_00_hello_world.png

  3. Input "Hi, please new a session, and tell what you see." Then, the Agent will interact with Screen, and give you a response. Example_00_01_hello_world.png

Note: You can also interact with Screen to debug your app.


Example2: Counter

from acte import Component, v
from acte.chatbot import OpenaiChatbot
from acte.server import Server
from acte.session import SessionManager
from acte.state.signal import Signal


class Counter(Component):
    def __init__(self) -> None:
        self._n = Signal(0)

    def view(self) -> None:
        v.text("This is a counter.")

        with v.div():
            v.text(lambda: f"Current Value: {self._n.value}")
            # _n is Signal, so you need to use self._n.value in lambda

        v.button("add", on_press=self._add)

    async def _add(self) -> None:
        await self._n.set(self._n.value + 1)


server = Server(
    session_manager=SessionManager(Counter, debug=True),
    chatbot=OpenaiChatbot(
        api_key="YOUR OPENAI API KEY",
    )
)

if __name__ == '__main__':
    server.run()
  1. Agent can press the button in Screen. The number on the right-top of the button is Interactive ID. Agent interacts with Screen by pointing to ID. Example_01_00_counter.png

  2. Interaction's result will show in Screen. You can click "View"s in Dialog to check the Screen status in each step. Example_01_01_counter.png


Example3: Restaurant Assistant

from typing import Callable, Awaitable

from acte.chatbot import OpenaiChatbot
from acte.schema import IntSchema
from acte.server import Server
from acte.session import SessionManager

from acte import Component, v, Prop, as_prop
from acte.state.signal import Signal


class MenuItem(Component):
   def __init__(
           self,
           name: Prop[str],  # Prop = Ref[T] | T
           price: Prop[float],
           quantity: Prop[int],
           on_quantity_change: Callable[[str, float, int], Awaitable[None]]
   ) -> None:
      self._name = as_prop(name)  # as_prop is to convert T to Ref[T]
      self._price = as_prop(price)
      self._quantity = as_prop(quantity)

      self._on_quantity_change = on_quantity_change

   def view(self) -> None:
      with v.div():
         v.text(lambda: f"{self._name.value}: ${self._price.value}")
         v.input("quantity", self._quantity, self._on_set, schema=IntSchema())

   async def _on_set(self, value: str) -> None:
      await self._on_quantity_change(
         self._name.value,
         self._price.value,
         0 if value == '' else int(value)
      )


class Menu(Component):
   def __init__(self) -> None:
      self._menu = {
         "Pizza": {"price": 10.0, "quantity": Signal(0)},  # Signal is a kind of Ref, but can be set
         "Coke": {"price": 2.0, "quantity": Signal(0)},
      }

   def view(self) -> None:
      v.text("Super Restaurant Menu")

      for key, value in self._menu.items():
         v.component(
            MenuItem(
               name=key,
               price=value['price'],
               quantity=value['quantity'],
               on_quantity_change=self._on_quantity_change,
            )
         )

      v.text(self.total)

      v.button("checkout", on_press=self._checkout)

   def total(self) -> str:
      total = 0

      for key, value in self._menu.items():
         total += value['price'] * value['quantity'].value

      return f"Total: ${total}"

   async def _on_quantity_change(self, name: str, price: float, quantity: int) -> None:
      await self._menu[name]['quantity'].set(quantity)

   async def _checkout(self) -> None:
      total = self.total()

      for value in self._menu.values():
         await value['quantity'].set(0)

      print(f"Checkout: {total}")


server = Server(
   session_manager=SessionManager(Menu, debug=True),
   chatbot=OpenaiChatbot(
      system_message="You are restaurant assistant to help customers to order food through App. "
                     "You should confirm before Checkout",
      api_key="YOUR OPENAI API KEY",
   )
)

if __name__ == '__main__':
   server.run()
  1. Agent can fill input fields in Screen. Example_02_00_restaurant_assistant.png

  2. Input fields also have their own Interactive ID. Agent can take multiple actions in one calling. Example_02_01_restaurant_assistant.png

  3. You can define the backend logic after Agent press the button, such as make a request. Example_02_02_restaurant_assistant.png

Tool API

Acte Tool has 3 APIs: new_session, execute, and display, which can be accessed by HTTP request or SessionManager

1. New Session

Start a new App session, then display the session's latest screen.

HTTP request

POST /session

SessionManager

from acte.session import SessionManager

sm = SessionManager(...)

sm.new_session()

Return

{
    "session_id": str,
    "screen": str,
}

2. Execute

Execute one or more action(s), then display the session's latest screen.

HTTP Request

POST /execute

json:
{
    "session_id": "str",
    "actions": [
        {
            "target_id": "str",
            "action_type": "str",
            "value": "str | None",
        },
    ]
}

SessionManager

from acte.session import SessionManager

sm = SessionManager(...)

sm.execute(
    {
        "session_id": str,
        "actions": [
            {
                "target_id": str,  # interactive id
                "action_type": str,  # one of ["press", "fill"]
                "value": str | None,  # required when action_type is "fill"
            },
            ...
        ]
    }
)

Return

{
    "session_id": str,
    "screen": str,
}

3. Display

Display the session's latest screen.

HTTP Request

POST /display

json: 
{
    "session_id": "str",
}

SessionManager

from acte.session import SessionManager

sm = SessionManager(...)

sm.execute(
    {
        "session_id": str,
    }
)

Return

{
    "session_id": str,
    "screen": str,
}

Roadmap

  • Full Document

  • Test Code

Note: The project is in Alpha stage. The API may change frequently.

LICENSE

The project is licensed under the terms of the MIT license.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

acte-0.0.13.tar.gz (28.8 kB view details)

Uploaded Source

Built Distribution

acte-0.0.13-py3-none-any.whl (47.6 kB view details)

Uploaded Python 3

File details

Details for the file acte-0.0.13.tar.gz.

File metadata

  • Download URL: acte-0.0.13.tar.gz
  • Upload date:
  • Size: 28.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: pdm/2.19.3 CPython/3.11.9 Windows/10

File hashes

Hashes for acte-0.0.13.tar.gz
Algorithm Hash digest
SHA256 0614d85c6bccdf79127d83347e29900a4d1b854db050e9b3c2580de50c4e8d2d
MD5 89a4048641c6de2d86df74a52c62dddf
BLAKE2b-256 54dbdf3e4f78559c7a632e96fc5a0dab7bcb527e69688df4064c944b883bd100

See more details on using hashes here.

File details

Details for the file acte-0.0.13-py3-none-any.whl.

File metadata

  • Download URL: acte-0.0.13-py3-none-any.whl
  • Upload date:
  • Size: 47.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: pdm/2.19.3 CPython/3.11.9 Windows/10

File hashes

Hashes for acte-0.0.13-py3-none-any.whl
Algorithm Hash digest
SHA256 533eb7a57a29d1461396d179b8c2b9501538d759c01a09b8aa3453fa429be050
MD5 ee2d2f179c806afdb1dfa5da924dd191
BLAKE2b-256 cfefaa1349034bba3884af319dfd87d6b02277230c0cb9ebb9a61fb12c2aab43

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page