Spaces:
Running
Running
Create utils/rag_agent.py
Browse files- utils/rag_agent.py +99 -0
utils/rag_agent.py
ADDED
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from sentence_transformers import SentenceTransformer
|
2 |
+
from faiss import IndexFlatIP
|
3 |
+
import numpy as np
|
4 |
+
from huggingface_hub import InferenceClient
|
5 |
+
import json
|
6 |
+
import os
|
7 |
+
|
8 |
+
class RAGInterviewAgent:
|
9 |
+
def __init__(self, job_role, cv_summary):
|
10 |
+
self.job_role = job_role
|
11 |
+
self.cv_summary = cv_summary
|
12 |
+
self.current_q = 0
|
13 |
+
|
14 |
+
# Initialize models
|
15 |
+
self.embedder = SentenceTransformer('all-MiniLM-L6-v2')
|
16 |
+
self.llm = InferenceClient(model="meta-llama/Meta-Llama-3-8B-Instruct")
|
17 |
+
|
18 |
+
# Setup FAISS index
|
19 |
+
self.index = IndexFlatIP(384) # Embedding dimension
|
20 |
+
self._setup_knowledge_base()
|
21 |
+
|
22 |
+
# Generate questions
|
23 |
+
self.questions = self._generate_questions()
|
24 |
+
|
25 |
+
def _setup_knowledge_base(self):
|
26 |
+
"""Load job requirements into vector store"""
|
27 |
+
reqs = {
|
28 |
+
"Software Engineer": [
|
29 |
+
"Explain SOLID principles",
|
30 |
+
"How would you optimize a slow SQL query?",
|
31 |
+
"Describe your experience with unit testing"
|
32 |
+
],
|
33 |
+
"Data Scientist": [
|
34 |
+
"Explain bias-variance tradeoff",
|
35 |
+
"How would you handle missing data?",
|
36 |
+
"Describe a machine learning project you worked on"
|
37 |
+
]
|
38 |
+
}
|
39 |
+
|
40 |
+
self.knowledge = reqs[self.job_role]
|
41 |
+
embeddings = self.embedder.encode(self.knowledge)
|
42 |
+
self.index.add(embeddings)
|
43 |
+
|
44 |
+
def _generate_questions(self):
|
45 |
+
"""Generate questions using RAG"""
|
46 |
+
questions = []
|
47 |
+
|
48 |
+
# Get most relevant requirements
|
49 |
+
cv_embed = self.embedder.encode(self.cv_summary["text"])
|
50 |
+
_, indices = self.index.search(np.array([cv_embed]), 3)
|
51 |
+
|
52 |
+
for i in indices[0]:
|
53 |
+
prompt = f"""
|
54 |
+
Generate an interview question for a {self.job_role} position
|
55 |
+
based on this requirement: {self.knowledge[i]}
|
56 |
+
Candidate's CV summary: {self.cv_summary['text'][:1000]}
|
57 |
+
"""
|
58 |
+
|
59 |
+
response = self.llm.text_generation(
|
60 |
+
prompt,
|
61 |
+
max_new_tokens=100,
|
62 |
+
temperature=0.7
|
63 |
+
)
|
64 |
+
questions.append({
|
65 |
+
"text": response.strip(),
|
66 |
+
"base_requirement": self.knowledge[i]
|
67 |
+
})
|
68 |
+
|
69 |
+
return questions
|
70 |
+
|
71 |
+
def get_current_question(self):
|
72 |
+
return self.questions[self.current_q]
|
73 |
+
|
74 |
+
def next_question(self):
|
75 |
+
self.current_q += 1
|
76 |
+
|
77 |
+
def evaluate_answer(self, answer):
|
78 |
+
"""Evaluate answer against knowledge base"""
|
79 |
+
# Get relevant requirement
|
80 |
+
req = self.questions[self.current_q]["base_requirement"]
|
81 |
+
|
82 |
+
prompt = f"""
|
83 |
+
Evaluate this interview answer on a scale of 1-10:
|
84 |
+
Requirement: {req}
|
85 |
+
Answer: {answer}
|
86 |
+
|
87 |
+
Provide JSON output with: score, feedback
|
88 |
+
"""
|
89 |
+
|
90 |
+
response = self.llm.text_generation(
|
91 |
+
prompt,
|
92 |
+
max_new_tokens=200,
|
93 |
+
temperature=0.3
|
94 |
+
)
|
95 |
+
|
96 |
+
try:
|
97 |
+
return json.loads(response.split("{")[1].split("}")[0] + "}")
|
98 |
+
except:
|
99 |
+
return {"score": 5, "feedback": "Evaluation failed"}
|