resumeChatService.tsā¢7.73 kB
import OpenAI from "openai";
import { ResumeParser } from "./resumeParser";
import { ResumeQuery, ResumeResponse } from "../types";
import { mcpConfig } from "../config/mcp";
export class ResumeChatService {
private openai: OpenAI;
private resumeParser: ResumeParser;
constructor(resumeParser: ResumeParser) {
this.openai = new OpenAI({
apiKey: mcpConfig.openai.apiKey,
});
this.resumeParser = resumeParser;
}
/**
* Answer questions about the resume
*/
async answerQuestion(query: ResumeQuery): Promise<ResumeResponse> {
try {
const resumeData = this.resumeParser.getResumeData();
if (!resumeData) {
throw new Error("Resume data not loaded");
}
// Create context from resume data
const context = this.createContext(resumeData);
// Prepare the prompt
const prompt = this.createPrompt(query.question, context);
// Get response from OpenAI
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.";
// Calculate confidence based on how well the question matches the resume content
const confidence = this.calculateConfidence(query.question, resumeData);
// Identify sources used in the response
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
*/
private createContext(resumeData: any): string {
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: any) =>
`${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: any) =>
`${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: any) =>
`${proj.name}: ${
proj.description
}. Technologies: ${proj.technologies.join(", ")}`
)
.join("; ")}`
);
}
if (resumeData.certifications) {
sections.push(
`Certifications: ${resumeData.certifications
.map((cert: any) => `${cert.name} from ${cert.issuer} (${cert.date})`)
.join("; ")}`
);
}
return sections.join("\n\n");
}
/**
* Create prompt for OpenAI
*/
private createPrompt(question: string, context: string): string {
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
*/
private calculateConfidence(question: string, resumeData: any): number {
const questionLower = question.toLowerCase();
let confidence = 0.5; // Base confidence
// Check if question relates to work experience
if (
questionLower.includes("work") ||
questionLower.includes("job") ||
questionLower.includes("position") ||
questionLower.includes("company")
) {
confidence += 0.2;
}
// Check if question relates to skills
if (
questionLower.includes("skill") ||
questionLower.includes("technology") ||
questionLower.includes("programming")
) {
confidence += 0.2;
}
// Check if question relates to education
if (
questionLower.includes("education") ||
questionLower.includes("degree") ||
questionLower.includes("university") ||
questionLower.includes("college")
) {
confidence += 0.2;
}
// Check if question asks for specific information that exists
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
*/
private identifySources(question: string, resumeData: any): string[] {
const sources: string[] = [];
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(): string[] {
const resumeData = this.resumeParser.getResumeData();
if (!resumeData) {
return [];
}
const questions = [
"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?",
];
return questions;
}
}