-
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.
feat: add assignment-agent (autogen + canvas) in py examples (#948)
- Loading branch information
1 parent
7425eec
commit 29e6cc4
Showing
5 changed files
with
281 additions
and
0 deletions.
There are no files selected for viewing
2 changes: 2 additions & 0 deletions
2
python/examples/advanced_agents/assignment-agent/.env.example
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,2 @@ | ||
OPENAI_API_KEY= | ||
COMPOSIO_API_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,4 @@ | ||
autogen | ||
.env | ||
__pycache__ | ||
.cache |
41 changes: 41 additions & 0 deletions
41
python/examples/advanced_agents/assignment-agent/README.md
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,41 @@ | ||
# AI Assignment Agent | ||
|
||
This project implements a single AI agent built using Autogen and Composio Tools that can either create or review assignments based on user selection. | ||
|
||
## Features | ||
- Create new assignments on Canvas | ||
- Review and grade submitted assignments on Canvas | ||
|
||
## Prerequisites | ||
|
||
- A connected Canvas account on Composio | ||
- OpenAI API key | ||
- Composio API key | ||
|
||
## Installation | ||
|
||
1. **Install dependencies**: | ||
```bash | ||
pip install -r requirements.txt | ||
``` | ||
|
||
2. **Set up environment variables**: | ||
Create a `.env` file with: | ||
``` | ||
OPENAI_API_KEY=your_openai_key | ||
COMPOSIO_API_KEY=your_composio_key | ||
``` | ||
|
||
## Usage | ||
|
||
Run the main script and select your desired operation: | ||
|
||
```bash | ||
python assignment_agent.py | ||
``` | ||
|
||
You'll be prompted to: | ||
1. Choose an operation: | ||
- Option 1: Create a new assignment | ||
- Option 2: Review existing assignments | ||
2. Provide necessary details based on your selection |
167 changes: 167 additions & 0 deletions
167
python/examples/advanced_agents/assignment-agent/assignment_agent.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,167 @@ | ||
from autogen import AssistantAgent, UserProxyAgent | ||
from composio_autogen import ComposioToolSet, Action | ||
from composio import AppType | ||
import os | ||
from dotenv import load_dotenv | ||
|
||
load_dotenv() | ||
|
||
toolset = ComposioToolSet( | ||
api_key=os.getenv("COMPOSIO_API_KEY"), | ||
entity_id="karthik", | ||
) | ||
llm_config = { | ||
"config_list": [ | ||
{ | ||
"model": "gpt-4o", | ||
"api_key": os.getenv("OPENAI_API_KEY"), | ||
} | ||
] | ||
} | ||
|
||
chatbot = AssistantAgent( | ||
"chatbot", | ||
system_message="You're a helpful assistant that creates assignments for a course & reviews them. You will be given the details of the assigment to create and review, after creating or reviewing you need to TERMINATE.", | ||
llm_config=llm_config, | ||
) | ||
|
||
user_proxy = UserProxyAgent( | ||
name="User", | ||
is_termination_msg=lambda x: x.get("content", "") | ||
and "TERMINATE" in x.get("content", ""), | ||
human_input_mode="NEVER", | ||
code_execution_config={"use_docker": False}, | ||
) | ||
|
||
toolset.register_tools( | ||
actions=[ | ||
Action.CANVAS_CREATE_ASSIGNMENT, | ||
Action.CANVAS_GET_ASSIGNMENT, | ||
Action.CANVAS_LIST_ASSIGNMENT_SUBMISSIONS, | ||
Action.CANVAS_GRADE_COMMENT_SUBMISSION, | ||
], | ||
caller=chatbot, | ||
executor=user_proxy, | ||
) | ||
|
||
def get_courses(): | ||
courses = toolset.execute_action( | ||
action=Action.CANVAS_LIST_COURSES, | ||
entity_id="karthik", | ||
params={} | ||
) | ||
return courses | ||
|
||
def get_assignments(course_id): | ||
assignments = toolset.execute_action( | ||
action=Action.CANVAS_GET_ALL_ASSIGNMENTS, | ||
entity_id="karthik", | ||
params={"course_id": course_id} | ||
) | ||
return assignments | ||
|
||
def get_course_id_by_name(): | ||
courses_response = get_courses() | ||
if not courses_response.get('successfull'): | ||
print("Failed to fetch courses") | ||
return None | ||
|
||
courses_data = courses_response['data']['response_data'] | ||
available_courses = {course['name'].strip(): course['id'] for course in courses_data} | ||
|
||
print("\nAvailable courses:") | ||
for course_name in available_courses.keys(): | ||
print(f"- {course_name}") | ||
|
||
while True: | ||
course_name = input("\nEnter course name: ").strip() | ||
if course_name in available_courses: | ||
return available_courses[course_name] | ||
print(f"Course '{course_name}' not found. Please try again.") | ||
|
||
def get_create_assignment_task(): | ||
course_id = get_course_id_by_name() | ||
if not course_id: | ||
return None | ||
|
||
name = input("\nEnter assignment name: ").strip() | ||
description = input("Enter assignment description: ") | ||
|
||
return f""" | ||
Create a new assignment for the course with id {course_id}. | ||
Assignment details: | ||
- Name: {name} | ||
- Description: {description} | ||
- Published: True | ||
- Assignment Group: everyone | ||
- Submission Types: Online (Text Entry) | ||
- Display grade as: Points (10 is total points) | ||
""" | ||
|
||
def get_assignment_id_by_name(course_id): | ||
assignments_response = get_assignments(course_id) | ||
if not assignments_response.get('successfull'): | ||
print("Failed to fetch assignments") | ||
return None | ||
|
||
assignments_data = assignments_response['data']['response_data'] | ||
available_assignments = {assignment['name'].strip(): assignment['id'] for assignment in assignments_data} | ||
|
||
if not available_assignments: | ||
print("No assignments found in this course") | ||
return None | ||
|
||
print("\nAvailable assignments:") | ||
for assignment_name in available_assignments.keys(): | ||
print(f"- {assignment_name}") | ||
|
||
while True: | ||
assignment_name = input("\nEnter assignment name: ").strip() | ||
if assignment_name in available_assignments: | ||
return available_assignments[assignment_name] | ||
print(f"Assignment '{assignment_name}' not found. Please try again.") | ||
|
||
def get_review_assignment_task(): | ||
course_id = get_course_id_by_name() | ||
if not course_id: | ||
return None | ||
|
||
assignment_id = get_assignment_id_by_name(course_id) | ||
if not assignment_id: | ||
return None | ||
|
||
return f""" | ||
You need to review the submissions for an assignment: | ||
1. First get the assignent details using: CANVAS_GET_ASSIGNMENT | ||
2. Then get the submissions for the assignment using: CANVAS_LIST_ASSIGNMENT_SUBMISSIONS | ||
3. Based on the assignment details, review the submissions, check if they are correct | ||
a. If all answers are correct, give full points (10) | ||
b. If one or more answers are incorrect, give partial points (5) | ||
c. If all answers are incorrect, give 0 points | ||
and grade the submissions using: CANVAS_GRADE_COMMENT_SUBMISSION | ||
Below are the details of the assignment: | ||
- Course ID: {course_id} | ||
- Assignment ID: {assignment_id} | ||
""" | ||
|
||
def main(): | ||
print("What would you like to do?") | ||
print("1. Create new assignment") | ||
print("2. Review an assignment") | ||
|
||
choice = input("Enter your choice (1 or 2): ") | ||
|
||
if choice == "1": | ||
task = get_create_assignment_task() | ||
elif choice == "2": | ||
task = get_review_assignment_task() | ||
else: | ||
print("Invalid choice. Please select 1 or 2.") | ||
return | ||
|
||
if task: | ||
response = user_proxy.initiate_chat(chatbot, message=task) | ||
print(response.chat_history) | ||
|
||
if __name__ == "__main__": | ||
main() |
67 changes: 67 additions & 0 deletions
67
python/examples/advanced_agents/assignment-agent/requirements.txt
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,67 @@ | ||
aiohappyeyeballs==2.4.4 | ||
aiohttp==3.11.9 | ||
aiosignal==1.3.1 | ||
annotated-types==0.7.0 | ||
anyio==4.6.2.post1 | ||
async-timeout==5.0.1 | ||
attrs==24.2.0 | ||
bcrypt==4.2.1 | ||
certifi==2024.8.30 | ||
cffi==1.17.1 | ||
charset-normalizer==3.4.0 | ||
click==8.1.7 | ||
composio_autogen==0.5.50 | ||
composio_core==0.5.50 | ||
cryptography==44.0.0 | ||
diskcache==5.6.3 | ||
distro==1.9.0 | ||
docker==7.1.0 | ||
exceptiongroup==1.2.2 | ||
fastapi==0.115.6 | ||
FLAML==2.2.0 | ||
frozenlist==1.5.0 | ||
h11==0.14.0 | ||
httpcore==1.0.7 | ||
httpx==0.28.0 | ||
idna==3.10 | ||
importlib_metadata==8.5.0 | ||
inflection==0.5.1 | ||
jiter==0.8.0 | ||
jsonref==1.1.0 | ||
jsonschema==4.23.0 | ||
jsonschema-specifications==2024.10.1 | ||
markdown-it-py==3.0.0 | ||
mdurl==0.1.2 | ||
multidict==6.1.0 | ||
numpy==1.26.4 | ||
openai==1.56.1 | ||
packaging==24.2 | ||
paramiko==3.5.0 | ||
propcache==0.2.1 | ||
pyautogen==0.4.1 | ||
pycparser==2.22 | ||
pydantic==2.9.2 | ||
pydantic_core==2.23.4 | ||
Pygments==2.18.0 | ||
PyNaCl==1.5.0 | ||
pyperclip==1.9.0 | ||
Pysher==1.0.8 | ||
python-dotenv==1.0.1 | ||
referencing==0.35.1 | ||
regex==2024.11.6 | ||
requests==2.32.3 | ||
rich==13.9.4 | ||
rpds-py==0.22.1 | ||
semver==3.0.2 | ||
sentry-sdk==2.19.0 | ||
sniffio==1.3.1 | ||
starlette==0.41.3 | ||
termcolor==2.5.0 | ||
tiktoken==0.8.0 | ||
tqdm==4.67.1 | ||
typing_extensions==4.12.2 | ||
urllib3==2.2.3 | ||
uvicorn==0.32.1 | ||
websocket-client==1.8.0 | ||
yarl==1.18.3 | ||
zipp==3.21.0 |