Skip to main content

Leveraging ​Artificial ​Intelligence for ​Skill ​Extraction &​ Research (LAiSER)

Documentation · PyPI · Cookbook notebooks

LAiSER turns free text such as job postings and course syllabi into structured skills, knowledge and tasks, each matched to an entry in ESCO, O*NET, the UK Skills Classification or the Open Skills Network.

Contents

About

LAiSER is a Python package for turning unstructured text about work and learning into structured, comparable skill data.

You give it a table of documents — job postings, course descriptions, syllabi. For each document, a language model extracts the skills it describes and, optionally, the knowledge and tasks behind them. LAiSER then matches every extracted phrase to its closest entries in established taxonomies using embedding similarity. The result is a table with one row per match: the phrase as written, the taxonomy entry it corresponds to, which taxonomy that entry comes from, and a similarity score.

Because results point at shared taxonomy entries rather than free-text phrases, they can be counted and compared across sources — the skills employers ask for can be set against the skills a program teaches, or tracked across thousands of postings.

The language model can be a hosted API (Gemini or OpenAI) or a model running on your own machine, including on CPU with no API key. Taxonomy alignment always runs locally against indexes prepared during setup.

Architecture

LAiSER runs four stages for every document:

  1. Extraction — The text is placed into a prompt for its input type and sent to the language model, which returns candidate concepts.
  2. Parsing and deduplication — The response is parsed into phrases. Exact duplicates are dropped and near-duplicates are collapsed by embedding similarity.
  3. Taxonomy alignment — Each phrase is embedded and searched against local FAISS indexes of taxonomy entries. Matches above a per-type similarity threshold are kept.
  4. Output — Matches are returned as a single table, optionally with graph edges linking knowledge areas to the tasks they enable.

Requirements

  • Python >=3.10; CI tests 3.10 through 3.13.
  • No GPU or API key is required. A GPU speeds up larger local models; hosted providers need their own API key.
  • Supported model providers and their settings are listed in the documentation.

Setup and Installation

  • Install LAiSER from PyPI:

    pip install laiser
    laiser setup
    
  • Install with GPU extras:

    pip install "laiser[gpu]"
    laiser setup
    
  • Install development dependencies from source:

    pip install -e ".[dev]"
    

You can check if your machine has a GPU available with:

python -c "import torch; print(torch.cuda.is_available())"

Usage

LAiSER is used as a Python package. The recommended API is SkillExtractorRefactored.

Without an API key

This runs a small open model locally on CPU. The model downloads on first use.

import pandas as pd

from laiser.skill_extractor_refactored import SkillExtractorRefactored

data = pd.DataFrame(
    [
        {
            "Research ID": "job-001",
            "description": "Build production machine learning systems in Python.",
        }
    ]
)

extractor = SkillExtractorRefactored(model_id="Qwen/Qwen2.5-0.5B-Instruct", use_gpu=False)

results = extractor.extract_concepts(
    data=data,
    id_column="Research ID",
    text_columns=["description"],
    input_type="job_desc",
    concepts=["skills"],
)

print(results[["Raw Concept", "Taxonomy Concept", "Taxonomy Source", "Correlation Coefficient"]])

Small local models are convenient for trying LAiSER out; hosted or larger models extract more reliably.

Job description extraction with Gemini

import os
import pandas as pd

from laiser.skill_extractor_refactored import SkillExtractorRefactored

data = pd.DataFrame(
    [
        {
            "Research ID": "job-001",
            "description": "Build production machine learning systems in Python.",
        }
    ]
)

extractor = SkillExtractorRefactored(
    model_id="gemini",
    api_key=os.getenv("GEMINI_API_KEY") or os.getenv("GOOGLE_API_KEY"),
    use_gpu=False,
)

results = extractor.extract_concepts(
    data=data,
    id_column="Research ID",
    text_columns=["description"],
    input_type="job_desc",
    concepts=["skills", "knowledge", "tasks"],
    allowed_sources=["esco", "onet", "osn", "ukos"],
)

print(results.head())

Course syllabus extraction

import os
import pandas as pd

from laiser.skill_extractor_refactored import SkillExtractorRefactored

data = pd.DataFrame(
    [
        {
            "Research ID": "course-001",
            "description": "Introduction to data visualization and exploratory analysis.",
            "learning_outcomes": "Create dashboards, explain patterns in data, and evaluate charts.",
        }
    ]
)

extractor = SkillExtractorRefactored(
    model_id="gemini",
    api_key=os.getenv("GEMINI_API_KEY") or os.getenv("GOOGLE_API_KEY"),
    use_gpu=False,
)

results = extractor.extract_concepts(
    data=data,
    id_column="Research ID",
    text_columns=["description", "learning_outcomes"],
    input_type="course_syllabi",
    concepts=["skills"],
    allowed_sources=["esco", "onet", "osn", "ukos"],
)

print(results.head())

Common runtime options

Option Description
model_id "gemini", "openai", or a Hugging Face model id to run locally
api_key API key for hosted providers
use_gpu run local models on GPU where available
backend "llama_cpp" to run a local GGUF model
temperature decoding temperature for every backend (default 0.0, greedy)
seed seed for backends that accept one (default 42)
concepts ["skills"] (default), or add "knowledge" and "tasks"
allowed_sources taxonomies to align against: "esco", "onet", "osn", "ukos"
top_k maximum aligned matches per concept type, per document (default 25)
return_edges return {nodes, edges} instead of only the results table
output_csv_path also write the results to this CSV file

Every option is described in the usage guide, and more snippets are in docs/examples.md.

Reproducible results

Every backend decodes greedily by default (temperature 0.0) and uses a fixed seed where the backend accepts one, so repeated runs over the same input give the same result. To make results reproducible for others, pin every setting that affects them:

extractor = SkillExtractorRefactored(
    model_id="Qwen/Qwen2.5-0.5B-Instruct",  # pin the model
    use_gpu=False,
    temperature=0.0,  # the default: greedy decoding
    seed=42,  # the default
)

results = extractor.extract_concepts(
    data=data,
    id_column="Research ID",
    text_columns=["description"],
    input_type="job_desc",
    concepts=["skills"],
    allowed_sources=["esco", "onet", "osn", "ukos"],
    similarity_thresholds={"skill": 0.60, "knowledge": 0.50, "task": 0.50},  # the defaults
)

When reporting results, also record the LAiSER version: it pins the taxonomy data and the embedding model used for alignment (sentence-transformers/all-MiniLM-L6-v2). Hosted providers do not guarantee identical output even at temperature 0.0. See Reproducibility for details.

Try it in Google Colab

The cookbook has complete analyses that open directly in Colab:

Notebook
Job skill analysis for job seekers Open in Colab
University program skill analysis Open in Colab
Pay equity analysis Open in Colab

Funding

George Washington University Gates Foundation Walmart Foundation

Authors

Partners


Metadata

Release files for laiser 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for laiser 1.0.1
File Size Uploaded Provenance Actions
laiser-1.0.1.tar.gz 79.6 kB With provenance Details for laiser-1.0.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for laiser 1.0.1
File Interpreter ABI Platform Actions
laiser-1.0.1-py3-none-any.whl Python 3 none any Details for laiser-1.0.1-py3-none-any.whl

Total release size: 148.1 kB

Release files / laiser-1.0.1.tar.gz

Download URL laiser-1.0.1.tar.gz
Size 79.6 kB
Tags Source
SHA-256 checksum
How to use checksums
ff2b0511fe7f09cd4cea5f722323cb2dcdae45e1604a30e1bd34d72cbfc51f6d
BLAKE2b-256 checksum
How to use checksums
e1c9091df24e2fb4bb9431a5245ea1b1e828530d3f8094a14589f4d9b94ca1c5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 7, 2026.

Transparency log

Release files / laiser-1.0.1-py3-none-any.whl

Download URL laiser-1.0.1-py3-none-any.whl
Size 68.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ca5a6300e1ca688b7a364f4b8c43a8e716d5ccd846a7b58077aa52adb0a051c1
BLAKE2b-256 checksum
How to use checksums
2259a9b7173a2076b4b8d619e7c91f46501acf12f4bbf7dd1f4ee5c38f6d9f74
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 7, 2026.

Transparency log

Security for laiser 1.0.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for laiser-1.0.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 7, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page