Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introducing AutoAnny: A New Discord Bot Built with AutoGen #1501

Merged
merged 15 commits into from
Feb 7, 2024
43 changes: 43 additions & 0 deletions samples/apps/auto-anny/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<div align="center">
<img src="images/icon.png" alt="Repo Icon" width="100" height="100">
</div>

# AutoAnny

AutoAnny is a Discord bot built using AutoGen to help with AutoGen's Discord server.
Actually Anny can help with any OSS GitHub project (set `ANNY_GH_REPO` below).

## Features

- **`/heyanny help`**: Lists commands.
- **`/heyanny ghstatus`**: Summarizes GitHub activity.
- **`/heyanny ghgrowth`**: Shows GitHub repo growth indicators.
- **`/heyanny ghunattended`**: Lists unattended issues and PRs.

## Installation

1. Clone the AutoGen repository and `cd samples/apps/auto-anny`
2. Install dependencies: `pip install -r requirements.txt`
3. Export Discord token and GitHub API token,
```
export OAI_CONFIG_LIST=your-autogen-config-list
export DISCORD_TOKEN=your-bot-token
export GH_TOKEN=your-gh-token
export ANNY_GH_REPO=microsoft/autogen # you may choose a different repo name
```
To get a Discord token, you will need to set up your Discord bot using these [instructions](https://discordpy.readthedocs.io/en/stable/discord.html).
4. Start the bot: `python bot.py`

Note: By default Anny will log data to `autoanny.log`.


## Roadmap

- Enable access control
- Enable a richer set of commands
- Enrich agents with tool use


## Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
36 changes: 36 additions & 0 deletions samples/apps/auto-anny/agent_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from autogen import AssistantAgent, UserProxyAgent, config_list_from_json


async def solve_task(task):
gagb marked this conversation as resolved.
Show resolved Hide resolved
config_list = config_list_from_json(env_or_file="OAI_CONFIG_LIST")
assistant = AssistantAgent("assistant", llm_config={"config_list": config_list})
user_proxy = UserProxyAgent(
"user_proxy",
code_execution_config={"work_dir": "coding", "use_docker": False},
human_input_mode="NEVER",
is_termination_msg=lambda msg: "TERMINATE" in msg.get("content", ""),
)
await user_proxy.a_initiate_chat(assistant, message=task)

await user_proxy.a_send(
f"""Based on the results in above conversation, create a response for the user.
While computing the response, remember that this conversation was your inner mono-logue.
The user does not need to know every detail of the conversation.
All they want to see is the appropriate result for their task (repeated below) in
a manner that would be most useful. Response should be less than 1500 characters.

The task was: {task}

There is no need to use the word TERMINATE in this response.

""",
assistant,
request_reply=False,
silent=True,
)
response = await assistant.a_generate_reply(assistant.chat_messages[user_proxy], user_proxy)
await assistant.a_send(response, user_proxy, request_reply=False, silent=True)

last_message = assistant.chat_messages[user_proxy][-1]["content"]

return last_message[:2000]
153 changes: 153 additions & 0 deletions samples/apps/auto-anny/bot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import os
import logging
import logging.handlers

import discord
from discord.ext import commands

from agent_utils import solve_task

logger = logging.getLogger("anny")
logger.setLevel(logging.INFO)
logging.getLogger("discord.http").setLevel(logging.INFO)

handler = logging.handlers.RotatingFileHandler(
filename="autoanny.log",
encoding="utf-8",
maxBytes=32 * 1024 * 1024, # 32 MiB
backupCount=5, # Rotate through 5 files
)
dt_fmt = "%Y-%m-%d %H:%M:%S"
formatter = logging.Formatter("[{asctime}] [{levelname:<8}] {name}: {message}", dt_fmt, style="{")
handler.setFormatter(formatter)
logger.addHandler(handler)

required_env_vars = ["OAI_CONFIG_LIST", "DISCORD_TOKEN", "GH_TOKEN", "ANNY_GH_REPO"]
for var in required_env_vars:
if var not in os.environ:
raise ValueError(f"{var} environment variable is not set.")

# read token from environment variable
DISCORD_TOKEN = os.environ["DISCORD_TOKEN"]
REPO = os.environ["ANNY_GH_REPO"]

intents = discord.Intents.default()
intents.message_content = True
intents.reactions = True
bot = commands.Bot(command_prefix="/", intents=intents)


@bot.event
async def on_message(message):
logger.info({"message": message.content, "author": message.author, "id": message.id})
await bot.process_commands(message)


@bot.event
async def on_reaction_add(reaction, user):
message = reaction.message
logger.info(
{
"message": message.content,
"author": message.author,
"id": message.id,
"reaction": reaction.emoji,
"reactor": user,
}
)


@bot.event
async def on_ready():
logger.info("Logged in", extra={"user": bot.user})


@bot.command(description="Invoke Anny to solve a task.")
async def heyanny(ctx, task: str = None):
if not task or task == "help":
response = help_msg()
await ctx.send(response)
return

task_map = {
"ghstatus": ghstatus,
"ghgrowth": ghgrowth,
"ghunattended": ghunattended,
"ghstudio": ghstudio,
}

if task in task_map:
await ctx.send("Working on it...")
response = await task_map[task](ctx)
await ctx.send(response)
else:
response = "Invalid command! Please type /heyanny help for the list of commands."
await ctx.send(response)


def help_msg():
response = f"""
Hi this is Anny an AutoGen-powered Discord bot to help with `{REPO}`. I can help you with the following tasks:
- ghstatus: Find the most recent issues and PRs from today.
- ghgrowth: Find the number of stars, forks, and indicators of growth.
- ghunattended: Find the most issues and PRs from today from today that haven't received a response/comment.

You can invoke me by typing `/heyanny <task>`.
"""
return response


async def ghstatus(ctx):
response = await solve_task(
f"""
Find the most recent issues and PRs from `{REPO}` in last 24 hours.
Separate issues and PRs.
Final response should contains title, number, date/time, URLs of the issues and PRs.
Markdown formatted response will make it look nice.
Make sure date/time is in PST and readily readable.
You can access github token from the environment variable called GH_TOKEN.
"""
)
return response


async def ghgrowth(ctx):
response = await solve_task(
f"""
Find the number of stars, forks, and indicators of growth of `{REPO}`.
Compare the stars of `{REPO}` this week vs last week.
Make sure date/time is in PST and readily readable.
You can access github token from the environment variable called GH_TOKEN.
"""
)
return response


async def ghunattended(ctx):
response = await solve_task(
f"""
Find the issues *created* in the last 24 hours from `{REPO}` that haven't
received a response/comment. Modified issues don't count.
Final response should contains title, number, date/time, URLs of the issues and PRs.
Make sure date/time is in PST and readily readable.
You can access github token from the environment variable called GH_TOKEN.
"""
)
return response


async def ghstudio(ctx):
# TODO: Generalize to feature name
response = await solve_task(
f"""
Find issues and PRs from `{REPO}` that are related to the AutoGen Studio.
The title or the body of the issue or PR should give you a hint whether its related.
Summarize the top 5 common complaints or issues. Cite the issue/PR number and URL.
Explain why you think this is a common issue in 2 sentences.
You can access github token from the environment variable called GH_TOKEN.
"""
)
return response


bot.run(DISCORD_TOKEN, log_handler=None)
Binary file added samples/apps/auto-anny/images/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions samples/apps/auto-anny/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
discord.py
pyautogen
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 42 additions & 0 deletions website/blog/2024-02-02-AutoAnny/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
title: "Anny: Assisting AutoGen Devs Via AutoGen"
authors:
- gagb
tags: [AutoGen]
---

import AutoAnnyLogo from './img/AutoAnnyLogo.jpg';

<div style={{ display: "flex", justifyContent: "center" }}>
<img src={AutoAnnyLogo} alt="AutoAnny Logo" style={{ width: "250px" }} />
</div>
<p align="center"><em>Anny is a Discord bot powered by AutoGen to help AutoGen's Discord server.</em></p>


### TLDR

To help AutoGen devs manage our OSS community, we are adding a new sample app called Anny-- a simple Discord bot powered by AutoGen. See `samples/apps/auto-anny` for details.

### Introduction

Over the past few months, our team has experienced both the satisfaction of growth and the overwhelming task of keeping up with community requests. Our daily process involves manually sifting through issues, PRs, and discussions on GitHub, as well as managing messages from our 2,000+ community members on Discord, not to mention direct messages and emails from colleagues both inside and outside our organization. All of this inaddition to pushing the frontiers of research on agents.

There many specific tasks we perform everyday, but here are some of the most common ones:
- Answering questions
- Recognizing and prioritizing bugs and features
- Maintaining responsiveness for our incredible community
- Tracking growth

This requires a significant amount of effort from our talented team. Agentic-workflows and interfaces promise adding immense value-added automation for many tasks, so we thought why don't we use AutoGen to make our lives easier?! So we're turning to automation to handle the more monotonous tasks and allow us to focus on what's most critical.

### Current Version of Anny
The current version of Anny is pretty simple -- it uses the Discord API and AutoGen to enable a bot that can respond to a set of commands.
For example, it supports commands like `/heyanny help` for command listing, `/heyanny ghstatus` for GitHub activity summary, `/heyanny ghgrowth` for GitHub repo growth indicators, and `/heyanny ghunattended` for listing unattended issues and PRs. Most of these commands use multiple AutoGen agents to accomplish these task.

To use Anny, please following instructions in [`samples/apps/auto-anny`](https://github.com/microsoft/autogen/tree/main/samples/apps/auto-anny).
gagb marked this conversation as resolved.
Show resolved Hide resolved




### Its Not Just for AutoGen
If you're an open-source developer managing your own project, you can probably relate to our challenges. We invite you to check out Anny and contribute to its development and roadmap.
1 change: 1 addition & 0 deletions website/docs/Examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Links to notebook examples:
- Automated Chess Game Playing & Chitchatting by GPT-4 Agents - [View Notebook](https://github.com/microsoft/autogen/blob/main/notebook/agentchat_chess.ipynb)
- Automated Continual Learning from New Data - [View Notebook](https://github.com/microsoft/autogen/blob/main/notebook/agentchat_stream.ipynb)
- [OptiGuide](https://github.com/microsoft/optiguide) - Coding, Tool Using, Safeguarding & Question Answering for Supply Chain Optimization
- [AutoAnny](https://github.com/microsoft/autogen/tree/main/samples/apps/auto-anny) - A Discord bot built using AutoGen
gagb marked this conversation as resolved.
Show resolved Hide resolved

1. **Tool Use**

Expand Down
Loading