From 96246d019759adbce46b4b034928ead6c26a8379 Mon Sep 17 00:00:00 2001 From: Joey Eamigh <55670930+JoeyEamigh@users.noreply.github.com> Date: Tue, 31 Mar 2026 16:27:47 -0400 Subject: [PATCH] docs & reference files --- docs/NARRATIVE.md | 23 +- docs/STATUS.md | 15 +- docs/reference/Capstone_assn_instructions.md | 449 ++ .../P3_SEC_Cybersecurity_Capstone.md | 688 +++ ...VerticalAI_Capstone_Pipeline_Example.ipynb | 4433 +++++++++++++++++ .../Ringel_488-2026_Capstone_Constructs.pdf | Bin 0 -> 465975 bytes docs/reference/Signoff_assn_instructions.md | 71 + 7 files changed, 5666 insertions(+), 13 deletions(-) create mode 100644 docs/reference/Capstone_assn_instructions.md create mode 100644 docs/reference/P3_SEC_Cybersecurity_Capstone.md create mode 100644 docs/reference/Ringel_2026_VerticalAI_Capstone_Pipeline_Example.ipynb create mode 100644 docs/reference/Ringel_488-2026_Capstone_Constructs.pdf create mode 100644 docs/reference/Signoff_assn_instructions.md diff --git a/docs/NARRATIVE.md b/docs/NARRATIVE.md index 53a12db..f02f261 100644 --- a/docs/NARRATIVE.md +++ b/docs/NARRATIVE.md @@ -795,7 +795,24 @@ The TAPT corpus is 72K Item 1C paragraphs (~10M tokens) — 50x smaller than the **Whole-word masking and tokenization:** Whole-word masking requires `offset_mapping` from the tokenizer to determine word boundaries. This is incompatible with DAPT's concatenate-and-chunk approach (which destroys offset_mapping by merging documents). TAPT tokenizes each paragraph individually with truncation, preserving offset_mapping. The data collator handles dynamic padding per batch. This is a different code path from DAPT's concatenation, but the data justifies it: paragraphs are natural self-contained units, unlike DAPT's long filings that must be chunked. -**Training time:** ~2,139 steps/epoch × 5 epochs = ~10,695 total steps. At ~1.84 it/s on the 3090, ~1.6 hours total. +**Training time:** ~2,139 steps/epoch × 5 epochs = ~10,695 total steps. 50 minutes on the RTX 3090 at ~3.56 steps/s (averaged over full run including torch.compile warmup). + +### TAPT Results + +| Metric | Value | +|--------|-------| +| Epochs | 5 | +| Total steps | 10,695 | +| Training time | 50 minutes | +| Initial loss | 1.46 | +| Final train loss (avg) | 0.6428 | +| Final eval loss | 1.0754 | +| Final perplexity | 2.11 | +| Throughput | 114 samples/s, 3.56 steps/s | + +Loss dropped from 1.46 → 1.08 over 5 epochs. For comparison, DAPT ended at eval loss 0.72 with standard subword masking at the same 30% rate — the gap reflects the harder whole-word masking objective (no subword hints), not a weaker model. The model learns to predict masked domain terms ("CISO", "materiality", "tabletop") from surrounding paragraph context alone, which is exactly the inductive bias TAPT is designed to create. + +The TAPT checkpoint is saved at `checkpoints/tapt/modernbert-large/final/` and is ready for fine-tuning. ### TAPT Launch — Whole-Word Masking Bugs @@ -851,8 +868,8 @@ Only nano's portion ($21.24) of the first run was wasted — the gemini and grok | Documentation + narrative | ~2h | Codebook updates, narrative writing, technical guide updates | | Labelapp build + infrastructure | ~8h | Monorepo restructure, Next.js app, quiz/warmup/labeling flows, BIBD assignment, sampling, Docker deployment, timer + migration infrastructure | | DAPT pre-training | ~14.5h GPU | 1 epoch on 500M tokens, RTX 3090. Two sessions (resumed from checkpoint-1280). | -| TAPT debugging + pre-training | ~2h dev + ~1.6h GPU | 4 bugs in transformers whole-word masking + Python 3.14 rollback. Training: 5 epochs on 72K paragraphs. | -| **Total to date** | **~53h** | Includes ~16h GPU time | +| TAPT debugging + pre-training | ~2h dev + ~50min GPU | 4 bugs in transformers whole-word masking + Python 3.14 rollback. Training: 5 epochs on 72K paragraphs, 50 min. | +| **Total to date** | **~52h** | Includes ~15.3h GPU time | ### Remaining Work (estimated) diff --git a/docs/STATUS.md b/docs/STATUS.md index 0171857..9fb544a 100644 --- a/docs/STATUS.md +++ b/docs/STATUS.md @@ -21,7 +21,8 @@ - [x] DAPT corpus: 14,568 documents, ~1.056B tokens, cleaned (XBRL, URLs, page numbers stripped) - [x] DAPT training complete: eval loss 0.7250, perplexity 1.65. 1 epoch on 500M tokens, ~14.5h on RTX 3090. - [x] DAPT checkpoint at `checkpoints/dapt/modernbert-large/final/` -- [x] TAPT config: 5 epochs, whole-word masking, seq_len=512, batch=32 +- [x] TAPT training complete: eval loss 1.0754, perplexity 2.11. 5 epochs, whole-word masking, ~50 min on RTX 3090. Loss: 1.46 → 1.08. +- [x] TAPT checkpoint at `checkpoints/tapt/modernbert-large/final/` - [x] Custom `WholeWordMaskCollator` (upstream `transformers` collator broken for BPE tokenizers) - [x] Python 3.14 → 3.13 rollback (dill/datasets pickle incompatibility) - [x] Procedure documented in `docs/DAPT-PROCEDURE.md` @@ -30,16 +31,10 @@ - [x] `docs/DATA-QUALITY-AUDIT.md` — full audit with all patches and quality tiers - [x] `docs/EDGAR-FILING-GENERATORS.md` — 14 generators with signatures and quality profiles - [x] `docs/DAPT-PROCEDURE.md` — pre-flight checklist, commands, monitoring guide -- [x] `docs/NARRATIVE.md` — 11 phases documented through TAPT launch +- [x] `docs/NARRATIVE.md` — 11 phases documented through TAPT completion ## What's In Progress -### TAPT Training — Running -Training on 72K Item 1C paragraphs using DAPT checkpoint. 5 epochs, whole-word masking, seq_len=512, batch=32. Early loss: 1.46 → 1.40 (first 1% of training). Expected ~1.6h total on RTX 3090. Expecting final loss ~1.0-1.2. -```bash -bun run py:train dapt --config configs/tapt/modernbert.yaml -``` - ### Human Labeling (139/1,200) - 3 of 6 annotators started: 68 + 50 + 21 paragraphs completed - Deployed via labelapp with quiz gating + warmup @@ -82,7 +77,7 @@ Full GenAI benchmark (9 models) on 1,200 holdout. Comparison tables. Write-up. ## Parallel Tracks ``` -Track A (GPU): DAPT ✓ → TAPT (running) → Fine-tuning → Eval +Track A (GPU): DAPT ✓ → TAPT ✓ → Fine-tuning → Eval ↑ Track B (API): Judge v3 → Judge run ───────────┤ ↑ @@ -91,7 +86,7 @@ Track C (Human): Labeling (139/1200) → Gold set validation Track D (Code): Fine-tune pipeline build ───────┘ ``` -TAPT finishes in ~1.5h. Track D (fine-tune pipeline) can proceed now. Track B can start (prompt update) but production run waits for Track C. Everything converges at fine-tuning. +DAPT + TAPT complete. Track D (fine-tune pipeline) can proceed now. Track B can start (prompt update) but production run waits for Track C. Everything converges at fine-tuning. ## Key File Locations diff --git a/docs/reference/Capstone_assn_instructions.md b/docs/reference/Capstone_assn_instructions.md new file mode 100644 index 0000000..315574f --- /dev/null +++ b/docs/reference/Capstone_assn_instructions.md @@ -0,0 +1,449 @@ +# Capstone: Build a Business-Grade Text Classifier + +**Due:** April 23 by 12pm | **Points:** 35 + +--- + +## Team Assignment: Build a Business-Grade Text Classifier + +**Team size:** 5–6 students: at least half must be en rolled in COMP488 or BUSI488. + +One-sentence summary: Your team will build an end-to-end system that turns raw text (reviews, filings, reports, speeches, etc.) into reliable business labels—and you’ll compare two approaches: genAI labeling vs a fine-tuned specialist model. + +## Form Your Team + +**People > Groups > CAPSTONE : People** + +- Each team member must join an EXISTING project group for THEIR SECTION +- DO NOT create your own (additional) projects groups. +- Each group must satisfy the following: + - Have at least two students enrolled in COMP488 + - Have at least two students enrolled in BUSI488 +- You can have at most three students enrolled in COMP488 and/or BUSI488 in your team, conditional on: + - All other teams having at least two of each in their team (see above). + - If other teams have less than two COMP488 and BUSI488 students, you cannot join a team that already has this minimum requirement. +- **ALL TEAM MEMBERS MUST BE IN THE SAME SECTION (1 vs. 2)** + +## Why This Assignment Matters (Business Reality) + +### Businesses Are Drowning in Text + +- Customer reviews, support chats, emails +- Social posts, news, press releases +- 10-K/10-Q filings, earnings calls, ESG reports +- Policies, regulatory communications, safety notices +- Research abstracts, patents, job postings + +### Text Classification Enables Business Value + +Text classification is one of the most common, high-ROI uses of AI because it converts messy language into structured signals that businesses can: + +- Count — How many "billing issues" this week? +- Trend — Are "delivery failures" rising? +- Segment — Which regions complain about what? +- Route — Send messages/tickets to the right team automatically +- Flag risk — Safety/adverse events, compliance issues, reputational threats +- Inform strategy — Competitor moves, pricing tactics, CX weaknesses +- Input into (predictive) models — As independent variables + +### Why Not Manual Reading? + +Firms don't just "read it manually" because volume is too high, humans are slow and inconsistent across people/time, and decisions often need speed (minutes/hours, not weeks). Leadership needs dashboards and measurable KPIs. + +This will feel like a stretch—and that's the point. You will be supported by structure, templates, and teamwork. + +## What You Will Produce (End Result) + +A working classifier for a well-documented, established, theoretically grounded construct (your choice), plus a business-style memo explaining: + +- What the construct of interest is that you selected from the seven options: + https://www.ringel.ai/UNC/2026/BUSI488/Class23/Ringel_488-2026_Capstone_Constructs.pdf +- How it was established and where it is theoretically anchored and motivated +- Why the business should care +- How well your classifier works +- What it costs (time + money) +- Whether it's reliable and reproducible + +## Choose a Construct of Interest: Meaningful and Labelable + +Your construct should be: + +- **Business-relevant** — addresses a real business decision +- **Theoretically grounded** — anchored in established literature +- **Well documented** — clearly defined in academic or industry sources +- **Observable in text** — detectable in your data source +- **Definable with clear rules** — specific enough for reliable labeling +- **Complex & nuanced** — more than just sentiment (not positive/negative) + +You must pick one of the seven provided constructs of interest from here: +https://www.ringel.ai/UNC/2026/BUSI488/Class23/Ringel_488-2026_Capstone_Constructs.pdf + +## Potential Public Data Sources + +Below are places to obtain public text data for your classifier (downloads and/or official APIs). For each of the seven constructs of interest, there are already some data sources suggested. Below are additional sources to consider. Use sources with clear educational/research access terms whenever possible. Or use your own source and data (but observe guardrails & ethics as outlined below). + +**Important:** Choose a source that fits your construct and is realistically useful to a firm. + +### Customer Reviews & Product Voice + +**Amazon Reviews (research datasets)** + +- McAuley Lab Amazon datasets +- Stanford SNAP Amazon dataset page +- Hugging Face: Amazon Reviews 2023 + +**Yelp Open Dataset** + +- Kaggle: Yelp Open Dataset + +### Corporate Filings & Investor Communications + +**SEC EDGAR (10-K / 10-Q / 8-K etc.) — Official APIs** + +- EDGAR Application Programming Interfaces +- SEC Developer Resources +- SEC Disclosure Data API announcement + +### Regulation, Enforcement, Safety & Compliance + +**FDA Warning Letters** + +- FDA: Warning Letters +- Data.gov: Warning Letters dataset + +**U.S. Consumer Product Safety Commission (CPSC) Recalls — API** + +- CPSC Recalls API information + +### Health & Public Policy (Public) + +**ClinicalTrials.gov (Modernized API)** + +- ClinicalTrials.gov Data API + +**PubMed / NCBI (E-utilities API)** + +- NCBI E-utilities documentation + +### Research & Innovation + +**arXiv (bulk data)** + +- arXiv bulk data help +- arXiv bulk data on AWS S3 + +**Patents (USPTO + PatentsView)** + +- USPTO Open Data Portal: bulk data +- PatentsView: bulk downloads + +### Government Documents & Speeches + +**govinfo API + documentation** (Congressional docs, Federal Register, etc.) + +- govinfo API overview +- govinfo API docs + +**Congress.gov API** + +- Congress.gov API (GPO) + +**U.S. Presidential speeches** (Miller Center data portal) + +- Miller Center: Presidential Speech Data + +### News / Media Monitoring + +**GDELT** (global news monitoring) + +- GDELT data downloads +- GDELT 2.0 API documentation (blog) + +**Common Crawl News dataset** (CC-NEWS) + +- Common Crawl: News dataset announcement + +### Security / Technical Risk + +**NIST National Vulnerability Database (NVD)** — CVE APIs & feeds + +- NVD: Vulnerabilities API +- NVD: Data feeds + +### Earnings Calls / Transcripts (public option) + +**Academic/open dataset option** + +- STRUX dataset page + +### Tips & Rules + +- **Tip:** Before committing, do a quick pilot on 100–200 texts to confirm your construct appears in the source and that your labels are workable +- **Rule:** Use public data or properly de-identified data only. No sensitive internal company data. + +--- + +## The Workflow: What You Must Do (Step-by-Step) + +### Step 1 — Construct Choice + Business Case + +**Goal:** Pick a well-documented, theoretically founded construct of interest. Explain why a firm would want to classify this construct at scale. +https://www.ringel.ai/UNC/2026/BUSI488/Class23/Ringel_488-2026_Capstone_Constructs.pdf + +**Include:** + +- Who is the stakeholder? (CX lead, compliance, product manager, investor relations, etc.) +- What decision/action will classification enable? +- What happens if the classifier is wrong? (false positives vs false negatives) +- Why now? (volume, speed, competitive need) + +**Deliverable:** 1–2 page concept brief + +### Step 2 — Define the Construct Precisely + +**Goal:** Turn the concept into labels humans can apply consistently. + +**You must create:** + +- Label set (classes) +- Clear definitions and decision rules +- Borderline cases: what to do when unclear +- "None/other" policy IF APPLICABLE (multi-class yes, multi-label no) +- 2-3 example texts per label (your own) + +**Decide:** multi-class (one label) vs multi-label (multiple labels can apply). + +**Deliverable:** Labeling codebook (PDF) + +### Step 3 — Identify and Justify the Data Source + +**Goal:** Show that your source actually contains your construct. + +**Include:** + +- Why this source fits the business purpose +- How a firm would use it regularly (weekly monitoring, quarterly reporting, etc.) +- Basic access plan (download/API/scrape—follow site rules) + +**Deliverable:** Data source plan + sampling approach + +### Step 4 — Collect Your Dataset + +**Targets:** + +- 20,000 texts total for train/test +- 1,200 texts for a locked holdout set + +**Deliverable:** Raw dataset file + collection notebook/script + documentation + +### Step 5 — Preprocess and Split + +**You must:** + +- Clean text (remove duplicates, empty, obvious spam) +- Create: train/test totaling 20,000; holdout = 1,200 (lock it in early—don't tune on it) + - **Beware of label imbalance!** May need to curate strategically! +- Report length stats and basic summaries +- Plan for imbalance (it's normal—just don't ignore it) + +**Deliverable:** Preprocessing notebook + split files + basic descriptive stats + +### Step 6 — Human Label the Holdout + +**Requirements:** + +- The 1,200 holdout must be labeled by humans +- At least 3 people must label each example +- Either independent labels + agreement report (Krippendorff's alpha recommended), or discussion-based consensus + documented process + +**Deliverable:** Holdout with 3+ labels per item (or consensus + notes) + reliability report + +### Step 7 — Benchmark GenAI Labeling (≥6 Models) + +**Goal:** Treat genAI as alternative "labelers" and compare. + +**Requirements:** + +- Run at least 6 models from at least 3 different suppliers (e.g., OpenAI, Anthropic, Meta, xAI, Google, FireworksAI, Deepseek, Moonshot) +- Fix prompts to make them comparable across models +- Track runtime, estimated cost, and reproducibility strategy + +**Metrics to report:** + +- Krippendorff's alpha (vs human labels) +- F1 (macro and per-class if possible) +- AUC (where applicable) +- MCC + +**Deliverable:** Benchmark notebook + results table + cost/time log + +### Step 8 — Select GenAI Labeling Strategy and Label Train/Test + +Choose the best single model or a combination (e.g., majority vote). Then label your 20,000 train/test set. + +**Deliverable:** Labeled train/test dataset + labeling script + total cost/time summary + +### Step 9 — Fine-Tune a Specialist Model + +**Goal:** Create a smaller, task-specific classifier that can match/exceed genAI labeling quality. + +**Minimum requirements:** + +- Fine-tune at least one pretrained model (RoBERTa or similar) +- Try at least four configurations (model choice or hyperparameters) +- Evaluate on holdout (only at the end) + +**Deliverable:** Training notebook + saved model + evaluation on holdout + +### Step 10 — Final Comparison: GenAI vs Specialist + +Your final analysis must answer: + +- Which is better on holdout and by how much? +- Which is cheaper per 1,000,000 texts? +- Which is faster? +- Which is more consistent and reproducible? +- What would you recommend a firm deploy, and why? + +**Deliverable:** Final comparison section + recommendation + +--- + +## What To Submit (Deliverables Checklist) + +### A) Executive Memo (Executive Style, Max 5 Pages) + +- Construct + why it matters + theoretically grounded and well documented +- Data source + governance/ethics +- Label schema overview +- Results summary: best genAI vs best specialist +- Cost/time/reproducibility comparison +- Recommendation for a real firm + +### B) Technical Appendix (Slides or PDF) + +- Pipeline diagram (data → labels → model → evaluation) +- Label codebook (or link/appendix) +- Benchmark table (≥6 genAI models) +- Fine-tuning experiments + results +- Error analysis: where does it fail and why? + +### C) Code + Artifacts (Datasets) + +- Colab notebooks (reproducible) +- **Datasets:** + - Holdout with human labels + - Train/test with genAI labels + - Any other data used + - All labels of all models for each run + majority labels +- Saved fine-tuned model + inference script (provide link to webspace/Google Drive/Dropbox; **do not upload to Canvas!**) +- Cost/time log + +### D) IGNITE Talk in Class + +- **20 PPTX Slides**, 15 sec per slide (automatic transitions), 5 min total +- Submit your PPTX slides (not PDF, not Google Slides, not other format!) set to auto transitions after 15 sec on Canvas +- I will have all slides ready for you to go in class +- **Key messages and insights only** +- **Every team member must present at least 2 slides** +- There will be a 3 min Q&A after each IGNITE talk + +**Learn more:** + +- https://en.wikipedia.org/wiki/Ignite_(event) +- https://www.ignitetalks.io/ +- https://robbiesenbach.com/deliver-successful-ignite-talk/ + +--- + +- **Start simple, then improve:** Your first codebook will be imperfect. Iterate. +- **Design labels for reliability:** If humans disagree a lot, the model will struggle. Fix definitions before scaling. +- **Lock the holdout early:** It counts 35% of your grade. Don't change direction repeatedly—fix it early and make sure it's representative for what you ultimately want to achieve from a business perspective. +- **Do a small pilot before spending money:** Test prompts and schema on 100–200 examples first. +- **Don't hide class imbalance:** Imbalance is normal. But it can damage evaluation and training. **You must solve this!** Use macro F1 and MCC, and document prevalence. + +## Team Structure (Recommended Roles) + +- **Project lead:** Scope, project plan, milestones, quality control +- **Data lead:** Collection, cleaning, dataset documentation +- **Labeling lead:** Codebook, human labeling workflow, reliability stats +- **GenAI lead:** API scripts, benchmarking, cost/time tracking +- **Modeling lead:** Fine-tuning, hyperparameters, reproducibility, evaluation +- **Delivery lead:** Assemble all outputs, organize write-ups, final quality control + +## Grading Rubric (100 Points) + +| Criterion | Points | +| ----------------------------------------- | ------ | +| Business framing & construct clarity | 20 | +| Data pipeline quality + documentation | 15 | +| Human labeling process + reliability | 15 | +| GenAI benchmarking rigor | 20 | +| Fine-tuning rigor + evaluation discipline | 20 | +| Final comparison + recommendation quality | 10 | + +### Minimum Requirements Per Letter Grade: + +#### C (- to +) + +- Fine-tuned model with F1 score > 0.80 +- Performance comparison genAI vs. fine-tuned model +- Labeled datasets +- Documentation +- Python notebook(s) to replicate pre-processing, training, and evaluation + +#### B (- to +) + +All of the above plus **at least three** of the following: + +- Cost, time, reproducibility analysis +- Comparison of 6 or more models from at least 3 different suppliers +- Contemporary data that you collected (not an off-the-shelf dataset) +- Compelling use-case for your classifier with complete business case + +#### A (- to A) + +All of the above plus **at least three** of the following: + +- Error-analysis (corner cases, rare or complex texts) +- Mitigation strategy and implementation to overcome identified model weaknesses +- Additional baselines (e.g., alternative classification approaches like dictionaries, topic models) +- Comparison to amateur labels + +## Guardrails (Ethics & Compliance) + +- Public data or approved de-identified data only +- Remove or avoid sensitive personal information +- Document limitations and potential bias +- If your construct is sensitive (health, safety, harassment), include a brief risk statement and mitigation steps + +## Estimated Effort + +| Task | Hours | +| --------------------------------------------------------- | ----- | +| Construct + codebook v1 + data source plan | 4 | +| Data collection + preprocessing + splits | 4 | +| 1.2K human labeling + reliability + codebook v2 | 8 | +| GenAI benchmarking (≥6 models) + choose labeling strategy | 3 | +| Label 20k + fine-tune specialist (2+ configs) | 2 | +| Final evaluation + memo + presentation | 3 | + +**Total: ~24 hours per student** + +## Best Work Featured in Vertical AI Paper + +I will select (and improve) the best 1–2 classifiers to be featured in my Vertical AI Paper where each team member will be acknowledged for their application of the synthetic expert/specialist approach. I will ask members whether they want to be named or not (choosing to remain anonymous has not impacted your grade). + +## Getting Started + +To help you with your Capstone, I wrote a full pipeline in a Python notebook that does all the key steps you need for your Capstone Project by example of classifying 10K sentences into business functions. This includes querying genAI via API at scale, creating holdout and training datasets, fine-tuning a pretrained LLM, and evaluating the performance of genAI and your fine-tuned (vertical AI) model. + +**What it does not do** is give you a construct of interest, collect your data, clean and preprocess your data, or draw conclusions and write reports for you. + +**Python notebook:** http://ringel.ai/UNC/2026/helpers/Ringel_2026_VerticalAI_Capstone_Pipeline_Example.ipynb + +**Zip file with outputs:** http://ringel.ai/UNC/2026/helpers/Ringel_2026_VerticalAI_Capstone_Pipeline_Example.zip (excludes the actual trained vertical AI because it is 1.5GB) + +All subfolders and datasets are included. This is a great blueprint for what data you need to deliver with your capstone on a shared drive (provide link to me) or uploaded if sufficiently small (less than 20MB). + +The contents of the zip file also help you see what the expected output is (by example of a multi-label classification problem). You will need to adapt this code to your problem. Use genAI (e.g., Claude Opus 4.6) for this. The pipeline gives you a solid base to work off. diff --git a/docs/reference/P3_SEC_Cybersecurity_Capstone.md b/docs/reference/P3_SEC_Cybersecurity_Capstone.md new file mode 100644 index 0000000..8fd17f2 --- /dev/null +++ b/docs/reference/P3_SEC_Cybersecurity_Capstone.md @@ -0,0 +1,688 @@ +# Project 3: SEC Cybersecurity Disclosure Quality Classifier + +## Capstone 2026 — BUSI488/COMP488 — Team Knowledge Transfer + +**Project:** Build a validated, reusable classifier that labels SEC cybersecurity disclosures by content category and specificity level, then fine-tune an open-weights model for deployment at scale. + +**Methodology:** Ringel (2023) "Synthetic Experts" pipeline — use frontier LLMs to generate training labels, then distill into a small open-weights encoder model. + +**Why this project:** No HuggingFace dataset of extracted Item 1C disclosures exists. No trained classifier for cybersecurity disclosure quality exists. No domain-adapted ModernBERT on SEC filings exists. The iXBRL CYD taxonomy just went live (Dec 2024). We produce **three publishable artifacts**: a novel dataset, a labeling methodology, and a SOTA classifier. + +--- + +## Table of Contents + +1. [Regulatory Background](#1-regulatory-background) +2. [Labeling Rubric](#2-labeling-rubric) +3. [Data Acquisition](#3-data-acquisition) +4. [GenAI Labeling Pipeline](#4-genai-labeling-pipeline) +5. [Model Strategy](#5-model-strategy) +6. [Evaluation & Validation](#6-evaluation--validation) +7. [Release Artifacts](#7-release-artifacts) +8. [3-Week Schedule (6 People)](#8-3-week-schedule-6-people) +9. [Budget](#9-budget) +10. [Reference Links](#10-reference-links) + +--- + +## 1. Regulatory Background + +### The Rule: SEC Release 33-11216 (July 2023) + +The SEC adopted final rules requiring public companies to disclose cybersecurity risk management, strategy, governance, and material incidents. This created a massive new text corpus with natural variation in quality — perfect for classification. + +Full rule PDF: +Fact sheet: + +### Item 1C — Annual Disclosure (10-K) + +Appears as **Regulation S-K Item 106**, reported in **Item 1C** of the 10-K. Two mandated subsections: + +**Item 106(b) — Risk Management and Strategy:** +1. Processes for assessing, identifying, and managing material cybersecurity risks +2. Whether/how cybersecurity processes integrate into overall enterprise risk management (ERM) +3. Whether the company engages external assessors, consultants, or auditors +4. Processes to oversee/identify risks from third-party service providers +5. Whether cybersecurity risks (including prior incidents) have materially affected or are reasonably likely to affect business strategy, results, or financial condition + +**Item 106(c) — Governance:** + +*Board Oversight (106(c)(1)):* +- Description of board's oversight of cybersecurity risks +- Identification of responsible board committee/subcommittee +- Processes by which the board/committee is informed about risks + +*Management's Role (106(c)(2)):* +- Which management positions/committees are responsible +- Relevant expertise of those persons +- How management monitors prevention, detection, mitigation, and remediation +- Whether and how frequently management reports to the board + +**Key design note:** The SEC uses "describe" — it does not prescribe specific items. The enumerated sub-items are non-exclusive suggestions. This principles-based approach creates natural variation in specificity and content, which is exactly what our rubric captures. + +### Item 1.05 — Incident Disclosure (8-K) + +Required within **4 business days** of determining a cybersecurity incident is material: +1. Material aspects of the nature, scope, and timing of the incident +2. Material impact or reasonably likely material impact on the registrant + +**Key nuances:** +- The 4-day clock starts at the **materiality determination**, not the incident itself +- Companies explicitly do NOT need to disclose technical details that would impede response/remediation +- The AG can delay disclosure up to 120 days for national security +- Companies must amend the 8-K when new material information becomes available + +**The May 2024 shift:** After SEC Director Erik Gerding clarified that Item 1.05 is only for *material* incidents, companies pivoted from Item 1.05 to Items 8.01/7.01 for non-material disclosures: +- Pre-guidance: 72% used Item 1.05, 28% used 8.01/7.01 +- Post-guidance: 34% used Item 1.05, 66% used 8.01/7.01 + +**Our extraction must capture all three item types.** + +### Compliance Timeline + +| Date | Milestone | +|------|-----------| +| Jul 26, 2023 | Rule adopted | +| Sep 5, 2023 | Rule effective | +| Dec 15, 2023 | Item 1C required in 10-Ks (FY ending on/after this date) | +| Dec 18, 2023 | Item 1.05 required in 8-Ks | +| Jun 15, 2024 | Item 1.05 required for smaller reporting companies | +| Dec 15, 2024 | iXBRL tagging of Item 106 (CYD taxonomy) required | +| Dec 18, 2024 | iXBRL tagging of 8-K Item 1.05 required | + +### iXBRL CYD Taxonomy + +The SEC published the **Cybersecurity Disclosure (CYD) Taxonomy** on Sep 16, 2024. Starting with filings after Dec 15, 2024, Item 1C disclosures are tagged in Inline XBRL using the `cyd` prefix. This means 2025 filings can be parsed programmatically via XBRL rather than HTML scraping. + +Taxonomy schema: `http://xbrl.sec.gov/cyd/2024` +Taxonomy guide: + +### Corpus Size + +| Filing Type | Estimated Count (as of early 2026) | +|-------------|-----------------------------------| +| 10-K with Item 1C (FY2023 cycle) | ~4,500 | +| 10-K with Item 1C (FY2024 cycle) | ~4,500 | +| 8-K cybersecurity incidents | ~80 filings (55 incidents + amendments) | +| **Total filings** | **~9,000-10,000** | +| **Estimated paragraphs** (from Item 1C) | **~50,000-80,000** | + +--- + +## 2. Labeling Rubric + +### Dimension 1: Content Category (single-label per paragraph) + +Derived directly from the SEC rule structure. Each paragraph receives exactly one category: + +| Category | SEC Basis | What It Covers | Example Markers | +|----------|-----------|----------------|-----------------| +| **Board Governance** | 106(c)(1) | Board/committee oversight, briefing frequency, board cyber expertise | "Audit Committee," "Board of Directors oversees," "quarterly briefings" | +| **Management Role** | 106(c)(2) | CISO/CTO identification, qualifications, reporting structure | "Chief Information Security Officer," "reports to," "years of experience" | +| **Risk Management Process** | 106(b) | Assessment/identification processes, ERM integration, framework references | "NIST CSF," "ISO 27001," "risk assessment," "vulnerability management" | +| **Third-Party Risk** | 106(b) | Vendor oversight, external assessors/consultants, supply chain risk | "third-party," "service providers," "penetration testing by," "external auditors" | +| **Incident Disclosure** | 8-K 1.05 | Nature/scope/timing of incidents, material impact, remediation | "unauthorized access," "detected," "incident," "remediation," "impacted" | +| **Strategy Integration** | 106(b)(2) | Material impact on business strategy, cyber insurance, resource allocation | "business strategy," "insurance," "investment," "material," "financial condition" | +| **None/Other** | — | Boilerplate intros, legal disclaimers, non-cybersecurity content | Forward-looking statement disclaimers, general risk language | + +### Dimension 2: Specificity (4-point ordinal per paragraph) + +Grounded in Berkman et al. (2018), Gibson Dunn surveys, and PwC quality tiers: + +| Level | Label | Definition | Decision Test | +|-------|-------|------------|---------------| +| **1** | **Generic Boilerplate** | Could apply to any company. Conditional language ("may," "could"). No named entities. Passive voice. | "Could I paste this into a different company's filing unchanged?" → Yes | +| **2** | **Sector-Adapted** | References industry context or named frameworks (NIST, ISO) but no firm-specific detail. | "Does this name something specific but not unique to THIS company?" → Yes | +| **3** | **Firm-Specific** | Names roles (CISO by name), committees, reporting lines, specific programs, or processes unique to the firm. Active voice with accountability. | "Does this contain at least one fact unique to THIS company?" → Yes | +| **4** | **Quantified-Verifiable** | Includes metrics, dollar amounts, dates, frequencies, third-party audit references, or independently verifiable facts. Multiple firm-specific facts with operational detail. | "Could an outsider verify a specific claim in this paragraph?" → Yes | + +**Boundary rules for annotators:** +- If torn between 1 and 2: "Does it name ANY framework, standard, or industry term?" → Yes = 2 +- If torn between 2 and 3: "Does it mention anything unique to THIS company?" → Yes = 3 +- If torn between 3 and 4: "Does it contain TWO OR MORE specific, verifiable facts?" → Yes = 4 + +**Important:** EvasionBench (Ma et al., 2026) found that a 5-level ordinal scale failed (kappa < 0.5) and had to be collapsed to 3 levels. **Pilot test this 4-level scale on 50 paragraphs early.** Be prepared to merge levels 1-2 or 3-4 if inter-annotator agreement is poor. + +### Boilerplate vs. Substantive Markers (from the literature) + +**Boilerplate indicators:** +- Conditional language: "may," "could," "might" +- Generic risk statements without company-specific context +- No named individuals, committees, or frameworks +- Identical language across same-industry filings (cosine similarity > 0.8) +- Passive voice: "cybersecurity risks are managed" + +**Substantive indicators:** +- Named roles and reporting structures ("Our CISO, Jane Smith, reports quarterly to the Audit Committee") +- Specific frameworks by name (NIST CSF, ISO 27001, SOC 2, PCI-DSS) +- Concrete processes (penetration testing frequency, tabletop exercises) +- Quantification (dollar investment, headcount, incident counts, training completion rates) +- Third-party names or types of assessments +- Temporal specificity (dates, frequencies, durations) + +### Mapping to NIST CSF 2.0 + +For academic grounding, our content categories map to NIST CSF 2.0 functions: + +| Our Category | NIST CSF 2.0 | +|-------------|-------------| +| Board Governance | GOVERN (GV.OV, GV.RR) | +| Management Role | GOVERN (GV.RR, GV.RM) | +| Risk Management Process | IDENTIFY (ID.RA), GOVERN (GV.RM), PROTECT (all) | +| Third-Party Risk | GOVERN (GV.SC) | +| Incident Disclosure | DETECT, RESPOND, RECOVER | +| Strategy Integration | GOVERN (GV.OC, GV.RM) | + +--- + +## 3. Data Acquisition + +### 3.1 Extracting 10-K Item 1C + +**Recommended pipeline:** + +``` +sec-edgar-downloader → edgar-crawler → paragraph segmentation → dataset + (bulk download) (parse Item 1C) (split into units) +``` + +**Tools:** + +| Tool | Purpose | Install | Notes | +|------|---------|---------|-------| +| `sec-edgar-downloader` | Bulk download 10-K filings by CIK | `pip install sec-edgar-downloader` | Pure downloader, no parsing | +| `edgar-crawler` | Extract specific item sections to JSON | `git clone github.com/lefterisloukas/edgar-crawler` | Best for bulk extraction; configure `['1C']` in items list | +| `edgartools` | Interactive exploration, XBRL parsing | `pip install edgartools` | `tenk['Item 1C']` accessor; great for prototyping | +| `sec-api` | Commercial API, zero parsing headaches | `pip install sec-api` | `extractorApi.get_section(url, "1C", "text")` — paid, free tier available | + +**EDGAR API requirements:** +- Rate limit: 10 requests/second +- Required: Custom `User-Agent` header with name and email (e.g., `"TeamName team@email.com"`) +- SEC blocks requests without proper User-Agent (returns 403) + +**For iXBRL-tagged filings (2025+):** Use `edgartools` XBRL parser to extract CYD taxonomy elements directly. This gives pre-structured data aligned with regulatory categories. + +**Fallback corpus:** `PleIAs/SEC` on HuggingFace (373K 10-K full texts, CC0 license) — but sections are NOT pre-parsed; you must extract Item 1C yourself. + +### 3.2 Extracting 8-K Incident Disclosures + +| Tool | Purpose | URL | +|------|---------|-----| +| `sec-8k-item105` | Extract Item 1.05 from 8-Ks, iXBRL + HTML fallback | `github.com/JMousqueton/sec-8k-item105` | +| `SECurityTr8Ker` | Monitor SEC RSS for new cyber 8-Ks, Slack/Teams alerts | `github.com/pancak3lullz/SECurityTr8Ker` | +| Debevoise 8-K Tracker | Curated list with filing links, dates, amendments | `debevoisedatablog.com/2024/03/06/cybersecurity-form-8-k-tracker/` | +| Board Cybersecurity Tracker | Links filings to MITRE ATT&CK, impact assessments | `board-cybersecurity.com/incidents/tracker` | + +**Critical:** Must capture Item 1.05 AND Items 8.01/7.01 (post-May 2024 shift). + +### 3.3 Paragraph Segmentation + +Once Item 1C text is extracted, segment into paragraphs: +- Split on double newlines or `

` tags (depending on extraction format) +- Minimum paragraph length: 20 words (filter out headers, whitespace) +- Maximum paragraph length: 500 words (split longer blocks at sentence boundaries) +- Preserve metadata: company name, CIK, ticker, filing date, fiscal year + +Expected yield: ~5-8 paragraphs per Item 1C disclosure × ~9,000 filings = **~50,000-70,000 paragraphs** + +### 3.4 Pre-Existing Datasets and Resources + +| Resource | What It Is | URL | +|----------|-----------|-----| +| PleIAs/SEC | 373K full 10-K texts (CC0) | `huggingface.co/datasets/PleIAs/SEC` | +| EDGAR-CORPUS | 220K filings with sections pre-parsed (Apache 2.0) | `huggingface.co/datasets/eloukas/edgar-corpus` | +| Board Cybersecurity 23-Feature Analysis | Regex-based extraction of 23 governance/security features from 4,538 10-Ks | `board-cybersecurity.com/research/insights/` | +| Gibson Dunn S&P 100 Survey | Detailed feature analysis of disclosure content | `corpgov.law.harvard.edu/2025/01/09/cybersecurity-disclosure-overview-...` | +| Florackis et al. (2023) "Cybersecurity Risk" | Firm-level cyber risk measure from 10-K text, RFS publication | SSRN: 3725130, data companion: 4319606 | +| zeroshot/cybersecurity-corpus | General cybersecurity text (not SEC-specific, useful for DAPT) | `huggingface.co/datasets/zeroshot/cybersecurity-corpus` | + +--- + +## 4. GenAI Labeling Pipeline + +### 4.1 Multi-Model Consensus (EvasionBench Architecture) + +We follow Ma et al. (2026, arXiv:2601.09142) — the EvasionBench pipeline designed for an almost identical task (ordinal classification of financial text). Their approach achieved Cohen's Kappa = 0.835 with human annotators. + +**Stage 1 — Dual Independent Annotation (all ~50K paragraphs):** +- Annotator A: **Claude Sonnet 4.6** (batch API — $1.50/$7.50 per M input/output tokens) +- Annotator B: **Gemini 2.5 Flash** ($0.30/$2.50 per M tokens) +- Architectural diversity (Anthropic vs. Google) minimizes correlated errors +- ~83% of paragraphs will have immediate agreement + +**Stage 2 — Judge Panel for Disagreements (~17% = ~8,500 cases):** +- Judge 1: **Claude Opus 4.6** (batch — $2.50/$12.50 per M tokens) +- Judge 2: **GPT-5** (batch — $0.63/$5.00 per M tokens) +- Judge 3: **Gemini 2.5 Pro** (~$2-4/$12-18 per M tokens) +- Majority vote (2/3) resolves disagreements +- Anti-bias: randomize label presentation order + +**Stage 3 — Active Learning Pass:** +- Cluster remaining low-confidence cases +- Human-review ~5% (~2,500 cases) to identify systematic errors +- Iterate rubric if needed, re-run affected subsets + +### 4.2 Prompt Template + +``` +SYSTEM PROMPT: +You are an expert annotator classifying paragraphs from SEC cybersecurity +disclosures (10-K Item 1C and 8-K Item 1.05 filings). + +For each paragraph, assign: +(a) content_category: exactly one of ["Board Governance", "Management Role", + "Risk Management Process", "Third-Party Risk", "Incident Disclosure", + "Strategy Integration", "None/Other"] +(b) specificity_level: integer 1-4 + +CONTENT CATEGORIES: +- Board Governance: Board/committee oversight of cybersecurity risks, briefing + frequency, board member cyber expertise +- Management Role: CISO/CTO/CIO identification, qualifications, reporting + structure, management committees +- Risk Management Process: Risk assessment methodology, framework adoption + (NIST, ISO, etc.), vulnerability management, monitoring, incident response + planning, tabletop exercises +- Third-Party Risk: Vendor/supplier risk oversight, external assessor engagement, + contractual security requirements, supply chain risk +- Incident Disclosure: Description of cybersecurity incidents, scope, timing, + impact, remediation actions +- Strategy Integration: Material impact on business strategy or financials, + cyber insurance, investment/resource allocation +- None/Other: Boilerplate introductions, legal disclaimers, forward-looking + statement warnings, non-cybersecurity content + +SPECIFICITY SCALE: +1 - Generic Boilerplate: Could apply to any company. Conditional language + ("may," "could"). No named entities. + Example: "We face cybersecurity risks that could materially affect our + business operations." + +2 - Sector-Adapted: References industry context or named frameworks but no + firm-specific details. + Example: "We employ a cybersecurity framework aligned with the NIST + Cybersecurity Framework to manage cyber risk." + +3 - Firm-Specific: Contains facts unique to this company — named roles, + committees, specific programs, reporting lines. + Example: "Our CISO reports quarterly to the Audit Committee on + cybersecurity risk posture and incident trends." + +4 - Quantified-Verifiable: Includes metrics, dollar amounts, dates, + frequencies, third-party audit references, or independently verifiable facts. + Example: "Following the March 2024 incident affecting our payment systems, + we engaged CrowdStrike and implemented network segmentation at a cost of + $4.2M, completing remediation in Q3 2024." + +BOUNDARY RULES: +- If torn between 1 and 2: "Does it name ANY framework, standard, or industry + term?" If yes → 2 +- If torn between 2 and 3: "Does it mention anything unique to THIS company?" + If yes → 3 +- If torn between 3 and 4: "Does it contain TWO OR MORE specific, verifiable + facts?" If yes → 4 + +Respond with valid JSON only. Include a brief reasoning field. + +USER PROMPT: +Company: {company_name} +Filing Date: {filing_date} +Paragraph: +{paragraph_text} +``` + +**Expected output:** +```json +{ + "content_category": "Board Governance", + "specificity_level": 3, + "reasoning": "Identifies Audit Committee by name and describes quarterly briefing cadence, both firm-specific facts." +} +``` + +### 4.3 Practical Labeling Notes + +- **Always use Batch API.** Both OpenAI and Anthropic offer 50% discount for async/batch processing (24-hour turnaround). No reason to use real-time. +- **Prompt caching:** The system prompt (~800 tokens) is identical for every request. With Anthropic's prompt caching, cached reads cost 10% of base price. Combined with batch discount = 5% of standard price. +- **Structured output mode:** Use JSON mode / structured outputs on all providers. Reduces parsing errors by ~90%. +- **Reasoning models (o3, extended thinking):** Use ONLY as judges for disagreement cases, not as primary annotators. They're overkill for clear-cut classification and expensive due to reasoning token consumption. + +### 4.4 Gold Set Protocol + +**Non-negotiable for publication quality.** + +1. Sample 300-500 paragraphs, stratified by: + - Expected content category (ensure all 7 represented) + - Expected specificity level (ensure all 4 represented) + - Industry (financial services, tech, healthcare, manufacturing) + - Filing year (FY2023 vs FY2024) + +2. Two team members independently label the full gold set + +3. Compute: + - Cohen's Kappa (binary/nominal categories) + - Krippendorff's Alpha (ordinal specificity scale) + - Per-class confusion matrices + - Target: Kappa > 0.75 ("substantial agreement") + +4. Adjudicate disagreements with a third team member + +5. Run the full MMC pipeline on the gold set and compare + +--- + +## 5. Model Strategy + +### 5.1 Primary: SEC-ModernBERT-large + +**This model does not exist publicly. Building it is a core contribution.** + +**Base model:** `answerdotai/ModernBERT-large` +- 395M parameters +- 8,192-token native context (vs. 512 for DeBERTa-v3-large) +- RoPE + alternating local/global attention + FlashAttention +- 2-4x faster than DeBERTa-v3-large +- Apache 2.0 license +- GLUE: 90.4 (only 1 point behind DeBERTa-v3-large's 91.4) + +**Step 1 — Domain-Adaptive Pre-Training (DAPT):** + +Continue MLM pre-training on SEC filing text to create "SEC-ModernBERT-large": + +- **Training corpus:** 200-500M tokens of SEC filings (from PleIAs/SEC or your own EDGAR download). Include 10-Ks, 10-Qs, 8-Ks, proxy statements. +- **MLM objective:** 30% masking rate (ModernBERT convention) +- **Learning rate:** ~5e-5 (much lower than from-scratch pre-training) +- **Hardware (RTX 3090):** bf16, gradient checkpointing, seq_len=1024-2048, batch_size=2-4 + gradient accumulation to effective batch 16-32 +- **VRAM estimate:** ~12-15GB at batch=4, seq=2048 with gradient checkpointing — fits on 3090 + +**Evidence DAPT works:** +- Gururangan et al. (2020): consistent improvements across all tested domains +- Patent domain ModernBERT (arXiv:2509.14926): +0.9 to +2.8 F1 from continued pre-training on 31.6B tokens +- Scaling-law analysis on SEC filings (arXiv:2512.12384): consistent improvement with largest gains in first 200M tokens +- Databricks customer report: 70% → 95% accuracy with domain-specific pre-training + +**Step 2 — Classification Fine-Tuning:** + +Fine-tune SEC-ModernBERT-large on the 50K labeled paragraphs: + +- **Sequence length:** 2048 tokens (captures full regulatory paragraphs that 512-token models truncate) +- **Two classification heads:** content_category (7-class softmax) + specificity_level (4-class ordinal or softmax) +- **Add supervised contrastive loss (SCL):** Combine standard cross-entropy with SCL that pulls same-class embeddings together. Gunel et al. (2020) showed +0.5-1.5% improvement, especially for rare/imbalanced classes. +- **VRAM:** ~11-13GB at batch=8, seq=2048 in bf16 — comfortable on 3090 +- **3090 supports bf16** natively via Ampere Tensor Cores. Use `bf16=True` in HuggingFace Trainer. No loss scaling needed (unlike fp16). + +### 5.2 Dark Horse: NeoBERT + +`chandar-lab/NeoBERT` +- **250M parameters** (100M fewer than ModernBERT-large, 185M fewer than DeBERTa-v3-large) +- 4,096-token context +- SwiGLU, RoPE, Pre-RMSNorm, FlashAttention +- GLUE: 89.0 (close to DeBERTa-v3-large's 91.4) +- MTEB: 51.3 (crushes everything else — ModernBERT-large is 46.9) +- MIT license +- Requires `trust_remote_code=True` +- Almost nobody is using it for domain-specific tasks + +Same DAPT + fine-tuning pipeline as ModernBERT-large, with even less VRAM. + +### 5.3 Baseline: DeBERTa-v3-large + +`microsoft/deberta-v3-large` +- 304M backbone + 131M embedding = ~435M total +- 512-token native context (can push to ~1024) +- Disentangled attention + ELECTRA-style RTD pre-training +- GLUE: **91.4** — still the highest among all encoders +- MIT license +- **Weakness:** no long context support, completely fails at retrieval tasks + +Include as baseline to show improvement from (a) long context and (b) DAPT. + +### 5.4 Ablation Design + +| Experiment | Model | Context | DAPT | SCL | Purpose | +|-----------|-------|---------|------|-----|---------| +| Baseline | DeBERTa-v3-large | 512 | No | No | "Standard" approach per syllabus | +| + Long context | ModernBERT-large | 2048 | No | No | Shows context window benefit | +| + Domain adapt | SEC-ModernBERT-large | 2048 | Yes | No | Shows DAPT benefit | +| + Contrastive | SEC-ModernBERT-large | 2048 | Yes | Yes | Shows SCL benefit | +| Efficiency | NeoBERT (+ DAPT) | 2048 | Yes | Yes | 40% fewer params, comparable? | +| **Ensemble** | SEC-ModernBERT + DeBERTa | mixed | mixed | — | Maximum performance | + +The ensemble averages logits from SEC-ModernBERT-large (long context, domain-adapted) and DeBERTa-v3-large (highest raw NLU). Their architecturally different attention mechanisms mean uncorrelated errors. + +### 5.5 Training Framework + +- **Encoder fine-tuning:** HuggingFace `transformers` + `Trainer` with `AutoModelForSequenceClassification` +- **DAPT continued pre-training:** HuggingFace `transformers` with `DataCollatorForLanguageModeling` +- **SCL implementation:** Custom training loop or modify Trainer with dual loss +- **Few-shot prototyping:** `SetFit` (sentence-transformers based) for rapid baseline in <30 seconds + +**Key reference:** Phil Schmid's ModernBERT fine-tuning tutorial: + +### 5.6 Domain-Specific Encoder Models (for comparison only) + +These exist but are all BERT-base (110M params, 512 context) — architecturally outdated: + +| Model | HuggingFace ID | Domain | Params | +|-------|---------------|--------|--------| +| SEC-BERT | `nlpaueb/sec-bert-base` | 260K 10-K filings | 110M | +| SEC-BERT-SHAPE | `nlpaueb/sec-bert-shape` | Same, with number normalization | 110M | +| FinBERT | `ProsusAI/finbert` | Financial sentiment | 110M | +| Legal-BERT | `nlpaueb/legal-bert-base-uncased` | 12GB legal text | 110M | +| SecureBERT | arXiv:2204.02685 | Cybersecurity text | 110M | + +Our DAPT approach on a modern architecture (ModernBERT-large or NeoBERT) will outperform all of these. Include SEC-BERT as an additional baseline if time permits. + +--- + +## 6. Evaluation & Validation + +### 6.1 Required Metrics (from syllabus) + +| Metric | Target | Notes | +|--------|--------|-------| +| **Macro-F1** on human holdout | Report per-class and overall | Minimum 1.2K holdout examples | +| **Per-class F1** | Identify weak categories | Expect "None/Other" to be noisiest | +| **Krippendorff's Alpha** | > 0.67 (adequate), > 0.75 (good) | GenAI labels vs. human gold set | +| **Calibration plots** | Reliability diagrams | For probabilistic outputs (softmax) | +| **Robustness splits** | Report by time period, industry, filing size | FY2023 vs FY2024; GICS sector; word count quartiles | + +### 6.2 Downstream Validity Tests + +These demonstrate that the classifier's predictions correlate with real-world outcomes: + +**Test 1 — Breach Prediction (strongest):** +- Do firms with lower specificity scores subsequently appear in breach databases? +- Cross-reference with: + - **Privacy Rights Clearinghouse** (80K+ breaches; Mendeley dataset provides ticker/CIK matching: `doi.org/10.17632/w33nhh3282.1`) + - **VCDB** (8K+ incidents, VERIS schema: `github.com/vz-risk/VCDB`) + - **Board Cybersecurity Incident Tracker** (direct SEC filing links: `board-cybersecurity.com/incidents/tracker`) + - **CISA KEV Catalog** (known exploited vulnerabilities: `cisa.gov/known-exploited-vulnerabilities-catalog`) + +**Test 2 — Market Reaction (if time permits):** +- Event study: abnormal returns in [-1, +3] window around 8-K Item 1.05 filing +- Does prior Item 1C disclosure quality predict magnitude of reaction? +- Small sample (~55 incidents) but high signal +- Regression: CAR = f(specificity_score, incident_severity, firm_size, industry) + +**Test 3 — Known-Groups Validity (easy, always include):** +- Do regulated industries (financial services under NYDFS, healthcare under HIPAA) produce systematically higher-specificity disclosures? +- Do larger firms (by market cap) have more specific disclosures? +- These are expected results — confirming them validates the measure + +**Test 4 — Boilerplate Index (easy, always include):** +- Compute cosine similarity of each company's Item 1C to the industry-median disclosure +- Does our specificity score inversely correlate with this similarity measure? +- This is an independent, construct-free validation of the "uniqueness" dimension + +### 6.3 External Benchmark + +Per syllabus: "include an external benchmark approach (i.e., previous best practice)." + +- **Board Cybersecurity's 23-feature regex extraction** is the natural benchmark. Their binary (present/absent) feature coding is the prior best practice. Our classifier should capture everything their regex captures plus the quality/specificity dimension they cannot measure. +- **Florackis et al. (2023) cybersecurity risk measure** from Item 1A text is another comparison — different section (1A vs 1C), different methodology (dictionary vs. classifier), different era (pre-rule vs. post-rule). + +--- + +## 7. Release Artifacts + +By project end, publish: + +1. **HuggingFace Dataset:** Extracted Item 1C paragraphs with labels — first public dataset of its kind +2. **SEC-ModernBERT-large:** Domain-adapted model weights — first SEC-specific ModernBERT +3. **Fine-tuned classifiers:** Content category + specificity models, ready to deploy +4. **Labeling rubric + prompt templates:** Reusable for future SEC disclosure research +5. **Extraction pipeline code:** EDGAR → structured paragraphs → labeled dataset +6. **Evaluation notebook:** All metrics, ablations, validation tests + +--- + +## 8. 3-Week Schedule (6 People) + +### Team Roles + +| Role | Person(s) | Primary Responsibility | +|------|-----------|----------------------| +| **Data Lead** | Person A | EDGAR extraction pipeline, paragraph segmentation, data cleaning | +| **Data Support** | Person B | 8-K extraction, breach database cross-referencing, dataset QA | +| **Labeling Lead** | Person C | Rubric refinement, GenAI prompt engineering, MMC pipeline orchestration | +| **Annotation** | Person D | Gold set human labeling, inter-rater reliability, active learning review | +| **Model Lead** | Person E | DAPT pre-training, classification fine-tuning, ablation experiments | +| **Eval & Writing** | Person F | Validation tests, metrics computation, final presentation, documentation | + +### Week 1: Data + Rubric + +| Day | Person A (Data Lead) | Person B (Data Support) | Person C (Labeling Lead) | Person D (Annotation) | Person E (Model Lead) | Person F (Eval & Writing) | +|-----|---------------------|------------------------|-------------------------|----------------------|----------------------|--------------------------| +| **Mon** | Set up EDGAR extraction pipeline (edgar-crawler + sec-edgar-downloader) | Set up 8-K extraction (sec-8k-item105) | Draft labeling rubric v1 from SEC rule | Read SEC rule + Gibson Dunn survey | Download ModernBERT-large, set up training env | Outline evaluation plan, identify breach databases | +| **Tue** | Begin bulk 10-K download (FY2023 cycle) | Extract all 8-K cyber filings (Items 1.05, 8.01, 7.01) | Pilot rubric on 30 paragraphs with Claude Opus | Pilot rubric on same 30 paragraphs independently | Download PleIAs/SEC corpus, prepare DAPT data | Download PRC Mendeley dataset, VCDB, set up cross-ref | +| **Wed** | Continue download (FY2024 cycle), begin Item 1C parsing | Build company metadata table (CIK → ticker → GICS sector → market cap) | Compare pilot labels with Person D, revise rubric boundary rules | Compute initial inter-rater agreement, flag problem areas | Begin DAPT pre-training (SEC-ModernBERT-large, ~2-3 days on 3090) | Map VCDB incidents to SEC filers by name matching | +| **Thu** | Paragraph segmentation pipeline, quality checks | Merge 8-K incidents with Board Cybersecurity Tracker data | Rubric v2 finalized; set up batch API calls for dual annotation | Begin gold set sampling (300-500 paragraphs, stratified) | DAPT continues (monitor loss, checkpoint) | Draft presentation outline | +| **Fri** | **Milestone: Full paragraph corpus ready (~50K+ paragraphs)** | **Milestone: 8-K incident dataset complete** | Launch Stage 1 dual annotation (Sonnet + Gemini Flash) on full corpus | Continue gold set labeling (target: finish 150/300) | DAPT continues | **Milestone: Evaluation framework + breach cross-ref ready** | + +### Week 2: Labeling + Training + +| Day | Person A | Person B | Person C | Person D | Person E | Person F | +|-----|----------|----------|----------|----------|----------|----------| +| **Mon** | Data cleaning — fix extraction errors, handle edge cases | Assist Person D with gold set labeling (second annotator) | Monitor dual annotation results (should be ~60% complete) | Continue gold set labeling, begin second pass | DAPT finishes; begin DeBERTa-v3-large baseline fine-tuning | Compute gold set inter-rater reliability (Kappa, Alpha) | +| **Tue** | Build train/holdout split logic (stratified by industry, year, specificity) | Continue gold set second-annotator pass | Dual annotation complete → extract disagreements (~17%) | Finish gold set, adjudicate disagreements with Person C | Baseline results in; begin ModernBERT-large (no DAPT) fine-tuning | Analyze gold set confusion patterns, recommend rubric tweaks | +| **Wed** | Final dataset assembly | Assist Person C with judge panel setup | Launch Stage 2 judge panel (Opus + GPT-5 + Gemini Pro) on disagreements | Run MMC pipeline on gold set, compare with human labels | ModernBERT-large done; begin SEC-ModernBERT-large fine-tuning | **Milestone: Gold set validated, Kappa computed** | +| **Thu** | Prepare HuggingFace dataset card | Begin active learning — cluster low-confidence cases | Judge panel results in; assemble final labeled dataset | Human-review ~500 low-confidence cases from active learning | SEC-ModernBERT-large done; begin NeoBERT experiment | Robustness split analysis (by industry, year, filing size) | +| **Fri** | **Milestone: Labeled dataset finalized (~50K paragraphs)** | **Milestone: Active learning pass complete** | QA final labels — spot-check 100 random samples | Assist Person E with evaluation | Begin ensemble experiment (SEC-ModernBERT + DeBERTa) | **Milestone: All baseline + ablation training complete** | + +### Week 3: Evaluation + Presentation + +| Day | Person A | Person B | Person C | Person D | Person E | Person F | +|-----|----------|----------|----------|----------|----------|----------| +| **Mon** | Publish dataset to HuggingFace | Run breach prediction validation (PRC + VCDB cross-ref) | Write labeling methodology section | Calibration plots for all models | Final ensemble tuning; publish model weights to HuggingFace | Compile all metrics into evaluation tables | +| **Tue** | Write data acquisition section | Run known-groups validity (industry, size effects) | Write GenAI labeling section | Boilerplate index validation (cosine similarity) | Write model strategy section | Draft full results section | +| **Wed** | Code cleanup, README for extraction pipeline | Market reaction analysis if feasible (optional) | Review/edit all written sections | Create figures: confusion matrices, calibration plots | Review/edit model section | Assemble presentation slides | +| **Thu** | **Full team: review presentation, rehearse, polish** | | | | | | +| **Fri** | **Presentation day** | | | | | | + +### Critical Path & Dependencies + +``` +Week 1: + Data extraction (A,B) ──────────────────┐ + Rubric design (C,D) ───→ Pilot test ───→ Rubric v2 ──→ GenAI labeling launch (Fri) + DAPT pre-training (E) ──────────────────────────────────→ (continues into Week 2) + Eval framework (F) ─────────────────────────────────────→ (ready for Week 2) + +Week 2: + GenAI labeling (C) ───→ Judge panel ───→ Active learning ───→ Final labels (Fri) + Gold set (D + B) ──────────────────────→ Validated (Wed) + Fine-tuning experiments (E) ───→ Baseline → ModernBERT → SEC-ModernBERT → NeoBERT → Ensemble + Metrics (F) ───────────────────→ Robustness splits + +Week 3: + Validation tests (B,D,F) ───→ Breach prediction, known-groups, boilerplate index + Writing (all) ──────────────→ Sections → Review → Presentation + Release (A,E) ──────────────→ HuggingFace dataset + model weights +``` + +--- + +## 9. Budget + +| Item | Cost | +|------|------| +| GenAI labeling — Stage 1 dual annotation (50K × 2 models, batch) | ~$115 | +| GenAI labeling — Stage 2 judge panel (~8.5K × 3 models, batch) | ~$55 | +| Prompt caching savings | -$30 to -$40 | +| SEC EDGAR data | $0 (public domain) | +| Breach databases (PRC open data, VCDB, CISA KEV) | $0 | +| Compute (RTX 3090, already owned) | $0 | +| **Total** | **~$130-170** | + +For comparison, human annotation at $0.50/label would cost $25,000+ for single-annotated, $75,000+ for triple-annotated. + +--- + +## 10. Reference Links + +### SEC Rule & Guidance +- [SEC Final Rule 33-11216 (PDF)](https://www.sec.gov/files/rules/final/2023/33-11216.pdf) +- [SEC Fact Sheet](https://www.sec.gov/files/33-11216-fact-sheet.pdf) +- [SEC Small Business Compliance Guide](https://www.sec.gov/resources-small-businesses/small-business-compliance-guides/cybersecurity-risk-management-strategy-governance-incident-disclosure) +- [CYD iXBRL Taxonomy Guide (PDF)](https://xbrl.sec.gov/cyd/2024/cyd-taxonomy-guide-2024-09-16.pdf) + +### Law Firm Surveys & Analysis +- [Gibson Dunn S&P 100 Survey (Harvard Law Forum)](https://corpgov.law.harvard.edu/2025/01/09/cybersecurity-disclosure-overview-a-survey-of-form-10-k-cybersecurity-disclosures-by-sp-100-companies/) +- [PwC First Wave of 10-K Cyber Disclosures](https://www.pwc.com/us/en/services/consulting/cybersecurity-risk-regulatory/sec-final-cybersecurity-disclosure-rules/sec-10-k-cyber-disclosures.html) +- [Debevoise 8-K Lessons Learned](https://www.debevoisedatablog.com/2024/03/06/cybersecurity-form-8-k-tracker/) +- [Greenberg Traurig 2025 Trends Update](https://www.gtlaw.com/en/insights/2025/2/sec-cybersecurity-disclosure-trends-2025-update-on-corporate-reporting-practices) +- [Known Trends: First Year of 8-K Filings](https://www.knowntrends.com/2025/02/snapshot-the-first-year-of-cybersecurity-incident-filings-on-form-8-k-since-adoption-of-new-rules/) +- [NYU: Lessons Learned from 8-K Reporting](https://wp.nyu.edu/compliance_enforcement/2025/03/25/lessons-learned-one-year-of-form-8-k-material-cybersecurity-incident-reporting/) + +### Data Extraction Tools +- [edgar-crawler (GitHub)](https://github.com/lefterisloukas/edgar-crawler) +- [edgartools (GitHub)](https://github.com/dgunning/edgartools) +- [sec-edgar-downloader (PyPI)](https://pypi.org/project/sec-edgar-downloader/) +- [sec-8k-item105 (GitHub)](https://github.com/JMousqueton/sec-8k-item105) +- [SECurityTr8Ker (GitHub)](https://github.com/pancak3lullz/SECurityTr8Ker) +- [SEC EDGAR APIs](https://www.sec.gov/search-filings/edgar-application-programming-interfaces) +- [SEC EDGAR Full-Text Search](https://efts.sec.gov/LATEST/search-index) + +### Datasets +- [PleIAs/SEC — 373K 10-K texts (HuggingFace, CC0)](https://huggingface.co/datasets/PleIAs/SEC) +- [EDGAR-CORPUS — 220K filings, sections parsed (HuggingFace, Apache 2.0)](https://huggingface.co/datasets/eloukas/edgar-corpus) +- [Board Cybersecurity 23-Feature Analysis](https://www.board-cybersecurity.com/research/insights/risk-frameworks-security-standards-in-10k-item-1c-cybersecurity-disclosures-through-2024-06-30/) +- [Board Cybersecurity Incident Tracker](https://www.board-cybersecurity.com/incidents/tracker) +- [PRC Mendeley Breach Dataset (with tickers)](http://dx.doi.org/10.17632/w33nhh3282.1) +- [VCDB (GitHub)](https://github.com/vz-risk/VCDB) +- [CISA KEV Catalog](https://www.cisa.gov/known-exploited-vulnerabilities-catalog) +- [zeroshot/cybersecurity-corpus (HuggingFace)](https://huggingface.co/datasets/zeroshot/cybersecurity-corpus) + +### Models +- [ModernBERT-large (HuggingFace, Apache 2.0)](https://huggingface.co/answerdotai/ModernBERT-large) +- [ModernBERT-base (HuggingFace, Apache 2.0)](https://huggingface.co/answerdotai/ModernBERT-base) +- [NeoBERT (HuggingFace, MIT)](https://huggingface.co/chandar-lab/NeoBERT) +- [DeBERTa-v3-large (HuggingFace, MIT)](https://huggingface.co/microsoft/deberta-v3-large) +- [SEC-BERT (HuggingFace)](https://huggingface.co/nlpaueb/sec-bert-base) +- [ProsusAI FinBERT (HuggingFace)](https://huggingface.co/ProsusAI/finbert) +- [EvasionBench Eva-4B-V2 (HuggingFace)](https://huggingface.co/FutureMa/Eva-4B-V2) + +### Key Papers +- Ringel (2023), "Creating Synthetic Experts with Generative AI" — [SSRN:4542949](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=4542949) +- Ludwig et al. (2026), "Extracting Consumer Insight from Text" — [arXiv:2602.15312](https://arxiv.org/abs/2602.15312) +- Ma et al. (2026), "EvasionBench" — [arXiv:2601.09142](https://arxiv.org/abs/2601.09142) +- Florackis et al. (2023), "Cybersecurity Risk" — [SSRN:3725130](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3725130) +- Gururangan et al. (2020), "Don't Stop Pretraining" — [arXiv:2004.10964](https://arxiv.org/abs/2004.10964) +- ModernBERT paper — [arXiv:2412.13663](https://arxiv.org/abs/2412.13663) +- NeoBERT paper — [arXiv:2502.19587](https://arxiv.org/abs/2502.19587) +- ModernBERT vs DeBERTa-v3 comparison — [arXiv:2504.08716](https://arxiv.org/abs/2504.08716) +- Patent domain ModernBERT DAPT — [arXiv:2509.14926](https://arxiv.org/abs/2509.14926) +- SEC filing scaling laws for continued pre-training — [arXiv:2512.12384](https://arxiv.org/abs/2512.12384) +- Gunel et al. (2020), Supervised Contrastive Learning for fine-tuning — [OpenReview](https://openreview.net/forum?id=cu7IUiOhujH) +- Phil Schmid, "Fine-tune classifier with ModernBERT in 2025" — [philschmid.de](https://www.philschmid.de/fine-tune-modern-bert-in-2025) +- Berkman et al. (2018), Cybersecurity disclosure quality scoring +- Li, No, and Boritz (2023), BERT-based classification of cybersecurity disclosures +- Scalable 10-K Analysis with LLMs — [arXiv:2409.17581](https://arxiv.org/abs/2409.17581) +- SecureBERT — [arXiv:2204.02685](https://arxiv.org/abs/2204.02685) +- Gilardi et al. (2023), "ChatGPT Outperforms Crowd-Workers" (PNAS) — [arXiv:2303.15056](https://arxiv.org/abs/2303.15056) +- Pangakis et al. (2023), "Automated Annotation Requires Validation" — [arXiv:2306.00176](https://arxiv.org/abs/2306.00176) + +### Methodological Playbook +- [Ringel 2026 Capstone Pipeline Example (ZIP)](http://ringel.ai/UNC/2026/helpers/Ringel_2026_VerticalAI_Capstone_Pipeline_Example.zip) +- [Class 21 Exemplary Presentation (PDF)](http://www.ringel.ai/UNC/2026/BUSI488/Class21/Ringel_488-2026_Class21.pdf) diff --git a/docs/reference/Ringel_2026_VerticalAI_Capstone_Pipeline_Example.ipynb b/docs/reference/Ringel_2026_VerticalAI_Capstone_Pipeline_Example.ipynb new file mode 100644 index 0000000..c17fc3e --- /dev/null +++ b/docs/reference/Ringel_2026_VerticalAI_Capstone_Pipeline_Example.ipynb @@ -0,0 +1,4433 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "f2658472-1630-4aae-aaa4-01987b0eff1e", + "metadata": {}, + "source": [ + "# Training a Vertical AI for 10K Text Classification in Business Functions\n", + "Supports APIs of OpenAI (Responses API), Anthropic, xAI, Fireworks AI, Google, UNC Azure hosted\n", + "\n", + "February 4, 2026 \n", + "\n", + "*Version 1.0*\n", + "\n", + "Copyright 2026 Daniel M. Ringel \n", + "www.ringel.ai \n", + "\n", + "\n", + "**Please cite this paper** if you use any part or all of this code in a project - be it commercial or academic: \n", + "\n", + "> Ringel, Daniel, *Creating Synthetic Experts with Generative Artificial Intelligence* (December 5, 2023). Kenan Institute of Private Enterprise Research Paper No. 4542949, Available at SSRN: https://ssrn.com/abstract=4542949 or http://dx.doi.org/10.2139/ssrn.4542949 \n" + ] + }, + { + "cell_type": "markdown", + "id": "4f4233be-6c67-41db-bc89-7b47bde71d59", + "metadata": {}, + "source": [ + "Query various serverless genAI models to classify text by example of a multi-label classification problem\n", + "- Sentences from 10K filings of fortune 500 companies\n", + "- Construct of Interest: Business functions\n", + "- Valid labels: Marketing, Finance, Accounting, Operations, IT, HR" + ] + }, + { + "cell_type": "markdown", + "id": "eda002cb-c5ef-4a68-ba10-4d4ee65e836a", + "metadata": {}, + "source": [ + "> **IMPORTANT** Running this code will cost you API credits (and requires you to ahve accounts with the providers). You will need to supply your own API keys. Beware that you may be subject to rate limits (how many queries you can send per minute) and which models you can use (OpenAI, for example, requires you to verify your identidy with an ID to access many models). Regardless, every time you execute this code, you will drain your API credits = real money! Thus, make wise decisions about what and how much to label." + ] + }, + { + "cell_type": "markdown", + "id": "9228e155-f4b0-45f8-96ba-8cb99c0bb990", + "metadata": {}, + "source": [ + "## **Disclaimer**\n", + "\n", + "**USE AT YOUR OWN RISK**\n", + "\n", + "This code is provided \"as is\" without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and noninfringement.\n", + "\n", + "Under no circumstances shall Daniel Ringel be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services, loss of use, data, or profits, or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this code, even if advised of the possibility of such damage.\n", + "\n", + "**Additional Notes:**\n", + "- API costs incurred from running this code are your sole responsibility\n", + "- Verify all API pricing before running at scale\n", + "- Test with small samples before processing large datasets\n", + "- The author makes no guarantees about the accuracy, reliability, or completeness of results\n", + "- This code is for educational and research purposes\n", + "\n", + "By using this code, you acknowledge that you have read this disclaimer and agree to its terms.\n" + ] + }, + { + "cell_type": "markdown", + "id": "4eed4986-cdb9-4285-80d4-7c2e415a5268", + "metadata": {}, + "source": [ + "# Installs and updates\n", + "- need to run only once if you are on your own computer\n", + "- on CoLab, you may need to run each time" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8714eefd-4af8-4116-a4fb-922bf1aa4667", + "metadata": {}, + "outputs": [], + "source": [ + "# Core\n", + "!pip install --upgrade pandas tqdm\n", + "# OpenAI (also used for xAI and Fireworks)\n", + "!pip install --upgrade openai\n", + "# Anthropic\n", + "!pip install --upgrade anthropic\n", + "# Google Gemini\n", + "!pip install --upgrade google-genai google-api-core\n", + "# For Label Agreement\n", + "!pip install -q -U krippendorff \n", + "# For Fine-tuning a pretrained LLM\n", + "!pip install -q -U transformers datasets accelerate scikit-learn\n", + "!pip install iterative-stratification" + ] + }, + { + "cell_type": "markdown", + "id": "9ef820f3-b6b2-4799-9af8-45e8e4ac5194", + "metadata": {}, + "source": [ + "# Set Environmental Variables (API Keys) on local Computer \n", + "### *(or on Colab in Secret Keys Tab)*\n", + "> **DO NOT SHARE API KEYS!!!** Delte them before sharing this notebook\n", + " \n", + "> On ***Colab***, use \"Secrets\" in Tab (key) on right. Make sure to use the exact same API Key names (e.g., \"OPENAI_API_KEY\") spelled and capitalized as shown!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c82d0c2c-8b19-49e0-80d1-1f7ebeb53f78", + "metadata": {}, + "outputs": [], + "source": [ + "# Put your API Keys here if you run this locally.\n", + "import os\n", + "os.environ[\"OPENAI_API_KEY\"] = \"\"\n", + "os.environ[\"ANTHROPIC_API_KEY\"] = \"\"\n", + "os.environ[\"FIREWORKS_API_KEY\"] = \"\"\n", + "os.environ[\"XAI_API_KEY\"] = \"\"\n", + "os.environ[\"GOOGLE_API_KEY\"] = \"\"\n", + "os.environ[\"AZURE_API_KEY\"] = \"\"" + ] + }, + { + "cell_type": "markdown", + "id": "8803ce06-67df-49d4-851e-2617cbf157be", + "metadata": {}, + "source": [ + "# Imports" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c0dbd424-0d89-4b2a-af13-aa98bc07f0a6", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import json\n", + "import time\n", + "import datetime\n", + "import pandas as pd\n", + "from tqdm import tqdm\n", + "\n", + "# Vendor SDKs\n", + "import openai\n", + "from openai import OpenAI, AzureOpenAI, RateLimitError, APIError, AuthenticationError\n", + "import anthropic\n", + "from google import genai\n", + "from google.genai import types\n", + "from google.api_core import exceptions as google_exceptions" + ] + }, + { + "cell_type": "markdown", + "id": "e3be8e22-dd79-4417-bf34-235900d5487a", + "metadata": {}, + "source": [ + "# Vendor/Model Configuration" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3c180681-cd7c-4d27-a429-06a149d8933c", + "metadata": {}, + "outputs": [], + "source": [ + "# -----------------------------\n", + "# Vendor/Model Configuration\n", + "# All prices per 1M tokens (USD) ----> UPDATE THE PRICES!!!!\n", + "# supplier = who made the model (for when using 3rd party APIs like Fireworks)\n", + "# -----------------------------\n", + "VENDORS = {\n", + " \"openai\": {\n", + " \"models\": {\n", + " # GPT-5 family\n", + " \"gpt-5.2\": {\"supplier\": \"openai\", \"price_in\": 1.75, \"price_out\": 14.00},\n", + " \"gpt-5\": {\"supplier\": \"openai\", \"price_in\": 1.25, \"price_out\": 10.00},\n", + " \"gpt-5-mini\": {\"supplier\": \"openai\", \"price_in\": 0.30, \"price_out\": 2.50},\n", + " \"gpt-5-nano\": {\"supplier\": \"openai\", \"price_in\": 0.10, \"price_out\": 0.40},\n", + " # GPT-4.1 family\n", + " \"gpt-4.1\": {\"supplier\": \"openai\", \"price_in\": 2.00, \"price_out\": 8.00},\n", + " # GPT-4o family\n", + " \"gpt-4o\": {\"supplier\": \"openai\", \"price_in\": 2.50, \"price_out\": 10.00},\n", + " }\n", + " },\n", + " \"azure\": {\n", + " \"models\": {\n", + " \"gpt-4.1\": {\"supplier\": \"openai\", \"price_in\": 2.00, \"price_out\": 8.00},\n", + " \"gpt-4o\": {\"supplier\": \"openai\", \"price_in\": 2.50, \"price_out\": 8.00},\n", + " },\n", + " \"endpoint\": \"https://azureaiapi.cloud.unc.edu\",\n", + " \"api_version\": \"2025-04-01-preview\",\n", + " },\n", + " \"anthropic\": {\n", + " \"models\": {\n", + " # Claude 4.5 family\n", + " \"claude-opus-4-5-20251101\": {\"supplier\": \"anthropic\", \"price_in\": 5.00, \"price_out\": 25.00},\n", + " \"claude-sonnet-4-5-20250929\": {\"supplier\": \"anthropic\", \"price_in\": 3.00, \"price_out\": 15.00},\n", + " \"claude-haiku-4-5-20251001\": {\"supplier\": \"anthropic\", \"price_in\": 1.00, \"price_out\": 5.00},\n", + " # Claude 4 family\n", + " \"claude-sonnet-4-20250514\": {\"supplier\": \"anthropic\", \"price_in\": 3.00, \"price_out\": 15.00},\n", + " }\n", + " },\n", + " \"google\": {\n", + " \"models\": {\n", + " # Gemini 3 - latest flagship - preview\n", + " \"gemini-3-pro-preview\": {\"supplier\": \"google\", \"price_in\": 2.00, \"price_out\": 12.00},\n", + " \"gemini-3-flash-preview\": {\"supplier\": \"google\", \"price_in\": 0.50, \"price_out\": 3.00},\n", + " # Gemini 2.5 - stable\n", + " \"gemini-2.5-pro\": {\"supplier\": \"google\", \"price_in\": 1.25, \"price_out\": 10.00},\n", + " \"gemini-2.5-flash\": {\"supplier\": \"google\", \"price_in\": 0.30, \"price_out\": 2.50},\n", + " }\n", + " },\n", + " \"xai\": {\n", + " \"models\": {\n", + " \"grok-4\": {\"supplier\": \"xai\", \"price_in\": 3.00, \"price_out\": 15.00},\n", + " \"grok-4-1-fast-reasoning\": {\"supplier\": \"xai\", \"price_in\": 0.20, \"price_out\": 0.50},\n", + " \"grok-4-1-fast-non-reasoning\": {\"supplier\": \"xai\", \"price_in\": 0.20, \"price_out\": 0.50}\n", + " }\n", + " },\n", + " \"fireworks\": {\n", + " \"models\": {\n", + " \"deepseek-v3p2\": {\"supplier\": \"deepseek\", \"price_in\": 0.56, \"price_out\": 1.68},\n", + " \"qwen3-vl-235b-a22b-instruct\": {\"supplier\": \"alibaba\", \"price_in\": 0.22, \"price_out\": 0.88},\n", + " \"deepseek-r1-0528\": {\"supplier\": \"deepseek\", \"price_in\": 1.35, \"price_out\": 5.40},\n", + " \"qwen3-vl-235b-a22b-thinking\": {\"supplier\": \"alibaba\", \"price_in\": 0.22, \"price_out\": 0.88},\n", + " \"kimi-k2p5\": {\"supplier\": \"moonshot\", \"price_in\": 1.20, \"price_out\": 1.20}\n", + " }\n", + " } \n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "3c799dc8-e11d-43f5-b48a-61ce699dcfec", + "metadata": {}, + "source": [ + "# System Prompt\n", + "- Be clear\n", + "- Be specific\n", + "- Try RTF (role task format)\n", + "- Succinct and exhaustive construct definitions\n", + "- Could give examples (few-shot), but may create noise or focus model too much on these cases\n", + "- Explain tie-breakers or dricky cases\n", + "- Define output format." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b46f6ca7-d791-48b2-838d-039fd696780d", + "metadata": {}, + "outputs": [], + "source": [ + "# -----------------------------\n", + "# System Prompt\n", + "# -----------------------------\n", + "SYSTEM_PROMPT = \"\"\"You are a business analyst classifying sentences from 10-K filings.\n", + "\n", + "Classify the sentence into one or more business functions: Marketing, Finance, Accounting, Operations, IT, HR (human resources)\n", + "\n", + "Definitions:\n", + "- Marketing: Customers, markets, demand, branding, advertising, promotion, pricing strategy, market research, segmentation, positioning, sales strategy, sales channels.\n", + "- Finance: Capital structure, funding, liquidity, treasury, investing, valuation, financial risk management (interest rates, FX, hedging), dividends, buybacks, M&A, financing activities.\n", + "- Accounting: Financial reporting, disclosures, GAAP/IFRS, accounting policies, accounting estimates, revenue recognition, impairments, reserves, depreciation, amortization, audits, internal controls over financial reporting (ICFR), tax accounting.\n", + "- Operations: Production, service delivery, supply chain, logistics, procurement, inventory management, manufacturing, capacity planning, facilities, quality control, safety, process efficiency, fulfillment, operational infrastructure, IT systems.\n", + "- IT: Information technology systems, software, hardware, cybersecurity, data management, cloud computing, digital infrastructure, technology platforms, system integration, IT support, technology investments, data analytics infrastructure.\n", + "- HR: Human resources, workforce, hiring, recruitment, talent acquisition, employee benefits, compensation, training, professional development, labor relations, employee retention, workplace safety, organizational culture.\n", + "\n", + "Rules:\n", + "1. Assign labels only when there is clear, direct evidence in the sentence.\n", + "2. Assign multiple labels if clearly relevant to more than one field.\n", + "3. Tie-breakers: Reporting/policies/controls/disclosures → Accounting; Funding/treasury/hedging/M&A → Finance.\n", + "4. Out of scope: General corporate governance, board matters, executive compensation, legal proceedings → return empty array.\n", + "5. Output: Return ONLY a JSON array with exact spelling: \"Marketing\", \"Finance\", \"Accounting\", \"Operations\", \"IT\". If none apply, return [].\n", + "6. DO NOT provide a reason or explanation for your labels.\"\"\"\n", + " \n", + "ALLOWED_LABELS = {\"Marketing\", \"Finance\", \"Accounting\", \"Operations\", \"IT\", \"HR\"}\n", + "LABEL_ORDER = [\"Marketing\", \"Finance\", \"Accounting\", \"Operations\", \"IT\", \"HR\"]" + ] + }, + { + "cell_type": "markdown", + "id": "09e63238-a066-4a80-95cd-1eacb59d19d5", + "metadata": {}, + "source": [ + "# Client Initialization & API Call Functions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2069211c-abff-4c85-8a5e-6de3539431dd", + "metadata": {}, + "outputs": [], + "source": [ + "# -----------------------------\n", + "# Client Initialization on a local PC (requires setting them at the beginning) or \n", + "# on Google CoLab (requires defining them in the secrets tab with key symbol)\n", + "# -----------------------------\n", + "def get_api_key(key_name: str) -> str:\n", + " \"\"\"Get API key from Colab secrets or environment variables.\"\"\"\n", + " try:\n", + " from google.colab import userdata\n", + " return userdata.get(key_name)\n", + " except (ImportError, ModuleNotFoundError):\n", + " # Not in Colab, use environment variables\n", + " return os.environ[key_name]\n", + "\n", + "\n", + "def init_client(vendor: str):\n", + " \"\"\"Initialize API client for vendor.\"\"\"\n", + " if vendor == \"openai\":\n", + " return OpenAI(api_key=get_api_key(\"OPENAI_API_KEY\"))\n", + " elif vendor == \"azure\":\n", + " return AzureOpenAI(\n", + " api_key=get_api_key(\"AZURE_API_KEY\"),\n", + " azure_endpoint=VENDORS[\"azure\"][\"endpoint\"],\n", + " api_version=VENDORS[\"azure\"][\"api_version\"],\n", + " ) \n", + " elif vendor == \"anthropic\":\n", + " return anthropic.Anthropic(api_key=get_api_key(\"ANTHROPIC_API_KEY\"))\n", + " elif vendor == \"google\":\n", + " return genai.Client(api_key=get_api_key(\"GOOGLE_API_KEY\"))\n", + " elif vendor == \"xai\":\n", + " return OpenAI(\n", + " api_key=get_api_key(\"XAI_API_KEY\"),\n", + " base_url=\"https://api.x.ai/v1\"\n", + " )\n", + " elif vendor == \"fireworks\":\n", + " return OpenAI(\n", + " api_key=get_api_key(\"FIREWORKS_API_KEY\"),\n", + " base_url=\"https://api.fireworks.ai/inference/v1\"\n", + " )\n", + " else:\n", + " raise ValueError(f\"Unknown vendor: {vendor}\")\n", + "\n", + "# -----------------------------\n", + "# API Call Functions\n", + "# -----------------------------\n", + "def call_openai(client, sentence: str, model: str, system_prompt: str,\n", + " max_tokens: int = 64, reasoning_effort: str = None) -> dict:\n", + " \"\"\"\n", + " Call OpenAI Responses API.\n", + " \n", + " Token billing:\n", + " - input_tokens: billed at input rate\n", + " - output_tokens: includes reasoning_tokens, all billed at output rate\n", + " - reasoning_tokens: subset of output_tokens (internal thinking)\n", + " \n", + " Note: For reasoning models, max_output_tokens must accommodate BOTH\n", + " reasoning tokens AND response tokens. We scale up accordingly.\n", + " \"\"\"\n", + " # For reasoning models, we need more output tokens to fit both reasoning + response\n", + " if reasoning_effort:\n", + " # Reasoning needs room: base response tokens + reasoning overhead\n", + " # low ~500, medium ~1000, high ~2000+ reasoning tokens typical\n", + " reasoning_overhead = {\"low\": 512, \"medium\": 1024, \"high\": 2048}.get(reasoning_effort, 512)\n", + " effective_max_tokens = max_tokens + reasoning_overhead\n", + " else:\n", + " effective_max_tokens = max_tokens\n", + " \n", + " params = {\n", + " \"model\": model,\n", + " \"instructions\": system_prompt,\n", + " \"input\": sentence,\n", + " \"max_output_tokens\": effective_max_tokens,\n", + " }\n", + " \n", + " if reasoning_effort:\n", + " params[\"reasoning\"] = {\"effort\": reasoning_effort}\n", + " else:\n", + " params[\"temperature\"] = 0\n", + " \n", + " resp = client.responses.create(**params)\n", + " \n", + " # Extract text - output_text may be empty for some response types\n", + " text = \"\"\n", + " if resp.output_text:\n", + " text = resp.output_text.strip()\n", + " else:\n", + " # Fallback: extract from output items\n", + " for item in resp.output:\n", + " if getattr(item, 'type', None) == 'message':\n", + " for block in getattr(item, 'content', []):\n", + " if getattr(block, 'type', None) == 'text':\n", + " text += getattr(block, 'text', '')\n", + " text = text.strip()\n", + " \n", + " # Extract token breakdown\n", + " input_tokens = resp.usage.input_tokens\n", + " output_tokens = resp.usage.output_tokens\n", + " \n", + " # Reasoning tokens are part of output_tokens (not additional)\n", + " reasoning_tokens = 0\n", + " if hasattr(resp.usage, 'output_tokens_details') and resp.usage.output_tokens_details:\n", + " reasoning_tokens = getattr(resp.usage.output_tokens_details, 'reasoning_tokens', 0) or 0\n", + " \n", + " return {\n", + " \"text\": text,\n", + " \"input_tokens\": input_tokens,\n", + " \"output_tokens\": output_tokens, # total output (includes reasoning)\n", + " \"reasoning_tokens\": reasoning_tokens, # internal thinking (subset of output)\n", + " \"response_tokens\": output_tokens - reasoning_tokens, # visible response\n", + " \"raw_response\": resp.model_dump() if hasattr(resp, 'model_dump') else str(resp),\n", + " }\n", + "\n", + "def call_azure(client, sentence: str, model: str, system_prompt: str,\n", + " max_tokens: int = 64) -> dict:\n", + " \"\"\"\n", + " Call Azure OpenAI API (chat completions).\n", + " \n", + " Azure uses the standard chat completions endpoint, not Responses API.\n", + " \"\"\"\n", + " params = {\n", + " \"model\": model,\n", + " \"messages\": [\n", + " {\"role\": \"system\", \"content\": system_prompt},\n", + " {\"role\": \"user\", \"content\": sentence}\n", + " ],\n", + " \"max_tokens\": max_tokens,\n", + " \"temperature\": 0, # Set temp to 0 to be deterministic\n", + " }\n", + " \n", + " resp = client.chat.completions.create(**params)\n", + " \n", + " text = (resp.choices[0].message.content or \"\").strip()\n", + " \n", + " return {\n", + " \"text\": text,\n", + " \"input_tokens\": resp.usage.prompt_tokens,\n", + " \"output_tokens\": resp.usage.completion_tokens,\n", + " \"reasoning_tokens\": 0,\n", + " \"response_tokens\": resp.usage.completion_tokens,\n", + " \"raw_response\": resp.model_dump() if hasattr(resp, 'model_dump') else str(resp),\n", + " }\n", + " \n", + "def call_anthropic(client, sentence: str, model: str, system_prompt: str,\n", + " max_tokens: int = 64, thinking_budget: int = None) -> dict:\n", + " \"\"\"\n", + " Call Anthropic Messages API.\n", + " \n", + " Token billing:\n", + " - input_tokens: billed at input rate\n", + " - output_tokens: includes thinking tokens, all billed at output rate\n", + " - NOTE: Anthropic doesn't provide separate thinking token count in usage.\n", + " The output_tokens is what's billed (includes full thinking, not summary).\n", + " \"\"\"\n", + " params = {\n", + " \"model\": model,\n", + " \"system\": system_prompt,\n", + " \"messages\": [{\"role\": \"user\", \"content\": sentence}],\n", + " }\n", + " \n", + " if thinking_budget:\n", + " thinking_budget = max(1024, thinking_budget)\n", + " params[\"thinking\"] = {\"type\": \"enabled\", \"budget_tokens\": thinking_budget}\n", + " params[\"max_tokens\"] = thinking_budget + max_tokens\n", + " else:\n", + " params[\"temperature\"] = 0\n", + " params[\"max_tokens\"] = max_tokens\n", + " \n", + " resp = client.messages.create(**params)\n", + " \n", + " # Extract text (skip thinking blocks - they're summarized in Claude 4)\n", + " text = \"\".join(b.text for b in resp.content if b.type == \"text\").strip()\n", + " \n", + " # output_tokens includes thinking tokens (billed amount)\n", + " # Anthropic doesn't provide breakdown like OpenAI does\n", + " output_tokens = resp.usage.output_tokens\n", + " \n", + " return {\n", + " \"text\": text,\n", + " \"input_tokens\": resp.usage.input_tokens,\n", + " \"output_tokens\": output_tokens, # total billed (includes thinking)\n", + " \"reasoning_tokens\": 0, # Anthropic doesn't provide breakdown\n", + " \"response_tokens\": output_tokens, # Can't separate, use total\n", + " \"raw_response\": resp.model_dump() if hasattr(resp, 'model_dump') else str(resp),\n", + " }\n", + "\n", + "def call_google(client, sentence: str, model: str, system_prompt: str,\n", + " max_tokens: int = 64, thinking_level: str = None) -> dict:\n", + " \"\"\"\n", + " Call Google Gemini API.\n", + " \n", + " Gemini 3 Pro: thinking_level \"low\", \"high\" (default)\n", + " Gemini 3 Flash: thinking_level \"minimal\", \"low\", \"medium\", \"high\" (default)\n", + " \n", + " Note: Even \"low\" still uses thinking tokens! Only Flash \"minimal\" truly minimizes.\n", + " \n", + " Token billing:\n", + " - output tokens include thinking tokens (no separate breakdown)\n", + " \"\"\"\n", + " from google.genai import types\n", + " \n", + " # Build config\n", + " config_params = {}\n", + " \n", + " # Determine token allocation based on thinking level: Even \"low\" uses thinking tokens (~50-200), so we need buffer\n", + " if thinking_level == \"minimal\":\n", + " # Only Flash supports minimal - truly minimal thinking\n", + " config_params[\"max_output_tokens\"] = max_tokens + 128\n", + " elif thinking_level == \"low\":\n", + " # Low still uses thinking tokens, need buffer\n", + " config_params[\"max_output_tokens\"] = max_tokens + 512\n", + " elif thinking_level == \"medium\":\n", + " config_params[\"max_output_tokens\"] = max_tokens + 2048\n", + " else:\n", + " # high or default (None) - full thinking\n", + " config_params[\"max_output_tokens\"] = max_tokens + 4096\n", + " \n", + " # Set thinking level if specified\n", + " if thinking_level:\n", + " config_params[\"thinking_config\"] = types.ThinkingConfig(\n", + " thinking_level=thinking_level\n", + " )\n", + " \n", + " # Gemini 3 recommends temperature=1.0 (default), don't override\n", + " \n", + " config = types.GenerateContentConfig(**config_params)\n", + " \n", + " # Combine system prompt and sentence\n", + " full_prompt = f\"{system_prompt}\\n{sentence}\"\n", + " \n", + " resp = client.models.generate_content(\n", + " model=model,\n", + " contents=full_prompt,\n", + " config=config,\n", + " )\n", + " \n", + " # Extract text - resp.text may be empty, need to check parts\n", + " text = \"\"\n", + " if resp.text:\n", + " text = resp.text.strip()\n", + " elif resp.candidates and resp.candidates[0].content and resp.candidates[0].content.parts:\n", + " # Extract text from parts, skipping thinking parts\n", + " for part in resp.candidates[0].content.parts:\n", + " # Skip thinking parts (they have 'thought' attribute set to True)\n", + " if hasattr(part, 'thought') and part.thought:\n", + " continue\n", + " if hasattr(part, 'text') and part.text:\n", + " text += part.text\n", + " text = text.strip()\n", + " \n", + " # Token usage\n", + " usage = resp.usage_metadata\n", + " input_tokens = usage.prompt_token_count\n", + " output_tokens = usage.candidates_token_count\n", + " # - candidates_token_count = actual response tokens\n", + " # - thoughts_token_count = thinking/reasoning tokens (billed as output)\n", + " thoughts_tokens = getattr(resp.usage_metadata, 'thoughts_token_count', 0) or 0\n", + " candidates_tokens = resp.usage_metadata.candidates_token_count or 0\n", + "\n", + " return {\n", + " \"text\": text,\n", + " \"input_tokens\": resp.usage_metadata.prompt_token_count,\n", + " \"output_tokens\": candidates_tokens + thoughts_tokens, # Total billed output\n", + " \"reasoning_tokens\": thoughts_tokens,\n", + " \"response_tokens\": candidates_tokens,\n", + " \"raw_response\": str(resp),\n", + " }\n", + " \n", + "def call_fireworks(client, sentence: str, model: str, system_prompt: str,\n", + " max_tokens: int = 64, reasoning_effort: str = None) -> dict:\n", + " \"\"\"\n", + " Call Fireworks API using OpenAI-compatible endpoint.\n", + " \n", + " Thinking models (*-thinking, r1, kimi) output reasoning in content,\n", + " so we allocate extra tokens and use recommended temperature.\n", + " \"\"\"\n", + " full_model_id = f\"accounts/fireworks/models/{model}\"\n", + " \n", + " # Thinking models need more tokens (thinking appears in content)\n", + " is_thinking_model = \"thinking\" in model or \"r1\" in model or model == \"kimi-k2p5\"\n", + " \n", + " if is_thinking_model:\n", + " effective_max_tokens = max_tokens + 4096\n", + " temperature = 0.6 # Recommended for thinking\n", + " else:\n", + " effective_max_tokens = max_tokens\n", + " temperature = 0 # Deterministic for chat\n", + " \n", + " params = {\n", + " \"model\": full_model_id,\n", + " \"messages\": [\n", + " {\"role\": \"system\", \"content\": system_prompt},\n", + " {\"role\": \"user\", \"content\": sentence}\n", + " ],\n", + " \"max_tokens\": effective_max_tokens,\n", + " \"temperature\": temperature,\n", + " }\n", + "\n", + " resp = client.chat.completions.create(**params)\n", + " \n", + " text = (resp.choices[0].message.content or \"\").strip()\n", + " \n", + " return {\n", + " \"text\": text,\n", + " \"input_tokens\": resp.usage.prompt_tokens,\n", + " \"output_tokens\": resp.usage.completion_tokens,\n", + " \"reasoning_tokens\": 0,\n", + " \"response_tokens\": resp.usage.completion_tokens,\n", + " \"raw_response\": resp.model_dump() if hasattr(resp, 'model_dump') else str(resp),\n", + " }\n", + "\n", + "def call_xai(client, sentence: str, model: str, system_prompt: str,\n", + " max_tokens: int = 64) -> dict:\n", + " \"\"\"\n", + " Call xAI API using OpenAI-compatible endpoint.\n", + " \n", + " grok-4 and *-reasoning models are always reasoning.\n", + " *-non-reasoning models are chat mode.\n", + " \n", + " Token billing:\n", + " - completion_tokens: visible response only\n", + " - reasoning_tokens: in completion_tokens_details, billed separately\n", + " - total output billed = completion_tokens + reasoning_tokens\n", + " \"\"\"\n", + " is_reasoning = \"non-reasoning\" not in model\n", + " \n", + " params = {\n", + " \"model\": model,\n", + " \"messages\": [\n", + " {\"role\": \"system\", \"content\": system_prompt},\n", + " {\"role\": \"user\", \"content\": sentence}\n", + " ],\n", + " \"max_tokens\": max_tokens + 4096 if is_reasoning else max_tokens,\n", + " \"temperature\": 1.0 if is_reasoning else 0,\n", + " }\n", + " \n", + " resp = client.chat.completions.create(**params)\n", + " text = (resp.choices[0].message.content or \"\").strip()\n", + " \n", + " # Extract reasoning tokens from completion_tokens_details\n", + " reasoning_tokens = 0\n", + " if hasattr(resp.usage, 'completion_tokens_details') and resp.usage.completion_tokens_details:\n", + " reasoning_tokens = getattr(resp.usage.completion_tokens_details, 'reasoning_tokens', 0) or 0\n", + " \n", + " # completion_tokens is visible response, reasoning_tokens is separate\n", + " # Both are billed at output rate\n", + " completion_tokens = resp.usage.completion_tokens\n", + " total_output = completion_tokens + reasoning_tokens\n", + " \n", + " return {\n", + " \"text\": text,\n", + " \"input_tokens\": resp.usage.prompt_tokens,\n", + " \"output_tokens\": total_output, # Total billed at output rate\n", + " \"reasoning_tokens\": reasoning_tokens,\n", + " \"response_tokens\": completion_tokens, # Visible response only\n", + " \"raw_response\": resp.model_dump() if hasattr(resp, 'model_dump') else str(resp),\n", + " }" + ] + }, + { + "cell_type": "markdown", + "id": "35a1a8ba-0a5d-4d1d-a10c-5404ca9a2919", + "metadata": {}, + "source": [ + "# Parsing & Cost" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ae5e0d1f-be15-4cd1-84d7-3a05743e7c0a", + "metadata": {}, + "outputs": [], + "source": [ + "# -----------------------------\n", + "# Parsing & Cost\n", + "# -----------------------------\n", + "\n", + "def parse_labels(text: str) -> list:\n", + " \"\"\"Parse JSON array, validate labels. Handles markdown code fences and extra text.\"\"\"\n", + " text = text.strip()\n", + "\n", + " # Strip thinking tags for models that use them (e.g., DeepSeek R1, QwQ)\n", + " if \"\" in text:\n", + " text = text.split(\"\")[-1].strip()\n", + " elif \"\" in text and \"\" not in text:\n", + " # Incomplete thinking block - try to find JSON after it\n", + " pass\n", + " \n", + " # Strip markdown code fences if present\n", + " if \"```\" in text:\n", + " lines = text.split(\"\\n\")\n", + " lines = [l for l in lines if not l.strip().startswith(\"```\")]\n", + " text = \"\\n\".join(lines).strip()\n", + " \n", + " # Find the LAST JSON array (thinking models put reasoning before answer)\n", + " # Search backwards for the final [...] pattern\n", + " start = text.rfind(\"[\")\n", + " if start == -1:\n", + " raise ValueError(\"No JSON array found\")\n", + " \n", + " # Find matching closing bracket\n", + " depth = 0\n", + " end = start\n", + " for i, char in enumerate(text[start:], start):\n", + " if char == \"[\":\n", + " depth += 1\n", + " elif char == \"]\":\n", + " depth -= 1\n", + " if depth == 0:\n", + " end = i + 1\n", + " break\n", + " \n", + " json_str = text[start:end]\n", + " data = json.loads(json_str)\n", + " \n", + " if not isinstance(data, list):\n", + " raise ValueError(\"Not a JSON array\")\n", + " invalid = [x for x in data if x not in ALLOWED_LABELS]\n", + " if invalid:\n", + " raise ValueError(f\"Invalid labels: {invalid}\")\n", + " return [label for label in LABEL_ORDER if label in set(data)]\n", + "\n", + "\n", + "def compute_cost(model_info: dict, input_tokens: int, output_tokens: int) -> float:\n", + " \"\"\"\n", + " Compute cost in USD.\n", + " Note: output_tokens includes reasoning/thinking tokens, all billed at output rate.\n", + " \"\"\"\n", + " return (input_tokens / 1e6) * model_info[\"price_in\"] + (output_tokens / 1e6) * model_info[\"price_out\"]\n", + "\n", + "\n", + "def get_mode_string(vendor: str, model: str = None, reasoning_effort: str = None, \n", + " thinking_budget: int = None, thinking_level: str = None) -> str:\n", + " \"\"\"Get mode string for filenames.\"\"\"\n", + " if vendor == \"openai\":\n", + " return f\"reasoning-{reasoning_effort}\" if reasoning_effort else \"chat\"\n", + " elif vendor == \"azure\":\n", + " return \"chat\"\n", + " elif vendor == \"anthropic\":\n", + " return f\"thinking-{thinking_budget}\" if thinking_budget else \"chat\"\n", + " elif vendor == \"google\":\n", + " if thinking_level == \"minimal\":\n", + " return \"chat\" # Only Flash supports minimal\n", + " elif thinking_level == \"low\":\n", + " return \"thinking-low\" # Still uses some thinking\n", + " elif thinking_level:\n", + " return f\"thinking-{thinking_level}\"\n", + " return \"thinking\" # default for Gemini 3 \n", + " elif vendor == \"fireworks\":\n", + " if reasoning_effort:\n", + " return f\"reasoning-{reasoning_effort}\"\n", + " # Auto-detected thinking models\n", + " if model and (\"thinking\" in model or \"r1\" in model or model == \"kimi-k2p5\"):\n", + " return \"thinking\"\n", + " elif vendor == \"xai\":\n", + " return \"chat\" if model and \"non-reasoning\" in model else \"reasoning\"\n", + " return \"chat\"" + ] + }, + { + "cell_type": "markdown", + "id": "9b028d13-8bd2-47e7-9f5d-f8589136d6d2", + "metadata": {}, + "source": [ + "# Classify Sentence and Retry on Error" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3cf0a31f-7403-4861-b8ab-69e6fdd65434", + "metadata": {}, + "outputs": [], + "source": [ + "# -----------------------------\n", + "# Single Sentence Classification with Retry\n", + "# -----------------------------\n", + "def classify_sentence(client, sentence: str, vendor: str, model: str, model_info: dict,\n", + " system_prompt: str, max_tokens: int = 64, max_retries: int = 5,\n", + " reasoning_effort: str = None, thinking_budget: int = None,\n", + " thinking_level: str = None) -> dict:\n", + " \"\"\"\n", + " Classify a single sentence with retry logic.\n", + " \n", + " Retry wait times: 3s, 3s, 6s, 12s, 30s\n", + " Rate limit errors: 60s\n", + " \"\"\"\n", + " # Import vendor-specific exceptions only when needed\n", + " if vendor == \"openai\":\n", + " rate_limit_errors = (RateLimitError,)\n", + " api_errors = (APIError,)\n", + " auth_errors = (AuthenticationError,)\n", + " elif vendor == \"azure\":\n", + " rate_limit_errors = (RateLimitError,)\n", + " api_errors = (APIError,)\n", + " auth_errors = (AuthenticationError,)\n", + " elif vendor == \"anthropic\":\n", + " import anthropic\n", + " rate_limit_errors = (anthropic.RateLimitError,)\n", + " api_errors = (anthropic.APIError,)\n", + " auth_errors = (anthropic.AuthenticationError,)\n", + " elif vendor == \"fireworks\":\n", + " import openai\n", + " rate_limit_errors = (openai.RateLimitError,)\n", + " api_errors = (openai.APIError,)\n", + " auth_errors = (openai.AuthenticationError,)\n", + " elif vendor == \"xai\":\n", + " import openai\n", + " rate_limit_errors = (openai.RateLimitError,)\n", + " api_errors = (openai.APIError,)\n", + " auth_errors = (openai.AuthenticationError,)\n", + " elif vendor == \"google\":\n", + " from google.api_core import exceptions as google_exceptions\n", + " rate_limit_errors = (google_exceptions.ResourceExhausted,)\n", + " api_errors = (google_exceptions.GoogleAPIError,)\n", + " auth_errors = (google_exceptions.Unauthenticated, google_exceptions.PermissionDenied)\n", + " else:\n", + " rate_limit_errors = ()\n", + " api_errors = ()\n", + " auth_errors = ()\n", + " \n", + " last_error = None\n", + " error_details = None\n", + " wait_times = {1: 3, 2: 3, 3: 6, 4: 12, 5: 30}\n", + " \n", + " for attempt in range(1, max_retries + 1):\n", + " try:\n", + " t0 = time.perf_counter()\n", + " \n", + " if vendor == \"openai\":\n", + " result = call_openai(client, sentence, model, system_prompt, \n", + " max_tokens, reasoning_effort)\n", + " elif vendor == \"azure\": \n", + " result = call_azure(client, sentence, model, system_prompt,\n", + " max_tokens)\n", + " elif vendor == \"anthropic\":\n", + " result = call_anthropic(client, sentence, model, system_prompt,\n", + " max_tokens, thinking_budget)\n", + " elif vendor == \"fireworks\":\n", + " result = call_fireworks(client, sentence, model, system_prompt,\n", + " max_tokens, reasoning_effort)\n", + " elif vendor == \"xai\":\n", + " result = call_xai(client, sentence, model, system_prompt,\n", + " max_tokens)\n", + " elif vendor == \"google\":\n", + " result = call_google(client, sentence, model, system_prompt,\n", + " max_tokens, thinking_level)\n", + " else:\n", + " raise ValueError(f\"Unknown vendor: {vendor}\")\n", + " \n", + " latency = time.perf_counter() - t0\n", + " labels = parse_labels(result[\"text\"])\n", + " \n", + " return {\n", + " \"labels\": labels,\n", + " \"response_text\": result[\"text\"],\n", + " \"input_tokens\": result[\"input_tokens\"],\n", + " \"output_tokens\": result[\"output_tokens\"],\n", + " \"internal_tokens\": result.get(\"reasoning_tokens\") or result.get(\"thinking_tokens\", 0),\n", + " \"response_tokens\": result.get(\"response_tokens\", result[\"output_tokens\"]),\n", + " \"cost_usd\": compute_cost(model_info, result[\"input_tokens\"], result[\"output_tokens\"]),\n", + " \"latency_sec\": latency,\n", + " \"attempts\": attempt,\n", + " \"error\": None,\n", + " \"raw_response\": result.get(\"raw_response\"),\n", + " }\n", + " \n", + " except auth_errors as e:\n", + " # Don't retry auth errors - they won't resolve\n", + " error_details = {\"type\": \"AuthenticationError\", \"attempt\": attempt, \"message\": str(e)}\n", + " print(f\" Authentication error (not retrying): {e}\")\n", + " return {\n", + " \"labels\": None,\n", + " \"response_text\": None,\n", + " \"input_tokens\": 0,\n", + " \"output_tokens\": 0,\n", + " \"internal_tokens\": 0,\n", + " \"response_tokens\": 0,\n", + " \"cost_usd\": 0.0,\n", + " \"latency_sec\": None,\n", + " \"attempts\": attempt,\n", + " \"error\": error_details,\n", + " \"raw_response\": None,\n", + " }\n", + " \n", + " except rate_limit_errors as e:\n", + " last_error = f\"RateLimitError: {e}\"\n", + " error_details = {\"type\": \"RateLimitError\", \"attempt\": attempt}\n", + " print(f\" Rate limit hit, waiting 60s...\")\n", + " time.sleep(60)\n", + " \n", + " except api_errors as e:\n", + " last_error = f\"APIError: {e}\"\n", + " error_details = {\"type\": \"APIError\", \"attempt\": attempt, \"message\": str(e)}\n", + " wait = wait_times.get(attempt, 3)\n", + " print(f\" API error (attempt {attempt}), waiting {wait}s...\")\n", + " time.sleep(wait)\n", + " \n", + " except (json.JSONDecodeError, ValueError) as e:\n", + " last_error = f\"ParseError: {e}\"\n", + " response_preview = result.get(\"text\", \"\")[:100] if 'result' in dir() and result else \"\"\n", + " error_details = {\"type\": \"ParseError\", \"attempt\": attempt, \"message\": str(e), \"response_preview\": response_preview}\n", + " wait = wait_times.get(attempt, 3)\n", + " print(f\" Parse error (attempt {attempt}): got '{response_preview}', waiting {wait}s...\")\n", + " time.sleep(wait)\n", + " \n", + " except Exception as e:\n", + " last_error = f\"{type(e).__name__}: {e}\"\n", + " error_details = {\"type\": type(e).__name__, \"attempt\": attempt, \"message\": str(e)}\n", + " print(f\" Error (attempt {attempt}): {last_error}\")\n", + " if attempt < max_retries:\n", + " time.sleep(wait_times.get(attempt, 3))\n", + " \n", + " return {\n", + " \"labels\": None,\n", + " \"response_text\": None,\n", + " \"input_tokens\": 0,\n", + " \"output_tokens\": 0,\n", + " \"internal_tokens\": 0,\n", + " \"response_tokens\": 0,\n", + " \"cost_usd\": 0.0,\n", + " \"latency_sec\": None,\n", + " \"attempts\": max_retries,\n", + " \"error\": error_details,\n", + " \"raw_response\": None,\n", + " }" + ] + }, + { + "cell_type": "markdown", + "id": "b7d9948c-1278-42bb-84f9-311f5a9bcaac", + "metadata": {}, + "source": [ + "# DataFrame Processing with Checkpointing" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5799882a-e057-4277-9583-94fbc1872481", + "metadata": {}, + "outputs": [], + "source": [ + "# -----------------------------\n", + "# DataFrame Processing with Checkpointing\n", + "# -----------------------------\n", + "def classify_dataframe(\n", + " df: pd.DataFrame,\n", + " sentence_col: str,\n", + " vendor: str,\n", + " model: str,\n", + " system_prompt: str = SYSTEM_PROMPT,\n", + " max_tokens: int = 64,\n", + " output_dir: str = \"./output\", ## default outout folder if none is passed\n", + " checkpoint_dir: str = \"./checkpoints\", ## default checkpoint folder if none is passed\n", + " save_interval: int = 100, ##### How often you want to save\n", + " run: int = 1,\n", + " reasoning_effort: str = None,\n", + " thinking_budget: int = None,\n", + " thinking_level: str = None,\n", + " max_consecutive_errors: int = 10,\n", + ") -> pd.DataFrame:\n", + " \"\"\"\n", + " Classify all sentences with checkpointing.\n", + " \n", + " Directory structure:\n", + " - checkpoint_dir/{vendor}_{model}_{mode}_run{run}.pkl (interim saves)\n", + " - output_dir/Run{run}/{vendor}_{model}_{mode}_run{run}.pkl (final output)\n", + " - output_dir/Run{run}/{vendor}_{model}_{mode}_run{run}.log.json (run log)\n", + " \"\"\"\n", + " # Validate\n", + " if sentence_col not in df.columns:\n", + " raise ValueError(f\"Column '{sentence_col}' not found\")\n", + " if vendor not in VENDORS:\n", + " raise ValueError(f\"Unknown vendor: {vendor}\")\n", + " if model not in VENDORS[vendor][\"models\"]:\n", + " raise ValueError(f\"Unknown model '{model}' for vendor '{vendor}'\")\n", + " \n", + " model_info = VENDORS[vendor][\"models\"][model]\n", + " mode_str = get_mode_string(vendor, model, reasoning_effort, thinking_budget, thinking_level)\n", + " # Derive dataset tag from output_dir (e.g., \"./output/holdout\" → \"holdout\")\n", + " dataset_tag = os.path.basename(os.path.normpath(output_dir)).lower()\n", + " base_name = f\"{dataset_tag}_{vendor}_{model}_{mode_str}_run{run}\"\n", + " \n", + " # Create directories\n", + " os.makedirs(checkpoint_dir, exist_ok=True)\n", + " run_dir = f\"{output_dir}/Run{run}\"\n", + " os.makedirs(run_dir, exist_ok=True)\n", + " \n", + " checkpoint_path = f\"{checkpoint_dir}/{base_name}.pkl\"\n", + " \n", + " print(f\"Checkpoint dir: {checkpoint_dir}\")\n", + " print(f\"Output dir: {run_dir}\")\n", + " print(f\"Checkpoint file: {checkpoint_path}\")\n", + " \n", + " # Load existing checkpoint\n", + " results = []\n", + " processed_ids = set()\n", + " \n", + " if os.path.exists(checkpoint_path):\n", + " try:\n", + " checkpoint_df = pd.read_pickle(checkpoint_path)\n", + " successful = checkpoint_df[checkpoint_df['error'].isna()]\n", + " results = successful.to_dict('records')\n", + " processed_ids = set(successful['id'].values) if 'id' in successful.columns else set()\n", + " failed_count = len(checkpoint_df) - len(successful)\n", + " print(f\"Resumed: {len(results)} processed, {failed_count} errors to retry\")\n", + " except Exception as e:\n", + " print(f\"Could not load checkpoint: {e}\")\n", + " \n", + " # Initialize client\n", + " client = init_client(vendor)\n", + " \n", + " # Track errors\n", + " consecutive_errors = 0\n", + " start_time = datetime.datetime.now()\n", + " \n", + " # Process\n", + " for idx, row in tqdm(df.iterrows(), total=len(df), desc=f\"Run {run}: {model} ({mode_str})\"):\n", + " row_id = row.get('id', idx)\n", + " \n", + " if row_id in processed_ids:\n", + " continue\n", + " \n", + " sentence = str(row[sentence_col])\n", + " \n", + " result = classify_sentence(\n", + " client, sentence, vendor, model, model_info, system_prompt, max_tokens,\n", + " reasoning_effort=reasoning_effort, thinking_budget=thinking_budget,\n", + " thinking_level=thinking_level\n", + " )\n", + " \n", + " ordered_result = {\n", + " 'id': row_id,\n", + " 'sentence': sentence,\n", + " **result\n", + " }\n", + " results.append(ordered_result)\n", + " \n", + " if result['error']:\n", + " consecutive_errors += 1\n", + " if consecutive_errors >= max_consecutive_errors:\n", + " print(f\"\\nStopping: {max_consecutive_errors} consecutive errors\")\n", + " break\n", + " else:\n", + " consecutive_errors = 0\n", + " processed_ids.add(row_id)\n", + " \n", + " # Checkpoint save\n", + " if len(results) % save_interval == 0:\n", + " pd.DataFrame(results).to_pickle(checkpoint_path)\n", + " print(f\"\\nCheckpoint saved: {len(results)} processed\")\n", + " \n", + " # Final results\n", + " results_df = pd.DataFrame(results)\n", + " end_time = datetime.datetime.now()\n", + " \n", + " # Save to checkpoint (for resume if needed)\n", + " results_df.to_pickle(checkpoint_path)\n", + " \n", + " # Save to run directory\n", + " results_df.to_pickle(f\"{run_dir}/{base_name}.pkl\")\n", + " results_df.to_csv(f\"{run_dir}/{base_name}.csv\", index=False)\n", + " \n", + " # Create log file\n", + " error_count = int(results_df['error'].notna().sum())\n", + " success_count = len(results_df) - error_count\n", + " \n", + " log = {\n", + " \"run\": run,\n", + " \"vendor\": vendor,\n", + " \"model\": model,\n", + " \"supplier\": model_info[\"supplier\"],\n", + " \"mode\": mode_str,\n", + " \"reasoning_effort\": reasoning_effort,\n", + " \"thinking_budget\": thinking_budget,\n", + " \"start_time\": str(start_time),\n", + " \"end_time\": str(end_time),\n", + " \"duration_sec\": (end_time - start_time).total_seconds(),\n", + " \"total_sentences\": len(df),\n", + " \"processed_sentences\": len(results_df),\n", + " \"successful\": success_count,\n", + " \"errors\": error_count,\n", + " \"tokens\": {\n", + " \"input\": int(results_df['input_tokens'].sum()),\n", + " \"output\": int(results_df['output_tokens'].sum()),\n", + " \"internal\": int(results_df['internal_tokens'].sum()),\n", + " \"response\": int(results_df['response_tokens'].sum()),\n", + " },\n", + " \"cost_usd\": float(results_df['cost_usd'].sum()),\n", + " \"pricing\": {\n", + " \"input_per_1m\": model_info[\"price_in\"],\n", + " \"output_per_1m\": model_info[\"price_out\"],\n", + " },\n", + " \"files\": {\n", + " \"checkpoint\": checkpoint_path,\n", + " \"output_pkl\": f\"{run_dir}/{base_name}.pkl\",\n", + " \"output_csv\": f\"{run_dir}/{base_name}.csv\",\n", + " }\n", + " }\n", + " \n", + " log_path = f\"{run_dir}/{base_name}.log.json\"\n", + " with open(log_path, 'w') as f:\n", + " json.dump(log, f, indent=2)\n", + " \n", + " print(f\"\\nRun {run} complete:\")\n", + " print(f\" Sentences: {success_count}/{len(results_df)}\")\n", + " print(f\" Tokens - Input: {log['tokens']['input']:,}, Output: {log['tokens']['output']:,} (Internal: {log['tokens']['internal']:,})\")\n", + " print(f\" Cost: ${log['cost_usd']:.4f}\")\n", + " print(f\" Log: {log_path}\")\n", + " \n", + " return results_df" + ] + }, + { + "cell_type": "markdown", + "id": "2e6d17c0-135a-42c6-8815-db44f8445894", + "metadata": {}, + "source": [ + "# Multi-Run Processing" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fba35e3e-e3ab-4f23-9b46-749ccecbe66d", + "metadata": {}, + "outputs": [], + "source": [ + "# -----------------------------\n", + "# Multi-Run Processing\n", + "# -----------------------------\n", + "def run_classification(\n", + " df: pd.DataFrame,\n", + " sentence_col: str,\n", + " vendor: str,\n", + " model: str,\n", + " runs: list = [1, 2, 3], # default if nothing passed\n", + " output_dir: str = \"./output\", # default if nothing passed\n", + " checkpoint_dir: str = \"./checkpoints\", # default if nothing passed\n", + " system_prompt: str = SYSTEM_PROMPT,\n", + " max_tokens: int = 64,\n", + " save_interval: int = 100,\n", + " reasoning_effort: str = None,\n", + " thinking_budget: int = None,\n", + " thinking_level: str = None,\n", + ") -> dict:\n", + " \"\"\"\n", + " Run classification multiple times.\n", + " \n", + " Directory structure:\n", + " output_dir/\n", + " Run1/\n", + " {vendor}_{model}_{mode}_run1.pkl\n", + " {vendor}_{model}_{mode}_run1.csv\n", + " {vendor}_{model}_{mode}_run1.log.json\n", + " Run2/\n", + " ...\n", + " checkpoint_dir/\n", + " {vendor}_{model}_{mode}_run1.pkl\n", + " ...\n", + " \n", + " Returns dict of {run: results_df}\n", + " \"\"\"\n", + " model_info = VENDORS[vendor][\"models\"][model]\n", + " mode_str = get_mode_string(vendor, model, reasoning_effort, thinking_budget, thinking_level)\n", + " job_start_time = time.perf_counter()\n", + " \n", + " print(f\"\\n{'='*60}\")\n", + " print(f\"CLASSIFICATION JOB\")\n", + " print(f\"{'='*60}\")\n", + " print(f\"Vendor: {vendor}\")\n", + " print(f\"Model: {model}\")\n", + " print(f\"Supplier: {model_info['supplier']}\")\n", + " print(f\"Mode: {mode_str}\")\n", + " print(f\"Pricing: ${model_info['price_in']}/M in, ${model_info['price_out']}/M out\")\n", + " print(f\"Runs: {runs}\")\n", + " print(f\"Sentences: {len(df)}\")\n", + " print(f\"Output dir: {output_dir}\")\n", + " print(f\"Checkpoint dir: {checkpoint_dir}\")\n", + " print(f\"{'='*60}\\n\")\n", + " \n", + " all_results = {}\n", + " \n", + " for run in runs:\n", + " print(f\"\\n{'='*40}\")\n", + " print(f\"RUN {run}\")\n", + " print(f\"{'='*40}\")\n", + " \n", + " results_df = classify_dataframe(\n", + " df, sentence_col, vendor, model, system_prompt, max_tokens,\n", + " output_dir=output_dir,\n", + " checkpoint_dir=checkpoint_dir,\n", + " save_interval=save_interval,\n", + " run=run,\n", + " reasoning_effort=reasoning_effort,\n", + " thinking_budget=thinking_budget,\n", + " thinking_level=thinking_level,\n", + " )\n", + " \n", + " all_results[run] = results_df\n", + " \n", + " all_results[run] = results_df\n", + " \n", + " # Print summary\n", + " job_runtime = time.perf_counter() - job_start_time\n", + " print(f\"\\n{'='*60}\")\n", + " print(\"SUMMARY\")\n", + " print(f\"{'='*60}\")\n", + " total_cost = sum(r['cost_usd'].sum() for r in all_results.values())\n", + " print(f\"Total runs: {len(runs)}\")\n", + " print(f\"Total cost: ${total_cost:.4f}\")\n", + " print(f\"Total runtime: {job_runtime:.1f}s ({job_runtime/60:.1f}m)\")\n", + " print(f\"Output location: {output_dir}/Run*/\")\n", + " \n", + " return all_results" + ] + }, + { + "cell_type": "markdown", + "id": "11c8f621-6826-4e71-b38c-32b1bd8de480", + "metadata": {}, + "source": [ + "# Load Data\n", + "\n", + ">**If you are running this in your local computer:** Subfolders will be automaticallty created inside the folder that this notebook is in. All files will be saved in those local folders/subfolders\n", + "\n", + "> **If you are on Google CoLab:**: FIRST, you will need to connect your google drive and navigate to the folder that this noteobok is in. Then, the code will create subfodlers inside the folder you navigated to on your google drive. All files will be saved in those local folders/subfolders on your google drive." + ] + }, + { + "cell_type": "markdown", + "id": "a90bfe58-576c-4b7a-88ff-b37ee816a391", + "metadata": {}, + "source": [ + "##### **IMPORTANT for Google CoLab**\n", + "\n", + "If you want to save to your google drive, you have to connect it first and then navigate to this current folder:\n", + "\n", + "- Import google drive and connect\n", + "- Change dir to folder that this notebook is in\n", + "\n", + "***Copy this code in a new code cell, modify folder as needed (if you don't want \"Project\") and run:***\n", + "```\n", + "from google.colab import drive\n", + "drive.mount('/content/drive')\n", + "\n", + "import os\n", + "\n", + "# Construct the full path to the desired folder within Google Drive\n", + "drive_path = '/content/drive/My Drive/Project'\n", + "\n", + "# Create the directory if it doesn't exist (optional, but good practice)\n", + "if not os.path.exists(drive_path):\n", + " os.makedirs(drive_path)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "336f43ce-f1b2-4d2f-8130-737ef8eea75d", + "metadata": {}, + "outputs": [], + "source": [ + "# Example Sentences\n", + "# sentences = ['The annual growth in our provision for uncollectible accounts was primarily attributable to transitioning multiple external payors from recognizing revenue on a cash basis to an accrual basis, thereby aligning with customer-related payment practices.', 'We handle certain sales-type leases internally, particularly those associated with facilities serving U.S. government hospital clients.', 'We expect that this acquisition will position us to broaden our offerings in the private label accessories segment, catering to customers seeking value-oriented solutions.', 'Additionally, the Tax Cuts and Jobs Act was enacted into law by the President in December 2017.', 'Valuations derived from the Black-Scholes model can vary significantly depending on the assumptions made regarding volatility and the duration of the underlying instruments.', 'Our audience is engaged across multiple channels, such as digital properties, print publications, as well as broadcast and streaming media.', 'The forecast incorporates management’s most informed assumptions regarding anticipated economic and market trends for the duration of the projection, encompassing anticipated changes in sales growth, cost structures, operating margin expectations, and future cash outlays.', 'As of December 31, 2007, a single credit remains unassigned to a particular reserve, which, absent any favorable developments, is at risk of defaulting imminently and may lead to the filing of a claim.', \"Our model incorporates assumptions regarding anticipated stock price fluctuations, utilizing historical volatility metrics, the applicable risk-free rate derived from the treasury yield curve, the projected duration of equity awards informed by past exercise trends and termination actions post-vesting, along with anticipated dividend equivalents to be paid during the award's estimated term, given that our stock appreciation rights participate in dividends.\", 'The Company conducts comprehensive physical counts of inventory across all store and warehouse locations at least once per year, and correspondingly updates the reported merchandise inventory to reflect the results of these assessments.', 'Substantial growth was realized across categories such as basketball and lifestyle footwear, as well as branded apparel and specialized cleats for wrestling, volleyball, and soccer.', 'Actuarial gains realized in 2007 will diminish the unrecognized loss allocated across the projected average remaining service years of active plan members, with such periods differing by plan from 6 to 23 years.', 'Platform utilization expanded across enterprise segments, reflecting enhanced operational efficiency and streamlined integration of internal systems, during fiscal 2020 for the technology company.', 'The advances carried maturities at assorted dates up to 2014, with interest rates ranging from 0.3% to 3.4%.', 'Furthermore, significant investments were made to upgrade essential operational systems, establish a comprehensive disaster recovery strategy, and strengthen compliance protocols designed to better serve our customers.', 'Subscription offerings expanded during fiscal 2023, reflecting successful margin optimization and process improvements within our technology platform, as we continued to innovate and refine our approach.', 'Provisions for loss contingencies are determined by management’s assessment regarding the probability of adverse results and the estimated magnitude of potential losses.', 'Before Discover Bank acquired SLC on December 31, 2010, SLC maintained a contractual relationship with Citi that facilitated the origination and ongoing management of private student loans for individuals.', 'Overview of BorgWarner Inc.’s Financial Condition and Operating Results Management’s Discussion and Analysis', 'We attribute the rise in RELIC watch sales chiefly to strategic modifications in our product offerings and the incremental expansion of our customer base achieved toward the end of Fiscal 2003.', 'PECO Electric Operating Statistics and Revenue Summary The following outlines PECO’s electric sales metrics and associated revenue information: (a) Full service represents energy provided to customers receiving electricity under standard tariffed rates.', 'As part of the 2009 Supervisory Capital Assessment Program, the Federal Reserve Board enhanced its review of the capital sufficiency of selected major bank holding companies by utilizing an alternative measure of Tier 1 capital referred to as Tier 1 common equity.', 'During the years ended 2008, 2007, and 2006, none of our customers individually represented 10% or greater of our overall revenue.', 'Other than our operating leases, which mainly pertain to restaurant locations, we do not engage in any off-balance sheet transactions.', 'Policyholders have the option to discontinue coverage as a result of their departure from medical practice due to retirement, disability, or passing.', 'Red Robin Gourmet Burgers®, Inc., a Delaware entity along with its subsidiaries (referred to herein as “Red Robin,” the “Company,” or by similar terms), is engaged predominantly in the development, operation, and franchising of casual-dining restaurants, totaling 514 outlets across North America as of the close of the fiscal year on December 28, 2014.', 'As of December 31, 2008, 51% of the outstanding home equity lines of credit were collateralized by properties located in New York State, while 21% and 26% were backed by properties in Pennsylvania and the Mid-Atlantic region, respectively.', \"The decline in property catastrophe offerings was attributable to non-renewed contracts and decreased participation levels, influenced by prevailing market dynamics and an increased reliance on retrocessional arrangements, whereas non-catastrophe property business during 2014 comprised an incoming unearned premium portfolio transfer of $50.2 million from Gulf Reinsurance Limited ('Gulf Re'), which the Company acquired in 2015.\", 'IPL’s operating performance reflected a $149 million decline in earnings allocable to common shareholders during 2008 and a $118 million improvement in 2007, which was largely attributable to a post-tax gain of $123 million stemming from the divestiture of IPL’s electric transmission assets in 2007.', 'Incorporating remote work practices forms an integral aspect of our overall business continuity strategy.', 'Upon the sale of a gift card, we record a corresponding liability on our balance sheet.', 'Management’s Discussion and Analysis Procedures for the Company and its Subsidiaries.', 'Our Carter’s, Just One Year, and Child of Mine brands are made available to third parties through licensing agreements.', 'SPP has initiated approvals for the development of transmission infrastructure designed to transport renewable energy from the wind-producing regions of western Oklahoma, the Texas Panhandle, and western Kansas to major demand centers, as part of its strategy to expand transmission capacity in these areas.', 'Consequently, we record revenue at the point when ownership is conveyed to our customer.', 'The credits provided will fluctuate from one quarter to the next, and ultimately, the cumulative benefits passed on to customers in the form of reduced electric rates will align with the amounts applied toward federal income tax obligations.', 'Outcomes may vary, and the divergence from these projections could be significant depending on alternative assumptions or circumstances.', 'Accruals associated with chargebacks and rebates involve a significant degree of estimation within our sales processes.', 'In the quarter concluding on September 30, 2013, we finalized a partnership arrangement with LPC MM Monrovia, LLC, an independent third party, specifically to facilitate the acquisition of a real estate asset in Monrovia, California, and to initiate the development of construction documentation for enhancements to the site.', 'Periodic legal proceedings or regulatory inquiries arise against the Company as a normal aspect of conducting its insurance operations.', 'In the interim between lease termination and final real estate disposition, we provided significant loan-based support to the hospital operator, enabling them to meet operational cash needs while awaiting reimbursement for patient services from Medicare and other payors.', 'Pursuant to the CRS agreement, close to one-fourth of the contract’s total value becomes payable by the customer and is subject to collection solely after launch and delivery objectives have been achieved for each of the eight CRS missions.', 'In 2008, the Company completed toll processing of 126,000 ounces of PGMs, an increase compared to the 112,000 ounces processed under toll arrangements in the prior year.', 'Operations within our ready-mixed concrete, precast concrete, and ancillary concrete businesses experience fluctuations attributable to seasonal patterns.', 'Historically, our highest working capital requirements arise in the latter half of the year, as accounts receivable and inventory expand due to elevated activity during the holiday sales period, and inventory builds ahead of anticipated factory shutdowns for Chinese New Year observances.', 'Cost of sales primarily includes expenses related to products, such as major aircraft and engine components, along with direct labor, overhead, and costs associated with maintaining aircraft.', 'Our proportional interest in the mines under our management affords us an annual rated pellet production capacity of 22.9 million tons, which equates to roughly 28% of the aggregate pellet capacity available throughout North America.', 'For the fiscal year ended December 31, 2009, a total of 338 da Vinci Surgical Systems were sold, representing a slight increase from the 335 units sold in the prior year ended December 31, 2008.', 'During the 2009 fiscal year, the Company incurred costs attributable to flooding totaling $7.6 million, while recognizing $16.7 million in recoveries from insurance claims.', 'The rise was tempered in part by the enhanced redeployment incentives offered through our equipment lease initiative to new customers.', 'The Company provides defined benefit pension arrangements, primarily benefiting salaried and management employees, and oversees the associated post-retirement medical plan accounting.', 'The gross profit margin declined to 30.7% in 2013 as compared to 31.4% in the previous year, largely attributable to a rise in sales from private label and international segments, which traditionally yield lower margins.', 'A substantial portion of our multi-family lending activity is directed toward longstanding property owners whose apartment buildings operate under rent control, resulting in rental rates that are lower than prevailing market levels.', 'Growth in distillery product revenues was driven by elevated unit volumes and enhanced pricing for food grade alcohol used in both beverage and industrial sectors, alongside strengthened pricing for fuel grade alcohol.', 'In October 2005, we completed delivery of the system to the customer.', 'On July 29, 2014, the Company completed an issuance of Senior Notes totaling $300 million, maturing on February 1, 2025, with a fixed interest rate of 5.375% and sold at par value, referred to herein as the 2014 Notes.', 'Expenses associated with reactivating these subscribers were recognized, and these customers were categorized as gross new DISH TV subscriber additions for the year ended December 31, 2017, with related costs captured under “Subscriber acquisition costs” within our Consolidated Statements of Operations and Comprehensive Income (Loss) and/or as “Purchases of property and equipment” in our Consolidated Statements of Cash Flows.', \"Refer to 'Item 8' under the section 'Loans Receivable.'\", 'Valuation of swaps, interest rate swaptions, and option contracts is determined through commonly accepted industry models that estimate the present value of anticipated derivative cash flows, reflecting both prevailing and anticipated market conditions.', 'On February 5, 2010, a total of 68 workover rigs were staffed and were either in service or subject to ongoing marketing efforts.', 'As a result of our commitment to making education more affordable for our students, we project that the typical debt burden for graduates of the Art Institutes has declined by nearly 15% since 2010.', 'The market valuation of distressed inventory is determined utilizing prior sales patterns for specific product categories, prevailing market dynamics, overall economic factors, and the worth of outstanding in-house orders associated with prospective sales of such inventory.', 'The Company factors such discounts and rebates into its determination of transaction price, recording them as deductions from gross sales.', 'Within the Caribbean region, we operate vertically integrated utilities as well as generation facilities, each governed by multi-year agreements established in partnership with governmental entities.', 'Nonetheless, despite Synovus Bank meeting all required quantitative capital standards, regulatory provisions allow for reclassification of an institution to a less favorable capital category, dependent on supervisory considerations beyond capital metrics.', 'For most of the securities measured through dealers and pricing services, we source several independent valuations, all of which are not legally binding on either our company or our counterparties.', '59 Overseas Shipholding Group, Inc. serves as the registry for this section.', 'Our strategy is to consistently keep U.S. wholesaler inventories for our products at or below a one-month average, supporting reliable supply for our customers.', 'Aside from the $202.9 million gain recognized in 2011 from the sales of Big Sandy and Langley, the year-over-year decline also reflected roughly 25% reduced realized prices for sales volumes, a 23% increase in the rate of production depletion, and elevated other operating costs, which were partially counterbalanced by a 33% rise in production output, a 30% expansion in gathered volumes, and increased transmission income.', '• Establishing further criteria for evaluating applications for disability-related benefit claims.', 'For fiscal year 2016, revenue totaled $28.2 million, representing a decline of $11.3 million, or 28.5%, compared to the prior year’s revenue of $39.5 million.', 'During 2010, the Company divested its Orthopaedic Implant production site located in Caen, France, resulting in a $24.3 million gain that was recognized within selling, general, and administrative expenses.', 'Illustrative instances of indemnification obligations under the Separation and Distribution Agreement and associated ancillary agreements include Navient’s duty to compensate the Company and the Bank for any liabilities, costs, or expenses they may face resulting from actions or potential actions concerning pre-Spin-Off SLM and its subsidiaries’ servicing, operational, and collections activities related to Private Education Loans and FFELP Loans that were held as assets by either the Bank or Navient at the time of the Spin-Off, contingent upon written notice being furnished to Navient by April 30, 2017, the third anniversary of the Spin-Off.', 'Growth in platform usage was observed, driven by improved internal workflows and resource allocation, during fiscal 2022 for the telecommunications company.', 'Acquisitions pursuant to the Plan may occur through open market transactions or privately arranged agreements, conducted periodically and in accordance with relevant legal requirements, inclusive of Rule 10b-18 under the amended Securities Exchange Act of 1934.', 'We ended our bridge revolving credit facility, originally established on June 13, 2007, with five U.S. and international banking institutions in February 2008.', \"Our management team regularly assesses the company's cost structure to confirm that operational expenditures are managed effectively without compromising the quality of service provided to customers.\", 'The company’s reach broadened in fiscal 2021, reflecting enhanced productivity and optimization of internal processes in expanded territories.', 'A portion of these rising costs was absorbed by the company, resulting in an average sales price uptick to customers of just $0.32 per kilogram.', 'The company saw advances in payment collection efficiency, reflecting cost reduction initiatives and automation of reconciliation tasks.', 'Advancements in technology have the potential to mitigate these factors or expand the availability of mineral resources.', 'Each of our two plans designed for small office and home office use provides a single business fax line at no extra cost, with supplementary fax lines available for a monthly fee.', 'In September 2011, the European Commission approved VIBATIV® for use in adult patients with hospital-acquired pneumonia, including cases linked to ventilators, where MRSA is known or suspected and alternative therapies are deemed inappropriate, thereby expanding therapeutic options for these individuals.', 'These trends are subject to modification due to factors such as the establishment of additional schools, launch of innovative programs, rising adult student enrollment, or potential acquisitions.', 'Funding requests, which generally arise at intervals of four to eight weeks, trigger the execution of necessary inspections and formal evaluations.', 'Assessing our yearly tax obligations and analyzing our tax strategies necessitates considerable judgment and expertise.', 'On March 24, 2006, the Grindle plaintiffs retracted their request to intervene, doing so without affecting their rights.', 'At December 31, 2017, the balance of commercial and industrial loans, which includes owner-occupied commercial properties, grew by $0.3 billion, reaching a total of $1.6 billion, reflecting support for our business customers’ financing needs.', 'After the merger, ARRIS retained complete indirect ownership of both ARRIS Group and Pace as wholly-owned subsidiaries.', '•On August 17, 2012, we provided a first mortgage loan totaling $46.0 million, secured by a Hilton hotel consisting of 315 rooms located in Rockville, Maryland.', 'Our Management’s Discussion and Analysis of Financial Condition and Results of Operations highlights our position as a foremost provider of independent, technology-driven portfolio management solutions, investment guidance, and retirement income services, serving participants predominantly within employer-sponsored defined contribution plans, including 401(k) arrangements.', 'The structure of our per-minute charges is designed to encompass the entirety of services provided.', 'On June 30, 2009, nearly 83% of our holdings, excluding cash balances, possessed maturities shorter than one year.', 'Distribution of Portfolio by Geography: The following table presents the Company’s operating square footage segmented by region at December 31, 2011 (in thousands). Industry Credit Risk Profile: The subsequent data illustrates the composition of our tenant portfolio by industry as of December 31, 2011.', '2 Includes additional products such as consumer revolving credit, installment loans, and consumer lease finance options tailored to customer needs.', 'Currently anticipated capital expenditures for 2006 total approximately $568.9 million, encompassing $24.0 million allocated to startup activities, resolution of the thruster defect previously detailed, and modifications mandated by customers for the GSF Development Driller I, $237.3 million dedicated to construction of a new semisubmersible unit, $45.0 million earmarked for repairs to our rig fleet due to hurricane impacts, $124.0 million assigned for significant fleet enhancements, $107.8 million directed toward additional equipment acquisitions and replacements, $17.3 million related to capitalized interest, and $13.5 million (net of intersegment eliminations) for oil and gas operations.', 'The Company plans to maintain its practice of issuing quarterly dividends, contingent upon Board approval, sufficient capital resources, and an assessment that such distributions remain advantageous for its shareholders.', 'As of December 31, 2008, the Company had no borrowings outstanding under its credit facility, with a total available capacity of roughly $48.4 million, reflecting the deduction for a $7.0 million letter of credit issued to BCBSF/HOI.', 'The progression of our product offerings relies on the availability and consistent performance of software sourced from external vendors.', 'The Company establishes BESP for its product deliverables through a weighted average pricing methodology, initiated by an examination of historical data on standalone sales transactions.']\n", + "# df = pd.DataFrame({'sentences': sentences})\n", + "# df=df.head(3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "20f2dab2-7738-435f-bdff-f9a9e3a2eb2c", + "metadata": {}, + "outputs": [], + "source": [ + "# Load Data: Preliminary Labeling of all available data\n", + "df = pd.read_csv(\"source_text/10K_unlabeled.csv\")\n", + "df = df.sample(n=10).reset_index(drop=True) # different sample each run\n", + "df" + ] + }, + { + "cell_type": "markdown", + "id": "dbc7642b-d0cd-4b73-836d-893c54531155", + "metadata": {}, + "source": [ + "# Set Output Paths\n", + "- Preliminary (\"OUTPUT_DIR\") vs. Holdout (\"HOLDOUT_DIR\") vs. Train (\"TRAIN_DIR\") sets\n", + "- ***Make sure not to accidentally overwrite your labeled data!***\n", + "- When you query a model (below in Run Models), you need to specifiy the output path." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a37fc60e-8234-4deb-b101-de383d378f09", + "metadata": {}, + "outputs": [], + "source": [ + "# =============================================================================\n", + "# OUTPUT CONFIGURATION - SET for Base, Holdout, Train\n", + "# =============================================================================\n", + "CHECKPOINT_DIR = \"./checkpoints\"\n", + "OUTPUT_DIR = \"./output\"\n", + "PRELIM_DIR = f\"{OUTPUT_DIR}/preliminary\"\n", + "HOLDOUT_DIR = f\"{OUTPUT_DIR}/holdout\"\n", + "TRAIN_DIR = f\"{OUTPUT_DIR}/train\"" + ] + }, + { + "cell_type": "markdown", + "id": "59c343be-dbbe-4c28-be41-44c518ed2526", + "metadata": {}, + "source": [ + "# Run Models\n", + "- Set desired parameters\n", + "- Set runs (currently set to 1 run per model for examples): runs=[1] vs runs=[1, 2, 3]\n", + "- Uncomment the models you what you want to run! \n", + "- Run different models? Make sure to define them above in the vendor/model configuration first.\n", + " - Not all models will run with this code.\n", + " - If you get errors, you need to debug and develop code further\n", + " - (I'd use Claude Opus 4.5 Thinking for that, but other genAI models may work as well / even better).\n", + "\n", + "> ***IMPORTANT*** If you want to rerun a model, make sure to delete its files from the checkpoints folder first. Otherwise, it will skip all examples (e.g., sentences) that the previous run already labeled (which could be all) and you don't get updated results.\n", + "\n", + "> **MORE IMPORTANT** Running this code will cost you API credits (and requires you to ahve accounts with the providers). You will need to supply your own API keys. Beware that you may be subject to rate limits (how many queries you can send per minute) and which models you can use (OpenAI, for example, requires you to verify your identidy with an ID to access many models). Regardless, every time you execute this code, you will drain your API credits = real money! Thus, make wise decisions about what and how much to label." + ] + }, + { + "cell_type": "markdown", + "id": "e4503bd1-0d03-4f09-8897-fc06be07d887", + "metadata": {}, + "source": [ + "## Labeling Approach:\n", + "\n", + "**What we ultimately need:**\n", + "- A holdout set (1000 examples)\n", + "- A training set (15k examples)\n", + "- The ability to test and train all classes / labels\n", + " - Need to have at least some balance in holdout set so that every class (label) is represented (e.g., at least 100 times)\n", + " - Need enough examples per class (label) in train set that fine-tuned model can learn them\n", + "> **Challenge**\n", + "> - How do we know that we have enough examples (i.e., sentences) per class (label)?\n", + "\n", + "> **Idea**\n", + "> - One possible approach is to label all data only once with a reasonably fast and inexpensive genAI model to get an idea about class (label) distribution. Depending how good the model is (which we cannot easily know yet unless we have a couple dozen examples that we manually constructed as preliminary evaluation set), we have at least a *directional idea* of which sentences may belong to which classes / have which labels.\n", + "> - We can then use this *directional idea* to ***construct a holdout set*** with at least N=100 (or more?) examples per class (label). This will be better than random sampling (unless classes (labels) are balanced in full data set, which is unlikely). It will still not be robust, but *at least give us some idea*.\n", + "> - We need to make sure to remove all examples that we put in the holdout set from the rest of our data (i.e., no holdout set example should also be in the training set to ***prevent leakage***). " + ] + }, + { + "cell_type": "markdown", + "id": "a2c07cc9-3961-4ff4-82db-d75006dfa14c", + "metadata": {}, + "source": [ + "### WARNING: MAKE SURE TO **PASS** THE CORRECT OUTPUT DIR!\n", + "What are you labeling? \n", + "- Prelimiary full data set (once to investigate class balance) --> PRELIM_DIR\n", + "- Holdout set --> HOLDOUT_DIR\n", + "- Train set --> TRAIN_DIR" + ] + }, + { + "cell_type": "markdown", + "id": "27552dca-0f9d-4feb-b2f0-0fe63df69d51", + "metadata": {}, + "source": [ + "### Google CoLab Runtime Timeouts\n", + "If you have a slow API and/or you are lableing many sentences (texts), Google CoLab may time-out or shut down your runtime. This will abort the labeling process. You can resume anytime, but you need to restart and run your notebook again. For this purpose, I've added checkpointing so that results are saved every N=100 sentences (texts) and the code will look for an intermis checkpoint and pickup from there (it will also find and retry errors where nothing valid was returned). *This may be less of a problem with CoLap PRO, which you can sign-up for free as a student.*\n", + "\n", + "> If you can, it may be well worth installing python and jupyter notebooks on your local computer. You won't face the timeout issues then and your code will query the APIs as long as your computer is connected to the internet (and running)." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "e892c00f-d577-4c86-b913-85dc75f51ff2", + "metadata": {}, + "outputs": [], + "source": [ + "# =============================================================================\n", + "# UNC Main Campus Computing on MS Azure\n", + "# Models: gpt-4.1, gpt-4o\n", + "# Modes: chat only!!! (temperature=0 set with openAI models) \n", + "# Notes: Experimental by Dr. D. To get odd number of lables per sentence across two models, I queried the first model 4 times (4 + 3 = 7)\n", + "# =============================================================================\n", + "\n", + "# results = run_classification(\n", + "# df,\n", + "# sentence_col=\"sentences\",\n", + "# vendor=\"azure\",\n", + "# model=\"gpt-4.1\",\n", + "# runs=[1],\n", + "# output_dir=OUTPUT_DIR, # overrides default: OUTPUT_DIR vs. HOLDOUT_DIR vs. TRAIN_DIR vs. PRELIM_DIR\n", + "# checkpoint_dir=CHECKPOINT_DIR, # overrides default\n", + "# )\n", + "\n", + "# results = run_classification(\n", + "# df,\n", + "# sentence_col=\"sentences\",\n", + "# vendor=\"azure\",\n", + "# model=\"gpt-4o\",\n", + "# runs=[1],\n", + "# output_dir=OUTPUT_DIR, # overrides default: OUTPUT_DIR vs. HOLDOUT_DIR vs. TRAIN_DIR vs. PRELIM_DIR\n", + "# checkpoint_dir=CHECKPOINT_DIR, # overrides default\n", + "# )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "55eefc77-28e4-4fbe-8e21-80c26a6d041a", + "metadata": {}, + "outputs": [], + "source": [ + "# =============================================================================\n", + "# OPENAI\n", + "# Models: gpt-5.2, gpt-5, gpt-5-mini, gpt-5-nano, gpt-4.1, gpt-4o\n", + "# Modes: chat (temperature=0) or reasoning (reasoning_effort)\n", + "# reasoning_effort: \"low\", \"medium\", \"high\"\n", + "# =============================================================================\n", + "\n", + "# # OpenAI chat mode (temperature=0)\n", + "# results = run_classification(\n", + "# df,\n", + "# sentence_col=\"sentences\",\n", + "# vendor=\"openai\",\n", + "# model=\"gpt-4.1\", # gpt-5.2, gpt-5, gpt-5-mini, gpt-5-nano, gpt-4.1, gpt-4o --> make sure these are defined with pricing in vendor/model configuration\n", + "# runs=[1],\n", + "# output_dir=OUTPUT_DIR, # overrides default: OUTPUT_DIR vs. HOLDOUT_DIR vs. TRAIN_DIR vs. PRELIM_DIR\n", + "# checkpoint_dir=CHECKPOINT_DIR, # overrides default\n", + "# )\n", + "\n", + "# OpenAI reasoning mode\n", + "# results = run_classification(\n", + "# df,\n", + "# sentence_col=\"sentences\",\n", + "# vendor=\"openai\",\n", + "# model=\"gpt-5.2\", # gpt-5.2, gpt-5, gpt-5-mini, gpt-5-nano, gpt-4.1, gpt-4o --> make sure these are defined with pricing in vendor/model configuration\n", + "# reasoning_effort=\"high\", # \"low\", \"medium\", \"high\"\n", + "# runs=[1],\n", + "# output_dir=OUTPUT_DIR, # overrides default: OUTPUT_DIR vs. HOLDOUT_DIR vs. TRAIN_DIR vs. PRELIM_DIR\n", + "# checkpoint_dir=CHECKPOINT_DIR, # overrides default\n", + "# )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "935a4056-5e2d-47da-add1-f38a2735844d", + "metadata": {}, + "outputs": [], + "source": [ + "# =============================================================================\n", + "# ANTHROPIC\n", + "# Models: claude-opus-4-5-20251101, claude-sonnet-4-5-20250929, \n", + "# claude-haiku-4-5-20251001, claude-sonnet-4-20250514\n", + "# Modes: chat (temperature=0) or thinking (thinking_budget)\n", + "# thinking_budget: min 1024, billed as output tokens\n", + "# =============================================================================\n", + "\n", + "# # Anthropic chat mode (temperature=0)\n", + "# results = run_classification(\n", + "# df,\n", + "# sentence_col=\"sentences\",\n", + "# vendor=\"anthropic\",\n", + "# model=\"claude-sonnet-4-5-20250929\", # opus-4-5, sonnet-4-5, haiku-4-5, sonnet-4\n", + "# runs=[1],\n", + "# output_dir=OUTPUT_DIR, # overrides default: OUTPUT_DIR vs. HOLDOUT_DIR vs. TRAIN_DIR vs. PRELIM_DIR\n", + "# checkpoint_dir=CHECKPOINT_DIR, # overrides default\n", + "# )\n", + "\n", + "# # Anthropic thinking mode\n", + "# results = run_classification(\n", + "# df,\n", + "# sentence_col=\"sentences\",\n", + "# vendor=\"anthropic\",\n", + "# model=\"claude-sonnet-4-5-20250929\", # opus-4-5, sonnet-4-5, haiku-4-5, sonnet-4\n", + "# thinking_budget=2048, # min 1024, billed as output tokens\n", + "# runs=[1],\n", + "# output_dir=OUTPUT_DIR, # overrides default: OUTPUT_DIR vs. HOLDOUT_DIR vs. TRAIN_DIR vs. PRELIM_DIR\n", + "# checkpoint_dir=CHECKPOINT_DIR, # overrides default\n", + "# )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5174d2b0-01b8-4971-8ead-9fb23bd416f3", + "metadata": {}, + "outputs": [], + "source": [ + "# =============================================================================\n", + "# FIREWORKS\n", + "# Models: deepseek-v3p2, deepseek-r1-0528, qwen3-vl-235b-a22b-instruct,\n", + "# qwen3-vl-235b-a22b-thinking, kimi-k2p5\n", + "# Modes: auto-detected from model name\n", + "# - Chat: deepseek-v3p2, qwen3-vl-235b-a22b-instruct\n", + "# - Thinking: deepseek-r1-0528, qwen3-vl-235b-a22b-thinking, kimi-k2p5\n", + "# =============================================================================\n", + "\n", + "# # DeepSeek V3.2 (chat)\n", + "# results = run_classification(\n", + "# df,\n", + "# sentence_col=\"sentences\",\n", + "# vendor=\"fireworks\",\n", + "# model=\"deepseek-v3p2\",\n", + "# runs=[1],\n", + "# output_dir=OUTPUT_DIR, # overrides default: OUTPUT_DIR vs. HOLDOUT_DIR vs. TRAIN_DIR vs. PRELIM_DIR\n", + "# checkpoint_dir=CHECKPOINT_DIR, # overrides default\n", + "# )\n", + "\n", + "# # DeepSeek R1 (thinking)\n", + "# results = run_classification(\n", + "# df,\n", + "# sentence_col=\"sentences\",\n", + "# vendor=\"fireworks\",\n", + "# model=\"deepseek-r1-0528\",\n", + "# runs=[1],\n", + "# output_dir=OUTPUT_DIR, # overrides default: OUTPUT_DIR vs. HOLDOUT_DIR vs. TRAIN_DIR vs. PRELIM_DIR\n", + "# checkpoint_dir=CHECKPOINT_DIR, # overrides default\n", + "# )\n", + "\n", + "# # Qwen3 VL Instruct (chat)\n", + "# results = run_classification(\n", + "# df,\n", + "# sentence_col=\"sentences\",\n", + "# vendor=\"fireworks\",\n", + "# model=\"qwen3-vl-235b-a22b-instruct\",\n", + "# runs=[1],\n", + "# output_dir=OUTPUT_DIR, # overrides default: OUTPUT_DIR vs. HOLDOUT_DIR vs. TRAIN_DIR vs. PRELIM_DIR\n", + "# checkpoint_dir=CHECKPOINT_DIR, # overrides default\n", + "# )\n", + "\n", + "# # Qwen3 VL Thinking (thinking)\n", + "# results = run_classification(\n", + "# df,\n", + "# sentence_col=\"sentences\",\n", + "# vendor=\"fireworks\",\n", + "# model=\"qwen3-vl-235b-a22b-thinking\",\n", + "# runs=[1],\n", + "# output_dir=OUTPUT_DIR, # overrides default: OUTPUT_DIR vs. HOLDOUT_DIR vs. TRAIN_DIR vs. PRELIM_DIR\n", + "# checkpoint_dir=CHECKPOINT_DIR, # overrides default\n", + "# )\n", + "\n", + "# # Kimi K2.5 (thinking)\n", + "# results = run_classification(\n", + "# df,\n", + "# sentence_col=\"sentences\",\n", + "# vendor=\"fireworks\",\n", + "# model=\"kimi-k2p5\",\n", + "# runs=[1],\n", + "# output_dir=OUTPUT_DIR, overrides default: OUTPUT_DIR vs. HOLDOUT_DIR vs. TRAIN_DIR vs. PRELIM_DIR\n", + "# checkpoint_dir=CHECKPOINT_DIR, # overrides default\n", + "# )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c4c2689d-f405-4061-8844-a83b2a53c80d", + "metadata": {}, + "outputs": [], + "source": [ + "# =============================================================================\n", + "# XAI (GROK)\n", + "# Models: grok-4, grok-4-1-fast-reasoning, grok-4-1-fast-non-reasoning\n", + "# Modes: auto-detected from model name\n", + "# - Reasoning: grok-4, grok-4-1-fast-reasoning\n", + "# - Chat: grok-4-1-fast-non-reasoning\n", + "# =============================================================================\n", + "\n", + "# # Grok 4 (reasoning)\n", + "# results = run_classification(\n", + "# df,\n", + "# sentence_col=\"sentences\",\n", + "# vendor=\"xai\",\n", + "# model=\"grok-4\", # grok-4, grok-4-1-fast-reasoning, grok-4-1-fast-non-reasoning\n", + "# runs=[1],\n", + "# output_dir=OUTPUT_DIR, # overrides default: OUTPUT_DIR vs. HOLDOUT_DIR vs. TRAIN_DIR vs. PRELIM_DIR\n", + "# checkpoint_dir=CHECKPOINT_DIR, # overrides default\n", + "# )\n", + "\n", + "# # Grok 4.1 Fast Reasoning\n", + "# results = run_classification(\n", + "# df,\n", + "# sentence_col=\"sentences\",\n", + "# vendor=\"xai\",\n", + "# model=\"grok-4-1-fast-reasoning\",\n", + "# runs=[1],\n", + "# output_dir=OUTPUT_DIR, # overrides default: OUTPUT_DIR vs. HOLDOUT_DIR vs. TRAIN_DIR vs. PRELIM_DIR\n", + "# checkpoint_dir=CHECKPOINT_DIR, # overrides default\n", + "# )\n", + "\n", + "# # Grok 4.1 Fast Non-Reasoning (chat)\n", + "# results = run_classification(\n", + "# df,\n", + "# sentence_col=\"sentences\",\n", + "# vendor=\"xai\",\n", + "# model=\"grok-4-1-fast-non-reasoning\",\n", + "# runs=[1],\n", + "# output_dir=OUTPUT_DIR, # overrides default: OUTPUT_DIR vs. HOLDOUT_DIR vs. TRAIN_DIR vs. PRELIM_DIR\n", + "# checkpoint_dir=CHECKPOINT_DIR, # overrides default\n", + "# )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5746b7c9-c3d0-4b0f-92a9-5cf087509421", + "metadata": {}, + "outputs": [], + "source": [ + "# =============================================================================\n", + "# GOOGLE GEMINI\n", + "# Models: gemini-3-pro-preview, gemini-3-flash-preview, \n", + "# gemini-2.5-pro, gemini-2.5-flash\n", + "# Modes: controlled via thinking_level\n", + "# - Pro: \"low\", \"high\" (default if not specified)\n", + "# - Flash: \"minimal\", \"low\", \"medium\", \"high\" (default if not specified)\n", + "# Note: Even \"low\" uses some thinking tokens. Only Flash \"minimal\" truly minimizes.\n", + "# =============================================================================\n", + "\n", + "# # Gemini 3 Pro - high thinking (default)\n", + "# results = run_classification(\n", + "# df,\n", + "# sentence_col=\"sentences\",\n", + "# vendor=\"google\",\n", + "# model=\"gemini-3-pro-preview\", # gemini-3-pro-preview, gemini-3-flash-preview, gemini-2.5-pro, gemini-2.5-flash\n", + "# thinking_level=\"high\", # Pro: \"low\", \"high\"\n", + "# runs=[1],\n", + "# output_dir=OUTPUT_DIR, # overrides default: OUTPUT_DIR vs. HOLDOUT_DIR vs. TRAIN_DIR vs. PRELIM_DIR\n", + "# checkpoint_dir=CHECKPOINT_DIR, # overrides default\n", + "# )\n", + "\n", + "# # Gemini 3 Pro - low thinking\n", + "# results = run_classification(\n", + "# df,\n", + "# sentence_col=\"sentences\",\n", + "# vendor=\"google\",\n", + "# model=\"gemini-3-pro-preview\",\n", + "# thinking_level=\"low\", # Pro: \"low\", \"high\"\n", + "# runs=[1],\n", + "# output_dir=OUTPUT_DIR, # overrides default: OUTPUT_DIR vs. HOLDOUT_DIR vs. TRAIN_DIR vs. PRELIM_DIR\n", + "# checkpoint_dir=CHECKPOINT_DIR, # overrides default\n", + "# )\n", + "\n", + "# # Gemini 3 Flash - high thinking (default)\n", + "# results = run_classification(\n", + "# df,\n", + "# sentence_col=\"sentences\",\n", + "# vendor=\"google\",\n", + "# model=\"gemini-3-flash-preview\",\n", + "# runs=[1],\n", + "# output_dir=OUTPUT_DIR, # overrides default: OUTPUT_DIR vs. HOLDOUT_DIR vs. TRAIN_DIR vs. PRELIM_DIR\n", + "# checkpoint_dir=CHECKPOINT_DIR, # overrides default\n", + "# )\n", + "\n", + "# # Gemini 3 Flash - minimal thinking (closest to chat mode)\n", + "# results = run_classification(\n", + "# df,\n", + "# sentence_col=\"sentences\",\n", + "# vendor=\"google\",\n", + "# model=\"gemini-3-flash-preview\",\n", + "# thinking_level=\"minimal\", # Flash: \"minimal\", \"low\", \"medium\", \"high\"\n", + "# runs=[1],\n", + "# output_dir=OUTPUT_DIR, # overrides default: OUTPUT_DIR vs. HOLDOUT_DIR vs. TRAIN_DIR vs. PRELIM_DIR\n", + "# checkpoint_dir=CHECKPOINT_DIR, # overrides default\n", + "# )" + ] + }, + { + "cell_type": "markdown", + "id": "b2e948ca-dafa-497d-8449-18af62945c33", + "metadata": {}, + "source": [ + "# Preliminary Labels and Holdout Set\n", + "Once we labeled out data ***one time*** with a model, we can get a first idea of class (label) distribution and construct our holdout set accordingly.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "74af47ed-ce00-4b45-beed-a0316a067589", + "metadata": {}, + "outputs": [], + "source": [ + "# I will use GPT 4.1 for this purpose that UNC hosted on Azure. \n", + "# You probably will not have access to this API and model.\n", + "# Pick a fast and not too expensive model that you feel confident can do an okay job (maybe get at least 70% correct)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e0128128-bcc9-4098-8cfd-de0d716384a5", + "metadata": {}, + "outputs": [], + "source": [ + "results = run_classification(\n", + " df,\n", + " sentence_col=\"sentences\", # provide the column name in which the text is you want to classify (sentence vs sentences?)\n", + " vendor=\"azure\",\n", + " model=\"gpt-4.1\",\n", + " runs=[1],\n", + " output_dir=PRELIM_DIR, # overrides default: OUTPUT_DIR vs. HOLDOUT_DIR vs. TRAIN_DIR vs. PRELIM_DIR\n", + " checkpoint_dir=CHECKPOINT_DIR, # overrides default\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "ee8af782-e8a6-43ce-ae24-8db0fe997a09", + "metadata": {}, + "source": [ + "## STEP 1: Load labeled data from a single genAI run" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "14621c20-9da6-4217-b6a7-d6412e224531", + "metadata": {}, + "outputs": [], + "source": [ + "# -----------------------------\n", + "# Configuration\n", + "# -----------------------------\n", + "\n", + "# CHANGE THIS: Path to your labeled data (one run, one model)\n", + "LABELED_FILE = \"./output/preliminary/Run1/preliminary_azure_gpt-4.1_chat_run1.pkl\"\n", + "\n", + "# Functional areas\n", + "CLASSES = [\"Marketing\", \"Finance\", \"Accounting\", \"Operations\", \"IT\", \"HR\"]\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7b2d53f0-22f2-4e16-8a58-8a6cca24adc1", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "import ast\n", + "\n", + "\n", + "# -----------------------------\n", + "# Load and Parse\n", + "# -----------------------------\n", + "\n", + "print(\"=\"*60)\n", + "print(\"LOADING LABELED DATA\")\n", + "print(\"=\"*60)\n", + "\n", + "df_raw = pd.read_pickle(LABELED_FILE)\n", + "print(f\"Source: {LABELED_FILE}\")\n", + "print(f\"Total sentences: {len(df_raw)}\")\n", + "\n", + "# Parse labels into binary columns\n", + "def parse_labels_safe(labels):\n", + " \"\"\"Parse labels from various formats.\"\"\"\n", + " if labels is None:\n", + " return []\n", + " if isinstance(labels, list):\n", + " return labels\n", + " if isinstance(labels, str):\n", + " try:\n", + " parsed = ast.literal_eval(labels)\n", + " return parsed if isinstance(parsed, list) else []\n", + " except:\n", + " return []\n", + " return []\n", + "\n", + "# Create binary columns for each class\n", + "df_labeled = df_raw[['id', 'sentence']].copy()\n", + "\n", + "parsed_labels = df_raw['labels'].apply(parse_labels_safe)\n", + "\n", + "for cls in CLASSES:\n", + " df_labeled[cls] = parsed_labels.apply(lambda x: 1 if cls in x else 0)\n", + "\n", + "# None = all classes are 0\n", + "df_labeled['None'] = (df_labeled[CLASSES].sum(axis=1) == 0).astype(int)\n", + "\n", + "# Remove rows where labeling failed (error column is not None/NaN)\n", + "if 'error' in df_raw.columns:\n", + " error_mask = df_raw['error'].notna()\n", + " n_errors = error_mask.sum()\n", + " if n_errors > 0:\n", + " df_labeled = df_labeled[~error_mask].reset_index(drop=True)\n", + " print(f\"Removed {n_errors} rows with labeling errors\")\n", + "\n", + "print(f\"Successfully labeled: {len(df_labeled)} sentences\")\n", + "\n", + "# Preview\n", + "print(f\"\\nPreview:\")\n", + "label_cols = CLASSES + ['None']\n", + "print(df_labeled[['sentence'] + label_cols].head(5))" + ] + }, + { + "cell_type": "markdown", + "id": "b6b4c4d7-2ed1-42a3-8d6b-09c7371bc9ba", + "metadata": {}, + "source": [ + "## STEP 2: Descriptives" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "91d6ef4d-6498-4d36-837a-91b44d329cd0", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "label_cols = CLASSES + ['None']\n", + "\n", + "print(\"=\"*60)\n", + "print(\"DESCRIPTIVE STATISTICS\")\n", + "print(\"=\"*60)\n", + "print(f\"Total sentences: {len(df_labeled)}\")\n", + "\n", + "# Class distribution\n", + "print(f\"\\n{'='*60}\")\n", + "print(\"CLASS DISTRIBUTION\")\n", + "print(f\"{'='*60}\")\n", + "print(f\"{'Class':<15} {'Count':>8} {'Share':>10}\")\n", + "print(f\"{'-'*35}\")\n", + "\n", + "for cls in label_cols:\n", + " count = df_labeled[cls].sum()\n", + " share = count / len(df_labeled) * 100\n", + " print(f\"{cls:<15} {count:>8} {share:>9.1f}%\")\n", + "\n", + "# Multi-label distribution\n", + "df_labeled['num_labels'] = df_labeled[CLASSES].sum(axis=1)\n", + "\n", + "print(f\"\\n{'='*60}\")\n", + "print(\"MULTI-LABEL DISTRIBUTION\")\n", + "print(f\"{'='*60}\")\n", + "print(f\"{'# Labels':<15} {'Count':>8} {'Share':>10}\")\n", + "print(f\"{'-'*35}\")\n", + "\n", + "for n in range(7):\n", + " count = (df_labeled['num_labels'] == n).sum()\n", + " if count > 0:\n", + " share = count / len(df_labeled) * 100\n", + " label_text = f\"{n} label{'s' if n != 1 else ''}\"\n", + " print(f\"{label_text:<15} {count:>8} {share:>9.1f}%\")\n", + "\n", + "print(f\"{'-'*35}\")\n", + "print(f\"{'Mean labels':<15} {df_labeled['num_labels'].mean():>8.2f}\")\n", + "print(f\"{'Median labels':<15} {df_labeled['num_labels'].median():>8.0f}\")\n", + "\n", + "# Co-occurrence matrix\n", + "print(f\"\\n{'='*60}\")\n", + "print(\"CO-OCCURRENCE MATRIX\")\n", + "print(f\"{'='*60}\")\n", + "\n", + "cooccurrence = pd.DataFrame(index=CLASSES, columns=CLASSES, dtype=int)\n", + "for cls1 in CLASSES:\n", + " for cls2 in CLASSES:\n", + " cooccurrence.loc[cls1, cls2] = ((df_labeled[cls1] == 1) & (df_labeled[cls2] == 1)).sum()\n", + "\n", + "print(cooccurrence.to_string())\n", + "\n", + "# Top label combinations\n", + "print(f\"\\n{'='*60}\")\n", + "print(\"TOP 10 LABEL COMBINATIONS\")\n", + "print(f\"{'='*60}\")\n", + "\n", + "def get_label_combo(row):\n", + " labels = [cls for cls in CLASSES if row[cls] == 1]\n", + " return str(labels) if labels else \"[]\"\n", + "\n", + "combo_counts = df_labeled.apply(get_label_combo, axis=1).value_counts().head(10)\n", + "print(f\"{'Combination':<50} {'Count':>8} {'Share':>10}\")\n", + "print(f\"{'-'*70}\")\n", + "for combo, count in combo_counts.items():\n", + " share = count / len(df_labeled) * 100\n", + " print(f\"{combo:<50} {count:>8} {share:>9.1f}%\")\n", + "\n", + "# Clean up temp column\n", + "df_labeled.drop(columns=['num_labels'], inplace=True)" + ] + }, + { + "cell_type": "markdown", + "id": "82b12506-7b3a-4f83-b3c9-da733c89306e", + "metadata": {}, + "source": [ + "## STEP 3: Create Holdout and Train Sets" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "86bf25c6-10b5-4d2c-8043-46c62c6598bd", + "metadata": {}, + "outputs": [], + "source": [ + "# =============================================================================\n", + "# STEP 3: CREATE HOLDOUT AND TRAIN SETS\n", + "# =============================================================================\n", + "\n", + "import os\n", + "\n", + "# -----------------------------\n", + "# Configuration\n", + "# -----------------------------\n", + "\n", + "HOLDOUT_SIZE = 1000\n", + "MIN_PER_CLASS = 100\n", + "MAX_PER_CLASS = 333\n", + "MAX_NONE = 100 # Maximum None sentences in holdout\n", + "OUT_DIR = \"./Holdout_Train\"\n", + "\n", + "os.makedirs(OUT_DIR, exist_ok=True)\n", + "\n", + "np.random.seed(42)\n", + "\n", + "# -----------------------------\n", + "# Helper\n", + "# -----------------------------\n", + "\n", + "def get_labels(row):\n", + " \"\"\"Get list of functional labels for a row.\"\"\"\n", + " return [cls for cls in CLASSES if row[cls] == 1]\n", + "\n", + "# Add temp columns\n", + "df_labeled['labels_list'] = df_labeled.apply(get_labels, axis=1)\n", + "df_labeled['num_labels'] = df_labeled[CLASSES].sum(axis=1)\n", + "\n", + "# -----------------------------\n", + "# Stratified Sampling (6 functional classes only — None is derived)\n", + "# -----------------------------\n", + "\n", + "selected_indices = set()\n", + "class_counts = {cls: 0 for cls in CLASSES}\n", + "\n", + "print(\"=\"*60)\n", + "print(\"STRATIFIED HOLDOUT SAMPLING\")\n", + "print(\"=\"*60)\n", + "print(f\"Target holdout size: {HOLDOUT_SIZE}\")\n", + "print(f\"Min per class: {MIN_PER_CLASS} (6 functional classes)\")\n", + "print(f\"Max per class: {MAX_PER_CLASS}\")\n", + "print(f\"None: not constrained (derived, not independently predicted)\")\n", + "\n", + "# Phase 1: Ensure minimums, rarest classes first\n", + "class_freq = {cls: int(df_labeled[cls].sum()) for cls in CLASSES}\n", + "classes_by_rarity = sorted(CLASSES, key=lambda c: class_freq[c])\n", + "\n", + "print(f\"\\n--- Phase 1: Ensure minimums (rarest first) ---\")\n", + "print(f\" Class frequencies: {', '.join(f'{c}: {class_freq[c]}' for c in classes_by_rarity)}\")\n", + "\n", + "for rare_class in classes_by_rarity:\n", + " candidates = df_labeled[\n", + " (df_labeled[rare_class] == 1) & \n", + " (~df_labeled.index.isin(selected_indices))\n", + " ].sort_values('num_labels', ascending=False)\n", + " \n", + " for idx, row in candidates.iterrows():\n", + " if class_counts[rare_class] >= MIN_PER_CLASS:\n", + " break\n", + " labels = row['labels_list']\n", + " if len(labels) > 0 and any(class_counts[lbl] >= MAX_PER_CLASS for lbl in labels):\n", + " continue\n", + " selected_indices.add(idx)\n", + " for lbl in labels:\n", + " class_counts[lbl] += 1\n", + " \n", + " print(f\" {rare_class}: {class_counts[rare_class]} sentences\")\n", + "\n", + "print(f\"\\nAfter Phase 1: {len(selected_indices)} sentences selected\")\n", + "\n", + "# Phase 2: Multi-label sentences\n", + "print(f\"\\n--- Phase 2: Add multi-label sentences ---\")\n", + "\n", + "current_multilabel = df_labeled.loc[list(selected_indices), 'num_labels'].gt(1).sum()\n", + "target_multilabel = int(HOLDOUT_SIZE * 0.18)\n", + "\n", + "multilabel_candidates = df_labeled[\n", + " (df_labeled['num_labels'] >= 2) & \n", + " (~df_labeled.index.isin(selected_indices))\n", + "].sample(frac=1, random_state=42)\n", + "\n", + "for idx, row in multilabel_candidates.iterrows():\n", + " if current_multilabel >= target_multilabel:\n", + " break\n", + " if len(selected_indices) >= HOLDOUT_SIZE:\n", + " break\n", + " labels = row['labels_list']\n", + " if len(labels) > 0 and any(class_counts[lbl] >= MAX_PER_CLASS for lbl in labels):\n", + " continue\n", + " selected_indices.add(idx)\n", + " for lbl in labels:\n", + " class_counts[lbl] += 1\n", + " current_multilabel += 1\n", + "\n", + "print(f\" Multi-label sentences: {current_multilabel}\")\n", + "print(f\" Total selected: {len(selected_indices)}\")\n", + "\n", + "# Phase 3: Fill remaining (cap None sentences)\n", + "none_count = sum(1 for idx in selected_indices if df_labeled.loc[idx, CLASSES].sum() == 0)\n", + "\n", + "print(f\"\\n--- Phase 3: Fill to {HOLDOUT_SIZE} (max None: {MAX_NONE}) ---\")\n", + "print(f\" None so far: {none_count}\")\n", + "\n", + "if len(selected_indices) < HOLDOUT_SIZE:\n", + " fill_candidates = df_labeled[\n", + " ~df_labeled.index.isin(selected_indices)\n", + " ].sample(frac=1, random_state=42)\n", + " \n", + " for idx, row in fill_candidates.iterrows():\n", + " if len(selected_indices) >= HOLDOUT_SIZE:\n", + " break\n", + " labels = row['labels_list']\n", + " \n", + " # Skip if any functional class would exceed max\n", + " if len(labels) > 0 and any(class_counts[lbl] >= MAX_PER_CLASS for lbl in labels):\n", + " continue\n", + " \n", + " # Skip if this is a None sentence and we've hit the cap\n", + " if len(labels) == 0 and none_count >= MAX_NONE:\n", + " continue\n", + " \n", + " selected_indices.add(idx)\n", + " for lbl in labels:\n", + " class_counts[lbl] += 1\n", + " if len(labels) == 0:\n", + " none_count += 1\n", + "\n", + "print(f\" Final count: {len(selected_indices)}\")\n", + "\n", + "# -----------------------------\n", + "# Create Clean DataFrames (LABELS BLANKED OUT)\n", + "# -----------------------------\n", + "\n", + "# Holdout and train get sentences + empty label columns\n", + "df_holdout = df_labeled.loc[list(selected_indices), ['sentence']].copy()\n", + "df_train = df_labeled.loc[~df_labeled.index.isin(selected_indices), ['sentence']].copy()\n", + "\n", + "# Add empty label columns (students fill these in)\n", + "for cls in CLASSES + ['None']:\n", + " df_holdout[cls] = \"\"\n", + " df_train[cls] = \"\"\n", + "\n", + "# Shuffle both\n", + "df_holdout = df_holdout.sample(frac=1, random_state=42).reset_index(drop=True)\n", + "df_train = df_train.sample(frac=1, random_state=42).reset_index(drop=True)\n", + "\n", + "# Clean up temp columns from df_labeled\n", + "df_labeled.drop(columns=['labels_list', 'num_labels'], inplace=True, errors='ignore')\n", + "\n", + "# -----------------------------\n", + "# Verification (using original labels for reporting only)\n", + "# -----------------------------\n", + "\n", + "print(f\"\\n{'='*60}\")\n", + "print(\"VERIFICATION\")\n", + "print(f\"{'='*60}\")\n", + "\n", + "print(f\"\\nDataset sizes:\")\n", + "print(f\" Holdout: {len(df_holdout)}\")\n", + "print(f\" Train: {len(df_train)}\")\n", + "print(f\" Total: {len(df_holdout) + len(df_train)}\")\n", + "\n", + "# Verify no overlap\n", + "overlap = set(df_holdout['sentence']) & set(df_train['sentence'])\n", + "print(f\"Overlap check: {len(overlap)} sentences (should be 0)\")\n", + "\n", + "# Report holdout class distribution (from original labels, for our reference)\n", + "print(f\"\\n{'='*60}\")\n", + "print(\"HOLDOUT CLASS DISTRIBUTION (from LLM labels, for reference)\")\n", + "print(f\"{'='*60}\")\n", + "print(f\"{'Class':<15} {'Count':>8} {'Share':>10} {'Min OK':>10} {'Max OK':>10}\")\n", + "print(f\"{'-'*55}\")\n", + "\n", + "holdout_sentences = set(df_holdout['sentence'])\n", + "df_holdout_check = df_labeled[df_labeled['sentence'].isin(holdout_sentences)]\n", + "\n", + "for cls in CLASSES:\n", + " count = df_holdout_check[cls].sum()\n", + " share = count / len(df_holdout_check) * 100\n", + " min_ok = \"✓\" if count >= MIN_PER_CLASS else \"✗\"\n", + " max_ok = \"✓\" if count <= MAX_PER_CLASS else \"✗\"\n", + " print(f\"{cls:<15} {count:>8} {share:>9.1f}% {min_ok:>10} {max_ok:>10}\")\n", + "\n", + "# None (derived, for reference)\n", + "none_count = (df_holdout_check[CLASSES].sum(axis=1) == 0).sum()\n", + "none_share = none_count / len(df_holdout_check) * 100\n", + "none_ok = \"✓\" if none_count <= MAX_NONE else \"✗\"\n", + "print(f\"{'None (derived)':<15} {none_count:>8} {none_share:>9.1f}% {'':>10} {none_ok:>10} (max {MAX_NONE})\")\n", + "\n", + "# Multi-label distribution\n", + "print(f\"\\n{'='*60}\")\n", + "print(\"HOLDOUT MULTI-LABEL DISTRIBUTION (from LLM labels, for reference)\")\n", + "print(f\"{'='*60}\")\n", + "print(f\"{'# Labels':<15} {'Count':>8} {'Share':>10}\")\n", + "print(f\"{'-'*35}\")\n", + "\n", + "num_labels = df_holdout_check[CLASSES].sum(axis=1)\n", + "for n in range(7):\n", + " count = (num_labels == n).sum()\n", + " if count > 0:\n", + " share = count / len(df_holdout_check) * 100\n", + " print(f\"{n} label{'s' if n != 1 else '':<14} {count:>8} {share:>9.1f}%\")\n", + "\n", + "# Preview\n", + "print(f\"\\nHoldout preview (labels are blank for human experts to fill):\")\n", + "print(df_holdout.head(5))\n", + "print(f\"\\nTrain preview (labels are blank for genAI to fill):\")\n", + "print(df_train.head(5))\n", + "\n", + "# -----------------------------\n", + "# Save\n", + "# -----------------------------\n", + "\n", + "df_holdout.to_csv(f\"{OUT_DIR}/holdout.csv\", index=False)\n", + "df_holdout.to_pickle(f\"{OUT_DIR}/holdout.pkl\")\n", + "df_train.to_csv(f\"{OUT_DIR}/train.csv\", index=False)\n", + "df_train.to_pickle(f\"{OUT_DIR}/train.pkl\")\n", + "\n", + "print(f\"\\n{'='*60}\")\n", + "print(\"SAVED\")\n", + "print(f\"{'='*60}\")\n", + "print(f\" Holdout: {OUT_DIR}/holdout.csv (.pkl)\")\n", + "print(f\" Train: {OUT_DIR}/train.csv (.pkl)\")\n", + "print(f\"\\nColumns: {list(df_holdout.columns)}\")\n", + "print(f\"Label columns are EMPTY - human experts must fill these in\")" + ] + }, + { + "cell_type": "markdown", + "id": "189837d8-bf61-4924-981a-3d5f83ec9e78", + "metadata": {}, + "source": [ + "# **Human Labeling of Holdout for Ground Truth**\n", + "\n", + "- Now we have a more or less balanced holdout set\n", + "- We need to get this labeled by human experts, that is, domain experts / subject matter experts\n", + "- You will need at least three humans to evaluate each sentence independently,\n", + " *or* work as an expert team and discuss each sentence to assign it the appropriate class (or labels)\n", + "- Make sure to save the file with the labels AND ***be sure that the text (e.g., sentences) are not broken / contain formatting or ASCI or HTML errors***\n", + " - You might want to label in excel, but then merge the labels from the XLSX or CSV file to the the holdout.pkl file (which better preserved the actual texts)\n", + "- If you have independent human experts label the holdout, then you need to have a majority vote per label (this suggests you need an odd number of human expert labelers). Good practice is also to check inter-rater agreement on the labels." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fac02954-21d8-419b-9215-733639f8fdb6", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3abaaf59-24e0-49dc-aef9-47f88dbc4469", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0e3aae9b-6565-413d-aa57-78113809acf5", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "546b0d8b-c049-4ae3-8f37-f471036a99bc", + "metadata": {}, + "source": [ + "# **genAI Labeling of Holdout**\n", + "> Now that you have a ground truth for your holdout set, you need to determine which genAI model performs best on it\n", + "\n", + "#### Approach: \n", + "1. **Label the holdout 3 times with a genAI mode** (use code from above, but instead of loading the \"10K_unlabeled.csv\" file for preliminary labeling, you want to load your holdout.pkl file (the one without your human labels).\n", + "2. **Check** the three runs for **label agreement** (krippendorff's alpha, for example)\n", + "3. Get the **majority vote** (for class or for labels - this example will be for ***labels*** that, unlike classes, are ***NOT mutually exclusive***\n", + "4. **Compare to human expert labels on holdout** set to measure genAI labeling **performance**\n", + "5. **Repeat** for other models (of other vendors)\n", + "6. **Find model** that does **best**, then use it to label the train set (3 times - same genAI API code from above but on different file: makre sure to adjust the paths where you store the data so you don't overwrite your holdout labels), get majority votes on train, then use those to fine-tune a pretrained and open-source LLM (like RoBERTa Large)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c81a6d50-b86b-4384-824c-3f7b1262d63e", + "metadata": {}, + "outputs": [], + "source": [ + "# =============================================================================\n", + "# OUTPUT CONFIGURATION - SET for Base, Holdout, Train\n", + "# =============================================================================\n", + "CHECKPOINT_DIR = \"./checkpoints\"\n", + "OUTPUT_DIR = \"./output\"\n", + "HOLDOUT_DIR = f\"{OUTPUT_DIR}/holdout\"\n", + "TRAIN_DIR = f\"{OUTPUT_DIR}/train\"\n", + "\n", + "# =============================================================================\n", + "# Load Holdout (not the human labeled, but the blank)\n", + "# =============================================================================\n", + "\n", + "# # Load Data: Labeling of (balanced) holdout data\n", + "df = pd.read_pickle(\"Holdout_Train/holdout.pkl\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7bea59bb-1faf-4469-819a-e5cbcf9d5425", + "metadata": {}, + "outputs": [], + "source": [ + "# =============================================================================\n", + "# Query genAI model via API\n", + "# =============================================================================\n", + "\n", + "# Here an example for gpt-4o via UNC Azure API\n", + "results = run_classification(\n", + " df,\n", + " sentence_col=\"sentence\", # --> Check if your file has the column as named here where the text is (sentence vs sentences vs text vs tweet vs ... )\n", + " vendor=\"azure\",\n", + " model=\"gpt-4o\",\n", + " runs=[1,2,3], # Doing 3 runs for conistency / replicability: will later take majority vote per lable across runs\n", + " output_dir=HOLDOUT_DIR, # overrides default: OUTPUT_DIR vs. HOLDOUT_DIR vs. TRAIN_DIR vs. PRELIM_DIR\n", + " checkpoint_dir=CHECKPOINT_DIR, # overrides default\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "207a4e45-dc15-4df4-855c-d151c1a9f649", + "metadata": {}, + "outputs": [], + "source": [ + "# =============================================================================\n", + "# Query another genAI model via API\n", + "# =============================================================================\n", + "\n", + "# Here an example for gpt-4o via UNC Azure API\n", + "results = run_classification(\n", + " df,\n", + " sentence_col=\"sentence\", # --> Check if your file has the column as named here where the text is (sentence vs sentences vs text vs tweet vs ... )\n", + " vendor=\"azure\",\n", + " model=\"gpt-4.1\",\n", + " runs=[1,2,3], # Doing 3 runs for conistency / replicability: will later take majority vote per lable across runs\n", + " output_dir=HOLDOUT_DIR, # overrides default: OUTPUT_DIR vs. HOLDOUT_DIR vs. TRAIN_DIR vs. PRELIM_DIR\n", + " checkpoint_dir=CHECKPOINT_DIR, # overrides default\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "158e92e8-1f1a-4b58-bb8e-a000f4fe9b59", + "metadata": {}, + "source": [ + "# genAI Label Agreement\n", + "\n", + "- How consistent is genAI in its labels?\n", + "- Test the extent to which genAI's labels agree across runs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4d0c9f7c-d74d-4cc5-a16c-55e20dc0293e", + "metadata": {}, + "outputs": [], + "source": [ + "# pip install -q -U krippendorff # already done at the very beginning. Keeping this as a reminder" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "793ba990-1e0d-4376-b2cc-887bbe633ee8", + "metadata": {}, + "outputs": [], + "source": [ + "# =============================================================================\n", + "# INTER-RATER AGREEMENT ACROSS RUNS (Krippendorff's Alpha)\n", + "# =============================================================================\n", + "\n", + "import pandas as pd\n", + "import numpy as np\n", + "import ast\n", + "import glob\n", + "import re\n", + "import krippendorff \n", + "\n", + "# -----------------------------\n", + "# Configuration\n", + "# -----------------------------\n", + "\n", + "HOLDOUT_DIR = \"./output/holdout\" # Set your holdout output directory\n", + "RUNS = [1, 2, 3] # Which runs to compare\n", + "CLASSES = [\"Marketing\", \"Finance\", \"Accounting\", \"Operations\", \"IT\", \"HR\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "063a4981-1524-4bb0-a91c-c937f345fc27", + "metadata": {}, + "outputs": [], + "source": [ + "# -----------------------------\n", + "# Helper Functions\n", + "# -----------------------------\n", + "\n", + "def parse_labels_safe(labels):\n", + " \"\"\"Parse labels from various formats.\"\"\"\n", + " if labels is None:\n", + " return []\n", + " if isinstance(labels, list):\n", + " return labels\n", + " if isinstance(labels, str):\n", + " try:\n", + " parsed = ast.literal_eval(labels)\n", + " return parsed if isinstance(parsed, list) else []\n", + " except:\n", + " return []\n", + " return []\n", + "\n", + "def parse_filename(filename):\n", + " \"\"\"\n", + " Parse filename like 'holdout_azure_gpt-4.1_chat_run1.pkl' \n", + " into (vendor, model, mode, run).\n", + " Handles optional dataset prefix (holdout_, train_, prelim_, output_).\n", + " \"\"\"\n", + " # Remove extension\n", + " name = filename.replace('.pkl', '').replace('.csv', '')\n", + " \n", + " # Strip known dataset prefixes\n", + " for prefix in ['holdout_', 'train_', 'prelim_', 'output_']:\n", + " if name.startswith(prefix):\n", + " name = name[len(prefix):]\n", + " break\n", + " \n", + " # Extract run number from end\n", + " match = re.search(r'_run(\\d+)$', name)\n", + " if not match:\n", + " return None\n", + " run = int(match.group(1))\n", + " name = name[:match.start()]\n", + " \n", + " # Extract mode (last part before run)\n", + " parts = name.rsplit('_', 1)\n", + " if len(parts) != 2:\n", + " return None\n", + " mode = parts[1]\n", + " remainder = parts[0]\n", + " \n", + " # Extract vendor (first part) and model (rest)\n", + " first_underscore = remainder.index('_')\n", + " vendor = remainder[:first_underscore]\n", + " model = remainder[first_underscore + 1:]\n", + " \n", + " return vendor, model, mode, run\n", + "\n", + "def discover_models(holdout_dir, runs):\n", + " \"\"\"\n", + " Discover all vendor_model_mode combinations that have ALL specified runs.\n", + " Returns dict: {(vendor, model, mode): {run: filepath}}\n", + " \"\"\"\n", + " models = {}\n", + " \n", + " for run in runs:\n", + " run_dir = f\"{holdout_dir}/Run{run}\"\n", + " pkl_files = glob.glob(f\"{run_dir}/*.pkl\")\n", + " \n", + " for filepath in pkl_files:\n", + " filename = filepath.split(\"/\")[-1]\n", + " parsed = parse_filename(filename)\n", + " if parsed is None:\n", + " continue\n", + " \n", + " vendor, model, mode, file_run = parsed\n", + " if file_run != run:\n", + " continue\n", + " \n", + " key = (vendor, model, mode)\n", + " if key not in models:\n", + " models[key] = {}\n", + " models[key][run] = filepath\n", + " \n", + " # Keep only models that have ALL specified runs\n", + " complete = {\n", + " key: paths for key, paths in models.items()\n", + " if all(r in paths for r in runs)\n", + " }\n", + " \n", + " return complete\n", + "\n", + "def load_and_binarize(filepath, classes):\n", + " \"\"\"Load pkl and convert labels to binary columns.\"\"\"\n", + " df = pd.read_pickle(filepath)\n", + " \n", + " parsed = df['labels'].apply(parse_labels_safe)\n", + " \n", + " binary = pd.DataFrame(index=df.index)\n", + " binary['id'] = df['id'] if 'id' in df.columns else df.index\n", + " binary['sentence'] = df['sentence']\n", + " \n", + " for cls in classes:\n", + " binary[cls] = parsed.apply(lambda x: 1 if cls in x else 0)\n", + " \n", + " # Remove error rows\n", + " if 'error' in df.columns:\n", + " binary = binary[df['error'].isna()].reset_index(drop=True)\n", + " \n", + " return binary\n", + "\n", + "def compute_agreement(model_runs, classes, runs):\n", + " \"\"\"\n", + " Compute Krippendorff's alpha per class and overall.\n", + " Only evaluates the 6 functional classes — None is derived, not labeled.\n", + " \n", + " Args:\n", + " model_runs: dict {run: filepath}\n", + " classes: list of class names (6 functional classes)\n", + " runs: list of run numbers\n", + " \n", + " Returns:\n", + " dict with per-class and overall alpha\n", + " \"\"\"\n", + " # Load all runs\n", + " run_dfs = {}\n", + " for run in runs:\n", + " run_dfs[run] = load_and_binarize(model_runs[run], classes)\n", + " \n", + " # Verify all runs have same sentences\n", + " n_sentences = len(run_dfs[runs[0]])\n", + " for run in runs:\n", + " assert len(run_dfs[run]) == n_sentences, \\\n", + " f\"Run {run} has {len(run_dfs[run])} sentences, expected {n_sentences}\"\n", + " \n", + " results = {}\n", + " \n", + " # Per-class alpha (6 functional classes only)\n", + " for cls in classes:\n", + " # Reliability matrix: rows = raters (runs), columns = units (sentences)\n", + " reliability_matrix = np.array([\n", + " run_dfs[run][cls].values for run in runs\n", + " ])\n", + " \n", + " # Krippendorff's alpha (nominal level for binary data)\n", + " try:\n", + " alpha = krippendorff.alpha(\n", + " reliability_data=reliability_matrix,\n", + " level_of_measurement='nominal',\n", + " )\n", + " except:\n", + " alpha = np.nan\n", + " \n", + " results[cls] = alpha\n", + " \n", + " # Overall alpha (flatten 6 functional classes into one reliability matrix)\n", + " overall_matrix = np.hstack([\n", + " np.array([run_dfs[run][cls].values for run in runs])\n", + " for cls in classes\n", + " ])\n", + " \n", + " try:\n", + " results['Overall'] = krippendorff.alpha(\n", + " reliability_data=overall_matrix,\n", + " level_of_measurement='nominal',\n", + " )\n", + " except:\n", + " results['Overall'] = np.nan\n", + " \n", + " # Pairwise agreement percentage per class (6 functional classes only)\n", + " pairwise = {}\n", + " for cls in classes:\n", + " agreements = []\n", + " for i, r1 in enumerate(runs):\n", + " for r2 in runs[i+1:]:\n", + " agree = (run_dfs[r1][cls].values == run_dfs[r2][cls].values).mean()\n", + " agreements.append(agree)\n", + " pairwise[cls] = np.mean(agreements)\n", + " pairwise['Overall'] = np.mean([pairwise[cls] for cls in classes])\n", + " \n", + " return results, pairwise, n_sentences\n", + "\n", + "\n", + "# -----------------------------\n", + "# Main Analysis\n", + "# -----------------------------\n", + "\n", + "print(\"=\"*70)\n", + "print(\"INTER-RATER AGREEMENT ANALYSIS (Krippendorff's Alpha)\")\n", + "print(\"=\"*70)\n", + "print(f\"Holdout dir: {HOLDOUT_DIR}\")\n", + "print(f\"Runs: {RUNS}\")\n", + "print(f\"Classes evaluated: {CLASSES} (None excluded — derived, not labeled)\")\n", + "\n", + "# Discover models\n", + "models = discover_models(HOLDOUT_DIR, RUNS)\n", + "\n", + "print(f\"\\nFound {len(models)} model(s) with all {len(RUNS)} runs:\")\n", + "for (vendor, model, mode), paths in models.items():\n", + " print(f\" {vendor} / {model} / {mode}\")\n", + " for run, path in sorted(paths.items()):\n", + " print(f\" Run {run}: {path}\")\n", + "\n", + "# Compute agreement for each model\n", + "all_results = {}\n", + "\n", + "for (vendor, model, mode), paths in models.items():\n", + " model_key = f\"{vendor}_{model}_{mode}\"\n", + " \n", + " print(f\"\\n{'='*70}\")\n", + " print(f\"MODEL: {vendor} / {model} / {mode}\")\n", + " print(f\"{'='*70}\")\n", + " \n", + " alphas, pairwise, n_sentences = compute_agreement(paths, CLASSES, RUNS)\n", + " all_results[model_key] = {'alphas': alphas, 'pairwise': pairwise}\n", + " \n", + " print(f\"Sentences: {n_sentences}\")\n", + " print(f\"Runs compared: {RUNS}\")\n", + " \n", + " # Per-class table (6 functional classes + Overall)\n", + " print(f\"\\n{'Class':<15} {'k-Alpha':>10} {'Agreement Share':>16}\")\n", + " print(\"-\"*45)\n", + " \n", + " for cls in CLASSES + ['Overall']:\n", + " alpha = alphas[cls]\n", + " agree = pairwise[cls]\n", + " \n", + " if cls == 'Overall':\n", + " print(\"-\"*45)\n", + " \n", + " print(f\"{cls:<15} {alpha:>10.4f} {agree:>15.1%}\")\n", + " \n", + " # Interpretation guide\n", + " print(f\"\\nKrippendorff's Alpha Interpretation:\")\n", + " print(f\" α ≥ 0.80 → Reliable agreement\")\n", + " print(f\" α ≥ 0.667 → Tentative agreement (acceptable for some purposes)\")\n", + " print(f\" α < 0.667 → Unreliable / insufficient agreement\")\n", + " print(f\"\\n Note: None class excluded — it is derived (all classes = 0),\")\n", + " print(f\" not independently labeled by the model.\")\n", + "\n", + "# -----------------------------\n", + "# Summary across models\n", + "# -----------------------------\n", + "\n", + "if len(all_results) > 1:\n", + " print(f\"\\n{'='*70}\")\n", + " print(\"SUMMARY ACROSS MODELS\")\n", + " print(f\"{'='*70}\")\n", + " \n", + " summary_rows = []\n", + " for model_key, data in all_results.items():\n", + " row = {'Model': model_key}\n", + " row['Overall_Alpha'] = data['alphas']['Overall']\n", + " row['Overall_Agreement'] = data['pairwise']['Overall']\n", + " for cls in CLASSES:\n", + " row[f'{cls}_Alpha'] = data['alphas'][cls]\n", + " summary_rows.append(row)\n", + " \n", + " df_summary = pd.DataFrame(summary_rows)\n", + " df_summary = df_summary.sort_values('Overall_Alpha', ascending=False)\n", + " \n", + " print(f\"\\n{'Model':<35} {'Overall α':>12} {'Agreement':>12}\")\n", + " print(\"-\"*60)\n", + " for _, row in df_summary.iterrows():\n", + " print(f\"{row['Model']:<35} {row['Overall_Alpha']:>12.4f} {row['Overall_Agreement']:>11.1%}\")\n", + " \n", + " # Save summary\n", + " df_summary.to_csv(f\"{HOLDOUT_DIR}/agreement_summary.csv\", index=False)\n", + " print(f\"\\nSaved summary to {HOLDOUT_DIR}/agreement_summary.csv\")" + ] + }, + { + "cell_type": "markdown", + "id": "b9b669eb-b3ea-4137-8d58-70455261198c", + "metadata": {}, + "source": [ + "# Majority Votes across Runs\n", + "\n", + "- Across runs\n", + "- Does not handle ties yet (assumes odd number of total runs)\n", + "- Assumes multi-label problem (one sentence can have multiple labels)\n", + "- Assumes that if majority is [] (none), then all other classes must be negative (0 or FALSE) " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3526fb48-f557-4025-b228-f4f75915abc2", + "metadata": {}, + "outputs": [], + "source": [ + "# =============================================================================\n", + "# MAJORITY VOTE PER MODEL (across its own runs)\n", + "# =============================================================================\n", + "\n", + "import pandas as pd\n", + "import numpy as np\n", + "import glob\n", + "import ast\n", + "import re\n", + "import os\n", + "\n", + "# -----------------------------\n", + "# Configuration\n", + "# -----------------------------\n", + "\n", + "HOLDOUT_DIR = \"./output/holdout\" # Where Run1/, Run2/, Run3/ etc. are\n", + "RUNS = [1, 2, 3] # Which runs to aggregate\n", + "CLASSES = [\"Marketing\", \"Finance\", \"Accounting\", \"Operations\", \"IT\", \"HR\"]\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "95aa527c-daa4-4063-a5e1-fc438f2f76fb", + "metadata": {}, + "outputs": [], + "source": [ + "# -----------------------------\n", + "# Helper Functions\n", + "# -----------------------------\n", + "\n", + "def parse_labels_safe(labels):\n", + " \"\"\"Parse labels from various formats.\"\"\"\n", + " if labels is None:\n", + " return []\n", + " if isinstance(labels, list):\n", + " return labels\n", + " if isinstance(labels, str):\n", + " try:\n", + " parsed = ast.literal_eval(labels)\n", + " return parsed if isinstance(parsed, list) else []\n", + " except:\n", + " return []\n", + " return []\n", + "\n", + "def parse_filename(filename):\n", + " \"\"\"\n", + " Parse filename like 'holdout_azure_gpt-4.1_chat_run1.pkl'\n", + " into (vendor, model, mode, run).\n", + " Handles optional dataset prefix (holdout_, train_, prelim_, output_).\n", + " \"\"\"\n", + " name = filename.replace('.pkl', '').replace('.csv', '')\n", + " \n", + " # Strip known dataset prefixes\n", + " for prefix in ['holdout_', 'train_', 'prelim_', 'output_']:\n", + " if name.startswith(prefix):\n", + " name = name[len(prefix):]\n", + " break\n", + " \n", + " match = re.search(r'_run(\\d+)$', name)\n", + " if not match:\n", + " return None\n", + " run = int(match.group(1))\n", + " name = name[:match.start()]\n", + " parts = name.rsplit('_', 1)\n", + " if len(parts) != 2:\n", + " return None\n", + " mode = parts[1]\n", + " remainder = parts[0]\n", + " first_underscore = remainder.index('_')\n", + " vendor = remainder[:first_underscore]\n", + " model = remainder[first_underscore + 1:]\n", + " return vendor, model, mode, run\n", + "\n", + "def discover_models(holdout_dir, runs):\n", + " \"\"\"Find all vendor_model_mode combos that have ALL specified runs.\"\"\"\n", + " models = {}\n", + " for run in runs:\n", + " run_dir = f\"{holdout_dir}/Run{run}\"\n", + " if not os.path.exists(run_dir):\n", + " continue\n", + " for filepath in glob.glob(f\"{run_dir}/*.pkl\"):\n", + " filename = filepath.split(\"/\")[-1]\n", + " parsed = parse_filename(filename)\n", + " if parsed is None:\n", + " continue\n", + " vendor, model, mode, file_run = parsed\n", + " if file_run != run:\n", + " continue\n", + " key = (vendor, model, mode)\n", + " if key not in models:\n", + " models[key] = {}\n", + " models[key][run] = filepath\n", + " \n", + " # Keep only models with ALL specified runs\n", + " return {k: v for k, v in models.items() if all(r in v for r in runs)}\n", + "\n", + "def compute_majority_vote(model_runs, classes, runs):\n", + " \"\"\"\n", + " Compute majority vote for a single model across its runs.\n", + " \n", + " Votes are counted for the 6 functional classes only.\n", + " None is derived: if no functional class gets majority, None = 1.\n", + " None_votes tracks how many runs returned an empty label list (for reference).\n", + " \n", + " Returns DataFrame with sentence + binary labels + vote counts.\n", + " \"\"\"\n", + " # Load all runs\n", + " run_dfs = {}\n", + " for run in runs:\n", + " run_dfs[run] = pd.read_pickle(model_runs[run])\n", + " \n", + " # Collect votes per sentence\n", + " votes = {}\n", + " for run in runs:\n", + " df = run_dfs[run]\n", + " for _, row in df.iterrows():\n", + " sent_id = row['id']\n", + " sentence = row['sentence']\n", + " labels = parse_labels_safe(row['labels'])\n", + " \n", + " # Skip error rows\n", + " if 'error' in df.columns and pd.notna(row.get('error')):\n", + " continue\n", + " \n", + " if sent_id not in votes:\n", + " votes[sent_id] = {\n", + " 'sentence': sentence,\n", + " **{cls: 0 for cls in classes},\n", + " 'none_runs': 0,\n", + " 'total_runs': 0,\n", + " }\n", + " \n", + " votes[sent_id]['total_runs'] += 1\n", + " \n", + " if len(labels) == 0:\n", + " votes[sent_id]['none_runs'] += 1\n", + " else:\n", + " for label in labels:\n", + " if label in classes:\n", + " votes[sent_id][label] += 1\n", + " \n", + " # Calculate majority\n", + " results = []\n", + " for sent_id, data in votes.items():\n", + " total = data['total_runs']\n", + " threshold = total / 2 # > 50%\n", + " \n", + " row = {'id': sent_id, 'sentence': data['sentence']}\n", + " \n", + " # Majority vote on 6 functional classes\n", + " for cls in classes:\n", + " row[cls] = 1 if data[cls] > threshold else 0\n", + " \n", + " # None is derived: all functional classes = 0\n", + " row['None'] = 1 if all(row[cls] == 0 for cls in classes) else 0\n", + " \n", + " # Vote counts (for reference / pseudo-probabilities)\n", + " for cls in classes:\n", + " row[f'{cls}_votes'] = data[cls]\n", + " row['None_votes'] = data['none_runs']\n", + " row['total_runs'] = total\n", + " \n", + " results.append(row)\n", + " \n", + " df_result = pd.DataFrame(results)\n", + " label_cols = classes + ['None']\n", + " vote_cols = [f'{cls}_votes' for cls in classes] + ['None_votes', 'total_runs']\n", + " df_result = df_result[['id', 'sentence'] + label_cols + vote_cols]\n", + " df_result = df_result.sort_values('id').reset_index(drop=True)\n", + " \n", + " return df_result\n", + "\n", + "# -----------------------------\n", + "# Main\n", + "# -----------------------------\n", + "\n", + "print(\"=\"*70)\n", + "print(\"MAJORITY VOTE PER MODEL\")\n", + "print(\"=\"*70)\n", + "print(f\"Holdout dir: {HOLDOUT_DIR}\")\n", + "print(f\"Runs: {RUNS}\")\n", + "\n", + "# Discover models\n", + "models = discover_models(HOLDOUT_DIR, RUNS)\n", + "\n", + "print(f\"\\nFound {len(models)} model(s) with all {len(RUNS)} runs:\")\n", + "for (vendor, model, mode), paths in models.items():\n", + " print(f\" {vendor} / {model} / {mode}\")\n", + "\n", + "# Process each model\n", + "all_majority = {}\n", + "\n", + "for (vendor, model, mode), paths in models.items():\n", + " model_key = f\"{vendor}_{model}_{mode}\"\n", + " \n", + " print(f\"\\n{'='*70}\")\n", + " print(f\"MODEL: {vendor} / {model} / {mode}\")\n", + " print(f\"{'='*70}\")\n", + " \n", + " # Compute majority vote\n", + " df_mv = compute_majority_vote(paths, CLASSES, RUNS)\n", + " all_majority[model_key] = df_mv\n", + " \n", + " # Report\n", + " print(f\"Total sentences: {len(df_mv)}\")\n", + " print(f\"Runs per sentence: {df_mv['total_runs'].iloc[0]}\")\n", + " \n", + " print(f\"\\n{'Class':<15} {'Count':>8} {'Share':>10}\")\n", + " print(\"-\"*35)\n", + " for cls in CLASSES:\n", + " count = df_mv[cls].sum()\n", + " share = count / len(df_mv) * 100\n", + " print(f\"{cls:<15} {count:>8} {share:>9.1f}%\")\n", + " \n", + " # None (derived)\n", + " none_count = df_mv['None'].sum()\n", + " none_share = none_count / len(df_mv) * 100\n", + " print(\"-\"*35)\n", + " print(f\"{'None (derived)':<15} {none_count:>8} {none_share:>9.1f}%\")\n", + " \n", + " # Multi-label distribution\n", + " num_labels = df_mv[CLASSES].sum(axis=1)\n", + " print(f\"\\n{'# Labels':<15} {'Count':>8} {'Share':>10}\")\n", + " print(\"-\"*35)\n", + " for n in range(7):\n", + " count = (num_labels == n).sum()\n", + " if count > 0:\n", + " share = count / len(df_mv) * 100\n", + " label_text = f\"{n} label{'s' if n != 1 else ''}\"\n", + " print(f\"{label_text:<15} {count:>8} {share:>9.1f}%\")\n", + " \n", + " # Save (with dataset prefix for consistency)\n", + " dataset_tag = os.path.basename(os.path.normpath(HOLDOUT_DIR)).lower()\n", + " save_path = f\"{HOLDOUT_DIR}/{dataset_tag}_{model_key}_majority_vote\"\n", + " df_mv.to_csv(f\"{save_path}.csv\", index=False)\n", + " df_mv.to_pickle(f\"{save_path}.pkl\")\n", + " print(f\"\\nSaved: {save_path}.csv (.pkl)\")\n", + "\n", + "# -----------------------------\n", + "# Summary across models\n", + "# -----------------------------\n", + "\n", + "if len(all_majority) > 1:\n", + " print(f\"\\n{'='*70}\")\n", + " print(\"COMPARISON ACROSS MODELS\")\n", + " print(f\"{'='*70}\")\n", + " \n", + " # Header\n", + " model_keys = list(all_majority.keys())\n", + " header = f\"{'Class':<15}\"\n", + " for key in model_keys:\n", + " short = key.split('_', 1)[1] # Remove vendor prefix for display\n", + " header += f\" {short:>20}\"\n", + " print(header)\n", + " print(\"-\" * (15 + 21 * len(model_keys)))\n", + " \n", + " for cls in CLASSES:\n", + " row = f\"{cls:<15}\"\n", + " for key in model_keys:\n", + " df_mv = all_majority[key]\n", + " count = df_mv[cls].sum()\n", + " share = count / len(df_mv) * 100\n", + " row += f\" {count:>8} ({share:>5.1f}%)\"\n", + " print(row)\n", + " \n", + " # None row\n", + " row = f\"{'None (derived)':<15}\"\n", + " for key in model_keys:\n", + " df_mv = all_majority[key]\n", + " count = df_mv['None'].sum()\n", + " share = count / len(df_mv) * 100\n", + " row += f\" {count:>8} ({share:>5.1f}%)\"\n", + " print(\"-\" * (15 + 21 * len(model_keys)))\n", + " print(row)\n", + "\n", + "print(f\"\\n{'='*70}\")\n", + "print(\"DONE\")\n", + "print(f\"{'='*70}\")" + ] + }, + { + "cell_type": "markdown", + "id": "4222ebe5-8ee4-444d-9d43-26a155112487", + "metadata": {}, + "source": [ + "# genAI Model Performance\n", + "\n", + "- Check genAI majority labels against ground truth from human experts" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "820abbf4-8938-4c3f-bfa0-a458a4841f5a", + "metadata": {}, + "outputs": [], + "source": [ + "# =============================================================================\n", + "# EVALUATE GenAI MODELS vs HUMAN LABELS ON HOLDOUT\n", + "# =============================================================================\n", + "\n", + "import pandas as pd\n", + "import numpy as np\n", + "import glob\n", + "import json\n", + "from sklearn.metrics import (\n", + " f1_score,\n", + " roc_auc_score,\n", + " matthews_corrcoef,\n", + " precision_score,\n", + " recall_score,\n", + " confusion_matrix,\n", + " hamming_loss,\n", + " jaccard_score,\n", + ")\n", + "\n", + "# -----------------------------\n", + "# Configuration\n", + "# -----------------------------\n", + "\n", + "HOLDOUT_DIR = \"./output/holdout\" # Where model majority vote files are\n", + "HUMAN_LABELS_PATH = \"./Holdout_Train/holdout_human.pkl\" # Ground truth\n", + "CLASSES = [\"Marketing\", \"Finance\", \"Accounting\", \"Operations\", \"IT\", \"HR\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4ffde335-fa5c-4944-a0ff-1b25fbd054d9", + "metadata": {}, + "outputs": [], + "source": [ + "# -----------------------------\n", + "# Load Human Labels (Ground Truth)\n", + "# -----------------------------\n", + "\n", + "print(\"=\"*70)\n", + "print(\"EVALUATE GenAI MODELS vs HUMAN LABELS\")\n", + "print(\"=\"*70)\n", + "\n", + "df_human = pd.read_pickle(HUMAN_LABELS_PATH)\n", + "print(f\"Human-labeled holdout: {len(df_human)} sentences\")\n", + "print(f\"Source: {HUMAN_LABELS_PATH}\")\n", + "\n", + "print(f\"\\nHuman label distribution:\")\n", + "for cls in CLASSES:\n", + " count = df_human[cls].sum()\n", + " share = count / len(df_human) * 100\n", + " print(f\" {cls}: {int(count)} ({share:.1f}%)\")\n", + "none_count = (df_human[CLASSES].sum(axis=1) == 0).sum()\n", + "print(f\" None (derived): {none_count} ({none_count / len(df_human) * 100:.1f}%)\")\n", + "\n", + "# -----------------------------\n", + "# Discover Model Majority Vote Files\n", + "# -----------------------------\n", + "\n", + "mv_files = glob.glob(f\"{HOLDOUT_DIR}/*_majority_vote.pkl\")\n", + "print(f\"\\nFound {len(mv_files)} model majority vote file(s):\")\n", + "for f in mv_files:\n", + " print(f\" {f.split('/')[-1]}\")\n", + "\n", + "# -----------------------------\n", + "# Evaluation Functions\n", + "# -----------------------------\n", + "\n", + "def evaluate_multilabel(y_true, y_pred, class_names):\n", + " \"\"\"\n", + " Comprehensive multi-label evaluation on the 6 functional classes.\n", + " \n", + " Each label is an independent binary decision.\n", + " None is derived (all classes = 0), not independently predicted,\n", + " so it is excluded from macro averaging but reported separately.\n", + " No AUC: requires continuous probabilities, not available for binary GenAI predictions.\n", + " \"\"\"\n", + " # Per-class metrics (6 functional classes)\n", + " per_class = {}\n", + " for i, cls in enumerate(class_names):\n", + " y_t = y_true[:, i]\n", + " y_p = y_pred[:, i]\n", + " \n", + " per_class[cls] = {\n", + " 'f1': f1_score(y_t, y_p, zero_division=0),\n", + " 'precision': precision_score(y_t, y_p, zero_division=0),\n", + " 'recall': recall_score(y_t, y_p, zero_division=0),\n", + " 'mcc': matthews_corrcoef(y_t, y_p),\n", + " 'support_true': int(y_t.sum()),\n", + " 'support_pred': int(y_p.sum()),\n", + " }\n", + " \n", + " # Macro averages (6 functional classes only)\n", + " macro = {\n", + " 'f1_macro': np.mean([per_class[c]['f1'] for c in class_names]),\n", + " 'precision_macro': np.mean([per_class[c]['precision'] for c in class_names]),\n", + " 'recall_macro': np.mean([per_class[c]['recall'] for c in class_names]),\n", + " 'mcc_macro': np.mean([per_class[c]['mcc'] for c in class_names]),\n", + " }\n", + " \n", + " # Micro averages (pooled across 6 classes)\n", + " micro = {\n", + " 'f1_micro': f1_score(y_true, y_pred, average='micro', zero_division=0),\n", + " 'precision_micro': precision_score(y_true, y_pred, average='micro', zero_division=0),\n", + " 'recall_micro': recall_score(y_true, y_pred, average='micro', zero_division=0),\n", + " }\n", + " \n", + " # Sample-based metrics (per sentence, 6 classes)\n", + " # Note: sentences where both true and predicted are all-zero (None) score 0/0.\n", + " # Using zero_division=1 so correct \"None\" predictions score 1.0, not 0.0.\n", + " sample = {\n", + " 'f1_samples': f1_score(y_true, y_pred, average='samples', zero_division=1),\n", + " 'jaccard_samples': jaccard_score(y_true, y_pred, average='samples', zero_division=1),\n", + " }\n", + " \n", + " # Overall metrics\n", + " overall = {\n", + " 'exact_match_ratio': (y_pred == y_true).all(axis=1).mean(),\n", + " 'hamming_loss': hamming_loss(y_true, y_pred),\n", + " }\n", + " \n", + " # None class (derived: all classes = 0, reported separately)\n", + " none_true = (y_true.sum(axis=1) == 0).astype(int)\n", + " none_pred = (y_pred.sum(axis=1) == 0).astype(int)\n", + " \n", + " none = {\n", + " 'f1': f1_score(none_true, none_pred, zero_division=0),\n", + " 'precision': precision_score(none_true, none_pred, zero_division=0),\n", + " 'recall': recall_score(none_true, none_pred, zero_division=0),\n", + " 'mcc': matthews_corrcoef(none_true, none_pred),\n", + " 'support_true': int(none_true.sum()),\n", + " 'support_pred': int(none_pred.sum()),\n", + " }\n", + " \n", + " return {\n", + " 'per_class': per_class,\n", + " 'macro': macro,\n", + " 'micro': micro,\n", + " 'sample': sample,\n", + " 'overall': overall,\n", + " 'none': none,\n", + " }\n", + "\n", + "\n", + "def print_evaluation_report(model_name, metrics, class_names):\n", + " \"\"\"Print formatted evaluation report for one model.\"\"\"\n", + " \n", + " print(f\"\\n{'='*70}\")\n", + " print(f\"MODEL: {model_name}\")\n", + " print(f\"{'='*70}\")\n", + " \n", + " # Per-class table\n", + " print(f\"\\n{'Class':<12} {'F1':>7} {'MCC':>7} {'Prec':>7} {'Rec':>7} {'True':>6} {'Pred':>6}\")\n", + " print(\"-\"*58)\n", + " \n", + " for cls in class_names:\n", + " m = metrics['per_class'][cls]\n", + " print(f\"{cls:<12} {m['f1']:>7.4f} {m['mcc']:>7.4f} \"\n", + " f\"{m['precision']:>7.4f} {m['recall']:>7.4f} {m['support_true']:>6} {m['support_pred']:>6}\")\n", + " \n", + " # None (derived, separate from macro)\n", + " print(\"-\"*58)\n", + " n = metrics['none']\n", + " print(f\"{'None':<12} {n['f1']:>7.4f} {n['mcc']:>7.4f} \"\n", + " f\"{n['precision']:>7.4f} {n['recall']:>7.4f} {n['support_true']:>6} {n['support_pred']:>6}\")\n", + " print(f\"{'':>12} (derived: all classes = 0, excluded from Macro)\")\n", + " \n", + " # Macro averages (6 functional classes)\n", + " print(\"-\"*58)\n", + " m = metrics['macro']\n", + " print(f\"{'Macro Avg':<12} {m['f1_macro']:>7.4f} {m['mcc_macro']:>7.4f} \"\n", + " f\"{m['precision_macro']:>7.4f} {m['recall_macro']:>7.4f}\")\n", + " print(f\"{'(6 classes)':>12}\")\n", + " \n", + " # Summary\n", + " print(\"\\n--- Summary Metrics ---\")\n", + " print(f\" Macro F1: {metrics['macro']['f1_macro']:.4f} ← Primary (class-balanced, 6 classes)\")\n", + " print(f\" Macro MCC: {metrics['macro']['mcc_macro']:.4f} ← Robust to imbalance\")\n", + " print(f\" Micro F1: {metrics['micro']['f1_micro']:.4f} ← Pooled across 6 classes\")\n", + " print(f\" Sample F1: {metrics['sample']['f1_samples']:.4f} ← Per-sentence average\")\n", + " print(f\" Sample Jaccard: {metrics['sample']['jaccard_samples']:.4f} ← Per-sentence |∩|/|∪|\")\n", + " print(f\" Exact Match: {metrics['overall']['exact_match_ratio']:.4f} ← All 6 labels correct\")\n", + " print(f\" Hamming Loss: {metrics['overall']['hamming_loss']:.4f} ← Fraction wrong (lower=better)\")\n", + "\n", + " # Interpretation\n", + " print(\"\\n--- Interpretation ---\")\n", + " gap = metrics['micro']['f1_micro'] - metrics['macro']['f1_macro']\n", + " print(f\" Macro F1 ({metrics['macro']['f1_macro']:.4f}) treats 6 functional classes equally;\")\n", + " print(f\" Micro F1 ({metrics['micro']['f1_micro']:.4f}) pools all labels, weighted by frequency.\")\n", + " if gap > 0.05:\n", + " print(f\" Gap of {gap:.4f} suggests rare classes (IT, HR) drag down Macro F1.\")\n", + " \n", + " print(f\" Sample F1 ({metrics['sample']['f1_samples']:.4f}) and Jaccard ({metrics['sample']['jaccard_samples']:.4f}):\")\n", + " print(f\" Per-sentence evaluation. Correct 'None' predictions (both empty) score 1.0.\")\n", + " print(f\" Exact Match ({metrics['overall']['exact_match_ratio']:.4f}): {metrics['overall']['exact_match_ratio']*100:.1f}% of sentences had ALL labels correct.\")\n", + " print(f\" Binary per sentence: one wrong label fails the entire sentence.\")\n", + " print(f\" Hamming Loss ({metrics['overall']['hamming_loss']:.4f}): {metrics['overall']['hamming_loss']*100:.1f}% of individual label decisions are wrong.\")\n", + " print(f\" MCC ({metrics['macro']['mcc_macro']:.4f}): Balanced metric even with class imbalance. >0.70 is good.\")\n", + " print(f\" None (derived): F1 = {metrics['none']['f1']:.4f}, MCC = {metrics['none']['mcc']:.4f}\")\n", + " print(f\" Not independently predicted — excluded from Macro to avoid inflating scores.\")\n", + "\n", + " # For paper\n", + " print(\"\\n--- For Paper/Report ---\")\n", + " print(f\" Primary: Macro F1 = {metrics['macro']['f1_macro']:.4f}\")\n", + " print(f\" Secondary: Macro MCC = {metrics['macro']['mcc_macro']:.4f}\")\n", + " print(f\" Overall: Exact Match = {metrics['overall']['exact_match_ratio']:.4f}, Hamming Loss = {metrics['overall']['hamming_loss']:.4f}\")\n", + "\n", + "\n", + "# -----------------------------\n", + "# Evaluate Each Model\n", + "# -----------------------------\n", + "\n", + "all_metrics = {}\n", + "\n", + "for mv_file in sorted(mv_files):\n", + " filename = mv_file.split('/')[-1]\n", + " #model_name = filename.replace('_majority_vote.pkl', '')\n", + " model_name = filename.replace('_majority_vote.pkl', '')\n", + " # Strip dataset prefix for clean display\n", + " for prefix in ['holdout_', 'train_', 'prelim_', 'output_']:\n", + " if model_name.startswith(prefix):\n", + " model_name = model_name[len(prefix):]\n", + " break\n", + " \n", + " # Load model predictions\n", + " df_model = pd.read_pickle(mv_file)\n", + " \n", + " # Merge with human labels on sentence (6 functional classes only)\n", + " df_merged = df_human[['sentence'] + CLASSES].merge(\n", + " df_model[['sentence'] + CLASSES],\n", + " on='sentence',\n", + " how='inner',\n", + " suffixes=('_true', '_pred'),\n", + " )\n", + " \n", + " # Check match rate\n", + " match_rate = len(df_merged) / len(df_human) * 100\n", + " print(f\"\\n{'─'*70}\")\n", + " print(f\"Model: {model_name}\")\n", + " print(f\"Matched sentences: {len(df_merged)}/{len(df_human)} ({match_rate:.1f}%)\")\n", + " \n", + " if len(df_merged) == 0:\n", + " print(\" WARNING: No matching sentences! Skipping.\")\n", + " continue\n", + " \n", + " # Extract true labels (human) — 6 functional classes\n", + " y_true = df_merged[[f'{cls}_true' for cls in CLASSES]].values.astype(int)\n", + " \n", + " # Extract predicted labels (model majority vote) — 6 functional classes\n", + " y_pred = df_merged[[f'{cls}_pred' for cls in CLASSES]].values.astype(int)\n", + " \n", + " # Evaluate\n", + " metrics = evaluate_multilabel(y_true, y_pred, CLASSES)\n", + " all_metrics[model_name] = metrics\n", + " \n", + " # Print report\n", + " print_evaluation_report(model_name, metrics, CLASSES)\n", + " \n", + " # Confusion matrices\n", + " print(f\"\\n--- Confusion Matrices ---\")\n", + " print(f\" {'Class':<12} {'TP':>6} {'TN':>6} {'FP':>6} {'FN':>6}\")\n", + " print(f\" {'-'*38}\")\n", + " \n", + " for i, cls in enumerate(CLASSES):\n", + " cm = confusion_matrix(y_true[:, i], y_pred[:, i])\n", + " tn, fp, fn, tp = cm.ravel()\n", + " print(f\" {cls:<12} {tp:>6} {tn:>6} {fp:>6} {fn:>6}\")\n", + " \n", + " # None confusion matrix (derived)\n", + " none_true = (y_true.sum(axis=1) == 0).astype(int)\n", + " none_pred = (y_pred.sum(axis=1) == 0).astype(int)\n", + " none_cm = confusion_matrix(none_true, none_pred)\n", + " none_tn, none_fp, none_fn, none_tp = none_cm.ravel()\n", + " print(f\" {'-'*38}\")\n", + " print(f\" {'None':<12} {none_tp:>6} {none_tn:>6} {none_fp:>6} {none_fn:>6}\")\n", + "\n", + "# -----------------------------\n", + "# Comparison Summary\n", + "# -----------------------------\n", + "\n", + "if len(all_metrics) > 1:\n", + " print(f\"\\n{'='*70}\")\n", + " print(\"MODEL COMPARISON SUMMARY\")\n", + " print(f\"{'='*70}\")\n", + " \n", + " # Summary table\n", + " print(f\"\\n{'Model':<40} {'F1 Mac':>8} {'MCC Mac':>8} {'Exact':>8} {'Hamming':>8}\")\n", + " print(\"-\"*68)\n", + " \n", + " summary_rows = []\n", + " for model_name, metrics in sorted(all_metrics.items(), \n", + " key=lambda x: x[1]['macro']['f1_macro'], \n", + " reverse=True):\n", + " m = metrics['macro']\n", + " o = metrics['overall']\n", + " print(f\"{model_name:<40} {m['f1_macro']:>8.4f} {m['mcc_macro']:>8.4f} \"\n", + " f\"{o['exact_match_ratio']:>8.4f} {o['hamming_loss']:>8.4f}\")\n", + " \n", + " summary_rows.append({\n", + " 'model': model_name,\n", + " 'f1_macro': m['f1_macro'],\n", + " 'mcc_macro': m['mcc_macro'],\n", + " 'f1_micro': metrics['micro']['f1_micro'],\n", + " 'f1_samples': metrics['sample']['f1_samples'],\n", + " 'jaccard_samples': metrics['sample']['jaccard_samples'],\n", + " 'exact_match': o['exact_match_ratio'],\n", + " 'hamming_loss': o['hamming_loss'],\n", + " 'none_f1': metrics['none']['f1'],\n", + " 'none_mcc': metrics['none']['mcc'],\n", + " })\n", + " \n", + " # Per-class F1 comparison\n", + " print(f\"\\n--- Per-Class F1 Comparison ---\")\n", + " header = f\"{'Class':<12}\"\n", + " for model_name in sorted(all_metrics.keys()):\n", + " short = model_name.replace('azure_', '').replace('fireworks_', 'fw_')\n", + " header += f\" {short:>20}\"\n", + " print(header)\n", + " print(\"-\" * (12 + 21 * len(all_metrics)))\n", + " \n", + " for cls in CLASSES + ['None', 'Macro Avg']:\n", + " row = f\"{cls:<12}\"\n", + " if cls == 'None':\n", + " row = f\"{'-'*12}\\n{cls:<12}\"\n", + " for model_name in sorted(all_metrics.keys()):\n", + " if cls == 'Macro Avg':\n", + " val = all_metrics[model_name]['macro']['f1_macro']\n", + " elif cls == 'None':\n", + " val = all_metrics[model_name]['none']['f1']\n", + " else:\n", + " val = all_metrics[model_name]['per_class'][cls]['f1']\n", + " row += f\" {val:>20.4f}\"\n", + " print(row)\n", + " \n", + " # Save comparison\n", + " df_summary = pd.DataFrame(summary_rows).sort_values('f1_macro', ascending=False)\n", + " df_summary.to_csv(f\"{HOLDOUT_DIR}/model_vs_human_comparison.csv\", index=False)\n", + " print(f\"\\nSaved comparison to {HOLDOUT_DIR}/model_vs_human_comparison.csv\")\n", + "\n", + "# -----------------------------\n", + "# Save all metrics\n", + "# -----------------------------\n", + "\n", + "def convert_for_json(obj):\n", + " \"\"\"Convert numpy types for JSON serialization.\"\"\"\n", + " if isinstance(obj, (np.integer,)):\n", + " return int(obj)\n", + " if isinstance(obj, (np.floating,)):\n", + " return float(obj)\n", + " if isinstance(obj, np.ndarray):\n", + " return obj.tolist()\n", + " if isinstance(obj, dict):\n", + " return {k: convert_for_json(v) for k, v in obj.items()}\n", + " return obj\n", + "\n", + "all_metrics_json = convert_for_json(all_metrics)\n", + "with open(f\"{HOLDOUT_DIR}/model_vs_human_metrics.json\", 'w') as f:\n", + " json.dump(all_metrics_json, f, indent=2)\n", + "print(f\"Saved all metrics to {HOLDOUT_DIR}/model_vs_human_metrics.json\")\n", + "\n", + "print(f\"\\n{'='*70}\")\n", + "print(\"DONE\")\n", + "print(f\"{'='*70}\")" + ] + }, + { + "cell_type": "markdown", + "id": "0af919a8-c95a-4598-847e-142fedee656c", + "metadata": {}, + "source": [ + "# Label Training Data with genAI\n", + "\n", + "- Determine which genAI model (or models) does on holdout\n", + "- Assume that this will also be the best model for labeling the train data\n", + "- Label train data at least 3 times (i.e. 3 runs: [1,2,3] with best genAI model (or models)\n", + "- Build final train set with majority votes across runs (and models if you want to pool genAI models for possibly better performance)\n", + "> I am giving an example here using GPT-4.1. ***This wil most likely not be the best model! Try others on the holdout!***" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "45c897fb-16e2-4ebe-abaf-9ab6be1dffe2", + "metadata": {}, + "outputs": [], + "source": [ + "# =============================================================================\n", + "# OUTPUT CONFIGURATION - SET for Train\n", + "# =============================================================================\n", + "CHECKPOINT_DIR = \"./checkpoints\"\n", + "OUTPUT_DIR = \"./output\"\n", + "TRAIN_DIR = f\"{OUTPUT_DIR}/train\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "72367ec1-6d23-44e3-81f5-826f53518666", + "metadata": {}, + "outputs": [], + "source": [ + "# =============================================================================\n", + "# Load Train dataset\n", + "# =============================================================================\n", + "\n", + "# # Load Data: Labeling of (balanced) holdout data\n", + "df = pd.read_pickle(\"Holdout_Train/train.pkl\")\n", + "df = df.head(101)\n", + "\n", + "# =============================================================================\n", + "# Query genAI model via API\n", + "# =============================================================================\n", + "\n", + "# Here an example for gpt-4.1 via UNC Azure API. \n", + "# Most likely, this will not be the best model! Try other vendors and other models.\n", + "results = run_classification(\n", + " df,\n", + " sentence_col=\"sentence\", # --> Check if your file has the column as named here where the text is (sentence vs sentences vs text vs tweet vs ... )\n", + " vendor=\"azure\",\n", + " model=\"gpt-4.1\",\n", + " runs=[1,2,3], # Doing 3 runs for conistency / replicability: will later take majority vote per lable across runs\n", + " output_dir=TRAIN_DIR, # overrides default: OUTPUT_DIR vs. HOLDOUT_DIR vs. TRAIN_DIR vs. PRELIM_DIR\n", + " checkpoint_dir=CHECKPOINT_DIR, # overrides default\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "16420fc3-a55a-4e90-a306-38f52ff8a3f6", + "metadata": {}, + "source": [ + "# Majority Votes\n", + "\n", + "- Across Runs\n", + "- If you are ***pooling models***, then you need to also do this ***Across Models***: THIS CODE DOES NOT DO THAT!\n", + "- Does not handle ties yet (assumes odd number of total runs across models)\n", + "- Assumes multi-label problem (one sentence can have multiple labels)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "45172423-8146-478a-bfcf-7060e52f60c0", + "metadata": {}, + "outputs": [], + "source": [ + "# =============================================================================\n", + "# MAJORITY VOTE PER MODEL (across its own runs)\n", + "# =============================================================================\n", + "\n", + "import pandas as pd\n", + "import numpy as np\n", + "import glob\n", + "import ast\n", + "import re\n", + "import os\n", + "\n", + "# -----------------------------\n", + "# Configuration\n", + "# -----------------------------\n", + "\n", + "TRAIN_DIR = \"./output/train\" # Now pointing to train (all code is the same, but we are sing a differnt folder for the files\n", + "RUNS = [1, 2, 3]\n", + "CLASSES = [\"Marketing\", \"Finance\", \"Accounting\", \"Operations\", \"IT\", \"HR\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "07170d67-f36c-45c6-a41c-2843cc5c52e0", + "metadata": {}, + "outputs": [], + "source": [ + "# -----------------------------\n", + "# Helper Functions\n", + "# -----------------------------\n", + "\n", + "def parse_labels_safe(labels):\n", + " \"\"\"Parse labels from various formats.\"\"\"\n", + " if labels is None:\n", + " return []\n", + " if isinstance(labels, list):\n", + " return labels\n", + " if isinstance(labels, str):\n", + " try:\n", + " parsed = ast.literal_eval(labels)\n", + " return parsed if isinstance(parsed, list) else []\n", + " except:\n", + " return []\n", + " return []\n", + "\n", + "def parse_filename(filename):\n", + " \"\"\"\n", + " Parse filename like 'train_azure_gpt-4.1_chat_run1.pkl'\n", + " into (vendor, model, mode, run).\n", + " Handles optional dataset prefix (holdout_, train_, prelim_, output_).\n", + " \"\"\"\n", + " name = filename.replace('.pkl', '').replace('.csv', '')\n", + " \n", + " # Strip known dataset prefixes\n", + " for prefix in ['holdout_', 'train_', 'prelim_', 'output_']:\n", + " if name.startswith(prefix):\n", + " name = name[len(prefix):]\n", + " break\n", + " \n", + " match = re.search(r'_run(\\d+)$', name)\n", + " if not match:\n", + " return None\n", + " run = int(match.group(1))\n", + " name = name[:match.start()]\n", + " parts = name.rsplit('_', 1)\n", + " if len(parts) != 2:\n", + " return None\n", + " mode = parts[1]\n", + " remainder = parts[0]\n", + " first_underscore = remainder.index('_')\n", + " vendor = remainder[:first_underscore]\n", + " model = remainder[first_underscore + 1:]\n", + " return vendor, model, mode, run\n", + "\n", + "def discover_models(train_dir, runs):\n", + " \"\"\"Find all vendor_model_mode combos that have ALL specified runs.\"\"\"\n", + " models = {}\n", + " for run in runs:\n", + " run_dir = f\"{train_dir}/Run{run}\"\n", + " if not os.path.exists(run_dir):\n", + " continue\n", + " for filepath in glob.glob(f\"{run_dir}/*.pkl\"):\n", + " filename = filepath.split(\"/\")[-1]\n", + " parsed = parse_filename(filename)\n", + " if parsed is None:\n", + " continue\n", + " vendor, model, mode, file_run = parsed\n", + " if file_run != run:\n", + " continue\n", + " key = (vendor, model, mode)\n", + " if key not in models:\n", + " models[key] = {}\n", + " models[key][run] = filepath\n", + " \n", + " # Keep only models with ALL specified runs\n", + " return {k: v for k, v in models.items() if all(r in v for r in runs)}\n", + "\n", + "def compute_majority_vote(model_runs, classes, runs):\n", + " \"\"\"\n", + " Compute majority vote for a single model across its runs.\n", + " \n", + " Votes are counted for the 6 functional classes only.\n", + " None is derived: if no functional class gets majority, None = 1.\n", + " None_votes tracks how many runs returned an empty label list (for reference).\n", + " \n", + " Returns DataFrame with sentence + binary labels + vote counts.\n", + " \"\"\"\n", + " # Load all runs\n", + " run_dfs = {}\n", + " for run in runs:\n", + " run_dfs[run] = pd.read_pickle(model_runs[run])\n", + " \n", + " # Collect votes per sentence\n", + " votes = {}\n", + " for run in runs:\n", + " df = run_dfs[run]\n", + " for _, row in df.iterrows():\n", + " sent_id = row['id']\n", + " sentence = row['sentence']\n", + " labels = parse_labels_safe(row['labels'])\n", + " \n", + " # Skip error rows\n", + " if 'error' in df.columns and pd.notna(row.get('error')):\n", + " continue\n", + " \n", + " if sent_id not in votes:\n", + " votes[sent_id] = {\n", + " 'sentence': sentence,\n", + " **{cls: 0 for cls in classes},\n", + " 'none_runs': 0,\n", + " 'total_runs': 0,\n", + " }\n", + " \n", + " votes[sent_id]['total_runs'] += 1\n", + " \n", + " if len(labels) == 0:\n", + " votes[sent_id]['none_runs'] += 1\n", + " else:\n", + " for label in labels:\n", + " if label in classes:\n", + " votes[sent_id][label] += 1\n", + " \n", + " # Calculate majority\n", + " results = []\n", + " for sent_id, data in votes.items():\n", + " total = data['total_runs']\n", + " threshold = total / 2 # > 50%\n", + " \n", + " row = {'id': sent_id, 'sentence': data['sentence']}\n", + " \n", + " # Majority vote on 6 functional classes\n", + " for cls in classes:\n", + " row[cls] = 1 if data[cls] > threshold else 0\n", + " \n", + " # None is derived: all functional classes = 0\n", + " row['None'] = 1 if all(row[cls] == 0 for cls in classes) else 0\n", + " \n", + " # Vote counts (for reference / pseudo-probabilities)\n", + " for cls in classes:\n", + " row[f'{cls}_votes'] = data[cls]\n", + " row['None_votes'] = data['none_runs']\n", + " row['total_runs'] = total\n", + " \n", + " results.append(row)\n", + " \n", + " df_result = pd.DataFrame(results)\n", + " label_cols = classes + ['None']\n", + " vote_cols = [f'{cls}_votes' for cls in classes] + ['None_votes', 'total_runs']\n", + " df_result = df_result[['id', 'sentence'] + label_cols + vote_cols]\n", + " df_result = df_result.sort_values('id').reset_index(drop=True)\n", + " \n", + " return df_result\n", + "\n", + "# -----------------------------\n", + "# Main\n", + "# -----------------------------\n", + "\n", + "print(\"=\"*70)\n", + "print(\"MAJORITY VOTE PER MODEL\")\n", + "print(\"=\"*70)\n", + "print(f\"Train dir: {TRAIN_DIR}\")\n", + "print(f\"Runs: {RUNS}\")\n", + "\n", + "# Discover models\n", + "models = discover_models(TRAIN_DIR, RUNS)\n", + "\n", + "print(f\"\\nFound {len(models)} model(s) with all {len(RUNS)} runs:\")\n", + "for (vendor, model, mode), paths in models.items():\n", + " print(f\" {vendor} / {model} / {mode}\")\n", + "\n", + "# Process each model\n", + "all_majority = {}\n", + "\n", + "for (vendor, model, mode), paths in models.items():\n", + " model_key = f\"{vendor}_{model}_{mode}\"\n", + " \n", + " print(f\"\\n{'='*70}\")\n", + " print(f\"MODEL: {vendor} / {model} / {mode}\")\n", + " print(f\"{'='*70}\")\n", + " \n", + " # Compute majority vote\n", + " df_mv = compute_majority_vote(paths, CLASSES, RUNS)\n", + " all_majority[model_key] = df_mv\n", + " \n", + " # Report\n", + " print(f\"Total sentences: {len(df_mv)}\")\n", + " print(f\"Runs per sentence: {df_mv['total_runs'].iloc[0]}\")\n", + " \n", + " print(f\"\\n{'Class':<15} {'Count':>8} {'Share':>10}\")\n", + " print(\"-\"*35)\n", + " for cls in CLASSES:\n", + " count = df_mv[cls].sum()\n", + " share = count / len(df_mv) * 100\n", + " print(f\"{cls:<15} {count:>8} {share:>9.1f}%\")\n", + " \n", + " # None (derived)\n", + " none_count = df_mv['None'].sum()\n", + " none_share = none_count / len(df_mv) * 100\n", + " print(\"-\"*35)\n", + " print(f\"{'None (derived)':<15} {none_count:>8} {none_share:>9.1f}%\")\n", + " \n", + " # Multi-label distribution\n", + " num_labels = df_mv[CLASSES].sum(axis=1)\n", + " print(f\"\\n{'# Labels':<15} {'Count':>8} {'Share':>10}\")\n", + " print(\"-\"*35)\n", + " for n in range(7):\n", + " count = (num_labels == n).sum()\n", + " if count > 0:\n", + " share = count / len(df_mv) * 100\n", + " label_text = f\"{n} label{'s' if n != 1 else ''}\"\n", + " print(f\"{label_text:<15} {count:>8} {share:>9.1f}%\")\n", + " \n", + " # Save (with dataset prefix for consistency)\n", + " dataset_tag = os.path.basename(os.path.normpath(TRAIN_DIR)).lower()\n", + " save_path = f\"{TRAIN_DIR}/{dataset_tag}_{model_key}_majority_vote\"\n", + " df_mv.to_csv(f\"{save_path}.csv\", index=False)\n", + " df_mv.to_pickle(f\"{save_path}.pkl\")\n", + " print(f\"\\nSaved: {save_path}.csv (.pkl)\")\n", + "\n", + "# -----------------------------\n", + "# Summary across models\n", + "# -----------------------------\n", + "\n", + "if len(all_majority) > 1:\n", + " print(f\"\\n{'='*70}\")\n", + " print(\"COMPARISON ACROSS MODELS\")\n", + " print(f\"{'='*70}\")\n", + " \n", + " # Header\n", + " model_keys = list(all_majority.keys())\n", + " header = f\"{'Class':<15}\"\n", + " for key in model_keys:\n", + " short = key.split('_', 1)[1] # Remove vendor prefix for display\n", + " header += f\" {short:>20}\"\n", + " print(header)\n", + " print(\"-\" * (15 + 21 * len(model_keys)))\n", + " \n", + " for cls in CLASSES:\n", + " row = f\"{cls:<15}\"\n", + " for key in model_keys:\n", + " df_mv = all_majority[key]\n", + " count = df_mv[cls].sum()\n", + " share = count / len(df_mv) * 100\n", + " row += f\" {count:>8} ({share:>5.1f}%)\"\n", + " print(row)\n", + " \n", + " # None row\n", + " row = f\"{'None (derived)':<15}\"\n", + " for key in model_keys:\n", + " df_mv = all_majority[key]\n", + " count = df_mv['None'].sum()\n", + " share = count / len(df_mv) * 100\n", + " row += f\" {count:>8} ({share:>5.1f}%)\"\n", + " print(\"-\" * (15 + 21 * len(model_keys)))\n", + " print(row)\n", + "\n", + "print(f\"\\n{'='*70}\")\n", + "print(\"DONE\")\n", + "print(f\"{'='*70}\")" + ] + }, + { + "cell_type": "markdown", + "id": "43c77538-5661-4801-ad7f-aaa06c6eb828", + "metadata": {}, + "source": [ + "# Fine-Tune a pretrained LLM to create a Vertical AI model\n", + "- We now have training data for fine-tuning a pretrained LLM (here, RoBERTa Large) to become a classifier for business functions\n", + "- You can experiment with different pretrained LLMs on Huggingface that may be more appropriate for your fine-tuning purpose:\n", + "> https://huggingface.co/models?pipeline_tag=fill-mask&library=transformers&sort=trending" + ] + }, + { + "cell_type": "markdown", + "id": "2ac54fc6-18a0-4577-941c-4aac33d2dd07", + "metadata": {}, + "source": [ + "### **IMPORTANT**: There is a hyperparameter that determines how long text (in tokens) can be at most for fine-tuning.\n", + "```\n", + "MAX_LENGTH = 128 # max length of sentences in tokens\n", + "```\n", + "> * I set it to 128. If your texts are longer, you need to change that because it will be truncated! \n", + "> * The larger the max length is, the slower the training process. \n", + "> * Why? See class 8 on Deep Learning. Hint: When you have more input tokens, more needs to be embedded and contextualized, which takes computer and RAM." + ] + }, + { + "cell_type": "markdown", + "id": "a912ff49-3530-42a4-bbc8-624b9b7b695f", + "metadata": {}, + "source": [ + "## Part 1: Imports and Configuration\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "42db0c31-14f2-4354-9e51-cc81a1ca85bc", + "metadata": {}, + "outputs": [], + "source": [ + "# Install if needed:\n", + "# pip install -q -U transformers datasets accelerate scikit-learn\n", + "\n", + "import os\n", + "import torch\n", + "import numpy as np\n", + "import pandas as pd\n", + "import json\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import (\n", + " f1_score,\n", + " roc_auc_score,\n", + " matthews_corrcoef,\n", + " precision_score,\n", + " recall_score,\n", + " classification_report,\n", + " confusion_matrix,\n", + " hamming_loss,\n", + " jaccard_score,\n", + ")\n", + "from transformers import (\n", + " RobertaTokenizer,\n", + " RobertaForSequenceClassification,\n", + " Trainer,\n", + " TrainingArguments,\n", + " EarlyStoppingCallback,\n", + ")\n", + "from datasets import Dataset\n", + "import warnings\n", + "warnings.filterwarnings('ignore')\n", + "\n", + "# -----------------------------\n", + "# Configuration\n", + "# -----------------------------\n", + "\n", + "MODEL_NAME = \"roberta-large\"\n", + "CLASSES = [\"Marketing\", \"Finance\", \"Accounting\", \"Operations\", \"IT\", \"HR\"]\n", + "NUM_LABELS = len(CLASSES)\n", + "\n", + "# Hyperparameters\n", + "LEARNING_RATE = 2e-5\n", + "WEIGHT_DECAY = 0.01\n", + "WARMUP_RATIO = 0.1\n", + "NUM_EPOCHS = 4\n", + "BATCH_SIZE = 32 # Reduce if OOM (out of memory)\n", + "GRADIENT_ACCUMULATION = 2 # Effective batch size = 32 * 2 = 54\n", + "MAX_LENGTH = 128 # max length of sentences in tokens\n", + "SEED = 42\n", + "\n", + "# Early stopping\n", + "EARLY_STOPPING_PATIENCE = 2\n", + "\n", + "# Threshold for binary predictions\n", + "THRESHOLD = 0.5\n", + "\n", + "# Mixed precision (True = faster, less memory; False = more stable)\n", + "USE_MIXED_PRECISION = True\n", + "\n", + "# -----------------------------\n", + "# Device Selection (CUDA > MPS > CPU)\n", + "# -----------------------------\n", + "\n", + "def get_device_and_precision():\n", + " \"\"\"Detect best available device and set precision flags.\"\"\"\n", + " if torch.cuda.is_available():\n", + " device = torch.device(\"cuda\")\n", + " device_name = torch.cuda.get_device_name(0)\n", + " fp16 = USE_MIXED_PRECISION\n", + " bf16 = False\n", + " use_mps = False\n", + " print(f\"Device: CUDA ({device_name})\")\n", + " print(f\" VRAM: {torch.cuda.get_device_properties(0).total_memory / 1e9:.1f} GB\")\n", + " \n", + " elif torch.backends.mps.is_available():\n", + " device = torch.device(\"mps\")\n", + " fp16 = False\n", + " bf16 = USE_MIXED_PRECISION\n", + " use_mps = True\n", + " print(f\"Device: Apple Silicon (MPS)\")\n", + " os.environ[\"PYTORCH_MPS_HIGH_WATERMARK_RATIO\"] = \"0.0\"\n", + " \n", + " else:\n", + " device = torch.device(\"cpu\")\n", + " fp16 = False\n", + " bf16 = False\n", + " use_mps = False\n", + " print(f\"Device: CPU (this will be slow!)\")\n", + " \n", + " precision = \"mixed (fp16)\" if fp16 else \"mixed (bf16)\" if bf16 else \"full (fp32)\"\n", + " print(f\" Precision: {precision}\")\n", + " \n", + " return device, fp16, bf16, use_mps\n", + "\n", + "device, use_fp16, use_bf16, use_mps = get_device_and_precision()\n", + "\n", + "print(f\"\\nConfiguration:\")\n", + "print(f\" Model: {MODEL_NAME}\")\n", + "print(f\" Classes: {CLASSES}\")\n", + "print(f\" Epochs: {NUM_EPOCHS}\")\n", + "print(f\" Batch size: {BATCH_SIZE} x {GRADIENT_ACCUMULATION} = {BATCH_SIZE * GRADIENT_ACCUMULATION}\")\n", + "print(f\" Learning rate: {LEARNING_RATE}\")\n", + "print(f\" Max length: {MAX_LENGTH}\")" + ] + }, + { + "cell_type": "markdown", + "id": "c3c3e7e6-8c47-4690-a490-b49dd3c08edb", + "metadata": {}, + "source": [ + "## Part 2: Prepare Data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "54863fc9-94f2-44ae-8ac8-c80b459b10da", + "metadata": {}, + "outputs": [], + "source": [ + "#!pip install iterative-stratification" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "81180705-cf64-4f5e-acd4-34e20e4cca39", + "metadata": {}, + "outputs": [], + "source": [ + "# -----------------------------\n", + "# Load Data\n", + "# -----------------------------\n", + "\n", + "print(\"=\"*60)\n", + "print(\"LOADING DATA\")\n", + "print(\"=\"*60)\n", + "\n", + "df_train_full = pd.read_pickle(\"./output/train/train_azure_gpt-4.1_chat_majority_vote.pkl\")\n", + "df_holdout = pd.read_pickle(\"./Holdout_Train/holdout_human.pkl\")\n", + "\n", + "print(f\"Train (full): {len(df_train_full)}\")\n", + "print(f\"Holdout: {len(df_holdout)}\")\n", + "\n", + "# -----------------------------\n", + "# Where to save model and results\n", + "# -----------------------------\n", + "model_save_path = \"./roberta_multilabel/best_model\"\n", + "\n", + "\n", + "# -----------------------------\n", + "# Train/Validation Split (90/10)\n", + "# -----------------------------\n", + "\n", + "# Option 1: Iterative stratification (best for multi-label)\n", + "# pip install iterative-stratification\n", + "try:\n", + " from iterstrat.ml_stratifiers import MultilabelStratifiedShuffleSplit\n", + " \n", + " msss = MultilabelStratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=SEED)\n", + " train_idx, val_idx = next(msss.split(df_train_full, df_train_full[CLASSES].values))\n", + " \n", + " df_train = df_train_full.iloc[train_idx].copy()\n", + " df_val = df_train_full.iloc[val_idx].copy()\n", + " print(\"Using: Iterative multi-label stratification\")\n", + "\n", + "except ImportError:\n", + " # Option 2: Simple random split (no stratification)\n", + " df_train, df_val = train_test_split(\n", + " df_train_full, \n", + " test_size=0.2, \n", + " random_state=SEED,\n", + " )\n", + " print(\"Using: Random split (install 'iterative-stratification' for better stratification)\")\n", + "\n", + "print(f\"\\nSplit:\")\n", + "print(f\" Train: {len(df_train)}\")\n", + "print(f\" Validation: {len(df_val)}\")\n", + "print(f\" Holdout: {len(df_holdout)}\")\n", + "\n", + "# -----------------------------\n", + "# Extract Labels\n", + "# -----------------------------\n", + "\n", + "def get_labels_array(df):\n", + " \"\"\"Extract labels as numpy array.\"\"\"\n", + " return df[CLASSES].values.astype(np.float32)\n", + "\n", + "train_labels = get_labels_array(df_train)\n", + "val_labels = get_labels_array(df_val)\n", + "holdout_labels = get_labels_array(df_holdout)\n", + "\n", + "print(f\"\\nLabel shapes:\")\n", + "print(f\" Train: {train_labels.shape}\")\n", + "print(f\" Val: {val_labels.shape}\")\n", + "print(f\" Holdout: {holdout_labels.shape}\")\n", + "\n", + "# Class distribution\n", + "print(f\"\\nTrain class distribution:\")\n", + "for i, cls in enumerate(CLASSES):\n", + " count = train_labels[:, i].sum()\n", + " pct = count / len(train_labels) * 100\n", + " print(f\" {cls}: {int(count)} ({pct:.1f}%)\")\n", + "\n", + "# Verify validation has all classes\n", + "print(f\"\\nValidation class distribution:\")\n", + "for i, cls in enumerate(CLASSES):\n", + " count = val_labels[:, i].sum()\n", + " pct = count / len(val_labels) * 100\n", + " print(f\" {cls}: {int(count)} ({pct:.1f}%)\")\n", + "\n", + "# -----------------------------\n", + "# Tokenization\n", + "# -----------------------------\n", + "\n", + "print(f\"\\n{'='*60}\")\n", + "print(\"TOKENIZATION\")\n", + "print(\"=\"*60)\n", + "\n", + "tokenizer = RobertaTokenizer.from_pretrained(MODEL_NAME)\n", + "\n", + "def tokenize_data(texts, labels):\n", + " \"\"\"Tokenize texts and create HuggingFace Dataset.\"\"\"\n", + " encodings = tokenizer(\n", + " texts.tolist(),\n", + " truncation=True,\n", + " padding='max_length',\n", + " max_length=MAX_LENGTH,\n", + " return_tensors=None,\n", + " )\n", + " \n", + " dataset = Dataset.from_dict({\n", + " 'input_ids': encodings['input_ids'],\n", + " 'attention_mask': encodings['attention_mask'],\n", + " 'labels': labels.tolist(),\n", + " })\n", + " \n", + " return dataset\n", + "\n", + "print(\"Tokenizing datasets...\")\n", + "train_dataset = tokenize_data(df_train['sentence'].values, train_labels)\n", + "val_dataset = tokenize_data(df_val['sentence'].values, val_labels)\n", + "holdout_dataset = tokenize_data(df_holdout['sentence'].values, holdout_labels)\n", + "\n", + "print(f\" Train: {len(train_dataset)}\")\n", + "print(f\" Validation: {len(val_dataset)}\")\n", + "print(f\" Holdout: {len(holdout_dataset)}\")\n", + "\n", + "# Sequence length stats\n", + "train_lengths = [len(ids) for ids in train_dataset['input_ids']]\n", + "print(f\" Sequence lengths: min={min(train_lengths)}, max={max(train_lengths)}, mean={np.mean(train_lengths):.0f}\")" + ] + }, + { + "cell_type": "markdown", + "id": "e9fabf48-8b21-4303-b8d4-cc2d1c4a17cd", + "metadata": {}, + "source": [ + "## PART 3: FINE-TUNE MODEL" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0bdfa218-edd5-41af-bdab-5ccced4510f7", + "metadata": {}, + "outputs": [], + "source": [ + "# -----------------------------\n", + "# Load Model\n", + "# -----------------------------\n", + "\n", + "print(\"=\"*60)\n", + "print(\"MODEL\")\n", + "print(\"=\"*60)\n", + "\n", + "model = RobertaForSequenceClassification.from_pretrained(\n", + " MODEL_NAME,\n", + " num_labels=NUM_LABELS,\n", + " problem_type=\"multi_label_classification\", # Enables BCE loss\n", + ")\n", + "\n", + "if not use_mps:\n", + " model.to(device)\n", + "\n", + "total_params = sum(p.numel() for p in model.parameters())\n", + "trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)\n", + "print(f\"Total parameters: {total_params:,}\")\n", + "print(f\"Trainable parameters: {trainable_params:,}\")\n", + "\n", + "# -----------------------------\n", + "# Metrics Function\n", + "# -----------------------------\n", + "\n", + "def compute_metrics(eval_pred):\n", + " \"\"\"Compute metrics for validation during training.\"\"\"\n", + " logits, labels = eval_pred\n", + " probs = torch.sigmoid(torch.tensor(logits)).numpy()\n", + " preds = (probs >= THRESHOLD).astype(int)\n", + " \n", + " f1_micro = f1_score(labels, preds, average='micro', zero_division=0)\n", + " f1_macro = f1_score(labels, preds, average='macro', zero_division=0)\n", + " f1_samples = f1_score(labels, preds, average='samples', zero_division=0)\n", + " \n", + " try:\n", + " auc_macro = roc_auc_score(labels, probs, average='macro')\n", + " except ValueError:\n", + " auc_macro = 0.0\n", + " \n", + " mcc_scores = []\n", + " for i in range(labels.shape[1]):\n", + " try:\n", + " mcc = matthews_corrcoef(labels[:, i], preds[:, i])\n", + " mcc_scores.append(mcc)\n", + " except:\n", + " mcc_scores.append(0.0)\n", + " mcc_macro = np.mean(mcc_scores)\n", + " \n", + " return {\n", + " 'f1_micro': f1_micro,\n", + " 'f1_macro': f1_macro,\n", + " 'f1_samples': f1_samples,\n", + " 'auc_macro': auc_macro,\n", + " 'mcc_macro': mcc_macro,\n", + " }\n", + "\n", + "# -----------------------------\n", + "# Training Arguments\n", + "# -----------------------------\n", + "\n", + "training_args = TrainingArguments(\n", + " output_dir=\"./roberta_multilabel\",\n", + " \n", + " # Training\n", + " num_train_epochs=NUM_EPOCHS,\n", + " per_device_train_batch_size=BATCH_SIZE,\n", + " per_device_eval_batch_size=BATCH_SIZE * 2,\n", + " gradient_accumulation_steps=GRADIENT_ACCUMULATION,\n", + " \n", + " # Optimizer\n", + " learning_rate=LEARNING_RATE,\n", + " weight_decay=WEIGHT_DECAY,\n", + " warmup_ratio=WARMUP_RATIO,\n", + " optim=\"adamw_torch\",\n", + " lr_scheduler_type=\"linear\",\n", + " max_grad_norm=1.0,\n", + " \n", + " # Evaluation & Saving\n", + " eval_strategy=\"epoch\",\n", + " save_strategy=\"epoch\",\n", + " load_best_model_at_end=True,\n", + " metric_for_best_model=\"f1_macro\",\n", + " greater_is_better=True,\n", + " save_total_limit=2,\n", + " \n", + " # Logging\n", + " logging_dir=\"./logs\",\n", + " logging_steps=50,\n", + " logging_first_step=True,\n", + " report_to=\"none\",\n", + " \n", + " # Precision\n", + " fp16=use_fp16,\n", + " bf16=use_bf16,\n", + " use_mps_device=use_mps,\n", + " \n", + " # Reproducibility\n", + " seed=SEED,\n", + " data_seed=SEED,\n", + " \n", + " # Performance\n", + " dataloader_num_workers=0 if use_mps else 2,\n", + " dataloader_pin_memory=not use_mps,\n", + " remove_unused_columns=False,\n", + ")\n", + "\n", + "# -----------------------------\n", + "# Trainer\n", + "# -----------------------------\n", + "\n", + "trainer = Trainer(\n", + " model=model,\n", + " args=training_args,\n", + " train_dataset=train_dataset,\n", + " eval_dataset=val_dataset,\n", + " compute_metrics=compute_metrics,\n", + " callbacks=[\n", + " EarlyStoppingCallback(early_stopping_patience=EARLY_STOPPING_PATIENCE),\n", + " ],\n", + ")\n", + "\n", + "# -----------------------------\n", + "# Train\n", + "# -----------------------------\n", + "\n", + "print(f\"\\n{'='*60}\")\n", + "print(\"TRAINING\")\n", + "print(\"=\"*60)\n", + "\n", + "train_result = trainer.train()\n", + "\n", + "print(f\"\\n{'='*60}\")\n", + "print(\"TRAINING COMPLETE\")\n", + "print(\"=\"*60)\n", + "print(f\"Runtime: {train_result.metrics['train_runtime']:.0f} seconds\")\n", + "print(f\"Samples/second: {train_result.metrics['train_samples_per_second']:.1f}\")\n", + "print(f\"Final loss: {train_result.metrics['train_loss']:.4f}\")\n", + "\n", + "# Validation results\n", + "print(f\"\\nValidation (Best Model):\")\n", + "val_results = trainer.evaluate()\n", + "for key, value in val_results.items():\n", + " if isinstance(value, float):\n", + " print(f\" {key}: {value:.4f}\")\n", + "\n", + "# -----------------------------\n", + "# Save Model\n", + "# -----------------------------\n", + "\n", + "trainer.save_model(model_save_path)\n", + "tokenizer.save_pretrained(model_save_path)\n", + "print(f\"\\nModel saved to: {model_save_path}\")" + ] + }, + { + "cell_type": "markdown", + "id": "44acf40a-da7d-4aa3-912c-2bdf883fdc54", + "metadata": {}, + "source": [ + "## Part 4: Evaluate on Holdout (ground truth human expert labels)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "df813061-90b2-4076-87ac-5c5be10ee048", + "metadata": {}, + "outputs": [], + "source": [ + "# -----------------------------\n", + "# Set performance metric output path first! It is based in the model save path you defined earlier\n", + "# -----------------------------\n", + "\n", + "MODEL_DIR = model_save_path.replace(\"best_model\", \"performance\")\n", + "os.makedirs(MODEL_DIR, exist_ok=True) " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0fede292-3cfc-4a69-8dfd-dd21e224572d", + "metadata": {}, + "outputs": [], + "source": [ + "# -----------------------------\n", + "# Evaluation Functions\n", + "# -----------------------------\n", + "\n", + "def evaluate_multilabel(y_true, y_pred, y_prob, class_names):\n", + " \"\"\"\n", + " Comprehensive multi-label evaluation.\n", + " \n", + " Each label is treated as an independent binary decision.\n", + " Macro averaging gives equal weight to each class (recommended for imbalanced data).\n", + " \"\"\"\n", + " n_classes = len(class_names)\n", + " \n", + " # Per-class metrics\n", + " per_class = {}\n", + " for i, cls in enumerate(class_names):\n", + " y_t = y_true[:, i]\n", + " y_p = y_pred[:, i]\n", + " y_pr = y_prob[:, i]\n", + " \n", + " try:\n", + " auc = roc_auc_score(y_t, y_pr)\n", + " except:\n", + " auc = 0.0\n", + " \n", + " per_class[cls] = {\n", + " 'f1': f1_score(y_t, y_p, zero_division=0),\n", + " 'precision': precision_score(y_t, y_p, zero_division=0),\n", + " 'recall': recall_score(y_t, y_p, zero_division=0),\n", + " 'mcc': matthews_corrcoef(y_t, y_p),\n", + " 'auc': auc,\n", + " 'support': int(y_t.sum()),\n", + " }\n", + " \n", + " # Macro averages (equal weight to each class)\n", + " macro = {\n", + " 'f1_macro': np.mean([per_class[c]['f1'] for c in class_names]),\n", + " 'precision_macro': np.mean([per_class[c]['precision'] for c in class_names]),\n", + " 'recall_macro': np.mean([per_class[c]['recall'] for c in class_names]),\n", + " 'mcc_macro': np.mean([per_class[c]['mcc'] for c in class_names]),\n", + " 'auc_macro': np.mean([per_class[c]['auc'] for c in class_names]),\n", + " }\n", + " \n", + " # Micro averages (pooled across all classes)\n", + " micro = {\n", + " 'f1_micro': f1_score(y_true, y_pred, average='micro', zero_division=0),\n", + " 'precision_micro': precision_score(y_true, y_pred, average='micro', zero_division=0),\n", + " 'recall_micro': recall_score(y_true, y_pred, average='micro', zero_division=0),\n", + " }\n", + " \n", + " # Sample-based metrics\n", + " # zero_division=1: correct \"None\" predictions (both empty) score 1.0, not 0.0\n", + " sample = {\n", + " 'f1_samples': f1_score(y_true, y_pred, average='samples', zero_division=1),\n", + " 'jaccard_samples': jaccard_score(y_true, y_pred, average='samples', zero_division=1),\n", + " }\n", + " \n", + " # Overall metrics\n", + " overall = {\n", + " 'exact_match_ratio': (y_pred == y_true).all(axis=1).mean(),\n", + " 'hamming_loss': hamming_loss(y_true, y_pred),\n", + " }\n", + " \n", + " return {\n", + " 'per_class': per_class,\n", + " 'macro': macro,\n", + " 'micro': micro,\n", + " 'sample': sample,\n", + " 'overall': overall,\n", + " }\n", + "\n", + "\n", + "def print_evaluation_report(metrics, class_names):\n", + " \"\"\"Print formatted evaluation report.\"\"\"\n", + " \n", + " print(\"=\"*70)\n", + " print(\"HOLDOUT EVALUATION REPORT\")\n", + " print(\"=\"*70)\n", + " \n", + " # Per-class table\n", + " print(\"\\n--- Per-Class Metrics (Each Label = Independent Binary Decision) ---\")\n", + " print(f\"{'Class':<12} {'F1':>7} {'AUC':>7} {'MCC':>7} {'Prec':>7} {'Rec':>7} {'Support':>8}\")\n", + " print(\"-\"*60)\n", + " \n", + " for cls in class_names:\n", + " m = metrics['per_class'][cls]\n", + " print(f\"{cls:<12} {m['f1']:>7.4f} {m['auc']:>7.4f} {m['mcc']:>7.4f} \"\n", + " f\"{m['precision']:>7.4f} {m['recall']:>7.4f} {m['support']:>8}\")\n", + " \n", + " # Macro averages\n", + " print(\"-\"*60)\n", + " m = metrics['macro']\n", + " print(f\"{'Macro Avg':<12} {m['f1_macro']:>7.4f} {m['auc_macro']:>7.4f} {m['mcc_macro']:>7.4f} \"\n", + " f\"{m['precision_macro']:>7.4f} {m['recall_macro']:>7.4f}\")\n", + " \n", + " # Summary\n", + " print(\"\\n--- Summary Metrics ---\")\n", + " print(f\" Macro F1: {metrics['macro']['f1_macro']:.4f} ← Primary (class-balanced)\")\n", + " print(f\" Macro AUC: {metrics['macro']['auc_macro']:.4f} ← Threshold-independent\")\n", + " print(f\" Macro MCC: {metrics['macro']['mcc_macro']:.4f} ← Robust to imbalance\")\n", + " print(f\" Micro F1: {metrics['micro']['f1_micro']:.4f} ← Dominated by frequent classes\")\n", + " print(f\" Sample F1: {metrics['sample']['f1_samples']:.4f} ← Per-instance average\")\n", + " print(f\" Exact Match: {metrics['overall']['exact_match_ratio']:.4f} ← All labels correct\")\n", + " print(f\" Hamming Loss: {metrics['overall']['hamming_loss']:.4f} ← Fraction wrong (lower=better)\")\n", + " \n", + " # For paper\n", + " print(\"\\n--- For Report ---\")\n", + " print(f\" Primary: Macro F1 = {metrics['macro']['f1_macro']:.4f}\")\n", + " print(f\" Secondary: Macro AUC = {metrics['macro']['auc_macro']:.4f}, Macro MCC = {metrics['macro']['mcc_macro']:.4f}\")\n", + " print(f\" Overall: Exact Match = {metrics['overall']['exact_match_ratio']:.4f}\")\n", + "\n", + "\n", + "# -----------------------------\n", + "# Get Predictions\n", + "# -----------------------------\n", + "\n", + "print(\"=\"*60)\n", + "print(\"HOLDOUT PREDICTIONS\")\n", + "print(\"=\"*60)\n", + "\n", + "holdout_output = trainer.predict(holdout_dataset)\n", + "holdout_logits = holdout_output.predictions\n", + "holdout_probs = torch.sigmoid(torch.tensor(holdout_logits)).numpy()\n", + "holdout_preds = (holdout_probs >= THRESHOLD).astype(int)\n", + "\n", + "print(f\"Holdout samples: {len(holdout_labels)}\")\n", + "print(f\"Predictions shape: {holdout_preds.shape}\")\n", + "\n", + "# -----------------------------\n", + "# Evaluate\n", + "# -----------------------------\n", + "\n", + "metrics = evaluate_multilabel(\n", + " y_true=holdout_labels,\n", + " y_pred=holdout_preds,\n", + " y_prob=holdout_probs,\n", + " class_names=CLASSES,\n", + ")\n", + "\n", + "print_evaluation_report(metrics, CLASSES)\n", + "\n", + "# -----------------------------\n", + "# None Class (Derived)\n", + "# -----------------------------\n", + "\n", + "print(\"\\n--- 'None' Class (Derived: all classes = 0) ---\")\n", + "\n", + "holdout_none_true = (holdout_labels.sum(axis=1) == 0).astype(int)\n", + "holdout_none_pred = (holdout_preds.sum(axis=1) == 0).astype(int)\n", + "holdout_none_prob = 1 - holdout_probs.max(axis=1)\n", + "\n", + "none_f1 = f1_score(holdout_none_true, holdout_none_pred, zero_division=0)\n", + "none_mcc = matthews_corrcoef(holdout_none_true, holdout_none_pred)\n", + "try:\n", + " none_auc = roc_auc_score(holdout_none_true, holdout_none_prob)\n", + "except:\n", + " none_auc = 0.0\n", + "none_precision = precision_score(holdout_none_true, holdout_none_pred, zero_division=0)\n", + "none_recall = recall_score(holdout_none_true, holdout_none_pred, zero_division=0)\n", + "none_support = int(holdout_none_true.sum())\n", + "\n", + "print(f\"{'None':<12} {none_f1:>7.4f} {none_auc:>7.4f} {none_mcc:>7.4f} \"\n", + " f\"{none_precision:>7.4f} {none_recall:>7.4f} {none_support:>8}\")\n", + "\n", + "# -----------------------------\n", + "# Confusion Matrices\n", + "# -----------------------------\n", + "\n", + "print(\"\\n--- Confusion Matrices (per class) ---\")\n", + "print(f\"{'Class':<12} {'TP':>6} {'TN':>6} {'FP':>6} {'FN':>6}\")\n", + "print(\"-\"*40)\n", + "\n", + "for i, cls in enumerate(CLASSES):\n", + " y_true = holdout_labels[:, i]\n", + " y_pred = holdout_preds[:, i]\n", + " cm = confusion_matrix(y_true, y_pred)\n", + " tn, fp, fn, tp = cm.ravel()\n", + " print(f\"{cls:<12} {tp:>6} {tn:>6} {fp:>6} {fn:>6}\")\n", + "\n", + "none_cm = confusion_matrix(holdout_none_true, holdout_none_pred)\n", + "none_tn, none_fp, none_fn, none_tp = none_cm.ravel()\n", + "print(f\"{'None':<12} {none_tp:>6} {none_tn:>6} {none_fp:>6} {none_fn:>6}\")\n", + "\n", + "# -----------------------------\n", + "# Multi-label Analysis\n", + "# -----------------------------\n", + "\n", + "print(\"\\n--- Multi-label Analysis ---\")\n", + "\n", + "true_label_counts = holdout_labels.sum(axis=1)\n", + "pred_label_counts = holdout_preds.sum(axis=1)\n", + "\n", + "print(f\"Average labels per sentence:\")\n", + "print(f\" True: {true_label_counts.mean():.2f}\")\n", + "print(f\" Predicted: {pred_label_counts.mean():.2f}\")\n", + "\n", + "print(f\"\\nLabel count distribution:\")\n", + "print(f\"{'# Labels':<10} {'True':>8} {'Predicted':>10}\")\n", + "print(\"-\"*30)\n", + "for n in range(7):\n", + " true_count = (true_label_counts == n).sum()\n", + " pred_count = (pred_label_counts == n).sum()\n", + " print(f\"{n:<10} {true_count:>8} {pred_count:>10}\")\n", + "\n", + "# -----------------------------\n", + "# Save Results\n", + "# -----------------------------\n", + "\n", + "print(\"\\n\" + \"=\"*60)\n", + "print(\"SAVING RESULTS\")\n", + "print(\"=\"*60)\n", + "\n", + "# Save predictions\n", + "df_holdout_results = df_holdout.copy()\n", + "for i, cls in enumerate(CLASSES):\n", + " df_holdout_results[f'{cls}_prob'] = holdout_probs[:, i]\n", + " df_holdout_results[f'{cls}_pred'] = holdout_preds[:, i]\n", + "df_holdout_results['None_prob'] = holdout_none_prob\n", + "df_holdout_results['None_pred'] = holdout_none_pred\n", + "\n", + "df_holdout_results.to_csv(f\"{MODEL_DIR}/holdout_predictions.csv\", index=False)\n", + "df_holdout_results.to_pickle(f\"{MODEL_DIR}/holdout_predictions.pkl\")\n", + "print(f\" Predictions: {MODEL_DIR}/holdout_predictions.csv\")\n", + "\n", + "# Save metrics\n", + "metrics_summary = {\n", + " 'model': MODEL_NAME,\n", + " 'threshold': THRESHOLD,\n", + " 'holdout_size': len(df_holdout),\n", + " 'macro': metrics['macro'],\n", + " 'micro': metrics['micro'],\n", + " 'sample': metrics['sample'],\n", + " 'overall': metrics['overall'],\n", + " 'per_class': metrics['per_class'],\n", + " 'none_class': {\n", + " 'f1': none_f1, 'auc': none_auc, 'mcc': none_mcc,\n", + " 'precision': none_precision, 'recall': none_recall, 'support': none_support,\n", + " },\n", + " 'hyperparameters': {\n", + " 'learning_rate': LEARNING_RATE,\n", + " 'weight_decay': WEIGHT_DECAY,\n", + " 'warmup_ratio': WARMUP_RATIO,\n", + " 'num_epochs': NUM_EPOCHS,\n", + " 'batch_size': BATCH_SIZE,\n", + " 'gradient_accumulation': GRADIENT_ACCUMULATION,\n", + " 'max_length': MAX_LENGTH,\n", + " },\n", + "}\n", + "\n", + "with open(f\"{MODEL_DIR}/holdout_metrics.json\", 'w') as f:\n", + " json.dump(metrics_summary, f, indent=2, default=float)\n", + "print(f\" Metrics: {MODEL_DIR}/holdout_metrics.json\")\n", + "\n", + "# Save training history\n", + "with open(f\"{MODEL_DIR}/training_history.json\", 'w') as f:\n", + " json.dump(trainer.state.log_history, f, indent=2)\n", + "print(f\" History: {MODEL_DIR}/training_history.json\")\n", + "\n", + "print(\"\\n\" + \"=\"*60)\n", + "print(\"DONE\")\n", + "print(\"=\"*60)\n", + "print(f\"\\nFinal Results:\")\n", + "print(f\" Macro F1: {metrics['macro']['f1_macro']:.4f}\")\n", + "print(f\" Macro AUC: {metrics['macro']['auc_macro']:.4f}\")\n", + "print(f\" Macro MCC: {metrics['macro']['mcc_macro']:.4f}\")\n", + "print(f\" Exact Match: {metrics['overall']['exact_match_ratio']:.4f}\")" + ] + }, + { + "cell_type": "markdown", + "id": "91936e6d-3591-4a86-956c-9090d7e46bb6", + "metadata": {}, + "source": [ + "**Please cite this paper** if you use any part or all of this code in a project - be it commercial or academic: \n", + "\n", + "> Ringel, Daniel, *Creating Synthetic Experts with Generative Artificial Intelligence* (December 5, 2023). Kenan Institute of Private Enterprise Research Paper No. 4542949, Available at SSRN: https://ssrn.com/abstract=4542949 or http://dx.doi.org/10.2139/ssrn.4542949 \n" + ] + }, + { + "cell_type": "markdown", + "id": "5e5e8344-2674-4daf-b468-6afbf7aa15bf", + "metadata": {}, + "source": [ + "*This notebook was developed by Daniel M. Ringel in January 2026 with the help of the various vendor's API documentation (and examples) as well as genAI models from OpenAI and Anthropic.*" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/reference/Ringel_488-2026_Capstone_Constructs.pdf b/docs/reference/Ringel_488-2026_Capstone_Constructs.pdf new file mode 100644 index 0000000000000000000000000000000000000000..af9e381d52215f4cb5cc25005713a2c616ce92e9 GIT binary patch literal 465975 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�#B} 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

IG-J*r~{f!`)rCnN(Ca_40`Y2`B3FBJ*_jfLocG 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

5m56Y=QO68?}J?Hi8wJVK%P)b!U#{ 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

~vbk7{?Gy0P_>N1yVR_u4d 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�)&`M5J6)6 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 literal 0 HcmV?d00001 diff --git a/docs/reference/Signoff_assn_instructions.md b/docs/reference/Signoff_assn_instructions.md new file mode 100644 index 0000000..4c9dae5 --- /dev/null +++ b/docs/reference/Signoff_assn_instructions.md @@ -0,0 +1,71 @@ +# CAPSTONE: Construct of Interest and Data Sign-off by Dr. D. + +**Due:** April 7 by 11:59pm | **Points:** 0 | **Submission:** File upload + +--- + +## Overview + +Your capstone project requires you to classify a construct of interest in data at scale. + +You must get approval for your construct of interest and data from your instructor. + +This is an ungraded assignment. However, it is the prerequisite to your capstone project. + +## Goal + +Pick a well-documented, theoretically founded construct of interest. Explain why a firm would want to classify this construct at scale. + +### Your Construct Must Be: + +- **Business-relevant** — addresses a real business decision +- **Theoretically grounded** — anchored in established literature +- **Well documented** — clearly defined in academic or industry sources +- **Observable in text** — detectable in your data source +- **Definable with clear rules** — specific enough for reliable labeling +- **Complex & nuanced** — more than just sentiment (not positive/negative) + +You must pick one of the seven provided constructs of interest from here: https://www.ringel.ai/UNC/2026/BUSI488/Class23/Ringel_488-2026_Capstone_Constructs.pdf + +## Define Your Construct Precisely + +Turn the concept into labels humans can apply consistently. + +### You Must Create: + +- **Label set** (classes/categories) +- **Clear definitions and decision rules** for each label +- **Borderline cases** — guidance for unclear examples +- **None/Other policy** — if applicable (multi-class yes, multi-label no) +- **2-3 example texts** per label (your own examples) +- **Decision:** multi-class (one label per item) vs multi-label (multiple labels can apply) + +### Consider Your Data Source + +Before finalizing, ask yourself: + +- Do these data, when classified, inform and improve a business decision? +- Can the construct of interest (all its labels/classes) be sufficiently found in these data? +- Are these data abundantly available and do they need to be analyzed frequently and/or at scale to justify building a vertical AI? + +## Important Guardrails + +- **Choose a data source** that fits your construct and is realistically useful to a firm +- **Use public data or properly de-identified data only** — no sensitive internal company data +- **Pilot test first:** Before committing, do a quick manual pilot on 100–200 texts in the developer platform playground or ChatGPT to confirm your construct appears in the source and that your labels are workable + +## Deliverable for This Assignment + +**Two-page maximum, double-spaced documentation** containing: + +1. **Definition** of your construct of interest and its labels/classes + +2. **Sources & Citations** that support your construct of interest (and its classes/labels), demonstrating that it is: + - Theoretically founded + - Well-established in literature + - Meaningful to decision makers + +3. **Data Description** explaining: + - What data you will identify it in + - How you will acquire these data + - Why identifying your construct at scale/frequently in these data is valuable (justifies the need for a vertical AI)