Khanmx99 commited on
Commit
cebd780
·
verified ·
1 Parent(s): 75f5e82

Deploy Pak Angels AI Tutor

Browse files
Files changed (10) hide show
  1. .env.example +4 -0
  2. .gitignore +19 -0
  3. README.md +208 -7
  4. app.py +292 -0
  5. config.py +20 -0
  6. deploy_requirements.txt +1 -0
  7. deploy_to_huggingface.py +205 -0
  8. openai_service.py +62 -0
  9. prompts.py +360 -0
  10. requirements.txt +2 -0
.env.example ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ OPENAI_API_KEY=your_openai_api_key_here
2
+ OPENAI_MODEL=your_preferred_model_here
3
+ HF_TOKEN=your_hugging_face_write_token_here
4
+ HF_SPACE_ID=your-username/your-space-name
.gitignore ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .env
2
+ .venv/
3
+ venv/
4
+ __pycache__/
5
+ *.py[cod]
6
+ *$py.class
7
+ .Python
8
+ .DS_Store
9
+ .cache/
10
+ .huggingface/
11
+ .pytest_cache/
12
+ .ruff_cache/
13
+ .mypy_cache/
14
+ dist/
15
+ build/
16
+ *.egg-info/
17
+ *.log
18
+ tmp/
19
+ temp/
README.md CHANGED
@@ -1,14 +1,215 @@
1
  ---
2
  title: Pak Angels AI Tutor
3
- emoji: 🌍
4
- colorFrom: green
5
- colorTo: green
6
  sdk: gradio
7
- sdk_version: 6.20.0
8
- python_version: '3.12'
9
  app_file: app.py
10
  pinned: false
11
- short_description: Pak Angels AI Tutoring Platform
12
  ---
13
 
14
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
  title: Pak Angels AI Tutor
3
+ emoji: 🎓
4
+ colorFrom: blue
5
+ colorTo: indigo
6
  sdk: gradio
7
+ sdk_version: 5.50.0
 
8
  app_file: app.py
9
  pinned: false
 
10
  ---
11
 
12
+ # Pak Angels AI Tutor
13
+
14
+ Pak Angels AI Tutor is an AI-powered learning companion for the Pak Angels AI
15
+ Training Program. It helps students, faculty, researchers, professionals,
16
+ entrepreneurs, startup founders, AI developers, business leaders, and innovation
17
+ teams learn Artificial Intelligence, build practical applications, design
18
+ intelligent workflows, automate business processes, and develop AI-powered
19
+ startups.
20
+
21
+ The app is built with Gradio and the official OpenAI Python SDK. It is
22
+ prepared for functional testing and demonstration on Hugging Face Spaces.
23
+
24
+ ## Features
25
+
26
+ - Clean blue-and-white Pak Angels visual identity
27
+ - Sidebar navigation with specialized learning modes
28
+ - Selected learning-mode label above the conversation area
29
+ - Streaming AI responses through the OpenAI Responses API
30
+ - Session-based chat history
31
+ - Suggested-question buttons for every learning mode
32
+ - New Conversation and Clear Chat controls
33
+ - Markdown rendering and syntax-highlighted code blocks
34
+ - Clear missing-key and OpenAI API error messages
35
+ - Privacy notice for sensitive information
36
+ - Hugging Face Spaces-compatible environment-variable configuration
37
+
38
+ ## Learning Modules
39
+
40
+ - Home
41
+ - AI-101 Foundations
42
+ - Prompt Engineering
43
+ - Generative AI
44
+ - Agentic AI
45
+ - Retrieval-Augmented Generation (RAG)
46
+ - Multi-Agent Systems
47
+ - AI Workflow Design
48
+ - Business Process Automation
49
+ - Gradio Development
50
+ - AI Startup Mentor
51
+ - About Pak Angels
52
+
53
+ ## Local Setup
54
+
55
+ Local setup is optional. Hugging Face Spaces can run the app directly from these
56
+ files.
57
+
58
+ 1. Create a virtual environment:
59
+
60
+ ```bash
61
+ python -m venv .venv
62
+ ```
63
+
64
+ 2. Activate the virtual environment:
65
+
66
+ ```bash
67
+ source .venv/bin/activate
68
+ ```
69
+
70
+ 3. Install dependencies:
71
+
72
+ ```bash
73
+ pip install -r requirements.txt
74
+ ```
75
+
76
+ 4. Configure environment variables:
77
+
78
+ ```bash
79
+ cp .env.example .env
80
+ ```
81
+
82
+ Add your real key only to `.env` or your shell environment. Do not commit
83
+ `.env`.
84
+
85
+ 5. Run the app:
86
+
87
+ ```bash
88
+ python app.py
89
+ ```
90
+
91
+ ## Hugging Face Spaces Deployment
92
+
93
+ 1. Create a Hugging Face account.
94
+ 2. Create a new Space.
95
+ 3. Select Gradio as the application SDK if available.
96
+ 4. Choose the desired visibility.
97
+ 5. Upload or push all project files from this folder.
98
+ 6. Open the Space Settings.
99
+ 7. Go to Variables and secrets.
100
+ 8. Add a new secret named `OPENAI_API_KEY`.
101
+ 9. Optionally add `OPENAI_MODEL`.
102
+ 10. Allow Hugging Face to build the application.
103
+ 11. Review build logs if deployment fails.
104
+ 12. Open the Space URL and test all learning modes.
105
+
106
+ To update the Space, replace the files through the Hugging Face web interface or
107
+ push changes through Git. Hugging Face will rebuild the Space after new changes
108
+ are uploaded.
109
+
110
+ ### Deploy With the Hugging Face Hub API
111
+
112
+ This project includes `deploy_to_huggingface.py`, which uploads the current
113
+ project folder to a Hugging Face Space using the Hugging Face Hub API.
114
+
115
+ Install the deployment helper dependency locally:
116
+
117
+ ```bash
118
+ python3 -m pip install -r deploy_requirements.txt
119
+ ```
120
+
121
+ Set the Hugging Face deployment credentials in your local environment:
122
+
123
+ ```bash
124
+ export HF_TOKEN=your_hugging_face_write_token_here
125
+ export HF_SPACE_ID=your-username/your-space-name
126
+ ```
127
+
128
+ Use your real Hugging Face username and Space name. Do not leave
129
+ `your-username/your-space-name` in the command.
130
+
131
+ Then upload the project to an existing Space:
132
+
133
+ ```bash
134
+ python3 deploy_to_huggingface.py
135
+ ```
136
+
137
+ If the Space does not exist yet, create it as a Gradio Space and upload in one
138
+ step:
139
+
140
+ ```bash
141
+ python3 deploy_to_huggingface.py --create
142
+ ```
143
+
144
+ You can also pass the Space id directly:
145
+
146
+ ```bash
147
+ python3 deploy_to_huggingface.py --space-id your-username/your-space-name --create
148
+ ```
149
+
150
+ The script excludes local-only files such as `.env`, `.venv/`, caches, logs, and
151
+ compiled Python files. It does not create or upload OpenAI secrets. Add
152
+ `OPENAI_API_KEY` separately in the Space settings.
153
+
154
+ ## Required Hugging Face Secret
155
+
156
+ The required secret name is:
157
+
158
+ ```text
159
+ OPENAI_API_KEY
160
+ ```
161
+
162
+ Optional:
163
+
164
+ ```text
165
+ OPENAI_MODEL
166
+ ```
167
+
168
+ Never upload a `.env` file containing a real API key to Hugging Face Spaces.
169
+
170
+ ## Troubleshooting
171
+
172
+ Missing API key: Add `OPENAI_API_KEY` under Hugging Face Space -> Settings ->
173
+ Variables and secrets -> New secret, then restart or rebuild the Space.
174
+
175
+ Quota exceeded or billing errors: Check OpenAI usage limits, billing settings,
176
+ and project access. The app will show a clear message for rate limits and quota
177
+ related API failures.
178
+
179
+ Dependency installation errors: Confirm `requirements.txt` is present in the
180
+ Space root folder and that the Space is using Python with Gradio support.
181
+
182
+ Python version problems: Use a current Hugging Face Gradio environment. The
183
+ code uses standard cross-platform Python and avoids Mac-specific paths.
184
+
185
+ Missing assets: The app does not require local image assets. Optional future
186
+ assets should use relative paths and should be committed with the app.
187
+
188
+ OpenAI API errors: Check the API key, selected model, quota, billing, and build
189
+ logs. If using `OPENAI_MODEL`, verify that the account has access to the model.
190
+
191
+ Gradio startup failures: Make sure `app.py` exists at the Space root. For local
192
+ testing, run `python app.py`.
193
+
194
+ Hugging Face build failures: Review the Space build logs, confirm all required
195
+ files are uploaded, and check that only necessary dependencies are listed.
196
+
197
+ ## Security
198
+
199
+ - API keys must never be committed to Git.
200
+ - API keys must never be placed directly in `app.py`.
201
+ - Real secrets must not be placed in `.env.example`.
202
+ - Users should not enter confidential, proprietary, financial, medical,
203
+ personal, or otherwise sensitive information into the tutor.
204
+
205
+ ## Architecture
206
+
207
+ - `app.py`: Gradio interface, navigation, chat state, and page rendering
208
+ - `config.py`: environment-variable configuration
209
+ - `prompts.py`: learning modules, suggested questions, and specialized tutor instructions
210
+ - `openai_service.py`: OpenAI Responses API streaming integration and error handling
211
+ - `requirements.txt`: deployment dependencies
212
+ - `deploy_to_huggingface.py`: Hugging Face Hub API upload script
213
+ - `deploy_requirements.txt`: local-only dependency for the upload script
214
+ - `.env.example`: safe placeholder environment variables
215
+ - `.gitignore`: local secrets and development artifact exclusions
app.py ADDED
@@ -0,0 +1,292 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from functools import partial
4
+
5
+ import gradio as gr
6
+
7
+ from config import APP_NAME, APP_SUBTITLE, get_openai_api_key, get_openai_model
8
+ from openai_service import format_openai_error, stream_tutor_response
9
+ from prompts import ABOUT_PAK_ANGELS, MODULES, build_system_instructions
10
+
11
+
12
+ PRIVACY_NOTICE = (
13
+ "Privacy notice: Do not enter confidential, proprietary, financial, medical, "
14
+ "personal, or otherwise sensitive information into the AI Tutor."
15
+ )
16
+
17
+
18
+ CSS = """
19
+ :root {
20
+ --pak-blue: #0b5cab;
21
+ --pak-blue-dark: #073f78;
22
+ --pak-blue-soft: #eaf4ff;
23
+ --pak-line: #d8e5f2;
24
+ --pak-text: #14213d;
25
+ }
26
+ body,
27
+ .gradio-container {
28
+ background: #f7fbff !important;
29
+ color: var(--pak-text);
30
+ }
31
+ .main-shell {
32
+ max-width: 1180px;
33
+ margin: 0 auto;
34
+ }
35
+ .hero {
36
+ background: linear-gradient(135deg, #ffffff 0%, #eaf4ff 62%, #d6ebff 100%);
37
+ border: 1px solid var(--pak-line);
38
+ border-radius: 8px;
39
+ padding: 24px;
40
+ margin-bottom: 14px;
41
+ }
42
+ .hero h1 {
43
+ color: var(--pak-blue-dark);
44
+ font-size: 38px;
45
+ line-height: 1.1;
46
+ margin: 0 0 8px 0;
47
+ }
48
+ .hero p {
49
+ margin: 5px 0;
50
+ font-size: 16px;
51
+ }
52
+ .mode-label {
53
+ border-left: 5px solid var(--pak-blue);
54
+ background: #ffffff;
55
+ border-radius: 8px;
56
+ padding: 14px 16px;
57
+ box-shadow: 0 1px 4px rgba(11, 92, 171, 0.08);
58
+ }
59
+ .privacy {
60
+ background: #fff8e8;
61
+ border: 1px solid #f1d28c;
62
+ border-radius: 8px;
63
+ padding: 12px 14px;
64
+ font-size: 14px;
65
+ }
66
+ .side-panel {
67
+ background: #ffffff;
68
+ border: 1px solid var(--pak-line);
69
+ border-radius: 8px;
70
+ padding: 14px;
71
+ }
72
+ .suggestion-button {
73
+ min-height: 46px;
74
+ }
75
+ button.primary {
76
+ background: var(--pak-blue) !important;
77
+ border-color: var(--pak-blue) !important;
78
+ }
79
+ """
80
+
81
+
82
+ def hero_html() -> str:
83
+ return f"""
84
+ <div class="hero">
85
+ <h1>{APP_NAME}</h1>
86
+ <p><strong>{APP_SUBTITLE}</strong></p>
87
+ <p>Pak Angels AI Tutor helps students, faculty, professionals,
88
+ entrepreneurs, and startup founders learn Artificial Intelligence,
89
+ build practical applications, design intelligent workflows, automate
90
+ business processes, and develop AI-powered startups.</p>
91
+ </div>
92
+ """
93
+
94
+
95
+ def module_summary_html(module_name: str) -> str:
96
+ module = MODULES[module_name]
97
+ about = ""
98
+ if module_name == "About Pak Angels":
99
+ about = f"<p>{ABOUT_PAK_ANGELS}</p>"
100
+ return f"""
101
+ <div class="mode-label">
102
+ <strong>Selected learning mode:</strong> {module_name}<br>
103
+ <span>{module["summary"]}</span>
104
+ {about}
105
+ </div>
106
+ """
107
+
108
+
109
+ def topics_markdown(module_name: str) -> str:
110
+ topics = "\n".join(f"- {topic}" for topic in MODULES[module_name]["topics"])
111
+ return f"### Topics in this mode\n{topics}"
112
+
113
+
114
+ def get_suggestion(module_name: str, index: int) -> str:
115
+ suggestions = MODULES[module_name]["suggestions"]
116
+ return suggestions[index] if index < len(suggestions) else ""
117
+
118
+
119
+ def update_module(module_name: str):
120
+ suggestions = MODULES[module_name]["suggestions"]
121
+ button_updates = [
122
+ gr.update(value=suggestion, visible=True) for suggestion in suggestions[:5]
123
+ ]
124
+ while len(button_updates) < 5:
125
+ button_updates.append(gr.update(value="", visible=False))
126
+
127
+ return (
128
+ module_summary_html(module_name),
129
+ topics_markdown(module_name),
130
+ *button_updates,
131
+ )
132
+
133
+
134
+ def add_user_message(message: str, history: list[dict[str, str]] | None):
135
+ history = list(history or [])
136
+ message = (message or "").strip()
137
+ if not message:
138
+ return "", history
139
+ history.append({"role": "user", "content": message})
140
+ return "", history
141
+
142
+
143
+ def generate_response(history: list[dict[str, str]] | None, module_name: str):
144
+ history = list(history or [])
145
+ if not history or history[-1]["role"] != "user":
146
+ yield history
147
+ return
148
+
149
+ api_key = get_openai_api_key()
150
+ if not api_key:
151
+ message = (
152
+ "OPENAI_API_KEY is not configured. In Hugging Face Spaces, add it under "
153
+ "Settings -> Variables and secrets -> New secret, then restart the Space."
154
+ )
155
+ history.append({"role": "assistant", "content": message})
156
+ yield history
157
+ return
158
+
159
+ history.append({"role": "assistant", "content": ""})
160
+ try:
161
+ for delta in stream_tutor_response(
162
+ api_key=api_key,
163
+ model=get_openai_model(),
164
+ system_instructions=build_system_instructions(module_name),
165
+ messages=history[:-1],
166
+ ):
167
+ history[-1]["content"] += delta
168
+ yield history
169
+ except Exception as error:
170
+ history[-1]["content"] = format_openai_error(error)
171
+ yield history
172
+
173
+
174
+ def submit_message(message: str, history: list[dict[str, str]] | None, module_name: str):
175
+ textbox, updated_history = add_user_message(message, history)
176
+ yield textbox, updated_history
177
+ for streamed_history in generate_response(updated_history, module_name):
178
+ yield textbox, streamed_history
179
+
180
+
181
+ def submit_suggestion(
182
+ suggestion_index: int,
183
+ history: list[dict[str, str]] | None,
184
+ module_name: str,
185
+ ):
186
+ question = get_suggestion(module_name, suggestion_index)
187
+ yield from submit_message(question, history, module_name)
188
+
189
+
190
+ def clear_conversation():
191
+ return []
192
+
193
+
194
+ def build_app() -> gr.Blocks:
195
+ with gr.Blocks(
196
+ title=APP_NAME,
197
+ css=CSS,
198
+ theme=gr.themes.Soft(primary_hue="blue", neutral_hue="slate"),
199
+ ) as demo:
200
+ with gr.Column(elem_classes=["main-shell"]):
201
+ gr.HTML(hero_html())
202
+
203
+ with gr.Row(equal_height=False):
204
+ with gr.Column(scale=1, min_width=260, elem_classes=["side-panel"]):
205
+ module_selector = gr.Radio(
206
+ choices=list(MODULES.keys()),
207
+ value="Home",
208
+ label="Learning mode",
209
+ )
210
+ gr.Textbox(
211
+ value=get_openai_model(),
212
+ label="OpenAI model",
213
+ interactive=False,
214
+ )
215
+ new_button = gr.Button("New Conversation")
216
+ clear_button = gr.Button("Clear Chat")
217
+ with gr.Accordion("About Pak Angels", open=False):
218
+ gr.Markdown(ABOUT_PAK_ANGELS)
219
+
220
+ with gr.Column(scale=3, min_width=420):
221
+ module_summary = gr.HTML(module_summary_html("Home"))
222
+ gr.HTML(f'<div class="privacy">{PRIVACY_NOTICE}</div>')
223
+ topics = gr.Markdown(topics_markdown("Home"))
224
+
225
+ gr.Markdown("### Suggested questions")
226
+ suggestion_buttons = []
227
+ with gr.Row():
228
+ suggestion_buttons.append(
229
+ gr.Button(get_suggestion("Home", 0), elem_classes=["suggestion-button"])
230
+ )
231
+ suggestion_buttons.append(
232
+ gr.Button(get_suggestion("Home", 1), elem_classes=["suggestion-button"])
233
+ )
234
+ with gr.Row():
235
+ suggestion_buttons.append(
236
+ gr.Button(get_suggestion("Home", 2), elem_classes=["suggestion-button"])
237
+ )
238
+ suggestion_buttons.append(
239
+ gr.Button(get_suggestion("Home", 3), elem_classes=["suggestion-button"])
240
+ )
241
+ suggestion_buttons.append(
242
+ gr.Button(get_suggestion("Home", 4), elem_classes=["suggestion-button"])
243
+ )
244
+
245
+ chatbot = gr.Chatbot(
246
+ label="Pak Angels AI Tutor",
247
+ type="messages",
248
+ height=520,
249
+ show_copy_button=True,
250
+ )
251
+ message_box = gr.Textbox(
252
+ label="Ask Pak Angels AI Tutor",
253
+ placeholder="Ask a question or choose a suggested question above.",
254
+ lines=3,
255
+ )
256
+ send_button = gr.Button("Send", variant="primary")
257
+
258
+ module_selector.change(
259
+ update_module,
260
+ inputs=[module_selector],
261
+ outputs=[module_summary, topics, *suggestion_buttons],
262
+ )
263
+
264
+ send_button.click(
265
+ submit_message,
266
+ inputs=[message_box, chatbot, module_selector],
267
+ outputs=[message_box, chatbot],
268
+ )
269
+ message_box.submit(
270
+ submit_message,
271
+ inputs=[message_box, chatbot, module_selector],
272
+ outputs=[message_box, chatbot],
273
+ )
274
+
275
+ for index, button in enumerate(suggestion_buttons):
276
+ button.click(
277
+ partial(submit_suggestion, index),
278
+ inputs=[chatbot, module_selector],
279
+ outputs=[message_box, chatbot],
280
+ )
281
+
282
+ new_button.click(clear_conversation, outputs=[chatbot])
283
+ clear_button.click(clear_conversation, outputs=[chatbot])
284
+
285
+ return demo
286
+
287
+
288
+ demo = build_app()
289
+
290
+
291
+ if __name__ == "__main__":
292
+ demo.queue().launch()
config.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Application configuration for Pak Angels AI Tutor."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+
7
+
8
+ APP_NAME = "Pak Angels AI Tutor"
9
+ APP_SUBTITLE = "Learn • Build • Innovate • Launch with Artificial Intelligence"
10
+ DEFAULT_MODEL = "gpt-4.1-mini"
11
+
12
+
13
+ def get_openai_api_key() -> str:
14
+ """Read the OpenAI API key from the environment."""
15
+ return os.getenv("OPENAI_API_KEY", "").strip()
16
+
17
+
18
+ def get_openai_model() -> str:
19
+ """Read the optional model name, falling back to a practical default."""
20
+ return os.getenv("OPENAI_MODEL", DEFAULT_MODEL).strip() or DEFAULT_MODEL
deploy_requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ huggingface_hub>=0.24,<1
deploy_to_huggingface.py ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Upload Pak Angels AI Tutor to a Hugging Face Space.
2
+
3
+ Required environment variables:
4
+ HF_TOKEN: A Hugging Face access token with write access to the Space.
5
+ HF_SPACE_ID: The Space repo id, for example "your-username/pak-angels-ai-tutor".
6
+
7
+ Optional environment variables:
8
+ HF_COMMIT_MESSAGE: Custom commit message for the upload.
9
+ HF_PRIVATE_SPACE: Set to "true" to create a private Space when using --create.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import argparse
15
+ import os
16
+ import sys
17
+ from pathlib import Path
18
+
19
+ from huggingface_hub import HfApi
20
+ from huggingface_hub.utils import HfHubHTTPError
21
+
22
+
23
+ PROJECT_ROOT = Path(__file__).resolve().parent
24
+ DEFAULT_IGNORE_PATTERNS = [
25
+ ".env",
26
+ ".env.local",
27
+ ".env.*.local",
28
+ ".git/",
29
+ ".git/**",
30
+ ".venv/",
31
+ ".venv/**",
32
+ "venv/",
33
+ "venv/**",
34
+ "__pycache__/",
35
+ "__pycache__/**",
36
+ "*.pyc",
37
+ ".DS_Store",
38
+ ".pytest_cache/",
39
+ ".pytest_cache/**",
40
+ ".ruff_cache/",
41
+ ".ruff_cache/**",
42
+ ".mypy_cache/",
43
+ ".mypy_cache/**",
44
+ "dist/",
45
+ "dist/**",
46
+ "build/",
47
+ "build/**",
48
+ "*.egg-info/",
49
+ "*.egg-info/**",
50
+ "*.log",
51
+ "tmp/",
52
+ "tmp/**",
53
+ "temp/",
54
+ "temp/**",
55
+ ]
56
+
57
+
58
+ def parse_args() -> argparse.Namespace:
59
+ parser = argparse.ArgumentParser(
60
+ description="Upload the current Pak Angels AI Tutor project to Hugging Face Spaces."
61
+ )
62
+ parser.add_argument(
63
+ "--space-id",
64
+ default=os.getenv("HF_SPACE_ID", "").strip(),
65
+ help='Hugging Face Space id, for example "username/pak-angels-ai-tutor".',
66
+ )
67
+ parser.add_argument(
68
+ "--token",
69
+ default=os.getenv("HF_TOKEN", "").strip(),
70
+ help="Hugging Face write token. Prefer setting HF_TOKEN instead of passing this flag.",
71
+ )
72
+ parser.add_argument(
73
+ "--commit-message",
74
+ default=os.getenv("HF_COMMIT_MESSAGE", "Deploy Pak Angels AI Tutor"),
75
+ help="Commit message shown in the Hugging Face Space repository.",
76
+ )
77
+ parser.add_argument(
78
+ "--repo-type",
79
+ default="space",
80
+ choices=["space"],
81
+ help="Repository type. Spaces deployments use 'space'.",
82
+ )
83
+ parser.add_argument(
84
+ "--create",
85
+ action="store_true",
86
+ help="Create the Gradio Space if it does not already exist.",
87
+ )
88
+ parser.add_argument(
89
+ "--private",
90
+ action="store_true",
91
+ default=os.getenv("HF_PRIVATE_SPACE", "").lower() in {"1", "true", "yes"},
92
+ help="Create the Space as private when --create is used.",
93
+ )
94
+ return parser.parse_args()
95
+
96
+
97
+ def validate_inputs(space_id: str, token: str) -> None:
98
+ missing = []
99
+ if not space_id:
100
+ missing.append("HF_SPACE_ID")
101
+ if not token:
102
+ missing.append("HF_TOKEN")
103
+
104
+ if missing:
105
+ joined = ", ".join(missing)
106
+ raise ValueError(
107
+ f"Missing required setting(s): {joined}. Set them as environment variables "
108
+ "or pass --space-id and --token."
109
+ )
110
+
111
+ if "/" not in space_id:
112
+ raise ValueError('HF_SPACE_ID should look like "username/space-name".')
113
+
114
+ placeholder_values = {
115
+ "your_hugging_face_write_token_here",
116
+ "your-token",
117
+ "your_token",
118
+ }
119
+ placeholder_space_ids = {
120
+ "your-username/your-space-name",
121
+ "username/space-name",
122
+ "your-username/pak-angels-ai-tutor",
123
+ }
124
+ if token in placeholder_values:
125
+ raise ValueError("HF_TOKEN is still a placeholder. Use a real Hugging Face write token.")
126
+ if space_id in placeholder_space_ids:
127
+ raise ValueError(
128
+ "HF_SPACE_ID is still a placeholder. Use your real Space id, such as "
129
+ '"mohammadanwarkhan/pak-angels-ai-tutor".'
130
+ )
131
+
132
+
133
+ def ensure_space_exists(api: HfApi, args: argparse.Namespace) -> None:
134
+ if not args.create:
135
+ return
136
+
137
+ api.create_repo(
138
+ repo_id=args.space_id,
139
+ repo_type=args.repo_type,
140
+ private=args.private,
141
+ space_sdk="gradio",
142
+ exist_ok=True,
143
+ )
144
+
145
+
146
+ def preflight_check(api: HfApi, args: argparse.Namespace) -> None:
147
+ whoami = api.whoami()
148
+ account_name = whoami.get("name") or whoami.get("fullname") or "authenticated account"
149
+ print(f"Authenticated with Hugging Face as: {account_name}")
150
+
151
+ try:
152
+ api.repo_info(repo_id=args.space_id, repo_type=args.repo_type)
153
+ print(f"Space is accessible: {args.space_id}")
154
+ except HfHubHTTPError as error:
155
+ if args.create:
156
+ raise
157
+ raise RuntimeError(
158
+ f"The token cannot access the Space '{args.space_id}'. Check that the Space id "
159
+ "is exact and that this Hugging Face token has write access to that Space. "
160
+ "If the Space does not exist, rerun with --create."
161
+ ) from error
162
+
163
+
164
+ def upload_project(args: argparse.Namespace) -> str:
165
+ api = HfApi(token=args.token)
166
+ ensure_space_exists(api, args)
167
+ preflight_check(api, args)
168
+ api.upload_folder(
169
+ folder_path=str(PROJECT_ROOT),
170
+ repo_id=args.space_id,
171
+ repo_type=args.repo_type,
172
+ commit_message=args.commit_message,
173
+ ignore_patterns=DEFAULT_IGNORE_PATTERNS,
174
+ )
175
+ return f"https://huggingface.co/spaces/{args.space_id}"
176
+
177
+
178
+ def main() -> int:
179
+ args = parse_args()
180
+ try:
181
+ validate_inputs(args.space_id, args.token)
182
+ url = upload_project(args)
183
+ except ValueError as error:
184
+ print(f"Configuration error: {error}", file=sys.stderr)
185
+ return 2
186
+ except HfHubHTTPError as error:
187
+ print(f"Hugging Face upload failed: {error}", file=sys.stderr)
188
+ print(
189
+ "Check that HF_SPACE_ID is your real Space id, HF_TOKEN is a real write token, "
190
+ "and the Space exists. If it does not exist, rerun with --create.",
191
+ file=sys.stderr,
192
+ )
193
+ return 1
194
+ except Exception as error:
195
+ print(f"Deployment failed: {error}", file=sys.stderr)
196
+ return 1
197
+
198
+ print("Deployment upload complete.")
199
+ print(f"Space URL: {url}")
200
+ print("Remember to set OPENAI_API_KEY in the Space secrets before testing the tutor.")
201
+ return 0
202
+
203
+
204
+ if __name__ == "__main__":
205
+ raise SystemExit(main())
openai_service.py ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """OpenAI Responses API integration."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Iterable
6
+
7
+ from openai import APIConnectionError, APIStatusError, AuthenticationError, OpenAI, RateLimitError
8
+
9
+
10
+ def format_openai_error(error: Exception) -> str:
11
+ """Return a learner-friendly error message."""
12
+ if isinstance(error, AuthenticationError):
13
+ return (
14
+ "The OpenAI API key was rejected. Please check that OPENAI_API_KEY is "
15
+ "set correctly in Hugging Face Secrets."
16
+ )
17
+ if isinstance(error, RateLimitError):
18
+ return (
19
+ "The request was rate limited or the account may have quota or billing "
20
+ "limits. Please wait briefly, then check OpenAI usage and billing settings."
21
+ )
22
+ if isinstance(error, APIConnectionError):
23
+ return (
24
+ "The app could not reach OpenAI. Please check the network connection and "
25
+ "try again."
26
+ )
27
+ if isinstance(error, APIStatusError):
28
+ status = getattr(error, "status_code", "unknown")
29
+ return (
30
+ f"OpenAI returned an API error with status {status}. Please review the "
31
+ "API key, model name, quota, billing status, and request details."
32
+ )
33
+ return "An unexpected AI service error occurred. Please try again or review the Space logs."
34
+
35
+
36
+ def stream_tutor_response(
37
+ *,
38
+ api_key: str,
39
+ model: str,
40
+ system_instructions: str,
41
+ messages: list[dict[str, str]],
42
+ ) -> Iterable[str]:
43
+ """Yield text deltas from the current event-based OpenAI Responses API stream."""
44
+ client = OpenAI(api_key=api_key)
45
+ input_messages = [
46
+ {"role": message["role"], "content": message["content"]}
47
+ for message in messages
48
+ if message.get("role") in {"user", "assistant"} and message.get("content")
49
+ ]
50
+
51
+ stream = client.responses.create(
52
+ model=model,
53
+ instructions=system_instructions,
54
+ input=input_messages,
55
+ stream=True,
56
+ )
57
+
58
+ for event in stream:
59
+ if getattr(event, "type", None) == "response.output_text.delta":
60
+ delta = getattr(event, "delta", "")
61
+ if delta:
62
+ yield delta
prompts.py ADDED
@@ -0,0 +1,360 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Learning-module content and tutor instructions."""
2
+
3
+ from __future__ import annotations
4
+
5
+
6
+ BASE_TUTOR_INSTRUCTIONS = """
7
+ You are Pak Angels AI Tutor, an educational AI companion for the Pak Angels AI
8
+ Training Program.
9
+
10
+ Your teaching style:
11
+ - Teach clearly and step by step.
12
+ - Adjust depth to the learner's apparent level.
13
+ - Use practical examples, frameworks, exercises, quiz questions, and project ideas.
14
+ - Encourage responsible and ethical AI use.
15
+ - Explain code in simple language when code is useful.
16
+ - Help learners move through Learn -> Practice -> Build -> Deploy -> Innovate -> Launch.
17
+ - Be encouraging, professional, and practical.
18
+ - Do not present uncertain information as fact.
19
+ - Encourage users to verify important legal, medical, financial, and technical decisions.
20
+ - Do not request confidential, proprietary, financial, medical, personal, or sensitive data.
21
+ """
22
+
23
+
24
+ MODULES = {
25
+ "Home": {
26
+ "summary": "Start here for an overview of the Pak Angels AI learning journey.",
27
+ "topics": [
28
+ "AI learning roadmap",
29
+ "Practical projects",
30
+ "Responsible AI",
31
+ "Startup and innovation pathways",
32
+ ],
33
+ "suggestions": [
34
+ "Help me choose where to start.",
35
+ "Create a 30-day AI learning plan.",
36
+ "What should I build after learning AI basics?",
37
+ "How can I use this tutor responsibly?",
38
+ ],
39
+ "instructions": """
40
+ Orient the learner. Recommend a pathway based on their background and goals.
41
+ Connect learning modules to practical projects, hackathons, entrepreneurship, and deployment.
42
+ """,
43
+ },
44
+ "AI-101 Foundations": {
45
+ "summary": "AI fundamentals, responsible use, careers, and practical applications.",
46
+ "topics": [
47
+ "Artificial Intelligence fundamentals",
48
+ "Machine Learning",
49
+ "Deep Learning",
50
+ "Large Language Models",
51
+ "Generative AI",
52
+ "Responsible AI",
53
+ "AI ethics",
54
+ "AI careers",
55
+ "Practical AI applications",
56
+ ],
57
+ "suggestions": [
58
+ "What is Artificial Intelligence?",
59
+ "What is the difference between AI, Machine Learning, and Generative AI?",
60
+ "How do Large Language Models work?",
61
+ "How can students use AI responsibly?",
62
+ "What AI career paths are available?",
63
+ ],
64
+ "instructions": """
65
+ Teach AI foundations with simple analogies, clear definitions, responsible AI guidance,
66
+ and practical examples for students, faculty, professionals, and entrepreneurs.
67
+ """,
68
+ },
69
+ "Prompt Engineering": {
70
+ "summary": "Design better prompts, templates, evaluations, and reliable outputs.",
71
+ "topics": [
72
+ "Prompt design",
73
+ "Prompt optimization",
74
+ "Role prompting",
75
+ "Context setting",
76
+ "Few-shot prompting",
77
+ "Structured prompts",
78
+ "Reusable prompt templates",
79
+ "Output formatting",
80
+ "Prompt evaluation",
81
+ ],
82
+ "suggestions": [
83
+ "How do I write an effective prompt?",
84
+ "Improve this prompt for me.",
85
+ "Why is context important in prompting?",
86
+ "Create a reusable research prompt template.",
87
+ "How can I make AI responses more consistent?",
88
+ ],
89
+ "instructions": """
90
+ Act as a prompt-engineering coach. Diagnose vague prompts, improve structure,
91
+ offer reusable templates, and explain why each change improves reliability.
92
+ """,
93
+ },
94
+ "Generative AI": {
95
+ "summary": "Text, image, code, productivity, and business uses of Generative AI.",
96
+ "topics": [
97
+ "Generative AI fundamentals",
98
+ "Large Language Models",
99
+ "Text generation",
100
+ "Image generation",
101
+ "Code generation",
102
+ "AI productivity",
103
+ "Content creation",
104
+ "Practical business applications",
105
+ ],
106
+ "suggestions": [
107
+ "How does ChatGPT work?",
108
+ "What can Generative AI create?",
109
+ "Compare major types of Generative AI tools.",
110
+ "How can professionals use AI productively?",
111
+ "What are common Generative AI business use cases?",
112
+ ],
113
+ "instructions": """
114
+ Teach Generative AI concepts and use cases. Explain capabilities, limitations,
115
+ responsible use, and concrete workflows for education, business, and creativity.
116
+ """,
117
+ },
118
+ "Agentic AI": {
119
+ "summary": "Goals, planning, tools, memory, supervision, and agent safety.",
120
+ "topics": [
121
+ "AI agents",
122
+ "Agent goals",
123
+ "Planning",
124
+ "Tool calling",
125
+ "Memory",
126
+ "Multi-step workflows",
127
+ "Human supervision",
128
+ "Autonomous task execution",
129
+ "Agent safety",
130
+ ],
131
+ "suggestions": [
132
+ "What is an AI agent?",
133
+ "How is an agent different from a chatbot?",
134
+ "How do AI agents use tools?",
135
+ "Design a simple research agent.",
136
+ "Explain memory and planning in agentic systems.",
137
+ ],
138
+ "instructions": """
139
+ Teach agentic systems with emphasis on goals, planning, tools, memory,
140
+ human oversight, safeguards, and practical workflow design.
141
+ """,
142
+ },
143
+ "Retrieval-Augmented Generation (RAG)": {
144
+ "summary": "Retrieval, embeddings, vector databases, and knowledge assistants.",
145
+ "topics": [
146
+ "RAG architecture",
147
+ "Embeddings",
148
+ "Vector databases",
149
+ "Knowledge retrieval",
150
+ "Document search",
151
+ "Enterprise knowledge assistants",
152
+ "Chunking",
153
+ "Retrieval quality",
154
+ "RAG evaluation",
155
+ ],
156
+ "suggestions": [
157
+ "What is Retrieval-Augmented Generation?",
158
+ "When should I use RAG?",
159
+ "Explain a simple RAG architecture.",
160
+ "Compare RAG with fine-tuning.",
161
+ "How do embeddings and vector databases work?",
162
+ ],
163
+ "instructions": """
164
+ Teach RAG architecture and evaluation. Compare RAG with fine-tuning, explain
165
+ chunking and retrieval quality, and use enterprise knowledge-assistant examples.
166
+ """,
167
+ },
168
+ "Multi-Agent Systems": {
169
+ "summary": "Agent roles, delegation, orchestration, collaboration, and review.",
170
+ "topics": [
171
+ "Agent collaboration",
172
+ "Agent specialization",
173
+ "Agent roles",
174
+ "Task delegation",
175
+ "Workflow orchestration",
176
+ "Communication between agents",
177
+ "Supervisor agents",
178
+ "Quality-control agents",
179
+ ],
180
+ "suggestions": [
181
+ "How do multiple AI agents collaborate?",
182
+ "What roles can agents perform in a workflow?",
183
+ "Design a multi-agent research team.",
184
+ "What is an agent supervisor?",
185
+ "How can agents review one another's work?",
186
+ ],
187
+ "instructions": """
188
+ Teach multi-agent design. Emphasize role clarity, handoffs, orchestration,
189
+ supervisor agents, quality control, and human review.
190
+ """,
191
+ },
192
+ "AI Workflow Design": {
193
+ "summary": "Turn real problems into structured, validated AI workflows.",
194
+ "topics": [
195
+ "Problem decomposition",
196
+ "Workflow mapping",
197
+ "Inputs and outputs",
198
+ "Decision points",
199
+ "Human-in-the-loop review",
200
+ "Tool selection",
201
+ "Task routing",
202
+ "Agent orchestration",
203
+ "Workflow validation",
204
+ "Error handling",
205
+ "Monitoring",
206
+ "Workflow optimization",
207
+ ],
208
+ "suggestions": [
209
+ "Design an AI workflow for customer support.",
210
+ "Create an AI workflow for invoice processing.",
211
+ "Design a healthcare appointment workflow.",
212
+ "Explain human-in-the-loop workflow design.",
213
+ "Convert this business problem into an AI workflow.",
214
+ ],
215
+ "instructions": """
216
+ Help users convert practical problems into structured AI workflows. Identify
217
+ inputs, outputs, decision points, tools, review steps, monitoring, and failure handling.
218
+ """,
219
+ },
220
+ "Business Process Automation": {
221
+ "summary": "Automate operations across sales, support, finance, HR, and more.",
222
+ "topics": [
223
+ "Business Process Automation",
224
+ "Intelligent automation",
225
+ "Email automation",
226
+ "Document processing",
227
+ "Customer support automation",
228
+ "Sales automation",
229
+ "Marketing automation",
230
+ "Human resources automation",
231
+ "Finance automation",
232
+ "Operations automation",
233
+ "Approval workflows",
234
+ "Exception handling",
235
+ "Process measurement",
236
+ ],
237
+ "suggestions": [
238
+ "Automate my sales follow-up process.",
239
+ "Build an AI-powered HR assistant.",
240
+ "Design an invoice-processing system.",
241
+ "Automate customer-support triage.",
242
+ "Help me identify which business process to automate first.",
243
+ ],
244
+ "instructions": """
245
+ Act as an AI business-automation mentor. Help users prioritize processes,
246
+ map workflows, select tools, measure outcomes, and design exception handling.
247
+ """,
248
+ },
249
+ "Gradio Development": {
250
+ "summary": "Build, debug, and deploy practical Gradio applications.",
251
+ "topics": [
252
+ "Python basics",
253
+ "Gradio applications",
254
+ "User-interface design",
255
+ "Blocks",
256
+ "Buttons",
257
+ "Chatbots",
258
+ "State management",
259
+ "OpenAI API integration",
260
+ "Error handling",
261
+ "Deployment",
262
+ "Debugging",
263
+ ],
264
+ "suggestions": [
265
+ "Help me build my first Gradio application.",
266
+ "How do I add buttons, inputs, and chatbots?",
267
+ "How do I connect the OpenAI API?",
268
+ "How does Gradio state management work?",
269
+ "How can I deploy a Gradio app on Hugging Face Spaces?",
270
+ ],
271
+ "instructions": """
272
+ Teach Gradio development in beginner-friendly steps. Provide small runnable
273
+ examples, explain Blocks, chatbot interfaces, state management, OpenAI integration,
274
+ deployment on Hugging Face Spaces, and debugging.
275
+ """,
276
+ },
277
+ "AI Startup Mentor": {
278
+ "summary": "Refine ideas, design MVPs, evaluate markets, and prepare to launch.",
279
+ "topics": [
280
+ "Startup idea refinement",
281
+ "Customer problems",
282
+ "Target markets",
283
+ "Customer discovery",
284
+ "Value propositions",
285
+ "Business models",
286
+ "MVP planning",
287
+ "Product-market fit",
288
+ "Risk analysis",
289
+ "Go-to-market strategy",
290
+ "Investor pitches",
291
+ "Financial assumptions",
292
+ "Investor readiness",
293
+ "Scaling",
294
+ ],
295
+ "suggestions": [
296
+ "Help me evaluate my startup idea.",
297
+ "Create a Business Model Canvas.",
298
+ "Help me prepare a three-minute investor pitch.",
299
+ "Build an MVP roadmap.",
300
+ "Develop a go-to-market strategy.",
301
+ "Identify the key risks in my startup idea.",
302
+ ],
303
+ "instructions": """
304
+ Act as a practical startup mentor. Ask clarifying questions when needed,
305
+ challenge assumptions, structure ideas, identify risks, and help users move
306
+ toward investor-ready and customer-validated plans.
307
+ """,
308
+ },
309
+ "About Pak Angels": {
310
+ "summary": "Learn about the Pak Angels mission and innovation ecosystem.",
311
+ "topics": [
312
+ "AI education",
313
+ "Entrepreneurship",
314
+ "Startup innovation",
315
+ "Technology commercialization",
316
+ "Investment readiness",
317
+ "Global Pakistani community",
318
+ ],
319
+ "suggestions": [
320
+ "What is Pak Angels?",
321
+ "How can Pak Angels support AI learners?",
322
+ "How can startups benefit from Pak Angels?",
323
+ "Suggest a Pak Angels AI training pathway.",
324
+ ],
325
+ "instructions": """
326
+ Explain the Pak Angels mission and connect users to education, practical AI
327
+ projects, entrepreneurship, startup innovation, and investment readiness.
328
+ """,
329
+ },
330
+ }
331
+
332
+
333
+ ABOUT_PAK_ANGELS = """
334
+ Pak Angels is a Silicon Valley-based global platform dedicated to accelerating
335
+ Artificial Intelligence education, entrepreneurship, startup innovation, technology
336
+ commercialization, and investment across Pakistan and the global Pakistani community.
337
+
338
+ Pak Angels helps students, faculty, professionals, entrepreneurs, and startups
339
+ learn, build, deploy, commercialize, and scale AI-powered solutions through
340
+ structured education, practical application development, hackathons, mentorship,
341
+ investment readiness, and access to global innovation ecosystems.
342
+ """
343
+
344
+
345
+ def build_system_instructions(module_name: str) -> str:
346
+ """Compose module-specific instructions for the selected learning mode."""
347
+ module = MODULES.get(module_name, MODULES["Home"])
348
+ topics = "\n".join(f"- {topic}" for topic in module["topics"])
349
+ return f"""
350
+ {BASE_TUTOR_INSTRUCTIONS}
351
+
352
+ Selected learning mode: {module_name}
353
+ Mode summary: {module["summary"]}
354
+
355
+ Priority topics:
356
+ {topics}
357
+
358
+ Specialized instructions:
359
+ {module["instructions"]}
360
+ """
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ gradio>=5.50,<6
2
+ openai>=1.93,<2