-
Notifications
You must be signed in to change notification settings - Fork 8
Added Docling Service #38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
PrakharG-kore
wants to merge
14
commits into
master
Choose a base branch
from
user/prakhar/Docling_service
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
d416fcf
Add files via upload
PrakharG-kore fc654e6
updated Docling Service
PrakharG-kore 9ace278
Delete DOCLING_SERVICES directory
PrakharG-kore 8396e3f
Delete Utilities/DOCLING_SERVICES directory
PrakharG-kore 6cceaf4
Added updated Docling Service
PrakharG-kore f121e13
Update README.md
PrakharG-kore 31b3258
Delete Utilities/DOCLING_SERVICES/app/__pycache__ directory
vivekj-kore a1e5eb1
Delete Utilities/DOCLING_SERVICES/app/utils/__pycache__ directory
vivekj-kore 2bb6a67
Delete Utilities/DOCLING_SERVICES/app/models/__pycache__ directory
vivekj-kore d554d10
Delete Utilities/DOCLING_SERVICES/app/routes/__pycache__ directory
vivekj-kore 6318855
Delete Utilities/DOCLING_SERVICES/app/services/__pycache__ directory
vivekj-kore 3ab9cc1
Delete Utilities/DOCLING_SERVICES/ocindex_profile_france_2023.pdf
vivekj-kore 212b734
refactor: Consolidated health check into pdf_processing.py and enhanc…
e7dc0fc
refactor: Remove health router import from main.py after consolidation
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| # DOCLING_SERVICES | ||
|
|
||
| ## Overview | ||
|
|
||
| DOCLING_SERVICES is a FastAPI-based application designed to process PDF files and convert them into Markdown format. It leverages the Docling library for efficient document conversion and provides a simple API for seamless integration. | ||
|
|
||
| ## Features | ||
|
|
||
| - **PDF to Markdown Conversion:** Easily convert PDF documents to Markdown. | ||
| - **Concurrent Processing:** Handles multiple PDF processing tasks concurrently. | ||
| - **Configurable Settings:** Customize host, port, and other parameters via `config.json` or environment variables. | ||
| - **Logging:** Comprehensive logging for monitoring and debugging. | ||
|
|
||
| ## Setup | ||
|
|
||
| ### Prerequisites | ||
|
|
||
| - Python 3.8 or higher | ||
| - Git | ||
|
|
||
| **Configure Environment (Optional)** | ||
|
|
||
| Customize settings by editing `config.json` or setting environment variables. Default configurations are provided in `config.json`. | ||
|
|
||
| ## Running the Service | ||
|
|
||
| ### Using the Setup Script | ||
|
|
||
| Execute the setup and run the service: | ||
|
|
||
| 1. **Clone the Repository** | ||
| ```bash | ||
| git clone <repository-url> | ||
| cd DOCLING_SERVICES | ||
| ``` | ||
|
|
||
| 2. **Install Dependencies** | ||
| ```bash | ||
| ./setup.sh | ||
| ``` | ||
|
|
||
| ### Manually Starting the Service | ||
|
|
||
| Ensure the virtual environment is activated, then run: | ||
| ```bash | ||
| python -m app.main | ||
| ``` | ||
|
|
||
| The service will start on the host and port specified in `config.json` (default is `0.0.0.0:8000`). | ||
|
|
||
| ## Usage | ||
|
|
||
| ### API Endpoint | ||
|
|
||
| - **POST** `/process-pdf-markdown/` | ||
|
|
||
| Upload a PDF file to convert it into Markdown format. | ||
|
|
||
| ### Example `curl` Command | ||
|
|
||
| ```bash | ||
| curl -X POST "http://0.0.0.0:8000/process-pdf-markdown/" \ | ||
| -H "accept: application/json" \ | ||
| -H "Content-Type: multipart/form-data" \ | ||
| -F "file=@/path/to/your/document.pdf" | ||
| ``` | ||
|
|
||
| ### Response Format | ||
|
|
||
| Upon successful processing, the API returns a JSON response: | ||
|
|
||
| ```json | ||
| { | ||
| "status": "success", | ||
| "chunks": [ | ||
| { | ||
| "chunkText": "Markdown content of page 1", | ||
| "filename": "document.pdf", | ||
| "page_number": 1 | ||
| }, | ||
| { | ||
| "chunkText": "Markdown content of page 2", | ||
| "filename": "document.pdf", | ||
| "page_number": 2 | ||
| } | ||
| // ... more pages | ||
| ] | ||
| } | ||
| ``` | ||
|
|
||
| ### Error Handling | ||
|
|
||
| If an error occurs during processing, the API responds with an appropriate HTTP status code and error message. | ||
|
|
||
|
|
||
|
|
||
| ## Logging | ||
|
|
||
| Logs are stored in the `logs/` directory by default. You can monitor the `markdown_service.log` file for detailed insights into the application's operations. | ||
|
|
||
| ## Configuration | ||
|
|
||
| Settings can be adjusted in the `config.json` file or via environment variables. Key configurations include: | ||
|
|
||
| - `HOST`: Server host (default: `0.0.0.0`) | ||
| - `MARKDOWN_SERVICE_PORT`: Server port (default: `8000`) | ||
| - `PDF_THREAD_POOL_SIZE`: Number of worker threads for PDF processing (default: `3`) | ||
| - `LOGS_DIR`: Directory for log files (default: `logs`) | ||
| - `MARKDOWN_LOG_FILE`: Log file name (default: `markdown_service.log`) | ||
|
|
||
| ## License | ||
| Kore.ai |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| # This file can be empty |
Binary file added
BIN
+153 Bytes
Utilities/DOCLING_SERVICES/app/__pycache__/__init__.cpython-310.pyc
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| import os | ||
| import json | ||
| from pathlib import Path | ||
| from dotenv import load_dotenv | ||
|
|
||
| # Get the base directory of the service | ||
| BASE_DIR = Path(__file__).resolve().parent.parent | ||
| ENV_FILE = BASE_DIR / 'config' / '.env' | ||
| load_dotenv(ENV_FILE) | ||
|
|
||
| # Try to load configuration from JSON file if it exists | ||
| config_data = {} | ||
| config_file_path = BASE_DIR / 'config.json' | ||
| if config_file_path.exists(): | ||
| with open(config_file_path, 'r') as config_file: | ||
| config_data = json.load(config_file) | ||
|
|
||
| # Configuration values with environment variable fallbacks | ||
| HOST = os.getenv('HOST', config_data.get('HOST', '0.0.0.0')) | ||
| MARKDOWN_SERVICE_PORT = int(os.getenv('MARKDOWN_SERVICE_PORT', config_data.get('MARKDOWN_SERVICE_PORT', 8000))) | ||
| PDF_THREAD_POOL_SIZE = int(os.getenv('PDF_THREAD_POOL_SIZE', config_data.get('PDF_THREAD_POOL_SIZE', 3))) | ||
|
|
||
| # Logging configuration | ||
| LOGS_DIR = os.path.join(BASE_DIR, 'logs') # Relative to service directory | ||
| MARKDOWN_LOG_FILE = os.path.join(LOGS_DIR, 'markdown_service.log') | ||
|
|
||
| # Ensure logs directory exists | ||
| os.makedirs(LOGS_DIR, exist_ok=True) | ||
|
|
||
| # Processing configuration | ||
| MAX_RETRIES = int(os.getenv('MAX_RETRIES', config_data.get('MAX_RETRIES', 3))) | ||
| RETRY_DELAY = int(os.getenv('RETRY_DELAY', config_data.get('RETRY_DELAY', 5000))) | ||
| REQUEST_TIMEOUT = int(os.getenv('REQUEST_TIMEOUT', config_data.get('REQUEST_TIMEOUT', 300000))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| from fastapi import FastAPI | ||
| import uvicorn | ||
| from app.routes.pdf_processing import router as pdf_router | ||
| from app.utils.logger import setup_logger | ||
| import app.config as config | ||
|
|
||
| # Initialize FastAPI app | ||
| app = FastAPI( | ||
| title="PDF Markdown Service", | ||
| description="Service for converting PDF files to markdown format", | ||
| version="1.0.0" | ||
| ) | ||
|
|
||
| # Setup logger | ||
| logger = setup_logger('markdown-service') | ||
|
|
||
| # Include routes | ||
| app.include_router(pdf_router) | ||
|
|
||
| @app.on_event("startup") | ||
| async def startup_event(): | ||
| logger.info(f"Starting PDF Markdown Service on {config.HOST}:{config.MARKDOWN_SERVICE_PORT}") | ||
| logger.info(f"Thread pool size: {config.PDF_THREAD_POOL_SIZE}") | ||
|
|
||
| if __name__ == "__main__": | ||
| try: | ||
| uvicorn.run( | ||
| app, | ||
| host=config.HOST, | ||
| port=config.MARKDOWN_SERVICE_PORT, | ||
| log_config=None # Use our custom logging config | ||
| ) | ||
| except Exception as e: | ||
| logger.error(f"Failed to start server: {str(e)}") | ||
| raise |
Binary file added
BIN
+2.21 KB
Utilities/DOCLING_SERVICES/app/models/__pycache__/processing.cpython-310.pyc
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| from docling.datamodel.base_models import InputFormat | ||
| from docling.document_converter import DocumentConverter, PdfFormatOption | ||
| from docling.datamodel.pipeline_options import PdfPipelineOptions | ||
| from docling_core.types.doc import ImageRefMode | ||
| from pathlib import Path | ||
| import time | ||
| import logging | ||
| from typing import List, Dict | ||
| import app.config as config | ||
| import os | ||
|
|
||
| logging.basicConfig( | ||
| level=logging.INFO, | ||
| format='%(asctime)s | %(levelname)s | %(message)s', | ||
| handlers=[ | ||
| logging.FileHandler(config.MARKDOWN_LOG_FILE), | ||
| logging.StreamHandler() | ||
| ] | ||
| ) | ||
| logger = logging.getLogger(__name__) | ||
|
|
||
| def ensure_logs_directory(): | ||
| """Ensure that the logs directory exists.""" | ||
| logs_dir = 'logs' | ||
| if not os.path.exists(logs_dir): | ||
| os.makedirs(logs_dir) | ||
|
|
||
| def process_uploaded_file_sync(file_path: str) -> List[Dict]: | ||
| """Synchronous version of process_uploaded_file""" | ||
| # Set up pipeline options | ||
| pipeline_options = PdfPipelineOptions() | ||
| pipeline_options.do_ocr = False | ||
| pipeline_options.do_table_structure = True | ||
| pipeline_options.table_structure_options.do_cell_matching = True | ||
| pipeline_options.generate_page_images = False | ||
| pipeline_options.generate_picture_images = False | ||
|
|
||
| # Create converter instance | ||
| doc_converter = DocumentConverter( | ||
| format_options={ | ||
| InputFormat.PDF: PdfFormatOption(pipeline_options=pipeline_options) | ||
| } | ||
| ) | ||
|
|
||
| chunks = [] | ||
| input_doc_path = Path(file_path) | ||
|
|
||
| try: | ||
| start_time = time.time() | ||
| # Convert document | ||
| logger.info(f"Started processing Document {file_path}") | ||
| conv_result = doc_converter.convert(input_doc_path) | ||
| end_time = time.time() - start_time | ||
| logger.info(f"Document {file_path} converted in {end_time:.2f} seconds.") | ||
|
|
||
| # Process each page | ||
| for page_no, page in conv_result.document.pages.items(): | ||
| page_content = conv_result.document.export_to_markdown( | ||
| image_mode=ImageRefMode.REFERENCED, | ||
| page_no=page_no | ||
| ) | ||
| chunk_obj = { | ||
| 'chunkText': page_content, | ||
| 'filename': str(input_doc_path.name), | ||
| 'page_number': page_no | ||
| } | ||
| chunks.append(chunk_obj) | ||
|
|
||
| return chunks | ||
| except Exception as e: | ||
| logger.error(f"Error processing document {file_path}: {str(e)}") | ||
| raise Exception(f"Error processing document: {str(e)}") |
Binary file added
BIN
+1.49 KB
Utilities/DOCLING_SERVICES/app/routes/__pycache__/pdf_processing.cpython-310.pyc
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| from fastapi import APIRouter, UploadFile, HTTPException | ||
| from fastapi.responses import JSONResponse | ||
| import time | ||
| import logging | ||
| from app.services.file_processing import save_and_process_file | ||
| from datetime import datetime | ||
|
|
||
| router = APIRouter() | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
| @router.post("/process-pdf-markdown/") | ||
| async def process_pdf_markdown(file: UploadFile) -> JSONResponse: | ||
| if not file: | ||
| raise HTTPException(status_code=400, detail="No file provided") | ||
|
|
||
| if not file.filename.lower().endswith('.pdf'): | ||
| raise HTTPException(status_code=400, detail="File must be a PDF") | ||
|
|
||
| start_time = time.time() | ||
| filename = file.filename | ||
| logger.info(f"[MARKDOWN] Starting processing for file: {filename}") | ||
| logger.info(f"[MARKDOWN] Start time: {datetime.fromtimestamp(start_time).isoformat()}") | ||
|
|
||
| try: | ||
| chunks = await save_and_process_file(file) | ||
| processing_time = time.time() - start_time | ||
| logger.info(f"[MARKDOWN] Completed processing for file: {filename}") | ||
| logger.info(f"[MARKDOWN] Processing time: {processing_time:.2f} seconds") | ||
| logger.info(f"[MARKDOWN] End time: {datetime.now().isoformat()}") | ||
|
|
||
| return JSONResponse(content={"status": "success", "chunks": chunks}, status_code=200) | ||
|
|
||
| except Exception as e: | ||
| logger.error(f"[MARKDOWN] Error processing {filename}: {str(e)}") | ||
| raise HTTPException(status_code=500, detail=f"Error processing file: {str(e)}") | ||
Binary file added
BIN
+1.27 KB
Utilities/DOCLING_SERVICES/app/services/__pycache__/file_processing.cpython-310.pyc
Binary file not shown.
25 changes: 25 additions & 0 deletions
25
Utilities/DOCLING_SERVICES/app/services/file_processing.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| import os | ||
| import tempfile | ||
| import asyncio | ||
| from fastapi import UploadFile | ||
| from concurrent.futures import ProcessPoolExecutor | ||
| from typing import List, Dict | ||
| from app.models.processing import process_uploaded_file_sync | ||
| import app.config as config | ||
| import shutil | ||
|
|
||
| # Create a process pool for concurrent CPU-bound processing | ||
| process_pool = ProcessPoolExecutor(max_workers=config.PDF_THREAD_POOL_SIZE) | ||
|
|
||
| async def save_and_process_file(file: UploadFile) -> List[Dict]: | ||
| """Save the uploaded file and process it.""" | ||
| with tempfile.TemporaryDirectory() as temp_dir: | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. create one folder instead of multiple folders and save the file in that global folder and delete the file once the process is completed |
||
| temp_file_path = os.path.join(temp_dir, file.filename) | ||
| save_uploaded_file(file, temp_file_path) | ||
| loop = asyncio.get_event_loop() | ||
| return await loop.run_in_executor(process_pool, process_uploaded_file_sync, temp_file_path) | ||
|
|
||
| def save_uploaded_file(file: UploadFile, destination: str) -> None: | ||
| """Save the uploaded file to the specified destination.""" | ||
| with open(destination, "wb") as buffer: | ||
| shutil.copyfileobj(file.file, buffer) | ||
Binary file added
BIN
+411 Bytes
Utilities/DOCLING_SERVICES/app/utils/__pycache__/ensure_logs_dir.cpython-310.pyc
Binary file not shown.
Binary file added
BIN
+732 Bytes
Utilities/DOCLING_SERVICES/app/utils/__pycache__/logger.cpython-310.pyc
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| import os | ||
|
|
||
| def ensure_logs_directory(): | ||
| """Ensure that the logs directory exists.""" | ||
| logs_dir = 'logs' | ||
| if not os.path.exists(logs_dir): | ||
| os.makedirs(logs_dir) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| import logging | ||
| import os | ||
| from app.config import LOGS_DIR, MARKDOWN_LOG_FILE | ||
|
|
||
| def setup_logger(name): | ||
| """Set up logger with file and console handlers.""" | ||
| logger = logging.getLogger(name) | ||
| logger.setLevel(logging.INFO) | ||
|
|
||
| # Create formatters and handlers | ||
| formatter = logging.Formatter( | ||
| '%(asctime)s - %(name)s - %(levelname)s - %(message)s' | ||
| ) | ||
|
|
||
| # File handler | ||
| file_handler = logging.FileHandler(MARKDOWN_LOG_FILE) | ||
| file_handler.setFormatter(formatter) | ||
| logger.addHandler(file_handler) | ||
|
|
||
| # Console handler | ||
| console_handler = logging.StreamHandler() | ||
| console_handler.setFormatter(formatter) | ||
| logger.addHandler(console_handler) | ||
|
|
||
| return logger |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| { | ||
| "HOST": "0.0.0.0", | ||
| "MARKDOWN_SERVICE_PORT": 8000, | ||
| "PDF_THREAD_POOL_SIZE": 3, | ||
| "PDF_PROCESS_POOL_SIZE": 3, | ||
| "MAX_RETRIES": 5, | ||
| "RETRY_DELAY": 5000, | ||
| "REQUEST_TIMEOUT": 300000, | ||
| "LOGS_DIR": "logs", | ||
| "MARKDOWN_LOG_FILE": "markdown.log" | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| docling==2.21.0 | ||
| docling-core==2.18.0 | ||
| docling-ibm-models==3.3.1 | ||
| docling-parse==3.3.0 | ||
| easyocr==1.7.2 | ||
| fastapi==0.115.8 | ||
| python-dotenv==1.0.1 | ||
| python-multipart==0.0.20 | ||
| uvicorn==0.34.0 |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.