Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions src/services/docling_service.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import asyncio
import json
from dataclasses import dataclass
from enum import Enum
import platform
from dataclasses import dataclass
from enum import StrEnum
from pathlib import Path
Comment on lines 3 to 6
from typing import Any

Expand All @@ -29,12 +29,11 @@ class DoclingConfig(BaseModel):
picture_description_local: dict | None = None



class DoclingServeError(Exception):
"""Raised when docling-serve conversion fails."""


class DoclingTaskState(str, Enum):
class DoclingTaskState(StrEnum):
"""Result of a single status check against Docling Serve."""

PENDING = "pending"
Expand All @@ -49,8 +48,8 @@ class DoclingStatusSnapshot:
"""Single-point-in-time view of a Docling task's state."""

state: DoclingTaskState
detail: Optional[str] = None
raw: Optional[dict] = None
detail: str | None = None
raw: dict | None = None


def get_docling_preset_configs(
Expand Down Expand Up @@ -78,7 +77,7 @@ class DoclingService:
_default_client: httpx.AsyncClient | None = None

def __init__(
self, docling_url: Optional[str] = None, httpx_client: Optional[httpx.AsyncClient] = None
self, docling_url: str | None = None, httpx_client: httpx.AsyncClient | None = None
):
"""
Initialize the DoclingService.
Expand Down Expand Up @@ -268,7 +267,7 @@ async def check_task_status(self, task_id: str) -> DoclingStatusSnapshot:
return DoclingStatusSnapshot(state=DoclingTaskState.PROCESSING, raw=payload)
return DoclingStatusSnapshot(state=DoclingTaskState.PENDING, raw=payload)

async def fetch_task_result(self, task_id: str) -> Dict[str, Any]:
async def fetch_task_result(self, task_id: str) -> dict[str, Any]:
"""
Fetch the converted document for a Docling task that is already SUCCESS.

Expand Down
38 changes: 22 additions & 16 deletions src/services/langflow_file_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def merge_ui_ingest_settings_into_tweaks(

return final_tweaks

async def upload_user_file(self, file_tuple, jwt_token: Optional[str] = None) -> Dict[str, Any]:
async def upload_user_file(self, file_tuple, jwt_token: str | None = None) -> dict[str, Any]:
"""Upload a file using Langflow Files API v2: POST /api/v2/files.
Returns JSON with keys: id, name, path, size, provider.
"""
Expand Down Expand Up @@ -515,8 +515,13 @@ async def _ensure_url_ingest_flow_id(self) -> str:
raise last_error
raise RuntimeError("Unable to validate/import URL ingest flow")

async def submit_to_docling(self, filename: str, content: bytes, jwt_token: Optional[str] = None,
owner: Optional[str] = None,) -> str:
async def submit_to_docling(
self,
filename: str,
content: bytes,
jwt_token: str | None = None,
owner: str | None = None,
) -> str:
"""Upload a file to Docling Serve and return the task_id immediately.

Phase 1 of the two-phase ingestion model. The caller is responsible
Expand All @@ -531,6 +536,7 @@ async def submit_to_docling(self, filename: str, content: bytes, jwt_token: Opti
try:
task_id = await self.docling_service.upload_to_docling_direct_async(
filename, content, user_id=owner, auth_header=jwt_token
)
logger.debug(
"[LF] Docling submission accepted",
extra={"task_id": task_id, "filename": filename},
Expand All @@ -541,22 +547,22 @@ async def submit_to_docling(self, filename: str, content: bytes, jwt_token: Opti
"[LF] Docling submission failed",
extra={"error": str(e), "filename": filename},
)
raise Exception(f"Docling upload failed: {str(e)}")
raise Exception(f"Docling upload failed: {str(e)}") from e

async def upload_and_ingest_file(
self,
file_tuple,
session_id: Optional[str] = None,
tweaks: Optional[Dict[str, Any]] = None,
settings: Optional[Dict[str, Any]] = None,
jwt_token: Optional[str] = None,
owner: Optional[str] = None,
owner_name: Optional[str] = None,
owner_email: Optional[str] = None,
connector_type: Optional[str] = None,
docling_polling_service: Optional[Any] = None,
file_task: Optional[Any] = None,
) -> Dict[str, Any]:
session_id: str | None = None,
tweaks: dict[str, Any] | None = None,
settings: dict[str, Any] | None = None,
jwt_token: str | None = None,
owner: str | None = None,
owner_name: str | None = None,
owner_email: str | None = None,
connector_type: str | None = None,
docling_polling_service: Any | None = None,
file_task: Any | None = None,
) -> dict[str, Any]:
"""
Two-phase Docling upload + Langflow ingest operation.

Expand Down Expand Up @@ -591,7 +597,7 @@ async def upload_and_ingest_file(
file_task.phase = IngestionPhase.DOCLING
file_task.docling_status = DoclingPhaseStatus.PENDING

task_id = await self.submit_to_docling(filename, content,user_id=owner, auth_header=jwt_token)
task_id = await self.submit_to_docling(filename, content, owner=owner, jwt_token=jwt_token)

if file_task is not None:
file_task.docling_task_id = task_id
Expand Down
Loading