resumeChatService.jsā¢7.03 kB
const OpenAI = require("openai");
// Configuration
const mcpConfig = {
openai: {
apiKey: process.env.OPENAI_API_KEY || "",
model: "gpt-3.5-turbo",
maxTokens: 1000,
temperature: 0.7,
},
};
class ResumeChatService {
constructor(resumeParser) {
this.openai = new OpenAI({
apiKey: mcpConfig.openai.apiKey,
});
this.resumeParser = resumeParser;
}
/**
* Answer questions about the resume
*/
async answerQuestion(query) {
try {
const resumeData = this.resumeParser.getResumeData();
if (!resumeData) {
throw new Error("Resume data not loaded");
}
const context = this.createContext(resumeData);
const prompt = this.createPrompt(query.question, context);
const completion = await this.openai.chat.completions.create({
model: mcpConfig.openai.model,
messages: [
{
role: "system",
content:
"You are a helpful assistant that answers questions about a person's resume/CV. Provide accurate, detailed, and professional responses based on the resume information provided.",
},
{
role: "user",
content: prompt,
},
],
max_tokens: mcpConfig.openai.maxTokens,
temperature: mcpConfig.openai.temperature,
});
const answer =
completion.choices[0]?.message?.content ||
"I could not generate a response.";
const confidence = this.calculateConfidence(query.question, resumeData);
const sources = this.identifySources(query.question, resumeData);
return {
answer,
confidence,
sources,
};
} catch (error) {
console.error("Error answering resume question:", error);
return {
answer:
"I encountered an error while processing your question. Please try again.",
confidence: 0,
sources: [],
};
}
}
/**
* Create context from resume data
*/
createContext(resumeData) {
const sections = [
`Personal Information: ${resumeData.personalInfo.name}, ${
resumeData.personalInfo.email
}, ${resumeData.personalInfo.location || "Location not specified"}`,
`Summary: ${resumeData.summary}`,
`Work Experience: ${resumeData.experience
.map(
(exp) =>
`${exp.position} at ${exp.company} (${exp.startDate} - ${
exp.endDate || "Present"
}): ${exp.description}. Achievements: ${exp.achievements.join(
", "
)}. Technologies: ${exp.technologies.join(", ")}`
)
.join("; ")}`,
`Education: ${resumeData.education
.map(
(edu) =>
`${edu.degree} in ${edu.field} from ${edu.institution} (${
edu.startDate
} - ${edu.endDate || "Present"})`
)
.join("; ")}`,
`Skills: ${resumeData.skills.join(", ")}`,
];
if (resumeData.projects) {
sections.push(
`Projects: ${resumeData.projects
.map(
(proj) =>
`${proj.name}: ${
proj.description
}. Technologies: ${proj.technologies.join(", ")}`
)
.join("; ")}`
);
}
if (resumeData.certifications) {
sections.push(
`Certifications: ${resumeData.certifications
.map((cert) => `${cert.name} from ${cert.issuer} (${cert.date})`)
.join("; ")}`
);
}
return sections.join("\n\n");
}
/**
* Create prompt for OpenAI
*/
createPrompt(question, context) {
return `
Based on the following resume information, please answer the question: "${question}"
Resume Information:
${context}
Please provide a detailed and accurate answer based on the information provided. If the question cannot be answered from the resume data, please say so clearly.
`.trim();
}
/**
* Calculate confidence score for the response
*/
calculateConfidence(question, resumeData) {
const questionLower = question.toLowerCase();
let confidence = 0.5;
if (
questionLower.includes("work") ||
questionLower.includes("job") ||
questionLower.includes("position") ||
questionLower.includes("company")
) {
confidence += 0.2;
}
if (
questionLower.includes("skill") ||
questionLower.includes("technology") ||
questionLower.includes("programming")
) {
confidence += 0.2;
}
if (
questionLower.includes("education") ||
questionLower.includes("degree") ||
questionLower.includes("university") ||
questionLower.includes("college")
) {
confidence += 0.2;
}
if (questionLower.includes("name") && resumeData.personalInfo.name) {
confidence += 0.1;
}
if (questionLower.includes("email") && resumeData.personalInfo.email) {
confidence += 0.1;
}
if (
questionLower.includes("location") &&
resumeData.personalInfo.location
) {
confidence += 0.1;
}
return Math.min(confidence, 1.0);
}
/**
* Identify sources used in the response
*/
identifySources(question, resumeData) {
const sources = [];
const questionLower = question.toLowerCase();
if (
questionLower.includes("work") ||
questionLower.includes("job") ||
questionLower.includes("position")
) {
sources.push("Work Experience");
}
if (
questionLower.includes("skill") ||
questionLower.includes("technology")
) {
sources.push("Skills");
}
if (
questionLower.includes("education") ||
questionLower.includes("degree")
) {
sources.push("Education");
}
if (questionLower.includes("project")) {
sources.push("Projects");
}
if (
questionLower.includes("certification") ||
questionLower.includes("certificate")
) {
sources.push("Certifications");
}
if (
questionLower.includes("name") ||
questionLower.includes("email") ||
questionLower.includes("contact")
) {
sources.push("Personal Information");
}
if (questionLower.includes("summary") || questionLower.includes("about")) {
sources.push("Summary");
}
return sources.length > 0 ? sources : ["General Resume Information"];
}
/**
* Get suggested questions based on resume content
*/
getSuggestedQuestions() {
const resumeData = this.resumeParser.getResumeData();
if (!resumeData) {
return [];
}
return [
"What is my current position?",
"What companies have I worked for?",
"What are my main skills?",
"What is my educational background?",
"What projects have I worked on?",
"What certifications do I have?",
"What was my last role?",
"What technologies do I use?",
"What is my experience level?",
"What are my key achievements?",
];
}
}
module.exports = { ResumeChatService };