# 管理数据来源与处理状态

将数据目录（Catalog）表、数据目录文件或本地上传文件加入语义模型，并查看来源处理与索引状态。添加请求成功只表示来源记录和处理任务已经创建，不表示内容已经可以使用。

## 来源类型和标识

| `source_type` | 来源 | 必要标识 |
| --- | --- | --- |
| `catalog_table` | 数据目录表 | 数值 `table_id` |
| `catalog_file` | 数据目录文件 | 字符串 `file_id` 和数值 `volume_id` |
| `local_file` | 通过语义模型上传接口上传的文件 | 上传返回的文件 ID及相关上传字段 |

数据目录文件必须同时提供其权威卷位置。不要把 `table`、显示名称或文件路径当作 `source_type` 或资源 ID。

## 添加数据目录来源

先检查目标文件或表是否已经存在：

```bash
curl -X POST "$PRODUCT_API_BASE_URL/semantic-models/$MODEL_ID/sources/existence" \
  -H "X-API-Key: $PRODUCT_API_KEY" \
  -H "X-Workspace-ID: $WORKSPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "file_ids": ["<FILE_ID>"],
    "table_ids": [<TABLE_ID>]
  }'
```

响应只返回已经存在于该模型中的请求 ID。排除重复项后，添加来源：

```bash
curl -X POST "$PRODUCT_API_BASE_URL/semantic-models/$MODEL_ID/sources" \
  -H "X-API-Key: $PRODUCT_API_KEY" \
  -H "X-Workspace-ID: $WORKSPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "sources": [
      {
        "source_type": "catalog_table",
        "table_id": <TABLE_ID>
      },
      {
        "source_type": "catalog_file",
        "file_id": "<FILE_ID>",
        "volume_id": <VOLUME_ID>
      }
    ]
  }'
```

成功响应包含已创建的 `sources[]` 和 `jobs[]`。保存每个来源的 `row_id`，它是来源详情、治理、分段和删除接口使用的路径标识；不要用 `source_id` 或数据目录 `file_id` 代替。

## 上传本地文件

向已有模型添加本地文件时，使用模型级上传入口：

```bash
curl -X POST "$PRODUCT_API_BASE_URL/semantic-models/$MODEL_ID/local-files/upload" \
  -H "X-API-Key: $PRODUCT_API_KEY" \
  -H "X-Workspace-ID: $WORKSPACE_ID" \
  -F "file=@<LOCAL_FILE_PATH>"
```

保存上传响应中的 `file_id`，再按当前上传结果要求构造 `local_file` 来源。创建模型之前上传则使用 `/semantic-models/local-files/upload`。

## 选择整组来源

需要从数据库或卷批量选择时，先调用 `/semantic-models/source-selections/preview`，请求体使用 `source_selections[]`。数据库表选择使用 `kind`、`database_id`、`selected_table_ids`；卷文件选择使用 `kind`、`volume_id`、`selected_file_ids`。

预览响应返回去重后的 `file_count`、`table_count` 和 `total_count`。确认数量后再创建或追加来源，避免因“全选”和排除条件组合产生超出预期的输入。

## 查询来源状态

```bash
curl "$PRODUCT_API_BASE_URL/semantic-models/$MODEL_ID/sources" \
  -H "X-API-Key: $PRODUCT_API_KEY" \
  -H "X-Workspace-ID: $WORKSPACE_ID"
```

| 字段 | 说明 |
| --- | --- |
| `data.items[].row_id` | 来源记录 ID。详情、治理和删除继续使用该值。 |
| `data.items[].source_type` | 来源类型。 |
| `data.items[].ingest_status` | 当前处理状态。只有服务端返回的成功状态才能作为处理完成依据。 |
| `data.items[].enabled` | 调用者配置的启用状态。 |
| `data.items[].effective_enabled` | 结合到期时间和治理规则后的实际启用状态。 |
| `data.items[].expired` | 来源是否已经过期。 |
| `data.items[].segment_version_id` | 当前分段版本标识。 |
| `data.items[].index_version` | 当前索引版本。 |
| `data.items[].error` | 来源处理错误摘要。 |

来源任务通过 `GET /semantic-models/{model_id}/source-jobs` 查询。响应中的 `job_status`、`error` 和 `reconcile_required` 用于判断处理是否仍在运行、已经失败或需要显式收敛状态。

只有 `reconcile_required: true` 时，才考虑调用 `POST /semantic-models/{model_id}/source-jobs/reconcile`。该操作用于处理来源任务状态，不是普通的“重试全部来源”按钮。

## 来源治理和分段

`PATCH /semantic-models/{model_id}/sources/{row_id}/governance` 可以更新标签、过期时间、启用状态和过期后强制启用设置。修改后读取 `effective_enabled`，不要只检查提交的 `enabled`。

文档详情接口返回当前分段版本、索引版本和分段内容。分段更新需要同时提供 `base_segment_version_id` 和 `base_index_version`，用于避免覆盖较新的修改。没有已提交分段版本或向量绑定时，分段写操作会被拒绝；普通来源接入流程不需要主动修改分段。

来源列表返回 `legacy_backfill_required: true` 时，旧模型可能需要迁移来源记录。只由具有维护权限的调用方按当前版本说明执行 `/sources/backfill-legacy`，不要对新模型例行调用。

## 删除来源

```text
DELETE /semantic-models/{model_id}/sources/{row_id}
```

删除前确认来源没有仍在运行的任务。删除来源不会删除原始数据目录表或文件，但会影响模型对该来源内容的使用。

## 常见问题

| 现象 | 先检查 | 下一步 |
| --- | --- | --- |
| 添加后仍不可用 | `ingest_status`、`effective_enabled` 和来源任务 | 等待任务终态或按 `error` 修正来源。 |
| 数据目录文件被拒绝 | `file_id` 和权威 `volume_id` | 从文件列表重新取得二者后再添加。 |
| 来源重复 | `/sources/existence` 结果 | 从请求中移除已经存在的文件和表 ID。 |
| 任务显示需要 Reconcile | `reconcile_required` 和最近任务错误 | 仅在该字段为真时调用 Reconcile，再重新读取任务。 |
| 分段更新冲突 | 基础分段版本和索引版本 | 重新读取文档详情，基于最新版本重新编辑。 |

## 下一步

- [添加业务指标和术语](entries.md)
- [校验语义模型](model-lifecycle.md#校验模型)
- [配置 Embedding Backend](../provider-backend-router/provider-backend.md)
