Files
dify/api/services/knowledge/external/application.py

105 lines
4.5 KiB
Python

"""External knowledge use cases without transport or persistence dependencies."""
from collections.abc import Mapping
from typing import Any, Protocol
from machinery.context import RequestContext
from services.entities.external_knowledge_entities.external_knowledge_entities import ExternalDatasetCreatePayload
from services.knowledge.dataset_access import DatasetAccess
from services.knowledge.entities.datasets import DatasetDetailRecord
from services.knowledge.resource_scope import DatasetRef
class ExternalTemplateNotFoundError(Exception):
pass
class ExternalHitTestingError(Exception):
pass
class ExternalKnowledgeOperations(Protocol):
def list_templates(self, workspace_id: str, *, page: int, limit: int, keyword: str | None) -> dict[str, Any]: ...
def get_template(self, workspace_id: str, template_id: str) -> dict[str, Any]: ...
def create_template(self, context: RequestContext, *, name: str, settings: Mapping[str, Any]) -> dict[str, Any]: ...
def update_template(
self, context: RequestContext, template_id: str, *, name: str, settings: Mapping[str, Any]
) -> dict[str, Any]: ...
def delete_template(self, workspace_id: str, template_id: str) -> None: ...
def template_usage(self, workspace_id: str, template_id: str) -> tuple[bool, int]: ...
def create_dataset(self, context: RequestContext, payload: ExternalDatasetCreatePayload) -> DatasetDetailRecord: ...
def retrieve(
self,
context: RequestContext,
ref: DatasetRef,
*,
query: str,
retrieval_model: dict[str, Any] | None,
metadata_filters: dict[str, Any] | None,
) -> dict[str, Any]: ...
class ExternalKnowledgeApplicationService:
def __init__(self, *, dataset_access: DatasetAccess, operations: ExternalKnowledgeOperations) -> None:
self._dataset_access = dataset_access
self._operations = operations
@staticmethod
def _validate_settings(settings: Mapping[str, Any]) -> None:
if not settings:
raise ValueError("api list is empty")
if not settings.get("endpoint"):
raise ValueError("endpoint is required")
if not settings.get("api_key"):
raise ValueError("api_key is required")
def list_templates(self, context: RequestContext, *, page: int, limit: int, keyword: str | None) -> dict[str, Any]:
return self._operations.list_templates(context.active_workspace_id, page=page, limit=limit, keyword=keyword)
def get_template(self, context: RequestContext, *, template_id: str) -> dict[str, Any]:
return self._operations.get_template(context.active_workspace_id, template_id)
def create_template(self, context: RequestContext, *, name: str, settings: Mapping[str, Any]) -> dict[str, Any]:
self._validate_settings(settings)
return self._operations.create_template(context, name=name, settings=settings)
def update_template(
self, context: RequestContext, *, template_id: str, name: str, settings: Mapping[str, Any]
) -> dict[str, Any]:
self._validate_settings(settings)
return self._operations.update_template(context, template_id, name=name, settings=settings)
def delete_template(self, context: RequestContext, *, template_id: str) -> None:
self._operations.delete_template(context.active_workspace_id, template_id)
def template_usage(self, context: RequestContext, *, template_id: str) -> tuple[bool, int]:
return self._operations.template_usage(context.active_workspace_id, template_id)
def create_dataset(self, context: RequestContext, *, payload: ExternalDatasetCreatePayload) -> DatasetDetailRecord:
return self._operations.create_dataset(context, payload)
def hit_testing(
self,
context: RequestContext,
*,
dataset_id: str,
query: str,
retrieval_model: dict[str, Any] | None,
metadata_filters: dict[str, Any] | None,
) -> dict[str, Any]:
dataset = self._dataset_access.require_accessible(context, dataset_id)
if not query:
raise ValueError("Query or attachment_ids is required")
if len(query) > 250:
raise ValueError("Query cannot exceed 250 characters")
try:
return self._operations.retrieve(
context,
DatasetRef(dataset.workspace_id, dataset.id),
query=query,
retrieval_model=retrieval_model,
metadata_filters=metadata_filters,
)
except Exception as error:
raise ExternalHitTestingError(str(error)) from error