Mahdiyar commited on
Commit
1f38061
Β·
1 Parent(s): 8f98e92

Add initial implementation of Hackathon Team Organizer application

Browse files

- Created main application structure with `main.py` as the entry point.
- Implemented participant generation script in `generate_participants.py`.
- Set up SQLite database for participant storage with `database.py`.
- Developed AI-powered team matching logic in `matching_agent.py`.
- Added Gradio-based UI in `app.py` for participant registration and team matching.
- Included `.gitignore` to exclude unnecessary files.
- Added `README.md` for project documentation and setup instructions.
- Established requirements in `requirements.txt` for dependencies.

.gitignore ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ .DS_Store
2
+ **/*.pyc
3
+ *.pyc
generate_participants.py ADDED
@@ -0,0 +1,372 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Generate Synthetic Hackathon Participants
4
+
5
+ This script creates 100 diverse hackathon participants and saves them to the database.
6
+ The participants represent various personas that might attend a hackathon focused on
7
+ "Connected Experiences" and AI agents.
8
+ """
9
+ import random
10
+ import sys
11
+ import os
12
+ from faker import Faker
13
+ from hackathon_organizer.database import initialize_database, add_participant, get_participants_dataframe
14
+
15
+ # Initialize Faker for generating realistic names and emails
16
+ fake = Faker()
17
+
18
+ # Define various participant personas and attributes
19
+ TECHNICAL_BACKGROUNDS = [
20
+ # Developers
21
+ "Full-stack developer with {years} years of experience in {stack}. {additional}",
22
+ "Backend engineer specializing in {backend_tech}. {additional}",
23
+ "Frontend developer focused on {frontend_tech}. {additional}",
24
+ "Mobile developer with expertise in {mobile_tech}. {additional}",
25
+ "DevOps engineer with experience in {devops_tech}. {additional}",
26
+ "Data scientist working with {ds_tech}. {additional}",
27
+ "Machine learning engineer focused on {ml_tech}. {additional}",
28
+ "AI researcher specializing in {ai_tech}. {additional}",
29
+ "Game developer using {game_tech}. {additional}",
30
+ "Embedded systems engineer working with {embedded_tech}. {additional}",
31
+
32
+ # Technical but not coding-focused
33
+ "UX/UI designer with {years} years of experience. {additional}",
34
+ "Product manager for {product_type} products. {additional}",
35
+ "QA engineer with expertise in {qa_tech}. {additional}",
36
+ "Technical writer specializing in {writing_focus}. {additional}",
37
+ "Solution architect with background in {arch_focus}. {additional}",
38
+ ]
39
+
40
+ NON_TECHNICAL_BACKGROUNDS = [
41
+ "Marketing professional with experience in {marketing_focus}. {additional}",
42
+ "Business development specialist in the {industry} industry. {additional}",
43
+ "Project manager with {years} years of experience in {pm_focus}. {additional}",
44
+ "Entrepreneur and founder of a {startup_type} startup. {additional}",
45
+ "Student studying {field} at {university}. {additional}",
46
+ "Design thinking facilitator and innovation consultant. {additional}",
47
+ "Content creator focusing on {content_focus}. {additional}",
48
+ "Sales professional in the {sales_industry} sector. {additional}",
49
+ "HR specialist interested in tech talent and culture. {additional}",
50
+ "Non-profit professional looking to leverage technology for social impact. {additional}",
51
+ ]
52
+
53
+ GOALS = [
54
+ # Learning-focused
55
+ "I want to learn about AI and how it can enhance user experiences at events.",
56
+ "I'm here to understand how to build AI agents and apply them to real-world problems.",
57
+ "I hope to gain practical experience with AI technologies and expand my technical skills.",
58
+ "I want to learn from experienced developers and improve my coding abilities.",
59
+ "I'm looking to understand how AI can create more meaningful human connections.",
60
+
61
+ # Project-focused
62
+ "I want to build a prototype that demonstrates the power of AI in connecting people.",
63
+ "I'm hoping to create an innovative solution that addresses the challenges of virtual events.",
64
+ "My goal is to develop an AI agent that enhances real-world social interactions.",
65
+ "I want to build something impressive for my portfolio that showcases my skills.",
66
+ "I'm aiming to create a practical tool that event organizers can actually use.",
67
+
68
+ # Networking-focused
69
+ "I'm primarily here to network with other professionals in the AI and event space.",
70
+ "I want to meet potential co-founders for a startup idea I've been developing.",
71
+ "I'm looking to connect with mentors who can guide my career in tech.",
72
+ "I hope to find collaborators for future projects beyond this hackathon.",
73
+ "I want to expand my professional network in the Toronto tech community.",
74
+
75
+ # Career-focused
76
+ "I'm exploring career opportunities in AI development and looking to showcase my skills.",
77
+ "I want to transition from my current role to a more tech-focused position.",
78
+ "I'm hoping this experience will help me land a job at an innovative tech company.",
79
+ "I want to demonstrate my abilities to potential employers or clients.",
80
+ "I'm building skills that will help me advance in my current organization.",
81
+
82
+ # Fun/Experience-focused
83
+ "I'm here for the creative experience and the thrill of building something in 24 hours.",
84
+ "I want to have fun while challenging myself technically.",
85
+ "I'm curious about hackathons and wanted to experience one firsthand.",
86
+ "I enjoy the collaborative atmosphere of hackathons and the energy they generate.",
87
+ "I'm looking for a break from my routine and a chance to work on something different.",
88
+ ]
89
+
90
+ # Technical stack components
91
+ STACK_COMPONENTS = {
92
+ "years": [str(i) for i in range(1, 16)],
93
+ "stack": [
94
+ "JavaScript/TypeScript and Python", "MERN stack", "MEAN stack", "Ruby on Rails",
95
+ "Django and React", "Vue.js and Node.js", "PHP and Laravel", "Java Spring Boot",
96
+ ".NET and Angular", "Go and React", "Python Flask and Vue.js"
97
+ ],
98
+ "backend_tech": [
99
+ "Node.js and Express", "Django and PostgreSQL", "Ruby on Rails", "Java Spring Boot",
100
+ "ASP.NET Core", "PHP and Laravel", "Go microservices", "Python FastAPI",
101
+ "GraphQL APIs", "Serverless architectures on AWS"
102
+ ],
103
+ "frontend_tech": [
104
+ "React and Redux", "Angular and RxJS", "Vue.js and Vuex", "Svelte and SvelteKit",
105
+ "Next.js", "Gatsby", "React Native", "Flutter", "TypeScript and Material UI",
106
+ "Tailwind CSS and Alpine.js"
107
+ ],
108
+ "mobile_tech": [
109
+ "React Native", "Flutter", "Swift for iOS", "Kotlin for Android",
110
+ "Xamarin", "Ionic", "PWAs", "Unity for mobile games", "NativeScript",
111
+ "Mobile AR/VR applications"
112
+ ],
113
+ "devops_tech": [
114
+ "Kubernetes and Docker", "AWS infrastructure", "Azure DevOps", "Google Cloud Platform",
115
+ "CI/CD pipelines", "Terraform and infrastructure as code", "Jenkins and GitLab CI",
116
+ "Monitoring and observability tools", "Site Reliability Engineering practices",
117
+ "Security automation"
118
+ ],
119
+ "ds_tech": [
120
+ "Python, Pandas, and scikit-learn", "R and Tidyverse", "SQL and data warehousing",
121
+ "Tableau and data visualization", "Big data technologies like Spark",
122
+ "ETL pipelines", "Statistical analysis", "A/B testing methodologies",
123
+ "Natural Language Processing", "Computer Vision"
124
+ ],
125
+ "ml_tech": [
126
+ "TensorFlow and Keras", "PyTorch", "scikit-learn", "deep learning models",
127
+ "MLOps and model deployment", "reinforcement learning", "computer vision algorithms",
128
+ "NLP models", "recommendation systems", "time series forecasting"
129
+ ],
130
+ "ai_tech": [
131
+ "large language models", "generative AI", "conversational agents", "computer vision systems",
132
+ "reinforcement learning", "multimodal AI", "AI ethics and responsible AI",
133
+ "autonomous systems", "AI for social good", "explainable AI"
134
+ ],
135
+ "game_tech": [
136
+ "Unity", "Unreal Engine", "Godot", "WebGL", "AR/VR development",
137
+ "mobile game development", "game AI", "procedural generation",
138
+ "multiplayer networking", "game physics"
139
+ ],
140
+ "embedded_tech": [
141
+ "Arduino", "Raspberry Pi", "IoT devices", "embedded Linux",
142
+ "RTOS", "C/C++ for microcontrollers", "sensor networks",
143
+ "firmware development", "hardware interfaces", "low-power systems"
144
+ ],
145
+ "product_type": [
146
+ "SaaS", "mobile", "enterprise", "consumer", "AI-powered",
147
+ "IoT", "fintech", "healthtech", "edtech", "e-commerce"
148
+ ],
149
+ "qa_tech": [
150
+ "automated testing", "Selenium and Cypress", "performance testing",
151
+ "security testing", "mobile app testing", "API testing",
152
+ "test-driven development", "behavior-driven development",
153
+ "continuous integration testing", "accessibility testing"
154
+ ],
155
+ "writing_focus": [
156
+ "API documentation", "user guides", "developer tutorials",
157
+ "knowledge bases", "technical blogs", "software requirements",
158
+ "open source documentation", "technical specifications",
159
+ "UX writing", "compliance documentation"
160
+ ],
161
+ "arch_focus": [
162
+ "cloud architectures", "microservices", "serverless",
163
+ "enterprise systems", "distributed systems", "API design",
164
+ "security architectures", "data platforms", "IoT systems",
165
+ "mobile and web applications"
166
+ ],
167
+ "additional": [
168
+ "I enjoy working in collaborative environments.",
169
+ "I'm passionate about creating accessible technology.",
170
+ "I've contributed to several open source projects.",
171
+ "I'm interested in ethical technology and responsible innovation.",
172
+ "I enjoy mentoring junior developers.",
173
+ "I have a background in design thinking.",
174
+ "I've worked in startups and enterprise environments.",
175
+ "I'm particularly interested in AI ethics.",
176
+ "I love solving complex algorithmic problems.",
177
+ "I focus on creating user-centered solutions.",
178
+ "I have experience leading small technical teams.",
179
+ "I'm self-taught and constantly learning new technologies.",
180
+ "I have a computer science degree but learned most of my skills on the job.",
181
+ "I'm currently transitioning careers into tech.",
182
+ "I'm an advocate for diversity in tech.",
183
+ "I've organized tech meetups and community events.",
184
+ "I'm interested in the intersection of technology and sustainability.",
185
+ "I have experience in both technical and business roles.",
186
+ "I'm passionate about making technology more accessible to everyone.",
187
+ "I enjoy the challenges of working with legacy systems.",
188
+ "", # Empty for some participants
189
+ ]
190
+ }
191
+
192
+ # Non-technical components
193
+ NON_TECH_COMPONENTS = {
194
+ "marketing_focus": [
195
+ "digital marketing", "content strategy", "brand development",
196
+ "social media campaigns", "event promotion", "growth hacking",
197
+ "community building", "influencer partnerships", "SEO/SEM",
198
+ "product marketing"
199
+ ],
200
+ "industry": [
201
+ "technology", "healthcare", "finance", "education", "retail",
202
+ "entertainment", "manufacturing", "non-profit", "government",
203
+ "hospitality"
204
+ ],
205
+ "years": [str(i) for i in range(1, 16)],
206
+ "pm_focus": [
207
+ "agile methodologies", "waterfall approaches", "hybrid frameworks",
208
+ "technical projects", "creative initiatives", "product launches",
209
+ "organizational change", "international teams", "startup environments",
210
+ "enterprise transformations"
211
+ ],
212
+ "startup_type": [
213
+ "tech", "social impact", "e-commerce", "healthcare", "education",
214
+ "fintech", "sustainability", "B2B SaaS", "consumer app", "AI/ML"
215
+ ],
216
+ "field": [
217
+ "Computer Science", "Business Administration", "Design", "Marketing",
218
+ "Engineering", "Data Science", "Psychology", "Communications",
219
+ "Information Technology", "Entrepreneurship"
220
+ ],
221
+ "university": [
222
+ "University of Toronto", "York University", "Ryerson University",
223
+ "Seneca College", "Humber College", "OCAD University",
224
+ "George Brown College", "McMaster University", "Waterloo University",
225
+ "Queen's University"
226
+ ],
227
+ "content_focus": [
228
+ "tech tutorials", "industry trends", "career development",
229
+ "product reviews", "educational content", "lifestyle and tech",
230
+ "startup stories", "coding challenges", "design inspiration",
231
+ "thought leadership"
232
+ ],
233
+ "sales_industry": [
234
+ "SaaS", "hardware", "consulting services", "enterprise solutions",
235
+ "consumer tech", "B2B technology", "telecommunications",
236
+ "cybersecurity", "cloud services", "digital transformation"
237
+ ],
238
+ "additional": [
239
+ "I'm excited to learn more about technology and how it can solve real problems.",
240
+ "I bring a unique perspective from my non-technical background.",
241
+ "I'm interested in the human aspects of technology.",
242
+ "I'm looking to collaborate with technical team members and contribute my skills.",
243
+ "I have strong communication and presentation skills.",
244
+ "I excel at understanding user needs and translating them into requirements.",
245
+ "I'm good at explaining complex concepts to diverse audiences.",
246
+ "I have experience managing stakeholder expectations.",
247
+ "I'm skilled at identifying market opportunities.",
248
+ "I enjoy bridging the gap between technical and non-technical teams.",
249
+ "I have a creative approach to problem-solving.",
250
+ "I'm passionate about user experience and accessibility.",
251
+ "I have a network of industry connections that could be valuable.",
252
+ "I'm experienced in gathering and synthesizing user feedback.",
253
+ "I'm interested in how technology can create social impact.",
254
+ "I have experience in project coordination and team organization.",
255
+ "I'm good at creating compelling narratives around technical products.",
256
+ "I'm curious about AI and its potential applications.",
257
+ "I have a background in psychology and understand human behavior.",
258
+ "I'm skilled at facilitating workshops and brainstorming sessions.",
259
+ "", # Empty for some participants
260
+ ]
261
+ }
262
+
263
+ def generate_background(is_technical=True):
264
+ """Generate a realistic background for a participant."""
265
+ if is_technical:
266
+ template = random.choice(TECHNICAL_BACKGROUNDS)
267
+ components = STACK_COMPONENTS
268
+ else:
269
+ template = random.choice(NON_TECHNICAL_BACKGROUNDS)
270
+ components = NON_TECH_COMPONENTS
271
+
272
+ # Fill in the template with random components
273
+ for key in components:
274
+ if "{" + key + "}" in template:
275
+ template = template.replace("{" + key + "}", random.choice(components[key]))
276
+
277
+ return template
278
+
279
+ def generate_linkedin_profile(name):
280
+ """Generate a realistic LinkedIn profile URL based on the name."""
281
+ # Remove spaces and special characters, convert to lowercase
282
+ name_part = ''.join(c for c in name if c.isalnum()).lower()
283
+
284
+ # Add some randomness to ensure uniqueness
285
+ if random.random() < 0.3:
286
+ # Some people use just their name
287
+ profile = name_part
288
+ elif random.random() < 0.6:
289
+ # Some add a random number
290
+ profile = f"{name_part}{random.randint(1, 999)}"
291
+ else:
292
+ # Some add their profession or location
293
+ suffixes = ["dev", "tech", "to", "canada", "design", "pm", "product", "marketing", "ai"]
294
+ profile = f"{name_part}-{random.choice(suffixes)}"
295
+
296
+ return f"linkedin.com/in/{profile}"
297
+
298
+ def generate_participants(count=100):
299
+ """Generate a specified number of diverse hackathon participants."""
300
+ participants = []
301
+
302
+ # Define the distribution of technical vs non-technical participants
303
+ # For a hackathon, we'll have more technical participants but still a good mix
304
+ technical_count = int(count * 0.7) # 70% technical
305
+ non_technical_count = count - technical_count # 30% non-technical
306
+
307
+ # Generate technical participants
308
+ for _ in range(technical_count):
309
+ name = fake.name()
310
+ email = fake.email()
311
+ linkedin = generate_linkedin_profile(name)
312
+ background = generate_background(is_technical=True)
313
+ goals = random.choice(GOALS)
314
+
315
+ participants.append({
316
+ "email": email,
317
+ "name": name,
318
+ "linkedin_profile": linkedin,
319
+ "background": background,
320
+ "goals": goals
321
+ })
322
+
323
+ # Generate non-technical participants
324
+ for _ in range(non_technical_count):
325
+ name = fake.name()
326
+ email = fake.email()
327
+ linkedin = generate_linkedin_profile(name)
328
+ background = generate_background(is_technical=False)
329
+ goals = random.choice(GOALS)
330
+
331
+ participants.append({
332
+ "email": email,
333
+ "name": name,
334
+ "linkedin_profile": linkedin,
335
+ "background": background,
336
+ "goals": goals
337
+ })
338
+
339
+ # Shuffle the participants to mix technical and non-technical
340
+ random.shuffle(participants)
341
+ return participants
342
+
343
+ def main():
344
+ """Main function to generate participants and save them to the database."""
345
+ print("Initializing database...")
346
+ initialize_database()
347
+
348
+ print("Generating 100 diverse hackathon participants...")
349
+ participants = generate_participants(100)
350
+
351
+ print("Adding participants to the database...")
352
+ for p in participants:
353
+ add_participant(p)
354
+
355
+ print("Participants added successfully.")
356
+
357
+ # Get and display a sample of the participants
358
+ df = get_participants_dataframe()
359
+ print(f"\nTotal participants in database: {len(df)}")
360
+ print("\nSample of participants:")
361
+ print(df.sample(5))
362
+
363
+ if __name__ == "__main__":
364
+ # Check if Faker is installed
365
+ try:
366
+ import faker
367
+ except ImportError:
368
+ print("The 'faker' package is required but not installed.")
369
+ print("Please install it using: pip install faker")
370
+ sys.exit(1)
371
+
372
+ main()
hackathon_organizer/README.md ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # πŸ€– AI-Powered HackBuddyAI
2
+
3
+ This project is a web application that helps hackathon organizers automatically form balanced teams from a list of participants. It uses a `TinyCodeAgent` to analyze participant skills and goals, creating optimal teams based on criteria defined by the organizer.
4
+
5
+ The application features a two-tab interface:
6
+ 1. **Participant Registration**: A form for participants to submit their profile, including skills, background, and what they want to achieve during the hackathon.
7
+ 2. **Organizer Dashboard**: A view for the organizer to see all registered participants, define matching criteria, and run the AI-powered team formation process.
8
+
9
+ ## Tech Stack
10
+ - **Backend**: Python
11
+ - **AI Agent Framework**: `TinyCodeAgent`
12
+ - **Web UI**: Gradio
13
+ - **Data Handling**: Pandas
14
+ - **Database**: SQLite
15
+
16
+ ---
17
+
18
+ ## Setup and Installation
19
+
20
+ ### 1. Prerequisites
21
+ - Python 3.8+
22
+ - An OpenAI API key
23
+
24
+ ### 2. Installation
25
+ 1. **Clone the repository** (if applicable) or ensure you have the project files in a directory.
26
+
27
+ 2. **Navigate to the project directory**:
28
+ ```bash
29
+ cd path/to/project
30
+ ```
31
+
32
+ 3. **Create a virtual environment** (recommended):
33
+ ```bash
34
+ python -m venv venv
35
+ source venv/bin/activate # On Windows, use `venv\Scripts\activate`
36
+ ```
37
+
38
+ 4. **Install dependencies**:
39
+ The project relies on the `tinyagent` library. Assuming it is available in your environment, install the other required packages:
40
+ ```bash
41
+ pip install -r hackathon_organizer/requirements.txt
42
+ ```
43
+
44
+ ### 3. Configure Environment Variables
45
+ You must set your OpenAI API key as an environment variable. The application will not run without it.
46
+
47
+ - **On macOS/Linux**:
48
+ ```bash
49
+ export OPENAI_API_KEY="your_api_key_here"
50
+ ```
51
+ - **On Windows (Command Prompt)**:
52
+ ```bash
53
+ set OPENAI_API_KEY="your_api_key_here"
54
+ ```
55
+
56
+ ---
57
+
58
+ ## πŸš€ Running the Application
59
+
60
+ Once the setup is complete, you can launch the Gradio web application using one of the following methods:
61
+
62
+ ### Method 1: Using the main script (recommended)
63
+
64
+ ```bash
65
+ python main.py
66
+ ```
67
+
68
+ This script handles all the necessary path configurations and launches the application.
69
+
70
+ ### Method 2: Running app.py directly
71
+
72
+ ```bash
73
+ cd hackathon_organizer
74
+ python app.py
75
+ ```
76
+
77
+ Either method will start a local web server, and you can access the application at the URL provided in the console (usually `http://127.0.0.1:7860`).
78
+
79
+ The application will create a `hackathon_participants.db` file in the working directory to store the participant data.
80
+
81
+ ---
82
+
83
+ ## πŸ§ͺ Running Tests
84
+
85
+ The project includes unit tests for the database and the agent setup logic. The tests are located in the `tests/` directory.
86
+
87
+ To run the tests:
88
+
89
+ ```bash
90
+ # From the project root directory
91
+ cd hackathon_organizer
92
+ python -m unittest discover tests
93
+ ```
94
+
95
+ The tests are designed to run without needing an active internet connection or a valid API key. They use mocks to simulate agent behavior and an in-memory database for testing database operations.
hackathon_organizer/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # This file makes the 'hackathon_organizer' directory a Python package.
hackathon_organizer/app.py ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+ import asyncio
4
+ import logging
5
+ import sys
6
+ import os
7
+ import io
8
+
9
+ # Change from absolute imports to relative imports
10
+ from database import initialize_database, add_participant, get_participants_dataframe
11
+ from matching_agent import create_matching_agent, run_matching
12
+ from tinyagent.hooks.logging_manager import LoggingManager
13
+
14
+ from tinyagent.hooks.logging_manager import LoggingManager
15
+ import logging
16
+
17
+
18
+ # --- Logging Setup ---
19
+ log_manager = LoggingManager(default_level=logging.INFO)
20
+ log_manager.set_levels({
21
+ 'tinyagent.hooks.gradio_callback': logging.DEBUG,
22
+ 'tinyagent.tiny_agent': logging.DEBUG,
23
+ 'tinyagent.mcp_client': logging.DEBUG,
24
+ 'tinyagent.code_agent': logging.DEBUG,
25
+ })
26
+
27
+ console_handler = logging.StreamHandler(sys.stdout)
28
+ log_manager.configure_handler(
29
+ console_handler,
30
+ format_string='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
31
+ level=logging.DEBUG
32
+ )
33
+
34
+ # Gradio log handler
35
+ log_stream = io.StringIO()
36
+ gradio_handler = logging.StreamHandler(log_stream)
37
+ log_manager.configure_handler(
38
+ gradio_handler,
39
+ format_string='%(asctime)s - %(levelname)s - %(name)s - %(message)s',
40
+ level=logging.DEBUG # Capture detailed logs for the UI
41
+ )
42
+
43
+ logger = log_manager.get_logger('app')
44
+
45
+ # --- Initial Setup ---
46
+ logger.info("Initializing database...")
47
+ initialize_database()
48
+
49
+ # Check for API key
50
+ if not os.environ.get("OPENAI_API_KEY"):
51
+ raise ValueError("The OPENAI_API_KEY environment variable is not set. Please set it before running the app.")
52
+
53
+ logger.info("Creating matching agent...")
54
+ agent = create_matching_agent(log_manager=log_manager)
55
+
56
+ # --- Gradio UI Functions ---
57
+
58
+ def register_participant(name, email, linkedin, background, goals):
59
+ """Callback function to register a new participant."""
60
+ if not all([name, email]):
61
+ return "Please provide at least a name and email.", get_participants_dataframe()
62
+
63
+ participant_data = {
64
+ "name": name,
65
+ "email": email,
66
+ "linkedin_profile": linkedin,
67
+ "background": background,
68
+ "goals": goals
69
+ }
70
+ try:
71
+ add_participant(participant_data)
72
+ feedback = f"βœ… Success! Participant '{name}' registered."
73
+ logger.info(f"Registered new participant: {email}")
74
+ except Exception as e:
75
+ feedback = f"❌ Error! Could not register participant. Reason: {e}"
76
+ logger.error(f"Failed to register participant {email}: {e}")
77
+
78
+ return feedback, get_participants_dataframe()
79
+
80
+ def refresh_participants_list():
81
+ """Callback to reload the participant data from the database."""
82
+ return get_participants_dataframe()
83
+
84
+ async def run_matching_process(organizer_criteria, progress=gr.Progress(track_tqdm=True)):
85
+ """Async callback to run the team matching process, with live log streaming."""
86
+ # 1. Clear previous logs and show panel
87
+ log_stream.seek(0)
88
+ log_stream.truncate(0)
89
+ progress(0, desc="Initializing...")
90
+ yield {
91
+ log_panel: gr.update(visible=True, open=True),
92
+ log_output: "Starting matching process...\n",
93
+ matching_results_out: "πŸš€ Setting up the matching process..."
94
+ }
95
+
96
+ # 2. Get participants and perform initial checks
97
+ logger.info("Fetching participants...")
98
+ progress(0, desc="Fetching participants...")
99
+ participants_df = get_participants_dataframe()
100
+ if len(participants_df) < 2:
101
+ warning_msg = "Matching process aborted: not enough participants."
102
+ logger.warning(warning_msg)
103
+ yield {
104
+ log_panel: gr.update(),
105
+ log_output: log_stream.getvalue(),
106
+ matching_results_out: "Cannot run matching with fewer than 2 participants."
107
+ }
108
+ return
109
+
110
+ logger.info(f"Running matching for {len(participants_df)} participants.")
111
+ progress(0.2, desc="🧠 Agent is thinking...")
112
+
113
+ # 3. Create a background task for the core matching logic
114
+ match_task = asyncio.create_task(
115
+ run_matching(agent, participants_df, organizer_criteria)
116
+ )
117
+
118
+ # 4. Stream logs while the agent works
119
+ while not match_task.done():
120
+ await asyncio.sleep(0.5) # Poll for new logs every 0.5s
121
+ yield {
122
+ log_panel: gr.update(),
123
+ log_output: log_stream.getvalue(),
124
+ matching_results_out: gr.update() # No change to final output yet
125
+ }
126
+
127
+ # 5. Process the final result from the agent
128
+ try:
129
+ final_report = await match_task
130
+ logger.info("Matching process completed successfully.")
131
+ progress(1.0, desc="βœ… Done!")
132
+ yield {
133
+ log_panel: gr.update(),
134
+ log_output: log_stream.getvalue(),
135
+ matching_results_out: final_report
136
+ }
137
+ except Exception as e:
138
+ logger.error(f"An error occurred during the matching process: {e}", exc_info=True)
139
+ yield {
140
+ log_panel: gr.update(),
141
+ log_output: log_stream.getvalue(),
142
+ matching_results_out: f"An error occurred: {e}"
143
+ }
144
+
145
+ # --- Gradio App Definition ---
146
+
147
+ with gr.Blocks(theme=gr.themes.Default(
148
+ font=[gr.themes.GoogleFont("Inter"), "Arial", "sans-serif"]
149
+ ), title="HackBuddyAI") as app:
150
+ gr.Markdown("# πŸ€– HackBuddyAI")
151
+
152
+ with gr.Tabs():
153
+ with gr.TabItem("πŸ‘€ Participant Registration"):
154
+ gr.Markdown("## Welcome, Participant!")
155
+ gr.Markdown("Fill out the form below to register for the hackathon.")
156
+ with gr.Row():
157
+ with gr.Column():
158
+ name_in = gr.Textbox(label="Full Name")
159
+ email_in = gr.Textbox(label="Email Address")
160
+ linkedin_in = gr.Textbox(label="LinkedIn Profile URL", placeholder="Optional")
161
+ with gr.Column():
162
+ background_in = gr.Textbox(label="Your Background & Skills", lines=5, placeholder="e.g., Python developer with 3 years of experience, specializing in Django and REST APIs...")
163
+ goals_in = gr.Textbox(label="Your Goals for this Hackathon", lines=5, placeholder="e.g., I want to learn about machine learning and work on a cool data visualization project...")
164
+
165
+ submit_button = gr.Button("Register", variant="primary")
166
+ registration_feedback = gr.Markdown()
167
+
168
+ with gr.TabItem("πŸ‘‘ Organizer Dashboard"):
169
+ gr.Markdown("## Welcome, Organizer!")
170
+ gr.Markdown("Here you can view registered participants and run the AI-powered team matching process.")
171
+
172
+ with gr.Accordion("View Registered Participants", open=False):
173
+ refresh_button = gr.Button("πŸ”„ Refresh List")
174
+ participants_df_out = gr.DataFrame(value=get_participants_dataframe, interactive=False)
175
+
176
+ gr.Markdown("### Run Matching")
177
+ organizer_criteria_in = gr.Textbox(
178
+ label="Matching Criteria",
179
+ lines=4,
180
+ value="Create teams of 3. Try to balance skills in each team (e.g., frontend, backend, data).",
181
+ placeholder="Describe your ideal team composition..."
182
+ )
183
+ run_button = gr.Button("πŸš€ Run AI Matching", variant="primary")
184
+
185
+ gr.Markdown("### 🀝 Matched Teams")
186
+ matching_results_out = gr.Markdown("Matching has not been run yet.")
187
+
188
+ with gr.Accordion("Agent Logs", open=False, visible=False) as log_panel:
189
+ log_output = gr.Code(
190
+ label="Live Logs",
191
+ lines=15,
192
+ interactive=False,
193
+ )
194
+
195
+ gr.Markdown("<p align='center'>Powered by Tiny Agent</p>")
196
+
197
+ # --- Event Handlers ---
198
+ submit_button.click(
199
+ fn=register_participant,
200
+ inputs=[name_in, email_in, linkedin_in, background_in, goals_in],
201
+ outputs=[registration_feedback, participants_df_out]
202
+ )
203
+
204
+ refresh_button.click(
205
+ fn=refresh_participants_list,
206
+ inputs=[],
207
+ outputs=[participants_df_out]
208
+ )
209
+
210
+ run_button.click(
211
+ fn=run_matching_process,
212
+ inputs=[organizer_criteria_in],
213
+ outputs=[matching_results_out, log_output, log_panel]
214
+ )
215
+
216
+ # --- Launching the App ---
217
+ if __name__ == "__main__":
218
+ try:
219
+ logger.info("Launching Gradio app...")
220
+ # queue() is important for handling multiple users and async calls
221
+ app.queue().launch(share=False)
222
+ except KeyboardInterrupt:
223
+ logger.info("Gradio app shutting down.")
224
+ finally:
225
+ # Clean up agent resources
226
+ logger.info("Closing agent resources...")
227
+ # We need to run the async close method
228
+ asyncio.run(agent.close())
229
+ logger.info("Cleanup complete.")
hackathon_organizer/database.py ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sqlite3
2
+ import pandas as pd
3
+ from typing import Dict, Any, List
4
+
5
+ DB_PATH = "hackathon_participants.db"
6
+ TABLE_NAME = "participants"
7
+
8
+ def initialize_database():
9
+ """
10
+ Initializes the database and creates the participants table if it doesn't exist.
11
+ """
12
+ with sqlite3.connect(DB_PATH) as conn:
13
+ cursor = conn.cursor()
14
+ cursor.execute(f"""
15
+ CREATE TABLE IF NOT EXISTS {TABLE_NAME} (
16
+ email TEXT PRIMARY KEY,
17
+ name TEXT NOT NULL,
18
+ linkedin_profile TEXT,
19
+ background TEXT,
20
+ goals TEXT
21
+ )
22
+ """)
23
+ conn.commit()
24
+
25
+ def add_participant(participant: Dict[str, Any]):
26
+ """
27
+ Adds a new participant to the database.
28
+
29
+ Args:
30
+ participant: A dictionary containing participant data.
31
+ Keys should be 'email', 'name', 'linkedin_profile', 'background', 'goals'.
32
+ """
33
+ with sqlite3.connect(DB_PATH) as conn:
34
+ cursor = conn.cursor()
35
+ cursor.execute(f"""
36
+ INSERT OR REPLACE INTO {TABLE_NAME} (email, name, linkedin_profile, background, goals)
37
+ VALUES (:email, :name, :linkedin_profile, :background, :goals)
38
+ """, participant)
39
+ conn.commit()
40
+
41
+ def get_participants_dataframe() -> pd.DataFrame:
42
+ """
43
+ Retrieves all participants from the database and returns them as a pandas DataFrame.
44
+
45
+ Returns:
46
+ A pandas DataFrame containing all participant data.
47
+ """
48
+ with sqlite3.connect(DB_PATH) as conn:
49
+ df = pd.read_sql_query(f"SELECT * FROM {TABLE_NAME}", conn)
50
+ return df
51
+
52
+ if __name__ == '__main__':
53
+ # Example usage and basic test
54
+ print("Initializing database...")
55
+ initialize_database()
56
+ print("Database initialized.")
57
+
58
+ # Sample participants
59
+ participants_to_add = [
60
+ {
61
+ "email": "[email protected]",
62
+ "name": "Alice Wonderland",
63
+ "linkedin_profile": "linkedin.com/in/alicew",
64
+ "background": "5 years of experience in frontend development with React and TypeScript. Interested in UI/UX design.",
65
+ "goals": "I want to build a cool project for my portfolio and learn about backend development."
66
+ },
67
+ {
68
+ "email": "[email protected]",
69
+ "name": "Bob Builder",
70
+ "linkedin_profile": "linkedin.com/in/bobb",
71
+ "background": "Backend developer specializing in Python, Django, and PostgreSQL. I'm also a DevOps enthusiast.",
72
+ "goals": "Looking to work on a challenging problem, maybe involving infrastructure or data engineering."
73
+ },
74
+ {
75
+ "email": "[email protected]",
76
+ "name": "Charlie Chocolate",
77
+ "linkedin_profile": "linkedin.com/in/charliec",
78
+ "background": "Data scientist with expertise in Python, Pandas, Scikit-learn, and TensorFlow. I love creating predictive models.",
79
+ "goals": "I hope to apply my machine learning skills to a real-world problem and collaborate with a diverse team."
80
+ }
81
+ ]
82
+
83
+ print(f"Adding {len(participants_to_add)} participants...")
84
+ for p in participants_to_add:
85
+ add_participant(p)
86
+ print("Participants added.")
87
+
88
+ print("\nRetrieving all participants:")
89
+ df = get_participants_dataframe()
90
+ print(df)
91
+
92
+ # Verify data
93
+ assert len(df) == 3
94
+ assert "[email protected]" in df["email"].values
95
+ print("\nData verified successfully.")
hackathon_organizer/hackathon_participants.db ADDED
Binary file (41 kB). View file
 
hackathon_organizer/matching_agent.py ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import pandas as pd
3
+ from tinyagent import TinyCodeAgent
4
+ from textwrap import dedent
5
+
6
+ organizer_prompt = dedent("""
7
+ You are a brilliant hackathon team-matching AI.
8
+ Your task is to form teams from a list of participants provided in a pandas DataFrame.
9
+ You will be given the DataFrame in a variable named `participants_df`.
10
+ You will also be given the organizer's criteria in a variable named `organizer_criteria`.
11
+
12
+ Your goal is to write and execute Python code using the `run_python` tool to group these participants into balanced teams.
13
+
14
+ Follow these steps:
15
+ 1. **Analyze the Data**: Inspect the `participants_df` DataFrame to understand the skills, backgrounds, and goals of the participants.
16
+ 2. **Plan Your Logic**: Based on the `organizer_criteria`, decide on a strategy for forming teams. Consider things like team size, skill diversity (e.g., frontend, backend, data science), and aligning participants' goals.
17
+ 3. **Implement the Matching**: Write Python code to create the teams. You can iterate through the DataFrame, use clustering algorithms, or any other method you see fit. Your code should produce a list of teams, where each team is a list of participant dictionaries.
18
+ 4. **Format the Output**: Once you have the teams, your final step is to generate a user-friendly report in Markdown format. For each team, list the members and write a brief, one-sentence justification for why they are a good match, based on their combined skills and goals.
19
+
20
+ Example of final output format:
21
+
22
+ ```markdown
23
+ ## Team 1
24
+
25
+ * **Alice Wonderland** (Frontend, React)
26
+ * **Bob Builder** (Backend, Python)
27
+ * **Charlie Chocolate** (Data Science)
28
+
29
+ **Justification**: This team has a strong, well-rounded skill set covering frontend, backend, and data science, making them capable of building a full-stack application.
30
+ ```
31
+
32
+ Do not ask for feedback. Execute the plan and provide the final Markdown report using the `final_answer` tool.
33
+ I can only see the final answer, not what happens in tool calls, so provide the full report in the final answer. Do not truncate team information
34
+ """)
35
+
36
+ def create_matching_agent(log_manager=None) -> TinyCodeAgent:
37
+ """
38
+ Initializes and configures a TinyCodeAgent for matching hackathon participants.
39
+
40
+ Args:
41
+ log_manager: An optional logging manager instance.
42
+
43
+ Returns:
44
+ A configured TinyCodeAgent instance.
45
+ """
46
+ # Create the agent without the system_prompt parameter
47
+ agent = TinyCodeAgent(
48
+ model="gpt-4.1-mini",
49
+ api_key=os.environ.get("OPENAI_API_KEY"),
50
+ log_manager=log_manager,
51
+ pip_packages=["pandas", "numpy", "scikit-learn"],
52
+ #authorized_imports=["pandas", "numpy", "io", "base64","collections","itertools"],
53
+ local_execution=False, # Use remote Modal for security by default
54
+ )
55
+
56
+ # Set the system prompt separately
57
+
58
+
59
+ return agent
60
+
61
+ async def run_matching(
62
+ agent: TinyCodeAgent,
63
+ participants_df: pd.DataFrame,
64
+ organizer_criteria: str
65
+ ) -> str:
66
+ """
67
+ Runs the matching process using the configured agent.
68
+
69
+ Args:
70
+ agent: The TinyCodeAgent instance.
71
+ participants_df: A DataFrame with participant data.
72
+ organizer_criteria: A string containing the organizer's preferences.
73
+
74
+ Returns:
75
+ The final markdown report of the matched teams.
76
+ """
77
+ # Set the participant data and criteria as variables for the agent's environment
78
+ print(participants_df.head())
79
+ agent.set_user_variables({
80
+ "participants_df": participants_df,
81
+ "organizer_criteria": organizer_criteria
82
+ })
83
+
84
+ # The user prompt is simple, as the main instructions are in the system prompt
85
+ task = dedent("""
86
+
87
+ You are a brilliant hackathon team-matching AI.
88
+ Your task is to form teams from a list of participants provided in a pandas DataFrame.
89
+ You will be given the DataFrame in a variable named `participants_df`.
90
+
91
+ Your goal is to write and execute Python code using the `run_python` tool to group these participants into balanced teams.""")
92
+
93
+
94
+ task = organizer_prompt+'\n\n'
95
+
96
+ task += ("Form the teams based on the provided data and criteria."
97
+ f"\n<Organizer Criteria>\n{organizer_criteria}\n</Organizer Criteria>")
98
+
99
+ final_report = await agent.run(task, max_turns=15)
100
+ print(agent.messages)
101
+ return final_report
hackathon_organizer/requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ tinyagent-py[all]==0.0.12
2
+ cloudpickle
3
+ modal
4
+ jinja2
5
+ pyyaml
6
+ gradio[mcp]
7
+ pandas
hackathon_organizer/tests/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # This file allows the 'tests' directory to be discovered as a package.
hackathon_participants.db ADDED
Binary file (41 kB). View file
 
main.py ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Hackathon Team Organizer - Main Entry Point
4
+
5
+ This script launches the Hackathon Team Organizer application.
6
+ It ensures the working directory is set correctly before running the app.
7
+ """
8
+ import os
9
+ import sys
10
+ import subprocess
11
+
12
+ def main():
13
+ # Get the directory where this script is located
14
+ script_dir = os.path.dirname(os.path.abspath(__file__))
15
+
16
+ # Change to the script directory to ensure relative paths work
17
+ os.chdir(script_dir)
18
+
19
+ # Add the current directory to the Python path
20
+ sys.path.insert(0, script_dir)
21
+
22
+ print("Starting Hackathon Team Organizer...")
23
+ print(f"Working directory: {os.getcwd()}")
24
+
25
+ # Check for OpenAI API key
26
+ if not os.environ.get("OPENAI_API_KEY"):
27
+ print("\n⚠️ WARNING: OPENAI_API_KEY environment variable is not set!")
28
+ print("The application requires an OpenAI API key to function properly.")
29
+ print("Please set it using:")
30
+ print(" export OPENAI_API_KEY='your-api-key' (macOS/Linux)")
31
+ print(" set OPENAI_API_KEY='your-api-key' (Windows)\n")
32
+ print("Running simplified version without AI matching...")
33
+ app_script = "hackathon_organizer/app_simple.py"
34
+ else:
35
+ print("OpenAI API key found. Running full version with AI matching...")
36
+ app_script = "hackathon_organizer/app.py"
37
+
38
+ # Run the application
39
+ try:
40
+ print(f"Launching application: {app_script}")
41
+ subprocess.run([sys.executable, app_script], check=True)
42
+ except KeyboardInterrupt:
43
+ print("\nApplication stopped by user.")
44
+ except subprocess.CalledProcessError as e:
45
+ print(f"\nError running the application: {e}")
46
+ sys.exit(1)
47
+ except Exception as e:
48
+ print(f"\nUnexpected error: {e}")
49
+ sys.exit(1)
50
+
51
+ if __name__ == "__main__":
52
+ main()
product_manager/organizer.md ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ #HackBuddyAI
3
+
4
+ Gradio APP for Hackathon Organizer
5
+
6
+ ## Problem
7
+ Many people join hackathons individually, and they need to be matched with other individuals to form a team. If the formed team is not suitable, non-of the team members will benefit from the hackathon, they will churn and not participate in the next hackathon.
8
+
9
+ - Help individuals find the right team
10
+ - If a selected team is not suitable, or some of participants didn't show up, the organizer could re-run the matching process to find a new team in no time.
11
+
12
+ ## Solution
13
+ 1. Web application for participants to fill their profile and goals, e_mail field to be used as a unique identifier, link to their linkedin profile, text field (multilined) for their background, skills, why they like to join the hackathon, etc.
14
+
15
+ ### 2. On form submission, the data will be stored in a database/ Google Sheet / SQLite
16
+
17
+ ### 3. Organizer part:
18
+ Organizer could define custom system prompt, to navigate the system for matching the participants, for example group size, why organizer looks to have in each group, etc.
19
+
20
+ ### 4. Matching Proccess,
21
+ AI Agent, will have access to pandas dataframe, including the participants data and organizer prefrences for matching.
22
+ It use its python code execution tool to actually interact with the data, and match the participants based on defined criteria.
23
+
24
+ ## End result
25
+ List of teams with their members, and a short description why they are a good match. in Markdown format.
26
+
27
+
28
+ ## Tech Stack
29
+ - Gradio
30
+ - Tiny Agent
31
+ - Tiny Code Agent
32
+ - Pandas
33
+
34
+ for developing the agent part we use tiny agent library, you have access to the documentation in the LLM_API_DOC.md file.
35
+
36
+ For the frontend we use gradio, gradio has an integration with tiny agent as well.
37
+
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ tinyagent-py[all]==0.0.12
2
+ cloudpickle
3
+ modal
4
+ jinja2
5
+ pyyaml
6
+ gradio[mcp]