BeyondJawad commited on
Commit
3b4a91d
·
verified ·
1 Parent(s): 2c704f8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +128 -133
app.py CHANGED
@@ -1,178 +1,173 @@
1
  import gradio as gr
2
- from huggingface_hub import InferenceClient
3
  import requests
 
4
 
5
- # Main + Fallback Models
6
  MODELS = [
7
  "meta-llama/Meta-Llama-3-8B-Instruct",
8
  "mistralai/Mistral-7B-Instruct-v0.3",
9
- "google/gemma-7b-it",
10
- "HuggingFaceH4/zephyr-7b-beta" # reliable fallback
11
  ]
12
 
13
- # ---------- Chat ----------
14
- def chat_with_ai(message, history):
15
  if history is None:
16
  history = []
17
  for model in MODELS:
18
  try:
19
  client = InferenceClient(model)
20
- conversation = "".join(
21
- [f"User: {h[0]}\nStudyMate: {h[1]}\n" for h in history]
22
- )
23
  prompt = (
24
- "You are StudyMate AI a friendly, multilingual personal tutor and assistant. "
25
- "You answer *every* question completely in the user’s language (English or Urdu). "
26
- "If unsure, provide a helpful general explanation or example.\n\n"
27
- f"{conversation}User: {message}\nStudyMate:"
 
28
  )
 
29
  reply = ""
30
  for chunk in client.text_generation(
31
  prompt, max_new_tokens=512, stream=True, temperature=0.7
32
  ):
33
  reply += chunk.token
34
- if reply.strip():
35
- history.append([message, reply])
36
- return history, ""
37
  except Exception:
38
  continue
39
- # Ultimate fallback response
40
- history.append([message, "I'm having a little trouble fetching a detailed response, but here's a quick idea:\n"
41
- f"{generate_smart_fallback(message)}"])
42
  return history, ""
43
 
44
- def generate_smart_fallback(question):
45
- # Simple built-in emergency logic
46
- if "job" in question.lower():
47
- return "Try searching for this in the Job Finder tab — it's updated daily with remote and local roles."
48
- if "career" in question.lower():
49
- return "Focus on upskilling and building a small portfolio — it opens many doors faster than degrees alone."
50
- if "love" in question.lower():
51
- return "Love and respect go hand in hand — nurture both and life feels lighter."
52
- return "I’ll keep learning from your feedback — please rephrase or ask again."
53
-
54
- # ---------- Job Finder ----------
55
- def find_jobs(skill):
56
  if not skill:
57
- return "Please enter a skill or job title."
58
- url = f"https://remotive.com/api/remote-jobs?search={skill}"
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  try:
60
- response = requests.get(url).json()
61
- jobs = response.get("jobs", [])
62
- if not jobs:
63
- return "No jobs found. Try a different keyword."
64
- result = ""
65
- for job in jobs[:5]:
66
- result += f"🔹 **{job['title']}**\n🏢 {job['company_name']}\n🌍 {job['candidate_required_location']}\n🔗 [Apply Here]({job['url']})\n\n"
67
- return result
68
- except Exception as e:
69
- return f"Error fetching jobs: {e}"
70
-
71
- job_posts = []
72
-
73
- def post_job(name, title, description, contact):
74
- if not name or not title or not description:
75
- return "Please fill in all fields."
76
- job_posts.append({
77
- "name": name,
78
- "title": title,
79
- "description": description,
80
- "contact": contact
81
- })
82
- return "✅ Job post added successfully!"
83
-
84
- def show_job_posts():
85
- if not job_posts:
86
- return "No community job posts yet."
87
- result = ""
88
- for j in job_posts[-10:][::-1]:
89
- result += f"**{j['title']}** by {j['name']}\n📄 {j['description']}\n📞 {j['contact']}\n\n"
90
- return result
91
-
92
- # ---------- Career Compass ----------
93
- def career_guidance(skills, goal, education):
94
- if not skills and not goal:
95
- return "Please provide your skills or career goal."
96
- for model in MODELS:
97
- try:
98
- client = InferenceClient(model)
99
- prompt = (
100
- "You are StudyMate AI — a professional career coach. "
101
- "Give career path suggestions, high-demand roles, and study resources. "
102
- "Write in clear, bullet-point form. If Urdu is detected, reply in Urdu.\n\n"
103
- f"Skills: {skills}\nGoal: {goal}\nEducation: {education}\n\nCareer Advice:"
104
- )
105
- reply = ""
106
- for chunk in client.text_generation(
107
- prompt, max_new_tokens=600, stream=True, temperature=0.7
108
- ):
109
- reply += chunk.token
110
- if reply.strip():
111
- return reply
112
- except Exception:
113
- continue
114
- return "Sorry, I couldn’t load a detailed career plan, but here’s a quick tip:\n" \
115
- "Pick one skill you enjoy most and start offering it online — consistent practice beats overthinking."
116
-
117
- # ---------- UI Theme ----------
118
- css_code = """
119
  body {
120
- background: linear-gradient(120deg, rgba(15,15,25,0.9), rgba(25,25,35,0.9)),
121
- url('https://images.unsplash.com/photo-1523050854058-8df90110c9f1?auto=format&fit=crop&w=1920&q=80')
122
- no-repeat center center fixed;
123
- background-size: cover;
124
  color: white;
125
  }
 
126
  .gradio-container {
127
- backdrop-filter: blur(18px);
128
  background: rgba(255, 255, 255, 0.05);
129
- border-radius: 18px;
130
- padding: 20px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  }
132
  """
133
 
134
- # ---------- BUILD APP ----------
135
- with gr.Blocks(css=css_code, theme=gr.themes.Soft(primary_hue="blue")) as demo:
136
  gr.HTML("""
137
- <div style="text-align:center; font-size:30px; font-weight:700; color:white;">
138
- StudyMate AI
139
- </div>
 
 
 
 
140
  """)
141
 
142
  with gr.Tab("💬 Chat"):
143
- chatbot = gr.Chatbot(label="Chat", height=480, bubble_full_width=False)
144
- msg = gr.Textbox(placeholder="Ask anything in Urdu or English…")
 
 
 
145
  clear = gr.Button("Clear Chat")
146
- msg.submit(chat_with_ai, [msg, chatbot], [chatbot, msg])
 
147
  clear.click(lambda: None, None, chatbot, queue=False)
148
 
149
- with gr.Tab("💼 Job Finder"):
150
- gr.Markdown("### 🔍 Find Remote Jobs")
151
- skill = gr.Textbox(label="Enter a skill (e.g. Python, Graphic Design)")
152
- search_btn = gr.Button("Find Jobs")
153
- job_output = gr.Markdown()
154
- search_btn.click(find_jobs, skill, job_output)
155
-
156
- gr.Markdown("---\n### 📢 Post a Local Job (Community Board)")
157
- name = gr.Textbox(label="Your Name")
158
- title = gr.Textbox(label="Job Title")
159
- desc = gr.Textbox(label="Description")
160
- contact = gr.Textbox(label="Contact Info")
161
- post_btn = gr.Button("Post Job")
162
- post_output = gr.Markdown()
163
- post_btn.click(post_job, [name, title, desc, contact], post_output)
164
-
165
- gr.Markdown("### 🗂️ Recent Community Job Posts")
166
- refresh = gr.Button("Refresh Job List")
167
- posts_display = gr.Markdown()
168
- refresh.click(show_job_posts, None, posts_display)
169
 
170
  with gr.Tab("🧭 Career Compass"):
171
- skills = gr.Textbox(label="Your Skills (e.g. Video Editing, Marketing)")
172
- goal = gr.Textbox(label="Career Goal (e.g. Doctor, Developer, Designer)")
173
- education = gr.Textbox(label="Education Level (e.g. Intermediate, Graduate)")
174
- generate = gr.Button("Get Career Plan")
175
- output = gr.Markdown()
176
- generate.click(career_guidance, [skills, goal, education], output)
177
 
178
  demo.launch()
 
1
  import gradio as gr
 
2
  import requests
3
+ from huggingface_hub import InferenceClient
4
 
5
+ # ---------- Chat & Career Models ----------
6
  MODELS = [
7
  "meta-llama/Meta-Llama-3-8B-Instruct",
8
  "mistralai/Mistral-7B-Instruct-v0.3",
9
+ "google/gemma-7b-it"
 
10
  ]
11
 
12
+ def ai_chat(message, history):
 
13
  if history is None:
14
  history = []
15
  for model in MODELS:
16
  try:
17
  client = InferenceClient(model)
18
+ conversation = ""
19
+ for h in history:
20
+ conversation += f"User: {h[0]}\nStudyMate: {h[1]}\n"
21
  prompt = (
22
+ "You are StudyMate AI, a multilingual tutor and career mentor. "
23
+ "Always reply clearly in the same language as the user. "
24
+ "If you are unsure, give your best explanation and encourage learning.\n\n"
25
+ + conversation
26
+ + f"User: {message}\nStudyMate:"
27
  )
28
+
29
  reply = ""
30
  for chunk in client.text_generation(
31
  prompt, max_new_tokens=512, stream=True, temperature=0.7
32
  ):
33
  reply += chunk.token
34
+ history.append((message, reply))
35
+ return history, ""
 
36
  except Exception:
37
  continue
38
+ history.append((message, "Sorry 😔 I couldn’t generate a full answer right now. Try again."))
 
 
39
  return history, ""
40
 
41
+ # ---------- Career Compass ----------
42
+ def career_compass(skill):
 
 
 
 
 
 
 
 
 
 
43
  if not skill:
44
+ return "Please enter a skill or field."
45
+ return (
46
+ f"📘 **Career Plan for {skill.title()}**\n\n"
47
+ f"**1️⃣ Learn:** Take beginner-to-advanced online courses (Coursera, YouTube, freecodecamp).\n"
48
+ f"**2️⃣ Build:** Create 2-3 small portfolio projects related to {skill}.\n"
49
+ f"**3️⃣ Connect:** Join LinkedIn groups or Pakistani Facebook communities for {skill}.\n"
50
+ f"**4️⃣ Earn:** Search for remote jobs or gigs via StudyMate AI’s Job Finder tab.\n"
51
+ f"**5️⃣ Scale:** Once confident, teach others — it multiplies learning.\n\n"
52
+ f"✨ Tip: Consistency for 90 days = visible progress."
53
+ )
54
+
55
+ # ---------- Voice ----------
56
+ def tts_generate(text):
57
+ if not text:
58
+ return None
59
  try:
60
+ client = InferenceClient("coqui-ai/TTS-1-en")
61
+ audio = client.audio_generation(text)
62
+ return (audio, )
63
+ except Exception:
64
+ return None
65
+
66
+ # ---------- CSS (iOS Glass Theme + Animations) ----------
67
+ css_style = """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  body {
69
+ background: radial-gradient(circle at top left, #0a0f1c, #111827);
70
+ overflow: hidden;
71
+ font-family: 'Poppins', sans-serif;
 
72
  color: white;
73
  }
74
+
75
  .gradio-container {
 
76
  background: rgba(255, 255, 255, 0.05);
77
+ backdrop-filter: blur(20px);
78
+ border-radius: 24px;
79
+ padding: 24px;
80
+ box-shadow: 0 0 20px rgba(255,255,255,0.05);
81
+ animation: fadeIn 1.5s ease-in;
82
+ }
83
+
84
+ button:hover {
85
+ transform: scale(1.05);
86
+ transition: 0.3s;
87
+ }
88
+
89
+ @keyframes fadeIn {
90
+ from { opacity: 0; transform: translateY(20px); }
91
+ to { opacity: 1; transform: translateY(0); }
92
+ }
93
+
94
+ /* Floating background icons */
95
+ .floating {
96
+ position: absolute;
97
+ width: 60px;
98
+ height: 60px;
99
+ opacity: 0.15;
100
+ animation: float 12s ease-in-out infinite;
101
+ }
102
+
103
+ @keyframes float {
104
+ 0% { transform: translateY(0) rotate(0deg); }
105
+ 50% { transform: translateY(-30px) rotate(20deg); }
106
+ 100% { transform: translateY(0) rotate(0deg); }
107
+ }
108
+
109
+ #icon1 { top: 10%; left: 20%; animation-delay: 0s; }
110
+ #icon2 { top: 60%; left: 70%; animation-delay: 2s; }
111
+ #icon3 { top: 40%; left: 10%; animation-delay: 4s; }
112
+
113
+ .loader {
114
+ display: inline-block;
115
+ width: 20px;
116
+ height: 20px;
117
+ border: 3px solid rgba(255,255,255,0.3);
118
+ border-radius: 50%;
119
+ border-top-color: #ffffff;
120
+ animation: spin 1s ease-in-out infinite;
121
+ }
122
+
123
+ @keyframes spin {
124
+ to { transform: rotate(360deg); }
125
  }
126
  """
127
 
128
+ # ---------- UI ----------
129
+ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue"), css=css_style) as demo:
130
  gr.HTML("""
131
+ <div style='text-align:center; position:relative;'>
132
+ <h1 style='font-size:2.5em; color:white;'>StudyMate AI</h1>
133
+ <p style='opacity:0.7;'>Your smart study, career, and voice companion</p>
134
+ <img id='icon1' class='floating' src='https://cdn-icons-png.flaticon.com/512/1048/1048945.png'/>
135
+ <img id='icon2' class='floating' src='https://cdn-icons-png.flaticon.com/512/616/616408.png'/>
136
+ <img id='icon3' class='floating' src='https://cdn-icons-png.flaticon.com/512/1828/1828778.png'/>
137
+ </div>
138
  """)
139
 
140
  with gr.Tab("💬 Chat"):
141
+ chatbot = gr.Chatbot(label="Ask anything", height=480)
142
+ msg = gr.Textbox(placeholder="Type or speak your question…")
143
+ voice_in = gr.Microphone(label="🎤 Speak", type="filepath")
144
+ voice_out = gr.Audio(label="🔊 Reply Voice", type="filepath")
145
+
146
  clear = gr.Button("Clear Chat")
147
+
148
+ msg.submit(ai_chat, [msg, chatbot], [chatbot, msg])
149
  clear.click(lambda: None, None, chatbot, queue=False)
150
 
151
+ def voice_to_text(audio, chat_history):
152
+ if audio is None:
153
+ return chat_history, ""
154
+ try:
155
+ client = InferenceClient("openai/whisper-tiny.en")
156
+ result = client.automatic_speech_recognition(audio)
157
+ text = result.get("text", "")
158
+ chat_history, _ = ai_chat(text, chat_history)
159
+ reply_audio = tts_generate(chat_history[-1][1])
160
+ return chat_history, reply_audio
161
+ except Exception:
162
+ chat_history.append(("", "Sorry, I couldn’t process voice input."))
163
+ return chat_history, None
164
+
165
+ voice_in.change(voice_to_text, [voice_in, chatbot], [chatbot, voice_out])
 
 
 
 
 
166
 
167
  with gr.Tab("🧭 Career Compass"):
168
+ skill = gr.Textbox(label="Enter your skill or goal")
169
+ plan_btn = gr.Button("Generate Career Plan")
170
+ plan_output = gr.Markdown()
171
+ plan_btn.click(career_compass, skill, plan_output)
 
 
172
 
173
  demo.launch()