joelazo commited on
Commit
57058ca
·
1 Parent(s): 854cd25

Streamlined code, added a clear button and updated the agent instructions. Also updated the environment to make it HuggingFace-GitHub friendly

Browse files
README.md CHANGED
@@ -1,6 +1,6 @@
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
 
@@ -50,3 +50,168 @@ Create a `.env` file in the project root with your OpenAI API key:
50
  ```
51
  OPENAI_API_KEY=your_api_key_here
52
  ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Instructor Assistant
2
 
3
+ An AI-powered multi-agent system that helps instructors create comprehensive course content including lesson plans, curriculum outlines, practice exercises, and quality assurance. The system uses OpenAI's Agent Framework to orchestrate specialized agents that collaborate to produce complete, well-structured course materials.
4
 
5
  ## Setup with UV
6
 
 
50
  ```
51
  OPENAI_API_KEY=your_api_key_here
52
  ```
53
+
54
+ ## Architecture
55
+
56
+ The application follows a multi-agent architecture where specialized agents collaborate to create comprehensive course content. Each agent is responsible for a specific aspect of course design.
57
+
58
+ ### Module Overview
59
+
60
+ #### 1. **coordinator_agent.py** - Main Orchestrator
61
+ The coordinator agent manages the entire course creation workflow by orchestrating all specialized agents.
62
+
63
+ **Key Components:**
64
+ - `CoordinatorAgent`: Main orchestrator that coordinates the workflow
65
+ - `Course`: Pydantic model representing the complete course with curriculum, instruction, practice, and QA
66
+ - `CoordinatorInstructions`: Defines the workflow and agent responsibilities
67
+
68
+ **Responsibilities:**
69
+ 1. Delegates curriculum design to CurriculumDesignerAgent
70
+ 2. Delegates instruction design to InstructionDesignerAgent
71
+ 3. Delegates practice exercise creation to PracticeDesignerAgent
72
+ 4. Delegates quality assurance to QAAgent
73
+ 5. Restarts the workflow if QA agent is not satisfied
74
+ 6. Generates final course plan
75
+
76
+ #### 2. **curriculum_designer_agent.py** - Curriculum Designer
77
+ Creates the structured curriculum with modules, lessons, and activities.
78
+
79
+ **Key Components:**
80
+ - `CurriculumDesignerAgent`: Designs the overall curriculum structure
81
+ - `Curriculum`: Pydantic model representing the complete curriculum
82
+ - `Module`: Represents a major section containing multiple lessons
83
+ - `Lesson`: Represents a lesson containing multiple activities
84
+ - `Activity`: Represents a learning activity within a lesson
85
+
86
+ **Responsibilities:**
87
+ - Break topics into logical modules and lessons
88
+ - Define learning objectives for each module
89
+ - Recommend prerequisites and progression flow
90
+ - Structure content hierarchically (modules → lessons → activities)
91
+
92
+ #### 3. **instruction_designer_agent.py** - Instruction Designer
93
+ Creates engaging and pedagogically sound lesson content.
94
+
95
+ **Key Components:**
96
+ - `InstructionDesignerAgent`: Designs instructional content
97
+ - `Instruction`: Pydantic model with title and description
98
+
99
+ **Responsibilities:**
100
+ - Transform curriculum outlines into detailed lesson content
101
+ - Write clear explanations, examples, and step-by-step breakdowns
102
+ - Incorporate pedagogical best practices
103
+ - Maintain appropriate tone for course level
104
+
105
+ #### 4. **practice_designer_agent.py** - Practice Exercise Creator
106
+ Generates practice exercises and assessments for students.
107
+
108
+ **Key Components:**
109
+ - `PracticeDesignerAgent`: Creates practice exercises
110
+ - `Practice`: Pydantic model containing questions
111
+ - `Question`: Individual question with answer and explanation
112
+
113
+ **Responsibilities:**
114
+ - Generate multiple choice questions (MCQs)
115
+ - Create short-answer questions
116
+ - Design case-based and scenario-driven exercises
117
+ - Provide answers and explanations for all items
118
+ - Align difficulty with lesson level
119
+
120
+ #### 5. **qa_agent.py** - Quality Assurance
121
+ Ensures the course content meets quality standards and learning objectives.
122
+
123
+ **Key Components:**
124
+ - `QAAgent`: Reviews course quality
125
+ - `QualityAssurance`: Pydantic model with satisfaction status and feedback
126
+
127
+ **Responsibilities:**
128
+ - Review lesson content and practice activities
129
+ - Verify alignment with learning objectives
130
+ - Ensure appropriate difficulty level
131
+ - Identify areas needing improvement
132
+ - Trigger workflow restart if quality standards aren't met
133
+
134
+ #### 6. **course_manager.py** - User Interface
135
+ Gradio-based web interface for interacting with the assistant.
136
+
137
+ **Key Features:**
138
+ - Simple, modern UI built with Gradio
139
+ - Real-time streaming of AI responses
140
+ - Logs textbox (5 lines visible before scrollbar)
141
+ - Interactive course plan display
142
+ - Run and Clear buttons for easy interaction
143
+ - Clear button dynamically enabled only when query text is present
144
+ - Increased max_turns (30) to handle complex multi-agent workflows
145
+
146
+ **Usage Flow:**
147
+ 1. User enters a course topic
148
+ 2. System generates curriculum, instruction, practice exercises
149
+ 3. QA agent reviews the content
150
+ 4. If quality is met, final course plan is displayed
151
+ 5. If not, the process repeats with improvements
152
+
153
+ ## Agent Workflow
154
+
155
+ ```
156
+ User Input → Coordinator Agent
157
+
158
+ CurriculumDesignerAgent (Step 1: Design curriculum structure)
159
+
160
+ InstructionDesignerAgent (Step 2: Create lesson content)
161
+
162
+ PracticeDesignerAgent (Step 3: Create practice exercises)
163
+
164
+ QAAgent (Step 4: Quality assurance)
165
+
166
+ [If QA fails, restart from appropriate step]
167
+
168
+ Final Course Plan
169
+ ```
170
+
171
+ ## Data Models
172
+
173
+ All agents use Pydantic models for structured data validation and type safety:
174
+ - **Curriculum**: Hierarchical structure with modules, lessons, and activities
175
+ - **Instruction**: Lesson content with title and description
176
+ - **Practice**: Collection of questions with answers and explanations
177
+ - **QualityAssurance**: QA status with satisfaction flag and feedback
178
+ - **Course**: Complete course containing all components
179
+
180
+ ## Technology Stack
181
+
182
+ - **Python 3.11+**: Core programming language
183
+ - **UV**: Fast Python package manager and project management
184
+ - **OpenAI Agents Framework**: Multi-agent orchestration and tool calling
185
+ - **OpenAI API**: GPT-4o-mini for agent reasoning
186
+ - **Pydantic**: Data validation and type safety
187
+ - **Gradio 4.44.1**: Web-based user interface
188
+ - **Hugging Face Hub**: Deployment platform integration
189
+ - **Python-dotenv**: Environment variable management
190
+
191
+ ## Dependencies
192
+
193
+ Main dependencies (see `requirements.txt` or `pyproject.toml`):
194
+ - `gradio==4.44.1` - Web UI framework
195
+ - `python-dotenv==1.2.1` - Environment variable management
196
+ - `openai==2.6.1` - OpenAI API client
197
+ - `pydantic==2.11.10` - Data validation and type safety
198
+ - `mailjet-rest==1.5.1` - Email integration (optional)
199
+ - `openai-agents>=0.4.2` - Multi-agent orchestration
200
+ - `huggingface-hub==0.22.2` - Hugging Face Spaces deployment support
201
+ - `typer>=0.20.0` - CLI interface (optional)
202
+
203
+ **Note:** Requirements are pinned to specific versions for Hugging Face Spaces deployment compatibility.
204
+
205
+ ## Deployment
206
+
207
+ ### Hugging Face Spaces
208
+
209
+ This project is configured for easy deployment to Hugging Face Spaces with GitHub repository sync:
210
+
211
+ 1. **Create a new Space** on [Hugging Face](https://huggingface.co/spaces)
212
+ 2. **Connect your GitHub repository** to the Space
213
+ 3. **Set environment variables** in the Space settings:
214
+ - `OPENAI_API_KEY`: Your OpenAI API key
215
+ 4. **Enable automatic deployment** - the Space will sync with your GitHub repository
216
+
217
+ The `requirements.txt` file is configured with pinned versions compatible with Hugging Face Spaces. The Gradio app will automatically launch when deployed.
__pycache__/coordinator_agent.cpython-312.pyc CHANGED
Binary files a/__pycache__/coordinator_agent.cpython-312.pyc and b/__pycache__/coordinator_agent.cpython-312.pyc differ
 
__pycache__/curriculum_designer_agent.cpython-312.pyc CHANGED
Binary files a/__pycache__/curriculum_designer_agent.cpython-312.pyc and b/__pycache__/curriculum_designer_agent.cpython-312.pyc differ
 
__pycache__/qa_agent.cpython-312.pyc CHANGED
Binary files a/__pycache__/qa_agent.cpython-312.pyc and b/__pycache__/qa_agent.cpython-312.pyc differ
 
coordinator_agent.py CHANGED
@@ -1,35 +1,25 @@
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
 
@@ -38,13 +28,6 @@ class CoordinatorInstructions():
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():
@@ -76,4 +59,7 @@ class CoordinatorAgent():
76
 
77
  def as_tool(self):
78
  instructions = CoordinatorInstructions()
79
- return self.agent.as_tool(tool_name=instructions.name(), tool_description=instructions.handoff_description())
 
 
 
 
1
  from typing import Literal
2
 
3
+ from curriculum_designer_agent import CurriculumDesignerAgent
4
+ from instruction_designer_agent import InstructionDesignerAgent
5
+ from practice_designer_agent import PracticeDesignerAgent
6
+ from qa_agent import QAAgent
 
7
 
8
  from agents import Agent
9
 
 
 
 
 
 
 
 
 
 
 
10
  class CoordinatorInstructions():
11
  def name(self):
12
  return "coordinator"
13
 
14
  def instructions(self):
15
  return (
16
+ "You are an coordinator agent, you are responsible for coordinating the course instruction flow. "
17
+ "1. First the curriculum designer agent will design the curriculum. "
18
+ "2. Then the instruction designer must design the course instruction. "
19
+ "3. Then the practice designer must design the practice exercises. "
20
+ "4. Then the QA agent must assure that this course has the right quality. "
21
+ "\tIf it doesn't have the right quality, you should start the flow again from "
22
+ "\tthe step the qa agent wasn't satisfied with. "
23
  "5. In the end based on all of the information provided to you in above steps, write a clear and concise course plan."
24
  )
25
 
 
28
 
29
  def model(self) -> Literal["gpt-4o-mini", "gpt-4o"]:
30
  return "gpt-4o-mini"
 
 
 
 
 
 
 
31
 
32
 
33
  class CoordinatorAgent():
 
59
 
60
  def as_tool(self):
61
  instructions = CoordinatorInstructions()
62
+ return self.agent.as_tool(
63
+ tool_name=instructions.name(),
64
+ tool_description=instructions.handoff_description()
65
+ )
course_manager.py CHANGED
@@ -9,7 +9,7 @@ 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():
@@ -26,14 +26,24 @@ async def run(query: str):
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)
 
9
 
10
  async def run(query: str):
11
  coordinator_agent = CoordinatorAgent().get_agent()
12
+ result = Runner.run_streamed(coordinator_agent, input=query, max_turns=30)
13
  response = ""
14
  status = ""
15
  async for event in result.stream_events():
 
26
  status += log_msg
27
  yield response, status
28
 
29
+ def clear_fields():
30
+ return "", ""
31
+
32
+ def update_clear_button(query: str):
33
+ return gr.update(interactive=bool(query.strip()))
34
+
35
+ with gr.Blocks(theme=gr.themes.Glass(primary_hue="fuchsia")) as ui:
36
  gr.Markdown("# Course Instructor Assistant")
37
  query_textbox = gr.Textbox(label="What topic would you like to create a course about?", placeholder="e.g. 'How to create your AI double'")
38
+ with gr.Row():
39
+ run_button = gr.Button("Run", variant="primary")
40
+ clear_button = gr.Button("Clear", variant="secondary", interactive=False)
41
+ logs = gr.Textbox(label="Logs", placeholder="Logs will appear here", lines=5)
42
  report = gr.Markdown(label="Report")
43
+
44
  run_button.click(fn=run, inputs=query_textbox, outputs=[report, logs])
45
  query_textbox.submit(fn=run, inputs=query_textbox, outputs=[report, logs])
46
+ clear_button.click(fn=clear_fields, outputs=[query_textbox, logs])
47
+ query_textbox.change(fn=update_clear_button, inputs=query_textbox, outputs=clear_button)
48
 
49
+ ui.launch(share=True, inbrowser=True)
curriculum_designer_agent.py CHANGED
@@ -14,10 +14,14 @@ class CurriculumDesignerInstructions():
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):
 
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
+ "* There should be a minimum of 3 modules and a maximum of 5 modules. \n"
18
+ "* Each module should have a minimum of 3 lessons and a maximum of 5 lessons. \n"
19
+ "* Each lesson should have a minimum of 3 activities and a maximum of 5 activities. \n"
20
+ "* Each activity should have a minimum of 2 resources and a maximum of 5 resources. \n"
21
  "* The curriculum should be a list of modules, each with a title, description, and a list of lessons. \n"
22
  "* Each lesson should have a title, description, and a list of activities. \n"
23
+ "* Each activity should have a title, description, and a list of resources. \n"
24
+ "* Recommend prerequisites and progression flow. \n"
25
  )
26
 
27
  def handoff_description(self):
qa_agent.py CHANGED
@@ -16,7 +16,6 @@ class QAAgentInstructions():
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"
@@ -38,7 +37,7 @@ class QAAgent():
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
  )
 
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
  "Return a JSON that matches the QualityAssurance model with the following fields: \n"
20
  "* is_satisfied: Whether the course is satisfied with the quality \n"
21
  "* reason: The reason if the satisfied or not, if not it should mention the step that needs to be improved \n"
 
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=QualityAssurance,
43
  )
requirements.txt CHANGED
@@ -1,7 +1,9 @@
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
-
 
1
  # Main dependencies
2
+ gradio==4.44.1
3
+ python-dotenv==1.2.1
4
+ openai==2.6.1
5
+ pydantic==2.11.10
6
+ mailjet-rest==1.5.1
7
  openai-agents>=0.4.2
8
+ huggingface-hub==0.22.2
9
+ typer>=0.20.0