O*NET Task Normalization
Relevant source files
The following files were used as context for generating this wiki page:
ONET Task Normalization is the process of canonicalizing U.S. ONET task statements into domain-stripped operation phrases. The primary goal is to strip profession-, industry-, and domain-specific terminology (e.g., "robotic," "solar") to isolate the core cognitive or physical operation being performed (e.g., "design hardware system"). This abstraction allows the system to group tasks from disparate occupations that share the same underlying work pattern, facilitating effective clustering and the construction of an "Operation Atlas."
Sources: scripts/normalize_task_operations.py:1-15, README.md:15-25
The normalization pipeline operates as a critical stage following initial ingestion and screening. By transforming specific descriptions like "Debug robotics programs" into "debug software," the system ensures that embedding-based clustering is dominated by the nature of the work rather than the domain nouns.
Sources: scripts/normalize_task_operations.py:17-25, scripts/build_operation_atlas.py:27-35
Pipeline Architecture and Data Flow
The normalization process is part of a larger reproduction pipeline that begins with raw O*NET data and ends with a consolidated operation taxonomy.
Data Flow Overview
The process starts with prepared tasks in Parquet format. These tasks undergo a two-round knowledge screen before being sent to a Large Language Model (LLM) for normalization. The output is cached in an append-only JSONL file to ensure the process is resumable and efficient.
This diagram illustrates the sequence of scripts and data artifacts leading to and resulting from the normalization stage.
Sources: README.md:143-165, scripts/normalize_task_operations.py:38-46
Implementation Details
The core logic resides in scripts/normalize_task_operations.py, which uses an LLM (defaulting to gpt-5.4-mini) to rewrite task statements.
LLM Prompting and Constraints
The system uses a detailed SYSTEM_PROMPT to enforce domain-stripping rules. The model is instructed to preserve "WHAT THE WORKER DOES" while using common-noun generalizations.
Sources: scripts/normalize_task_operations.py:65-90
Key normalization rules include:
- Verb + Generic Object: Phrases must follow the
<verb> <generic object>structure. - Preserve Purpose: Load-bearing criteria (e.g., "for validity") must be kept if they define the operation's identity.
- Avoid Umbrella Verbs: Strong, active verbs are preferred over weak umbrella terms like "manage" or "observe."
- Object Type Enumeration: Every task must be mapped to one of the canonical object types.
Sources: scripts/normalize_task_operations.py:92-120
Canonical Object Types
The normalization process categorizes tasks into a specific enum of 14 object types:
| Object Type | Description |
|---|---|
code | Software, programs, or scripts |
hardware | Physical systems, machinery, or components |
material | Raw substances or chemical components |
document | Records, reports, or formal papers |
plan | Strategies, schedules, or care plans |
data | Measurements, statistics, or records |
image_or_media | Visual or creative production |
person | Direct interpersonal operations |
organization | Entities or internal units |
environment | Sites, ecosystems, or workspaces |
money | Budgets, cash, or financial assets |
schedule | Time-based coordination |
procedure | Protocols or instructional sequences |
other | Fallback for non-conforming objects |
| Sources: scripts/normalize_task_operations.py:48-62 |
Data Structures and Output Format
The normalization output is structured to facilitate downstream inspection and embedding.
Task Operation Schema
Each normalized task is represented by the following JSON structure:
{
"onetsoc_code": "string",
"task_id": "integer",
"operation_phrase": "3-10 word domain-stripped phrase",
"operation_verbs": ["list", "of", "1-3", "verbs"],
"operation_object_type": "enum",
"domain_stripped": ["list", "of", "removed", "terms"],
"notes": "optional technical notes"
}
Sources: scripts/normalize_task_operations.py:27-36
Normalization Examples
| Original O*NET Statement | Normalized Phrase | Object Type |
|---|---|---|
| "Debug robotics programs." | "debug software" | code |
| "Develop and implement treatment plans." | "develop and implement care plan for a person" | plan |
| "Maintain student attendance records, grades, and other required records." | "maintain records" | document |
| "Testify in court or at administrative proceedings." | "testify in a formal setting" | document |
| Sources: scripts/normalize_task_operations.py:129-165 |
Operational Components
Resumable Execution
The script scripts/normalize_task_operations.py implements a multi-threaded execution model using a ThreadPoolExecutor. It utilizes an append-only JSONL cache to track processed task_id and onetsoc_code pairs, allowing the process to resume after interruptions without redundant API calls.
Sources: scripts/normalize_task_operations.py:202-230
Pre-Normalization Screening
Normalization is only performed on tasks that pass the knowledge-work screens defined in scripts/prepare_onet_tasks.py and scripts/round2_knowledge_screen.py.
Summary
O*NET Task Normalization serves as the bridge between raw occupational data and a generalized taxonomy of knowledge work. By stripping domain-specific context via LLM-based rewriting, the system enables the discovery of 18 core operations—such as analysis, coordination, and troubleshooting—that recur across the professional landscape. This normalization is essential for the valid evaluation of AI agents against professional constructs rather than simple primitive benchmarks.
Sources: README.md:15-40, scripts/normalize_task_operations.py:17-25