- 人工智能
- 大模型
- AI Agent
- RAG
- 后端
- 前端
【免费下载链接】TaskingAI
The open source platform for AI-native application development.
在 TaskingAI 的检索(Retrieval)体系中,Chunk 是存储于 Collection 内的最小文本单元,每条 Chunk 都由 Embedding 模型生成向量表示并参与语义检索。本文围绕 TaskingAI 官方 REST API 模板中的"删除一个 Chunk"操作展开,先给出可直接复制的 curl 命令与完整响应说明,再深入源码剖析删除操作在数据库层的真实执行链路(含num_chunks计数更新、Record 级联关系等),并给出删除后通过 Get 接口验证、以及与删除 Record 的差异对比等工程实践要点。读完本文,你将能够安全、准确地通过 REST API 删除指定 Chunk,并理解删除操作对 Collection、Record 及后续查询结果的完整影响。
一、核心接口:DELETE /v1/collections/{collection_id}/chunks/{chunk_id}
原文档给出的 REST 调用模板位于 backend/resources/code_templates/collection/3_rest_api/3_chunk/5_delete_a_chunk.md,其完整 curl 命令如下:
curl -X DELETE $$SERVICE_HOST$$/v1/collections/$$COLLECTION_ID$$/chunks/$$CHUNK_ID$$ \ -H "Authorization: Bearer $$API_KEY$$" \ -H "Content-Type: application/json"其中三个占位符需要替换为实际值:
| 占位符 | 含义 | 取值来源 |
|---|---|---|
$$SERVICE_HOST$$ | TaskingAI 服务的访问地址 | 部署后服务的 Base URL,形如http://localhost:8000 |
$$COLLECTION_ID$$ | 目标 Collection 的 ID | 创建 Collection 时返回,或以 4_list_collections.md 中的 List Collections 接口查询获得 |
$$CHUNK_ID$$ | 待删除 Chunk 的 ID | 创建 Chunk 时返回,或以 4_list_chunks.md 中的 List Chunks 接口查询获得 |
$$API_KEY$$ | 认证使用的 API Key | 在控制台创建,用于请求头Authorization: Bearer |
执行成功后,服务端返回一个仅包含状态字段的 JSON 响应(响应模型定义见 backend/app/schemas/auto/chunk_delete_response.py):
{ "status": "success" }删除操作采用DELETEHTTP 方法,无需请求体;文档中的Content-Type: application/json仅为通用头信息,保持默认即可。
原文档明确指出:执行删除后,指定的 Chunk 会从 Collection 中永久移除。但如果被删除的 Chunk 是通过创建 Record 而产生的,那么在 Record 层级上,该 Record 依然存在。
二、后端实现:DELETE 路由的完整调用链
要真正理解"删除一个 Chunk"背后发生了什么,需要沿着 REST 路由向下追踪源码调用链。TaskingAI 的 Chunk CRUD 路由位于 backend/app/routes/auto/chunk.py,其中删除接口定义为:
@router.delete( path="/collections/{collection_id}/chunks/{chunk_id}", tags=["Retrieval - Chunk"], summary="Delete Chunk", operation_id="delete_chunk", response_model=ChunkDeleteResponse, responses={422: {"description": "Unprocessable Entity"}}, ) async def api_delete( request: Request, path_params: Dict = Depends(path_params_required), auth_info: Dict = Depends(auth_info_required), ): check_path_params( model_operator=ops, object_id_required=True, path_params=path_params, ) await ops.delete(**path_params) return ChunkDeleteResponse()该实现透露出几个关键事实:
- 路径参数校验:
path_params_required依赖从 URL 提取collection_id与chunk_id两个路径参数,随后check_path_params会做三重校验——检查主键字段是否齐全(Chunk 的主键为["collection_id", "chunk_id"],见 backend/app/models/retrieval/chunk.py)、校验路径参数仅含[_a-zA-Z0-9]字符、以及调用模型层validate_path_params验证 ID 格式(实现见 backend/app/routes/utils.py)。 - 认证拦截:所有请求必须携带有效 Bearer Token,
auth_info_required会根据部署模式(CONFIG.WEB或CONFIG.API)选择对应的认证校验逻辑(见 backend/app/routes/utils.py)。 - 删除成功即返回:
ops.delete(**path_params)执行完毕后直接返回ChunkDeleteResponse(),该响应模型只包含status: "success"一个字段(见 backend/app/schemas/auto/chunk_delete_response.py)。
操作层的删除实现
路由层调用的是chunk_ops.delete(),实现在 backend/app/operators/retrieval/chunk.py:
async def delete(self, **kwargs) -> None: self._check_kwargs(object_id_required=None, **kwargs) collection_id = kwargs["collection_id"] chunk_id = kwargs["chunk_id"] # delete chunk collection = await collection_ops.get(collection_id=collection_id) chunk = await self.get(collection_id=collection_id, chunk_id=chunk_id) await db_chunk.delete_chunk(chunk=chunk) await collection_ops.redis.pop(collection)其执行顺序为:先确认 Collection 存在,再按主键(collection_id, chunk_id)查出目标 Chunk,随后调用数据库层delete_chunk真正执行删除,最后清理该 Collection 在 Redis 中的缓存。值得注意的是,如果目标 Chunk 不存在,self.get()会抛出OBJECT_NOT_FOUND(404)错误,这一点在测试用例中得到了验证(见下文第四节)。
数据库层的删除与计数同步
真正的数据变更发生在 backend/app/database_ops/retrieval/chunk/delete.py 的delete_chunk()中,它在同一个数据库连接的事务语义下完成三件事:
async def delete_chunk(chunk: Chunk): chunk_table_name = Collection.get_chunk_table_name(chunk.collection_id) # 1. delete from db async with postgres_pool.get_db_connection() as conn: await conn.execute(f"DELETE FROM {chunk_table_name} WHERE chunk_id=$1;", chunk.chunk_id) # 2. update collection num_chunks await conn.execute( "UPDATE collection " "SET num_chunks = num_chunks - 1 " "WHERE collection_id=$1;", chunk.collection_id ) if chunk.record_id: # 3. update record num_chunks await conn.execute( "UPDATE record " "SET num_chunks = num_chunks - 1 " "WHERE collection_id=$1 AND record_id=$2;", chunk.collection_id, chunk.record_id, )这里有两个极易被忽略但至关重要的细节:
- 分表存储:每个 Collection 拥有独立的 chunk 数据表,表名由
Collection.get_chunk_table_name(collection_id)动态生成。因此删除时是通过拼装出的具体表名执行的,这也解释了为何删除必须同时携带collection_id与chunk_id两个主键。 - 计数自动同步:删除一条 Chunk 后,其所属 Collection 的
num_chunks自动减 1;若该 Chunk 关联了record_id(即由 Record 解析产生),所属 Record 的num_chunks同样自动减 1。这意味着你无需手动维护统计字段,只需关心业务删除动作本身。
三、与 Record 层级的关系:删除 Chunk 不删除 Record
原文档特别强调了一个数据一致性要点:如果被删除的 Chunk 是通过创建 Record 而生成的,Record 本身并不会被删除。
这一设计可以从 Record 的删除逻辑反证。在 backend/app/database_ops/retrieval/record/utils.py 中,删除 Record 时反而会级联删除其下全部 Chunk:
async def delete_record_chunks(conn, collection_id: str, record_id: str) -> int: chunk_table_name = Collection.get_chunk_table_name(collection_id) result = await conn.fetchrow( f""" SELECT COUNT(*) FROM {chunk_table_name} WHERE record_id = $1 """, record_id, ) num_chunks = result[0] or 0 await conn.execute( f""" DELETE FROM {chunk_table_name} WHERE record_id = $1 """, record_id, ) return num_chunks因此两条规则可以一并记住:
- 删除 Chunk(本文主题):仅移除该 Chunk 及关联向量数据,Record 与其余 Chunk 不受影响,Collection/Record 的
num_chunks各自减 1; - 删除 Record:会连同其下所有 Chunk 一起删除(参见 5_delete_a_record.md 对应的记录删除接口),这是由
ON DELETE CASCADE外键语义与上述delete_record_chunks逻辑共同保证的。
此外,从数据库建表脚本也能印证层级关系:backend/app/database/pg_scripts/postgres_0001.sql 中 chunk 表的collection_id CHAR(24) NOT NULL REFERENCES collection (collection_id) ON DELETE CASCADE,说明删除 Collection 会级联删除其下全部 Chunk;而 Chunk 与 Record 之间则通过(collection_id, record_id)组合外键关联(见 backend/app/database_ops/retrieval/collection/create.py)。
四、测试验证:删除成功与删除后再查询的行为
仓库中的自动化测试为删除接口的行为提供了直接证据。backend/tests/api_services/retrieval/chunk.py 封装了与 curl 等价的客户端调用:
async def delete_chunk(collection_id: str, chunk_id: str): headers = get_headers(CONFIG.Authentication) async with aiohttp.ClientSession(headers=headers) as session: request_url = f"{COLLECTION_BASE_URL}/{collection_id}/chunks/{chunk_id}" response = await session.delete(request_url) return ResponseWrapper(response.status, await response.json())对应的端到端断言位于 backend/tests/services_tests/retrieval/test_chunk.py:
@pytest.mark.run(order=157) @pytest.mark.asyncio async def test_delete_chunk(self): res = await delete_chunk(self.collection_id, Retrieval.chunk_id) res_json = res.json() assert res.status_code == 200, res.json() assert res_json.get("status") == "success" get_res = await get_chunk(self.collection_id, Retrieval.chunk_id) get_res_json = get_res.json() assert get_res.status_code == 404, get_res.json() assert get_res_json.get("status") == "error" assert get_res_json.get("error").get("code") == "OBJECT_NOT_FOUND"该测试清晰展示了两个可复现的行为:
- 删除成功的响应:HTTP 状态码为
200,响应体status为success; - 删除后立即查询:再次调用 Get Chunk 接口(
GET /v1/collections/{collection_id}/chunks/{chunk_id})会返回404与错误码OBJECT_NOT_FOUND,证实 Chunk 已被永久移除,且该错误码在 backend/tkhelper/error/error_code.py 中统一定义。
五、实战建议:删除 Chunk 的完整操作流程
结合文档模板与源码行为,建议在实际项目中按以下流程操作:
- 确认目标 ID:通过 List Chunks 接口(
GET /v1/collections/{collection_id}/chunks,见 4_list_chunks.md)按prefix_filter或equal_filter定位需要删除的 Chunk,记录其chunk_id。 - 确认删除意图:删除前明确该 Chunk 的来源——直接创建的独立 Chunk,删除后即彻底消失;由 Record 派生的 Chunk,删除后 Record 仍保留(此时建议用 List Record Chunks 接口(
GET /v1/collections/{collection_id}/records/{record_id}/chunks,见 backend/app/routes/retrieval/chunk.py)核对 Record 下剩余 Chunk)。 - 执行删除并校验:执行 curl 命令,确认返回
{"status": "success"};随后调用 Get Chunk 接口确认返回404 OBJECT_NOT_FOUND,即可认定删除成功。 - 注意容量与计数:删除会同步将 Collection 的
num_chunks减 1(Record 派生的 Chunk 同时将 Record 的num_chunks减 1),这些计数是后续 6_query_chunks.md 检索与容量判断的基础,删除后无需(也不应)手动修改。
六、与 Python SDK 调用的对应关系
同一删除操作在 Python SDK 中的写法(模板见 backend/resources/code_templates/collection/1_python/3_chunk/5_delete_a_chunk.md)与 REST 接口一一对应:
import taskingai # delete chunk taskingai.retrieval.delete_chunk( collection_id="$$COLLECTION_ID$$", chunk_id="$$CHUNK_ID$$", ) print(f"deleted chunk $$CHUNK_ID$$ from collection $$COLLECTION_ID$$")两种方式最终都落到上文分析的DELETE /v1/collections/{collection_id}/chunks/{chunk_id}路由与相同的数据库删除逻辑,语义完全一致,你可以根据应用场景(脚本自动化 vs 服务端集成)自由选择。
总结
删除 Chunk 是 TaskingAI Retrieval 数据生命周期管理中最常用的清理操作。其核心要点可以归纳为:一个 REST 接口(DELETE /v1/collections/{collection_id}/chunks/{chunk_id},携带 Bearer 认证)、两条数据规则(Chunk 永久移除;Record 派生的 Chunk 被删除后 Record 仍存在)、三处底层同步(删除行数据、Collectionnum_chunks减 1、Recordnum_chunks减 1)。理解这些源码级细节,能帮助你在构建知识库清理、增量更新与数据治理流程时,避免因对级联语义的误判而产生数据事故。
- 人工智能
- 大模型
- AI Agent
- RAG
- 后端
- 前端
【免费下载链接】TaskingAI
The open source platform for AI-native application development.
相关推荐
umap 复现性指南:随机种子、多线程与可重复嵌入的权衡
umap 复现性指南:随机种子、多线程与可重复嵌入的权衡 UMAP 是一个随机算法,其近似计算与优化过程依赖随机性,因此不同次运行可能产生略有差异的嵌入结果。本
人工智能大模型AI AgentRAG后端前端Kata Containers 与 Cloud Hypervisor 的 ConsoleConfig:串口/控制台配置模型与源码实现解析
Kata Containers 与 Cloud Hypervisor 的 ConsoleConfig:串口/控制台配置模型与源码实现解析 Kata Contai
人工智能大模型AI AgentRAG后端前端SQLModel 关系属性教程:级联删除与被动删除机制详解
SQLModel 关系属性教程:级联删除与被动删除机制详解 前言 在数据库关系设计中,如何处理关联数据的删除操作是一个常见问题。SQLModel 作为 Pyth
ORM数据库后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考