Balaprime commited on
Commit
c868c3d
·
verified ·
1 Parent(s): 5be288f

Upload llm_utils.py

Browse files
Files changed (1) hide show
  1. llm_utils.py +123 -0
llm_utils.py ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from dotenv import load_dotenv
3
+ from huggingface_hub import InferenceClient
4
+ import re
5
+ from typing import List
6
+ import logging
7
+
8
+ # Set up logging
9
+ logging.basicConfig(filename="llm_errors.log", level=logging.ERROR)
10
+
11
+ # Load environment variables
12
+ load_dotenv()
13
+
14
+ class LLMHelper:
15
+ def __init__(self):
16
+ self.client = InferenceClient(
17
+ model=os.getenv("HF_MODEL", "HuggingFaceH4/zephyr-7b-beta"),
18
+ token=os.getenv("HF_TOKEN")
19
+ )
20
+
21
+ def generate_text(self, prompt: str, max_tokens: int = 500) -> str:
22
+ """Generate text from the LLM with error handling and retry"""
23
+ for attempt in range(2): # Retry once on failure
24
+ try:
25
+ response = self.client.text_generation(
26
+ prompt,
27
+ max_new_tokens=max_tokens,
28
+ temperature=0.7,
29
+ do_sample=True
30
+ )
31
+ return response.strip()
32
+ except Exception as e:
33
+ logging.error(f"LLM Error (Attempt {attempt + 1}): {str(e)}")
34
+ if attempt == 1:
35
+ return ""
36
+ return ""
37
+
38
+ def parse_tech_stack(input_str: str) -> List[str]:
39
+ """Parse tech stack input into a cleaned list of technologies"""
40
+ if not input_str.strip():
41
+ return []
42
+
43
+ replacements = {
44
+ "c#": "C#",
45
+ "c++": "C++",
46
+ "f#": "F#",
47
+ "golang": "Go",
48
+ "js": "JavaScript",
49
+ "ts": "TypeScript",
50
+ "nodejs": "Node.js",
51
+ "node": "Node.js",
52
+ "reactjs": "React",
53
+ "vuejs": "Vue.js",
54
+ "postgresql": "PostgreSQL",
55
+ "mysql": "MySQL"
56
+ }
57
+
58
+ techs = re.split(r'[,;/\n]', input_str)
59
+ cleaned = []
60
+
61
+ for tech in techs:
62
+ tech = tech.strip()
63
+ if tech:
64
+ tech = tech.lower()
65
+ tech = replacements.get(tech, tech)
66
+ if not re.match(r'^[a-z0-9+#]+$', tech):
67
+ tech = tech.title()
68
+ if tech not in cleaned and len(tech) > 1:
69
+ cleaned.append(tech)
70
+
71
+ return cleaned
72
+
73
+ def generate_tech_questions(tech_stack: List[str], years_experience: int) -> List[str]:
74
+ """Generate technical questions based on tech stack and experience level"""
75
+ if not tech_stack:
76
+ return ["Please describe your technical experience."]
77
+
78
+ llm = LLMHelper()
79
+ difficulty = "beginner" if years_experience < 2 else "intermediate" if years_experience < 5 else "advanced"
80
+ questions = []
81
+
82
+ for tech in tech_stack:
83
+ prompt = f"""Generate exactly 3 technical questions about {tech} for a candidate with {years_experience} years of experience.
84
+ Difficulty level: {difficulty}
85
+ Format each question clearly numbered like:
86
+ 1. [Question about {tech}]
87
+ 2. [Question about {tech}]
88
+ 3. [Question about {tech}]
89
+
90
+ The questions should:
91
+ - Be technical and specific to {tech}
92
+ - Cover different aspects (syntax, architecture, debugging)
93
+ - Require detailed answers
94
+ - Avoid simple yes/no or one-word answers
95
+ - Be unique and not repetitive
96
+ - Be relevant to real-world use cases
97
+
98
+ Example for Python (intermediate):
99
+ 1. How would you optimize memory usage in a Python application processing large datasets?
100
+ 2. Explain the differences between multiprocessing and threading in Python with examples.
101
+ 3. Describe how you would implement and test a custom context manager in Python.
102
+ """
103
+ response = llm.generate_text(prompt)
104
+
105
+ tech_questions = []
106
+ for line in response.split('\n'):
107
+ line = line.strip()
108
+ if line and re.match(r'^\d+\.\s*\[.*\]\s*$', line):
109
+ question = line.split('.', 1)[1].strip()[1:-1].strip()
110
+ if question:
111
+ tech_questions.append(f"{tech}: {question}")
112
+
113
+ if len(tech_questions) < 3:
114
+ default_questions = [
115
+ f"{tech}: Explain the most challenging {tech} project you've worked on and the key technical decisions you made.",
116
+ f"{tech}: How would you optimize performance in a {tech} application handling high traffic?",
117
+ f"{tech}: Describe your approach to debugging a complex issue in a {tech} application."
118
+ ]
119
+ tech_questions.extend(default_questions[:3 - len(tech_questions)])
120
+
121
+ questions.extend(tech_questions[:3])
122
+
123
+ return questions[:15] # Limit to 15 questions max to avoid overwhelming candidates