Build a CSV-to-JSON Classification Service
Scale AIBackend Engineer · OnsiteLast updated
Implement a resilient data pipeline service that parses CSV records, enriches them using an external classification client with validation and retries, and writes ordered, structured JSON Lines output safely.
Scenario
In machine learning ingestion pipelines, unstructured text data often arrives via CSV files and must be cleaned, classified via a model API, and output as structured JSON Lines (.jsonl) for downstream annotation tasks.
Implement a backend processing function process_and_classify that reads a CSV file, classifies each text payload against a restricted list of allowed categories using a provided classification client, and writes valid JSON records to an output file while handling errors gracefully.
Requirements
- Validation & Categorization: For each record, send the text to
classifier.classify(text). The returned category must be validated againstallowed_categories. If the category returned is not allowed or the API raises aClassificationError, retry the call up tomax_retriestimes. - Failure Handling: If a row exhausts all retries or has invalid/missing required columns, write a record to the output file with
"status": "FAILED"and an"error"message, rather than aborting the entire process. - Output Order: The output records written to
output_pathmust match the original row order of the CSV. - Summary: Return a summary dictionary containing processing counts.
Interface
from typing import Protocol, List, Dict, Any
class ClassificationError(Exception):
pass
class ClassifierAPI(Protocol):
def classify(self, text: str) -> str:
"""Calls an external LLM/model. May raise ClassificationError."""
...
def process_and_classify(
input_csv_path: str,
output_jsonl_path: str,
classifier: ClassifierAPI,
allowed_categories: List[str],
max_retries: int = 2
) -> Dict[str, int]:
"""
Returns a summary dict:
{
"total": int,
"success": int,
"failed": int
}
"""
pass
Format & Schema
Input CSV Schema:
id: Unique string identifier for the record.text: The raw text content to be classified.
Output JSONL Schema (each line is a standalone JSON object):
- Successful row:
{"id": "123", "text": "...", "category": "billing", "status": "SUCCESS"} - Failed row:
{"id": "124", "text": "...", "category": null, "status": "FAILED", "error": ""}
Example
Input CSV (tasks.csv):
id,text
rec_1,Where is my refund?
rec_2,System error code 500
rec_3,
Configuration:
allowed_categories = ["billing", "technical_support", "general"]classifier.classify("Where is my refund?")->"billing"classifier.classify("System error code 500")-> raisesClassificationErroron all retries
Output JSONL (output.jsonl):
{"id": "rec_1", "text": "Where is my refund?", "category": "billing", "status": "SUCCESS"}
{"id": "rec_2", "text": "System error code 500", "category": null, "status": "FAILED", "error": "ClassificationError: rate limit reached"}
{"id": "rec_3", "text": "", "category": null, "status": "FAILED", "error": "Empty text"}
Return Value:
{"total": 3, "success": 1, "failed": 2}
Constraints
allowed_categoriescontains 1 to 50 unique string values.- Number of rows in CSV is between
0and100,000. - Empty or missing
idortextfields should immediately be marked asFAILEDwithout calling the classifier.
Hints
Hint 1
Use a thread pool or asynchronous executor for concurrent network requests, but keep track of row indices to guarantee deterministic output ordering.
Hint 2
Handle transient network failures and invalid output labels as separate retry conditions inside a helper function with exponential backoff.
Hint 3
Stream the CSV reading and JSONL writing line-by-line or in batches rather than loading all 100,000 records into memory at once.
Follow-up questions
- How would you make this service resumable if the worker crashes midway through a 10-million-row file?
- If the classification API enforces a strict rate limit of 50 requests per second, how would you design bounded concurrency and token-bucket rate limiting across workers?
- How would you protect the service from path traversal vulnerabilities if `input_csv_path` and `output_jsonl_path` are user-supplied?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.