Spaces:
Runtime error
Runtime error
github-actions[bot]
commited on
Commit
·
1383efa
0
Parent(s):
Sync from https://github.com/ryanlinjui/menu-text-detection
Browse files- .checkpoints/.gitkeep +0 -0
- .env.example +3 -0
- .github/workflows/sync.yml +25 -0
- .gitignore +24 -0
- .python-version +1 -0
- LICENSE +21 -0
- README.md +65 -0
- app.py +322 -0
- menu/donut.py +472 -0
- menu/llm/__init__.py +2 -0
- menu/llm/base.py +12 -0
- menu/llm/gemini.py +36 -0
- menu/llm/openai.py +43 -0
- menu/utils.py +48 -0
- pyproject.toml +27 -0
- requirements.txt +1475 -0
- tools/schema_gemini.json +44 -0
- tools/schema_openai.json +47 -0
- train.ipynb +235 -0
- uv.lock +0 -0
.checkpoints/.gitkeep
ADDED
|
File without changes
|
.env.example
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
HUGGINGFACE_TOKEN="HUGGINGFACE_TOKEN"
|
| 2 |
+
GEMINI_API_TOKEN="GEMINI_API_TOKEN"
|
| 3 |
+
OPENAI_API_TOKEN="OPENAI_API_TOKEN"
|
.github/workflows/sync.yml
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Sync to Hugging Face Spaces
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
push:
|
| 5 |
+
branches:
|
| 6 |
+
- main
|
| 7 |
+
jobs:
|
| 8 |
+
sync:
|
| 9 |
+
name: Sync
|
| 10 |
+
runs-on: ubuntu-latest
|
| 11 |
+
steps:
|
| 12 |
+
- name: Checkout Repository
|
| 13 |
+
uses: actions/checkout@v4
|
| 14 |
+
|
| 15 |
+
- name: Remove bad files
|
| 16 |
+
run: rm -rf examples assets
|
| 17 |
+
|
| 18 |
+
- name: Sync to Hugging Face Spaces
|
| 19 |
+
uses: JacobLinCool/huggingface-sync@v1
|
| 20 |
+
with:
|
| 21 |
+
github: ${{ secrets.GITHUB_TOKEN }}
|
| 22 |
+
user: ryanlinjui # Hugging Face username or organization name
|
| 23 |
+
space: menu-text-detection # Hugging Face space name
|
| 24 |
+
token: ${{ secrets.HF_TOKEN }} # Hugging Face token
|
| 25 |
+
python_version: 3.11 # Python version
|
.gitignore
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# mac
|
| 2 |
+
.DS_Store
|
| 3 |
+
|
| 4 |
+
# cache
|
| 5 |
+
__pycache__
|
| 6 |
+
|
| 7 |
+
# datasets
|
| 8 |
+
datasets
|
| 9 |
+
|
| 10 |
+
# papers
|
| 11 |
+
docs/papers
|
| 12 |
+
|
| 13 |
+
# uv
|
| 14 |
+
.venv
|
| 15 |
+
|
| 16 |
+
# gradio
|
| 17 |
+
.gradio
|
| 18 |
+
|
| 19 |
+
# env
|
| 20 |
+
.env
|
| 21 |
+
|
| 22 |
+
# checkpoint
|
| 23 |
+
.checkpoints/*
|
| 24 |
+
!.checkpoints/.gitkeep
|
.python-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
3.11
|
LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2025 RyanLin
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
+
in the Software without restriction, including without limitation the rights
|
| 8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
+
furnished to do so, subject to the following conditions:
|
| 11 |
+
|
| 12 |
+
The above copyright notice and this permission notice shall be included in all
|
| 13 |
+
copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 21 |
+
SOFTWARE.
|
README.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: menu text detection
|
| 3 |
+
emoji: 🦄
|
| 4 |
+
colorFrom: indigo
|
| 5 |
+
colorTo: pink
|
| 6 |
+
sdk: gradio
|
| 7 |
+
python_version: 3.11
|
| 8 |
+
short_description: Extract structured menu information from images into JSON...
|
| 9 |
+
tags: [ "document-understanding","donut","fine-tuning","image-text-to-text","transformer" ]
|
| 10 |
+
---
|
| 11 |
+
|
| 12 |
+
# Menu Text Detection System
|
| 13 |
+
|
| 14 |
+
Extract structured menu information from images into JSON using a fine-tuned E2E model or LLM.
|
| 15 |
+
|
| 16 |
+
[](https://huggingface.co/spaces/ryanlinjui/menu-text-detection)
|
| 17 |
+
[](https://huggingface.co/collections/ryanlinjui/menu-text-detection-670ccf527626bb004bbfb39b)
|
| 18 |
+
|
| 19 |
+
https://github.com/user-attachments/assets/80e5d54c-f2c8-4593-ad9b-499e5b71d8f6
|
| 20 |
+
|
| 21 |
+
## 🚀 Features
|
| 22 |
+
### Overview
|
| 23 |
+
Currently supports the following information from menu images:
|
| 24 |
+
|
| 25 |
+
- **Restaurant Name**
|
| 26 |
+
- **Business Hours**
|
| 27 |
+
- **Address**
|
| 28 |
+
- **Phone Number**
|
| 29 |
+
- **Dish Information**
|
| 30 |
+
- Name
|
| 31 |
+
- Price
|
| 32 |
+
|
| 33 |
+
> For the JSON schema, see [tools directory](./tools).
|
| 34 |
+
|
| 35 |
+
### Supported Methods to Extract Menu Information
|
| 36 |
+
#### Fine-tuned E2E model and Training metrics
|
| 37 |
+
- [**Donut (Document Parsing Task)**](https://huggingface.co/ryanlinjui/donut-base-finetuned-menu) - Base model by [Clova AI (ECCV ’22)](https://github.com/clovaai/donut)
|
| 38 |
+
|
| 39 |
+
#### LLM Function Calling
|
| 40 |
+
- Google Gemini API
|
| 41 |
+
- OpenAI GPT API
|
| 42 |
+
|
| 43 |
+
## 💻 Training / Fine-Tuning
|
| 44 |
+
### Setup
|
| 45 |
+
Use [uv](https://github.com/astral-sh/uv) to set up the development environment:
|
| 46 |
+
|
| 47 |
+
```bash
|
| 48 |
+
uv sync
|
| 49 |
+
```
|
| 50 |
+
|
| 51 |
+
> or use `pip install -r requirements.txt` if it has any problems
|
| 52 |
+
|
| 53 |
+
### Training Script (Datasets collecting, Fine-Tuning)
|
| 54 |
+
Please refer [`train.ipynb`](./train.ipynb). Use Jupyter Notebook for training:
|
| 55 |
+
|
| 56 |
+
```bash
|
| 57 |
+
uv run jupyter-notebook
|
| 58 |
+
```
|
| 59 |
+
|
| 60 |
+
> For VSCode users, please install Jupyter extension, then select `.venv/bin/python` as your kernel.
|
| 61 |
+
|
| 62 |
+
### Run Demo Locally
|
| 63 |
+
```bash
|
| 64 |
+
uv run python app.py
|
| 65 |
+
```
|
app.py
ADDED
|
@@ -0,0 +1,322 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import json
|
| 3 |
+
import requests
|
| 4 |
+
from io import BytesIO
|
| 5 |
+
from typing import List
|
| 6 |
+
|
| 7 |
+
import gradio as gr
|
| 8 |
+
from PIL import Image
|
| 9 |
+
from dotenv import load_dotenv
|
| 10 |
+
from pillow_heif import register_heif_opener
|
| 11 |
+
|
| 12 |
+
from menu.llm import (
|
| 13 |
+
GeminiAPI,
|
| 14 |
+
OpenAIAPI
|
| 15 |
+
)
|
| 16 |
+
from menu.donut import DonutFinetuned
|
| 17 |
+
|
| 18 |
+
donut_finetuned = DonutFinetuned("ryanlinjui/donut-base-finetuned-menu")
|
| 19 |
+
|
| 20 |
+
register_heif_opener()
|
| 21 |
+
load_dotenv(override=True)
|
| 22 |
+
GEMINI_API_TOKEN = os.getenv("GEMINI_API_TOKEN", "")
|
| 23 |
+
OPENAI_API_TOKEN = os.getenv("OPENAI_API_TOKEN", "")
|
| 24 |
+
|
| 25 |
+
SOURCE_CODE_GH_URL = "https://github.com/ryanlinjui/menu-text-detection"
|
| 26 |
+
BADGE_URL = "https://img.shields.io/badge/GitHub_Code-Click_Here!!-default?logo=github"
|
| 27 |
+
|
| 28 |
+
GITHUB_RAW_URL = "https://raw.githubusercontent.com/ryanlinjui/menu-text-detection/main"
|
| 29 |
+
EXAMPLE_IMAGE_LIST = [
|
| 30 |
+
[f"{GITHUB_RAW_URL}/examples/menu-hd.jpg"],
|
| 31 |
+
[f"{GITHUB_RAW_URL}/examples/menu-vs.jpg"],
|
| 32 |
+
[f"{GITHUB_RAW_URL}/examples/menu-si.jpg"],
|
| 33 |
+
[f"{GITHUB_RAW_URL}/examples/menu-hd.jpg", f"{GITHUB_RAW_URL}/examples/menu-si.jpg"],
|
| 34 |
+
[f"{GITHUB_RAW_URL}/examples/menu-si.jpg", f"{GITHUB_RAW_URL}/examples/menu-vs.jpg", f"{GITHUB_RAW_URL}/examples/menu-hd.jpg", f"{GITHUB_RAW_URL}/examples/menu-vs.jpg"],
|
| 35 |
+
]
|
| 36 |
+
FINETUNED_MODEL_LIST = [
|
| 37 |
+
"Donut (Document Parsing Task) Fine-tuned Model"
|
| 38 |
+
]
|
| 39 |
+
LLM_MODEL_LIST = [
|
| 40 |
+
"gemini-2.5-pro",
|
| 41 |
+
"gemini-2.5-flash",
|
| 42 |
+
"gemini-2.0-flash",
|
| 43 |
+
"gpt-4.1",
|
| 44 |
+
"gpt-4o",
|
| 45 |
+
"o4-mini"
|
| 46 |
+
]
|
| 47 |
+
CSS_STYLE = """
|
| 48 |
+
.image-panel {
|
| 49 |
+
display: flex;
|
| 50 |
+
flex-direction: column;
|
| 51 |
+
height: 600px;
|
| 52 |
+
}
|
| 53 |
+
.image-panel img {
|
| 54 |
+
object-fit: contain;
|
| 55 |
+
max-height: 550px;
|
| 56 |
+
max-width: 550px;
|
| 57 |
+
width: 100%;
|
| 58 |
+
}
|
| 59 |
+
.large-text textarea {
|
| 60 |
+
font-size: 20px !important;
|
| 61 |
+
height: 600px !important;
|
| 62 |
+
width: 100% !important;
|
| 63 |
+
}
|
| 64 |
+
.control-row {
|
| 65 |
+
margin-top: -10px !important;
|
| 66 |
+
margin-bottom: -10px !important;
|
| 67 |
+
align-items: center !important;
|
| 68 |
+
justify-content: center !important;
|
| 69 |
+
}
|
| 70 |
+
.page-info {
|
| 71 |
+
text-align: center !important;
|
| 72 |
+
font-size: 20px !important;
|
| 73 |
+
display: flex !important;
|
| 74 |
+
align-items: center !important;
|
| 75 |
+
justify-content: center !important;
|
| 76 |
+
height: 100% !important;
|
| 77 |
+
font-weight: 900 !important;
|
| 78 |
+
color: #374151; /* Darker gray for clarity */
|
| 79 |
+
}
|
| 80 |
+
.page-info p {
|
| 81 |
+
margin: 0 !important;
|
| 82 |
+
width: 100% !important;
|
| 83 |
+
text-align: center !important;
|
| 84 |
+
}
|
| 85 |
+
.upload-btn {
|
| 86 |
+
margin-top: 2px !important;
|
| 87 |
+
background-color: #e0f2fe !important; /* Light blue background */
|
| 88 |
+
color: #0369a1 !important; /* Dark blue text */
|
| 89 |
+
border: 1px solid #0ea5e9 !important;
|
| 90 |
+
}
|
| 91 |
+
.upload-btn:hover {
|
| 92 |
+
background-color: #bae6fd !important;
|
| 93 |
+
}
|
| 94 |
+
.clear-btn {
|
| 95 |
+
margin-top: 2px !important;
|
| 96 |
+
}
|
| 97 |
+
.image-container {
|
| 98 |
+
height: 650px !important;
|
| 99 |
+
display: flex;
|
| 100 |
+
flex-direction: column;
|
| 101 |
+
border: 1px solid #e5e7eb;
|
| 102 |
+
border-radius: 8px;
|
| 103 |
+
padding: 4px;
|
| 104 |
+
}
|
| 105 |
+
"""
|
| 106 |
+
|
| 107 |
+
def handle(images: List[str], model: str, api_token: str) -> str:
|
| 108 |
+
if not images:
|
| 109 |
+
raise gr.Error("Please upload an image first.")
|
| 110 |
+
|
| 111 |
+
# Convert file paths or URLs to PIL Images
|
| 112 |
+
pil_images = []
|
| 113 |
+
for img in images:
|
| 114 |
+
if img.startswith("http://") or img.startswith("https://"):
|
| 115 |
+
try:
|
| 116 |
+
response = requests.get(img)
|
| 117 |
+
response.raise_for_status()
|
| 118 |
+
pil_images.append(Image.open(BytesIO(response.content)))
|
| 119 |
+
except Exception as e:
|
| 120 |
+
raise gr.Error(f"Failed to load image from URL: {str(e)}")
|
| 121 |
+
else:
|
| 122 |
+
pil_images.append(Image.open(img))
|
| 123 |
+
|
| 124 |
+
if model == FINETUNED_MODEL_LIST[0]:
|
| 125 |
+
result = donut_finetuned.predict(pil_images[0])
|
| 126 |
+
|
| 127 |
+
elif model in LLM_MODEL_LIST:
|
| 128 |
+
if len(api_token) < 10:
|
| 129 |
+
raise gr.Error(f"Please provide a valid token for {model}.")
|
| 130 |
+
try:
|
| 131 |
+
if model in LLM_MODEL_LIST[:3]:
|
| 132 |
+
result = GeminiAPI.call(pil_images, model, api_token)
|
| 133 |
+
else:
|
| 134 |
+
result = OpenAIAPI.call(pil_images, model, api_token)
|
| 135 |
+
except Exception as e:
|
| 136 |
+
raise gr.Error(f"Failed to process with API model {model}: {str(e)}")
|
| 137 |
+
else:
|
| 138 |
+
raise gr.Error("Invalid model selection. Please choose a valid model.")
|
| 139 |
+
|
| 140 |
+
return json.dumps(result, indent=4, ensure_ascii=False, sort_keys=True)
|
| 141 |
+
|
| 142 |
+
def UserInterface() -> gr.Interface:
|
| 143 |
+
with gr.Blocks(delete_cache=(86400, 86400), css=CSS_STYLE) as gradio_interface:
|
| 144 |
+
gr.HTML(f'<a href="{SOURCE_CODE_GH_URL}"><img src="{BADGE_URL}" alt="GitHub Code"/></a>')
|
| 145 |
+
gr.Markdown("# Menu Text Detection")
|
| 146 |
+
|
| 147 |
+
images_state = gr.State([])
|
| 148 |
+
current_index_state = gr.State(0)
|
| 149 |
+
|
| 150 |
+
with gr.Row():
|
| 151 |
+
with gr.Column(scale=1, min_width=500):
|
| 152 |
+
gr.Markdown("## 📷 Menu Image")
|
| 153 |
+
|
| 154 |
+
with gr.Column(elem_classes="image-container"):
|
| 155 |
+
menu_image_display = gr.Image(
|
| 156 |
+
label="Input menu image",
|
| 157 |
+
type="filepath",
|
| 158 |
+
elem_classes="image-panel",
|
| 159 |
+
interactive=False,
|
| 160 |
+
show_download_button=False,
|
| 161 |
+
show_label=True
|
| 162 |
+
)
|
| 163 |
+
with gr.Row(elem_classes="control-row"):
|
| 164 |
+
prev_btn = gr.Button("◀️ Previous", variant="secondary", scale=1)
|
| 165 |
+
with gr.Column(scale=2, min_width=50):
|
| 166 |
+
page_info = gr.Markdown("Page 1 / 1", elem_classes="page-info")
|
| 167 |
+
next_btn = gr.Button("Next ▶️", variant="secondary", scale=1)
|
| 168 |
+
|
| 169 |
+
with gr.Row():
|
| 170 |
+
upload_btn = gr.UploadButton(
|
| 171 |
+
"📷 Upload Menu Images",
|
| 172 |
+
file_types=["image"],
|
| 173 |
+
file_count="multiple",
|
| 174 |
+
scale=3,
|
| 175 |
+
elem_classes="upload-btn",
|
| 176 |
+
variant="primary"
|
| 177 |
+
)
|
| 178 |
+
clear_btn = gr.Button("🗑️ Remove", variant="stop", scale=1, elem_classes="clear-btn")
|
| 179 |
+
|
| 180 |
+
gr.Markdown("## 🤖 Model Selection")
|
| 181 |
+
model_choice_dropdown = gr.Dropdown(
|
| 182 |
+
choices=FINETUNED_MODEL_LIST + LLM_MODEL_LIST,
|
| 183 |
+
value=FINETUNED_MODEL_LIST[0],
|
| 184 |
+
label="Select Text Detection Model"
|
| 185 |
+
)
|
| 186 |
+
|
| 187 |
+
api_token_textbox = gr.Textbox(
|
| 188 |
+
label="API Token",
|
| 189 |
+
placeholder="Enter your API token here...",
|
| 190 |
+
type="password",
|
| 191 |
+
visible=False
|
| 192 |
+
)
|
| 193 |
+
|
| 194 |
+
generate_button = gr.Button("Generate Menu Information", variant="primary")
|
| 195 |
+
example_receiver = gr.Image(visible=False, label="Example Preview", type="filepath")
|
| 196 |
+
|
| 197 |
+
examples_component = gr.Examples(
|
| 198 |
+
examples=[[img_list[0]] for img_list in EXAMPLE_IMAGE_LIST],
|
| 199 |
+
inputs=example_receiver,
|
| 200 |
+
label="Example Menu Images"
|
| 201 |
+
)
|
| 202 |
+
|
| 203 |
+
with gr.Column(scale=1):
|
| 204 |
+
gr.Markdown("## 🍽️ Menu Info")
|
| 205 |
+
menu_json_textbox = gr.Textbox(
|
| 206 |
+
label="Output JSON",
|
| 207 |
+
interactive=True,
|
| 208 |
+
text_align="left",
|
| 209 |
+
elem_classes="large-text"
|
| 210 |
+
)
|
| 211 |
+
|
| 212 |
+
def update_display(images, index):
|
| 213 |
+
if not images:
|
| 214 |
+
return None, "Page 1 / 1"
|
| 215 |
+
idx = max(0, min(index, len(images) - 1))
|
| 216 |
+
return images[idx], f"Page {idx + 1} / {len(images)}"
|
| 217 |
+
|
| 218 |
+
def on_upload(new_files, current_images):
|
| 219 |
+
if current_images is None:
|
| 220 |
+
current_images = []
|
| 221 |
+
if new_files:
|
| 222 |
+
new_paths = [f.name for f in new_files]
|
| 223 |
+
current_images.extend(new_paths)
|
| 224 |
+
new_index = len(current_images) - 1
|
| 225 |
+
img, info = update_display(current_images, new_index)
|
| 226 |
+
return current_images, new_index, img, info
|
| 227 |
+
|
| 228 |
+
upload_btn.upload(
|
| 229 |
+
fn=on_upload,
|
| 230 |
+
inputs=[upload_btn, images_state],
|
| 231 |
+
outputs=[images_state, current_index_state, menu_image_display, page_info]
|
| 232 |
+
)
|
| 233 |
+
|
| 234 |
+
def on_clear(images, index):
|
| 235 |
+
if not images:
|
| 236 |
+
return [], 0, None, "Page 1 / 1"
|
| 237 |
+
|
| 238 |
+
new_images = list(images)
|
| 239 |
+
if 0 <= index < len(new_images):
|
| 240 |
+
new_images.pop(index)
|
| 241 |
+
|
| 242 |
+
if not new_images:
|
| 243 |
+
return [], 0, None, "Page 1 / 1"
|
| 244 |
+
|
| 245 |
+
new_index = index
|
| 246 |
+
if new_index >= len(new_images):
|
| 247 |
+
new_index = len(new_images) - 1
|
| 248 |
+
|
| 249 |
+
img, info = update_display(new_images, new_index)
|
| 250 |
+
return new_images, new_index, img, info
|
| 251 |
+
|
| 252 |
+
clear_btn.click(
|
| 253 |
+
fn=on_clear,
|
| 254 |
+
inputs=[images_state, current_index_state],
|
| 255 |
+
outputs=[images_state, current_index_state, menu_image_display, page_info]
|
| 256 |
+
)
|
| 257 |
+
|
| 258 |
+
def on_prev(images, index):
|
| 259 |
+
if not images:
|
| 260 |
+
return 0, None, "Page 1 / 1"
|
| 261 |
+
new_index = max(0, index - 1)
|
| 262 |
+
img, info = update_display(images, new_index)
|
| 263 |
+
return new_index, img, info
|
| 264 |
+
|
| 265 |
+
def on_next(images, index):
|
| 266 |
+
if not images:
|
| 267 |
+
return 0, None, "Page 1 / 1"
|
| 268 |
+
new_index = min(len(images) - 1, index + 1)
|
| 269 |
+
img, info = update_display(images, new_index)
|
| 270 |
+
return new_index, img, info
|
| 271 |
+
|
| 272 |
+
prev_btn.click(on_prev, [images_state, current_index_state], [current_index_state, menu_image_display, page_info])
|
| 273 |
+
next_btn.click(on_next, [images_state, current_index_state], [current_index_state, menu_image_display, page_info])
|
| 274 |
+
|
| 275 |
+
def on_example_click(evt: gr.SelectData):
|
| 276 |
+
if evt.index is None:
|
| 277 |
+
return [], 0, None, "Page 1 / 1"
|
| 278 |
+
|
| 279 |
+
# Retrieve the full batch based on the clicked index
|
| 280 |
+
if 0 <= evt.index < len(EXAMPLE_IMAGE_LIST):
|
| 281 |
+
current_images = EXAMPLE_IMAGE_LIST[evt.index]
|
| 282 |
+
else:
|
| 283 |
+
current_images = []
|
| 284 |
+
|
| 285 |
+
new_index = 0
|
| 286 |
+
img, info = update_display(current_images, new_index)
|
| 287 |
+
return current_images, new_index, img, info
|
| 288 |
+
|
| 289 |
+
examples_component.dataset.select(
|
| 290 |
+
fn=on_example_click,
|
| 291 |
+
inputs=None,
|
| 292 |
+
outputs=[images_state, current_index_state, menu_image_display, page_info]
|
| 293 |
+
)
|
| 294 |
+
|
| 295 |
+
def update_token_visibility(choice):
|
| 296 |
+
if choice in LLM_MODEL_LIST:
|
| 297 |
+
current_token = ""
|
| 298 |
+
if choice in LLM_MODEL_LIST[:3]:
|
| 299 |
+
current_token = GEMINI_API_TOKEN
|
| 300 |
+
else:
|
| 301 |
+
current_token = OPENAI_API_TOKEN
|
| 302 |
+
return gr.update(visible=True, value=current_token)
|
| 303 |
+
else:
|
| 304 |
+
return gr.update(visible=False)
|
| 305 |
+
|
| 306 |
+
model_choice_dropdown.change(
|
| 307 |
+
fn=update_token_visibility,
|
| 308 |
+
inputs=model_choice_dropdown,
|
| 309 |
+
outputs=api_token_textbox
|
| 310 |
+
)
|
| 311 |
+
|
| 312 |
+
generate_button.click(
|
| 313 |
+
fn=handle,
|
| 314 |
+
inputs=[images_state, model_choice_dropdown, api_token_textbox],
|
| 315 |
+
outputs=menu_json_textbox
|
| 316 |
+
)
|
| 317 |
+
|
| 318 |
+
return gradio_interface
|
| 319 |
+
|
| 320 |
+
if __name__ == "__main__":
|
| 321 |
+
demo = UserInterface()
|
| 322 |
+
demo.launch()
|
menu/donut.py
ADDED
|
@@ -0,0 +1,472 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
This file is modified from the HuggingFace transformers tutorial script for fine-tuning Donut on a custom dataset.
|
| 3 |
+
It's defined from `.ipynb` to the module implementation for better reusability and maintainability.
|
| 4 |
+
Reference: https://github.com/NielsRogge/Transformers-Tutorials/blob/master/Donut/CORD/Fine_tune_Donut_on_a_custom_dataset_(CORD)_with_PyTorch_Lightning.ipynb
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
import re
|
| 8 |
+
import random
|
| 9 |
+
from typing import Any, List, Tuple, Dict
|
| 10 |
+
|
| 11 |
+
import torch
|
| 12 |
+
import numpy as np
|
| 13 |
+
from PIL import Image
|
| 14 |
+
from tqdm.auto import tqdm
|
| 15 |
+
from nltk import edit_distance
|
| 16 |
+
import pytorch_lightning as pl
|
| 17 |
+
from datasets import DatasetDict
|
| 18 |
+
from donut import JSONParseEvaluator
|
| 19 |
+
from huggingface_hub import upload_folder
|
| 20 |
+
from pillow_heif import register_heif_opener
|
| 21 |
+
from pytorch_lightning.callbacks import Callback
|
| 22 |
+
from pytorch_lightning.loggers import TensorBoardLogger
|
| 23 |
+
from torch.utils.data import (
|
| 24 |
+
Dataset,
|
| 25 |
+
DataLoader
|
| 26 |
+
)
|
| 27 |
+
from transformers import (
|
| 28 |
+
DonutProcessor,
|
| 29 |
+
VisionEncoderDecoderModel,
|
| 30 |
+
VisionEncoderDecoderConfig
|
| 31 |
+
)
|
| 32 |
+
|
| 33 |
+
TASK_PROMPT_NAME = "<s_menu-text-detection>"
|
| 34 |
+
register_heif_opener()
|
| 35 |
+
|
| 36 |
+
class DonutFinetuned:
|
| 37 |
+
def __init__(self, pretrained_model_repo_id: str = "ryanlinjui/donut-test"):
|
| 38 |
+
self.device = (
|
| 39 |
+
"cuda"
|
| 40 |
+
if torch.cuda.is_available()
|
| 41 |
+
else "mps" if torch.backends.mps.is_available() else "cpu"
|
| 42 |
+
)
|
| 43 |
+
self.processor = DonutProcessor.from_pretrained(pretrained_model_repo_id)
|
| 44 |
+
self.model = VisionEncoderDecoderModel.from_pretrained(pretrained_model_repo_id)
|
| 45 |
+
self.model.eval()
|
| 46 |
+
self.model.to(self.device)
|
| 47 |
+
print(f"Using {self.device} device")
|
| 48 |
+
|
| 49 |
+
def predict(self, image: Image.Image) -> Dict[str, Any]:
|
| 50 |
+
# prepare encoder inputs
|
| 51 |
+
pixel_values = self.processor(image.convert("RGB"), return_tensors="pt").pixel_values
|
| 52 |
+
pixel_values = pixel_values.to(self.device)
|
| 53 |
+
|
| 54 |
+
# prepare decoder inputs
|
| 55 |
+
decoder_input_ids = self.processor.tokenizer(TASK_PROMPT_NAME, add_special_tokens=False, return_tensors="pt").input_ids
|
| 56 |
+
decoder_input_ids = decoder_input_ids.to(self.device)
|
| 57 |
+
|
| 58 |
+
# autoregressively generate sequence
|
| 59 |
+
outputs = self.model.generate(
|
| 60 |
+
pixel_values,
|
| 61 |
+
decoder_input_ids=decoder_input_ids,
|
| 62 |
+
max_length=self.model.decoder.config.max_position_embeddings,
|
| 63 |
+
early_stopping=True,
|
| 64 |
+
pad_token_id=self.processor.tokenizer.pad_token_id,
|
| 65 |
+
eos_token_id=self.processor.tokenizer.eos_token_id,
|
| 66 |
+
use_cache=True,
|
| 67 |
+
num_beams=1,
|
| 68 |
+
bad_words_ids=[[self.processor.tokenizer.unk_token_id]],
|
| 69 |
+
return_dict_in_generate=True
|
| 70 |
+
)
|
| 71 |
+
|
| 72 |
+
# turn into JSON
|
| 73 |
+
seq = self.processor.batch_decode(outputs.sequences)[0]
|
| 74 |
+
seq = seq.replace(self.processor.tokenizer.eos_token, "").replace(self.processor.tokenizer.pad_token, "")
|
| 75 |
+
seq = re.sub(r"<.*?>", "", seq, count=1).strip() # remove first task start token
|
| 76 |
+
seq = self.processor.token2json(seq)
|
| 77 |
+
return seq
|
| 78 |
+
|
| 79 |
+
def evaluate(self, dataset: Dataset, ground_truth_key: str = "ground_truth") -> Tuple[Dict[str, Any], List[Any]]:
|
| 80 |
+
output_list = []
|
| 81 |
+
accs = []
|
| 82 |
+
ted_accs = []
|
| 83 |
+
f1_accs = []
|
| 84 |
+
|
| 85 |
+
for idx, sample in tqdm(enumerate(dataset), total=len(dataset)):
|
| 86 |
+
seq = self.predict(sample["image"])
|
| 87 |
+
ground_truth = sample[ground_truth_key]
|
| 88 |
+
|
| 89 |
+
# Original JSON accuracy
|
| 90 |
+
evaluator = JSONParseEvaluator()
|
| 91 |
+
score = evaluator.cal_acc(seq, ground_truth)
|
| 92 |
+
accs.append(score)
|
| 93 |
+
output_list.append(seq)
|
| 94 |
+
|
| 95 |
+
# TED (Tree Edit Distance) Accuracy
|
| 96 |
+
# Convert predictions and ground truth to string format for comparison
|
| 97 |
+
pred_str = str(seq) if seq else ""
|
| 98 |
+
gt_str = str(ground_truth) if ground_truth else ""
|
| 99 |
+
|
| 100 |
+
# Calculate normalized edit distance (1 - normalized_edit_distance = accuracy)
|
| 101 |
+
if len(pred_str) == 0 and len(gt_str) == 0:
|
| 102 |
+
ted_acc = 1.0
|
| 103 |
+
elif len(pred_str) == 0 or len(gt_str) == 0:
|
| 104 |
+
ted_acc = 0.0
|
| 105 |
+
else:
|
| 106 |
+
edit_dist = edit_distance(pred_str, gt_str)
|
| 107 |
+
max_len = max(len(pred_str), len(gt_str))
|
| 108 |
+
ted_acc = 1 - (edit_dist / max_len)
|
| 109 |
+
ted_accs.append(ted_acc)
|
| 110 |
+
|
| 111 |
+
# F1 Score Accuracy (character-level)
|
| 112 |
+
if len(pred_str) == 0 and len(gt_str) == 0:
|
| 113 |
+
f1_acc = 1.0
|
| 114 |
+
elif len(pred_str) == 0 or len(gt_str) == 0:
|
| 115 |
+
f1_acc = 0.0
|
| 116 |
+
else:
|
| 117 |
+
# Character-level precision and recall
|
| 118 |
+
pred_chars = set(pred_str)
|
| 119 |
+
gt_chars = set(gt_str)
|
| 120 |
+
|
| 121 |
+
if len(pred_chars) == 0:
|
| 122 |
+
precision = 0.0
|
| 123 |
+
else:
|
| 124 |
+
precision = len(pred_chars.intersection(gt_chars)) / len(pred_chars)
|
| 125 |
+
|
| 126 |
+
if len(gt_chars) == 0:
|
| 127 |
+
recall = 0.0
|
| 128 |
+
else:
|
| 129 |
+
recall = len(pred_chars.intersection(gt_chars)) / len(gt_chars)
|
| 130 |
+
|
| 131 |
+
if precision + recall == 0:
|
| 132 |
+
f1_acc = 0.0
|
| 133 |
+
else:
|
| 134 |
+
f1_acc = 2 * (precision * recall) / (precision + recall)
|
| 135 |
+
f1_accs.append(f1_acc)
|
| 136 |
+
|
| 137 |
+
scores = {
|
| 138 |
+
"accuracies": accs,
|
| 139 |
+
"mean_accuracy": np.mean(accs),
|
| 140 |
+
"ted_accuracies": ted_accs,
|
| 141 |
+
"mean_ted_accuracy": np.mean(ted_accs),
|
| 142 |
+
"f1_accuracies": f1_accs,
|
| 143 |
+
"mean_f1_accuracy": np.mean(f1_accs),
|
| 144 |
+
"length": len(accs)
|
| 145 |
+
}
|
| 146 |
+
return scores, output_list
|
| 147 |
+
|
| 148 |
+
class DonutTrainer:
|
| 149 |
+
processor = None
|
| 150 |
+
max_length = 768
|
| 151 |
+
image_size = [1280, 960]
|
| 152 |
+
added_tokens = []
|
| 153 |
+
train_dataloader = None
|
| 154 |
+
val_dataloader = None
|
| 155 |
+
huggingface_model_id = None
|
| 156 |
+
|
| 157 |
+
class DonutDataset(Dataset):
|
| 158 |
+
"""
|
| 159 |
+
PyTorch Dataset for Donut. This class takes a HuggingFace Dataset as input.
|
| 160 |
+
|
| 161 |
+
Each row, consists of image path(png/jpg/jpeg) and gt data (json/jsonl/txt),
|
| 162 |
+
and it will be converted into pixel_values (vectorized image) and labels (input_ids of the tokenized string).
|
| 163 |
+
|
| 164 |
+
Args:
|
| 165 |
+
dataset: HuggingFace DatasetDict containing the dataset to be used
|
| 166 |
+
max_length: the max number of tokens for the target sequences
|
| 167 |
+
split: whether to load "train", "validation" or "test" split
|
| 168 |
+
ignore_id: ignore_index for torch.nn.CrossEntropyLoss
|
| 169 |
+
task_start_token: the special token to be fed to the decoder to conduct the target task
|
| 170 |
+
prompt_end_token: the special token at the end of the sequences
|
| 171 |
+
sort_json_key: whether or not to sort the JSON keys
|
| 172 |
+
"""
|
| 173 |
+
|
| 174 |
+
def __init__(
|
| 175 |
+
self,
|
| 176 |
+
dataset: DatasetDict,
|
| 177 |
+
ground_truth_key: str,
|
| 178 |
+
max_length: int,
|
| 179 |
+
split: str = "train",
|
| 180 |
+
ignore_id: int = -100,
|
| 181 |
+
task_start_token: str = "<s>",
|
| 182 |
+
prompt_end_token: str = None,
|
| 183 |
+
sort_json_key: bool = True,
|
| 184 |
+
):
|
| 185 |
+
super().__init__()
|
| 186 |
+
|
| 187 |
+
self.dataset = dataset[split]
|
| 188 |
+
self.ground_truth_key = ground_truth_key
|
| 189 |
+
self.max_length = max_length
|
| 190 |
+
self.split = split
|
| 191 |
+
self.ignore_id = ignore_id
|
| 192 |
+
self.task_start_token = task_start_token
|
| 193 |
+
self.prompt_end_token = prompt_end_token if prompt_end_token else task_start_token
|
| 194 |
+
self.sort_json_key = sort_json_key
|
| 195 |
+
|
| 196 |
+
self.dataset_length = len(self.dataset)
|
| 197 |
+
|
| 198 |
+
self.gt_token_sequences = []
|
| 199 |
+
for sample in self.dataset:
|
| 200 |
+
ground_truth = sample[self.ground_truth_key]
|
| 201 |
+
self.gt_token_sequences.append(
|
| 202 |
+
[
|
| 203 |
+
self.json2token(
|
| 204 |
+
gt_json,
|
| 205 |
+
update_special_tokens_for_json_key=self.split == "train",
|
| 206 |
+
sort_json_key=self.sort_json_key,
|
| 207 |
+
)
|
| 208 |
+
+ DonutTrainer.processor.tokenizer.eos_token
|
| 209 |
+
for gt_json in [ground_truth] # load json from list of json
|
| 210 |
+
]
|
| 211 |
+
)
|
| 212 |
+
|
| 213 |
+
self.add_tokens([self.task_start_token, self.prompt_end_token])
|
| 214 |
+
self.prompt_end_token_id = DonutTrainer.processor.tokenizer.convert_tokens_to_ids(self.prompt_end_token)
|
| 215 |
+
|
| 216 |
+
def json2token(self, obj: Any, update_special_tokens_for_json_key: bool = True, sort_json_key: bool = True):
|
| 217 |
+
"""
|
| 218 |
+
Convert an ordered JSON object into a token sequence
|
| 219 |
+
"""
|
| 220 |
+
if type(obj) == dict:
|
| 221 |
+
if len(obj) == 1 and "text_sequence" in obj:
|
| 222 |
+
return obj["text_sequence"]
|
| 223 |
+
else:
|
| 224 |
+
output = ""
|
| 225 |
+
if sort_json_key:
|
| 226 |
+
keys = sorted(obj.keys(), reverse=True)
|
| 227 |
+
else:
|
| 228 |
+
keys = obj.keys()
|
| 229 |
+
for k in keys:
|
| 230 |
+
if update_special_tokens_for_json_key:
|
| 231 |
+
self.add_tokens([fr"<s_{k}>", fr"</s_{k}>"])
|
| 232 |
+
output += (
|
| 233 |
+
fr"<s_{k}>"
|
| 234 |
+
+ self.json2token(obj[k], update_special_tokens_for_json_key, sort_json_key)
|
| 235 |
+
+ fr"</s_{k}>"
|
| 236 |
+
)
|
| 237 |
+
return output
|
| 238 |
+
elif type(obj) == list:
|
| 239 |
+
return r"<sep/>".join(
|
| 240 |
+
[self.json2token(item, update_special_tokens_for_json_key, sort_json_key) for item in obj]
|
| 241 |
+
)
|
| 242 |
+
else:
|
| 243 |
+
obj = str(obj)
|
| 244 |
+
if f"<{obj}/>" in DonutTrainer.added_tokens:
|
| 245 |
+
obj = f"<{obj}/>" # for categorical special tokens
|
| 246 |
+
return obj
|
| 247 |
+
|
| 248 |
+
def add_tokens(self, list_of_tokens: List[str]):
|
| 249 |
+
"""
|
| 250 |
+
Add special tokens to tokenizer and resize the token embeddings of the decoder
|
| 251 |
+
"""
|
| 252 |
+
newly_added_num = DonutTrainer.processor.tokenizer.add_tokens(list_of_tokens)
|
| 253 |
+
if newly_added_num > 0:
|
| 254 |
+
DonutTrainer.model.decoder.resize_token_embeddings(len(DonutTrainer.processor.tokenizer))
|
| 255 |
+
DonutTrainer.added_tokens.extend(list_of_tokens)
|
| 256 |
+
|
| 257 |
+
def __len__(self) -> int:
|
| 258 |
+
return self.dataset_length
|
| 259 |
+
|
| 260 |
+
def __getitem__(self, idx: int) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
|
| 261 |
+
"""
|
| 262 |
+
Load image from image_path of given dataset_path and convert into input_tensor and labels
|
| 263 |
+
Convert gt data into input_ids (tokenized string)
|
| 264 |
+
Returns:
|
| 265 |
+
input_tensor : preprocessed image
|
| 266 |
+
input_ids : tokenized gt_data
|
| 267 |
+
labels : masked labels (model doesn't need to predict prompt and pad token)
|
| 268 |
+
"""
|
| 269 |
+
sample = self.dataset[idx]
|
| 270 |
+
|
| 271 |
+
# inputs
|
| 272 |
+
pixel_values = DonutTrainer.processor(sample["image"], random_padding=self.split == "train", return_tensors="pt").pixel_values
|
| 273 |
+
pixel_values = pixel_values.squeeze()
|
| 274 |
+
|
| 275 |
+
# targets
|
| 276 |
+
target_sequence = random.choice(self.gt_token_sequences[idx]) # can be more than one, e.g., DocVQA Task 1
|
| 277 |
+
input_ids = DonutTrainer.processor.tokenizer(
|
| 278 |
+
target_sequence,
|
| 279 |
+
add_special_tokens=False,
|
| 280 |
+
max_length=self.max_length,
|
| 281 |
+
padding="max_length",
|
| 282 |
+
truncation=True,
|
| 283 |
+
return_tensors="pt",
|
| 284 |
+
)["input_ids"].squeeze(0)
|
| 285 |
+
|
| 286 |
+
labels = input_ids.clone()
|
| 287 |
+
labels[labels == DonutTrainer.processor.tokenizer.pad_token_id] = self.ignore_id # model doesn't need to predict pad token
|
| 288 |
+
# labels[: torch.nonzero(labels == self.prompt_end_token_id).sum() + 1] = self.ignore_id # model doesn't need to predict prompt (for VQA)
|
| 289 |
+
return pixel_values, labels, target_sequence
|
| 290 |
+
|
| 291 |
+
|
| 292 |
+
class DonutModelPLModule(pl.LightningModule):
|
| 293 |
+
def __init__(self, config, processor, model):
|
| 294 |
+
super().__init__()
|
| 295 |
+
self.config = config
|
| 296 |
+
self.processor = processor
|
| 297 |
+
self.model = model
|
| 298 |
+
|
| 299 |
+
def training_step(self, batch, batch_idx):
|
| 300 |
+
pixel_values, labels, _ = batch
|
| 301 |
+
|
| 302 |
+
outputs = self.model(pixel_values, labels=labels)
|
| 303 |
+
loss = outputs.loss
|
| 304 |
+
self.log("train_loss", loss)
|
| 305 |
+
return loss
|
| 306 |
+
|
| 307 |
+
def validation_step(self, batch, batch_idx, dataset_idx=0):
|
| 308 |
+
pixel_values, labels, answers = batch
|
| 309 |
+
batch_size = pixel_values.shape[0]
|
| 310 |
+
# we feed the prompt to the model
|
| 311 |
+
decoder_input_ids = torch.full((batch_size, 1), self.model.config.decoder_start_token_id, device=self.device)
|
| 312 |
+
|
| 313 |
+
outputs = self.model.generate(pixel_values,
|
| 314 |
+
decoder_input_ids=decoder_input_ids,
|
| 315 |
+
max_length=DonutTrainer.max_length,
|
| 316 |
+
early_stopping=True,
|
| 317 |
+
pad_token_id=self.processor.tokenizer.pad_token_id,
|
| 318 |
+
eos_token_id=self.processor.tokenizer.eos_token_id,
|
| 319 |
+
use_cache=True,
|
| 320 |
+
num_beams=1,
|
| 321 |
+
bad_words_ids=[[self.processor.tokenizer.unk_token_id]],
|
| 322 |
+
return_dict_in_generate=True,)
|
| 323 |
+
|
| 324 |
+
predictions = []
|
| 325 |
+
for seq in self.processor.tokenizer.batch_decode(outputs.sequences):
|
| 326 |
+
seq = seq.replace(self.processor.tokenizer.eos_token, "").replace(self.processor.tokenizer.pad_token, "")
|
| 327 |
+
seq = re.sub(r"<.*?>", "", seq, count=1).strip() # remove first task start token
|
| 328 |
+
predictions.append(seq)
|
| 329 |
+
|
| 330 |
+
scores = []
|
| 331 |
+
for pred, answer in zip(predictions, answers):
|
| 332 |
+
pred = re.sub(r"(?:(?<=>) | (?=</s_))", "", pred)
|
| 333 |
+
# NOT NEEDED ANYMORE
|
| 334 |
+
# answer = re.sub(r"<.*?>", "", answer, count=1)
|
| 335 |
+
answer = answer.replace(self.processor.tokenizer.eos_token, "")
|
| 336 |
+
scores.append(edit_distance(pred, answer) / max(len(pred), len(answer)))
|
| 337 |
+
|
| 338 |
+
if self.config.get("verbose", False) and len(scores) == 1:
|
| 339 |
+
print(f"Prediction: {pred}")
|
| 340 |
+
print(f" Answer: {answer}")
|
| 341 |
+
print(f" Normed ED: {scores[0]}")
|
| 342 |
+
|
| 343 |
+
val_edit_distance = np.mean(scores)
|
| 344 |
+
self.log("val_edit_distance", val_edit_distance)
|
| 345 |
+
print(f"Validation Edit Distance: {val_edit_distance}")
|
| 346 |
+
|
| 347 |
+
return scores
|
| 348 |
+
|
| 349 |
+
def configure_optimizers(self):
|
| 350 |
+
# you could also add a learning rate scheduler if you want
|
| 351 |
+
optimizer = torch.optim.Adam(self.parameters(), lr=self.config.get("lr"))
|
| 352 |
+
|
| 353 |
+
return optimizer
|
| 354 |
+
|
| 355 |
+
def train_dataloader(self):
|
| 356 |
+
return DonutTrainer.train_dataloader
|
| 357 |
+
|
| 358 |
+
def val_dataloader(self):
|
| 359 |
+
return DonutTrainer.val_dataloader
|
| 360 |
+
|
| 361 |
+
class PushToHubCallback(Callback):
|
| 362 |
+
def on_train_epoch_end(self, trainer, pl_module):
|
| 363 |
+
print(f"Pushing model to the hub, epoch {trainer.current_epoch}")
|
| 364 |
+
pl_module.model.push_to_hub(DonutTrainer.huggingface_model_id, commit_message=f"Training in progress, epoch {trainer.current_epoch}")
|
| 365 |
+
self._upload_logs(trainer.logger.log_dir, trainer.current_epoch)
|
| 366 |
+
|
| 367 |
+
def on_train_end(self, trainer, pl_module):
|
| 368 |
+
print(f"Pushing model to the hub after training")
|
| 369 |
+
pl_module.processor.push_to_hub(DonutTrainer.huggingface_model_id,commit_message=f"Training done")
|
| 370 |
+
pl_module.model.push_to_hub(DonutTrainer.huggingface_model_id, commit_message=f"Training done")
|
| 371 |
+
self._upload_logs(trainer.logger.log_dir, "final")
|
| 372 |
+
|
| 373 |
+
def _upload_logs(self, log_dir: str, epoch_info):
|
| 374 |
+
try:
|
| 375 |
+
print(f"Attempting to upload logs from: {log_dir}")
|
| 376 |
+
upload_folder(folder_path=log_dir, repo_id=DonutTrainer.huggingface_model_id,
|
| 377 |
+
path_in_repo="tensorboard_logs",
|
| 378 |
+
commit_message=f"Upload logs - epoch {epoch_info}", ignore_patterns=["*.tmp", "*.lock"])
|
| 379 |
+
print(f"Successfully uploaded logs for epoch {epoch_info}")
|
| 380 |
+
except Exception as e:
|
| 381 |
+
print(f"Failed to upload logs: {e}")
|
| 382 |
+
pass
|
| 383 |
+
|
| 384 |
+
@classmethod
|
| 385 |
+
def train(
|
| 386 |
+
cls,
|
| 387 |
+
dataset: DatasetDict,
|
| 388 |
+
pretrained_model_repo_id: str,
|
| 389 |
+
huggingface_model_id: str,
|
| 390 |
+
epochs: int,
|
| 391 |
+
train_batch_size: int,
|
| 392 |
+
val_batch_size: int,
|
| 393 |
+
learning_rate: float,
|
| 394 |
+
val_check_interval: float,
|
| 395 |
+
check_val_every_n_epoch: int,
|
| 396 |
+
gradient_clip_val: float,
|
| 397 |
+
num_training_samples_per_epoch: int,
|
| 398 |
+
num_nodes: int,
|
| 399 |
+
warmup_steps: int,
|
| 400 |
+
ground_truth_key: str = "ground_truth"
|
| 401 |
+
):
|
| 402 |
+
cls.huggingface_model_id = huggingface_model_id
|
| 403 |
+
config = VisionEncoderDecoderConfig.from_pretrained(pretrained_model_repo_id)
|
| 404 |
+
config.encoder.image_size = cls.image_size
|
| 405 |
+
config.decoder.max_length = cls.max_length
|
| 406 |
+
|
| 407 |
+
cls.processor = DonutProcessor.from_pretrained(pretrained_model_repo_id)
|
| 408 |
+
cls.model = VisionEncoderDecoderModel.from_pretrained(pretrained_model_repo_id, config=config)
|
| 409 |
+
cls.processor.image_processor.size = cls.image_size[::-1]
|
| 410 |
+
cls.processor.image_processor.do_align_long_axis = False
|
| 411 |
+
|
| 412 |
+
train_dataset = cls.DonutDataset(
|
| 413 |
+
dataset=dataset,
|
| 414 |
+
ground_truth_key=ground_truth_key,
|
| 415 |
+
max_length=cls.max_length,
|
| 416 |
+
split="train",
|
| 417 |
+
task_start_token=TASK_PROMPT_NAME,
|
| 418 |
+
prompt_end_token=TASK_PROMPT_NAME,
|
| 419 |
+
sort_json_key=True
|
| 420 |
+
)
|
| 421 |
+
val_dataset = cls.DonutDataset(
|
| 422 |
+
dataset=dataset,
|
| 423 |
+
ground_truth_key=ground_truth_key,
|
| 424 |
+
max_length=cls.max_length,
|
| 425 |
+
split="validation",
|
| 426 |
+
task_start_token=TASK_PROMPT_NAME,
|
| 427 |
+
prompt_end_token=TASK_PROMPT_NAME,
|
| 428 |
+
sort_json_key=True
|
| 429 |
+
)
|
| 430 |
+
|
| 431 |
+
cls.model.config.pad_token_id = cls.processor.tokenizer.pad_token_id
|
| 432 |
+
cls.model.config.decoder_start_token_id = cls.processor.tokenizer.convert_tokens_to_ids([TASK_PROMPT_NAME])[0]
|
| 433 |
+
|
| 434 |
+
cls.train_dataloader = DataLoader(train_dataset, batch_size=1, shuffle=True, num_workers=4)
|
| 435 |
+
cls.val_dataloader = DataLoader(val_dataset, batch_size=1, shuffle=False, num_workers=4)
|
| 436 |
+
|
| 437 |
+
config = {
|
| 438 |
+
"max_epochs": epochs,
|
| 439 |
+
"val_check_interval": val_check_interval, # how many times we want to validate during an epoch
|
| 440 |
+
"check_val_every_n_epoch": check_val_every_n_epoch,
|
| 441 |
+
"gradient_clip_val": gradient_clip_val,
|
| 442 |
+
"num_training_samples_per_epoch": num_training_samples_per_epoch,
|
| 443 |
+
"lr": learning_rate,
|
| 444 |
+
"train_batch_sizes": [train_batch_size],
|
| 445 |
+
"val_batch_sizes": [val_batch_size],
|
| 446 |
+
# "seed":2022,
|
| 447 |
+
"num_nodes": num_nodes,
|
| 448 |
+
"warmup_steps": warmup_steps, # 10%
|
| 449 |
+
"result_path": "./.checkpoints",
|
| 450 |
+
"verbose": True,
|
| 451 |
+
}
|
| 452 |
+
model_module = cls.DonutModelPLModule(config, cls.processor, cls.model)
|
| 453 |
+
|
| 454 |
+
device = (
|
| 455 |
+
"cuda"
|
| 456 |
+
if torch.cuda.is_available()
|
| 457 |
+
else "mps" if torch.backends.mps.is_available() else "cpu"
|
| 458 |
+
)
|
| 459 |
+
print(f"Using {device} device")
|
| 460 |
+
trainer = pl.Trainer(
|
| 461 |
+
accelerator="gpu" if device == "cuda" else "mps" if device == "mps" else "cpu",
|
| 462 |
+
devices=1 if device == "cuda" else 0,
|
| 463 |
+
max_epochs=config.get("max_epochs"),
|
| 464 |
+
val_check_interval=config.get("val_check_interval"),
|
| 465 |
+
check_val_every_n_epoch=config.get("check_val_every_n_epoch"),
|
| 466 |
+
gradient_clip_val=config.get("gradient_clip_val"),
|
| 467 |
+
precision=16 if device == "cuda" else 32, # we'll use mixed precision if device == "cuda"
|
| 468 |
+
num_sanity_val_steps=0,
|
| 469 |
+
logger=TensorBoardLogger(save_dir="./.checkpoints", name="donut_training", version=None),
|
| 470 |
+
callbacks=[cls.PushToHubCallback()]
|
| 471 |
+
)
|
| 472 |
+
trainer.fit(model_module)
|
menu/llm/__init__.py
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .gemini import GeminiAPI
|
| 2 |
+
from .openai import OpenAIAPI
|
menu/llm/base.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import List
|
| 2 |
+
from abc import ABC, abstractmethod
|
| 3 |
+
|
| 4 |
+
from PIL import Image
|
| 5 |
+
|
| 6 |
+
PROMPT = "The provided images display a menu. IMPORTANT: There may be MULTIPLE images representing different pages. You MUST examine EVERY image provided and combine all extracted information into the final result. Do not miss any dishes from any page."
|
| 7 |
+
|
| 8 |
+
class LLMBase(ABC):
|
| 9 |
+
@classmethod
|
| 10 |
+
@abstractmethod
|
| 11 |
+
def call(cls, images: List[Image.Image], model: str, token: str) -> dict:
|
| 12 |
+
raise NotImplementedError
|
menu/llm/gemini.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json
|
| 2 |
+
from typing import List
|
| 3 |
+
|
| 4 |
+
from PIL import Image
|
| 5 |
+
from google import genai
|
| 6 |
+
from google.genai import types
|
| 7 |
+
|
| 8 |
+
from .base import LLMBase, PROMPT
|
| 9 |
+
|
| 10 |
+
FUNCTION_CALL = json.load(open("tools/schema_gemini.json", "r"))
|
| 11 |
+
|
| 12 |
+
class GeminiAPI(LLMBase):
|
| 13 |
+
@classmethod
|
| 14 |
+
def call(cls, images: List[Image.Image], model: str, token: str) -> dict:
|
| 15 |
+
client = genai.Client(api_key=token) # Initialize the client with the API key
|
| 16 |
+
|
| 17 |
+
config = types.GenerateContentConfig(
|
| 18 |
+
tools=[types.Tool(function_declarations=[FUNCTION_CALL])],
|
| 19 |
+
tool_config={
|
| 20 |
+
"function_calling_config": {
|
| 21 |
+
"mode": "ANY",
|
| 22 |
+
"allowed_function_names": [FUNCTION_CALL["name"]]
|
| 23 |
+
}
|
| 24 |
+
}
|
| 25 |
+
)
|
| 26 |
+
|
| 27 |
+
response = client.models.generate_content(
|
| 28 |
+
model=model,
|
| 29 |
+
contents=images + [PROMPT],
|
| 30 |
+
config=config
|
| 31 |
+
)
|
| 32 |
+
if response.candidates[0].content.parts[0].function_call:
|
| 33 |
+
function_call = response.candidates[0].content.parts[0].function_call
|
| 34 |
+
return function_call.args
|
| 35 |
+
|
| 36 |
+
return {}
|
menu/llm/openai.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json
|
| 2 |
+
import base64
|
| 3 |
+
from io import BytesIO
|
| 4 |
+
from typing import List
|
| 5 |
+
|
| 6 |
+
from PIL import Image
|
| 7 |
+
from openai import OpenAI
|
| 8 |
+
|
| 9 |
+
from .base import LLMBase, PROMPT
|
| 10 |
+
|
| 11 |
+
FUNCTION_CALL = json.load(open("tools/schema_openai.json", "r"))
|
| 12 |
+
|
| 13 |
+
class OpenAIAPI(LLMBase):
|
| 14 |
+
@classmethod
|
| 15 |
+
def call(cls, images: List[Image.Image], model: str, token: str) -> dict:
|
| 16 |
+
client = OpenAI(api_key=token) # Initialize the client with the API key
|
| 17 |
+
|
| 18 |
+
content = []
|
| 19 |
+
for image in images:
|
| 20 |
+
buffer = BytesIO()
|
| 21 |
+
image.save(buffer, format="JPEG")
|
| 22 |
+
encode_img = base64.b64encode(buffer.getvalue()).decode("utf-8")
|
| 23 |
+
content.append({
|
| 24 |
+
"type": "input_image",
|
| 25 |
+
"image_url": {"url": f"data:image/jpeg;base64,{encode_img}"},
|
| 26 |
+
})
|
| 27 |
+
|
| 28 |
+
content.append({"type": "text", "text": PROMPT})
|
| 29 |
+
|
| 30 |
+
response = client.responses.create(
|
| 31 |
+
model=model,
|
| 32 |
+
input=[
|
| 33 |
+
{
|
| 34 |
+
"role": "user",
|
| 35 |
+
"content": content,
|
| 36 |
+
}
|
| 37 |
+
],
|
| 38 |
+
tools=[FUNCTION_CALL],
|
| 39 |
+
)
|
| 40 |
+
if response and response.output:
|
| 41 |
+
if hasattr(response.output[0], "arguments"):
|
| 42 |
+
return json.loads(response.output[0].arguments)
|
| 43 |
+
return {}
|
menu/utils.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Optional
|
| 2 |
+
|
| 3 |
+
from datasets import Dataset, DatasetDict
|
| 4 |
+
|
| 5 |
+
def split_dataset(
|
| 6 |
+
dataset: Dataset,
|
| 7 |
+
train: float,
|
| 8 |
+
validation: float,
|
| 9 |
+
test: float,
|
| 10 |
+
seed: Optional[int] = None
|
| 11 |
+
) -> DatasetDict:
|
| 12 |
+
"""
|
| 13 |
+
Split a single-split Hugging Face Dataset into train/validation/test subsets.
|
| 14 |
+
|
| 15 |
+
Args:
|
| 16 |
+
dataset (Dataset): The input dataset (e.g. load_dataset(...)['train']).
|
| 17 |
+
train (float): Proportion of data for the train split (0 < train < 1).
|
| 18 |
+
val (float): Proportion of data for the validation split (0 < val < 1).
|
| 19 |
+
test (float): Proportion of data for the test split (0 < test < 1).
|
| 20 |
+
Must satisfy train + val + test == 1.0.
|
| 21 |
+
seed (int): Random seed for reproducibility (default: None).
|
| 22 |
+
|
| 23 |
+
Returns:
|
| 24 |
+
DatasetDict: A dictionary with keys "train", "validation", and "test".
|
| 25 |
+
"""
|
| 26 |
+
# Verify ratios sum to 1.0
|
| 27 |
+
total = train + validation + test
|
| 28 |
+
if abs(total - 1.0) > 1e-8:
|
| 29 |
+
raise ValueError(f"train + validation + test must equal 1.0 (got {total})")
|
| 30 |
+
|
| 31 |
+
# First split: extract train vs. temp (validation + test)
|
| 32 |
+
temp_size = validation + test
|
| 33 |
+
split_1 = dataset.train_test_split(test_size=temp_size, seed=seed)
|
| 34 |
+
train_ds = split_1["train"]
|
| 35 |
+
temp_ds = split_1["test"]
|
| 36 |
+
|
| 37 |
+
# Second split: divide temp into validation vs. test
|
| 38 |
+
relative_test_size = test / temp_size
|
| 39 |
+
split_2 = temp_ds.train_test_split(test_size=relative_test_size, seed=seed)
|
| 40 |
+
validation_ds = split_2["train"]
|
| 41 |
+
test_ds = split_2["test"]
|
| 42 |
+
|
| 43 |
+
# Return a DatasetDict with all three splits
|
| 44 |
+
return DatasetDict({
|
| 45 |
+
"train": train_ds,
|
| 46 |
+
"validation": validation_ds,
|
| 47 |
+
"test": test_ds,
|
| 48 |
+
})
|
pyproject.toml
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[project]
|
| 2 |
+
authors = [{name = "ryanlinjui", email = "ryanlinjui@gmail.com"}]
|
| 3 |
+
name = "menu-text-detection"
|
| 4 |
+
version = "0.1.0"
|
| 5 |
+
description = "Extract structured menu information from images into JSON using a fine-tuned Donut E2E model."
|
| 6 |
+
readme = "README.md"
|
| 7 |
+
requires-python = "==3.11.*"
|
| 8 |
+
dependencies = [
|
| 9 |
+
"datasets>=3.6.0",
|
| 10 |
+
"dotenv>=0.9.9",
|
| 11 |
+
"google-genai>=1.14.0",
|
| 12 |
+
"gradio>=5.29.0",
|
| 13 |
+
"huggingface-hub>=0.31.1,<1.0",
|
| 14 |
+
"matplotlib>=3.10.1",
|
| 15 |
+
"nltk>=3.9.1",
|
| 16 |
+
"notebook>=7.4.2",
|
| 17 |
+
"openai>=1.77.0",
|
| 18 |
+
"pillow>=11.2.1",
|
| 19 |
+
"pillow-heif>=0.22.0",
|
| 20 |
+
"protobuf>=6.30.2",
|
| 21 |
+
"pytorch-lightning>=2.5.2",
|
| 22 |
+
"sentencepiece>=0.2.0",
|
| 23 |
+
"tensorboardx>=2.6.2.2",
|
| 24 |
+
"transformers==4.49",
|
| 25 |
+
"torch==2.4.1",
|
| 26 |
+
"donut-python>=1.0.9",
|
| 27 |
+
]
|
requirements.txt
ADDED
|
@@ -0,0 +1,1475 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file was autogenerated by uv via the following command:
|
| 2 |
+
# uv export --format requirements-txt
|
| 3 |
+
aiofiles==24.1.0 \
|
| 4 |
+
--hash=sha256:22a075c9e5a3810f0c2e48f3008c94d68c65d763b9b03857924c99e57355166c \
|
| 5 |
+
--hash=sha256:b4ec55f4195e3eb5d7abd1bf7e061763e864dd4954231fb8539a0ef8bb8260e5
|
| 6 |
+
# via gradio
|
| 7 |
+
aiohappyeyeballs==2.6.1 \
|
| 8 |
+
--hash=sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558 \
|
| 9 |
+
--hash=sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8
|
| 10 |
+
# via aiohttp
|
| 11 |
+
aiohttp==3.11.18 \
|
| 12 |
+
--hash=sha256:0700055a6e05c2f4711011a44364020d7a10fbbcd02fbf3e30e8f7e7fddc8717 \
|
| 13 |
+
--hash=sha256:122f3e739f6607e5e4c6a2f8562a6f476192a682a52bda8b4c6d4254e1138f4d \
|
| 14 |
+
--hash=sha256:25557982dd36b9e32c0a3357f30804e80790ec2c4d20ac6bcc598533e04c6361 \
|
| 15 |
+
--hash=sha256:2c828b6d23b984255b85b9b04a5b963a74278b7356a7de84fda5e3b76866597b \
|
| 16 |
+
--hash=sha256:3a621d85e85dccabd700294494d7179ed1590b6d07a35709bb9bd608c7f5dd1d \
|
| 17 |
+
--hash=sha256:3d518ce32179f7e2096bf4e3e8438cf445f05fedd597f252de9f54c728574756 \
|
| 18 |
+
--hash=sha256:427fdc56ccb6901ff8088544bde47084845ea81591deb16f957897f0f0ba1be9 \
|
| 19 |
+
--hash=sha256:5c2eaa145bb36b33af1ff2860820ba0589e165be4ab63a49aebfd0981c173b66 \
|
| 20 |
+
--hash=sha256:73b8870fe1c9a201b8c0d12c94fe781b918664766728783241a79e0468427e4f \
|
| 21 |
+
--hash=sha256:7e889c9df381a2433802991288a61e5a19ceb4f61bd14f5c9fa165655dcb1fd1 \
|
| 22 |
+
--hash=sha256:8bd1cde83e4684324e6ee19adfc25fd649d04078179890be7b29f76b501de8e4 \
|
| 23 |
+
--hash=sha256:9c23fd8d08eb9c2af3faeedc8c56e134acdaf36e2117ee059d7defa655130e5f \
|
| 24 |
+
--hash=sha256:9ea345fda05bae217b6cce2acf3682ce3b13d0d16dd47d0de7080e5e21362421 \
|
| 25 |
+
--hash=sha256:9f26545b9940c4b46f0a9388fd04ee3ad7064c4017b5a334dd450f616396590e \
|
| 26 |
+
--hash=sha256:ae856e1138612b7e412db63b7708735cff4d38d0399f6a5435d3dac2669f558a \
|
| 27 |
+
--hash=sha256:d9e6b0e519067caa4fd7fb72e3e8002d16a68e84e62e7291092a5433763dc0dd \
|
| 28 |
+
--hash=sha256:e6f3c0a3a1e73e88af384b2e8a0b9f4fb73245afd47589df2afcab6b638fa0e6
|
| 29 |
+
# via fsspec
|
| 30 |
+
aiosignal==1.3.2 \
|
| 31 |
+
--hash=sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5 \
|
| 32 |
+
--hash=sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54
|
| 33 |
+
# via aiohttp
|
| 34 |
+
annotated-types==0.7.0 \
|
| 35 |
+
--hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \
|
| 36 |
+
--hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89
|
| 37 |
+
# via pydantic
|
| 38 |
+
anyio==4.9.0 \
|
| 39 |
+
--hash=sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028 \
|
| 40 |
+
--hash=sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c
|
| 41 |
+
# via
|
| 42 |
+
# google-genai
|
| 43 |
+
# gradio
|
| 44 |
+
# httpx
|
| 45 |
+
# jupyter-server
|
| 46 |
+
# openai
|
| 47 |
+
# starlette
|
| 48 |
+
appnope==0.1.4 ; sys_platform == 'darwin' \
|
| 49 |
+
--hash=sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee \
|
| 50 |
+
--hash=sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c
|
| 51 |
+
# via ipykernel
|
| 52 |
+
argon2-cffi==23.1.0 \
|
| 53 |
+
--hash=sha256:879c3e79a2729ce768ebb7d36d4609e3a78a4ca2ec3a9f12286ca057e3d0db08 \
|
| 54 |
+
--hash=sha256:c670642b78ba29641818ab2e68bd4e6a78ba53b7eff7b4c3815ae16abf91c7ea
|
| 55 |
+
# via jupyter-server
|
| 56 |
+
argon2-cffi-bindings==21.2.0 \
|
| 57 |
+
--hash=sha256:58ed19212051f49a523abb1dbe954337dc82d947fb6e5a0da60f7c8471a8476c \
|
| 58 |
+
--hash=sha256:603ca0aba86b1349b147cab91ae970c63118a0f30444d4bc80355937c950c082 \
|
| 59 |
+
--hash=sha256:8cd69c07dd875537a824deec19f978e0f2078fdda07fd5c42ac29668dda5f40f \
|
| 60 |
+
--hash=sha256:9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d \
|
| 61 |
+
--hash=sha256:b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f \
|
| 62 |
+
--hash=sha256:b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae \
|
| 63 |
+
--hash=sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3 \
|
| 64 |
+
--hash=sha256:bd46088725ef7f58b5a1ef7ca06647ebaf0eb4baff7d1d0d177c6cc8744abd86 \
|
| 65 |
+
--hash=sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367 \
|
| 66 |
+
--hash=sha256:e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93 \
|
| 67 |
+
--hash=sha256:f1152ac548bd5b8bcecfb0b0371f082037e47128653df2e8ba6e914d384f3c3e
|
| 68 |
+
# via argon2-cffi
|
| 69 |
+
arrow==1.3.0 \
|
| 70 |
+
--hash=sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80 \
|
| 71 |
+
--hash=sha256:d4540617648cb5f895730f1ad8c82a65f2dad0166f57b75f3ca54759c4d67a85
|
| 72 |
+
# via isoduration
|
| 73 |
+
asttokens==3.0.0 \
|
| 74 |
+
--hash=sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7 \
|
| 75 |
+
--hash=sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2
|
| 76 |
+
# via stack-data
|
| 77 |
+
async-lru==2.0.5 \
|
| 78 |
+
--hash=sha256:481d52ccdd27275f42c43a928b4a50c3bfb2d67af4e78b170e3e0bb39c66e5bb \
|
| 79 |
+
--hash=sha256:ab95404d8d2605310d345932697371a5f40def0487c03d6d0ad9138de52c9943
|
| 80 |
+
# via jupyterlab
|
| 81 |
+
attrs==25.3.0 \
|
| 82 |
+
--hash=sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3 \
|
| 83 |
+
--hash=sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b
|
| 84 |
+
# via
|
| 85 |
+
# aiohttp
|
| 86 |
+
# jsonschema
|
| 87 |
+
# referencing
|
| 88 |
+
babel==2.17.0 \
|
| 89 |
+
--hash=sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d \
|
| 90 |
+
--hash=sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2
|
| 91 |
+
# via jupyterlab-server
|
| 92 |
+
beautifulsoup4==4.13.4 \
|
| 93 |
+
--hash=sha256:9bbbb14bfde9d79f38b8cd5f8c7c85f4b8f2523190ebed90e950a8dea4cb1c4b \
|
| 94 |
+
--hash=sha256:dbb3c4e1ceae6aefebdaf2423247260cd062430a410e38c66f2baa50a8437195
|
| 95 |
+
# via nbconvert
|
| 96 |
+
bleach==6.2.0 \
|
| 97 |
+
--hash=sha256:117d9c6097a7c3d22fd578fcd8d35ff1e125df6736f554da4e432fdd63f31e5e \
|
| 98 |
+
--hash=sha256:123e894118b8a599fd80d3ec1a6d4cc7ce4e5882b1317a7e1ba69b56e95f991f
|
| 99 |
+
# via nbconvert
|
| 100 |
+
cachetools==5.5.2 \
|
| 101 |
+
--hash=sha256:1a661caa9175d26759571b2e19580f9d6393969e5dfca11fdb1f947a23e640d4 \
|
| 102 |
+
--hash=sha256:d26a22bcc62eb95c3beabd9f1ee5e820d3d2704fe2967cbe350e20c8ffcd3f0a
|
| 103 |
+
# via google-auth
|
| 104 |
+
certifi==2025.4.26 \
|
| 105 |
+
--hash=sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6 \
|
| 106 |
+
--hash=sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3
|
| 107 |
+
# via
|
| 108 |
+
# httpcore
|
| 109 |
+
# httpx
|
| 110 |
+
# requests
|
| 111 |
+
cffi==1.17.1 \
|
| 112 |
+
--hash=sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824 \
|
| 113 |
+
--hash=sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf \
|
| 114 |
+
--hash=sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1 \
|
| 115 |
+
--hash=sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d \
|
| 116 |
+
--hash=sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655 \
|
| 117 |
+
--hash=sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41 \
|
| 118 |
+
--hash=sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6 \
|
| 119 |
+
--hash=sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401 \
|
| 120 |
+
--hash=sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6 \
|
| 121 |
+
--hash=sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0 \
|
| 122 |
+
--hash=sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f \
|
| 123 |
+
--hash=sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4 \
|
| 124 |
+
--hash=sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b
|
| 125 |
+
# via
|
| 126 |
+
# argon2-cffi-bindings
|
| 127 |
+
# pyzmq
|
| 128 |
+
charset-normalizer==3.4.2 \
|
| 129 |
+
--hash=sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0 \
|
| 130 |
+
--hash=sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7 \
|
| 131 |
+
--hash=sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8 \
|
| 132 |
+
--hash=sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63 \
|
| 133 |
+
--hash=sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5 \
|
| 134 |
+
--hash=sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0 \
|
| 135 |
+
--hash=sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645 \
|
| 136 |
+
--hash=sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2 \
|
| 137 |
+
--hash=sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd \
|
| 138 |
+
--hash=sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a \
|
| 139 |
+
--hash=sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28 \
|
| 140 |
+
--hash=sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82 \
|
| 141 |
+
--hash=sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9 \
|
| 142 |
+
--hash=sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544 \
|
| 143 |
+
--hash=sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f
|
| 144 |
+
# via requests
|
| 145 |
+
click==8.1.8 \
|
| 146 |
+
--hash=sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2 \
|
| 147 |
+
--hash=sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a
|
| 148 |
+
# via
|
| 149 |
+
# nltk
|
| 150 |
+
# typer
|
| 151 |
+
# uvicorn
|
| 152 |
+
colorama==0.4.6 ; sys_platform == 'win32' \
|
| 153 |
+
--hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \
|
| 154 |
+
--hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6
|
| 155 |
+
# via
|
| 156 |
+
# click
|
| 157 |
+
# ipython
|
| 158 |
+
# tqdm
|
| 159 |
+
comm==0.2.2 \
|
| 160 |
+
--hash=sha256:3fd7a84065306e07bea1773df6eb8282de51ba82f77c72f9c85716ab11fe980e \
|
| 161 |
+
--hash=sha256:e6fb86cb70ff661ee8c9c14e7d36d6de3b4066f1441be4063df9c5009f0a64d3
|
| 162 |
+
# via ipykernel
|
| 163 |
+
contourpy==1.3.2 \
|
| 164 |
+
--hash=sha256:1c48188778d4d2f3d48e4643fb15d8608b1d01e4b4d6b0548d9b336c28fc9b6f \
|
| 165 |
+
--hash=sha256:3859783aefa2b8355697f16642695a5b9792e7a46ab86da1118a4a23a51a33d7 \
|
| 166 |
+
--hash=sha256:49b65a95d642d4efa8f64ba12558fcb83407e58a2dfba9d796d77b63ccfcaff5 \
|
| 167 |
+
--hash=sha256:5ebac872ba09cb8f2131c46b8739a7ff71de28a24c869bcad554477eb089a878 \
|
| 168 |
+
--hash=sha256:5f5964cdad279256c084b69c3f412b7801e15356b16efa9d78aa974041903da0 \
|
| 169 |
+
--hash=sha256:65a887a6e8c4cd0897507d814b14c54a8c2e2aa4ac9f7686292f9769fcf9a6ab \
|
| 170 |
+
--hash=sha256:6a37a2fb93d4df3fc4c0e363ea4d16f83195fc09c891bc8ce072b9d084853445 \
|
| 171 |
+
--hash=sha256:70771a461aaeb335df14deb6c97439973d253ae70660ca085eec25241137ef43 \
|
| 172 |
+
--hash=sha256:8c5acb8dddb0752bf252e01a3035b21443158910ac16a3b0d20e7fed7d534ce5 \
|
| 173 |
+
--hash=sha256:b6945942715a034c671b7fc54f9588126b0b8bf23db2696e3ca8328f3ff0ab54 \
|
| 174 |
+
--hash=sha256:b7cd50c38f500bbcc9b6a46643a40e0913673f869315d8e70de0438817cb7773 \
|
| 175 |
+
--hash=sha256:d6658ccc7251a4433eebd89ed2672c2ed96fba367fd25ca9512aa92a4b46c4f1 \
|
| 176 |
+
--hash=sha256:d91a3ccc7fea94ca0acab82ceb77f396d50a1f67412efe4c526f5d20264e6ecd \
|
| 177 |
+
--hash=sha256:eab0f6db315fa4d70f1d8ab514e527f0366ec021ff853d7ed6a2d33605cf4b83
|
| 178 |
+
# via matplotlib
|
| 179 |
+
cycler==0.12.1 \
|
| 180 |
+
--hash=sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30 \
|
| 181 |
+
--hash=sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c
|
| 182 |
+
# via matplotlib
|
| 183 |
+
datasets==3.6.0 \
|
| 184 |
+
--hash=sha256:1b2bf43b19776e2787e181cfd329cb0ca1a358ea014780c3581e0f276375e041 \
|
| 185 |
+
--hash=sha256:25000c4a2c0873a710df127d08a202a06eab7bf42441a6bc278b499c2f72cd1b
|
| 186 |
+
# via
|
| 187 |
+
# donut-python
|
| 188 |
+
# menu-text-detection
|
| 189 |
+
debugpy==1.8.14 \
|
| 190 |
+
--hash=sha256:1b2ac8c13b2645e0b1eaf30e816404990fbdb168e193322be8f545e8c01644a9 \
|
| 191 |
+
--hash=sha256:5cd9a579d553b6cb9759a7908a41988ee6280b961f24f63336835d9418216a20 \
|
| 192 |
+
--hash=sha256:7816acea4a46d7e4e50ad8d09d963a680ecc814ae31cdef3622eb05ccacf7b01 \
|
| 193 |
+
--hash=sha256:7cd287184318416850aa8b60ac90105837bb1e59531898c07569d197d2ed5322 \
|
| 194 |
+
--hash=sha256:c99295c76161ad8d507b413cd33422d7c542889fbb73035889420ac1fad354f2 \
|
| 195 |
+
--hash=sha256:cf431c343a99384ac7eab2f763980724834f933a271e90496944195318c619e2
|
| 196 |
+
# via ipykernel
|
| 197 |
+
decorator==5.2.1 \
|
| 198 |
+
--hash=sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360 \
|
| 199 |
+
--hash=sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a
|
| 200 |
+
# via ipython
|
| 201 |
+
defusedxml==0.7.1 \
|
| 202 |
+
--hash=sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69 \
|
| 203 |
+
--hash=sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61
|
| 204 |
+
# via nbconvert
|
| 205 |
+
dill==0.3.8 \
|
| 206 |
+
--hash=sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca \
|
| 207 |
+
--hash=sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7
|
| 208 |
+
# via
|
| 209 |
+
# datasets
|
| 210 |
+
# multiprocess
|
| 211 |
+
distro==1.9.0 \
|
| 212 |
+
--hash=sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed \
|
| 213 |
+
--hash=sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2
|
| 214 |
+
# via openai
|
| 215 |
+
donut-python==1.0.9 \
|
| 216 |
+
--hash=sha256:cf2e99fa0515f6f7bd8da6d1198c1bb5532760d8595425b2036d62ec92532329
|
| 217 |
+
# via menu-text-detection
|
| 218 |
+
dotenv==0.9.9 \
|
| 219 |
+
--hash=sha256:29cf74a087b31dafdb5a446b6d7e11cbce8ed2741540e2339c69fbef92c94ce9
|
| 220 |
+
# via menu-text-detection
|
| 221 |
+
executing==2.2.0 \
|
| 222 |
+
--hash=sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa \
|
| 223 |
+
--hash=sha256:5d108c028108fe2551d1a7b2e8b713341e2cb4fc0aa7dcf966fa4327a5226755
|
| 224 |
+
# via stack-data
|
| 225 |
+
fastapi==0.115.12 \
|
| 226 |
+
--hash=sha256:1e2c2a2646905f9e83d32f04a3f86aff4a286669c6c950ca95b5fd68c2602681 \
|
| 227 |
+
--hash=sha256:e94613d6c05e27be7ffebdd6ea5f388112e5e430c8f7d6494a9d1d88d43e814d
|
| 228 |
+
# via gradio
|
| 229 |
+
fastjsonschema==2.21.1 \
|
| 230 |
+
--hash=sha256:794d4f0a58f848961ba16af7b9c85a3e88cd360df008c59aac6fc5ae9323b5d4 \
|
| 231 |
+
--hash=sha256:c9e5b7e908310918cf494a434eeb31384dd84a98b57a30bcb1f535015b554667
|
| 232 |
+
# via nbformat
|
| 233 |
+
ffmpy==0.5.0 \
|
| 234 |
+
--hash=sha256:277e131f246d18e9dcfee9bb514c50749031c43582ce5ef82c57b51e3d3955c3 \
|
| 235 |
+
--hash=sha256:df3799cf5816daa56d4959a023630ee53c6768b66009dae6d131519ba4b80233
|
| 236 |
+
# via gradio
|
| 237 |
+
filelock==3.18.0 \
|
| 238 |
+
--hash=sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2 \
|
| 239 |
+
--hash=sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de
|
| 240 |
+
# via
|
| 241 |
+
# datasets
|
| 242 |
+
# huggingface-hub
|
| 243 |
+
# torch
|
| 244 |
+
# transformers
|
| 245 |
+
# triton
|
| 246 |
+
fonttools==4.57.0 \
|
| 247 |
+
--hash=sha256:17168a4670bbe3775f3f3f72d23ee786bd965395381dfbb70111e25e81505b9d \
|
| 248 |
+
--hash=sha256:3122c604a675513c68bd24c6a8f9091f1c2376d18e8f5fe5a101746c81b3e98f \
|
| 249 |
+
--hash=sha256:3871349303bdec958360eedb619169a779956503ffb4543bb3e6211e09b647c4 \
|
| 250 |
+
--hash=sha256:39acf68abdfc74e19de7485f8f7396fa4d2418efea239b7061d6ed6a2510c746 \
|
| 251 |
+
--hash=sha256:46370ac47a1e91895d40e9ad48effbe8e9d9db1a4b80888095bc00e7beaa042f \
|
| 252 |
+
--hash=sha256:727ece10e065be2f9dd239d15dd5d60a66e17eac11aea47d447f9f03fdbc42de \
|
| 253 |
+
--hash=sha256:967b65232e104f4b0f6370a62eb33089e00024f2ce143aecbf9755649421c683 \
|
| 254 |
+
--hash=sha256:9d077f909f2343daf4495ba22bb0e23b62886e8ec7c109ee8234bdbd678cf344 \
|
| 255 |
+
--hash=sha256:c59375e85126b15a90fcba3443eaac58f3073ba091f02410eaa286da9ad80ed8 \
|
| 256 |
+
--hash=sha256:ca2aed95855506b7ae94e8f1f6217b7673c929e4f4f1217bcaa236253055cb36
|
| 257 |
+
# via matplotlib
|
| 258 |
+
fqdn==1.5.1 \
|
| 259 |
+
--hash=sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f \
|
| 260 |
+
--hash=sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014
|
| 261 |
+
# via jsonschema
|
| 262 |
+
frozenlist==1.6.0 \
|
| 263 |
+
--hash=sha256:118e97556306402e2b010da1ef21ea70cb6d6122e580da64c056b96f524fbd6a \
|
| 264 |
+
--hash=sha256:1c6eceb88aaf7221f75be6ab498dc622a151f5f88d536661af3ffc486245a626 \
|
| 265 |
+
--hash=sha256:3e911391bffdb806001002c1f860787542f45916c3baf764264a52765d5a5603 \
|
| 266 |
+
--hash=sha256:431ef6937ae0f853143e2ca67d6da76c083e8b1fe3df0e96f3802fd37626e606 \
|
| 267 |
+
--hash=sha256:49ba23817781e22fcbd45fd9ff2b9b8cdb7b16a42a4851ab8025cae7b22e96d0 \
|
| 268 |
+
--hash=sha256:535eec9987adb04701266b92745d6cdcef2e77669299359c3009c3404dd5d191 \
|
| 269 |
+
--hash=sha256:54dece0d21dce4fdb188a1ffc555926adf1d1c516e493c2914d7c370e454bc9e \
|
| 270 |
+
--hash=sha256:62c828a5b195570eb4b37369fcbbd58e96c905768d53a44d13044355647838ff \
|
| 271 |
+
--hash=sha256:654e4ba1d0b2154ca2f096bed27461cf6160bc7f504a7f9a9ef447c293caf860 \
|
| 272 |
+
--hash=sha256:716bbba09611b4663ecbb7cd022f640759af8259e12a6ca939c0a6acd49eedba \
|
| 273 |
+
--hash=sha256:7b8c4dc422c1a3ffc550b465090e53b0bf4839047f3e436a34172ac67c45d595 \
|
| 274 |
+
--hash=sha256:8c952f69dd524558694818a461855f35d36cc7f5c0adddce37e962c85d06eac0 \
|
| 275 |
+
--hash=sha256:8f5fef13136c4e2dee91bfb9a44e236fff78fc2cd9f838eddfc470c3d7d90afe \
|
| 276 |
+
--hash=sha256:9d124b38b3c299ca68433597ee26b7819209cb8a3a9ea761dfe9db3a04bba584 \
|
| 277 |
+
--hash=sha256:ae8337990e7a45683548ffb2fee1af2f1ed08169284cd829cdd9a7fa7470530d \
|
| 278 |
+
--hash=sha256:b11534872256e1666116f6587a1592ef395a98b54476addb5e8d352925cb5d4a \
|
| 279 |
+
--hash=sha256:b99655c32c1c8e06d111e7f41c06c29a5318cb1835df23a45518e02a47c63b68 \
|
| 280 |
+
--hash=sha256:e1c6bd2c6399920c9622362ce95a7d74e7f9af9bfec05fff91b8ce4b9647845a \
|
| 281 |
+
--hash=sha256:fb3b309f1d4086b5533cf7bbcf3f956f0ae6469664522f1bde4feed26fba60f1
|
| 282 |
+
# via
|
| 283 |
+
# aiohttp
|
| 284 |
+
# aiosignal
|
| 285 |
+
fsspec==2025.3.0 \
|
| 286 |
+
--hash=sha256:a935fd1ea872591f2b5148907d103488fc523295e6c64b835cfad8c3eca44972 \
|
| 287 |
+
--hash=sha256:efb87af3efa9103f94ca91a7f8cb7a4df91af9f74fc106c9c7ea0efd7277c1b3
|
| 288 |
+
# via
|
| 289 |
+
# datasets
|
| 290 |
+
# gradio-client
|
| 291 |
+
# huggingface-hub
|
| 292 |
+
# pytorch-lightning
|
| 293 |
+
# torch
|
| 294 |
+
google-auth==2.40.1 \
|
| 295 |
+
--hash=sha256:58f0e8416a9814c1d86c9b7f6acf6816b51aba167b2c76821965271bac275540 \
|
| 296 |
+
--hash=sha256:ed4cae4f5c46b41bae1d19c036e06f6c371926e97b19e816fc854eff811974ee
|
| 297 |
+
# via google-genai
|
| 298 |
+
google-genai==1.14.0 \
|
| 299 |
+
--hash=sha256:5916ee985bf69ac7b68c4488949225db71e21579afc7ba5ecd5321173b60d3b2 \
|
| 300 |
+
--hash=sha256:7c608de5bb173486a546f5ec4562255c26bae72d33d758a3207bb26f695d0087
|
| 301 |
+
# via menu-text-detection
|
| 302 |
+
gradio==5.29.0 \
|
| 303 |
+
--hash=sha256:56fdd8b7cb31de8e4c382677560ef8a79f4ae0c3fbb139341bce052aab728064 \
|
| 304 |
+
--hash=sha256:6b58321c3b2d596a701e9b1660334772a160262e4c67f18848bd54b6c0db7d89
|
| 305 |
+
# via menu-text-detection
|
| 306 |
+
gradio-client==1.10.0 \
|
| 307 |
+
--hash=sha256:463bd60f0b11580185de13a01a1621fbff179fe29359dfa8810c1b3f9df5e342 \
|
| 308 |
+
--hash=sha256:47bfc878a3715604f6f0a554dc63f9ed78d14b126274f7d137e25447c737cd63
|
| 309 |
+
# via gradio
|
| 310 |
+
groovy==0.1.2 \
|
| 311 |
+
--hash=sha256:25c1dc09b3f9d7e292458aa762c6beb96ea037071bf5e917fc81fb78d2231083 \
|
| 312 |
+
--hash=sha256:7f7975bab18c729a257a8b1ae9dcd70b7cafb1720481beae47719af57c35fa64
|
| 313 |
+
# via gradio
|
| 314 |
+
h11==0.16.0 \
|
| 315 |
+
--hash=sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1 \
|
| 316 |
+
--hash=sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86
|
| 317 |
+
# via
|
| 318 |
+
# httpcore
|
| 319 |
+
# uvicorn
|
| 320 |
+
hf-xet==1.1.0 ; platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64' \
|
| 321 |
+
--hash=sha256:0322c42551e275fcb7949c083a54a81b2898e50787c9aa74284fcb8d2c58c12c \
|
| 322 |
+
--hash=sha256:3aee847da362393331f515c4010d0aaa1c2669acfcca1f4b28946d6949cc0086 \
|
| 323 |
+
--hash=sha256:4ee9222bf9274b1c198b88a929de0b5a49349c4962d89c5b3b2f0f7f47d9761c \
|
| 324 |
+
--hash=sha256:667153a0304ac2debf2af95a8ff7687186f885b493f4cd16344869af270cd110 \
|
| 325 |
+
--hash=sha256:68c5813a6074aa36e12ef5983230e3b03148cce61e0fcdd294096493795565b4 \
|
| 326 |
+
--hash=sha256:73153eab9abf3d6973b21e94a67ccba5d595c3e12feb8c0bf50be02964e7f126 \
|
| 327 |
+
--hash=sha256:995eeffb119636ea617b96c7d7bf3c3f5ea8727fa57974574e25d700b8532d48 \
|
| 328 |
+
--hash=sha256:a7c2a4c2b6eee9ce0a1a367a82b60d95ba634420ef1c250addad7aa4af419cf4
|
| 329 |
+
# via huggingface-hub
|
| 330 |
+
httpcore==1.0.9 \
|
| 331 |
+
--hash=sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55 \
|
| 332 |
+
--hash=sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8
|
| 333 |
+
# via httpx
|
| 334 |
+
httpx==0.28.1 \
|
| 335 |
+
--hash=sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc \
|
| 336 |
+
--hash=sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad
|
| 337 |
+
# via
|
| 338 |
+
# google-genai
|
| 339 |
+
# gradio
|
| 340 |
+
# gradio-client
|
| 341 |
+
# jupyterlab
|
| 342 |
+
# openai
|
| 343 |
+
# safehttpx
|
| 344 |
+
huggingface-hub==0.31.1 \
|
| 345 |
+
--hash=sha256:43f73124819b48b42d140cbc0d7a2e6bd15b2853b1b9d728d4d55ad1750cac5b \
|
| 346 |
+
--hash=sha256:492bb5f545337aa9e2f59b75ef4c5f535a371e8958a6ce90af056387e67f1180
|
| 347 |
+
# via
|
| 348 |
+
# datasets
|
| 349 |
+
# gradio
|
| 350 |
+
# gradio-client
|
| 351 |
+
# menu-text-detection
|
| 352 |
+
# timm
|
| 353 |
+
# tokenizers
|
| 354 |
+
# transformers
|
| 355 |
+
idna==3.10 \
|
| 356 |
+
--hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \
|
| 357 |
+
--hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3
|
| 358 |
+
# via
|
| 359 |
+
# anyio
|
| 360 |
+
# httpx
|
| 361 |
+
# jsonschema
|
| 362 |
+
# requests
|
| 363 |
+
# yarl
|
| 364 |
+
ipykernel==6.29.5 \
|
| 365 |
+
--hash=sha256:afdb66ba5aa354b09b91379bac28ae4afebbb30e8b39510c9690afb7a10421b5 \
|
| 366 |
+
--hash=sha256:f093a22c4a40f8828f8e330a9c297cb93dcab13bd9678ded6de8e5cf81c56215
|
| 367 |
+
# via jupyterlab
|
| 368 |
+
ipython==9.2.0 \
|
| 369 |
+
--hash=sha256:62a9373dbc12f28f9feaf4700d052195bf89806279fc8ca11f3f54017d04751b \
|
| 370 |
+
--hash=sha256:fef5e33c4a1ae0759e0bba5917c9db4eb8c53fee917b6a526bd973e1ca5159f6
|
| 371 |
+
# via ipykernel
|
| 372 |
+
ipython-pygments-lexers==1.1.1 \
|
| 373 |
+
--hash=sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81 \
|
| 374 |
+
--hash=sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c
|
| 375 |
+
# via ipython
|
| 376 |
+
isoduration==20.11.0 \
|
| 377 |
+
--hash=sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9 \
|
| 378 |
+
--hash=sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042
|
| 379 |
+
# via jsonschema
|
| 380 |
+
jedi==0.19.2 \
|
| 381 |
+
--hash=sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0 \
|
| 382 |
+
--hash=sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9
|
| 383 |
+
# via ipython
|
| 384 |
+
jinja2==3.1.6 \
|
| 385 |
+
--hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \
|
| 386 |
+
--hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67
|
| 387 |
+
# via
|
| 388 |
+
# gradio
|
| 389 |
+
# jupyter-server
|
| 390 |
+
# jupyterlab
|
| 391 |
+
# jupyterlab-server
|
| 392 |
+
# nbconvert
|
| 393 |
+
# torch
|
| 394 |
+
jiter==0.9.0 \
|
| 395 |
+
--hash=sha256:2221176dfec87f3470b21e6abca056e6b04ce9bff72315cb0b243ca9e835a4b5 \
|
| 396 |
+
--hash=sha256:3c7adb66f899ffa25e3c92bfcb593391ee1947dbdd6a9a970e0d7e713237d572 \
|
| 397 |
+
--hash=sha256:42f8a68a69f047b310319ef8e2f52fdb2e7976fb3313ef27df495cf77bcad965 \
|
| 398 |
+
--hash=sha256:51c4e1a4f8ea84d98b7b98912aa4290ac3d1eabfde8e3c34541fae30e9d1f08b \
|
| 399 |
+
--hash=sha256:5f4c677c424dc76684fea3e7285a7a2a7493424bea89ac441045e6a1fb1d7b3b \
|
| 400 |
+
--hash=sha256:6c4d99c71508912a7e556d631768dcdef43648a93660670986916b297f1c54af \
|
| 401 |
+
--hash=sha256:8f60fb8ce7df529812bf6c625635a19d27f30806885139e367af93f6e734ef58 \
|
| 402 |
+
--hash=sha256:923b54afdd697dfd00d368b7ccad008cccfeb1efb4e621f32860c75e9f25edbd \
|
| 403 |
+
--hash=sha256:a25519efb78a42254d59326ee417d6f5161b06f5da827d94cf521fed961b1ff2 \
|
| 404 |
+
--hash=sha256:aadba0964deb424daa24492abc3d229c60c4a31bfee205aedbf1acc7639d7893 \
|
| 405 |
+
--hash=sha256:c98d27330fdfb77913c1097a7aab07f38ff2259048949f499c9901700789ac15 \
|
| 406 |
+
--hash=sha256:dd5ab5ddc11418dce28343123644a100f487eaccf1de27a459ab36d6cca31043 \
|
| 407 |
+
--hash=sha256:eda3f8cc74df66892b1d06b5d41a71670c22d95a1ca2cbab73654745ce9d0419
|
| 408 |
+
# via openai
|
| 409 |
+
joblib==1.5.0 \
|
| 410 |
+
--hash=sha256:206144b320246485b712fc8cc51f017de58225fa8b414a1fe1764a7231aca491 \
|
| 411 |
+
--hash=sha256:d8757f955389a3dd7a23152e43bc297c2e0c2d3060056dad0feefc88a06939b5
|
| 412 |
+
# via nltk
|
| 413 |
+
json5==0.12.0 \
|
| 414 |
+
--hash=sha256:0b4b6ff56801a1c7dc817b0241bca4ce474a0e6a163bfef3fc594d3fd263ff3a \
|
| 415 |
+
--hash=sha256:6d37aa6c08b0609f16e1ec5ff94697e2cbbfbad5ac112afa05794da9ab7810db
|
| 416 |
+
# via jupyterlab-server
|
| 417 |
+
jsonpointer==3.0.0 \
|
| 418 |
+
--hash=sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942 \
|
| 419 |
+
--hash=sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef
|
| 420 |
+
# via jsonschema
|
| 421 |
+
jsonschema==4.23.0 \
|
| 422 |
+
--hash=sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4 \
|
| 423 |
+
--hash=sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566
|
| 424 |
+
# via
|
| 425 |
+
# jupyter-events
|
| 426 |
+
# jupyterlab-server
|
| 427 |
+
# nbformat
|
| 428 |
+
jsonschema-specifications==2025.4.1 \
|
| 429 |
+
--hash=sha256:4653bffbd6584f7de83a67e0d620ef16900b390ddc7939d56684d6c81e33f1af \
|
| 430 |
+
--hash=sha256:630159c9f4dbea161a6a2205c3011cc4f18ff381b189fff48bb39b9bf26ae608
|
| 431 |
+
# via jsonschema
|
| 432 |
+
jupyter-client==8.6.3 \
|
| 433 |
+
--hash=sha256:35b3a0947c4a6e9d589eb97d7d4cd5e90f910ee73101611f01283732bd6d9419 \
|
| 434 |
+
--hash=sha256:e8a19cc986cc45905ac3362915f410f3af85424b4c0905e94fa5f2cb08e8f23f
|
| 435 |
+
# via
|
| 436 |
+
# ipykernel
|
| 437 |
+
# jupyter-server
|
| 438 |
+
# nbclient
|
| 439 |
+
jupyter-core==5.7.2 \
|
| 440 |
+
--hash=sha256:4f7315d2f6b4bcf2e3e7cb6e46772eba760ae459cd1f59d29eb57b0a01bd7409 \
|
| 441 |
+
--hash=sha256:aa5f8d32bbf6b431ac830496da7392035d6f61b4f54872f15c4bd2a9c3f536d9
|
| 442 |
+
# via
|
| 443 |
+
# ipykernel
|
| 444 |
+
# jupyter-client
|
| 445 |
+
# jupyter-server
|
| 446 |
+
# jupyterlab
|
| 447 |
+
# nbclient
|
| 448 |
+
# nbconvert
|
| 449 |
+
# nbformat
|
| 450 |
+
jupyter-events==0.12.0 \
|
| 451 |
+
--hash=sha256:6464b2fa5ad10451c3d35fabc75eab39556ae1e2853ad0c0cc31b656731a97fb \
|
| 452 |
+
--hash=sha256:fc3fce98865f6784c9cd0a56a20644fc6098f21c8c33834a8d9fe383c17e554b
|
| 453 |
+
# via jupyter-server
|
| 454 |
+
jupyter-lsp==2.2.5 \
|
| 455 |
+
--hash=sha256:45fbddbd505f3fbfb0b6cb2f1bc5e15e83ab7c79cd6e89416b248cb3c00c11da \
|
| 456 |
+
--hash=sha256:793147a05ad446f809fd53ef1cd19a9f5256fd0a2d6b7ce943a982cb4f545001
|
| 457 |
+
# via jupyterlab
|
| 458 |
+
jupyter-server==2.15.0 \
|
| 459 |
+
--hash=sha256:872d989becf83517012ee669f09604aa4a28097c0bd90b2f424310156c2cdae3 \
|
| 460 |
+
--hash=sha256:9d446b8697b4f7337a1b7cdcac40778babdd93ba614b6d68ab1c0c918f1c4084
|
| 461 |
+
# via
|
| 462 |
+
# jupyter-lsp
|
| 463 |
+
# jupyterlab
|
| 464 |
+
# jupyterlab-server
|
| 465 |
+
# notebook
|
| 466 |
+
# notebook-shim
|
| 467 |
+
jupyter-server-terminals==0.5.3 \
|
| 468 |
+
--hash=sha256:41ee0d7dc0ebf2809c668e0fc726dfaf258fcd3e769568996ca731b6194ae9aa \
|
| 469 |
+
--hash=sha256:5ae0295167220e9ace0edcfdb212afd2b01ee8d179fe6f23c899590e9b8a5269
|
| 470 |
+
# via jupyter-server
|
| 471 |
+
jupyterlab==4.4.2 \
|
| 472 |
+
--hash=sha256:857111a50bed68542bf55dca784522fe728f9f88b4fe69e8c585db5c50900419 \
|
| 473 |
+
--hash=sha256:afa9caf28c0cb966488be18e5e8daba9f018a1c4273a406b7d5006344cbc6d16
|
| 474 |
+
# via notebook
|
| 475 |
+
jupyterlab-pygments==0.3.0 \
|
| 476 |
+
--hash=sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d \
|
| 477 |
+
--hash=sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780
|
| 478 |
+
# via nbconvert
|
| 479 |
+
jupyterlab-server==2.27.3 \
|
| 480 |
+
--hash=sha256:e697488f66c3db49df675158a77b3b017520d772c6e1548c7d9bcc5df7944ee4 \
|
| 481 |
+
--hash=sha256:eb36caca59e74471988f0ae25c77945610b887f777255aa21f8065def9e51ed4
|
| 482 |
+
# via
|
| 483 |
+
# jupyterlab
|
| 484 |
+
# notebook
|
| 485 |
+
kiwisolver==1.4.8 \
|
| 486 |
+
--hash=sha256:11e1022b524bd48ae56c9b4f9296bce77e15a2e42a502cceba602f804b32bb79 \
|
| 487 |
+
--hash=sha256:16523b40aab60426ffdebe33ac374457cf62863e330a90a0383639ce14bf44b2 \
|
| 488 |
+
--hash=sha256:23454ff084b07ac54ca8be535f4174170c1094a4cff78fbae4f73a4bcc0d4dab \
|
| 489 |
+
--hash=sha256:23d5f023bdc8c7e54eb65f03ca5d5bb25b601eac4d7f1a042888a1f45237987e \
|
| 490 |
+
--hash=sha256:3a96c0e790ee875d65e340ab383700e2b4891677b7fcd30a699146f9384a2bb0 \
|
| 491 |
+
--hash=sha256:3b9b4d2892fefc886f30301cdd80debd8bb01ecdf165a449eb6e78f79f0fabd6 \
|
| 492 |
+
--hash=sha256:768cade2c2df13db52475bd28d3a3fac8c9eff04b0e9e2fda0f3760f20b3f7fc \
|
| 493 |
+
--hash=sha256:856b269c4d28a5c0d5e6c1955ec36ebfd1651ac00e1ce0afa3e28da95293b561 \
|
| 494 |
+
--hash=sha256:87b287251ad6488e95b4f0b4a79a6d04d3ea35fde6340eb38fbd1ca9cd35bbbc \
|
| 495 |
+
--hash=sha256:a4d3601908c560bdf880f07d94f31d734afd1bb71e96585cace0e38ef44c6d84 \
|
| 496 |
+
--hash=sha256:b21dbe165081142b1232a240fc6383fd32cdd877ca6cc89eab93e5f5883e1c25 \
|
| 497 |
+
--hash=sha256:c2b9a96e0f326205af81a15718a9073328df1173a2619a68553decb7097fd5d7 \
|
| 498 |
+
--hash=sha256:c5020c83e8553f770cb3b5fc13faac40f17e0b205bd237aebd21d53d733adb03 \
|
| 499 |
+
--hash=sha256:d47cfb2650f0e103d4bf68b0b5804c68da97272c84bb12850d877a95c056bd67 \
|
| 500 |
+
--hash=sha256:dace81d28c787956bfbfbbfd72fdcef014f37d9b48830829e488fdb32b49d954 \
|
| 501 |
+
--hash=sha256:ed33ca2002a779a2e20eeb06aea7721b6e47f2d4b8a8ece979d8ba9e2a167e34
|
| 502 |
+
# via matplotlib
|
| 503 |
+
lightning-utilities==0.14.3 \
|
| 504 |
+
--hash=sha256:37e2f83f273890052955a44054382c211a303012ee577619efbaa5df9e65e9f5 \
|
| 505 |
+
--hash=sha256:4ab9066aa36cd7b93a05713808901909e96cc3f187ea6fd3052b2fd91313b468
|
| 506 |
+
# via
|
| 507 |
+
# pytorch-lightning
|
| 508 |
+
# torchmetrics
|
| 509 |
+
markdown-it-py==3.0.0 ; sys_platform != 'emscripten' \
|
| 510 |
+
--hash=sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1 \
|
| 511 |
+
--hash=sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb
|
| 512 |
+
# via rich
|
| 513 |
+
markupsafe==3.0.2 \
|
| 514 |
+
--hash=sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4 \
|
| 515 |
+
--hash=sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca \
|
| 516 |
+
--hash=sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832 \
|
| 517 |
+
--hash=sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e \
|
| 518 |
+
--hash=sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d \
|
| 519 |
+
--hash=sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b \
|
| 520 |
+
--hash=sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d \
|
| 521 |
+
--hash=sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93 \
|
| 522 |
+
--hash=sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84 \
|
| 523 |
+
--hash=sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798 \
|
| 524 |
+
--hash=sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0
|
| 525 |
+
# via
|
| 526 |
+
# gradio
|
| 527 |
+
# jinja2
|
| 528 |
+
# nbconvert
|
| 529 |
+
matplotlib==3.10.1 \
|
| 530 |
+
--hash=sha256:057206ff2d6ab82ff3e94ebd94463d084760ca682ed5f150817b859372ec4401 \
|
| 531 |
+
--hash=sha256:0f69dc9713e4ad2fb21a1c30e37bd445d496524257dfda40ff4a8efb3604ab5c \
|
| 532 |
+
--hash=sha256:11b65088c6f3dae784bc72e8d039a2580186285f87448babb9ddb2ad0082993a \
|
| 533 |
+
--hash=sha256:4c59af3e8aca75d7744b68e8e78a669e91ccbcf1ac35d0102a7b1b46883f1dd7 \
|
| 534 |
+
--hash=sha256:56c5d9fcd9879aa8040f196a235e2dcbdf7dd03ab5b07c0696f80bc6cf04bedd \
|
| 535 |
+
--hash=sha256:a144867dd6bf8ba8cb5fc81a158b645037e11b3e5cf8a50bd5f9917cb863adfe \
|
| 536 |
+
--hash=sha256:e8d2d0e3881b129268585bf4765ad3ee73a4591d77b9a18c214ac7e3a79fb2ba
|
| 537 |
+
# via menu-text-detection
|
| 538 |
+
matplotlib-inline==0.1.7 \
|
| 539 |
+
--hash=sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90 \
|
| 540 |
+
--hash=sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca
|
| 541 |
+
# via
|
| 542 |
+
# ipykernel
|
| 543 |
+
# ipython
|
| 544 |
+
mdurl==0.1.2 ; sys_platform != 'emscripten' \
|
| 545 |
+
--hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \
|
| 546 |
+
--hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba
|
| 547 |
+
# via markdown-it-py
|
| 548 |
+
mistune==3.1.3 \
|
| 549 |
+
--hash=sha256:1a32314113cff28aa6432e99e522677c8587fd83e3d51c29b82a52409c842bd9 \
|
| 550 |
+
--hash=sha256:a7035c21782b2becb6be62f8f25d3df81ccb4d6fa477a6525b15af06539f02a0
|
| 551 |
+
# via nbconvert
|
| 552 |
+
mpmath==1.3.0 \
|
| 553 |
+
--hash=sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f \
|
| 554 |
+
--hash=sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c
|
| 555 |
+
# via sympy
|
| 556 |
+
multidict==6.4.3 \
|
| 557 |
+
--hash=sha256:1b2019317726f41e81154df636a897de1bfe9228c3724a433894e44cd2512378 \
|
| 558 |
+
--hash=sha256:1f4e0334d7a555c63f5c8952c57ab6f1c7b4f8c7f3442df689fc9f03df315c08 \
|
| 559 |
+
--hash=sha256:255dac25134d2b141c944b59a0d2f7211ca12a6d4779f7586a98b4b03ea80508 \
|
| 560 |
+
--hash=sha256:2e329114f82ad4b9dd291bef614ea8971ec119ecd0f54795109976de75c9a852 \
|
| 561 |
+
--hash=sha256:30c433a33be000dd968f5750722eaa0991037be0be4a9d453eba121774985bc8 \
|
| 562 |
+
--hash=sha256:3ada0b058c9f213c5f95ba301f922d402ac234f1111a7d8fd70f1b99f3c281ec \
|
| 563 |
+
--hash=sha256:43173924fa93c7486402217fab99b60baf78d33806af299c56133a3755f69589 \
|
| 564 |
+
--hash=sha256:4eb33b0bdc50acd538f45041f5f19945a1f32b909b76d7b117c0c25d8063df56 \
|
| 565 |
+
--hash=sha256:59fe01ee8e2a1e8ceb3f6dbb216b09c8d9f4ef1c22c4fc825d045a147fa2ebc9 \
|
| 566 |
+
--hash=sha256:740915eb776617b57142ce0bb13b7596933496e2f798d3d15a20614adf30d229 \
|
| 567 |
+
--hash=sha256:75482f43465edefd8a5d72724887ccdcd0c83778ded8f0cb1e0594bf71736cc0 \
|
| 568 |
+
--hash=sha256:8aac2eeff69b71f229a405c0a4b61b54bade8e10163bc7b44fcd257949620618 \
|
| 569 |
+
--hash=sha256:ab583ac203af1d09034be41458feeab7863c0635c650a16f15771e1386abf2d7 \
|
| 570 |
+
--hash=sha256:ce5b3082e86aee80b3925ab4928198450d8e5b6466e11501fe03ad2191c6d777 \
|
| 571 |
+
--hash=sha256:d4e8535bd4d741039b5aad4285ecd9b902ef9e224711f0b6afda6e38d7ac02c7 \
|
| 572 |
+
--hash=sha256:e413152e3212c4d39f82cf83c6f91be44bec9ddea950ce17af87fbf4e32ca6b2 \
|
| 573 |
+
--hash=sha256:f2882bf27037eb687e49591690e5d491e677272964f9ec7bc2abbe09108bdfb8 \
|
| 574 |
+
--hash=sha256:f6f19170197cc29baccd33ccc5b5d6a331058796485857cf34f7635aa25fb0cd \
|
| 575 |
+
--hash=sha256:fbf226ac85f7d6b6b9ba77db4ec0704fde88463dc17717aec78ec3c8546c70ad
|
| 576 |
+
# via
|
| 577 |
+
# aiohttp
|
| 578 |
+
# yarl
|
| 579 |
+
multiprocess==0.70.16 \
|
| 580 |
+
--hash=sha256:161af703d4652a0e1410be6abccecde4a7ddffd19341be0a7011b94aeb171ac1 \
|
| 581 |
+
--hash=sha256:a0bafd3ae1b732eac64be2e72038231c1ba97724b60b09400d68f229fcc2fbf3 \
|
| 582 |
+
--hash=sha256:a71d82033454891091a226dfc319d0cfa8019a4e888ef9ca910372a446de4435 \
|
| 583 |
+
--hash=sha256:af4cabb0dac72abfb1e794fa7855c325fd2b55a10a44628a3c1ad3311c04127a \
|
| 584 |
+
--hash=sha256:c4a9944c67bd49f823687463660a2d6daae94c289adff97e0f9d696ba6371d02
|
| 585 |
+
# via datasets
|
| 586 |
+
munch==4.0.0 \
|
| 587 |
+
--hash=sha256:542cb151461263216a4e37c3fd9afc425feeaf38aaa3025cd2a981fadb422235 \
|
| 588 |
+
--hash=sha256:71033c45db9fb677a0b7eb517a4ce70ae09258490e419b0e7f00d1e386ecb1b4
|
| 589 |
+
# via sconf
|
| 590 |
+
nbclient==0.10.2 \
|
| 591 |
+
--hash=sha256:4ffee11e788b4a27fabeb7955547e4318a5298f34342a4bfd01f2e1faaeadc3d \
|
| 592 |
+
--hash=sha256:90b7fc6b810630db87a6d0c2250b1f0ab4cf4d3c27a299b0cde78a4ed3fd9193
|
| 593 |
+
# via nbconvert
|
| 594 |
+
nbconvert==7.16.6 \
|
| 595 |
+
--hash=sha256:1375a7b67e0c2883678c48e506dc320febb57685e5ee67faa51b18a90f3a712b \
|
| 596 |
+
--hash=sha256:576a7e37c6480da7b8465eefa66c17844243816ce1ccc372633c6b71c3c0f582
|
| 597 |
+
# via jupyter-server
|
| 598 |
+
nbformat==5.10.4 \
|
| 599 |
+
--hash=sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a \
|
| 600 |
+
--hash=sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b
|
| 601 |
+
# via
|
| 602 |
+
# jupyter-server
|
| 603 |
+
# nbclient
|
| 604 |
+
# nbconvert
|
| 605 |
+
nest-asyncio==1.6.0 \
|
| 606 |
+
--hash=sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe \
|
| 607 |
+
--hash=sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c
|
| 608 |
+
# via ipykernel
|
| 609 |
+
networkx==3.4.2 \
|
| 610 |
+
--hash=sha256:307c3669428c5362aab27c8a1260aa8f47c4e91d3891f48be0141738d8d053e1 \
|
| 611 |
+
--hash=sha256:df5d4365b724cf81b8c6a7312509d0c22386097011ad1abe274afd5e9d3bbc5f
|
| 612 |
+
# via torch
|
| 613 |
+
nltk==3.9.1 \
|
| 614 |
+
--hash=sha256:4fa26829c5b00715afe3061398a8989dc643b92ce7dd93fb4585a70930d168a1 \
|
| 615 |
+
--hash=sha256:87d127bd3de4bd89a4f81265e5fa59cb1b199b27440175370f7417d2bc7ae868
|
| 616 |
+
# via
|
| 617 |
+
# donut-python
|
| 618 |
+
# menu-text-detection
|
| 619 |
+
notebook==7.4.2 \
|
| 620 |
+
--hash=sha256:9ccef602721aaa5530852e3064710b8ae5415c4e2ce26f8896d0433222755259 \
|
| 621 |
+
--hash=sha256:e739defd28c3f615a6bfb0a2564bd75018a9cc6613aa00bbd9c15e68eed2de1b
|
| 622 |
+
# via menu-text-detection
|
| 623 |
+
notebook-shim==0.2.4 \
|
| 624 |
+
--hash=sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef \
|
| 625 |
+
--hash=sha256:b4b2cfa1b65d98307ca24361f5b30fe785b53c3fd07b7a47e89acb5e6ac638cb
|
| 626 |
+
# via
|
| 627 |
+
# jupyterlab
|
| 628 |
+
# notebook
|
| 629 |
+
numpy==2.2.5 \
|
| 630 |
+
--hash=sha256:262d23f383170f99cd9191a7c85b9a50970fe9069b2f8ab5d786eca8a675d60b \
|
| 631 |
+
--hash=sha256:369e0d4647c17c9363244f3468f2227d557a74b6781cb62ce57cf3ef5cc7c610 \
|
| 632 |
+
--hash=sha256:37e32e985f03c06206582a7323ef926b4e78bdaa6915095ef08070471865b906 \
|
| 633 |
+
--hash=sha256:498815b96f67dc347e03b719ef49c772589fb74b8ee9ea2c37feae915ad6ebda \
|
| 634 |
+
--hash=sha256:6411f744f7f20081b1b4e7112e0f4c9c5b08f94b9f086e6f0adf3645f85d3a4d \
|
| 635 |
+
--hash=sha256:9de6832228f617c9ef45d948ec1cd8949c482238d68b2477e6f642c33a7b0a54 \
|
| 636 |
+
--hash=sha256:a9c0d994680cd991b1cb772e8b297340085466a6fe964bc9d4e80f5e2f43c291 \
|
| 637 |
+
--hash=sha256:aa70fdbdc3b169d69e8c59e65c07a1c9351ceb438e627f0fdcd471015cd956be \
|
| 638 |
+
--hash=sha256:b13f04968b46ad705f7c8a80122a42ae8f620536ea38cf4bdd374302926424dd \
|
| 639 |
+
--hash=sha256:c42365005c7a6c42436a54d28c43fe0e01ca11eb2ac3cefe796c25a5f98e5e9b \
|
| 640 |
+
--hash=sha256:f5045039100ed58fa817a6227a356240ea1b9a1bc141018864c306c1a16d4175
|
| 641 |
+
# via
|
| 642 |
+
# contourpy
|
| 643 |
+
# datasets
|
| 644 |
+
# gradio
|
| 645 |
+
# matplotlib
|
| 646 |
+
# pandas
|
| 647 |
+
# tensorboardx
|
| 648 |
+
# torchmetrics
|
| 649 |
+
# torchvision
|
| 650 |
+
# transformers
|
| 651 |
+
nvidia-cublas-cu12==12.1.3.1 ; platform_machine == 'x86_64' and sys_platform == 'linux' \
|
| 652 |
+
--hash=sha256:ee53ccca76a6fc08fb9701aa95b6ceb242cdaab118c3bb152af4e579af792728
|
| 653 |
+
# via
|
| 654 |
+
# nvidia-cudnn-cu12
|
| 655 |
+
# nvidia-cusolver-cu12
|
| 656 |
+
# torch
|
| 657 |
+
nvidia-cuda-cupti-cu12==12.1.105 ; platform_machine == 'x86_64' and sys_platform == 'linux' \
|
| 658 |
+
--hash=sha256:e54fde3983165c624cb79254ae9818a456eb6e87a7fd4d56a2352c24ee542d7e
|
| 659 |
+
# via torch
|
| 660 |
+
nvidia-cuda-nvrtc-cu12==12.1.105 ; platform_machine == 'x86_64' and sys_platform == 'linux' \
|
| 661 |
+
--hash=sha256:339b385f50c309763ca65456ec75e17bbefcbbf2893f462cb8b90584cd27a1c2
|
| 662 |
+
# via torch
|
| 663 |
+
nvidia-cuda-runtime-cu12==12.1.105 ; platform_machine == 'x86_64' and sys_platform == 'linux' \
|
| 664 |
+
--hash=sha256:6e258468ddf5796e25f1dc591a31029fa317d97a0a94ed93468fc86301d61e40
|
| 665 |
+
# via torch
|
| 666 |
+
nvidia-cudnn-cu12==9.1.0.70 ; platform_machine == 'x86_64' and sys_platform == 'linux' \
|
| 667 |
+
--hash=sha256:165764f44ef8c61fcdfdfdbe769d687e06374059fbb388b6c89ecb0e28793a6f
|
| 668 |
+
# via torch
|
| 669 |
+
nvidia-cufft-cu12==11.0.2.54 ; platform_machine == 'x86_64' and sys_platform == 'linux' \
|
| 670 |
+
--hash=sha256:794e3948a1aa71fd817c3775866943936774d1c14e7628c74f6f7417224cdf56
|
| 671 |
+
# via torch
|
| 672 |
+
nvidia-curand-cu12==10.3.2.106 ; platform_machine == 'x86_64' and sys_platform == 'linux' \
|
| 673 |
+
--hash=sha256:9d264c5036dde4e64f1de8c50ae753237c12e0b1348738169cd0f8a536c0e1e0
|
| 674 |
+
# via torch
|
| 675 |
+
nvidia-cusolver-cu12==11.4.5.107 ; platform_machine == 'x86_64' and sys_platform == 'linux' \
|
| 676 |
+
--hash=sha256:8a7ec542f0412294b15072fa7dab71d31334014a69f953004ea7a118206fe0dd
|
| 677 |
+
# via torch
|
| 678 |
+
nvidia-cusparse-cu12==12.1.0.106 ; platform_machine == 'x86_64' and sys_platform == 'linux' \
|
| 679 |
+
--hash=sha256:f3b50f42cf363f86ab21f720998517a659a48131e8d538dc02f8768237bd884c
|
| 680 |
+
# via
|
| 681 |
+
# nvidia-cusolver-cu12
|
| 682 |
+
# torch
|
| 683 |
+
nvidia-nccl-cu12==2.20.5 ; platform_machine == 'x86_64' and sys_platform == 'linux' \
|
| 684 |
+
--hash=sha256:057f6bf9685f75215d0c53bf3ac4a10b3e6578351de307abad9e18a99182af56
|
| 685 |
+
# via torch
|
| 686 |
+
nvidia-nvjitlink-cu12==12.6.85 ; platform_machine == 'x86_64' and sys_platform == 'linux' \
|
| 687 |
+
--hash=sha256:eedc36df9e88b682efe4309aa16b5b4e78c2407eac59e8c10a6a47535164369a
|
| 688 |
+
# via
|
| 689 |
+
# nvidia-cusolver-cu12
|
| 690 |
+
# nvidia-cusparse-cu12
|
| 691 |
+
nvidia-nvtx-cu12==12.1.105 ; platform_machine == 'x86_64' and sys_platform == 'linux' \
|
| 692 |
+
--hash=sha256:dc21cf308ca5691e7c04d962e213f8a4aa9bbfa23d95412f452254c2caeb09e5
|
| 693 |
+
# via torch
|
| 694 |
+
openai==1.77.0 \
|
| 695 |
+
--hash=sha256:07706e91eb71631234996989a8ea991d5ee56f0744ef694c961e0824d4f39218 \
|
| 696 |
+
--hash=sha256:897969f927f0068b8091b4b041d1f8175bcf124f7ea31bab418bf720971223bc
|
| 697 |
+
# via menu-text-detection
|
| 698 |
+
orjson==3.10.18 \
|
| 699 |
+
--hash=sha256:187aefa562300a9d382b4b4eb9694806e5848b0cedf52037bb5c228c61bb66d4 \
|
| 700 |
+
--hash=sha256:3f9478ade5313d724e0495d167083c6f3be0dd2f1c9c8a38db9a9e912cdaf947 \
|
| 701 |
+
--hash=sha256:50ce016233ac4bfd843ac5471e232b865271d7d9d44cf9d33773bcd883ce442b \
|
| 702 |
+
--hash=sha256:51f8c63be6e070ec894c629186b1c0fe798662b8687f3d9fdfa5e401c6bd7679 \
|
| 703 |
+
--hash=sha256:5e3c9cc2ba324187cd06287ca24f65528f16dfc80add48dc99fa6c836bb3137e \
|
| 704 |
+
--hash=sha256:5ef7c164d9174362f85238d0cd4afdeeb89d9e523e4651add6a5d458d6f7d42d \
|
| 705 |
+
--hash=sha256:7b672502323b6cd133c4af6b79e3bea36bad2d16bca6c1f645903fce83909a7a \
|
| 706 |
+
--hash=sha256:9da552683bc9da222379c7a01779bddd0ad39dd699dd6300abaf43eadee38334 \
|
| 707 |
+
--hash=sha256:a6c7c391beaedd3fa63206e5c2b7b554196f14debf1ec9deb54b5d279b1b46f5 \
|
| 708 |
+
--hash=sha256:afd14c5d99cdc7bf93f22b12ec3b294931518aa019e2a147e8aa2f31fd3240f7 \
|
| 709 |
+
--hash=sha256:b3ceff74a8f7ffde0b2785ca749fc4e80e4315c0fd887561144059fb1c138aa7 \
|
| 710 |
+
--hash=sha256:c28082933c71ff4bc6ccc82a454a2bffcef6e1d7379756ca567c772e4fb3278a \
|
| 711 |
+
--hash=sha256:e0a183ac3b8e40471e8d843105da6fbe7c070faab023be3b08188ee3f85719b8 \
|
| 712 |
+
--hash=sha256:e450885f7b47a0231979d9c49b567ed1c4e9f69240804621be87c40bc9d3cf17 \
|
| 713 |
+
--hash=sha256:e8da3947d92123eda795b68228cafe2724815621fe35e8e320a9e9593a4bcd53 \
|
| 714 |
+
--hash=sha256:fdba703c722bd868c04702cac4cb8c6b8ff137af2623bc0ddb3b3e6a2c8996c1
|
| 715 |
+
# via gradio
|
| 716 |
+
overrides==7.7.0 \
|
| 717 |
+
--hash=sha256:55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a \
|
| 718 |
+
--hash=sha256:c7ed9d062f78b8e4c1a7b70bd8796b35ead4d9f510227ef9c5dc7626c60d7e49
|
| 719 |
+
# via jupyter-server
|
| 720 |
+
packaging==25.0 \
|
| 721 |
+
--hash=sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484 \
|
| 722 |
+
--hash=sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f
|
| 723 |
+
# via
|
| 724 |
+
# datasets
|
| 725 |
+
# gradio
|
| 726 |
+
# gradio-client
|
| 727 |
+
# huggingface-hub
|
| 728 |
+
# ipykernel
|
| 729 |
+
# jupyter-events
|
| 730 |
+
# jupyter-server
|
| 731 |
+
# jupyterlab
|
| 732 |
+
# jupyterlab-server
|
| 733 |
+
# lightning-utilities
|
| 734 |
+
# matplotlib
|
| 735 |
+
# nbconvert
|
| 736 |
+
# pytorch-lightning
|
| 737 |
+
# tensorboardx
|
| 738 |
+
# torchmetrics
|
| 739 |
+
# transformers
|
| 740 |
+
pandas==2.2.3 \
|
| 741 |
+
--hash=sha256:29401dbfa9ad77319367d36940cd8a0b3a11aba16063e39632d98b0e931ddf32 \
|
| 742 |
+
--hash=sha256:3fc6873a41186404dad67245896a6e440baacc92f5b716ccd1bc9ed2995ab2c5 \
|
| 743 |
+
--hash=sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667 \
|
| 744 |
+
--hash=sha256:63cc132e40a2e084cf01adf0775b15ac515ba905d7dcca47e9a251819c575ef3 \
|
| 745 |
+
--hash=sha256:66108071e1b935240e74525006034333f98bcdb87ea116de573a6a0dccb6c039 \
|
| 746 |
+
--hash=sha256:7c2875855b0ff77b2a64a0365e24455d9990730d6431b9e0ee18ad8acee13dbd \
|
| 747 |
+
--hash=sha256:c124333816c3a9b03fbeef3a9f230ba9a737e9e5bb4060aa2107a86cc0a497fc \
|
| 748 |
+
--hash=sha256:cd8d0c3be0515c12fed0bdbae072551c8b54b7192c7b1fda0ba56059a0179698
|
| 749 |
+
# via
|
| 750 |
+
# datasets
|
| 751 |
+
# gradio
|
| 752 |
+
pandocfilters==1.5.1 \
|
| 753 |
+
--hash=sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e \
|
| 754 |
+
--hash=sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc
|
| 755 |
+
# via nbconvert
|
| 756 |
+
parso==0.8.4 \
|
| 757 |
+
--hash=sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18 \
|
| 758 |
+
--hash=sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d
|
| 759 |
+
# via jedi
|
| 760 |
+
pexpect==4.9.0 ; sys_platform != 'emscripten' and sys_platform != 'win32' \
|
| 761 |
+
--hash=sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523 \
|
| 762 |
+
--hash=sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f
|
| 763 |
+
# via ipython
|
| 764 |
+
pillow==11.2.1 \
|
| 765 |
+
--hash=sha256:036e53f4170e270ddb8797d4c590e6dd14d28e15c7da375c18978045f7e6c37b \
|
| 766 |
+
--hash=sha256:0f5c7eda47bf8e3c8a283762cab94e496ba977a420868cb819159980b6709193 \
|
| 767 |
+
--hash=sha256:14f73f7c291279bd65fda51ee87affd7c1e097709f7fdd0188957a16c264601f \
|
| 768 |
+
--hash=sha256:208653868d5c9ecc2b327f9b9ef34e0e42a4cdd172c2988fd81d62d2bc9bc044 \
|
| 769 |
+
--hash=sha256:35ca289f712ccfc699508c4658a1d14652e8033e9b69839edf83cbdd0ba39e70 \
|
| 770 |
+
--hash=sha256:4d375eb838755f2528ac8cbc926c3e31cc49ca4ad0cf79cff48b20e30634a4a7 \
|
| 771 |
+
--hash=sha256:738db0e0941ca0376804d4de6a782c005245264edaa253ffce24e5a15cbdc7bd \
|
| 772 |
+
--hash=sha256:80f1df8dbe9572b4b7abdfa17eb5d78dd620b1d55d9e25f834efdbee872d3aed \
|
| 773 |
+
--hash=sha256:8f4f3724c068be008c08257207210c138d5f3731af6c155a81c2b09a9eb3a788 \
|
| 774 |
+
--hash=sha256:9db98ab6565c69082ec9b0d4e40dd9f6181dab0dd236d26f7a50b8b9bfbd5076 \
|
| 775 |
+
--hash=sha256:a0a6709b47019dff32e678bc12c63008311b82b9327613f534e496dacaefb71e \
|
| 776 |
+
--hash=sha256:a64dd61998416367b7ef979b73d3a85853ba9bec4c2925f74e588879a58716b6 \
|
| 777 |
+
--hash=sha256:b93a07e76d13bff9444f1a029e0af2964e654bfc2e2c2d46bfd080df5ad5f3d8 \
|
| 778 |
+
--hash=sha256:cc5d875d56e49f112b6def6813c4e3d3036d269c008bf8aef72cd08d20ca6df6 \
|
| 779 |
+
--hash=sha256:d4e5c5edee874dce4f653dbe59db7c73a600119fbea8d31f53423586ee2aafd7 \
|
| 780 |
+
--hash=sha256:e0409af9f829f87a2dfb7e259f78f317a5351f2045158be321fd135973fff7bf \
|
| 781 |
+
--hash=sha256:e6def7eed9e7fa90fde255afaf08060dc4b343bbe524a8f69bdd2a2f0018f600 \
|
| 782 |
+
--hash=sha256:ea926cfbc3957090becbcbbb65ad177161a2ff2ad578b5a6ec9bb1e1cd78753c \
|
| 783 |
+
--hash=sha256:f6b0c664ccb879109ee3ca702a9272d877f4fcd21e5eb63c26422fd6e415365e
|
| 784 |
+
# via
|
| 785 |
+
# datasets
|
| 786 |
+
# gradio
|
| 787 |
+
# matplotlib
|
| 788 |
+
# menu-text-detection
|
| 789 |
+
# pillow-heif
|
| 790 |
+
# torchvision
|
| 791 |
+
pillow-heif==0.22.0 \
|
| 792 |
+
--hash=sha256:550093ee350c8cd404dbba61f7449d4ecc018109ab65f6f89b96a6dc39dde177 \
|
| 793 |
+
--hash=sha256:61d473929340d3073722f6316b7fbbdb11132faa6bac0242328e8436cc55b39a \
|
| 794 |
+
--hash=sha256:646f2d05dd4a84ee1feb3a4aaa092269bf8f3f615c8f36d6e5d15b22a79d7cdd \
|
| 795 |
+
--hash=sha256:782eef461c836b3947fe253baaa5dcf6c75fba484c4905b4ac6b5b1a0bb04b7c \
|
| 796 |
+
--hash=sha256:8ccd70ff3c30e93f8153fa08b5533aee54a73574c980784f0b74f5fba7b61e19 \
|
| 797 |
+
--hash=sha256:b3035b4b4304e7624f9559989618ccad8ac614144befd30361ff51941b8c1b44 \
|
| 798 |
+
--hash=sha256:bf30bcaab9d2c0dbc43bb58d385faa9d3d8a693392beb50287aa6cda7a2f769e \
|
| 799 |
+
--hash=sha256:f73b7ce0d47e2dbd4f89de765a0c2d6e75f7dde95c5a5d87c4a6ad11bc9da4a3
|
| 800 |
+
# via menu-text-detection
|
| 801 |
+
platformdirs==4.3.8 \
|
| 802 |
+
--hash=sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc \
|
| 803 |
+
--hash=sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4
|
| 804 |
+
# via jupyter-core
|
| 805 |
+
prometheus-client==0.21.1 \
|
| 806 |
+
--hash=sha256:252505a722ac04b0456be05c05f75f45d760c2911ffc45f2a06bcaed9f3ae3fb \
|
| 807 |
+
--hash=sha256:594b45c410d6f4f8888940fe80b5cc2521b305a1fafe1c58609ef715a001f301
|
| 808 |
+
# via jupyter-server
|
| 809 |
+
prompt-toolkit==3.0.51 \
|
| 810 |
+
--hash=sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07 \
|
| 811 |
+
--hash=sha256:931a162e3b27fc90c86f1b48bb1fb2c528c2761475e57c9c06de13311c7b54ed
|
| 812 |
+
# via ipython
|
| 813 |
+
propcache==0.3.1 \
|
| 814 |
+
--hash=sha256:1eb34d90aac9bfbced9a58b266f8946cb5935869ff01b164573a7634d39fbcb5 \
|
| 815 |
+
--hash=sha256:3e19ea4ea0bf46179f8a3652ac1426e6dcbaf577ce4b4f65be581e237340420d \
|
| 816 |
+
--hash=sha256:40d980c33765359098837527e18eddefc9a24cea5b45e078a7f3bb5b032c6ecf \
|
| 817 |
+
--hash=sha256:43593c6772aa12abc3af7784bff4a41ffa921608dd38b77cf1dfd7f5c4e71371 \
|
| 818 |
+
--hash=sha256:58aa11f4ca8b60113d4b8e32d37e7e78bd8af4d1a5b5cb4979ed856a45e62005 \
|
| 819 |
+
--hash=sha256:5cdb0f3e1eb6dfc9965d19734d8f9c481b294b5274337a8cb5cb01b462dcb7e0 \
|
| 820 |
+
--hash=sha256:61014615c1274df8da5991a1e5da85a3ccb00c2d4701ac6f3383afd3ca47ab0a \
|
| 821 |
+
--hash=sha256:71ebe3fe42656a2328ab08933d420df5f3ab121772eef78f2dc63624157f0ed9 \
|
| 822 |
+
--hash=sha256:7f30241577d2fef2602113b70ef7231bf4c69a97e04693bde08ddab913ba0ce5 \
|
| 823 |
+
--hash=sha256:9532ea0b26a401264b1365146c440a6d78269ed41f83f23818d4b79497aeabe7 \
|
| 824 |
+
--hash=sha256:9a8ecf38de50a7f518c21568c80f985e776397b902f1ce0b01f799aba1608b40 \
|
| 825 |
+
--hash=sha256:a75801768bbe65499495660b777e018cbe90c7980f07f8aa57d6be79ea6f71da \
|
| 826 |
+
--hash=sha256:b0313e8b923b3814d1c4a524c93dfecea5f39fa95601f6a9b1ac96cd66f89ea0 \
|
| 827 |
+
--hash=sha256:b23c11c2c9e6d4e7300c92e022046ad09b91fd00e36e83c44483df4afa990073 \
|
| 828 |
+
--hash=sha256:bd39c92e4c8f6cbf5f08257d6360123af72af9f4da75a690bef50da77362d25f \
|
| 829 |
+
--hash=sha256:e861ad82892408487be144906a368ddbe2dc6297074ade2d892341b35c59844a \
|
| 830 |
+
--hash=sha256:f35c7070eeec2cdaac6fd3fe245226ed2a6292d3ee8c938e5bb645b434c5f256 \
|
| 831 |
+
--hash=sha256:f6f1324db48f001c2ca26a25fa25af60711e09b9aaf4b28488602776f4f9a744
|
| 832 |
+
# via
|
| 833 |
+
# aiohttp
|
| 834 |
+
# yarl
|
| 835 |
+
protobuf==6.30.2 \
|
| 836 |
+
--hash=sha256:0eb523c550a66a09a0c20f86dd554afbf4d32b02af34ae53d93268c1f73bc65b \
|
| 837 |
+
--hash=sha256:35c859ae076d8c56054c25b59e5e59638d86545ed6e2b6efac6be0b6ea3ba048 \
|
| 838 |
+
--hash=sha256:4f6c687ae8efae6cf6093389a596548214467778146b7245e886f35e1485315d \
|
| 839 |
+
--hash=sha256:50f32cc9fd9cb09c783ebc275611b4f19dfdfb68d1ee55d2f0c7fa040df96815 \
|
| 840 |
+
--hash=sha256:7653c99774f73fe6b9301b87da52af0e69783a2e371e8b599b3e9cb4da4b12b9 \
|
| 841 |
+
--hash=sha256:ae86b030e69a98e08c77beab574cbcb9fff6d031d57209f574a5aea1445f4b51 \
|
| 842 |
+
--hash=sha256:b12ef7df7b9329886e66404bef5e9ce6a26b54069d7f7436a0853ccdeb91c103
|
| 843 |
+
# via
|
| 844 |
+
# menu-text-detection
|
| 845 |
+
# tensorboardx
|
| 846 |
+
psutil==7.0.0 \
|
| 847 |
+
--hash=sha256:101d71dc322e3cffd7cea0650b09b3d08b8e7c4109dd6809fe452dfd00e58b25 \
|
| 848 |
+
--hash=sha256:1fcee592b4c6f146991ca55919ea3d1f8926497a713ed7faaf8225e174581e91 \
|
| 849 |
+
--hash=sha256:39db632f6bb862eeccf56660871433e111b6ea58f2caea825571951d4b6aa3da \
|
| 850 |
+
--hash=sha256:4b1388a4f6875d7e2aff5c4ca1cc16c545ed41dd8bb596cefea80111db353a34 \
|
| 851 |
+
--hash=sha256:4cf3d4eb1aa9b348dec30105c55cd9b7d4629285735a102beb4441e38db90553 \
|
| 852 |
+
--hash=sha256:7be9c3eba38beccb6495ea33afd982a44074b78f28c434a1f51cc07fd315c456 \
|
| 853 |
+
--hash=sha256:a5f098451abc2828f7dc6b58d44b532b22f2088f4999a937557b603ce72b1993 \
|
| 854 |
+
--hash=sha256:ba3fcef7523064a6c9da440fc4d6bd07da93ac726b5733c29027d7dc95b39d99
|
| 855 |
+
# via ipykernel
|
| 856 |
+
ptyprocess==0.7.0 ; os_name != 'nt' or (sys_platform != 'emscripten' and sys_platform != 'win32') \
|
| 857 |
+
--hash=sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35 \
|
| 858 |
+
--hash=sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220
|
| 859 |
+
# via
|
| 860 |
+
# pexpect
|
| 861 |
+
# terminado
|
| 862 |
+
pure-eval==0.2.3 \
|
| 863 |
+
--hash=sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0 \
|
| 864 |
+
--hash=sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42
|
| 865 |
+
# via stack-data
|
| 866 |
+
pyarrow==20.0.0 \
|
| 867 |
+
--hash=sha256:24ca380585444cb2a31324c546a9a56abbe87e26069189e14bdba19c86c049f0 \
|
| 868 |
+
--hash=sha256:3346babb516f4b6fd790da99b98bed9708e3f02e734c84971faccb20736848dc \
|
| 869 |
+
--hash=sha256:5f0fb1041267e9968c6d0d2ce3ff92e3928b243e2b6d11eeb84d9ac547308232 \
|
| 870 |
+
--hash=sha256:6bb830757103a6cb300a04610e08d9636f0cd223d32f388418ea893a3e655f1c \
|
| 871 |
+
--hash=sha256:7a3a5dcf54286e6141d5114522cf31dd67a9e7c9133d150799f30ee302a7a1ab \
|
| 872 |
+
--hash=sha256:95b330059ddfdc591a3225f2d272123be26c8fa76e8c9ee1a77aad507361cfdb \
|
| 873 |
+
--hash=sha256:96e37f0766ecb4514a899d9a3554fadda770fb57ddf42b63d80f14bc20aa7db3 \
|
| 874 |
+
--hash=sha256:a6ad3e7758ecf559900261a4df985662df54fb7fdb55e8e3b3aa99b23d526b62 \
|
| 875 |
+
--hash=sha256:b8ff87cc837601532cc8242d2f7e09b4e02404de1b797aee747dd4ba4bd6313f \
|
| 876 |
+
--hash=sha256:febc4a913592573c8d5805091a6c2b5064c8bd6e002131f01061797d91c783c1
|
| 877 |
+
# via datasets
|
| 878 |
+
pyasn1==0.6.1 \
|
| 879 |
+
--hash=sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629 \
|
| 880 |
+
--hash=sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034
|
| 881 |
+
# via
|
| 882 |
+
# pyasn1-modules
|
| 883 |
+
# rsa
|
| 884 |
+
pyasn1-modules==0.4.2 \
|
| 885 |
+
--hash=sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a \
|
| 886 |
+
--hash=sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6
|
| 887 |
+
# via google-auth
|
| 888 |
+
pycparser==2.22 \
|
| 889 |
+
--hash=sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6 \
|
| 890 |
+
--hash=sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc
|
| 891 |
+
# via cffi
|
| 892 |
+
pydantic==2.11.4 \
|
| 893 |
+
--hash=sha256:32738d19d63a226a52eed76645a98ee07c1f410ee41d93b4afbfa85ed8111c2d \
|
| 894 |
+
--hash=sha256:d9615eaa9ac5a063471da949c8fc16376a84afb5024688b3ff885693506764eb
|
| 895 |
+
# via
|
| 896 |
+
# fastapi
|
| 897 |
+
# google-genai
|
| 898 |
+
# gradio
|
| 899 |
+
# openai
|
| 900 |
+
pydantic-core==2.33.2 \
|
| 901 |
+
--hash=sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab \
|
| 902 |
+
--hash=sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf \
|
| 903 |
+
--hash=sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7 \
|
| 904 |
+
--hash=sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612 \
|
| 905 |
+
--hash=sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1 \
|
| 906 |
+
--hash=sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a \
|
| 907 |
+
--hash=sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7 \
|
| 908 |
+
--hash=sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51 \
|
| 909 |
+
--hash=sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e \
|
| 910 |
+
--hash=sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65 \
|
| 911 |
+
--hash=sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de \
|
| 912 |
+
--hash=sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc \
|
| 913 |
+
--hash=sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb \
|
| 914 |
+
--hash=sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef \
|
| 915 |
+
--hash=sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc \
|
| 916 |
+
--hash=sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30 \
|
| 917 |
+
--hash=sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e \
|
| 918 |
+
--hash=sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593 \
|
| 919 |
+
--hash=sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f \
|
| 920 |
+
--hash=sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8 \
|
| 921 |
+
--hash=sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf \
|
| 922 |
+
--hash=sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246 \
|
| 923 |
+
--hash=sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8 \
|
| 924 |
+
--hash=sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d
|
| 925 |
+
# via pydantic
|
| 926 |
+
pydub==0.25.1 \
|
| 927 |
+
--hash=sha256:65617e33033874b59d87db603aa1ed450633288aefead953b30bded59cb599a6 \
|
| 928 |
+
--hash=sha256:980a33ce9949cab2a569606b65674d748ecbca4f0796887fd6f46173a7b0d30f
|
| 929 |
+
# via gradio
|
| 930 |
+
pygments==2.19.1 \
|
| 931 |
+
--hash=sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f \
|
| 932 |
+
--hash=sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c
|
| 933 |
+
# via
|
| 934 |
+
# ipython
|
| 935 |
+
# ipython-pygments-lexers
|
| 936 |
+
# nbconvert
|
| 937 |
+
# rich
|
| 938 |
+
pyparsing==3.2.3 \
|
| 939 |
+
--hash=sha256:a749938e02d6fd0b59b356ca504a24982314bb090c383e3cf201c95ef7e2bfcf \
|
| 940 |
+
--hash=sha256:b9c13f1ab8b3b542f72e28f634bad4de758ab3ce4546e4301970ad6fa77c38be
|
| 941 |
+
# via matplotlib
|
| 942 |
+
python-dateutil==2.9.0.post0 \
|
| 943 |
+
--hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \
|
| 944 |
+
--hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427
|
| 945 |
+
# via
|
| 946 |
+
# arrow
|
| 947 |
+
# jupyter-client
|
| 948 |
+
# matplotlib
|
| 949 |
+
# pandas
|
| 950 |
+
python-dotenv==1.1.0 \
|
| 951 |
+
--hash=sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5 \
|
| 952 |
+
--hash=sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d
|
| 953 |
+
# via dotenv
|
| 954 |
+
python-json-logger==3.3.0 \
|
| 955 |
+
--hash=sha256:12b7e74b17775e7d565129296105bbe3910842d9d0eb083fc83a6a617aa8df84 \
|
| 956 |
+
--hash=sha256:dd980fae8cffb24c13caf6e158d3d61c0d6d22342f932cb6e9deedab3d35eec7
|
| 957 |
+
# via jupyter-events
|
| 958 |
+
python-multipart==0.0.20 \
|
| 959 |
+
--hash=sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104 \
|
| 960 |
+
--hash=sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13
|
| 961 |
+
# via gradio
|
| 962 |
+
pytorch-lightning==2.5.2 \
|
| 963 |
+
--hash=sha256:17cfdf89bd98074e389101f097cdf34c486a1f5c6d3fdcefbaf4dea7f97ff0bf \
|
| 964 |
+
--hash=sha256:f817087d611be8d43b777dd4e543d72703e235510936677a13e6c29f7fd790e3
|
| 965 |
+
# via
|
| 966 |
+
# donut-python
|
| 967 |
+
# menu-text-detection
|
| 968 |
+
pytz==2025.2 \
|
| 969 |
+
--hash=sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3 \
|
| 970 |
+
--hash=sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00
|
| 971 |
+
# via pandas
|
| 972 |
+
pywin32==310 ; platform_python_implementation != 'PyPy' and sys_platform == 'win32' \
|
| 973 |
+
--hash=sha256:126298077a9d7c95c53823934f000599f66ec9296b09167810eb24875f32689c \
|
| 974 |
+
--hash=sha256:19ec5fc9b1d51c4350be7bb00760ffce46e6c95eaf2f0b2f1150657b1a43c582 \
|
| 975 |
+
--hash=sha256:1e765f9564e83011a63321bb9d27ec456a0ed90d3732c4b2e312b855365ed8bd
|
| 976 |
+
# via jupyter-core
|
| 977 |
+
pywinpty==2.0.15 ; os_name == 'nt' \
|
| 978 |
+
--hash=sha256:312cf39153a8736c617d45ce8b6ad6cd2107de121df91c455b10ce6bba7a39b2 \
|
| 979 |
+
--hash=sha256:9a6bcec2df2707aaa9d08b86071970ee32c5026e10bcc3cc5f6f391d85baf7ca
|
| 980 |
+
# via
|
| 981 |
+
# jupyter-server
|
| 982 |
+
# jupyter-server-terminals
|
| 983 |
+
# terminado
|
| 984 |
+
pyyaml==6.0.2 \
|
| 985 |
+
--hash=sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5 \
|
| 986 |
+
--hash=sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee \
|
| 987 |
+
--hash=sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85 \
|
| 988 |
+
--hash=sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317 \
|
| 989 |
+
--hash=sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c \
|
| 990 |
+
--hash=sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e \
|
| 991 |
+
--hash=sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774 \
|
| 992 |
+
--hash=sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e \
|
| 993 |
+
--hash=sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44 \
|
| 994 |
+
--hash=sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4
|
| 995 |
+
# via
|
| 996 |
+
# datasets
|
| 997 |
+
# gradio
|
| 998 |
+
# huggingface-hub
|
| 999 |
+
# jupyter-events
|
| 1000 |
+
# pytorch-lightning
|
| 1001 |
+
# timm
|
| 1002 |
+
# transformers
|
| 1003 |
+
pyzmq==26.4.0 \
|
| 1004 |
+
--hash=sha256:2f9f7ffe9db1187a253fca95191854b3fda24696f086e8789d1d449308a34b88 \
|
| 1005 |
+
--hash=sha256:3709c9ff7ba61589b7372923fd82b99a81932b592a5c7f1a24147c91da9a68d6 \
|
| 1006 |
+
--hash=sha256:382a4a48c8080e273427fc692037e3f7d2851959ffe40864f2db32646eeb3cef \
|
| 1007 |
+
--hash=sha256:43b03c1ceea27c6520124f4fb2ba9c647409b9abdf9a62388117148a90419494 \
|
| 1008 |
+
--hash=sha256:4478b14cb54a805088299c25a79f27eaf530564a7a4f72bf432a040042b554eb \
|
| 1009 |
+
--hash=sha256:4550af385b442dc2d55ab7717837812799d3674cb12f9a3aa897611839c18e9e \
|
| 1010 |
+
--hash=sha256:4bd13f85f80962f91a651a7356fe0472791a5f7a92f227822b5acf44795c626d \
|
| 1011 |
+
--hash=sha256:7731abd23a782851426d4e37deb2057bf9410848a4459b5ede4fe89342e687a9 \
|
| 1012 |
+
--hash=sha256:8a28ac29c60e4ba84b5f58605ace8ad495414a724fe7aceb7cf06cd0598d04e1 \
|
| 1013 |
+
--hash=sha256:963977ac8baed7058c1e126014f3fe58b3773f45c78cce7af5c26c09b6823896 \
|
| 1014 |
+
--hash=sha256:a222ad02fbe80166b0526c038776e8042cd4e5f0dec1489a006a1df47e9040e0 \
|
| 1015 |
+
--hash=sha256:bfcf82644c9b45ddd7cd2a041f3ff8dce4a0904429b74d73a439e8cab1bd9e54 \
|
| 1016 |
+
--hash=sha256:c0c8e8cadc81e44cc5088fcd53b9b3b4ce9344815f6c4a03aec653509296fae3 \
|
| 1017 |
+
--hash=sha256:ccdff8ac4246b6fb60dcf3982dfaeeff5dd04f36051fe0632748fc0aa0679c01 \
|
| 1018 |
+
--hash=sha256:d56aad0517d4c09e3b4f15adebba8f6372c5102c27742a5bdbfc74a7dceb8fca \
|
| 1019 |
+
--hash=sha256:e9bcae3979b2654d5289d3490742378b2f3ce804b0b5fd42036074e2bf35b030 \
|
| 1020 |
+
--hash=sha256:f8f3c30fb2d26ae5ce36b59768ba60fb72507ea9efc72f8f69fa088450cff1df
|
| 1021 |
+
# via
|
| 1022 |
+
# ipykernel
|
| 1023 |
+
# jupyter-client
|
| 1024 |
+
# jupyter-server
|
| 1025 |
+
referencing==0.36.2 \
|
| 1026 |
+
--hash=sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa \
|
| 1027 |
+
--hash=sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0
|
| 1028 |
+
# via
|
| 1029 |
+
# jsonschema
|
| 1030 |
+
# jsonschema-specifications
|
| 1031 |
+
# jupyter-events
|
| 1032 |
+
regex==2024.11.6 \
|
| 1033 |
+
--hash=sha256:02e28184be537f0e75c1f9b2f8847dc51e08e6e171c6bde130b2687e0c33cf60 \
|
| 1034 |
+
--hash=sha256:068376da5a7e4da51968ce4c122a7cd31afaaec4fccc7856c92f63876e57b51d \
|
| 1035 |
+
--hash=sha256:1062b39a0a2b75a9c694f7a08e7183a80c63c0d62b301418ffd9c35f55aaa114 \
|
| 1036 |
+
--hash=sha256:167ed4852351d8a750da48712c3930b031f6efdaa0f22fa1933716bfcd6bf4a3 \
|
| 1037 |
+
--hash=sha256:202eb32e89f60fc147a41e55cb086db2a3f8cb82f9a9a88440dcfc5d37faae8d \
|
| 1038 |
+
--hash=sha256:2c89a8cc122b25ce6945f0423dc1352cb9593c68abd19223eebbd4e56612c5b7 \
|
| 1039 |
+
--hash=sha256:2d548dafee61f06ebdb584080621f3e0c23fff312f0de1afc776e2a2ba99a74f \
|
| 1040 |
+
--hash=sha256:4181b814e56078e9b00427ca358ec44333765f5ca1b45597ec7446d3a1ef6e34 \
|
| 1041 |
+
--hash=sha256:5478c6962ad548b54a591778e93cd7c456a7a29f8eca9c49e4f9a806dcc5d638 \
|
| 1042 |
+
--hash=sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519 \
|
| 1043 |
+
--hash=sha256:94d87b689cdd831934fa3ce16cc15cd65748e6d689f5d2b8f4f4df2065c9fa20 \
|
| 1044 |
+
--hash=sha256:9714398225f299aa85267fd222f7142fcb5c769e73d7733344efc46f2ef5cf89 \
|
| 1045 |
+
--hash=sha256:ac10f2c4184420d881a3475fb2c6f4d95d53a8d50209a2500723d831036f7c45 \
|
| 1046 |
+
--hash=sha256:bec9931dfb61ddd8ef2ebc05646293812cb6b16b60cf7c9511a832b6f1854b55 \
|
| 1047 |
+
--hash=sha256:c36f9b6f5f8649bb251a5f3f66564438977b7ef8386a52460ae77e6070d309d9 \
|
| 1048 |
+
--hash=sha256:f2a19f302cd1ce5dd01a9099aaa19cae6173306d1302a43b627f62e21cf18ac0
|
| 1049 |
+
# via
|
| 1050 |
+
# nltk
|
| 1051 |
+
# transformers
|
| 1052 |
+
requests==2.32.3 \
|
| 1053 |
+
--hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \
|
| 1054 |
+
--hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6
|
| 1055 |
+
# via
|
| 1056 |
+
# datasets
|
| 1057 |
+
# google-genai
|
| 1058 |
+
# huggingface-hub
|
| 1059 |
+
# jupyterlab-server
|
| 1060 |
+
# transformers
|
| 1061 |
+
rfc3339-validator==0.1.4 \
|
| 1062 |
+
--hash=sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b \
|
| 1063 |
+
--hash=sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa
|
| 1064 |
+
# via
|
| 1065 |
+
# jsonschema
|
| 1066 |
+
# jupyter-events
|
| 1067 |
+
rfc3986-validator==0.1.1 \
|
| 1068 |
+
--hash=sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9 \
|
| 1069 |
+
--hash=sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055
|
| 1070 |
+
# via
|
| 1071 |
+
# jsonschema
|
| 1072 |
+
# jupyter-events
|
| 1073 |
+
rich==14.0.0 ; sys_platform != 'emscripten' \
|
| 1074 |
+
--hash=sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0 \
|
| 1075 |
+
--hash=sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725
|
| 1076 |
+
# via typer
|
| 1077 |
+
rpds-py==0.24.0 \
|
| 1078 |
+
--hash=sha256:04ecf5c1ff4d589987b4d9882872f80ba13da7d42427234fce8f22efb43133bc \
|
| 1079 |
+
--hash=sha256:04f2b712a2206e13800a8136b07aaedc23af3facab84918e7aa89e4be0260032 \
|
| 1080 |
+
--hash=sha256:174e46569968ddbbeb8a806d9922f17cd2b524aa753b468f35b97ff9c19cb718 \
|
| 1081 |
+
--hash=sha256:2d3ee4615df36ab8eb16c2507b11e764dcc11fd350bbf4da16d09cda11fcedef \
|
| 1082 |
+
--hash=sha256:34d90ad8c045df9a4259c47d2e16a3f21fdb396665c94520dbfe8766e62187a4 \
|
| 1083 |
+
--hash=sha256:4cd031e63bc5f05bdcda120646a0d32f6d729486d0067f09d79c8db5368f4586 \
|
| 1084 |
+
--hash=sha256:5ef877fa3bbfb40b388a5ae1cb00636a624690dcb9a29a65267054c9ea86d88a \
|
| 1085 |
+
--hash=sha256:630d3d8ea77eabd6cbcd2ea712e1c5cecb5b558d39547ac988351195db433f6c \
|
| 1086 |
+
--hash=sha256:6a727fd083009bc83eb83d6950f0c32b3c94c8b80a9b667c87f4bd1274ca30ba \
|
| 1087 |
+
--hash=sha256:772cc1b2cd963e7e17e6cc55fe0371fb9c704d63e44cacec7b9b7f523b78919e \
|
| 1088 |
+
--hash=sha256:9abc80fe8c1f87218db116016de575a7998ab1629078c90840e8d11ab423ee25 \
|
| 1089 |
+
--hash=sha256:9c39438c55983d48f4bb3487734d040e22dad200dab22c41e331cee145e7a50d \
|
| 1090 |
+
--hash=sha256:9d7e8ce990ae17dda686f7e82fd41a055c668e13ddcf058e7fb5e9da20b57793 \
|
| 1091 |
+
--hash=sha256:9ea7f4174d2e4194289cb0c4e172d83e79a6404297ff95f2875cf9ac9bced8ba \
|
| 1092 |
+
--hash=sha256:bb2954155bb8f63bb19d56d80e5e5320b61d71084617ed89efedb861a684baea \
|
| 1093 |
+
--hash=sha256:c43583ea8517ed2e780a345dd9960896afc1327e8cf3ac8239c167530397440d \
|
| 1094 |
+
--hash=sha256:cf86f72d705fc2ef776bb7dd9e5fbba79d7e1f3e258bf9377f8204ad0fc1c51e \
|
| 1095 |
+
--hash=sha256:d6e109a454412ab82979c5b1b3aee0604eca4bbf9a02693bb9df027af2bfa91a \
|
| 1096 |
+
--hash=sha256:e13ae74a8a3a0c2f22f450f773e35f893484fcfacb00bb4344a7e0f4f48e1f97 \
|
| 1097 |
+
--hash=sha256:e274f62cbd274359eff63e5c7e7274c913e8e09620f6a57aae66744b3df046d6 \
|
| 1098 |
+
--hash=sha256:e838bf2bb0b91ee67bf2b889a1a841e5ecac06dd7a2b1ef4e6151e2ce155c7ae \
|
| 1099 |
+
--hash=sha256:ebcb786b9ff30b994d5969213a8430cbb984cdd7ea9fd6df06663194bd3c450c \
|
| 1100 |
+
--hash=sha256:eda5c1e2a715a4cbbca2d6d304988460942551e4e5e3b7457b50943cd741626d \
|
| 1101 |
+
--hash=sha256:f9e0057a509e096e47c87f753136c9b10d7a91842d8042c2ee6866899a717c0d \
|
| 1102 |
+
--hash=sha256:fc1c892b1ec1f8cbd5da8de287577b455e388d9c328ad592eabbdcb6fc93bee5
|
| 1103 |
+
# via
|
| 1104 |
+
# jsonschema
|
| 1105 |
+
# referencing
|
| 1106 |
+
rsa==4.9.1 \
|
| 1107 |
+
--hash=sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762 \
|
| 1108 |
+
--hash=sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75
|
| 1109 |
+
# via google-auth
|
| 1110 |
+
ruamel-yaml==0.18.14 \
|
| 1111 |
+
--hash=sha256:710ff198bb53da66718c7db27eec4fbcc9aa6ca7204e4c1df2f282b6fe5eb6b2 \
|
| 1112 |
+
--hash=sha256:7227b76aaec364df15936730efbf7d72b30c0b79b1d578bbb8e3dcb2d81f52b7
|
| 1113 |
+
# via sconf
|
| 1114 |
+
ruamel-yaml-clib==0.2.12 ; platform_python_implementation == 'CPython' \
|
| 1115 |
+
--hash=sha256:1492a6051dab8d912fc2adeef0e8c72216b24d57bd896ea607cb90bb0c4981d3 \
|
| 1116 |
+
--hash=sha256:4a6679521a58256a90b0d89e03992c15144c5f3858f40d7c18886023d7943db6 \
|
| 1117 |
+
--hash=sha256:6c8fbb13ec503f99a91901ab46e0b07ae7941cd527393187039aec586fdfd36f \
|
| 1118 |
+
--hash=sha256:7dd5adc8b930b12c8fc5b99e2d535a09889941aa0d0bd06f4749e9a9397c71d2 \
|
| 1119 |
+
--hash=sha256:811ea1594b8a0fb466172c384267a4e5e367298af6b228931f273b111f17ef52 \
|
| 1120 |
+
--hash=sha256:a274fb2cb086c7a3dea4322ec27f4cb5cc4b6298adb583ab0e211a4682f241eb \
|
| 1121 |
+
--hash=sha256:bb43a269eb827806502c7c8efb7ae7e9e9d0573257a46e8e952f4d4caba4f31e \
|
| 1122 |
+
--hash=sha256:bd0a08f0bab19093c54e18a14a10b4322e1eacc5217056f3c063bd2f59853ce4 \
|
| 1123 |
+
--hash=sha256:cf12567a7b565cbf65d438dec6cfbe2917d3c1bdddfce84a9930b7d35ea59642 \
|
| 1124 |
+
--hash=sha256:d84318609196d6bd6da0edfa25cedfbabd8dbde5140a0a23af29ad4b8f91fb1e
|
| 1125 |
+
# via ruamel-yaml
|
| 1126 |
+
ruff==0.11.8 ; sys_platform != 'emscripten' \
|
| 1127 |
+
--hash=sha256:0eba551324733efc76116d9f3a0d52946bc2751f0cd30661564117d6fd60897c \
|
| 1128 |
+
--hash=sha256:161eb4cff5cfefdb6c9b8b3671d09f7def2f960cee33481dd898caf2bcd02304 \
|
| 1129 |
+
--hash=sha256:258f3585057508d317610e8a412788cf726efeefa2fec4dba4001d9e6f90d46c \
|
| 1130 |
+
--hash=sha256:304432e4c4a792e3da85b7699feb3426a0908ab98bf29df22a31b0cdd098fac2 \
|
| 1131 |
+
--hash=sha256:3dca977cc4fc8f66e89900fa415ffe4dbc2e969da9d7a54bfca81a128c5ac219 \
|
| 1132 |
+
--hash=sha256:4d9aaa91035bdf612c8ee7266153bcf16005c7c7e2f5878406911c92a31633cb \
|
| 1133 |
+
--hash=sha256:5b18caa297a786465cc511d7f8be19226acf9c0a1127e06e736cd4e1878c3ea2 \
|
| 1134 |
+
--hash=sha256:6d742d10626f9004b781f4558154bb226620a7242080e11caeffab1a40e99df8 \
|
| 1135 |
+
--hash=sha256:6e70d11043bef637c5617297bdedec9632af15d53ac1e1ba29c448da9341b0c4 \
|
| 1136 |
+
--hash=sha256:727d01702f7c30baed3fc3a34901a640001a2828c793525043c29f7614994a8c \
|
| 1137 |
+
--hash=sha256:7f024d32e62faad0f76b2d6afd141b8c171515e4fb91ce9fd6464335c81244e5 \
|
| 1138 |
+
--hash=sha256:896a37516c594805e34020c4a7546c8f8a234b679a7716a3f08197f38913e1a3 \
|
| 1139 |
+
--hash=sha256:ab86d22d3d721a40dd3ecbb5e86ab03b2e053bc93c700dc68d1c3346b36ce835 \
|
| 1140 |
+
--hash=sha256:c1dba3135ca503727aa4648152c0fa67c3b1385d3dc81c75cd8a229c4b2a1458 \
|
| 1141 |
+
--hash=sha256:c657fa987d60b104d2be8b052d66da0a2a88f9bd1d66b2254333e84ea2720c7f \
|
| 1142 |
+
--hash=sha256:d365618d3ad747432e1ae50d61775b78c055fee5936d77fb4d92c6f559741948 \
|
| 1143 |
+
--hash=sha256:f2e74b021d0de5eceb8bd32919f6ff8a9b40ee62ed97becd44993ae5b9949474 \
|
| 1144 |
+
--hash=sha256:f9b5ef39820abc0f2c62111f7045009e46b275f5b99d5e59dda113c39b7f4f38
|
| 1145 |
+
# via gradio
|
| 1146 |
+
safehttpx==0.1.6 \
|
| 1147 |
+
--hash=sha256:407cff0b410b071623087c63dd2080c3b44dc076888d8c5823c00d1e58cb381c \
|
| 1148 |
+
--hash=sha256:b356bfc82cee3a24c395b94a2dbeabbed60aff1aa5fa3b5fe97c4f2456ebce42
|
| 1149 |
+
# via gradio
|
| 1150 |
+
safetensors==0.5.3 \
|
| 1151 |
+
--hash=sha256:1077f3e94182d72618357b04b5ced540ceb71c8a813d3319f1aba448e68a770d \
|
| 1152 |
+
--hash=sha256:11bce6164887cd491ca75c2326a113ba934be596e22b28b1742ce27b1d076467 \
|
| 1153 |
+
--hash=sha256:21d01c14ff6c415c485616b8b0bf961c46b3b343ca59110d38d744e577f9cce7 \
|
| 1154 |
+
--hash=sha256:32c3ef2d7af8b9f52ff685ed0bc43913cdcde135089ae322ee576de93eae5135 \
|
| 1155 |
+
--hash=sha256:37f1521be045e56fc2b54c606d4455573e717b2d887c579ee1dbba5f868ece04 \
|
| 1156 |
+
--hash=sha256:391ac8cab7c829452175f871fcaf414aa1e292b5448bd02620f675a7f3e7abb9 \
|
| 1157 |
+
--hash=sha256:4a243be3590bc3301c821da7a18d87224ef35cbd3e5f5727e4e0728b8172411e \
|
| 1158 |
+
--hash=sha256:799021e78287bac619c7b3f3606730a22da4cda27759ddf55d37c8db7511c74b \
|
| 1159 |
+
--hash=sha256:836cbbc320b47e80acd40e44c8682db0e8ad7123209f69b093def21ec7cafd11 \
|
| 1160 |
+
--hash=sha256:8bd84b12b1670a6f8e50f01e28156422a2bc07fb16fc4e98bded13039d688a0d \
|
| 1161 |
+
--hash=sha256:b6b0d6ecacec39a4fdd99cc19f4576f5219ce858e6fd8dbe7609df0b8dc56965 \
|
| 1162 |
+
--hash=sha256:bd20eb133db8ed15b40110b7c00c6df51655a2998132193de2f75f72d99c7073 \
|
| 1163 |
+
--hash=sha256:cead1fa41fc54b1e61089fa57452e8834f798cb1dc7a09ba3524f1eb08e0317a \
|
| 1164 |
+
--hash=sha256:cfc0ec0846dcf6763b0ed3d1846ff36008c6e7290683b61616c4b040f6a54ace \
|
| 1165 |
+
--hash=sha256:df26da01aaac504334644e1b7642fa000bfec820e7cef83aeac4e355e03195ff
|
| 1166 |
+
# via
|
| 1167 |
+
# timm
|
| 1168 |
+
# transformers
|
| 1169 |
+
sconf==0.2.5 \
|
| 1170 |
+
--hash=sha256:c557b5a87d39dd7d5334a1236112873d2e0b1b71b386d24e2f01726aec1d957a
|
| 1171 |
+
# via donut-python
|
| 1172 |
+
semantic-version==2.10.0 \
|
| 1173 |
+
--hash=sha256:bdabb6d336998cbb378d4b9db3a4b56a1e3235701dc05ea2690d9a997ed5041c \
|
| 1174 |
+
--hash=sha256:de78a3b8e0feda74cabc54aab2da702113e33ac9d9eb9d2389bcf1f58b7d9177
|
| 1175 |
+
# via gradio
|
| 1176 |
+
send2trash==1.8.3 \
|
| 1177 |
+
--hash=sha256:0c31227e0bd08961c7665474a3d1ef7193929fedda4233843689baa056be46c9 \
|
| 1178 |
+
--hash=sha256:b18e7a3966d99871aefeb00cfbcfdced55ce4871194810fc71f4aa484b953abf
|
| 1179 |
+
# via jupyter-server
|
| 1180 |
+
sentencepiece==0.2.0 \
|
| 1181 |
+
--hash=sha256:0993dbc665f4113017892f1b87c3904a44d0640eda510abcacdfb07f74286d36 \
|
| 1182 |
+
--hash=sha256:17982700c4f6dbb55fa3594f3d7e5dd1c8659a274af3738e33c987d2a27c9d5c \
|
| 1183 |
+
--hash=sha256:27f90c55a65013cbb8f4d7aab0599bf925cde4adc67ae43a0d323677b5a1c6cb \
|
| 1184 |
+
--hash=sha256:7c867012c0e8bcd5bdad0f791609101cb5c66acb303ab3270218d6debc68a65e \
|
| 1185 |
+
--hash=sha256:7fd6071249c74f779c5b27183295b9202f8dedb68034e716784364443879eaa6 \
|
| 1186 |
+
--hash=sha256:a52c19171daaf2e697dc6cbe67684e0fa341b1248966f6aebb541de654d15843 \
|
| 1187 |
+
--hash=sha256:b293734059ef656dcd65be62ff771507bea8fed0a711b6733976e1ed3add4553 \
|
| 1188 |
+
--hash=sha256:c581258cf346b327c62c4f1cebd32691826306f6a41d8c4bec43b010dee08e75 \
|
| 1189 |
+
--hash=sha256:e58b47f933aca74c6a60a79dcb21d5b9e47416256c795c2d58d55cec27f9551d
|
| 1190 |
+
# via
|
| 1191 |
+
# donut-python
|
| 1192 |
+
# menu-text-detection
|
| 1193 |
+
setuptools==80.3.1 \
|
| 1194 |
+
--hash=sha256:31e2c58dbb67c99c289f51c16d899afedae292b978f8051efaf6262d8212f927 \
|
| 1195 |
+
--hash=sha256:ea8e00d7992054c4c592aeb892f6ad51fe1b4d90cc6947cc45c45717c40ec537
|
| 1196 |
+
# via
|
| 1197 |
+
# jupyterlab
|
| 1198 |
+
# lightning-utilities
|
| 1199 |
+
shellingham==1.5.4 ; sys_platform != 'emscripten' \
|
| 1200 |
+
--hash=sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686 \
|
| 1201 |
+
--hash=sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de
|
| 1202 |
+
# via typer
|
| 1203 |
+
six==1.17.0 \
|
| 1204 |
+
--hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \
|
| 1205 |
+
--hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81
|
| 1206 |
+
# via
|
| 1207 |
+
# python-dateutil
|
| 1208 |
+
# rfc3339-validator
|
| 1209 |
+
# zss
|
| 1210 |
+
sniffio==1.3.1 \
|
| 1211 |
+
--hash=sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2 \
|
| 1212 |
+
--hash=sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc
|
| 1213 |
+
# via
|
| 1214 |
+
# anyio
|
| 1215 |
+
# openai
|
| 1216 |
+
soupsieve==2.7 \
|
| 1217 |
+
--hash=sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4 \
|
| 1218 |
+
--hash=sha256:ad282f9b6926286d2ead4750552c8a6142bc4c783fd66b0293547c8fe6ae126a
|
| 1219 |
+
# via beautifulsoup4
|
| 1220 |
+
stack-data==0.6.3 \
|
| 1221 |
+
--hash=sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9 \
|
| 1222 |
+
--hash=sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695
|
| 1223 |
+
# via ipython
|
| 1224 |
+
starlette==0.46.2 \
|
| 1225 |
+
--hash=sha256:595633ce89f8ffa71a015caed34a5b2dc1c0cdb3f0f1fbd1e69339cf2abeec35 \
|
| 1226 |
+
--hash=sha256:7f7361f34eed179294600af672f565727419830b54b7b084efe44bb82d2fccd5
|
| 1227 |
+
# via
|
| 1228 |
+
# fastapi
|
| 1229 |
+
# gradio
|
| 1230 |
+
sympy==1.14.0 \
|
| 1231 |
+
--hash=sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517 \
|
| 1232 |
+
--hash=sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5
|
| 1233 |
+
# via torch
|
| 1234 |
+
tensorboardx==2.6.2.2 \
|
| 1235 |
+
--hash=sha256:160025acbf759ede23fd3526ae9d9bfbfd8b68eb16c38a010ebe326dc6395db8 \
|
| 1236 |
+
--hash=sha256:c6476d7cd0d529b0b72f4acadb1269f9ed8b22f441e87a84f2a3b940bb87b666
|
| 1237 |
+
# via menu-text-detection
|
| 1238 |
+
terminado==0.18.1 \
|
| 1239 |
+
--hash=sha256:a4468e1b37bb318f8a86514f65814e1afc977cf29b3992a4500d9dd305dcceb0 \
|
| 1240 |
+
--hash=sha256:de09f2c4b85de4765f7714688fff57d3e75bad1f909b589fde880460c753fd2e
|
| 1241 |
+
# via
|
| 1242 |
+
# jupyter-server
|
| 1243 |
+
# jupyter-server-terminals
|
| 1244 |
+
timm==1.0.16 \
|
| 1245 |
+
--hash=sha256:a3b8130dd2cb8dc3b9f5e3d09ab6d677a6315a8695fd5264eb6d52a4a46c1044 \
|
| 1246 |
+
--hash=sha256:a640e58f4ae41e0445517d1133b34be75bb2bd49cdb830d739925ce1fb7d2526
|
| 1247 |
+
# via donut-python
|
| 1248 |
+
tinycss2==1.4.0 \
|
| 1249 |
+
--hash=sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7 \
|
| 1250 |
+
--hash=sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289
|
| 1251 |
+
# via bleach
|
| 1252 |
+
tokenizers==0.21.1 \
|
| 1253 |
+
--hash=sha256:0f0dcbcc9f6e13e675a66d7a5f2f225a736745ce484c1a4e07476a89ccdad382 \
|
| 1254 |
+
--hash=sha256:1039a3a5734944e09de1d48761ade94e00d0fa760c0e0551151d4dd851ba63e3 \
|
| 1255 |
+
--hash=sha256:28da6b72d4fb14ee200a1bd386ff74ade8992d7f725f2bde2c495a9a98cf4d9f \
|
| 1256 |
+
--hash=sha256:2dd9a0061e403546f7377df940e866c3e678d7d4e9643d0461ea442b4f89e61a \
|
| 1257 |
+
--hash=sha256:2fdbd4c067c60a0ac7eca14b6bd18a5bebace54eb757c706b47ea93204f7a37c \
|
| 1258 |
+
--hash=sha256:34d8cfde551c9916cb92014e040806122295a6800914bab5865deb85623931cf \
|
| 1259 |
+
--hash=sha256:9ac78b12e541d4ce67b4dfd970e44c060a2147b9b2a21f509566d556a509c67d \
|
| 1260 |
+
--hash=sha256:a1bb04dc5b448985f86ecd4b05407f5a8d97cb2c0532199b2a302a604a0165ab \
|
| 1261 |
+
--hash=sha256:a21a15d5c8e603331b8a59548bbe113564136dc0f5ad8306dd5033459a226da0 \
|
| 1262 |
+
--hash=sha256:aaa852d23e125b73d283c98f007e06d4595732104b65402f46e8ef24b588d9f8 \
|
| 1263 |
+
--hash=sha256:cd51cd0a91ecc801633829fcd1fda9cf8682ed3477c6243b9a095539de4aecf3 \
|
| 1264 |
+
--hash=sha256:db9484aeb2e200c43b915a1a0150ea885e35f357a5a8fabf7373af333dcc8dbf \
|
| 1265 |
+
--hash=sha256:e5a69c1a4496b81a5ee5d2c1f3f7fbdf95e90a0196101b0ee89ed9956b8a168f \
|
| 1266 |
+
--hash=sha256:e78e413e9e668ad790a29456e677d9d3aa50a9ad311a40905d6861ba7692cf41 \
|
| 1267 |
+
--hash=sha256:ed248ab5279e601a30a4d67bdb897ecbe955a50f1e7bb62bd99f07dd11c2f5b6
|
| 1268 |
+
# via transformers
|
| 1269 |
+
tomlkit==0.13.2 \
|
| 1270 |
+
--hash=sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde \
|
| 1271 |
+
--hash=sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79
|
| 1272 |
+
# via gradio
|
| 1273 |
+
torch==2.4.1 \
|
| 1274 |
+
--hash=sha256:092e7c2280c860eff762ac08c4bdcd53d701677851670695e0c22d6d345b269c \
|
| 1275 |
+
--hash=sha256:0b5f88afdfa05a335d80351e3cea57d38e578c8689f751d35e0ff36bce872113 \
|
| 1276 |
+
--hash=sha256:ddddbd8b066e743934a4200b3d54267a46db02106876d21cf31f7da7a96f98ea \
|
| 1277 |
+
--hash=sha256:ef503165f2341942bfdf2bd520152f19540d0c0e34961232f134dc59ad435be8
|
| 1278 |
+
# via
|
| 1279 |
+
# menu-text-detection
|
| 1280 |
+
# pytorch-lightning
|
| 1281 |
+
# timm
|
| 1282 |
+
# torchmetrics
|
| 1283 |
+
# torchvision
|
| 1284 |
+
torchmetrics==1.7.3 \
|
| 1285 |
+
--hash=sha256:08450a19cdb67ba1608aac0b213e5dc73033e11b60ad4719696ebcede591621e \
|
| 1286 |
+
--hash=sha256:7b6fd43e92f0a1071c8bcb029637f252b0630699140a93ed8817ce7afe9db34e
|
| 1287 |
+
# via pytorch-lightning
|
| 1288 |
+
torchvision==0.19.1 \
|
| 1289 |
+
--hash=sha256:40514282b4896d62765b8e26d7091c32e17c35817d00ec4be2362ea3ba3d1787 \
|
| 1290 |
+
--hash=sha256:5a91be061ae5d6d5b95e833b93e57ca4d3c56c5a57444dd15da2e3e7fba96050 \
|
| 1291 |
+
--hash=sha256:70dea324174f5e9981b68e4b7cd524512c106ba64aedef560a86a0bbf2fbf62c \
|
| 1292 |
+
--hash=sha256:d71a6a6fe3a5281ca3487d4c56ad4aad20ff70f82f1d7c79bcb6e7b0c2af00c8
|
| 1293 |
+
# via timm
|
| 1294 |
+
tornado==6.4.2 \
|
| 1295 |
+
--hash=sha256:072ce12ada169c5b00b7d92a99ba089447ccc993ea2143c9ede887e0937aa803 \
|
| 1296 |
+
--hash=sha256:1a017d239bd1bb0919f72af256a970624241f070496635784d9bf0db640d3fec \
|
| 1297 |
+
--hash=sha256:2876cef82e6c5978fde1e0d5b1f919d756968d5b4282418f3146b79b58556482 \
|
| 1298 |
+
--hash=sha256:304463bd0772442ff4d0f5149c6f1c2135a1fae045adf070821c6cdc76980634 \
|
| 1299 |
+
--hash=sha256:908b71bf3ff37d81073356a5fadcc660eb10c1476ee6e2725588626ce7e5ca38 \
|
| 1300 |
+
--hash=sha256:92bad5b4746e9879fd7bf1eb21dce4e3fc5128d71601f80005afa39237ad620b \
|
| 1301 |
+
--hash=sha256:932d195ca9015956fa502c6b56af9eb06106140d844a335590c1ec7f5277d10c \
|
| 1302 |
+
--hash=sha256:bca9eb02196e789c9cb5c3c7c0f04fb447dc2adffd95265b2c7223a8a615ccbf \
|
| 1303 |
+
--hash=sha256:c36e62ce8f63409301537222faffcef7dfc5284f27eec227389f2ad11b09d946 \
|
| 1304 |
+
--hash=sha256:c82c46813ba483a385ab2a99caeaedf92585a1f90defb5693351fa7e4ea0bf73 \
|
| 1305 |
+
--hash=sha256:e828cce1123e9e44ae2a50a9de3055497ab1d0aeb440c5ac23064d9e44880da1
|
| 1306 |
+
# via
|
| 1307 |
+
# ipykernel
|
| 1308 |
+
# jupyter-client
|
| 1309 |
+
# jupyter-server
|
| 1310 |
+
# jupyterlab
|
| 1311 |
+
# notebook
|
| 1312 |
+
# terminado
|
| 1313 |
+
tqdm==4.67.1 \
|
| 1314 |
+
--hash=sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2 \
|
| 1315 |
+
--hash=sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2
|
| 1316 |
+
# via
|
| 1317 |
+
# datasets
|
| 1318 |
+
# huggingface-hub
|
| 1319 |
+
# nltk
|
| 1320 |
+
# openai
|
| 1321 |
+
# pytorch-lightning
|
| 1322 |
+
# transformers
|
| 1323 |
+
traitlets==5.14.3 \
|
| 1324 |
+
--hash=sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7 \
|
| 1325 |
+
--hash=sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f
|
| 1326 |
+
# via
|
| 1327 |
+
# comm
|
| 1328 |
+
# ipykernel
|
| 1329 |
+
# ipython
|
| 1330 |
+
# jupyter-client
|
| 1331 |
+
# jupyter-core
|
| 1332 |
+
# jupyter-events
|
| 1333 |
+
# jupyter-server
|
| 1334 |
+
# jupyterlab
|
| 1335 |
+
# matplotlib-inline
|
| 1336 |
+
# nbclient
|
| 1337 |
+
# nbconvert
|
| 1338 |
+
# nbformat
|
| 1339 |
+
transformers==4.49.0 \
|
| 1340 |
+
--hash=sha256:6b4fded1c5fee04d384b1014495b4235a2b53c87503d7d592423c06128cbbe03 \
|
| 1341 |
+
--hash=sha256:7e40e640b5b8dc3f48743f5f5adbdce3660c82baafbd3afdfc04143cdbd2089e
|
| 1342 |
+
# via
|
| 1343 |
+
# donut-python
|
| 1344 |
+
# menu-text-detection
|
| 1345 |
+
triton==3.0.0 ; platform_machine == 'x86_64' and sys_platform == 'linux' \
|
| 1346 |
+
--hash=sha256:5ce8520437c602fb633f1324cc3871c47bee3b67acf9756c1a66309b60e3216c
|
| 1347 |
+
# via torch
|
| 1348 |
+
typer==0.15.3 ; sys_platform != 'emscripten' \
|
| 1349 |
+
--hash=sha256:818873625d0569653438316567861899f7e9972f2e6e0c16dab608345ced713c \
|
| 1350 |
+
--hash=sha256:c86a65ad77ca531f03de08d1b9cb67cd09ad02ddddf4b34745b5008f43b239bd
|
| 1351 |
+
# via gradio
|
| 1352 |
+
types-python-dateutil==2.9.0.20241206 \
|
| 1353 |
+
--hash=sha256:18f493414c26ffba692a72369fea7a154c502646301ebfe3d56a04b3767284cb \
|
| 1354 |
+
--hash=sha256:e248a4bc70a486d3e3ec84d0dc30eec3a5f979d6e7ee4123ae043eedbb987f53
|
| 1355 |
+
# via arrow
|
| 1356 |
+
typing-extensions==4.13.2 \
|
| 1357 |
+
--hash=sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c \
|
| 1358 |
+
--hash=sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef
|
| 1359 |
+
# via
|
| 1360 |
+
# anyio
|
| 1361 |
+
# beautifulsoup4
|
| 1362 |
+
# fastapi
|
| 1363 |
+
# google-genai
|
| 1364 |
+
# gradio
|
| 1365 |
+
# gradio-client
|
| 1366 |
+
# huggingface-hub
|
| 1367 |
+
# ipython
|
| 1368 |
+
# lightning-utilities
|
| 1369 |
+
# openai
|
| 1370 |
+
# pydantic
|
| 1371 |
+
# pydantic-core
|
| 1372 |
+
# pytorch-lightning
|
| 1373 |
+
# referencing
|
| 1374 |
+
# torch
|
| 1375 |
+
# typer
|
| 1376 |
+
# typing-inspection
|
| 1377 |
+
typing-inspection==0.4.0 \
|
| 1378 |
+
--hash=sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f \
|
| 1379 |
+
--hash=sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122
|
| 1380 |
+
# via pydantic
|
| 1381 |
+
tzdata==2025.2 \
|
| 1382 |
+
--hash=sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8 \
|
| 1383 |
+
--hash=sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9
|
| 1384 |
+
# via pandas
|
| 1385 |
+
uri-template==1.3.0 \
|
| 1386 |
+
--hash=sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7 \
|
| 1387 |
+
--hash=sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363
|
| 1388 |
+
# via jsonschema
|
| 1389 |
+
urllib3==2.4.0 \
|
| 1390 |
+
--hash=sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466 \
|
| 1391 |
+
--hash=sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813
|
| 1392 |
+
# via
|
| 1393 |
+
# gradio
|
| 1394 |
+
# requests
|
| 1395 |
+
uvicorn==0.34.2 ; sys_platform != 'emscripten' \
|
| 1396 |
+
--hash=sha256:0e929828f6186353a80b58ea719861d2629d766293b6d19baf086ba31d4f3328 \
|
| 1397 |
+
--hash=sha256:deb49af569084536d269fe0a6d67e3754f104cf03aba7c11c40f01aadf33c403
|
| 1398 |
+
# via gradio
|
| 1399 |
+
wcwidth==0.2.13 \
|
| 1400 |
+
--hash=sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859 \
|
| 1401 |
+
--hash=sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5
|
| 1402 |
+
# via prompt-toolkit
|
| 1403 |
+
webcolors==24.11.1 \
|
| 1404 |
+
--hash=sha256:515291393b4cdf0eb19c155749a096f779f7d909f7cceea072791cb9095b92e9 \
|
| 1405 |
+
--hash=sha256:ecb3d768f32202af770477b8b65f318fa4f566c22948673a977b00d589dd80f6
|
| 1406 |
+
# via jsonschema
|
| 1407 |
+
webencodings==0.5.1 \
|
| 1408 |
+
--hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \
|
| 1409 |
+
--hash=sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923
|
| 1410 |
+
# via
|
| 1411 |
+
# bleach
|
| 1412 |
+
# tinycss2
|
| 1413 |
+
websocket-client==1.8.0 \
|
| 1414 |
+
--hash=sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526 \
|
| 1415 |
+
--hash=sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da
|
| 1416 |
+
# via jupyter-server
|
| 1417 |
+
websockets==15.0.1 \
|
| 1418 |
+
--hash=sha256:16b6c1b3e57799b9d38427dda63edcbe4926352c47cf88588c0be4ace18dac85 \
|
| 1419 |
+
--hash=sha256:27ccee0071a0e75d22cb35849b1db43f2ecd3e161041ac1ee9d2352ddf72f065 \
|
| 1420 |
+
--hash=sha256:54479983bd5fb469c38f2f5c7e3a24f9a4e70594cd68cd1fa6b9340dadaff7cf \
|
| 1421 |
+
--hash=sha256:66dd88c918e3287efc22409d426c8f729688d89a0c587c88971a0faa2c2f3792 \
|
| 1422 |
+
--hash=sha256:678999709e68425ae2593acf2e3ebcbcf2e69885a5ee78f9eb80e6e371f1bf57 \
|
| 1423 |
+
--hash=sha256:693f0192126df6c2327cce3baa7c06f2a117575e32ab2308f7f8216c29d9e2e3 \
|
| 1424 |
+
--hash=sha256:823c248b690b2fd9303ba00c4f66cd5e2d8c3ba4aa968b2779be9532a4dad431 \
|
| 1425 |
+
--hash=sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee \
|
| 1426 |
+
--hash=sha256:8dd8327c795b3e3f219760fa603dcae1dcc148172290a8ab15158cf85a953413 \
|
| 1427 |
+
--hash=sha256:8fdc51055e6ff4adeb88d58a11042ec9a5eae317a0a53d12c062c8a8865909e8 \
|
| 1428 |
+
--hash=sha256:d50fd1ee42388dcfb2b3676132c78116490976f1300da28eb629272d5d93e905 \
|
| 1429 |
+
--hash=sha256:d99e5546bf73dbad5bf3547174cd6cb8ba7273062a23808ffea025ecb1cf8562 \
|
| 1430 |
+
--hash=sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f
|
| 1431 |
+
# via
|
| 1432 |
+
# google-genai
|
| 1433 |
+
# gradio-client
|
| 1434 |
+
xxhash==3.5.0 \
|
| 1435 |
+
--hash=sha256:02c2e816896dc6f85922ced60097bcf6f008dedfc5073dcba32f9c8dd786f3c1 \
|
| 1436 |
+
--hash=sha256:109b436096d0a2dd039c355fa3414160ec4d843dfecc64a14077332a00aeb7da \
|
| 1437 |
+
--hash=sha256:1308fa542bbdbf2fa85e9e66b1077eea3a88bef38ee8a06270b4298a7a62a166 \
|
| 1438 |
+
--hash=sha256:25b5a51dc3dfb20a10833c8eee25903fd2e14059e9afcd329c9da20609a307b2 \
|
| 1439 |
+
--hash=sha256:6027dcd885e21581e46d3c7f682cfb2b870942feeed58a21c29583512c3f09f8 \
|
| 1440 |
+
--hash=sha256:685c4f4e8c59837de103344eb1c8a3851f670309eb5c361f746805c5471b8c88 \
|
| 1441 |
+
--hash=sha256:84f2caddf951c9cbf8dc2e22a89d4ccf5d86391ac6418fe81e3c67d0cf60b45f \
|
| 1442 |
+
--hash=sha256:89997aa1c4b6a5b1e5b588979d1da048a3c6f15e55c11d117a56b75c84531f5a \
|
| 1443 |
+
--hash=sha256:924361811732ddad75ff23e90efd9ccfda4f664132feecb90895bade6a1b4623 \
|
| 1444 |
+
--hash=sha256:963be41bcd49f53af6d795f65c0da9b4cc518c0dd9c47145c98f61cb464f4839 \
|
| 1445 |
+
--hash=sha256:a8fb786fb754ef6ff8c120cb96629fb518f8eb5a61a16aac3a979a9dbd40a084 \
|
| 1446 |
+
--hash=sha256:a905ad00ad1e1c34fe4e9d7c1d949ab09c6fa90c919860c1534ff479f40fd12d \
|
| 1447 |
+
--hash=sha256:b702f806693201ad6c0a05ddbbe4c8f359626d0b3305f766077d51388a6bac58 \
|
| 1448 |
+
--hash=sha256:c28b2fdcee797e1c1961cd3bcd3d545cab22ad202c846235197935e1df2f8ef7 \
|
| 1449 |
+
--hash=sha256:c4dcb4120d0cc3cc448624147dba64e9021b278c63e34a38789b688fd0da9bf3 \
|
| 1450 |
+
--hash=sha256:dbd2ecfbfee70bc1a4acb7461fa6af7748ec2ab08ac0fa298f281c51518f982c
|
| 1451 |
+
# via datasets
|
| 1452 |
+
yarl==1.20.0 \
|
| 1453 |
+
--hash=sha256:077989b09ffd2f48fb2d8f6a86c5fef02f63ffe6b1dd4824c76de7bb01e4f2e2 \
|
| 1454 |
+
--hash=sha256:0a6a1e6ae21cdd84011c24c78d7a126425148b24d437b5702328e4ba640a8902 \
|
| 1455 |
+
--hash=sha256:0acfaf1da020253f3533526e8b7dd212838fdc4109959a2c53cafc6db611bff2 \
|
| 1456 |
+
--hash=sha256:40ed574b4df723583a26c04b298b283ff171bcc387bc34c2683235e2487a65a5 \
|
| 1457 |
+
--hash=sha256:5d0fe6af927a47a230f31e6004621fd0959eaa915fc62acfafa67ff7229a3124 \
|
| 1458 |
+
--hash=sha256:634b7ba6b4a85cf67e9df7c13a7fb2e44fa37b5d34501038d174a63eaac25ee2 \
|
| 1459 |
+
--hash=sha256:686d51e51ee5dfe62dec86e4866ee0e9ed66df700d55c828a615640adc885307 \
|
| 1460 |
+
--hash=sha256:6d409e321e4addf7d97ee84162538c7258e53792eb7c6defd0c33647d754172e \
|
| 1461 |
+
--hash=sha256:86de313371ec04dd2531f30bc41a5a1a96f25a02823558ee0f2af0beaa7ca791 \
|
| 1462 |
+
--hash=sha256:8c12cd754d9dbd14204c328915e23b0c361b88f3cffd124129955e60a4fbfcfb \
|
| 1463 |
+
--hash=sha256:a0bc5e05f457b7c1994cc29e83b58f540b76234ba6b9648a4971ddc7f6aa52da \
|
| 1464 |
+
--hash=sha256:b4230ac0b97ec5eeb91d96b324d66060a43fd0d2a9b603e3327ed65f084e41f8 \
|
| 1465 |
+
--hash=sha256:c8703517b924463994c344dcdf99a2d5ce9eca2b6882bb640aa555fb5efc706a \
|
| 1466 |
+
--hash=sha256:c9471ca18e6aeb0e03276b5e9b27b14a54c052d370a9c0c04a68cefbd1455eb4 \
|
| 1467 |
+
--hash=sha256:db243357c6c2bf3cd7e17080034ade668d54ce304d820c2a58514a4e51d0cfd6 \
|
| 1468 |
+
--hash=sha256:dd59c9dd58ae16eaa0f48c3d0cbe6be8ab4dc7247c3ff7db678edecbaf59327f \
|
| 1469 |
+
--hash=sha256:ea52f7328a36960ba3231c6677380fa67811b414798a6e071c7085c57b6d20a9 \
|
| 1470 |
+
--hash=sha256:eaddd7804d8e77d67c28d154ae5fab203163bd0998769569861258e525039d2a \
|
| 1471 |
+
--hash=sha256:fdb5204d17cb32b2de2d1e21c7461cabfacf17f3645e4b9039f210c5d3378bf3
|
| 1472 |
+
# via aiohttp
|
| 1473 |
+
zss==1.2.0 \
|
| 1474 |
+
--hash=sha256:07bb937441929ccb82961f4f7b80fbce9e2b20d0e46ddcbcbc1fcb094f585b50
|
| 1475 |
+
# via donut-python
|
tools/schema_gemini.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "extract_menu_data",
|
| 3 |
+
"description": "Extract structured menu information from images.",
|
| 4 |
+
"parameters": {
|
| 5 |
+
"type": "object",
|
| 6 |
+
"properties": {
|
| 7 |
+
"restaurant": {
|
| 8 |
+
"type": "string",
|
| 9 |
+
"description": "Name of the restaurant. If the name is not available, it should be ''."
|
| 10 |
+
},
|
| 11 |
+
"address": {
|
| 12 |
+
"type": "string",
|
| 13 |
+
"description": "Address of the restaurant. If the address is not available, it should be ''."
|
| 14 |
+
},
|
| 15 |
+
"phone": {
|
| 16 |
+
"type": "string",
|
| 17 |
+
"description": "Phone number of the restaurant. If the phone number is not available, it should be ''."
|
| 18 |
+
},
|
| 19 |
+
"business_hours": {
|
| 20 |
+
"type": "string",
|
| 21 |
+
"description": "Business hours of the restaurant. If the business hours are not available, it should be ''."
|
| 22 |
+
},
|
| 23 |
+
"dishes": {
|
| 24 |
+
"type": "array",
|
| 25 |
+
"items": {
|
| 26 |
+
"type": "object",
|
| 27 |
+
"properties": {
|
| 28 |
+
"name": {
|
| 29 |
+
"type": "string",
|
| 30 |
+
"description": "Name of the menu item."
|
| 31 |
+
},
|
| 32 |
+
"price": {
|
| 33 |
+
"type": "string",
|
| 34 |
+
"description": "Price of the menu item. If the price is not available, it should be -1."
|
| 35 |
+
}
|
| 36 |
+
},
|
| 37 |
+
"required": ["name", "price"]
|
| 38 |
+
},
|
| 39 |
+
"description": "List of menu dishes item."
|
| 40 |
+
}
|
| 41 |
+
},
|
| 42 |
+
"required": ["restaurant", "address", "phone", "business_hours", "dishes"]
|
| 43 |
+
}
|
| 44 |
+
}
|
tools/schema_openai.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"type": "function",
|
| 3 |
+
"name": "extract_menu_data",
|
| 4 |
+
"description": "Extract structured menu information from images.",
|
| 5 |
+
"parameters": {
|
| 6 |
+
"type": "object",
|
| 7 |
+
"properties": {
|
| 8 |
+
"restaurant": {
|
| 9 |
+
"type": "string",
|
| 10 |
+
"description": "Name of the restaurant. If the name is not available, it should be ''."
|
| 11 |
+
},
|
| 12 |
+
"address": {
|
| 13 |
+
"type": "string",
|
| 14 |
+
"description": "Address of the restaurant. If the address is not available, it should be ''."
|
| 15 |
+
},
|
| 16 |
+
"phone": {
|
| 17 |
+
"type": "string",
|
| 18 |
+
"description": "Phone number of the restaurant. If the phone number is not available, it should be ''."
|
| 19 |
+
},
|
| 20 |
+
"business_hours": {
|
| 21 |
+
"type": "string",
|
| 22 |
+
"description": "Business hours of the restaurant. If the business hours are not available, it should be ''."
|
| 23 |
+
},
|
| 24 |
+
"dishes": {
|
| 25 |
+
"type": "array",
|
| 26 |
+
"items": {
|
| 27 |
+
"type": "object",
|
| 28 |
+
"properties": {
|
| 29 |
+
"name": {
|
| 30 |
+
"type": "string",
|
| 31 |
+
"description": "Name of the menu item."
|
| 32 |
+
},
|
| 33 |
+
"price": {
|
| 34 |
+
"type": "string",
|
| 35 |
+
"description": "Price of the menu item. If the price is not available, it should be -1."
|
| 36 |
+
}
|
| 37 |
+
},
|
| 38 |
+
"required": ["name", "price"],
|
| 39 |
+
"additionalProperties": false
|
| 40 |
+
},
|
| 41 |
+
"description": "List of menu dishes item."
|
| 42 |
+
}
|
| 43 |
+
},
|
| 44 |
+
"required": ["restaurant", "address", "phone", "business_hours", "dishes"],
|
| 45 |
+
"additionalProperties": false
|
| 46 |
+
}
|
| 47 |
+
}
|
train.ipynb
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cells": [
|
| 3 |
+
{
|
| 4 |
+
"cell_type": "markdown",
|
| 5 |
+
"metadata": {},
|
| 6 |
+
"source": [
|
| 7 |
+
"# Login to HuggingFace (just login once)"
|
| 8 |
+
]
|
| 9 |
+
},
|
| 10 |
+
{
|
| 11 |
+
"cell_type": "code",
|
| 12 |
+
"execution_count": null,
|
| 13 |
+
"metadata": {},
|
| 14 |
+
"outputs": [],
|
| 15 |
+
"source": [
|
| 16 |
+
"from huggingface_hub import interpreter_login\n",
|
| 17 |
+
"interpreter_login()"
|
| 18 |
+
]
|
| 19 |
+
},
|
| 20 |
+
{
|
| 21 |
+
"cell_type": "markdown",
|
| 22 |
+
"metadata": {},
|
| 23 |
+
"source": [
|
| 24 |
+
"# Collect Menu Image Datasets\n",
|
| 25 |
+
"- Use `metadata.jsonl` to label the images's ground truth. You can visit [here](https://github.com/ryanlinjui/menu-text-detection/tree/main/examples) to see the examples.\n",
|
| 26 |
+
"- After finishing, push to HuggingFace Datasets.\n",
|
| 27 |
+
"- For labeling:\n",
|
| 28 |
+
" - [Google AI Studio](https://aistudio.google.com) or [OpenAI ChatGPT](https://chatgpt.com).\n",
|
| 29 |
+
" - Use function calling by API. Start the gradio app locally or visit [here](https://huggingface.co/spaces/ryanlinjui/menu-text-detection).\n",
|
| 30 |
+
"\n",
|
| 31 |
+
"### Menu Type\n",
|
| 32 |
+
"- **h**: horizontal menu\n",
|
| 33 |
+
"- **v**: vertical menu\n",
|
| 34 |
+
"- **d**: document-style menu\n",
|
| 35 |
+
"- **s**: in-scene menu (non-document style)\n",
|
| 36 |
+
"- **i**: irregular menu (menu with irregular text layout)\n",
|
| 37 |
+
"\n",
|
| 38 |
+
"> Please see the [examples](https://github.com/ryanlinjui/menu-text-detection/tree/main/examples) for more details."
|
| 39 |
+
]
|
| 40 |
+
},
|
| 41 |
+
{
|
| 42 |
+
"cell_type": "code",
|
| 43 |
+
"execution_count": null,
|
| 44 |
+
"metadata": {},
|
| 45 |
+
"outputs": [],
|
| 46 |
+
"source": [
|
| 47 |
+
"import os\n",
|
| 48 |
+
"import json\n",
|
| 49 |
+
"\n",
|
| 50 |
+
"import numpy as np\n",
|
| 51 |
+
"from PIL import Image\n",
|
| 52 |
+
"from pillow_heif import register_heif_opener\n",
|
| 53 |
+
"\n",
|
| 54 |
+
"from menu.llm import (\n",
|
| 55 |
+
" GeminiAPI,\n",
|
| 56 |
+
" OpenAIAPI\n",
|
| 57 |
+
")\n",
|
| 58 |
+
"\n",
|
| 59 |
+
"IMAGE_DIR = \"datasets/images\" # set your image directory here\n",
|
| 60 |
+
"SELECTED_MODEL = \"gemini-2.5-flash\" # set model name here, refer MODEL_LIST from app.py for more\n",
|
| 61 |
+
"API_TOKEN = \"\" # set your API token here\n",
|
| 62 |
+
"SELECTED_FUNCTION = GeminiAPI # set \"GeminiAPI\" or \"OpenAIAPI\"\n",
|
| 63 |
+
"\n",
|
| 64 |
+
"register_heif_opener()\n",
|
| 65 |
+
"\n",
|
| 66 |
+
"for file in os.listdir(IMAGE_DIR):\n",
|
| 67 |
+
" print(f\"Processing image: {file}\")\n",
|
| 68 |
+
" try:\n",
|
| 69 |
+
" image = np.array(Image.open(os.path.join(IMAGE_DIR, file)))\n",
|
| 70 |
+
" data = {\n",
|
| 71 |
+
" \"file_name\": file,\n",
|
| 72 |
+
" \"menu\": SELECTED_FUNCTION.call(image, SELECTED_MODEL, API_TOKEN)\n",
|
| 73 |
+
" }\n",
|
| 74 |
+
" with open(os.path.join(IMAGE_DIR, \"metadata.jsonl\"), \"a\", encoding=\"utf-8\") as metaf:\n",
|
| 75 |
+
" metaf.write(json.dumps(data, ensure_ascii=False, sort_keys=True) + \"\\n\")\n",
|
| 76 |
+
" except Exception as e:\n",
|
| 77 |
+
" print(f\"Skipping invalid image '{file}': {e}\")\n",
|
| 78 |
+
" continue"
|
| 79 |
+
]
|
| 80 |
+
},
|
| 81 |
+
{
|
| 82 |
+
"cell_type": "markdown",
|
| 83 |
+
"metadata": {},
|
| 84 |
+
"source": [
|
| 85 |
+
"# Push Datasets to HuggingFace"
|
| 86 |
+
]
|
| 87 |
+
},
|
| 88 |
+
{
|
| 89 |
+
"cell_type": "code",
|
| 90 |
+
"execution_count": null,
|
| 91 |
+
"metadata": {},
|
| 92 |
+
"outputs": [],
|
| 93 |
+
"source": [
|
| 94 |
+
"from datasets import load_dataset\n",
|
| 95 |
+
"\n",
|
| 96 |
+
"dataset = load_dataset(path=\"datasets/menu-zh-TW\") # load dataset from the local directory including the metadata.jsonl, images files.\n",
|
| 97 |
+
"dataset.push_to_hub(repo_id=\"ryanlinjui/menu-zh-TW\") # push to the huggingface dataset hub"
|
| 98 |
+
]
|
| 99 |
+
},
|
| 100 |
+
{
|
| 101 |
+
"cell_type": "markdown",
|
| 102 |
+
"metadata": {},
|
| 103 |
+
"source": [
|
| 104 |
+
"# Prepare the dataset for training"
|
| 105 |
+
]
|
| 106 |
+
},
|
| 107 |
+
{
|
| 108 |
+
"cell_type": "code",
|
| 109 |
+
"execution_count": null,
|
| 110 |
+
"metadata": {},
|
| 111 |
+
"outputs": [],
|
| 112 |
+
"source": [
|
| 113 |
+
"from menu.utils import split_dataset\n",
|
| 114 |
+
"from datasets import load_dataset\n",
|
| 115 |
+
"\n",
|
| 116 |
+
"dataset = load_dataset(path=\"ryanlinjui/menu-zh-TW\") # set your dataset repo id for training\n",
|
| 117 |
+
"dataset = split_dataset(dataset[\"train\"], train=0.8, validation=0.1, test=0.1, seed=42) # (optional) use it if your dataset is not split into train/validation/test\n",
|
| 118 |
+
"print(f\"Dataset split: {len(dataset['train'])} train, {len(dataset['validation'])} validation, {len(dataset['test'])} test\")"
|
| 119 |
+
]
|
| 120 |
+
},
|
| 121 |
+
{
|
| 122 |
+
"cell_type": "markdown",
|
| 123 |
+
"metadata": {},
|
| 124 |
+
"source": [
|
| 125 |
+
"# Fine-tune Donut Model"
|
| 126 |
+
]
|
| 127 |
+
},
|
| 128 |
+
{
|
| 129 |
+
"cell_type": "code",
|
| 130 |
+
"execution_count": null,
|
| 131 |
+
"metadata": {},
|
| 132 |
+
"outputs": [],
|
| 133 |
+
"source": [
|
| 134 |
+
"import logging\n",
|
| 135 |
+
"from menu.donut import DonutTrainer\n",
|
| 136 |
+
"\n",
|
| 137 |
+
"logging.getLogger(\"transformers\").setLevel(logging.ERROR) # filter output message from transformers\n",
|
| 138 |
+
"\n",
|
| 139 |
+
"DonutTrainer.train(\n",
|
| 140 |
+
" dataset=dataset,\n",
|
| 141 |
+
" pretrained_model_repo_id=\"naver-clova-ix/donut-base\", # set your pretrained model repo id for fine-tuning\n",
|
| 142 |
+
" ground_truth_key=\"menu\", # set your ground truth key for training\n",
|
| 143 |
+
" huggingface_model_id=\"ryanlinjui/donut-base-finetuned-menu\", # set your huggingface model repo id for saving / pushing to the hub\n",
|
| 144 |
+
" epochs=15, # set your training epochs\n",
|
| 145 |
+
" train_batch_size=8, # set your training batch size\n",
|
| 146 |
+
" val_batch_size=1, # set your validation batch size\n",
|
| 147 |
+
" learning_rate=3e-5, # set your learning rate\n",
|
| 148 |
+
" val_check_interval=0.5, # how many times we want to validate during an epoch\n",
|
| 149 |
+
" check_val_every_n_epoch=1, # how many epochs we want to validate\n",
|
| 150 |
+
" gradient_clip_val=1.0, # gradient clipping value for training stability\n",
|
| 151 |
+
" num_training_samples_per_epoch=198, # set num_training_samples_per_epoch = training set size\n",
|
| 152 |
+
" num_nodes=1, # number of nodes for distributed training\n",
|
| 153 |
+
" warmup_steps=75 # number of warmup steps for learning rate scheduler, 198/8*30/10, 10%\n",
|
| 154 |
+
")"
|
| 155 |
+
]
|
| 156 |
+
},
|
| 157 |
+
{
|
| 158 |
+
"cell_type": "markdown",
|
| 159 |
+
"metadata": {},
|
| 160 |
+
"source": [
|
| 161 |
+
"# Evaluate Donut Model"
|
| 162 |
+
]
|
| 163 |
+
},
|
| 164 |
+
{
|
| 165 |
+
"cell_type": "code",
|
| 166 |
+
"execution_count": null,
|
| 167 |
+
"metadata": {},
|
| 168 |
+
"outputs": [],
|
| 169 |
+
"source": [
|
| 170 |
+
"import json\n",
|
| 171 |
+
"from datasets import load_dataset\n",
|
| 172 |
+
"\n",
|
| 173 |
+
"from menu.utils import split_dataset\n",
|
| 174 |
+
"from menu.donut import DonutFinetuned\n",
|
| 175 |
+
"\n",
|
| 176 |
+
"dataset = load_dataset(\"ryanlinjui/menu-zh-TW\")\n",
|
| 177 |
+
"dataset = split_dataset(dataset[\"train\"], train=0.8, validation=0.1, test=0.1, seed=42) # (optional) use it if your dataset is not split into train/validation/test\n",
|
| 178 |
+
"donut_finetuned = DonutFinetuned(pretrained_model_repo_id=\"ryanlinjui/donut-base-finetuned-menu\")\n",
|
| 179 |
+
"scores, output_list = donut_finetuned.evaluate(dataset=dataset[\"test\"], ground_truth_key=\"menu\")\n",
|
| 180 |
+
"\n",
|
| 181 |
+
"print(\"Evaluation scores:\")\n",
|
| 182 |
+
"for key, value in scores.items():\n",
|
| 183 |
+
" print(f\"{key}: {value}\")\n",
|
| 184 |
+
"\n",
|
| 185 |
+
"print(\"\\nSample outputs:\")\n",
|
| 186 |
+
"for output in output_list[:5]:\n",
|
| 187 |
+
" print(json.dumps(output, ensure_ascii=False, indent=4))"
|
| 188 |
+
]
|
| 189 |
+
},
|
| 190 |
+
{
|
| 191 |
+
"cell_type": "markdown",
|
| 192 |
+
"metadata": {},
|
| 193 |
+
"source": [
|
| 194 |
+
"# Test Donut Model"
|
| 195 |
+
]
|
| 196 |
+
},
|
| 197 |
+
{
|
| 198 |
+
"cell_type": "code",
|
| 199 |
+
"execution_count": null,
|
| 200 |
+
"metadata": {},
|
| 201 |
+
"outputs": [],
|
| 202 |
+
"source": [
|
| 203 |
+
"from PIL import Image\n",
|
| 204 |
+
"from menu.donut import DonutFinetuned\n",
|
| 205 |
+
"\n",
|
| 206 |
+
"image = Image.open(\"./examples/menu-hd.jpg\")\n",
|
| 207 |
+
"\n",
|
| 208 |
+
"donut_finetuned = DonutFinetuned(pretrained_model_repo_id=\"ryanlinjui/donut-base-finetuned-menu\")\n",
|
| 209 |
+
"outputs = donut_finetuned.predict(image=image)\n",
|
| 210 |
+
"print(outputs)"
|
| 211 |
+
]
|
| 212 |
+
}
|
| 213 |
+
],
|
| 214 |
+
"metadata": {
|
| 215 |
+
"kernelspec": {
|
| 216 |
+
"display_name": "menu-text-detection",
|
| 217 |
+
"language": "python",
|
| 218 |
+
"name": "python3"
|
| 219 |
+
},
|
| 220 |
+
"language_info": {
|
| 221 |
+
"codemirror_mode": {
|
| 222 |
+
"name": "ipython",
|
| 223 |
+
"version": 3
|
| 224 |
+
},
|
| 225 |
+
"file_extension": ".py",
|
| 226 |
+
"mimetype": "text/x-python",
|
| 227 |
+
"name": "python",
|
| 228 |
+
"nbconvert_exporter": "python",
|
| 229 |
+
"pygments_lexer": "ipython3",
|
| 230 |
+
"version": "3.11.12"
|
| 231 |
+
}
|
| 232 |
+
},
|
| 233 |
+
"nbformat": 4,
|
| 234 |
+
"nbformat_minor": 2
|
| 235 |
+
}
|
uv.lock
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|