mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-05-05 09:47:47 +08:00
Refa: empty ids means no-op operation (#13439)
### What problem does this PR solve? Empty ids means no-op operation. ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) - [x] Documentation Update - [x] Refactoring --------- Co-authored-by: writinwaters <cai.keith@gmail.com>
This commit is contained in:
@ -25,6 +25,36 @@ def batch_create_datasets(client: RAGFlow, num: int) -> list[DataSet]:
|
||||
return [client.create_dataset(name=f"dataset_{i}") for i in range(num)]
|
||||
|
||||
|
||||
def delete_all_datasets(client: RAGFlow, *, page_size: int = 1000) -> None:
|
||||
# Dataset DELETE now treats null/empty ids as a no-op, so cleanup must enumerate explicit ids.
|
||||
page = 1
|
||||
dataset_ids: list[str] = []
|
||||
while True:
|
||||
datasets = client.list_datasets(page=page, page_size=page_size)
|
||||
dataset_ids.extend(dataset.id for dataset in datasets)
|
||||
if len(datasets) < page_size:
|
||||
break
|
||||
page += 1
|
||||
|
||||
if dataset_ids:
|
||||
client.delete_datasets(ids=dataset_ids)
|
||||
|
||||
|
||||
def delete_all_chats(client: RAGFlow, *, page_size: int = 1000) -> None:
|
||||
# Chat DELETE now treats null/empty ids as a no-op, so cleanup must enumerate explicit ids.
|
||||
page = 1
|
||||
chat_ids: list[str] = []
|
||||
while True:
|
||||
chats = client.list_chats(page=page, page_size=page_size)
|
||||
chat_ids.extend(chat.id for chat in chats)
|
||||
if len(chats) < page_size:
|
||||
break
|
||||
page += 1
|
||||
|
||||
if chat_ids:
|
||||
client.delete_chats(ids=chat_ids)
|
||||
|
||||
|
||||
# FILE MANAGEMENT WITHIN DATASET
|
||||
def bulk_upload_documents(dataset: DataSet, num: int, tmp_path: Path) -> list[Document]:
|
||||
document_infos = []
|
||||
@ -37,6 +67,51 @@ def bulk_upload_documents(dataset: DataSet, num: int, tmp_path: Path) -> list[Do
|
||||
return dataset.upload_documents(document_infos)
|
||||
|
||||
|
||||
def delete_all_documents(dataset: DataSet, *, page_size: int = 1000) -> None:
|
||||
# Document DELETE now treats missing/null/empty ids as a no-op, so cleanup must enumerate explicit ids.
|
||||
page = 1
|
||||
document_ids: list[str] = []
|
||||
while True:
|
||||
documents = dataset.list_documents(page=page, page_size=page_size)
|
||||
document_ids.extend(document.id for document in documents)
|
||||
if len(documents) < page_size:
|
||||
break
|
||||
page += 1
|
||||
|
||||
if document_ids:
|
||||
dataset.delete_documents(ids=document_ids)
|
||||
|
||||
|
||||
def delete_all_sessions(chat_assistant: Chat, *, page_size: int = 1000) -> None:
|
||||
# Session DELETE now treats missing/null/empty ids as a no-op, so cleanup must enumerate explicit ids.
|
||||
page = 1
|
||||
session_ids: list[str] = []
|
||||
while True:
|
||||
sessions = chat_assistant.list_sessions(page=page, page_size=page_size)
|
||||
session_ids.extend(session.id for session in sessions)
|
||||
if len(sessions) < page_size:
|
||||
break
|
||||
page += 1
|
||||
|
||||
if session_ids:
|
||||
chat_assistant.delete_sessions(ids=session_ids)
|
||||
|
||||
|
||||
def delete_all_chunks(document: Document, *, page_size: int = 1000) -> None:
|
||||
# Chunk DELETE now treats missing/null/empty ids as a no-op, so cleanup must enumerate explicit ids.
|
||||
page = 1
|
||||
chunk_ids: list[str] = []
|
||||
while True:
|
||||
chunks = document.list_chunks(page=page, page_size=page_size)
|
||||
chunk_ids.extend(chunk.id for chunk in chunks)
|
||||
if len(chunks) < page_size:
|
||||
break
|
||||
page += 1
|
||||
|
||||
if chunk_ids:
|
||||
document.delete_chunks(ids=chunk_ids)
|
||||
|
||||
|
||||
# CHUNK MANAGEMENT WITHIN DATASET
|
||||
def batch_add_chunks(document: Document, num: int) -> list[Chunk]:
|
||||
return [document.add_chunk(content=f"chunk test {i}") for i in range(num)]
|
||||
|
||||
@ -23,6 +23,10 @@ from common import (
|
||||
batch_create_chat_assistants,
|
||||
batch_create_datasets,
|
||||
bulk_upload_documents,
|
||||
delete_all_chats,
|
||||
delete_all_chunks,
|
||||
delete_all_datasets,
|
||||
delete_all_sessions,
|
||||
)
|
||||
from configs import HOST_ADDRESS, VERSION
|
||||
from pytest import FixtureRequest
|
||||
@ -88,7 +92,7 @@ def client(token: str) -> RAGFlow:
|
||||
@pytest.fixture(scope="function")
|
||||
def clear_datasets(request: FixtureRequest, client: RAGFlow):
|
||||
def cleanup():
|
||||
client.delete_datasets(ids=None)
|
||||
delete_all_datasets(client)
|
||||
|
||||
request.addfinalizer(cleanup)
|
||||
|
||||
@ -96,7 +100,7 @@ def clear_datasets(request: FixtureRequest, client: RAGFlow):
|
||||
@pytest.fixture(scope="function")
|
||||
def clear_chat_assistants(request: FixtureRequest, client: RAGFlow):
|
||||
def cleanup():
|
||||
client.delete_chats(ids=None)
|
||||
delete_all_chats(client)
|
||||
|
||||
request.addfinalizer(cleanup)
|
||||
|
||||
@ -106,7 +110,7 @@ def clear_session_with_chat_assistants(request, add_chat_assistants):
|
||||
def cleanup():
|
||||
for chat_assistant in chat_assistants:
|
||||
try:
|
||||
chat_assistant.delete_sessions(ids=None)
|
||||
delete_all_sessions(chat_assistant)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@ -118,7 +122,7 @@ def clear_session_with_chat_assistants(request, add_chat_assistants):
|
||||
@pytest.fixture(scope="class")
|
||||
def add_dataset(request: FixtureRequest, client: RAGFlow) -> DataSet:
|
||||
def cleanup():
|
||||
client.delete_datasets(ids=None)
|
||||
delete_all_datasets(client)
|
||||
|
||||
request.addfinalizer(cleanup)
|
||||
return batch_create_datasets(client, 1)[0]
|
||||
@ -127,7 +131,7 @@ def add_dataset(request: FixtureRequest, client: RAGFlow) -> DataSet:
|
||||
@pytest.fixture(scope="function")
|
||||
def add_dataset_func(request: FixtureRequest, client: RAGFlow) -> DataSet:
|
||||
def cleanup():
|
||||
client.delete_datasets(ids=None)
|
||||
delete_all_datasets(client)
|
||||
|
||||
request.addfinalizer(cleanup)
|
||||
return batch_create_datasets(client, 1)[0]
|
||||
@ -142,7 +146,7 @@ def add_document(add_dataset: DataSet, ragflow_tmp_dir: Path) -> tuple[DataSet,
|
||||
def add_chunks(request: FixtureRequest, add_document: tuple[DataSet, Document]) -> tuple[DataSet, Document, list[Chunk]]:
|
||||
def cleanup():
|
||||
try:
|
||||
document.delete_chunks(ids=[])
|
||||
delete_all_chunks(document)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@ -161,7 +165,7 @@ def add_chunks(request: FixtureRequest, add_document: tuple[DataSet, Document])
|
||||
def add_chat_assistants(request, client, add_document) -> tuple[DataSet, Document, list[Chat]]:
|
||||
def cleanup():
|
||||
try:
|
||||
client.delete_chats(ids=None)
|
||||
delete_all_chats(client)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
import pytest
|
||||
from common import batch_create_chat_assistants
|
||||
from common import batch_create_chat_assistants, delete_all_chats
|
||||
from pytest import FixtureRequest
|
||||
from ragflow_sdk import Chat, DataSet, Document, RAGFlow
|
||||
from utils import wait_for
|
||||
@ -32,7 +32,7 @@ def condition(_dataset: DataSet):
|
||||
@pytest.fixture(scope="function")
|
||||
def add_chat_assistants_func(request: FixtureRequest, client: RAGFlow, add_document: tuple[DataSet, Document]) -> tuple[DataSet, Document, list[Chat]]:
|
||||
def cleanup():
|
||||
client.delete_chats(ids=None)
|
||||
delete_all_chats(client)
|
||||
|
||||
request.addfinalizer(cleanup)
|
||||
|
||||
|
||||
@ -23,8 +23,8 @@ class TestChatAssistantsDelete:
|
||||
@pytest.mark.parametrize(
|
||||
"payload, expected_message, remaining",
|
||||
[
|
||||
pytest.param(None, "", 0, marks=pytest.mark.p3),
|
||||
pytest.param({"ids": []}, "", 0, marks=pytest.mark.p3),
|
||||
pytest.param(None, "", 5, marks=pytest.mark.p3),
|
||||
pytest.param({"ids": []}, "", 5, marks=pytest.mark.p3),
|
||||
pytest.param({"ids": ["invalid_id"]}, "Assistant(invalid_id) not found.", 5, marks=pytest.mark.p3),
|
||||
pytest.param({"ids": ["\n!?。;!?\"'"]}, """Assistant(\n!?。;!?"\') not found.""", 5, marks=pytest.mark.p3),
|
||||
pytest.param(lambda r: {"ids": r[:1]}, "", 4, marks=pytest.mark.p3),
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
from time import sleep
|
||||
|
||||
import pytest
|
||||
from common import batch_add_chunks
|
||||
from common import batch_add_chunks, delete_all_chunks
|
||||
from pytest import FixtureRequest
|
||||
from ragflow_sdk import Chunk, DataSet, Document
|
||||
from utils import wait_for
|
||||
@ -37,7 +37,7 @@ def condition(_dataset: DataSet):
|
||||
def add_chunks_func(request: FixtureRequest, add_document: tuple[DataSet, Document]) -> tuple[DataSet, Document, list[Chunk]]:
|
||||
def cleanup():
|
||||
try:
|
||||
document.delete_chunks(ids=[])
|
||||
delete_all_chunks(document)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
@ -88,12 +88,12 @@ class TestChunksDeletion:
|
||||
@pytest.mark.parametrize(
|
||||
"payload, expected_message, remaining",
|
||||
[
|
||||
pytest.param(None, "TypeError", 5, marks=pytest.mark.skip),
|
||||
pytest.param(None, "", 5, marks=pytest.mark.p3),
|
||||
pytest.param({"ids": ["invalid_id"]}, "rm_chunk deleted chunks 0, expect 1", 5, marks=pytest.mark.p3),
|
||||
pytest.param("not json", "UnboundLocalError", 5, marks=pytest.mark.skip(reason="pull/6376")),
|
||||
pytest.param(lambda r: {"ids": r[:1]}, "", 4, marks=pytest.mark.p3),
|
||||
pytest.param(lambda r: {"ids": r}, "", 1, marks=pytest.mark.p1),
|
||||
pytest.param({"ids": []}, "", 0, marks=pytest.mark.p3),
|
||||
pytest.param({"ids": []}, "", 5, marks=pytest.mark.p3),
|
||||
],
|
||||
)
|
||||
def test_basic_scenarios(self, add_chunks_func, payload, expected_message, remaining):
|
||||
@ -107,7 +107,10 @@ class TestChunksDeletion:
|
||||
document.delete_chunks(**payload)
|
||||
assert expected_message in str(exception_info.value), str(exception_info.value)
|
||||
else:
|
||||
document.delete_chunks(**payload)
|
||||
if payload is None:
|
||||
document.delete_chunks()
|
||||
else:
|
||||
document.delete_chunks(**payload)
|
||||
|
||||
remaining_chunks = document.list_chunks()
|
||||
assert len(remaining_chunks) == remaining, str(remaining_chunks)
|
||||
|
||||
@ -16,13 +16,13 @@
|
||||
|
||||
|
||||
import pytest
|
||||
from common import batch_create_datasets
|
||||
from common import batch_create_datasets, delete_all_datasets
|
||||
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def add_datasets(client, request):
|
||||
def cleanup():
|
||||
client.delete_datasets(**{"ids": None})
|
||||
delete_all_datasets(client)
|
||||
|
||||
request.addfinalizer(cleanup)
|
||||
|
||||
@ -32,7 +32,7 @@ def add_datasets(client, request):
|
||||
@pytest.fixture(scope="function")
|
||||
def add_datasets_func(client, request):
|
||||
def cleanup():
|
||||
client.delete_datasets(**{"ids": None})
|
||||
delete_all_datasets(client)
|
||||
|
||||
request.addfinalizer(cleanup)
|
||||
|
||||
|
||||
@ -95,7 +95,7 @@ class TestDatasetsDelete:
|
||||
client.delete_datasets(**payload)
|
||||
|
||||
datasets = client.list_datasets()
|
||||
assert len(datasets) == 0, str(datasets)
|
||||
assert len(datasets) == 3, str(datasets)
|
||||
|
||||
@pytest.mark.p2
|
||||
@pytest.mark.usefixtures("add_dataset_func")
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
|
||||
|
||||
import pytest
|
||||
from common import bulk_upload_documents
|
||||
from common import bulk_upload_documents, delete_all_documents
|
||||
from pytest import FixtureRequest
|
||||
from ragflow_sdk import DataSet, Document
|
||||
|
||||
@ -27,7 +27,7 @@ def add_document_func(request: FixtureRequest, add_dataset: DataSet, ragflow_tmp
|
||||
documents = bulk_upload_documents(dataset, 1, ragflow_tmp_dir)
|
||||
|
||||
def cleanup():
|
||||
dataset.delete_documents(ids=None)
|
||||
delete_all_documents(dataset)
|
||||
|
||||
request.addfinalizer(cleanup)
|
||||
return dataset, documents[0]
|
||||
@ -39,7 +39,7 @@ def add_documents(request: FixtureRequest, add_dataset: DataSet, ragflow_tmp_dir
|
||||
documents = bulk_upload_documents(dataset, 5, ragflow_tmp_dir)
|
||||
|
||||
def cleanup():
|
||||
dataset.delete_documents(ids=None)
|
||||
delete_all_documents(dataset)
|
||||
|
||||
request.addfinalizer(cleanup)
|
||||
return dataset, documents
|
||||
@ -51,7 +51,7 @@ def add_documents_func(request: FixtureRequest, add_dataset_func: DataSet, ragfl
|
||||
documents = bulk_upload_documents(dataset, 3, ragflow_tmp_dir)
|
||||
|
||||
def cleanup():
|
||||
dataset.delete_documents(ids=None)
|
||||
delete_all_documents(dataset)
|
||||
|
||||
request.addfinalizer(cleanup)
|
||||
return dataset, documents
|
||||
|
||||
@ -24,8 +24,8 @@ class TestDocumentsDeletion:
|
||||
@pytest.mark.parametrize(
|
||||
"payload, expected_message, remaining",
|
||||
[
|
||||
({"ids": None}, "", 0),
|
||||
({"ids": []}, "", 0),
|
||||
({"ids": None}, "", 3),
|
||||
({"ids": []}, "", 3),
|
||||
({"ids": ["invalid_id"]}, "Documents not found: ['invalid_id']", 3),
|
||||
({"ids": ["\n!?。;!?\"'"]}, "Documents not found: ['\\n!?。;!?\"\\'']", 3),
|
||||
("not json", "must be a mapping", 3),
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
import pytest
|
||||
from common import batch_add_sessions_with_chat_assistant
|
||||
from common import batch_add_sessions_with_chat_assistant, delete_all_sessions
|
||||
from pytest import FixtureRequest
|
||||
from ragflow_sdk import Chat, DataSet, Document, Session
|
||||
|
||||
@ -24,7 +24,7 @@ def add_sessions_with_chat_assistant(request: FixtureRequest, add_chat_assistant
|
||||
def cleanup():
|
||||
for chat_assistant in chat_assistants:
|
||||
try:
|
||||
chat_assistant.delete_sessions(ids=None)
|
||||
delete_all_sessions(chat_assistant)
|
||||
except Exception :
|
||||
pass
|
||||
|
||||
@ -39,7 +39,7 @@ def add_sessions_with_chat_assistant_func(request: FixtureRequest, add_chat_assi
|
||||
def cleanup():
|
||||
for chat_assistant in chat_assistants:
|
||||
try:
|
||||
chat_assistant.delete_sessions(ids=None)
|
||||
delete_all_sessions(chat_assistant)
|
||||
except Exception :
|
||||
pass
|
||||
|
||||
|
||||
@ -84,12 +84,12 @@ class TestSessionWithChatAssistantDelete:
|
||||
@pytest.mark.parametrize(
|
||||
"payload, expected_message, remaining",
|
||||
[
|
||||
pytest.param(None, """TypeError("argument of type \'NoneType\' is not iterable")""", 0, marks=pytest.mark.skip),
|
||||
pytest.param(None, "", 5, marks=pytest.mark.p3),
|
||||
pytest.param({"ids": ["invalid_id"]}, "The chat doesn't own the session invalid_id", 5, marks=pytest.mark.p3),
|
||||
pytest.param("not json", """AttributeError("\'str\' object has no attribute \'get\'")""", 5, marks=pytest.mark.skip),
|
||||
pytest.param(lambda r: {"ids": r[:1]}, "", 4, marks=pytest.mark.p3),
|
||||
pytest.param(lambda r: {"ids": r}, "", 0, marks=pytest.mark.p1),
|
||||
pytest.param({"ids": []}, "", 0, marks=pytest.mark.p3),
|
||||
pytest.param({"ids": []}, "", 5, marks=pytest.mark.p3),
|
||||
],
|
||||
)
|
||||
def test_basic_scenarios(self, add_sessions_with_chat_assistant_func, payload, expected_message, remaining):
|
||||
@ -102,7 +102,10 @@ class TestSessionWithChatAssistantDelete:
|
||||
chat_assistant.delete_sessions(**payload)
|
||||
assert expected_message in str(exception_info.value)
|
||||
else:
|
||||
chat_assistant.delete_sessions(**payload)
|
||||
if payload is None:
|
||||
chat_assistant.delete_sessions()
|
||||
else:
|
||||
chat_assistant.delete_sessions(**payload)
|
||||
|
||||
sessions = chat_assistant.list_sessions()
|
||||
assert len(sessions) == remaining
|
||||
|
||||
Reference in New Issue
Block a user