mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-07-30 04:29:24 +08:00
Feat: More APIs for compiler list and deletion of compilation result. (#17425)
### Summary More APIs for comliler list and deletion of compilation result.
This commit is contained in:
@@ -671,6 +671,12 @@ def prompts():
|
||||
)
|
||||
|
||||
|
||||
# Synthetic ``canvas_category`` the frontend passes to list compilation template
|
||||
# groups through the merged /agents endpoint. Also the ``type`` discriminator
|
||||
# stamped on group items in the merged response.
|
||||
_COMPILATION_TEMPLATE_GROUP_CATEGORY = "compilation_template_group"
|
||||
|
||||
|
||||
@manager.route("/agents", methods=["GET"]) # noqa: F821
|
||||
@login_required
|
||||
@add_tenant_id_to_kwargs
|
||||
@@ -702,6 +708,75 @@ def list_agents(tenant_id):
|
||||
else:
|
||||
effective_owner_ids = list(authorized_owner_ids)
|
||||
|
||||
# Groups-only: an explicit ``compilation_template_group`` category returns
|
||||
# just the caller's template groups (no agents) via list_saved, so the
|
||||
# frontend can render a dedicated tab. list_saved paginates in Python.
|
||||
if canvas_category == _COMPILATION_TEMPLATE_GROUP_CATEGORY:
|
||||
from api.db.services.compilation_template_group_service import CompilationTemplateGroupService
|
||||
|
||||
try:
|
||||
groups = CompilationTemplateGroupService.list_saved(tenant_id, keywords, "", order_by, desc)
|
||||
except Exception:
|
||||
logging.exception("list_agents: compilation template group list failed for tenant=%s", tenant_id)
|
||||
groups = []
|
||||
for group in groups:
|
||||
group["type"] = _COMPILATION_TEMPLATE_GROUP_CATEGORY
|
||||
total = len(groups)
|
||||
if page_number and items_per_page:
|
||||
start = (page_number - 1) * items_per_page
|
||||
groups = groups[start : start + items_per_page]
|
||||
return get_json_result(data={"canvas": groups, "total": total})
|
||||
|
||||
# Merge mode: with no ``canvas_category`` (and no agent-only filters), list
|
||||
# the caller's compilation template groups alongside agents, interleaved by
|
||||
# ``update_time``. ``canvas_type`` / ``tags`` are agent-only concepts, so
|
||||
# their presence keeps the response agent-only.
|
||||
merge_groups = not canvas_category and not canvas_type and not tags
|
||||
if merge_groups:
|
||||
from api.db.services.compilation_template_group_service import CompilationTemplateGroupService
|
||||
|
||||
# Fetch every matching agent (page_number=0 disables SQL pagination) so
|
||||
# the two sources can be globally ordered before we page in Python.
|
||||
agents, _ = UserCanvasService.get_by_tenant_ids(
|
||||
effective_owner_ids,
|
||||
tenant_id,
|
||||
0,
|
||||
0,
|
||||
order_by,
|
||||
desc,
|
||||
keywords,
|
||||
None,
|
||||
tags,
|
||||
canvas_type,
|
||||
)
|
||||
# Groups are owner-only (no team sharing), so they're scoped to the
|
||||
# caller. Keyword filters the group name; scope is left unfiltered.
|
||||
try:
|
||||
groups = CompilationTemplateGroupService.list_saved(tenant_id, keywords, "", order_by, desc)
|
||||
except Exception:
|
||||
logging.exception("list_agents: compilation template group merge failed for tenant=%s", tenant_id)
|
||||
groups = []
|
||||
|
||||
items: list[dict] = []
|
||||
for agent in agents:
|
||||
agent["type"] = "agent"
|
||||
items.append(agent)
|
||||
for group in groups:
|
||||
group["type"] = _COMPILATION_TEMPLATE_GROUP_CATEGORY
|
||||
group["title"] = group["name"]
|
||||
items.append(group)
|
||||
|
||||
# Interleave by update_time (the requested merge key); items missing the
|
||||
# field sort as oldest.
|
||||
items.sort(key=lambda item: item.get("update_time") or 0, reverse=desc)
|
||||
|
||||
total = len(items)
|
||||
if page_number and items_per_page:
|
||||
start = (page_number - 1) * items_per_page
|
||||
items = items[start : start + items_per_page]
|
||||
|
||||
return get_json_result(data={"canvas": items, "total": total})
|
||||
|
||||
canvas, total = UserCanvasService.get_by_tenant_ids(
|
||||
effective_owner_ids,
|
||||
tenant_id,
|
||||
|
||||
@@ -747,6 +747,47 @@ async def get_dataset_structure(tenant_id, dataset_id):
|
||||
return get_error_data_result(message="Internal server error")
|
||||
|
||||
|
||||
@manager.route("/datasets/<dataset_id>/artifacts_structure", methods=["DELETE"]) # noqa: F821
|
||||
@login_required
|
||||
@add_tenant_id_to_kwargs
|
||||
def delete_dataset_structure(tenant_id, dataset_id):
|
||||
"""Delete the dataset-scope (KB-wide) structure graph for one kind.
|
||||
|
||||
DELETE /api/v1/datasets/<dataset_id>/artifacts_structure?kind=<kind>
|
||||
Optional query param: wipe=false cancels the task without deleting stored rows.
|
||||
"""
|
||||
kind = request.args.get("kind", "")
|
||||
if isinstance(kind, str):
|
||||
kind = kind.strip()
|
||||
if not kind:
|
||||
return get_error_data_result(
|
||||
message="`kind` is required (one of: graph, mindmap, timeline, session_essence, session_graph).",
|
||||
code=RetCode.ARGUMENT_ERROR,
|
||||
)
|
||||
if dataset_api_service._resolve_dataset_structure_kind(kind) is None:
|
||||
return get_error_data_result(
|
||||
message=f"Unsupported structure kind: {kind!r}. Expected one of: graph, mindmap, timeline, session_essence, session_graph.",
|
||||
code=RetCode.ARGUMENT_ERROR,
|
||||
)
|
||||
wipe_arg = (request.args.get("wipe", "true") or "true").strip().lower()
|
||||
wipe = wipe_arg not in ("false", "0", "no", "off")
|
||||
try:
|
||||
success, result = dataset_api_service.delete_dataset_structure(
|
||||
dataset_id,
|
||||
tenant_id,
|
||||
kind,
|
||||
wipe=wipe,
|
||||
)
|
||||
if success:
|
||||
return get_result(data=result)
|
||||
if result == "No authorization.":
|
||||
return get_result(data=False, message=result, code=RetCode.AUTHENTICATION_ERROR)
|
||||
return get_error_data_result(message=result)
|
||||
except Exception as e:
|
||||
logging.exception(e)
|
||||
return get_error_data_result(message="Internal server error")
|
||||
|
||||
|
||||
@manager.route("/datasets/<dataset_id>/artifacts/alteration", methods=["GET"]) # noqa: F821
|
||||
@login_required
|
||||
@add_tenant_id_to_kwargs
|
||||
|
||||
@@ -1721,6 +1721,13 @@ _DATASET_STRUCTURE_KIND_ALIASES = {
|
||||
"session_essence": "session_essence",
|
||||
"session_graph": "session_graph",
|
||||
}
|
||||
_DATASET_STRUCTURE_KIND_TO_INDEX_TYPE = {
|
||||
"knowledge_graph": "structure_graph",
|
||||
"mind_map": "structure_mindmap",
|
||||
"timeline": "timeline",
|
||||
"session_essence": "session_essence",
|
||||
"session_graph": "session_graph",
|
||||
}
|
||||
|
||||
|
||||
def _resolve_dataset_structure_kind(kind) -> str | None:
|
||||
@@ -1730,6 +1737,15 @@ def _resolve_dataset_structure_kind(kind) -> str | None:
|
||||
return _DATASET_STRUCTURE_KIND_ALIASES.get(kind.strip().lower().replace("-", "_"))
|
||||
|
||||
|
||||
def delete_dataset_structure(dataset_id: str, tenant_id: str, kind: str, wipe: bool = True):
|
||||
"""Delete the merged KB-wide structure rows for one artifacts_structure kind."""
|
||||
resolved_kind = _resolve_dataset_structure_kind(kind)
|
||||
if not resolved_kind:
|
||||
return False, f"Unsupported structure kind: {kind!r}. Expected one of: graph, mindmap, timeline, session_essence, session_graph."
|
||||
index_type = _DATASET_STRUCTURE_KIND_TO_INDEX_TYPE[resolved_kind]
|
||||
return delete_index(dataset_id, tenant_id, index_type, wipe=wipe)
|
||||
|
||||
|
||||
async def get_dataset_structure(dataset_id: str, tenant_id: str, kind: str, keywords: str = ""):
|
||||
"""Load the dataset-scope (KB-wide) structure graph for one ``kind``.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user