EATosin commited on
Commit
bdb087c
Β·
verified Β·
1 Parent(s): 9e93904

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +158 -0
app.py ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import google.generativeai as genai
3
+ from github import Github
4
+ import os
5
+ from dotenv import load_dotenv
6
+
7
+ # --- CONFIG & SETUP ---
8
+ st.set_page_config(page_title="DevResume AI", layout="wide", page_icon="πŸš€")
9
+
10
+ # Load Keys (Cloud or Local)
11
+ api_key = os.getenv("GEMINI_API_KEY")
12
+ github_token = os.getenv("GITHUB_TOKEN")
13
+
14
+ # Fallback for local testing
15
+ if not api_key:
16
+ load_dotenv()
17
+ api_key = os.getenv("GEMINI_API_KEY")
18
+ github_token = os.getenv("GITHUB_TOKEN")
19
+
20
+ # --- ENGINE 1: GITHUB CRAWLER ---
21
+ def fetch_github_data(username):
22
+ """
23
+ SOTA Scraper: Fetches top repos, stars, languages, and README summaries.
24
+ """
25
+ try:
26
+ # Auth guarantees higher rate limits
27
+ g = Github(github_token) if github_token else Github()
28
+ user = g.get_user(username)
29
+
30
+ data = {
31
+ "name": user.name or username,
32
+ "bio": user.bio or "AI & Software Engineer",
33
+ "url": user.html_url,
34
+ "repos": []
35
+ }
36
+
37
+ # Sort repos by Stars (Metric of Impact)
38
+ repos = user.get_repos()
39
+ sorted_repos = sorted(repos, key=lambda x: x.stargazers_count, reverse=True)[:6]
40
+
41
+ for repo in sorted_repos:
42
+ # Skip forked repos to focus on original work
43
+ if repo.fork:
44
+ continue
45
+
46
+ # Smart README Fetcher
47
+ readme_text = "No details provided."
48
+ try:
49
+ readme = repo.get_readme()
50
+ if readme.decoded_content:
51
+ readme_text = readme.decoded_content.decode("utf-8")[:1500] # Context Window Optimization
52
+ except:
53
+ pass
54
+
55
+ data["repos"].append({
56
+ "name": repo.name,
57
+ "stars": repo.stargazers_count,
58
+ "lang": repo.language,
59
+ "desc": repo.description,
60
+ "readme": readme_text
61
+ })
62
+
63
+ return data
64
+ except Exception as e:
65
+ return {"error": f"GitHub API Error: {str(e)}"}
66
+
67
+ # --- ENGINE 2: GEMINI RESUME ARCHITECT ---
68
+ def generate_resume_content(profile, target_role):
69
+ genai.configure(api_key=api_key)
70
+
71
+ # Try SOTA Model first
72
+ try:
73
+ model = genai.GenerativeModel('gemini-2.5-flash')
74
+ except:
75
+ model = genai.GenerativeModel('gemini-1.5-flash')
76
+
77
+ # Context Construction
78
+ repo_context = ""
79
+ for r in profile['repos']:
80
+ repo_context += f"""
81
+ - PROJECT: {r['name']} ({r['stars']} Stars, {r['lang']})
82
+ DESCRIPTION: {r['desc']}
83
+ TECHNICAL CONTEXT: {r['readme']}
84
+ """
85
+
86
+ prompt = f"""
87
+ You are a Senior Technical Recruiter for a FAANG company.
88
+
89
+ CANDIDATE: {profile['name']}
90
+ ROLE: {target_role}
91
+
92
+ TASK:
93
+ Write the "Featured Projects" section of a resume based on their GitHub code.
94
+
95
+ RULES:
96
+ 1. Select the top 3 most technically impressive projects.
97
+ 2. Write 3 bullet points for each project.
98
+ 3. STRICTLY use the "XYZ Pattern" (Accomplished [X] as measured by [Y], by doing [Z]).
99
+ 4. Quantify impact where possible (e.g., "Reduced latency by...", "Processed 10k+ requests...").
100
+ 5. Highlight stack: Python, PyTorch, FastAPI, Docker, etc.
101
+
102
+ INPUT DATA (GitHub Scrape):
103
+ {repo_context}
104
+
105
+ OUTPUT FORMAT (Markdown):
106
+ ## πŸš€ Featured Projects
107
+
108
+ **[Project Name]** | *[Languages/Tools]*
109
+ * [Bullet 1 using XYZ pattern]
110
+ * [Bullet 2 using XYZ pattern]
111
+ * [Bullet 3 using XYZ pattern]
112
+ """
113
+
114
+ try:
115
+ response = model.generate_content(prompt)
116
+ return response.text
117
+ except Exception as e:
118
+ return f"AI Generation Error: {str(e)}"
119
+
120
+ # --- UI LAYER ---
121
+ with st.sidebar:
122
+ st.title("πŸš€ DevResume AI")
123
+ st.markdown("Turns your **GitHub Code** into a **Senior Resume** instantly.")
124
+ st.info("Powered by **Gemini 2.5** & **PyGithub**")
125
+ st.caption("Built by Owadokun Tosin Tobi")
126
+
127
+ st.title("πŸ‘¨β€πŸ’» GitHub-to-Resume Generator")
128
+ st.markdown("Stop writing generic bullets. Let AI analyze your actual code and write high-impact XYZ statements.")
129
+
130
+ col1, col2 = st.columns([1, 2])
131
+
132
+ with col1:
133
+ gh_user = st.text_input("GitHub Username", placeholder="eatosin")
134
+ role = st.text_input("Target Role", value="Senior AI Engineer")
135
+ generate_btn = st.button("✨ Generate Resume", type="primary")
136
+
137
+ with col2:
138
+ if generate_btn:
139
+ if not gh_user:
140
+ st.warning("Please enter a username.")
141
+ else:
142
+ with st.status("πŸ•·οΈ Crawling GitHub Ecosystem...", expanded=True) as status:
143
+ st.write("Connecting to GitHub API...")
144
+ data = fetch_github_data(gh_user)
145
+
146
+ if "error" in data:
147
+ status.update(label="❌ Error", state="error")
148
+ st.error(data['error'])
149
+ else:
150
+ st.write(f"βœ… Found {len(data['repos'])} repositories.")
151
+ st.write("🧠 Analyzing READMEs & Codebase...")
152
+ resume = generate_resume_content(data, role)
153
+ status.update(label="βœ… Resume Generated!", state="complete")
154
+
155
+ st.markdown("---")
156
+ st.subheader("πŸ“„ Generated Project Section")
157
+ st.markdown(resume)
158
+ st.download_button("πŸ“₯ Download Markdown", resume, file_name="featured_projects.md")