Spaces:
Sleeping
Sleeping
import streamlit as st | |
import requests | |
from typing import Dict, List | |
import os | |
from dotenv import load_dotenv | |
# Load environment variables | |
load_dotenv() | |
# Page config | |
st.set_page_config( | |
page_title="100xEngineers Discovery Platform", | |
page_icon="π", | |
layout="wide", | |
initial_sidebar_state="expanded" | |
) | |
# API client setup | |
class APIClient: | |
def __init__(self): | |
# Get the Hugging Face Space URL from environment or use localhost | |
space_url = os.getenv("HF_SPACE_URL") | |
if space_url: | |
# In Hugging Face Spaces, the FastAPI service will be available at port 8000 | |
self.base_url = f"https://{space_url}-8000.hf.space" | |
else: | |
# Local development | |
self.base_url = "http://localhost:8000" | |
st.sidebar.text(f"API URL: {self.base_url}") | |
def _handle_response(self, response): | |
if response.ok: | |
return response.json() | |
st.error(f"Error: {response.status_code} - {response.text}") | |
return None | |
def get(self, endpoint: str): | |
try: | |
response = requests.get(f"{self.base_url}{endpoint}") | |
return self._handle_response(response) | |
except Exception as e: | |
st.error(f"API Error: {str(e)}") | |
return None | |
api = APIClient() | |
def create_profile(profile_data: dict): | |
# Validate and clean the data before sending | |
if profile_data.get("portfolio_url"): | |
url = profile_data["portfolio_url"].strip() | |
if not (url.startswith("http://") or url.startswith("https://")): | |
url = f"https://{url}" | |
try: | |
# Basic URL validation | |
if not url.replace("https://", "").replace("http://", ""): | |
profile_data.pop("portfolio_url", None) | |
else: | |
profile_data["portfolio_url"] = url | |
except Exception: | |
profile_data.pop("portfolio_url", None) | |
else: | |
profile_data.pop("portfolio_url", None) | |
try: | |
response = requests.post(f"{api.base_url}/api/profiles", json=profile_data) | |
if response.status_code == 422: | |
error_detail = response.json().get('detail', []) | |
if isinstance(error_detail, list): | |
for error in error_detail: | |
st.error(f"Validation Error: {error.get('msg')}") | |
else: | |
st.error(f"Validation Error: {error_detail}") | |
return None | |
elif not response.ok: | |
st.error(f"Server Error: {response.status_code}") | |
return None | |
return response.json() | |
except requests.exceptions.ConnectionError: | |
st.error("Could not connect to the server. Please make sure the backend is running.") | |
return None | |
except Exception as e: | |
st.error(f"An unexpected error occurred: {str(e)}") | |
return None | |
def search_profiles(query: str): | |
try: | |
response = requests.post( | |
f"{api.base_url}/api/search", | |
json={"query": query} # Send query in correct format | |
) | |
if not response.ok: | |
if response.status_code == 422: | |
st.error("Invalid search query format") | |
else: | |
st.error(f"Search failed with status code: {response.status_code}") | |
return [] | |
return response.json() | |
except requests.exceptions.ConnectionError: | |
st.error("Could not connect to the server. Please make sure the backend is running.") | |
return [] | |
except Exception as e: | |
st.error(f"An unexpected error occurred during search: {str(e)}") | |
return [] | |
def list_profiles(): | |
try: | |
response = requests.get(f"{api.base_url}/api/profiles") | |
if not response.ok: | |
st.error(f"Failed to fetch profiles: {response.status_code}") | |
return [] | |
return response.json() | |
except requests.exceptions.ConnectionError: | |
st.error("Could not connect to the server. Please make sure the backend is running.") | |
return [] | |
except Exception as e: | |
st.error(f"An unexpected error occurred while fetching profiles: {str(e)}") | |
return [] | |
# UI Components | |
st.title("100xEngineers Discovery Platform π") | |
# Sidebar navigation | |
page = st.sidebar.radio("Navigation", ["Search Profiles", "Create Profile", "View All Profiles"]) | |
if page == "Create Profile": | |
st.header("Create Your Profile") | |
with st.form("profile_form"): | |
name = st.text_input("Name", help="Enter your full name (minimum 2 characters)") | |
technical_skills = st.text_input("Technical Skills (comma-separated)", | |
help="Enter your technical skills, separated by commas") | |
projects = st.text_input("Projects (comma-separated)", | |
help="List your notable projects, separated by commas") | |
ai_expertise = st.text_input("AI Expertise (comma-separated)", | |
help="List your AI-related skills and expertise") | |
mentoring_preferences = st.text_area("Mentoring Preferences", | |
help="Describe your mentoring preferences (minimum 10 characters)") | |
collaboration_interests = st.text_input("Collaboration Interests (comma-separated)", | |
help="List your interests for collaboration") | |
portfolio_url = st.text_input("Portfolio URL", | |
help="Enter your portfolio URL (optional)") | |
submitted = st.form_submit_button("Create Profile") | |
if submitted: | |
if len(name.strip()) < 2: | |
st.error("Name must be at least 2 characters long") | |
elif len(mentoring_preferences.strip()) < 10: | |
st.error("Mentoring preferences must be at least 10 characters long") | |
else: | |
profile_data = { | |
"name": name.strip(), | |
"technical_skills": [s.strip() for s in technical_skills.split(",") if s.strip()], | |
"projects": [p.strip() for p in projects.split(",") if p.strip()], | |
"ai_expertise": [a.strip() for a in ai_expertise.split(",") if a.strip()], | |
"mentoring_preferences": mentoring_preferences.strip(), | |
"collaboration_interests": [c.strip() for c in collaboration_interests.split(",") if c.strip()], | |
"portfolio_url": portfolio_url.strip() if portfolio_url.strip() else None | |
} | |
if profile := create_profile(profile_data): | |
st.success("Profile created successfully!") | |
st.json(profile) | |
elif page == "Search Profiles": | |
st.header("Search Profiles") | |
st.markdown(""" | |
Search for engineers using natural language. Examples: | |
- "Find someone experienced in machine learning and NLP" | |
- "Looking for a mentor in backend development" | |
- "Need a collaborator for an open source AI project" | |
""") | |
query = st.text_input("Enter your search query in natural language") | |
if query: | |
results = search_profiles(query) | |
if results: | |
st.subheader(f"Found {len(results)} matches") | |
for result in results: | |
profile = result['profile'] | |
explanation = result['explanation'] | |
with st.expander(f"{profile['name']}"): | |
# Display match explanation | |
st.markdown(f"**Match Analysis:**\n{explanation}") | |
st.markdown("---") | |
# Display profile details | |
st.write("**Technical Skills:**", ", ".join(profile["technical_skills"])) | |
st.write("**AI Expertise:**", ", ".join(profile["ai_expertise"])) | |
st.write("**Projects:**", ", ".join(profile["projects"])) | |
st.write("**Mentoring Preferences:**", profile["mentoring_preferences"]) | |
st.write("**Collaboration Interests:**", ", ".join(profile["collaboration_interests"])) | |
if profile.get("portfolio_url"): | |
st.write("**Portfolio:**", profile["portfolio_url"]) | |
else: | |
st.info("No matching profiles found. Try adjusting your search query.") | |
else: # View All Profiles | |
st.header("All Profiles") | |
profiles = list_profiles() | |
if profiles: | |
for profile in profiles: | |
with st.expander(f"{profile['name']}"): | |
st.write("**Technical Skills:**", ", ".join(profile["technical_skills"])) | |
st.write("**AI Expertise:**", ", ".join(profile["ai_expertise"])) | |
st.write("**Projects:**", ", ".join(profile["projects"])) | |
st.write("**Mentoring Preferences:**", profile["mentoring_preferences"]) | |
st.write("**Collaboration Interests:**", ", ".join(profile["collaboration_interests"])) | |
if profile.get("portfolio_url"): | |
st.write("**Portfolio:**", profile["portfolio_url"]) | |
else: | |
st.info("No profiles found. Create one to get started!") |