Kuberwastaken commited on
Commit
f7933a5
·
1 Parent(s): 22351fe

Made it look better :)

Browse files
Files changed (4) hide show
  1. app.py +43 -52
  2. main.py +62 -15
  3. prompts.yaml +2 -0
  4. tools/resumescraper.py +1 -1
app.py CHANGED
@@ -1,58 +1,49 @@
1
- import gradio as gr
2
- import io
3
- from PyPDF2 import PdfReader
4
- from app import create_agent
 
5
 
6
- def extract_text_from_pdf(file_obj) -> str:
7
- reader = PdfReader(file_obj)
8
- text = ""
9
- for page in reader.pages:
10
- page_text = page.extract_text()
11
- if page_text:
12
- text += page_text + "\n"
13
- return text
14
-
15
- def process_resume(input_method, resume_text, pdf_file):
16
- if input_method == "Text":
17
- text = resume_text
18
- else:
19
- if pdf_file is None:
20
- return "No PDF uploaded."
21
- # Check if pdf_file is a string (i.e. a file path) or a file-like object
22
- if isinstance(pdf_file, str):
23
- with open(pdf_file, "rb") as f:
24
- file_bytes = f.read()
25
- else:
26
- file_bytes = pdf_file.read()
27
- file_obj = io.BytesIO(file_bytes)
28
- text = extract_text_from_pdf(file_obj)
29
-
30
- if not text.strip():
31
- return "No resume text found."
32
-
33
- agent = create_agent()
34
- # Instruct the agent to roast the resume using the resume text.
35
- response = agent.run(f"Roast this resume: {text}")
36
- return response
37
 
 
 
38
 
39
- def toggle_inputs(method):
40
- if method == "Text":
41
- return gr.update(visible=True), gr.update(visible=False)
42
- else:
43
- return gr.update(visible=False), gr.update(visible=True)
44
-
45
- with gr.Blocks() as demo:
46
- gr.Markdown("# Resume Roaster")
47
- gr.Markdown("Enter your resume as text or upload a PDF to receive a humorous, professional roast!")
48
 
49
- input_method = gr.Radio(choices=["Text", "PDF"], label="Input Method", value="Text")
50
- resume_text = gr.Textbox(label="Resume Text", lines=10, visible=True)
51
- pdf_file = gr.File(label="Upload Resume PDF", file_types=[".pdf"], visible=False)
52
- output = gr.Textbox(label="Roast Result", lines=10)
53
- submit_btn = gr.Button("Roast It!")
 
 
54
 
55
- input_method.change(fn=toggle_inputs, inputs=input_method, outputs=[resume_text, pdf_file])
56
- submit_btn.click(fn=process_resume, inputs=[input_method, resume_text, pdf_file], outputs=output)
 
 
 
 
 
 
 
 
 
 
 
 
 
57
 
58
- demo.launch(share=True)
 
1
+ import yaml
2
+ from smolagents import CodeAgent, HfApiModel
3
+ from smolagents.tools import Tool
4
+ from tools.resumescraper import ResumeScraperTool
5
+ from huggingface_hub import InferenceClient
6
 
7
+ class FinalAnswerTool(Tool):
8
+ name = "final_answer"
9
+ description = "Use this tool to provide your final roast"
10
+ inputs = {
11
+ "answer": {
12
+ "type": "string",
13
+ "description": "The final roast for the resume"
14
+ }
15
+ }
16
+ output_type = "string"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
+ def forward(self, answer: str) -> str:
19
+ return answer
20
 
21
+ def create_agent():
22
+ final_answer = FinalAnswerTool()
23
+ resume_scraper = ResumeScraperTool()
 
 
 
 
 
 
24
 
25
+ # Instantiate HfApiModel using Qwen/Qwen2.5-Coder-32B-Instruct for roasting.
26
+ model = HfApiModel(
27
+ max_tokens=2096,
28
+ temperature=0.5,
29
+ model_id='Qwen/Qwen2.5-Coder-32B-Instruct',
30
+ custom_role_conversions=None,
31
+ )
32
 
33
+ # Create a dedicated InferenceClient using your public endpoint
34
+ client = InferenceClient("https://jc26mwg228mkj8dw.us-east-1.aws.endpoints.huggingface.cloud")
35
+ # Override the model's client with our dedicated client
36
+ model.client = client
37
+
38
+ with open("prompts.yaml", 'r') as stream:
39
+ prompt_templates = yaml.safe_load(stream)
40
+
41
+ agent = CodeAgent(
42
+ model=model,
43
+ tools=[resume_scraper, final_answer],
44
+ max_steps=6,
45
+ verbosity_level=1,
46
+ prompt_templates=prompt_templates
47
+ )
48
 
49
+ return agent
main.py CHANGED
@@ -24,7 +24,6 @@ def process_resume(input_method, resume_text, pdf_file):
24
  file_bytes = f.read()
25
  else:
26
  file_bytes = pdf_file.read()
27
- import io
28
  file_obj = io.BytesIO(file_bytes)
29
  text = extract_text_from_pdf(file_obj)
30
 
@@ -32,28 +31,76 @@ def process_resume(input_method, resume_text, pdf_file):
32
  return "No resume text found."
33
 
34
  agent = create_agent()
35
- # Directly run the agent to roast the resume. With our updated prompts,
36
- # the agent should output plain text that we can simply print.
37
  response = agent.run(f"Roast this resume: {text}")
38
  return response
39
 
40
  def toggle_inputs(method):
 
41
  if method == "Text":
42
- return gr.update(visible=True), gr.update(visible=False)
43
- else:
44
  return gr.update(visible=False), gr.update(visible=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
- with gr.Blocks() as demo:
47
- gr.Markdown("# Resume Roaster")
48
- gr.Markdown("Enter your resume as text or upload a PDF to receive a humorous, professional roast!")
 
49
 
50
- input_method = gr.Radio(choices=["Text", "PDF"], label="Input Method", value="Text")
51
- resume_text = gr.Textbox(label="Resume Text", lines=10, visible=True)
52
- pdf_file = gr.File(label="Upload Resume PDF", file_types=[".pdf"], visible=False)
53
- output = gr.Textbox(label="Roast Result", lines=10)
54
- submit_btn = gr.Button("Roast It!")
 
 
55
 
56
- input_method.change(fn=toggle_inputs, inputs=input_method, outputs=[resume_text, pdf_file])
 
57
  submit_btn.click(fn=process_resume, inputs=[input_method, resume_text, pdf_file], outputs=output)
58
 
59
- demo.launch(share=True)
 
 
 
 
 
 
 
 
 
 
24
  file_bytes = f.read()
25
  else:
26
  file_bytes = pdf_file.read()
 
27
  file_obj = io.BytesIO(file_bytes)
28
  text = extract_text_from_pdf(file_obj)
29
 
 
31
  return "No resume text found."
32
 
33
  agent = create_agent()
34
+ # Use the agent to roast the resume.
 
35
  response = agent.run(f"Roast this resume: {text}")
36
  return response
37
 
38
  def toggle_inputs(method):
39
+ # Updated order: pdf_file first, then resume_text.
40
  if method == "Text":
 
 
41
  return gr.update(visible=False), gr.update(visible=True)
42
+ else:
43
+ return gr.update(visible=True), gr.update(visible=False)
44
+
45
+ css_custom = """
46
+ footer {visibility: hidden;}
47
+ .center {
48
+ margin: 0 auto;
49
+ text-align: center;
50
+ }
51
+ @keyframes beat {
52
+ 0%, 20%, 40%, 60%, 80%, 100% { transform: scale(1); }
53
+ 10%, 30%, 50%, 70%, 90% { transform: scale(1.2); }
54
+ }
55
+ .beating-heart {
56
+ display: inline-block;
57
+ animation: beat 2s infinite;
58
+ }
59
+ .fire-effect {
60
+ font-size: 2.5em;
61
+ font-weight: bold;
62
+ background: linear-gradient(45deg, red, orange, yellow);
63
+ background-size: 200%;
64
+ -webkit-background-clip: text;
65
+ -webkit-text-fill-color: transparent;
66
+ animation: fireAnimation 3s linear infinite;
67
+ }
68
+ @keyframes fireAnimation {
69
+ 0% { background-position: 0%; }
70
+ 50% { background-position: 100%; }
71
+ 100% { background-position: 0%; }
72
+ }
73
+ /* Center the radio button options */
74
+ div[role="radiogroup"] {
75
+ display: flex;
76
+ justify-content: center;
77
+ }
78
+ """
79
 
80
+ with gr.Blocks(css=css_custom) as demo:
81
+ with gr.Column(elem_classes="center"):
82
+ gr.Markdown('<div class="fire-effect">Resume Roaster</div>')
83
+ gr.Markdown("Upload your resume as a PDF (default) or paste the text to receive a humorous, professional roast!")
84
 
85
+ # Reordered radio choices so that PDF is first.
86
+ input_method = gr.Radio(choices=["PDF", "Text"], label="Input Method", value="PDF")
87
+ # PDF upload comes first
88
+ pdf_file = gr.File(label="Upload Resume PDF", file_types=[".pdf"], visible=True)
89
+ resume_text = gr.Textbox(label="Resume Text", lines=10, visible=False)
90
+ output = gr.Textbox(label="Roast Result", lines=10)
91
+ submit_btn = gr.Button("Roast It!")
92
 
93
+ # Adjusted toggle outputs to match new order.
94
+ input_method.change(fn=toggle_inputs, inputs=input_method, outputs=[pdf_file, resume_text])
95
  submit_btn.click(fn=process_resume, inputs=[input_method, resume_text, pdf_file], outputs=output)
96
 
97
+ gr.Markdown(
98
+ """
99
+ <div id="custom_footer" style="text-align: center; margin-top: 20px; font-size: 14px;">
100
+ Made with <span class="beating-heart">💓</span> by Kuber Mehta<br>
101
+ All jokes are crafted in good humor to provide professional levity.
102
+ </div>
103
+ """
104
+ )
105
+
106
+ demo.launch(share=False)
prompts.yaml CHANGED
@@ -3,12 +3,14 @@ system_prompt: |
3
  Your job is to create a humorous, professional roast of a resume.
4
  Focus on teasing overly verbose descriptions, excessive buzzwords, and generic statements,
5
  while keeping the tone light and appropriate for a professional setting.
 
6
  task_prompt: |
7
  Using the provided resume details, craft a roast that:
8
  1. References key sections such as Summary, Experience, Education, and Skills.
9
  2. Is humorous but not mean-spirited.
10
  3. Maintains a professional tone.
11
  4. Adds creative flair that makes the roast both entertaining and insightful.
 
12
  final_answer:
13
  pre_messages: "Final Roast:"
14
  post_messages: ""
 
3
  Your job is to create a humorous, professional roast of a resume.
4
  Focus on teasing overly verbose descriptions, excessive buzzwords, and generic statements,
5
  while keeping the tone light and appropriate for a professional setting.
6
+
7
  task_prompt: |
8
  Using the provided resume details, craft a roast that:
9
  1. References key sections such as Summary, Experience, Education, and Skills.
10
  2. Is humorous but not mean-spirited.
11
  3. Maintains a professional tone.
12
  4. Adds creative flair that makes the roast both entertaining and insightful.
13
+
14
  final_answer:
15
  pre_messages: "Final Roast:"
16
  post_messages: ""
tools/resumescraper.py CHANGED
@@ -46,4 +46,4 @@ class ResumeScraperTool(Tool):
46
  end = lower_text.find("\n\n", start)
47
  sections["skills"] = resume_text[start + len("skills:"): end].strip() if end != -1 else resume_text[start + len("skills:"):].strip()
48
 
49
- return sections
 
46
  end = lower_text.find("\n\n", start)
47
  sections["skills"] = resume_text[start + len("skills:"): end].strip() if end != -1 else resume_text[start + len("skills:"):].strip()
48
 
49
+ return sections