mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-09-08 10:14:35 +08:00
feat(api): add unified index API and dataset management endpoints (#14222)
### What problem does this PR solve?
## Summary
Refactor the dataset API layer into a clean service/REST separation
pattern, add a unified `/index` API for graph/raptor/mindmap operations,
and introduce several new dataset management endpoints with full test
coverage.
## Changes
### Service Layer (`dataset_api_service.py`)
- Added `trace_index(dataset_id, tenant_id, index_type)` — unified trace
function for all index types
- Added `run_index`, `delete_index` service functions
- Added `get_dataset`, `get_ingestion_summary`, `list_ingestion_logs`,
`get_ingestion_log`
- Added `run_embedding`, `list_tags`, `aggregate_tags`, `delete_tags`,
`rename_tag`
- Added `get_flattened_metadata`, `get_auto_metadata`,
`update_auto_metadata`
### REST API Layer (`dataset_api.py`)
**New unified routes:**
| Method | Route | Description |
|--------|-------|-------------|
| POST | `/datasets/<id>/index?type=graph\|raptor\|mindmap` | Run index
task |
| GET | `/datasets/<id>/index?type=graph\|raptor\|mindmap` | Trace index
task |
| DELETE | `/datasets/<id>/<index_type>` | Delete index |
| GET | `/datasets/<id>` | Get dataset details |
| GET | `/datasets/<id>/ingestions/summary` | Ingestion summary |
| GET | `/datasets/<id>/ingestions` | List ingestion logs |
| GET | `/datasets/<id>/ingestions/<log_id>` | Get single ingestion log
|
| POST | `/datasets/<id>/embedding` | Run embedding |
| GET | `/datasets/<id>/tags` | List tags |
| GET | `/datasets/tags/aggregation` | Aggregate tags across datasets |
| DELETE | `/datasets/<id>/tags` | Delete tags |
| PUT | `/datasets/<id>/tags` | Rename tag |
| GET | `/datasets/metadata/flattened` | Get flattened metadata |
| GET/PUT | `/datasets/<id>/metadata/config` | New metadata config path
|
**Removed routes (replaced by unified `/index`):**
- `POST /datasets/<id>/mindmap`
- `GET /datasets/<id>/mindmap`
**Preserved legacy routes (backward compatibility):**
- `/run_graphrag`, `/trace_graphrag`, `/run_raptor`, `/trace_raptor`
- `/auto_metadata` GET/PUT
### Test Suite
- Updated `common.py` helpers: added `trace_index`, removed
`run_mindmap`/`trace_mindmap`
- Added 7 new test files with 39 test cases total:
| Test File | Cases |
|-----------|-------|
| `test_get_dataset.py` | 4 |
| `test_ingestion_summary.py` | 2 |
| `test_ingestion_logs.py` | 5 |
| `test_index_api.py` | 14 |
| `test_embedding.py` | 2 |
| `test_tags.py` | 8 |
| `test_flattened_metadata.py` | 4 |
- Deleted `test_mindmap_tasks.py` (covered by unified index tests)
## Design Decisions
1. **Unified `/index?type=...`** — single endpoint replaces 3 separate
route pairs for graph/raptor/mindmap
2. **Backward compatibility** — old routes (`/run_graphrag`,
`/run_raptor`, `/auto_metadata`) preserved alongside new paths
3. **`_VALID_INDEX_TYPES = {"graph", "raptor", "mindmap"}`** — input
validation via constant set
4. **`_INDEX_TYPE_TO_TASK_ID_FIELD`** — maps index type to KB model task
ID field for clean dispatch
## Files Changed
- `api/apps/restful_apis/dataset_api.py`
- `api/apps/services/dataset_api_service.py`
- `sdk/python/ragflow_sdk/modules/dataset.py`
- `test/testcases/test_http_api/common.py`
- `test/testcases/test_http_api/test_dataset_management/` (7 new files)
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
- [x] Refactoring
---------
Signed-off-by: noob <yixiao121314@outlook.com>
This commit is contained in:
@@ -203,7 +203,7 @@ def get_request_json_payload(response) -> dict:
|
||||
payload = None
|
||||
|
||||
if not isinstance(payload, dict):
|
||||
raise AssertionError(f"Expected JSON object payload for /v1/kb/update, got={payload!r}")
|
||||
raise AssertionError(f"Expected JSON object payload for /api/v1/datasets update, got={payload!r}")
|
||||
return payload
|
||||
|
||||
|
||||
@@ -334,7 +334,7 @@ def step_03_create_dataset(
|
||||
create_response = capture_response(
|
||||
page,
|
||||
trigger,
|
||||
lambda resp: resp.request.method == "POST" and "/v1/kb/create" in resp.url,
|
||||
lambda resp: resp.request.method == "POST" and "/api/v1/datasets" in resp.url,
|
||||
timeout_ms=RESULT_TIMEOUT_MS * 2,
|
||||
)
|
||||
try:
|
||||
@@ -540,23 +540,20 @@ def step_04_set_dataset_settings(
|
||||
response = capture_response(
|
||||
page,
|
||||
trigger,
|
||||
lambda resp: resp.request.method == "POST" and "/v1/kb/update" in resp.url,
|
||||
lambda resp: resp.request.method == "PUT" and f"/api/v1/datasets/{dataset_id}" in resp.url,
|
||||
timeout_ms=RESULT_TIMEOUT_MS * 2,
|
||||
)
|
||||
assert 200 <= response.status < 400, f"Unexpected /v1/kb/update status={response.status}"
|
||||
assert 200 <= response.status < 400, f"Unexpected /api/v1/datasets update status={response.status}"
|
||||
response_payload = response.json()
|
||||
if isinstance(response_payload, dict):
|
||||
assert response_payload.get("code") == 0, (
|
||||
f"/v1/kb/update response code={response_payload.get('code')} "
|
||||
f"/api/v1/datasets update response code={response_payload.get('code')} "
|
||||
f"message={response_payload.get('message')}"
|
||||
)
|
||||
|
||||
payload = get_request_json_payload(response)
|
||||
assert payload.get("kb_id") == dataset_id, (
|
||||
f"Expected kb_id={dataset_id!r}, got {payload.get('kb_id')!r}"
|
||||
)
|
||||
for key in ("name", "language", "parser_config"):
|
||||
assert key in payload, f"Expected key {key!r} in /v1/kb/update payload"
|
||||
assert key in payload, f"Expected key {key!r} in /api/v1/datasets update payload"
|
||||
parser_config = payload.get("parser_config") or {}
|
||||
assert (
|
||||
parser_config.get("image_table_context_window")
|
||||
|
||||
Reference in New Issue
Block a user