Spaces:
Running
Running
File size: 9,344 Bytes
1f38061 c47b1e1 1f38061 c47b1e1 1f38061 c47b1e1 1f38061 c47b1e1 1f38061 c47b1e1 1f38061 c47b1e1 1f38061 5bff28e 4996d09 8cb7bb9 5bff28e 1f38061 c47b1e1 1f38061 c47b1e1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
import gradio as gr
import pandas as pd
import asyncio
import logging
import sys
import os
import io
from contextlib import asynccontextmanager
# Change from absolute imports to relative imports
from database import initialize_database, add_participant, get_participants_dataframe
from matching_agent import create_matching_agent, run_matching
from tinyagent.hooks.logging_manager import LoggingManager
from tinyagent.hooks.logging_manager import LoggingManager
import logging
# --- Logging Setup ---
log_manager = LoggingManager(default_level=logging.INFO)
log_manager.set_levels({
'tinyagent.hooks.gradio_callback': logging.DEBUG,
'tinyagent.tiny_agent': logging.DEBUG,
'tinyagent.mcp_client': logging.DEBUG,
'tinyagent.code_agent': logging.DEBUG,
})
console_handler = logging.StreamHandler(sys.stdout)
log_manager.configure_handler(
console_handler,
format_string='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.DEBUG
)
# Gradio log handler
log_stream = io.StringIO()
gradio_handler = logging.StreamHandler(log_stream)
log_manager.configure_handler(
gradio_handler,
format_string='%(asctime)s - %(levelname)s - %(name)s - %(message)s',
level=logging.DEBUG # Capture detailed logs for the UI
)
logger = log_manager.get_logger('app')
# --- Initial Setup ---
logger.info("Initializing database...")
initialize_database()
# Check for API key
if not os.environ.get("OPENAI_API_KEY"):
raise ValueError("The OPENAI_API_KEY environment variable is not set. Please set it before running the app.")
# --- Session Management ---
@asynccontextmanager
async def agent_session():
"""Create and manage a session-specific agent."""
session_agent = create_matching_agent(log_manager=log_manager)
try:
yield session_agent
finally:
await session_agent.close()
logger.info("Session agent resources cleaned up")
# --- Gradio UI Functions ---
def register_participant(name, email, linkedin, background, goals):
"""Callback function to register a new participant."""
if not all([name, email]):
return "Please provide at least a name and email.", get_participants_dataframe()
participant_data = {
"name": name,
"email": email,
"linkedin_profile": linkedin,
"background": background,
"goals": goals
}
try:
add_participant(participant_data)
feedback = f"β
Success! Participant '{name}' registered."
logger.info(f"Registered new participant: {email}")
except Exception as e:
feedback = f"β Error! Could not register participant. Reason: {e}"
logger.error(f"Failed to register participant {email}: {e}")
return feedback, get_participants_dataframe()
def refresh_participants_list():
"""Callback to reload the participant data from the database."""
return get_participants_dataframe()
async def run_matching_process(organizer_criteria, progress=gr.Progress(track_tqdm=True)):
"""Async callback to run the team matching process, with live log streaming."""
# 1. Clear previous logs and show panel
log_stream.seek(0)
log_stream.truncate(0)
progress(0, desc="Initializing...")
yield [
gr.update(visible=True, open=True), # log_panel
"Starting matching process...\n", # log_output
"π Setting up the matching process..." # matching_results_out
]
# 2. Get participants and perform initial checks
logger.info("Fetching participants...")
progress(0, desc="Fetching participants...")
participants_df = get_participants_dataframe()
if len(participants_df) < 2:
warning_msg = "Matching process aborted: not enough participants."
logger.warning(warning_msg)
yield [
gr.update(), # log_panel
log_stream.getvalue(), # log_output
"Cannot run matching with fewer than 2 participants." # matching_results_out
]
return
logger.info(f"Running matching for {len(participants_df)} participants.")
progress(0.2, desc="π§ Agent is thinking...")
# 3. Create a session-specific agent and run matching
async with agent_session() as session_agent:
logger.info("Created session-specific agent")
# Create a background task for the core matching logic
match_task = asyncio.create_task(
run_matching(session_agent, participants_df, organizer_criteria)
)
# 4. Stream logs while the agent works
while not match_task.done():
await asyncio.sleep(0.5) # Poll for new logs every 0.5s
yield [
gr.update(), # log_panel
log_stream.getvalue(), # log_output
gr.update() # matching_results_out - No change to final output yet
]
# 5. Process the final result from the agent
try:
final_report = await match_task
logger.info("Matching process completed successfully.")
progress(1.0, desc="β
Done!")
yield [
gr.update(), # log_panel
log_stream.getvalue(), # log_output
final_report # matching_results_out
]
except Exception as e:
logger.error(f"An error occurred during the matching process: {e}", exc_info=True)
yield [
gr.update(), # log_panel
log_stream.getvalue(), # log_output
f"An error occurred: {e}" # matching_results_out
]
# --- Gradio App Definition ---
with gr.Blocks(theme=gr.themes.Default(
font=[gr.themes.GoogleFont("Inter"), "Arial", "sans-serif"]
), title="HackBuddyAI") as app:
gr.Markdown("# π€ HackBuddyAI")
with gr.Tabs():
with gr.TabItem("π€ Participant Registration"):
gr.Markdown("## Welcome, Participant!")
gr.Markdown("Fill out the form below to register for the hackathon.")
with gr.Row():
with gr.Column():
name_in = gr.Textbox(label="Full Name")
email_in = gr.Textbox(label="Email Address")
linkedin_in = gr.Textbox(label="LinkedIn Profile URL", placeholder="Optional")
with gr.Column():
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...")
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...")
submit_button = gr.Button("Register", variant="primary")
registration_feedback = gr.Markdown()
with gr.TabItem("π Organizer Dashboard"):
gr.Markdown("## Welcome, Organizer!")
gr.Markdown("Here you can view registered participants and run the AI-powered team matching process.")
with gr.Accordion("View Registered Participants", open=False):
refresh_button = gr.Button("π Refresh List")
participants_df_out = gr.DataFrame(value=get_participants_dataframe, interactive=False)
gr.Markdown("### Run Matching")
organizer_criteria_in = gr.Textbox(
label="Matching Criteria",
lines=4,
value="Create teams of 3. Try to balance skills in each team (e.g., frontend, backend, data).",
placeholder="Describe your ideal team composition..."
)
run_button = gr.Button("π Run AI Matching", variant="primary")
gr.Markdown("### π€ Matched Teams")
matching_results_out = gr.Markdown("Matching has not been run yet.")
with gr.Accordion("Agent Logs", open=False, visible=False) as log_panel:
log_output = gr.Code(
label="Live Logs",
lines=15,
interactive=False,
)
# Footer
gr.Markdown(
"<div style='text-align: center; margin-top: 20px;'>"
"Built with β€οΈ by <a href='https://github.com/askbudi/tinyagent' target='_blank'>TinyAgent</a>"
"<br>Start building your own AI agents with TinyAgent"
"</div>"
)
# --- Event Handlers ---
submit_button.click(
fn=register_participant,
inputs=[name_in, email_in, linkedin_in, background_in, goals_in],
outputs=[registration_feedback, participants_df_out]
)
refresh_button.click(
fn=refresh_participants_list,
inputs=[],
outputs=[participants_df_out]
)
run_button.click(
fn=run_matching_process,
inputs=[organizer_criteria_in],
outputs=[log_panel, log_output, matching_results_out]
)
# --- Launching the App ---
if __name__ == "__main__":
try:
logger.info("Launching Gradio app...")
# queue() is important for handling multiple users and async calls
app.queue().launch(share=False)
except KeyboardInterrupt:
logger.info("Gradio app shutting down.")
finally:
logger.info("Shutdown complete.") |