Dataset Segment Batch Import#
Batch import lets users add many segments to a knowledge-base document at once by uploading a CSV file. The operation is asynchronous: the API returns a job ID immediately, and callers poll a status endpoint until the job reaches a terminal state.
Entry Points#
| Layer | File | Route |
|---|---|---|
| HTTP API | datasets_segments.py | POST /datasets/{dataset_id}/documents/{document_id}/segments/batch_import |
| Status poll | same file | GET /datasets/batch_import_status/{job_id} |
| Celery task | batch_create_segment_to_index_task.py | queue: dataset |
Job Lifecycle (Redis)#
The controller and task coordinate via a single Redis key: segment_batch_import_{job_id} .
waitingβ written by the controller withsetnx(no TTL) immediately before dispatching the Celery task . Becausesetnxis used, the write is a no-op if the key already exists, which guards against accidental double-dispatch.errorβ written by the task withsetex+ 600-second TTL if any exception occurs .completedβ written by the task withsetex+ 600-second TTL after vector creation succeeds .
The 600-second TTL on terminal states ensures automatic Redis cleanup; there is no explicit deletion step.
Task Processing Phases#
batch_create_segment_to_index_task runs in four sequential phases :
- Setup (session 1) β validates dataset, document, and upload file from the DB; extracts the storage key and configuration dicts; any failure sets status
errorand returns . - CSV parsing β downloads the file from object storage into a temp directory, reads it with pandas, and builds a list of
{content, answer?}dicts. QA-indexed datasets expect two columns; plain datasets expect one . - Segment creation (session 2) β inserts one
DocumentSegmentrow per CSV row, withstatus=COMPLETEDandindexing_at/completed_attimestamps set immediately . Token counts come from the embedding model for high-quality datasets, or default to0for economy datasets . - Vectorization (session 3) β calls
VectorService.create_segments_vector()to push the new segments to the vector store.
Error Handling and the Pre-Fix Bug#
Prior to PR #38863, only the setup phase had error handling. If CSV parsing, DB writes, or vector creation failed, the Redis key stayed at waiting (no TTL, no expiry). The status endpoint would return waiting indefinitely, causing the frontend to poll forever without surfacing the error .
The fix wraps the entire processing phase (phases 2β4) in a try/except block that calls redis_client.setex(indexing_cache_key, 600, "error") on any exception . Two concrete failure modes are covered by tests:
- Empty CSV (header row only) β raises
ValueError("The CSV file is empty."). - QA dataset with single-column CSV β raises
IndexErroronrow.iloc[1].
Both now correctly resolve to status error rather than stalling at waiting.
Key Files#
| File | Purpose |
|---|---|
api/controllers/console/datasets/datasets_segments.py | HTTP endpoints β dispatches task, polls Redis |
api/tasks/batch_create_segment_to_index_task.py | Celery task β full batch import logic |
api/services/vector_service.py | create_segments_vector() β final vectorization step |