Using an LLM API as a Data Labeling Tool
Data Science & ML Projects (Intermediate)
Chapter 7 · Using an LLM API as a Data Labeling Tool
What We're Building
A pipeline that labels a large batch of unstructured customer-feedback text with a custom business category ("Billing Issue," "Bug Report," "Feature Request," "Praise," "Other") — categories with no existing labeled training data anywhere, making dsproj2-1's own from-scratch approach genuinely impractical here. The LLM applies the labeling scheme directly, at scale, the moment it can be described in a prompt — then the results get analyzed statistically with this track's own established tools.
Step 1: The Unlabeled Batch
import pandas as pd feedback = pd.read_csv("customer_feedback.csv") # one column: raw text, no labels at all print(feedback.shape)
Step 2: Designing the Labeling Prompt
CATEGORIES = ["Billing Issue", "Bug Report", "Feature Request", "Praise", "Other"] PROMPT_TEMPLATE = """Classify the following customer feedback into exactly one of these categories: {categories}. Feedback: "{text}" Respond with only valid JSON: {{"category": "...", "confidence": "high"|"medium"|"low"}}"""
prompt1's own anatomy of a good prompt, put directly to use rather than re-taught here. Asking for structured JSON specifically, rather than a free-form sentence, is what makes Step 4's own parsing step possible at all.
Step 3: Calling the API — claude-adv1's Own Territory, Applied Minimally
import anthropic, json, time client = anthropic.Anthropic() # API key read from environment, per claude-adv1 def label_feedback(text): response = client.messages.create( model="claude-sonnet-4-5", max_tokens=100, messages=[{"role": "user", "content": PROMPT_TEMPLATE.format(categories=CATEGORIES, text=text)}], ) time.sleep(0.5) return json.loads(response.content[0].text)
The full API surface — streaming, tool use, system prompts — is claude-adv1's own territory in depth. This chapter uses exactly one call shape, deliberately, since the point here is what the API call accomplishes inside a larger pipeline, not the API itself.
dsproj1-3's and dsproj1-6's own APIs (Open-Meteo, REST Countries) were free, with no per-call cost. A real LLM API call has a real, per-token price, and rate limits that matter at genuine scale — 10,000 feedback rows means 10,000 real billed calls, not a rounding error. This is a real, practical planning consideration specific to this chapter, not present anywhere else in this track.
Step 4: Running the Batch and Parsing Results
results = [] for text in feedback["text"]: try: label = label_feedback(text) results.append({"text": text, **label}) except (json.JSONDecodeError, KeyError): results.append({"text": text, "category": "parse_error", "confidence": None}) labeled = pd.DataFrame(results)
Same JSON-parsing reflex ds1-3 established, now applied to a live model's own output instead of a file or a conventional API response — and the same defensive try/except instinct this track has used since dsproj1-1's own scraper, since a model occasionally returning malformed JSON is a real, expected possibility, not a bug to be surprised by.
Step 5: Analyzing the Labeled Data — This Track's Own Familiar Tools
import matplotlib.pyplot as plt category_counts = labeled["category"].value_counts() category_counts.plot(kind="barh", color="#15803D") plt.title("Feedback Volume by Category") plt.savefig("feedback_categories.png")
Nothing new here at all — .value_counts() and a bar chart, the exact ds1-level analysis skill this whole track opened with, applied here to data an LLM helped create rather than data that arrived pre-labeled.
The Honest Trade-Off, Stated Directly
| dsproj2-1's own from-scratch model | This chapter's LLM-as-tool | |
|---|---|---|
| Training data needed | 25,000 labeled examples | None — the category scheme just needs describing |
| Cost per use once built | Free — a trained model runs at no marginal cost | Real per-call cost, every single time |
| Measured accuracy | A real number, against a held-out test set | No ground truth to measure against, unless one is built |
| Adapting to a new category scheme | Requires retraining on newly labeled data | Edit the prompt |
llm1-10's own mechanical explanation, an LLM has no built-in fact-checker; it can mislabel ambiguous feedback confidently, the same way it can hallucinate anywhere else. The real, practical mitigation is what production pipelines actually do: pull a random sample of the labeled output and have a human spot-check it, the same "flag for review, don't blindly trust" instinct dsproj1-2's own outlier-flagging and dsproj1-6's own missing-value handling already established in this track.
No training data required
A custom category scheme works the moment it can be described in a prompt.
Structured output via JSON
Requesting a specific format makes the model's own output immediately parseable.
Real per-call cost
Unlike every free API used earlier in this track — a genuine planning factor at scale.
Sample-based spot-checking
The practical substitute for a held-out test-set accuracy number.
Try these on your own:
- Pull a random sample of 50 labeled rows, label them by hand, and compute real agreement between your labels and the model's own — a genuine, honest accuracy estimate.
- Add a retry-with-backoff loop around
label_feedback()for real API rate-limit errors, not just malformed JSON. - Ask the model to also extract a one-sentence summary alongside the category, and add it as a new column.
- Compare this chapter's own category-volume chart against Chapter 1's own sentiment scores for the same feedback batch, if both are available — do certain categories skew more negative?
What's Next
Chapter 8: Capstone — An End-to-End ML-Powered Mini App — collection, cleaning, feature engineering, model training/evaluation, and a minimal interface, combined into one real application, with a chapter-attribution table spanning both dsproj1 and dsproj2.
Chapter 7 Quick Reference
- The only chapter in this course that trains nothing — an already-trained LLM used as one stage in a larger pipeline
- prompt1's own prompt-anatomy material applied directly, not re-taught; claude-adv1's own API surface used minimally, on purpose
- Real per-call cost and rate limits — a genuinely different consideration than this track's earlier free APIs
- No training data needed for a custom category scheme — but also no measured test-set accuracy, unlike every model trained earlier in this course
- llm1-10's own hallucination material applies directly here — sample-based human spot-checking is the honest, practical mitigation