joelazo commited on
Commit
854cd25
·
1 Parent(s): 0693b60

Initial commit of the AI instructor assistant agent.

Browse files
README.md CHANGED
@@ -1,2 +1,52 @@
1
  # instructor_assistant
 
2
  AI Agent helps instructors create lesson plans, course outline, exercise program... any resource needed for faster course preparation and execution.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # instructor_assistant
2
+
3
  AI Agent helps instructors create lesson plans, course outline, exercise program... any resource needed for faster course preparation and execution.
4
+
5
+ ## Setup with UV
6
+
7
+ This project uses [UV](https://github.com/astral-sh/uv) for package management.
8
+
9
+ ### Prerequisites
10
+
11
+ Install UV if you haven't already:
12
+
13
+ ```bash
14
+ curl -LsSf https://astral.sh/uv/install.sh | sh
15
+ ```
16
+
17
+ Or on macOS with Homebrew:
18
+ ```bash
19
+ brew install uv
20
+ ```
21
+
22
+ ### Setup Instructions
23
+
24
+ 1. **Install dependencies:**
25
+ ```bash
26
+ uv sync
27
+ ```
28
+
29
+ 2. **Activate the virtual environment:**
30
+ ```bash
31
+ source .venv/bin/activate # On macOS/Linux
32
+ # or
33
+ .venv\Scripts\activate # On Windows
34
+ ```
35
+
36
+ 3. **Run the application:**
37
+ ```bash
38
+ uv run python course_manager.py
39
+ ```
40
+
41
+ Alternatively, you can run directly with UV without activating the venv:
42
+ ```bash
43
+ uv run course_manager.py
44
+ ```
45
+
46
+ ### Environment Variables
47
+
48
+ Create a `.env` file in the project root with your OpenAI API key:
49
+
50
+ ```
51
+ OPENAI_API_KEY=your_api_key_here
52
+ ```
__pycache__/coordinator_agent.cpython-312.pyc ADDED
Binary file (4.75 kB). View file
 
__pycache__/curriculum_designer_agent.cpython-312.pyc ADDED
Binary file (5.46 kB). View file
 
__pycache__/instruction_designer_agent.cpython-312.pyc ADDED
Binary file (3.13 kB). View file
 
__pycache__/practice_designer_agent.cpython-312.pyc ADDED
Binary file (3.33 kB). View file
 
__pycache__/qa_agent.cpython-312.pyc ADDED
Binary file (3.23 kB). View file
 
coordinator_agent.py ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Literal
2
+
3
+ from curriculum_designer_agent import Curriculum, CurriculumDesignerAgent
4
+ from instruction_designer_agent import Instruction, InstructionDesignerAgent
5
+ from practice_designer_agent import Practice, PracticeDesignerAgent
6
+ from pydantic import BaseModel
7
+ from qa_agent import QAAgent, QualityAssurance
8
+
9
+ from agents import Agent
10
+
11
+ INSTRUCTIONS = (
12
+ """You are an coordinator agent, you are responsible for coordinating the course instruction flow.
13
+ 1. First the curriculum designer agent will design the curriculum.
14
+ 2. Then the instruction designer must design the course instruction.
15
+ 3. Then the practice designer must design the practice exercises.
16
+ 4. Then the QA agent must assure that this course has the right quality.
17
+ If it doesn't have the right quality, you should start the flow again from the step the qa agent wasn't satisfied with.
18
+ """
19
+ )
20
+
21
+ class CoordinatorInstructions():
22
+ def name(self):
23
+ return "coordinator"
24
+
25
+ def instructions(self):
26
+ return (
27
+ "You are an coordinator agent, you are responsible for coordinating the course instruction flow."
28
+ "1. First the curriculum designer agent will design the curriculum."
29
+ "2. Then the instruction designer must design the course instruction."
30
+ "3. Then the practice designer must design the practice exercises."
31
+ "4. Then the QA agent must assure that this course has the right quality."
32
+ "If it doesn't have the right quality, you should start the flow again from the step the qa agent wasn't satisfied with."
33
+ "5. In the end based on all of the information provided to you in above steps, write a clear and concise course plan."
34
+ )
35
+
36
+ def handoff_description(self):
37
+ return self.instructions()
38
+
39
+ def model(self) -> Literal["gpt-4o-mini", "gpt-4o"]:
40
+ return "gpt-4o-mini"
41
+
42
+
43
+ class Course(BaseModel):
44
+ curriculum: Curriculum
45
+ instruction: Instruction
46
+ practice: Practice
47
+ qa: QualityAssurance
48
+
49
+
50
+ class CoordinatorAgent():
51
+ def __init__(self):
52
+ self.curriculum_designer_agent = CurriculumDesignerAgent()
53
+ self.instruction_designer_agent = InstructionDesignerAgent()
54
+ self.practice_designer_agent = PracticeDesignerAgent()
55
+ self.qa_agent = QAAgent()
56
+ self.agent = self.init_agent()
57
+
58
+ def get_agent(self):
59
+ return self.agent
60
+
61
+ def init_agent(self):
62
+ tools = [
63
+ self.curriculum_designer_agent.as_tool(),
64
+ self.instruction_designer_agent.as_tool(),
65
+ self.practice_designer_agent.as_tool(),
66
+ self.qa_agent.as_tool(),
67
+ ]
68
+ instructions = CoordinatorInstructions()
69
+ agent = Agent(
70
+ name=instructions.name(),
71
+ instructions=instructions.instructions(),
72
+ model=instructions.model(),
73
+ tools=tools,
74
+ )
75
+ return agent
76
+
77
+ def as_tool(self):
78
+ instructions = CoordinatorInstructions()
79
+ return self.agent.as_tool(tool_name=instructions.name(), tool_description=instructions.handoff_description())
course_manager.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from coordinator_agent import CoordinatorAgent
3
+ from dotenv import load_dotenv
4
+ from openai.types.responses import ResponseTextDeltaEvent
5
+
6
+ from agents import Runner
7
+
8
+ load_dotenv(override=True)
9
+
10
+ async def run(query: str):
11
+ coordinator_agent = CoordinatorAgent().get_agent()
12
+ result = Runner.run_streamed(coordinator_agent, input=query)
13
+ response = ""
14
+ status = ""
15
+ async for event in result.stream_events():
16
+ if event.type == "raw_response_event" and isinstance(event.data, ResponseTextDeltaEvent) and event.data.delta:
17
+ response += event.data.delta
18
+ yield response, status
19
+ elif event.type == "run_item_stream_event":
20
+ item = event.item
21
+ item_type = getattr(item, "type", "")
22
+
23
+ if item_type == "tool_call_item":
24
+ tool_name = getattr(item.raw_item, 'name', '')
25
+ log_msg = f"Tool call: {tool_name}\n"
26
+ status += log_msg
27
+ yield response, status
28
+
29
+ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue")) as ui:
30
+ gr.Markdown("# Course Instructor Assistant")
31
+ query_textbox = gr.Textbox(label="What topic would you like to create a course about?", placeholder="e.g. 'How to create your AI double'")
32
+ run_button = gr.Button("Run", variant="primary")
33
+ logs = gr.Textbox(label="Logs", placeholder="Logs will appear here")
34
+ report = gr.Markdown(label="Report")
35
+
36
+ run_button.click(fn=run, inputs=query_textbox, outputs=[report, logs])
37
+ query_textbox.submit(fn=run, inputs=query_textbox, outputs=[report, logs])
38
+
39
+ ui.launch(inbrowser=True)
curriculum_designer_agent.py ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Literal
2
+
3
+ from pydantic import BaseModel, Field
4
+
5
+ from agents import Agent
6
+
7
+
8
+ class CurriculumDesignerInstructions():
9
+ def name(self):
10
+ return "curriculum_designer"
11
+
12
+ def instructions(self):
13
+ return (
14
+ "You are a curriculum designer. Given a course outline, you design a curriculum for the course. \n"
15
+ "* Break it into logical modules and lessons. \n"
16
+ "* Define learning objectives for each module.\n"
17
+ "* Recommend prerequisites and progression flow. \n"
18
+ "* The curriculum should be a list of modules, each with a title, description, and a list of lessons. \n"
19
+ "* Each lesson should have a title, description, and a list of activities. \n"
20
+ "Each activity should have a title, description, and a list of resources. "
21
+ )
22
+
23
+ def handoff_description(self):
24
+ return self.instructions()
25
+
26
+ def model(self) -> Literal["gpt-4o-mini", "gpt-4o"]:
27
+ return "gpt-4o-mini"
28
+
29
+ class Activity(BaseModel):
30
+ """
31
+ Represents a learning activity within a lesson.
32
+
33
+ Attributes:
34
+ title (str): The name or heading of the activity
35
+ description (str): Detailed explanation of what the activity entails
36
+ """
37
+ title: str = Field(description="The title of the activity")
38
+ description: str = Field(description="The description of the activity")
39
+
40
+ class Lesson(BaseModel):
41
+ """
42
+ Represents a lesson within a module of the curriculum.
43
+
44
+ Attributes:
45
+ title (str): The name or heading of the lesson
46
+ description (str): Detailed explanation of the lesson content and objectives
47
+ activities (list[Activity]): Collection of learning activities that make up the lesson
48
+ """
49
+ title: str = Field(description="The title of the lesson")
50
+ description: str = Field(description="The description of the lesson")
51
+ activities: list[Activity] = Field(description="The list of activities in the lesson")
52
+
53
+ class Module(BaseModel):
54
+ """
55
+ Represents a module, which is a major section of the curriculum containing multiple lessons.
56
+
57
+ Attributes:
58
+ title (str): The name or heading of the module
59
+ description (str): Detailed explanation of the module's content and learning objectives
60
+ lessons (list[Lesson]): Collection of lessons that make up the module
61
+ """
62
+ title: str = Field(description="The title of the module")
63
+ description: str = Field(description="The description of the module")
64
+ lessons: list[Lesson] = Field(description="The list of lessons in the module")
65
+
66
+ class Curriculum(BaseModel):
67
+ """
68
+ Represents the complete curriculum structure for a course.
69
+
70
+ Attributes:
71
+ modules (list[Module]): Collection of all modules that make up the complete curriculum
72
+ """
73
+ modules: list[Module] = Field(description="The list of the modules of the course")
74
+
75
+
76
+ class CurriculumDesignerAgent():
77
+ def __init__(self):
78
+ instructions = CurriculumDesignerInstructions()
79
+ self.agent = Agent(
80
+ name=instructions.name(),
81
+ instructions=instructions.instructions(),
82
+ model=instructions.model(),
83
+ handoff_description=instructions.handoff_description(),
84
+ output_type=Curriculum,
85
+ )
86
+
87
+ def as_tool(self):
88
+ instructions = CurriculumDesignerInstructions()
89
+ return self.agent.as_tool(tool_name=instructions.name(), tool_description=instructions.handoff_description())
90
+
instruction_designer_agent.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Literal
2
+
3
+ from pydantic import BaseModel, Field
4
+
5
+ from agents import Agent
6
+
7
+
8
+ class InstructionDesignerInstructions():
9
+ def name(self):
10
+ return "instruction_designer"
11
+
12
+ def instructions(self):
13
+ return (
14
+ "You are an instructional designer agent. Your job is to turn curriculum outlines into engaging, "
15
+ "clear, and pedagogically sound lesson content. \n"
16
+ "For each lesson:"
17
+ "* Follow the learning objectives. \n"
18
+ "* Write explanations, examples, and step-by-step breakdowns. \n"
19
+ "* Incorporate analogies or visuals when appropriate (text description only). \n"
20
+ "* Keep tone aligned with the course level (beginner, intermediate, expert). \n"
21
+ "Do not generate quizzes or assessments. Pass structured lessons to the next agent."
22
+ )
23
+
24
+ def handoff_description(self):
25
+ return self.instructions()
26
+
27
+ def model(self) -> Literal["gpt-4o-mini", "gpt-4o"]:
28
+ return "gpt-4o-mini"
29
+
30
+ class Instruction(BaseModel):
31
+ title: str = Field(description="The title of the instruction")
32
+ description: str = Field(description="The description of the instruction")
33
+
34
+ class InstructionDesignerAgent():
35
+ def __init__(self):
36
+ instructions = InstructionDesignerInstructions()
37
+ self.agent = Agent(
38
+ name=instructions.name(),
39
+ instructions=instructions.instructions(),
40
+ model=instructions.model(),
41
+ handoff_description=instructions.handoff_description(),
42
+ output_type=Instruction,
43
+ )
44
+
45
+ def as_tool(self):
46
+ instructions = InstructionDesignerInstructions()
47
+ return self.agent.as_tool(tool_name=instructions.name(), tool_description=instructions.handoff_description())
instructor_assistant.egg-info/PKG-INFO ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ Metadata-Version: 2.4
2
+ Name: instructor-assistant
3
+ Version: 0.1.0
4
+ Summary: AI Agent helps instructors create lesson plans, course outline, exercise program... any resource needed for faster course preparation and execution.
5
+ Requires-Python: >=3.11
6
+ Requires-Dist: gradio>=5.49.1
7
+ Requires-Dist: python-dotenv>=1.2.1
8
+ Requires-Dist: openai[agents]>=1.54.0
9
+ Requires-Dist: pydantic>=2.11.10
10
+ Requires-Dist: openai-agents>=0.4.2
instructor_assistant.egg-info/SOURCES.txt ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ README.md
2
+ coordinator_agent.py
3
+ course_manager.py
4
+ curriculum_designer_agent.py
5
+ instruction_designer_agent.py
6
+ practice_designer_agent.py
7
+ pyproject.toml
8
+ qa_agent.py
9
+ instructor_assistant.egg-info/PKG-INFO
10
+ instructor_assistant.egg-info/SOURCES.txt
11
+ instructor_assistant.egg-info/dependency_links.txt
12
+ instructor_assistant.egg-info/requires.txt
13
+ instructor_assistant.egg-info/top_level.txt
instructor_assistant.egg-info/dependency_links.txt ADDED
@@ -0,0 +1 @@
 
 
1
+
instructor_assistant.egg-info/requires.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ gradio>=5.49.1
2
+ python-dotenv>=1.2.1
3
+ openai[agents]>=1.54.0
4
+ pydantic>=2.11.10
5
+ openai-agents>=0.4.2
instructor_assistant.egg-info/top_level.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ coordinator_agent
2
+ course_manager
3
+ curriculum_designer_agent
4
+ instruction_designer_agent
5
+ practice_designer_agent
6
+ qa_agent
practice_designer_agent.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Literal
2
+
3
+ from pydantic import BaseModel, Field
4
+
5
+ from agents import Agent
6
+
7
+
8
+ class PracticeDesignerInstructions():
9
+ def name(self):
10
+ return "practice_designer"
11
+
12
+ def instructions(self):
13
+ return (
14
+ "You are a test designer agent. Based on lesson content and learning objectives, you generate:\n"
15
+ "* Multiple choice questions (MCQs). \n"
16
+ "* Short-answer questions. \n"
17
+ "* Case-based or scenario-driven exercises (if applicable). \n"
18
+ "* Include answers and explanations for each item. \n"
19
+ "* Ensure difficulty aligns with the lesson level and purpose (formative or summative assessment). \n"
20
+ "* Ensure coverage of all critical concepts. \n"
21
+ )
22
+
23
+ def handoff_description(self):
24
+ return self.instructions()
25
+
26
+ def model(self) -> Literal["gpt-4o-mini", "gpt-4o"]:
27
+ return "gpt-4o-mini"
28
+
29
+ class Question(BaseModel):
30
+ question: str = Field(description="The question to be asked from the student")
31
+ answer: str = Field(description="The answer to the question")
32
+ explanation: str = Field(description="The explanation of the answer")
33
+
34
+ class Practice(BaseModel):
35
+ questions: list[Question]
36
+
37
+ class PracticeDesignerAgent():
38
+ def __init__(self):
39
+ instructions = PracticeDesignerInstructions()
40
+ self.agent = Agent(
41
+ name=instructions.name(),
42
+ instructions=instructions.instructions(),
43
+ model=instructions.model(),
44
+ handoff_description=instructions.handoff_description(),
45
+ output_type=Practice,
46
+ )
47
+
48
+ def as_tool(self):
49
+ instructions = PracticeDesignerInstructions()
50
+ return self.agent.as_tool(tool_name=instructions.name(), tool_description=instructions.handoff_description())
51
+
pyproject.toml ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [project]
2
+ name = "instructor-assistant"
3
+ version = "0.1.0"
4
+ description = "AI Agent helps instructors create lesson plans, course outline, exercise program... any resource needed for faster course preparation and execution."
5
+ requires-python = ">=3.11"
6
+ dependencies = [
7
+ "gradio>=5.49.1",
8
+ "python-dotenv>=1.2.1",
9
+ "openai[agents]>=1.54.0",
10
+ "pydantic>=2.11.10",
11
+ "openai-agents>=0.4.2",
12
+ ]
13
+
14
+ [build-system]
15
+ requires = ["setuptools>=61.0", "wheel"]
16
+ build-backend = "setuptools.build_meta"
17
+
18
+ [tool.setuptools]
19
+ py-modules = ["coordinator_agent", "course_manager", "curriculum_designer_agent", "instruction_designer_agent", "practice_designer_agent", "qa_agent"]
20
+
qa_agent.py ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Literal
2
+
3
+ from pydantic import BaseModel, Field
4
+
5
+ from agents import Agent
6
+
7
+
8
+ class QAAgentInstructions():
9
+ def name(self):
10
+ return "qa_agent"
11
+
12
+ def instructions(self):
13
+ return (
14
+ "You are a QA agent. Your job is to review the lesson content and practice activities to ensure \n"
15
+ "they are aligned with the learning objectives and are appropriate for the course level. \n"
16
+ "For each lesson: \n"
17
+ "* Review the lesson content and practice activities. \n"
18
+ "* Ensure they are aligned with the learning objectives and are appropriate for the course level. \n"
19
+ "* Ensure they are appropriate for the course level. \n"
20
+ "Return a JSON that matches the QualityAssurance model with the following fields: \n"
21
+ "* is_satisfied: Whether the course is satisfied with the quality \n"
22
+ "* reason: The reason if the satisfied or not, if not it should mention the step that needs to be improved \n"
23
+ )
24
+
25
+ def handoff_description(self):
26
+ return self.instructions()
27
+
28
+ def model(self) -> Literal["gpt-4o-mini", "gpt-4o"]:
29
+ return "gpt-4o-mini"
30
+
31
+ class QualityAssurance(BaseModel):
32
+ is_satisfied: bool = Field(description="Whether the course is satisfied with the quality")
33
+ reason: str = Field(description="The reason if the satisfied or not, if not it should mention the step that needs to be improved")
34
+
35
+ class QAAgent():
36
+ def __init__(self):
37
+ instructions = QAAgentInstructions()
38
+ self.agent = Agent(
39
+ name=instructions.name(),
40
+ instructions=instructions.instructions(),
41
+ model="gpt-4o-mini",
42
+ handoff_description=instructions.handoff_description(),
43
+ output_type=QualityAssurance,
44
+ )
45
+
46
+
47
+ def as_tool(self):
48
+ instructions = QAAgentInstructions()
49
+ return self.agent.as_tool(tool_name=instructions.name(), tool_description=instructions.handoff_description())
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ # Main dependencies
2
+ gradio>=5.49.1
3
+ python-dotenv>=1.2.1
4
+ openai[agents]>=1.54.0
5
+ openai-agents>=0.4.2
6
+ pydantic>=2.11.10
7
+
uv.lock ADDED
The diff for this file is too large to render. See raw diff