Spaces:
Sleeping
Sleeping
import streamlit as st | |
import os | |
import tempfile | |
from pathlib import Path | |
import time | |
from typing import List, Dict | |
import pandas as pd | |
# Initialize Streamlit app | |
st.set_page_config( | |
page_title="IntraTalent Resume Processor", | |
page_icon="π", | |
layout="wide" | |
) | |
def save_uploaded_file(uploaded_file) -> str: | |
"""Save uploaded file to temporary directory and return path.""" | |
try: | |
with tempfile.NamedTemporaryFile(delete=False, suffix='.pdf') as tmp_file: | |
tmp_file.write(uploaded_file.getvalue()) | |
return tmp_file.name | |
except Exception as e: | |
st.error(f"Error saving file: {e}") | |
return None | |
def process_resumes(uploaded_files: List[st.UploadedFile]) -> Dict: | |
"""Process multiple resumes and return results.""" | |
results = {} | |
progress_bar = st.progress(0) | |
for idx, file in enumerate(uploaded_files): | |
if file.type != "application/pdf": | |
st.warning(f"Skipping {file.name}: Not a PDF file") | |
continue | |
temp_path = save_uploaded_file(file) | |
if temp_path: | |
try: | |
name, projects = parse_resume(temp_path) | |
results[file.name] = { | |
"name": name, | |
"projects": projects | |
} | |
# Update progress | |
progress_bar.progress((idx + 1) / len(uploaded_files)) | |
except Exception as e: | |
st.error(f"Error processing {file.name}: {e}") | |
finally: | |
# Clean up temporary file | |
os.unlink(temp_path) | |
return results | |
def display_results(results: Dict): | |
"""Display processed resume results in an organized manner.""" | |
if not results: | |
return | |
st.subheader("Processed Resumes") | |
for filename, data in results.items(): | |
with st.expander(f"π {data['name']} ({filename})"): | |
if data['projects']: | |
df = pd.DataFrame(data['projects']) | |
st.dataframe( | |
df, | |
column_config={ | |
"name": "Project Name", | |
"description": "Description" | |
}, | |
hide_index=True | |
) | |
else: | |
st.info("No projects found in this resume") | |
def main(): | |
st.title("IntraTalent Resume Processor") | |
# File uploader section | |
st.header("Upload Resumes") | |
uploaded_files = st.file_uploader( | |
"Upload up to 10 resumes (PDF only)", | |
type=['pdf'], | |
accept_multiple_files=True, | |
key="resume_uploader" | |
) | |
# Validate number of files | |
if len(uploaded_files) > 10: | |
st.error("Maximum 10 files allowed. Please remove some files.") | |
return | |
# Process button | |
if uploaded_files and st.button("Process Resumes"): | |
with st.spinner("Processing resumes..."): | |
results = process_resumes(uploaded_files) | |
st.session_state['processed_results'] = results | |
display_results(results) | |
# Query section | |
st.header("Search Projects") | |
query = st.text_area( | |
"Enter your project requirements", | |
placeholder="Example: Looking for team members with experience in machine learning and computer vision...", | |
height=100 | |
) | |
if query and st.button("Search"): | |
if 'processed_results' not in st.session_state: | |
st.warning("Please process some resumes first!") | |
return | |
with st.spinner("Searching for matches..."): | |
# Here you would implement the embedding and similarity search | |
# Using the code from your original script | |
st.success("Search completed!") | |
# Display results in a nice format | |
st.subheader("Top Matches") | |
# Placeholder for search results | |
st.info("Feature coming soon: Will display matching projects and candidates based on similarity search") | |
if __name__ == "__main__": | |
main() |