Raheel31 commited on
Commit
435ca27
·
verified ·
1 Parent(s): 701700d

Upload 5 files

Browse files
Files changed (5) hide show
  1. .gitattributes +35 -35
  2. .gitignore +0 -0
  3. README.md +79 -1
  4. app.py +150 -0
  5. requirements.txt +12 -0
.gitattributes CHANGED
@@ -1,35 +1,35 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
File without changes
README.md CHANGED
@@ -1,3 +1,81 @@
1
  ---
2
- license: apache-2.0
 
 
 
 
 
 
 
 
 
 
 
3
  ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: GenAI Career Agent
3
+ emoji: 💬
4
+ colorFrom: yellow
5
+ colorTo: purple
6
+ sdk: gradio
7
+ sdk_version: 5.42.0
8
+ app_file: app.py
9
+ pinned: false
10
+ hf_oauth: true
11
+ hf_oauth_scopes:
12
+ - inference-api
13
+ short_description: A generative AI model that acts as a career coach
14
  ---
15
+
16
+ A Resume–Job Fit Analysis chatbot built using **Gradio**, **FAISS Vector Search**, and the **Hugging Face Inference API**.
17
+ This Space hosts the **GenAI Career Agent**, a generative AI that analyzes user resumes, retrieves structured resume data through a vectorstore (FAISS), and evaluates how well a candidate fits any provided job description.
18
+
19
+ ### 🚀 Features
20
+
21
+ - **AI Career Coach** – Helps users understand job fit, strengths, and areas for improvement.
22
+ - **RAG Pipeline** – Uses FAISS to retrieve relevant resume chunks.
23
+ - **LLM-Powered Analysis** – Uses a remote Hugging Face model via `InferenceClient`.
24
+ - **Structured JSON Output** including:
25
+ - `job_fit_score`
26
+ - `fit_summary`
27
+ - `strengths`
28
+ - `missing_skills`
29
+ - `recommendations`
30
+ - **Secure Token Handling** with Hugging Face Space Secrets.
31
+
32
+ ### 📌 Current Capability
33
+
34
+ ✔ **Resume Parsing & Analysis**
35
+ The system currently parses the user's resume (pre-embedded with MiniLM) and produces job-fit analytics using RAG + LLM inference.
36
+
37
+ ### 🛠️ Upcoming Features
38
+
39
+ 🔜 **GitHub Repo Intelligence**
40
+ - Automatic retrieval of repositories
41
+ - Summarization of project impact
42
+ - Extraction of tech stack & coding patterns
43
+ - Integration into the job-fit score
44
+
45
+ 🔜 **LinkedIn Profile Integration**
46
+ - Work history extraction
47
+ - Skill inference
48
+ - Keyword alignment
49
+ - Soft-skill assessment
50
+
51
+ These features will be integrated into the same RAG pipeline so the model can reason across **Resume + GitHub + LinkedIn** for a unified career profile.
52
+
53
+ ### 🧠 How It Works
54
+
55
+ 1. Resume data is pre-embedded using
56
+ `sentence-transformers/all-MiniLM-L6-v2`.
57
+ 2. Embeddings are stored inside
58
+ `data/vectorstores/`.
59
+ 3. The FAISS retriever fetches the most relevant resume sections based on the job description.
60
+ 4. A custom prompt formats the retrieved text and sends it to the LLM.
61
+ 5. The LLM generates structured JSON insights.
62
+
63
+ ### 🗂️ Tech Stack
64
+
65
+ - **Gradio 5** (ChatInterface front-end)
66
+ - **LangChain Runnables**
67
+ - **FAISS** Vector Search
68
+ - **HuggingFace Embeddings**
69
+ - **Hugging Face Inference API**
70
+
71
+ ### 🔒 Token Handling
72
+
73
+ Set secrets in your Space
74
+
75
+
76
+ ### 📜 Model Licensing & Notices
77
+
78
+ 🧍 Personal / Educational Use
79
+
80
+ This is a personal project, intended solely for educational and career-analysis purposes.
81
+ Users are solely responsible for how they use the outputs.
app.py ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import gradio as gr
4
+ from huggingface_hub import InferenceClient
5
+
6
+ sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
7
+ from rag.logger import get_logger
8
+ from rag.analysis_chain import retriever, hf_llm, analyze_resume_against_job
9
+
10
+ logger = get_logger(__name__)
11
+
12
+ # -----------------------------------
13
+ # Load HuggingFace API key
14
+ # -----------------------------------
15
+ HF_API_TOKEN = os.getenv("HUGGINGFACE_API_TOKEN")
16
+ if not HF_API_TOKEN:
17
+ raise RuntimeError("Environment variable HUGGINGFACE_API_TOKEN is missing!")
18
+
19
+ client = InferenceClient(
20
+ token=HF_API_TOKEN,
21
+ model="" # When in use insert model name as parameter here
22
+ )
23
+
24
+ # -----------------------------------
25
+ # System Prompt
26
+ # -----------------------------------
27
+ DEFAULT_SYSTEM_MESSAGE = """
28
+ You are a helpful resume-analysis chatbot.
29
+
30
+ You can perform the following tasks on the data you have:
31
+ 1. Job description analysis using the RAG pipeline.
32
+ 2. Candidate summarization using the vectorstore *WHICH YOU ALREADY HAVE*.
33
+ 3. General conversation.
34
+
35
+ Always respond clearly and professionally as if you were a talent aquisition specialist.
36
+ """
37
+
38
+ # -----------------------------------
39
+ # INTENT DETECTOR
40
+ # -----------------------------------
41
+ def detect_intent(user_message: str):
42
+ """Lightweight rule-based intent classifier."""
43
+ message = user_message.lower()
44
+
45
+ # --- JOB DESCRIPTION ANALYSIS ---
46
+ jd_keywords = [
47
+ "responsibilities", "requirements", "we are looking for",
48
+ "qualifications", "role description", "job description",
49
+ "candidate must", "skills required", "apply", "position",
50
+ "looking for a", "experience required"
51
+ ]
52
+ if any(k in message for k in jd_keywords):
53
+ return "job_analysis"
54
+
55
+ # --- CANDIDATE SUMMARY ---
56
+ candidate_keywords = [
57
+ "candidate", "tell me about him", "tell me about her", "profile summary",
58
+ "summary", "skills", "experience", "background", "what can he do",
59
+ "what is his experience", "what is his background", "about the candidate", "about his resume"
60
+ ]
61
+ if any(k in message for k in candidate_keywords):
62
+ return "candidate_info"
63
+
64
+ # --- DEFAULT ---
65
+ return "general"
66
+
67
+
68
+ # -----------------------------------
69
+ # BOT RESPONSE
70
+ # -----------------------------------
71
+ def bot_response(message, history):
72
+ system_msg = DEFAULT_SYSTEM_MESSAGE
73
+ max_tokens = 500
74
+ temperature = 0.7
75
+ top_p = 0.95
76
+ intent = detect_intent(message)
77
+
78
+ # -----------------------------------
79
+ # INTENT 1 → JOB ANALYSIS USING RAG
80
+ # -----------------------------------
81
+ if intent == "job_analysis":
82
+ rag_output = analyze_resume_against_job(
83
+ job_description=message,
84
+ retriever=retriever,
85
+ llm_callable=hf_llm
86
+ )
87
+ prompt = f"{system_msg}\n\n{rag_output}"
88
+
89
+ # -----------------------------------
90
+ # INTENT 2 → CANDIDATE SUMMARY
91
+ # -----------------------------------
92
+ elif intent == "candidate_info":
93
+ # Use LCEL retriever interface (correct for VectorStoreRetriever)
94
+ retrieved_docs = retriever.invoke("candidate overall profile")
95
+ combined = "\n".join([doc.page_content for doc in retrieved_docs])
96
+
97
+ prompt = f"""
98
+ You are a professional candidate summarization assistant.
99
+
100
+ Using the resume data below, create a detailed profile summary.
101
+
102
+ Resume Data:
103
+ {combined}
104
+
105
+ Provide:
106
+ - background
107
+ - key experiences
108
+ - technical + soft skills
109
+ - strengths
110
+ - ideal job roles
111
+ """
112
+
113
+ # -----------------------------------
114
+ # INTENT 3 → GENERAL CHAT
115
+ # -----------------------------------
116
+ else:
117
+ prompt = f"{system_msg}\nUser: {message}"
118
+
119
+ # -----------------------------------
120
+ # STREAMING HF LLM OUTPUT
121
+ # -----------------------------------
122
+ response = ""
123
+ for chunk in client.chat_completion(
124
+ messages=[{"role": "user", "content": prompt}],
125
+ max_tokens=max_tokens,
126
+ temperature=temperature,
127
+ top_p=top_p,
128
+ stream=True
129
+ ):
130
+ token = chunk.choices[0].delta.content or ""
131
+ response += token
132
+ yield response
133
+
134
+
135
+ # -----------------------------------
136
+ # UI: ChatGPT-style interface
137
+ # -----------------------------------
138
+ chatbot = gr.ChatInterface(
139
+ fn=bot_response,
140
+ title="GenAI Career Agent"
141
+ )
142
+
143
+
144
+ # -----------------------------------
145
+ # Layout (NO LOGIN)
146
+ # -----------------------------------
147
+ with gr.Blocks() as demo:
148
+ gr.Markdown("## Resume Analyst RAG Chatbot")
149
+ gr.Markdown("Uses FAISS + HuggingFace LLM + custom RAG analysis pipeline.")
150
+ chatbot.render()
requirements.txt ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ gradio>=5.0
2
+ huggingface_hub>=0.22.0
3
+ langchain>=0.2.0
4
+ langchain-community>=0.2.0
5
+ langchain-huggingface>=0.1.0
6
+ langchain-text-splitters>=0.0.1
7
+
8
+ faiss-cpu
9
+ sentence-transformers
10
+
11
+ requests
12
+ python-dotenv