resume-parser / lib /llm-parser.ts
PPSA's picture
Upload 235 files
dca8ede verified
import type { Resume, Experience, Education } from "@/types/resume"
interface ParsedResume {
name: string
email: string
phone: string
location: string
title: string
summary: string
skills: string[]
experience: Experience[]
education: string[]
educationDetails: Education[]
certifications: string[]
languages: string[]
experienceLevel: string
}
/**
* Parses resume text using DeepSeek LLM
*/
export async function parseResumeWithLLM(resumeText: string): Promise<ParsedResume> {
try {
const apiKey = process.env.DEEPSEEK_API_KEY || "sk-02f34bd0ea4849e8a4232bc656e28727"
const apiUrl = "https://api.deepseek.com/v1/chat/completions"
const prompt = `
You are an expert resume parser. Extract the following information from the resume text below:
1. Full Name
2. Email Address (primary)
3. Phone Number (primary)
4. Location/Address
5. Current Job Title
6. Professional Summary
7. Skills (as a list)
8. Work Experience (for each position: title, company, duration, and description)
9. Education (list of degrees/qualifications)
10. Education Details (for each institution: degree, institution name, and graduation year)
11. Certifications (as a list)
12. Languages (as a list)
13. Experience Level (Entry Level, Mid Level, Senior, or Executive)
Format the output as a JSON object with these fields:
{
"name": string,
"email": string,
"phone": string,
"location": string,
"title": string,
"summary": string,
"skills": string[],
"experience": [{ "title": string, "company": string, "duration": string, "description": string }],
"education": string[],
"educationDetails": [{ "degree": string, "institution": string, "year": string }],
"certifications": string[],
"languages": string[],
"experienceLevel": string
}
If any information is missing, use empty strings for text fields and empty arrays for lists.
Resume Text:
${resumeText}
`
const response = await fetch(apiUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${apiKey}`,
},
body: JSON.stringify({
model: "deepseek-chat",
messages: [
{
role: "system",
content: "You are an expert resume parser that extracts structured information from resume text.",
},
{
role: "user",
content: prompt,
},
],
temperature: 0.1,
max_tokens: 4000,
}),
})
if (!response.ok) {
throw new Error(`DeepSeek API error: ${response.statusText}`)
}
const data = await response.json()
const parsedContent = data.choices[0].message.content
// Extract the JSON object from the response
let parsedResume: ParsedResume
try {
// The LLM might return the JSON with markdown code blocks, so we need to extract it
const jsonMatch = parsedContent.match(/```json\n([\s\S]*?)\n```/) ||
parsedContent.match(/```\n([\s\S]*?)\n```/) || [null, parsedContent]
const jsonString = jsonMatch[1] || parsedContent
const rawParsed = JSON.parse(jsonString)
// Ensure all required fields are present with correct types
parsedResume = {
name: rawParsed.name || "",
email: rawParsed.email || "",
phone: rawParsed.phone || "",
location: rawParsed.location || "",
title: rawParsed.title || "",
summary: rawParsed.summary || "",
skills: Array.isArray(rawParsed.skills) ? rawParsed.skills : [],
experience: Array.isArray(rawParsed.experience) ? rawParsed.experience.map((exp: any) => ({
title: exp.title || "",
company: exp.company || "",
duration: exp.duration || "",
description: exp.description || "",
})) : [],
education: Array.isArray(rawParsed.education) ? rawParsed.education : [],
educationDetails: Array.isArray(rawParsed.educationDetails) ? rawParsed.educationDetails.map((edu: any) => ({
degree: edu.degree || "",
institution: edu.institution || "",
year: edu.year || "",
})) : [],
certifications: Array.isArray(rawParsed.certifications) ? rawParsed.certifications : [],
languages: Array.isArray(rawParsed.languages) ? rawParsed.languages : [],
experienceLevel: rawParsed.experienceLevel || "Not specified",
}
} catch (error) {
console.error("Error parsing LLM response as JSON:", error)
console.log("Raw LLM response:", parsedContent)
// Fallback to a basic structure if parsing fails
parsedResume = {
name: "",
email: "",
phone: "",
location: "",
title: "",
summary: "",
skills: [],
experience: [],
education: [],
educationDetails: [],
certifications: [],
languages: [],
experienceLevel: "Not specified",
}
}
return parsedResume
} catch (error) {
console.error("Error parsing resume with LLM:", error)
throw new Error("Failed to parse resume with LLM")
}
}