How prajwalachart/langgraph_job_search_agent works
Purpose and Entry Points
This is an educational LangGraph-based job-search agent. It accepts a PDF CV, extracts a structured candidate profile, autonomously searches jobs, ranks listings against the CV, and produces a personalized result.
Primary entry points:
• Interactive learning workflow: job_search_agent.ipynb
• Streamlit upload-and-results UI: streamlit_app.py
• Reusable graph construction: agent_core.py
Orchestrated Agent Graph
agent_core.py defines the LangGraph state and five-stage workflow:
START → parse_cv → agent ⇄ tools → score → format → END
The agent/tools cycle implements ReAct control flow: the LLM determines search actions, invokes job-search tooling, observes results, and may issue additional searches before downstream ranking.
Grounding paths: agent_core.py, job_search_agent.ipynb.
CV Ingestion and Profile Boundary
cv_parser.py is the input-normalization boundary. It reads uploaded/local PDF content and uses an LLM to convert unstructured CV text into a typed Pydantic CVProfile containing candidate attributes such as skills and experience.
The structured profile becomes the durable candidate representation consumed by job-search planning, scoring, and result formatting.
Grounding paths: cv_parser.py, streamlit_app.py.
LLM Planning and Result Writing
The Groq-hosted LLM serves two distinct responsibilities:
• Parse CV text into the structured profile.
• Drive search decisions and write the final encouraging, personalized summary.
LLM calls are used for semantic interpretation and control decisions; deterministic/local components handle retrieval caching and ranking. The default documented model is Groq’s Llama 3.3 70B variant, with a smaller Groq model as a quota fallback.
Grounding paths: agent_core.py, cv_parser.py.
Job Retrieval Tool and Resilience
job_tool.py exposes the search_jobs tool used by the graph’s tools node. Its primary external dependency is RapidAPI’s JSearch API for live listings.
Retrieval has an availability and cost boundary:
• Successful searches are cached to avoid repeated JSearch requests.
• Cached listings and sample_jobs.json provide offline/demo fallback when the live API is disabled or returns no results.
• Job data crosses from external API responses into the agent state as listings for local scoring.
Grounding paths: job_tool.py, sample_jobs.json.
Local Ranking Stage
scorer.py ranks retrieved jobs against the CV with local semantic embeddings. It uses FastEmbed’s BAAI/bge-small-en-v1.5 model and cosine similarity, executed through ONNX runtime rather than a hosted embedding API.
This stage is intentionally independent of LLM and JSearch quotas after the embedding model’s initial local download. Its output is the ordered set of matched jobs used by the final formatting node.
Grounding paths: scorer.py, agent_core.py.
UI, Observability, and Runtime Dependencies
streamlit_app.py provides the operational user flow: upload PDF, launch the graph, and render ranked jobs with application links. It additionally sends Streamlit-run LLM traces to Comet Opik and exposes a trace link; notebook execution intentionally omits tracing.
Material external services are Groq (LLM), RapidAPI/JSearch (job retrieval), and Opik (observability). Python package/runtime dependencies are declared in requirements.txt; environment configuration is represented by config.toml.
Grounding paths: streamlit_app.py, requirements.txt, config.toml.
Main entry points: agent_core.py LangGraph workflow · job_tool.py search_jobs · streamlit_app.py Streamlit UI · scorer.py Local scorer
Components 16
Entry points
- Learning notebook · Interactive workflow entry point.
job_search_agent.ipynb - Streamlit UI · Uploads CVs and renders matched jobs.
streamlit_app.py
Agent workflow
- CV parser · Converts PDF CV text into a typed profile.
cv_parser.py - CVProfile · Durable structured candidate representation.
cv_parser.py - LangGraph workflow · Coordinates parse, ReAct search, scoring, and formatting.
agent_core.py - Search agent · LLM decides searches and interprets tool observations.
agent_core.py - Tools node
agent_core.py - Local scorer · Ranks listings with FastEmbed embeddings and cosine similarity.
scorer.py - Result formatter · Produces a personalized encouraging summary.
agent_core.py
Job retrieval
- search_jobs · Retrieves and caches job listings.
job_tool.py - Job cache · Avoids repeated live retrieval requests.
job_tool.py - Sample listings · Demo fallback when live search is unavailable.
sample_jobs.json
External services
- Groq LLM · Parses CVs, drives ReAct decisions, and writes results.
- RapidAPI JSearch
- FastEmbed / ONNX · BAAI/bge-small-en-v1.5 semantic embeddings.
- Comet Opik · Receives Streamlit-run LLM traces.
Connections 21
- Streamlit UI → CV parser: uploaded PDF
- Learning notebook → LangGraph workflow: runs workflow
- Streamlit UI → LangGraph workflow: launches graph
- CV parser → CVProfile: structured profile
- CV parser → Groq LLM: extracts profile
- CVProfile → LangGraph workflow: candidate state
- LangGraph workflow → Search agent: plan search
- Search agent → Tools node: tool calls
- Tools node → Search agent: observations · Repeats until search is complete.
- Search agent → Groq LLM: search decisions
- Tools node → search_jobs: search_jobs
- search_jobs → RapidAPI JSearch: live search
- search_jobs → Job cache: read/write listings
- search_jobs → Sample listings: offline fallback
- LangGraph workflow → Local scorer: retrieved listings
- CVProfile → Local scorer: skills and experience
- Local scorer → FastEmbed / ONNX: local embeddings
- Local scorer → Result formatter: ranked jobs
- Result formatter → Groq LLM: personalized summary
- Result formatter → Streamlit UI: results and links
- Streamlit UI → Comet Opik: LLM traces