-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
247 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
OPENAI_API_KEY=KEY |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
# Import necessary libraries | ||
import os | ||
from tkinter import END # For accessing environment variables | ||
import dotenv # For loading environment variables from a .env file | ||
# Import modules from Composio and LlamaIndex | ||
import re | ||
from datetime import datetime | ||
from composio_llamaindex import App, ComposioToolSet, Action | ||
from llama_index.core.agent import FunctionCallingAgentWorker | ||
from llama_index.core.llms import ChatMessage | ||
from llama_index.llms.openai import OpenAI | ||
from composio.client.collections import TriggerEventData | ||
from composio_llamaindex import Action, App, ComposioToolSet | ||
|
||
# Load environment variables from a .env file | ||
dotenv.load_dotenv() | ||
|
||
BOT_USER_ID = os.environ[ | ||
"BOT_USER_ID" | ||
] # Bot ID for Composio. Replace with your own bot member ID, once bot joins the channel. | ||
RESPOND_ONLY_IF_TAGGED = ( | ||
True # Set to True to have the bot respond only when tagged in a message | ||
) | ||
|
||
llm = OpenAI(model="gpt-4o") | ||
|
||
composio_toolset = ComposioToolSet() | ||
slack_listener = composio_toolset.create_trigger_listener() | ||
gmail_listener = composio_toolset.create_trigger_listener() | ||
|
||
def proc(): | ||
print("listener") | ||
composio_toolset.execute_action( | ||
action=Action.SLACKBOT_SENDS_A_MESSAGE_TO_A_SLACK_CHANNEL, | ||
params={ | ||
"channel": "general", | ||
"text": f"Are you sure you want to post message:{mail_message} from sender email:{sender_mail}. If yes, tag test_app and tell it the project id and team id.", | ||
}, | ||
) | ||
slack_listener.listen() | ||
|
||
composio_tools = composio_toolset.get_tools( | ||
apps=[App.LINEAR, App.GMAIL] | ||
) | ||
|
||
|
||
|
||
prefix_messages = [ | ||
ChatMessage( | ||
role="system", | ||
content=( | ||
"You are an agent that creates issues in Linear based on customer feedback emails" | ||
), | ||
) | ||
] | ||
|
||
agent = FunctionCallingAgentWorker( | ||
tools=composio_tools, | ||
llm=llm, | ||
prefix_messages=prefix_messages, | ||
max_function_calls=10, | ||
allow_parallel_tool_calls=False, | ||
verbose=True, | ||
).as_agent() | ||
|
||
|
||
# Callback function for handling new messages in a Slack channel | ||
@slack_listener.callback(filters={"trigger_name": "slackbot_receive_message"}) | ||
def callback_new_message(event: TriggerEventData) -> None: | ||
print("Recieved new messsage") | ||
payload = event.payload | ||
user_id = payload.get("user", "") | ||
|
||
# Ignore messages from the bot itself to prevent self-responses | ||
if user_id == BOT_USER_ID: | ||
return "Bot ignored" | ||
|
||
message = payload.get("text", "") | ||
|
||
# Respond only if the bot is tagged in the message, if configured to do so | ||
if RESPOND_ONLY_IF_TAGGED and f"<@{BOT_USER_ID}>" not in message: | ||
print(f"Bot not tagged, ignoring message - {message} - {BOT_USER_ID}") | ||
return ( | ||
f"Bot not tagged, ignoring message - {json.dumps(payload)} - {BOT_USER_ID}" | ||
) | ||
|
||
# Extract channel and timestamp information from the event payload | ||
channel_id = payload.get("channel", "") | ||
ts = payload.get("ts", "") | ||
thread_ts = payload.get("thread_ts", ts) | ||
|
||
|
||
|
||
YES_OR_NO_prefix_messages = [ | ||
ChatMessage( | ||
role="system", | ||
content=( | ||
"Take input from the user on team id and project id and create an issue on Linear " | ||
), | ||
) | ||
] | ||
tools = composio_toolset.get_actions(apps=[App.LINEAR]) | ||
# Process the message and post the response in the same channel or thread | ||
check_agent = FunctionCallingAgentWorker( | ||
tools=tools, | ||
llm=llm, | ||
prefix_messages=YES_OR_NO_prefix_messages, | ||
max_function_calls=10, | ||
allow_parallel_tool_calls=False, | ||
verbose=True, | ||
).as_agent() | ||
query_task = f""" | ||
2. If you decide to create an issue, Create it on Linear. | ||
3. If you decide to create an issue it should be a summary of the email content. | ||
4. The email content is {mail_message} and sender email is {sender_mail} | ||
4. The format should be <id>:<content> | ||
5. If you decide NO, then dont call any agent and end operation. | ||
message:{message} | ||
6. If the user does not give project id or team id find them out by using Linear Tool's actions. | ||
""" | ||
result = check_agent.chat(query_task) | ||
print(result) | ||
composio_toolset.execute_action( | ||
action=Action.SLACKBOT_CHAT_POST_MESSAGE, | ||
params={ | ||
"channel": channel_id, | ||
"text": result.response, | ||
"thread_ts": thread_ts, | ||
}, | ||
) | ||
|
||
|
||
@gmail_listener.callback(filters={"trigger_name": "gmail_new_gmail_message"}) | ||
def callback_new_message(event: TriggerEventData) -> None: | ||
print("MESSAGE RECEIVED") | ||
print("here in the function") | ||
payload = event.payload | ||
global mail_message | ||
global sender_mail | ||
thread_id = payload.get("threadId") | ||
mail_message = payload.get("messageText") | ||
print(payload) | ||
sender_mail = payload.get("sender") | ||
if sender_mail is None: | ||
print("No sender email found") | ||
return | ||
print(sender_mail) | ||
print("WAITING FOR SLACK CONFIRMATION") | ||
composio_toolset_1 = ComposioToolSet( | ||
processors={ | ||
"pre": { | ||
Action.LINEAR_CREATE_LINEAR_ISSUE: proc() | ||
}, | ||
} | ||
) | ||
|
||
|
||
print("GMAIL LISTENING") | ||
|
||
gmail_listener.listen() | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# Human in the Loop Guide | ||
|
||
This guide provides detailed steps to create a Human in the Loop Agent that leverages Composio, agentic frameworks such as LlamaIndex and ChatGPT to review PRs every time they're created. Ensure you have Python 3.8 or higher installed. | ||
|
||
## Adding a Slackbot | ||
![alt text](https://github.com/composiohq/composio/blob/feat/slack-assistant/python/examples/slack_bot_agent/adding_slack_bot.gif?raw=true) | ||
|
||
## Steps to perform before running | ||
|
||
Ensure that triggers are enabled in the Composio Dashboard. These are the triggers to enable: | ||
1. [Slack Bot Receive Message (trigger_id = SLACKBOT_RECEIVE_MESSAGE)](https://app.composio.dev/app/slackbot) | ||
2. [Slack Bot Receive Thread Reply (trigger_id = SLACKBOT_RECEIVE_THREAD_REPLY)](https://app.composio.dev/app/slackbot) | ||
3. [Gmail Receive Email (trigger_id = NEW_GMAIL_MESSAGE)](https://app.composio.dev/app/gmail) | ||
Add the slackbot to any channel in your workspace to use it. | ||
|
||
## Steps to Run | ||
|
||
**Navigate to the Project Directory:** | ||
Change to the directory where the `setup.sh`, `main.py`, `requirements.txt`, and `README.md` files are located. For example: | ||
```sh | ||
cd path/to/project/directory | ||
``` | ||
|
||
### 1. Run the Setup File | ||
Make the setup.sh Script Executable (if necessary): | ||
On Linux or macOS, you might need to make the setup.sh script executable: | ||
```shell | ||
chmod +x setup.sh | ||
``` | ||
Execute the setup.sh script to set up the environment and install dependencies: | ||
```shell | ||
./setup.sh | ||
``` | ||
Now, fill in the `.env` file with your secrets. | ||
|
||
### 2. Run the Python Script | ||
```shell | ||
python cookbook/examples/human_in_the_loop/main.py | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
composio-llamaindex | ||
llama-index | ||
python-dotenv |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
#!/bin/bash | ||
|
||
# Create a virtual environment | ||
echo "Creating virtual environment..." | ||
python3 -m venv ~/.venvs/human_in_the_loop | ||
|
||
# Activate the virtual environment | ||
echo "Activating virtual environment..." | ||
source ~/.venvs/human_in_the_loop/bin/activate | ||
|
||
# Install libraries from requirements.txt | ||
echo "Installing libraries from requirements.txt..." | ||
pip install -r requirements.txt | ||
|
||
# Login to your account | ||
echo "Login to your Composio acount" | ||
composio login | ||
|
||
# Add trello tool | ||
|
||
echo "Add slackbot tool. Finish the flow" | ||
composio add slackbot | ||
composio add gmail | ||
|
||
echo "Enable Slackbot triggers" | ||
composio triggers enable slackbot_receive_message | ||
composio triggers enable slackbot_receive_thread_reply | ||
composio triggers enable new_gmail_message | ||
|
||
# Copy env backup to .env file | ||
if [ -f ".env.example" ]; then | ||
echo "Copying .env.example to .env..." | ||
cp .env.example .env | ||
else | ||
echo "No .env.example file found. Creating a new .env file..." | ||
touch .env | ||
fi | ||
|
||
# Prompt user to fill the .env file | ||
echo "Please fill in the .env file with the necessary environment variables." | ||
|
||
echo "Setup completed successfully!" |