Files
dify/api/fields/document_fields.py
T
2026-07-15 06:48:28 +00:00

150 lines
4.6 KiB
Python

"""Response schemas for dataset document endpoints."""
from collections.abc import Iterable
from dataclasses import dataclass
from datetime import datetime
from typing import Any
from pydantic import Field, field_validator
from sqlalchemy.orm import Session
from fields.base import ResponseModel
from libs.helper import to_timestamp
from models.dataset import DocMetadataDetailItem, Document
def normalize_enum(value: Any) -> Any:
if isinstance(value, str) or value is None:
return value
return getattr(value, "value", value)
class DocumentMetadataResponse(ResponseModel):
id: str
name: str
type: str
value: str | int | float | bool | None = None
class DocumentResponse(ResponseModel):
id: str
position: int | None = None
data_source_type: str | None = None
data_source_info: Any = Field(default=None, validation_alias="data_source_info_dict")
data_source_detail_dict: Any = None
dataset_process_rule_id: str | None = None
name: str
created_from: str | None = None
created_by: str | None = None
created_at: int | None = None
tokens: int | None = None
indexing_status: str | None = None
error: str | None = None
enabled: bool | None = None
disabled_at: int | None = None
disabled_by: str | None = None
archived: bool | None = None
display_status: str | None = None
word_count: int | None = None
hit_count: int | None = None
doc_form: str | None = None
doc_metadata: list[DocumentMetadataResponse] = Field(default_factory=list, validation_alias="doc_metadata_details")
summary_index_status: str | None = None
need_summary: bool | None = None
@field_validator("data_source_type", "indexing_status", "display_status", "doc_form", mode="before")
@classmethod
def _normalize_enum_fields(cls, value: Any) -> Any:
return normalize_enum(value)
@field_validator("doc_metadata", mode="before")
@classmethod
def _normalize_doc_metadata(cls, value: Any) -> list[Any]:
if value is None:
return []
return value
@field_validator("created_at", "disabled_at", mode="before")
@classmethod
def _normalize_timestamp(cls, value: datetime | int | None) -> int | None:
return to_timestamp(value)
@dataclass(frozen=True)
class DocumentWithSession:
"""Expose session-backed document fields during response validation."""
document: Document
session: Session
@property
def data_source_detail_dict(self) -> dict[str, Any]:
return self.document.get_data_source_detail_dict(session=self.session)
@property
def hit_count(self) -> int:
return self.document.get_hit_count(session=self.session)
@property
def doc_metadata_details(self) -> list[DocMetadataDetailItem] | None:
return self.document.get_doc_metadata_details(session=self.session)
def __getattr__(self, name: str) -> Any:
return getattr(self.document, name) # noqa: no-new-getattr response adapter delegates model fields
def document_response(document: Document, *, session: Session) -> DocumentResponse:
return DocumentResponse.model_validate(
DocumentWithSession(document=document, session=session), from_attributes=True
)
def document_responses(documents: Iterable[Document], *, session: Session) -> list[DocumentResponse]:
return [document_response(document, session=session) for document in documents]
class DocumentListResponse(ResponseModel):
data: list[DocumentResponse]
has_more: bool
limit: int
total: int
page: int
class DocumentStatusResponse(ResponseModel):
id: str
indexing_status: str
processing_started_at: int | None
parsing_completed_at: int | None
cleaning_completed_at: int | None
splitting_completed_at: int | None
completed_at: int | None
paused_at: int | None
error: str | None
stopped_at: int | None
completed_segments: int | None = None
total_segments: int | None = None
@field_validator("indexing_status", mode="before")
@classmethod
def _normalize_indexing_status(cls, value: Any) -> Any:
return normalize_enum(value)
@field_validator(
"processing_started_at",
"parsing_completed_at",
"cleaning_completed_at",
"splitting_completed_at",
"completed_at",
"paused_at",
"stopped_at",
mode="before",
)
@classmethod
def _normalize_timestamp(cls, value: datetime | int | None) -> int | None:
return to_timestamp(value)
class DocumentStatusListResponse(ResponseModel):
data: list[DocumentStatusResponse]