Enhance job search parser with AI analysis capabilities
- Added support for customizable AI context and model selection in job search analysis. - Improved logging to provide detailed information about AI analysis status and parameters. - Updated README to mask sensitive LinkedIn credentials for security. - Refactored AI analysis integration to streamline data preparation and result embedding.
This commit is contained in:
parent
4099b23744
commit
c692853c38
@ -64,3 +64,4 @@ module.exports = CoreParser;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -78,8 +78,8 @@ Professional network job postings with comprehensive job data.
|
|||||||
|
|
||||||
- LinkedIn credentials (username and password) must be set in `.env` file:
|
- LinkedIn credentials (username and password) must be set in `.env` file:
|
||||||
```env
|
```env
|
||||||
LINKEDIN_USERNAME=tatiana.litvak25@gmail.com
|
LINKEDIN_USERNAME=******@gmail.com
|
||||||
LINKEDIN_PASSWORD=Sladkiy99(
|
LINKEDIN_PASSWORD=***
|
||||||
LINKEDIN_JOB_LOCATION=Canada # Optional: LinkedIn location filter
|
LINKEDIN_JOB_LOCATION=Canada # Optional: LinkedIn location filter
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ const fs = require("fs");
|
|||||||
const CoreParser = require("../core-parser");
|
const CoreParser = require("../core-parser");
|
||||||
const { skipthedriveStrategy } = require("./strategies/skipthedrive-strategy");
|
const { skipthedriveStrategy } = require("./strategies/skipthedrive-strategy");
|
||||||
const { linkedinJobsStrategy } = require("./strategies/linkedin-jobs-strategy");
|
const { linkedinJobsStrategy } = require("./strategies/linkedin-jobs-strategy");
|
||||||
const { logger, analyzeBatch, checkOllamaStatus } = require("ai-analyzer");
|
const { logger, analyzeBatch, checkOllamaStatus, DEFAULT_MODEL } = require("ai-analyzer");
|
||||||
|
|
||||||
// Load environment variables
|
// Load environment variables
|
||||||
require("dotenv").config({ path: path.join(__dirname, ".env") });
|
require("dotenv").config({ path: path.join(__dirname, ".env") });
|
||||||
@ -22,6 +22,8 @@ const SEARCH_KEYWORDS =
|
|||||||
process.env.SEARCH_KEYWORDS || "co-op,intern";//"software engineer,developer,programmer";
|
process.env.SEARCH_KEYWORDS || "co-op,intern";//"software engineer,developer,programmer";
|
||||||
const LOCATION_FILTER = process.env.LOCATION_FILTER;
|
const LOCATION_FILTER = process.env.LOCATION_FILTER;
|
||||||
const ENABLE_AI_ANALYSIS = process.env.ENABLE_AI_ANALYSIS === "true";
|
const ENABLE_AI_ANALYSIS = process.env.ENABLE_AI_ANALYSIS === "true";
|
||||||
|
const AI_CONTEXT = process.env.AI_CONTEXT || "Job market analysis focusing on job postings, skills, and trends";
|
||||||
|
const OLLAMA_MODEL = process.env.OLLAMA_MODEL || DEFAULT_MODEL;
|
||||||
const MAX_PAGES = parseInt(process.env.MAX_PAGES) || 5;
|
const MAX_PAGES = parseInt(process.env.MAX_PAGES) || 5;
|
||||||
const EXCLUDE_REJECTED = process.env.EXCLUDE_REJECTED === "true";
|
const EXCLUDE_REJECTED = process.env.EXCLUDE_REJECTED === "true";
|
||||||
|
|
||||||
@ -104,6 +106,10 @@ async function startJobSearchParser(options = {}) {
|
|||||||
logger.info(
|
logger.info(
|
||||||
`🧠 AI Analysis: ${ENABLE_AI_ANALYSIS ? "Enabled" : "Disabled"}`
|
`🧠 AI Analysis: ${ENABLE_AI_ANALYSIS ? "Enabled" : "Disabled"}`
|
||||||
);
|
);
|
||||||
|
if (ENABLE_AI_ANALYSIS) {
|
||||||
|
logger.info(` Context: "${AI_CONTEXT}"`);
|
||||||
|
logger.info(` Model: ${OLLAMA_MODEL}`);
|
||||||
|
}
|
||||||
|
|
||||||
const allResults = [];
|
const allResults = [];
|
||||||
const allRejectedResults = [];
|
const allRejectedResults = [];
|
||||||
@ -188,12 +194,36 @@ async function startJobSearchParser(options = {}) {
|
|||||||
if (ENABLE_AI_ANALYSIS && allResults.length > 0) {
|
if (ENABLE_AI_ANALYSIS && allResults.length > 0) {
|
||||||
logger.step("🧠 Running AI Analysis...");
|
logger.step("🧠 Running AI Analysis...");
|
||||||
|
|
||||||
const ollamaStatus = await checkOllamaStatus();
|
const ollamaAvailable = await checkOllamaStatus(OLLAMA_MODEL);
|
||||||
if (ollamaStatus.available) {
|
if (ollamaAvailable) {
|
||||||
analysisResults = await analyzeBatch(allResults, {
|
// Prepare data for analysis (analyzeBatch expects objects with 'text' field)
|
||||||
context:
|
const analysisData = allResults.map((job) => ({
|
||||||
"Job market analysis focusing on job postings, skills, and trends",
|
text: `${job.title || ""} at ${job.company || ""}. ${job.description || ""}`.trim(),
|
||||||
|
location: job.location || "",
|
||||||
|
keyword: job.keyword || "",
|
||||||
|
timestamp: job.extractedAt || job.postedDate || "",
|
||||||
|
}));
|
||||||
|
|
||||||
|
analysisResults = await analyzeBatch(
|
||||||
|
analysisData,
|
||||||
|
AI_CONTEXT,
|
||||||
|
OLLAMA_MODEL
|
||||||
|
);
|
||||||
|
|
||||||
|
// Embed AI analysis into each job result
|
||||||
|
allResults.forEach((job, index) => {
|
||||||
|
if (analysisResults && analysisResults[index]) {
|
||||||
|
job.aiAnalysis = {
|
||||||
|
isRelevant: analysisResults[index].isRelevant,
|
||||||
|
confidence: analysisResults[index].confidence,
|
||||||
|
reasoning: analysisResults[index].reasoning,
|
||||||
|
context: AI_CONTEXT,
|
||||||
|
model: OLLAMA_MODEL,
|
||||||
|
analyzedAt: new Date().toISOString(),
|
||||||
|
};
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
logger.success(
|
logger.success(
|
||||||
`✅ AI Analysis completed for ${allResults.length} jobs`
|
`✅ AI Analysis completed for ${allResults.length} jobs`
|
||||||
);
|
);
|
||||||
@ -214,6 +244,9 @@ async function startJobSearchParser(options = {}) {
|
|||||||
sites: sites,
|
sites: sites,
|
||||||
keywords: keywords.join(", "),
|
keywords: keywords.join(", "),
|
||||||
locationFilter,
|
locationFilter,
|
||||||
|
aiAnalysisEnabled: ENABLE_AI_ANALYSIS,
|
||||||
|
aiContext: ENABLE_AI_ANALYSIS ? AI_CONTEXT : undefined,
|
||||||
|
aiModel: ENABLE_AI_ANALYSIS ? OLLAMA_MODEL : undefined,
|
||||||
analysisResults,
|
analysisResults,
|
||||||
rejectedJobsExcluded: excludeRejected,
|
rejectedJobsExcluded: excludeRejected,
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user