Update Langgraph studio Example (#128)
This commit is contained in:
parent
275a3d63b9
commit
7f4280853c
2 changed files with 139 additions and 79 deletions
131
README.md
131
README.md
|
|
@ -2,7 +2,7 @@
|
|||
<a name="readme-top"></a>
|
||||
<img
|
||||
src="https://docs.arcade-ai.com/images/logo/arcade-ai-logo.png"
|
||||
height="200"
|
||||
style="width: 400px;"
|
||||
>
|
||||
</h3>
|
||||
<div align="center">
|
||||
|
|
@ -12,44 +12,41 @@
|
|||
<a href="https://pepy.tech/project/arcade-ai">
|
||||
<img src="https://static.pepy.tech/badge/arcade-ai" alt="Downloads">
|
||||
</a>
|
||||
<a href="https://github.com/ArcadeAI/arcade-ai/graphs/contributors">
|
||||
<img src="https://img.shields.io/github/contributors/arcadeai/arcade-ai.svg" alt="GitHub Contributors">
|
||||
<img src="https://img.shields.io/github/last-commit/ArcadeAI/arcade-ai" alt="GitHub last commit">
|
||||
</a>
|
||||
<a href="https://arcade-ai.com">
|
||||
<img src="https://img.shields.io/badge/Visit_Our_Website-orange" alt="Visit arcade-ai.com">
|
||||
<a href="https://img.shields.io/pypi/pyversions/arcade-ai">
|
||||
<img src="https://img.shields.io/pypi/pyversions/arcade-ai" alt="Python Version">
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<p align="center">
|
||||
<p align="center" style="display: flex; justify-content: center; gap: 10px;">
|
||||
<a href="https://x.com/TryArcade">
|
||||
<img src="https://img.shields.io/badge/Follow%20on%20X-000000?style=for-the-badge&logo=x&logoColor=white" alt="Follow on X" />
|
||||
<img src="https://img.shields.io/badge/Follow%20on%20X-000000?style=for-the-badge&logo=x&logoColor=white" alt="Follow on X" style="width: 125px;height: 25px; padding-top: .8px; border-radius: 5px;" />
|
||||
</a>
|
||||
<a href="https://www.linkedin.com/company/arcade-ai">
|
||||
<img src="https://img.shields.io/badge/Follow%20on%20LinkedIn-0077B5?style=for-the-badge&logo=linkedin&logoColor=white" alt="Follow on LinkedIn" />
|
||||
<a href="https://www.linkedin.com/company/arcade-ai" >
|
||||
<img src="https://img.shields.io/badge/Follow%20on%20LinkedIn-0077B5?style=for-the-badge&logo=linkedin&logoColor=white" alt="Follow on LinkedIn" style="width: 150px; padding-top: 1.5px;height: 22px; border-radius: 5px;" />
|
||||
</a>
|
||||
<a href="https://discord.com/invite/GUZEMpEZ9p">
|
||||
<img src="https://img.shields.io/badge/Join%20our%20Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white" alt="Join our Discord" />
|
||||
<img src="https://img.shields.io/badge/Join%20our%20Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white" alt="Join our Discord" style="width: 150px; padding-top: 1.5px; height: 22px; border-radius: 5px;" />
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p align="center">
|
||||
<p align="center" style="display: flex; justify-content: center; gap: 5px; font-size: 15px;">
|
||||
<a href="https://docs.arcade-ai.com" target="_blank">Docs</a> •
|
||||
<a href="https://docs.arcade-ai.com/integrations" target="_blank">Integrations</a> •
|
||||
<a href="https://github.com/ArcadeAI/cookbook" target="_blank">Cookbook</a> •
|
||||
<a href="https://github.com/ArcadeAI/arcade-py" target="_blank">Python Client</a> •
|
||||
<a href="https://github.com/ArcadeAI/arcade-js" target="_blank">JavaScript Client</a>
|
||||
</p>
|
||||
<a href="https://docs.arcade-ai.com/integrations/toolkits" target="_blank">Toolkits</a> •
|
||||
<a href="https://github.com/ArcadeAI/arcade-ai/tree/main/examples" target="_blank">Examples</a>
|
||||
|
||||
## What is Arcade AI?
|
||||
|
||||
[Arcade AI](https://arcade-ai.com?ref=github) offers developer-focused tooling and APIs designed to improve the capabilities of LLM applications and agents.
|
||||
[Arcade AI](https://arcade-ai.com?ref=github) provides developer-focused tooling and APIs designed to improve the capabilities of LLM applications and agents.
|
||||
|
||||
By providing an authentication and authorization layer for agents and the tools agents use, Arcade AI connects agentic applications with your users' data and services - like accessing their Gmail, GitHub, Zoom, Spotify, LinkedIn, and more.
|
||||
By removing the complexity of connecting agentic applications with your users' data and services, Arcade AI enables developers to focus on building their agentic applications.
|
||||
|
||||
To learn more, check out our [documentation](https://docs.arcade-ai.com).
|
||||
|
||||
_Pst. hey, you, join our stargazers! It's free!_
|
||||
_Pst. hey, you, give us a star if you like it!_
|
||||
|
||||
<a href="https://github.com/arcadeai/arcade-ai">
|
||||
<img src="https://img.shields.io/github/stars/arcadeai/arcade-ai.svg?style=social&label=Star&maxAge=2592000" alt="GitHub stars">
|
||||
|
|
@ -59,52 +56,52 @@ _Pst. hey, you, join our stargazers! It's free!_
|
|||
|
||||
### Requirements
|
||||
|
||||
1. An **[Arcade AI account](https://arcade-ai.typeform.com/early-access)** (current a waitlist)
|
||||
2. **Python 3.10+**. Verify your Python version by running `python --version` or `python3 --version` in your terminal
|
||||
3. **pip**, the Python package installer that is typically included with Python
|
||||
1. An **[Arcade AI account](https://arcade-ai.typeform.com/early-access)** (currently a waitlist)
|
||||
2. **Python 3.10+** and **pip**
|
||||
|
||||
### Installation
|
||||
|
||||
Install the package:
|
||||
|
||||
```bash
|
||||
pip install 'arcade-ai[fastapi]'
|
||||
```
|
||||
|
||||
Then login to your account (we're working through the waitlist as fast as we can!)
|
||||
Log in to your account:
|
||||
|
||||
```bash
|
||||
arcade login
|
||||
```
|
||||
|
||||
This will open a browser window to login.
|
||||
This opens a browser window for authentication.
|
||||
|
||||
### Verify Installation using `arcade chat`
|
||||
### Verify Installation with `arcade chat`
|
||||
|
||||
The `arcade-ai` package comes with a CLI app called `arcade chat` that is used to test tools as you develop them.
|
||||
|
||||
By default, `arcade chat` will connect to the hosted version of Arcade AI with built-in tools (found in `toolkits`).
|
||||
Use the `arcade chat` CLI app to test tools:
|
||||
|
||||
```bash
|
||||
arcade chat
|
||||
```
|
||||
|
||||
This launches a chat with the Arcade Cloud Engine (hosted at `api.arcade-ai.com`). All pre-built Arcade tools are available to use.
|
||||
This connects to the Arcade Cloud Engine (`api.arcade-ai.com`) with all pre-built Arcade tools.
|
||||
|
||||
For example, try asking:
|
||||
For example, try:
|
||||
|
||||
```
|
||||
star the ArcadeAI/arcade-ai repo on Github
|
||||
User (dev@arcade-ai.com):
|
||||
> star the ArcadeAI/arcade-ai repo on Github
|
||||
```
|
||||
|
||||
Arcade AI will ask you to authorize with GitHub, and then the AI assistant will star the [ArcadeAI/arcade-ai](https://github.com/ArcadeAI/arcade-ai) repo on your behalf.
|
||||
Arcade AI will prompt you to authorize with GitHub and will star the [ArcadeAI/arcade-ai](https://github.com/ArcadeAI/arcade-ai) repo on your behalf.
|
||||
|
||||
You'll see output similar to this:
|
||||
You'll see:
|
||||
|
||||
```
|
||||
Assistant (gpt-4o):
|
||||
I starred the ArcadeAI/arcade-ai repo on Github for you!
|
||||
```
|
||||
|
||||
You can use Ctrl-C to exit the chat at any time.
|
||||
Press `Ctrl-C` to exit the chat.
|
||||
|
||||
## Arcade Cloud
|
||||
|
||||
|
|
@ -242,6 +239,60 @@ Arcade AI offers a number of prebuilt toolkits that can be used by agents to int
|
|||
</tbody>
|
||||
</table>
|
||||
|
||||
### Supported Language Models
|
||||
|
||||
The LLM API supports a variety of language models. Currently, the ones supported in Arcade Cloud are OpenAI, Anthropic, Ollama, and Groq.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align: center;">Model</th>
|
||||
<th style="text-align: center;">Provider</th>
|
||||
<th style="text-align: center;">Documentation</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="text-align: center;">
|
||||
<img src="https://docs.arcade-ai.com/images/icons/openai.png" alt="OpenAI" width="30" height="30" />
|
||||
</td>
|
||||
<td style="text-align: center;">OpenAI</td>
|
||||
<td style="text-align: center;">
|
||||
<a href="https://docs.arcade-ai.com/integrations/models/openai">OpenAI Models Docs</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center;">
|
||||
<img src="https://docs.arcade-ai.com/images/icons/anthropic.png" alt="Anthropic" width="30" height="30" />
|
||||
</td>
|
||||
<td style="text-align: center;">Anthropic</td>
|
||||
<td style="text-align: center;">
|
||||
<a href="https://docs.arcade-ai.com/integrations/models/anthropic">Anthropic Models Docs</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center;">
|
||||
<img src="https://docs.arcade-ai.com/images/icons/ollama.png" alt="Ollama" width="30" height="30" />
|
||||
</td>
|
||||
<td style="text-align: center;">Ollama</td>
|
||||
<td style="text-align: center;">
|
||||
<a href="https://docs.arcade-ai.com/integrations/models/ollama">Ollama Models Docs</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: center;">
|
||||
<img src="https://docs.arcade-ai.com/images/icons/groq.png" alt="Groq" width="30" height="30" />
|
||||
</td>
|
||||
<td style="text-align: center;">Groq</td>
|
||||
<td style="text-align: center;">
|
||||
<a href="https://docs.arcade-ai.com/integrations/models/groq">Groq Models Docs</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
For more information, refer to the [models documentation](https://docs.arcade-ai.com/integrations/models/openai).
|
||||
|
||||
### Building Your Own Tools
|
||||
|
||||
Learn how to build your own tools by following our [creating a custom toolkit guide](https://docs.arcade-ai.com/tools/overview).
|
||||
|
|
@ -252,24 +303,10 @@ Arcade AI enables you to evaluate your custom tools to ensure they function corr
|
|||
|
||||
Learn how to evaluate your tools by following our [evaluating tools guide](https://docs.arcade-ai.com/home/evaluate-tools/create-an-evaluation-suite).
|
||||
|
||||
### Models
|
||||
|
||||
<img src="https://docs.arcade-ai.com/images/icons/openai.png" alt="" width="30" height="30" style="vertical-align: top;" /><img src="https://docs.arcade-ai.com/images/icons/anthropic.png" alt="" width="30" height="30" style="vertical-align: top;" /><img src="https://docs.arcade-ai.com/images/icons/ollama.png" alt="" width="30" height="30" style="vertical-align: top;" /><img src="https://docs.arcade-ai.com/images/icons/groq.png" alt="" width="30" height="30" style="vertical-align: top;" />
|
||||
<br><br>
|
||||
Arcade AI supports a variety of model providers when using the Arcade AI LLM API.
|
||||
|
||||
To see all available models, refer to the [models documentation](https://docs.arcade-ai.com/integrations/models/openai).
|
||||
|
||||
## Contributing
|
||||
|
||||
We love contributions! Please read our [contributing guide](CONTRIBUTING.md) before submitting a pull request. If you'd like to self-host, refer to the [self-hosting documentation](https://docs.arcade-ai.com/home/install/overview).
|
||||
|
||||
## Contributors
|
||||
|
||||
<a href="https://github.com/ArcadeAI/arcade-ai/graphs/contributors">
|
||||
<img alt="contributors" src="https://contrib.rocks/image?repo=ArcadeAI/arcade-ai"/>
|
||||
</a>
|
||||
|
||||
<p align="right" style="font-size: 14px; color: #555; margin-top: 20px;">
|
||||
<a href="#readme-top" style="text-decoration: none; color: #007bff; font-weight: bold;">
|
||||
↑ Back to Top ↑
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import os
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
from configuration import AgentConfigurable
|
||||
from langchain_arcade import ArcadeToolManager
|
||||
from langchain_core.messages import HumanMessage, ToolMessage
|
||||
from langchain_core.prompts import ChatPromptTemplate
|
||||
from langchain_openai import ChatOpenAI
|
||||
from langgraph.graph import END, START, MessagesState, StateGraph
|
||||
from langgraph.prebuilt import ToolNode
|
||||
|
|
@ -16,54 +18,73 @@ toolkit = ArcadeToolManager(api_key=arcade_api_key)
|
|||
tools = toolkit.get_tools(langgraph=True)
|
||||
tool_node = ToolNode(tools)
|
||||
|
||||
PROMPT_TEMPLATE = f"""
|
||||
You are a helpful assistant who can use tools to help users with tasks
|
||||
Today's date is {datetime.now().strftime("%Y-%m-%d")}
|
||||
|
||||
ALL RESPONSES should be in plain text and not markdown.
|
||||
"""
|
||||
# prompt for the main agent
|
||||
prompt = ChatPromptTemplate.from_messages([
|
||||
("system", PROMPT_TEMPLATE),
|
||||
("placeholder", "{messages}"),
|
||||
])
|
||||
# Initialize the language model with your OpenAI API key
|
||||
model = ChatOpenAI(model="gpt-4o", api_key=openai_api_key)
|
||||
# make the model aware of the tools
|
||||
model_with_tools = model.bind_tools(tools)
|
||||
model = ChatOpenAI(model="gpt-4o", api_key=openai_api_key).bind_tools(tools)
|
||||
prompted_model = prompt | model
|
||||
|
||||
|
||||
# Define the agent function that invokes the model
|
||||
def call_agent(state):
|
||||
"""Define the agent function that invokes the model"""
|
||||
messages = state["messages"]
|
||||
response = model_with_tools.invoke(messages)
|
||||
# Return the updated message history
|
||||
return {"messages": [*messages, response]}
|
||||
# replace placeholder with messages from state
|
||||
response = prompted_model.invoke({"messages": messages})
|
||||
return {"messages": [response]}
|
||||
|
||||
|
||||
# Function to determine the next step based on the model's response
|
||||
def should_continue(state: MessagesState):
|
||||
def should_continue(state: MessagesState, config: dict):
|
||||
"""Function to determine the next step based on the model's response"""
|
||||
last_message = state["messages"][-1]
|
||||
if last_message.tool_calls:
|
||||
tool_name = last_message.tool_calls[0]["name"]
|
||||
if toolkit.requires_auth(tool_name):
|
||||
user_id = config["configurable"].get("user_id")
|
||||
tool_name = state["messages"][-1].tool_calls[0]["name"]
|
||||
auth_response = toolkit.authorize(tool_name, user_id)
|
||||
if auth_response.status == "completed":
|
||||
return "tools"
|
||||
else:
|
||||
# If the tool requires authorization, proceed to the authorization step
|
||||
return "authorization"
|
||||
else:
|
||||
# If no authorization is needed, proceed to execute the tool
|
||||
return "tools"
|
||||
# If no tool calls are present, end the workflow
|
||||
return END
|
||||
|
||||
|
||||
# Function to handle tool authorization
|
||||
def wait_for_auth(state: MessagesState):
|
||||
last_message = state["messages"][-1]
|
||||
if isinstance(last_message, HumanMessage):
|
||||
return "agent"
|
||||
return "tools"
|
||||
|
||||
|
||||
def authorize(state: MessagesState, config: dict):
|
||||
"""Function to handle tool authorization"""
|
||||
user_id = config["configurable"].get("user_id")
|
||||
tool_name = state["messages"][-1].tool_calls[0]["name"]
|
||||
auth_response = toolkit.authorize(tool_name, user_id)
|
||||
|
||||
if auth_response.status == "completed":
|
||||
# Authorization is complete; proceed to the next step
|
||||
return {"messages": state["messages"]}
|
||||
else:
|
||||
# Prompt the user to complete authorization
|
||||
print("Please authorize the application in your browser:")
|
||||
print(auth_response.authorization_url)
|
||||
input("Press Enter after completing authorization...")
|
||||
|
||||
# Poll for authorization status
|
||||
while not toolkit.is_authorized(auth_response.authorization_id):
|
||||
time.sleep(3)
|
||||
return {"messages": state["messages"]}
|
||||
auth_message = (
|
||||
f"Please authorize the application in your browser:\n\n {auth_response.authorization_url}"
|
||||
)
|
||||
tool_call_id = state["messages"][-1].tool_calls[0]["id"]
|
||||
response = ToolMessage(
|
||||
content=auth_message,
|
||||
tool_call_id=tool_call_id,
|
||||
)
|
||||
# Add the new message to the message history and add a new human message
|
||||
# saying that the agent should try again
|
||||
try_message = HumanMessage(
|
||||
content="Please try the previous tool call again now that you are authorized."
|
||||
)
|
||||
return {"messages": [response, try_message]}
|
||||
|
||||
|
||||
# Build the workflow graph
|
||||
|
|
@ -73,12 +94,14 @@ workflow = StateGraph(MessagesState, AgentConfigurable)
|
|||
workflow.add_node("agent", call_agent)
|
||||
workflow.add_node("tools", tool_node)
|
||||
workflow.add_node("authorization", authorize)
|
||||
# workflow.add_node("wait_for_auth", wait_for_auth)
|
||||
|
||||
# Define the edges and control flow
|
||||
workflow.add_edge(START, "agent")
|
||||
workflow.add_conditional_edges("agent", should_continue, ["authorization", "tools", END])
|
||||
workflow.add_edge("authorization", "tools")
|
||||
workflow.add_edge("authorization", "agent")
|
||||
workflow.add_edge("tools", "agent")
|
||||
|
||||
# Compile the graph
|
||||
graph = workflow.compile()
|
||||
# Compile the graph with an interrupt after the authorization node
|
||||
# so that we can prompt the user to authorize the application
|
||||
graph = workflow.compile(interrupt_after=["authorization"])
|
||||
|
|
|
|||
Loading…
Reference in a new issue