Svngoku Oz commited on
Commit
e79f3c0
·
verified ·
1 Parent(s): 57cacdc

feat: add Hugging Face OAuth

Browse files

Chrys-assisted

Summary:
- Enable Gradio Sign in with Hugging Face for the Space.
- Use scoped visitor OAuth tokens for dataset creation and updates.
- Install Gradio OAuth support through the locked uv environment.

Validation:
- uv sync --frozen
- Python compile and OAuth behavior smoke checks
- uv lock --check
- uv build

Conversation: https://app.warp.dev/conversation/f2ab5d06-489f-47ae-abd7-e9eced4d755f

Co-Authored-By: Oz <oz-agent@warp.dev>

Files changed (6) hide show
  1. .gitignore +6 -0
  2. README.md +4 -0
  3. app.py +21 -19
  4. pyproject.toml +30 -0
  5. requirements.txt +0 -14
  6. uv.lock +0 -0
.gitignore ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ .env
2
+ __pycache__/
3
+ *.pyc
4
+ .venv/
5
+ dist/
6
+ *.egg-info/
README.md CHANGED
@@ -7,6 +7,10 @@ sdk: gradio
7
  sdk_version: 5.20.1
8
  app_file: app.py
9
  pinned: false
 
 
 
 
10
  ---
11
 
12
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
7
  sdk_version: 5.20.1
8
  app_file: app.py
9
  pinned: false
10
+ hf_oauth: true
11
+ hf_oauth_scopes:
12
+ - contribute-repos
13
+ - write-repos
14
  ---
15
 
16
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py CHANGED
@@ -18,7 +18,7 @@ from datasets.features import Image as HFImage
18
  from huggingface_hub import HfApi, get_token
19
  import huggingface_hub
20
  import os
21
- from mistralai.client import Mistral
22
  import fitz # pymupdf
23
  from PIL import Image
24
  import io
@@ -933,7 +933,7 @@ def get_hf_token(explicit_token: str | None = None) -> str | None:
933
  def process_files(
934
  file_paths: list[str],
935
  chunk_size: int,
936
- hf_token: str,
937
  repo_name: str,
938
  append_mode: bool = False,
939
  min_chunk_chars: int = 20,
@@ -975,7 +975,7 @@ def process_files(
975
  return (
976
  "Error: No valid Hugging Face token found.\n"
977
  "Please either:\n"
978
- "1. Provide a token in the input field (starts with 'hf_')\n"
979
  "2. Set HF_TOKEN environment variable\n"
980
  "3. Run `huggingface-cli login` in your terminal"
981
  )
@@ -1356,9 +1356,17 @@ else:
1356
 
1357
 
1358
  def _gradio_process(
1359
- file_objs, chunk_size, hf_token, repo_name, append_mode, min_chars, min_words
1360
- ):
1361
- """Bridge between Gradio file objects and core processing logic."""
 
 
 
 
 
 
 
 
1362
  if not file_objs:
1363
  return "Error: No files uploaded."
1364
  if not isinstance(file_objs, list):
@@ -1367,7 +1375,7 @@ def _gradio_process(
1367
  return process_files(
1368
  file_paths,
1369
  chunk_size,
1370
- hf_token,
1371
  repo_name,
1372
  append_mode=append_mode,
1373
  min_chunk_chars=min_chars,
@@ -1427,15 +1435,11 @@ with gr.Blocks(**GRADIO_BLOCKS_KWARGS) as demo:
1427
 
1428
  with gr.Group(elem_classes=["mistral-section"]):
1429
  gr.Markdown("### Hugging Face output")
 
1430
  repo_name = gr.Textbox(
1431
  label="Dataset repository",
1432
  placeholder="your-username/your-dataset-name",
1433
  )
1434
- hf_token = gr.Textbox(
1435
- label="Hugging Face token",
1436
- type="password",
1437
- placeholder="hf_... or set HF_TOKEN",
1438
- )
1439
  append_mode = gr.Checkbox(
1440
  label="Append to existing dataset",
1441
  value=False,
@@ -1465,7 +1469,7 @@ with gr.Blocks(**GRADIO_BLOCKS_KWARGS) as demo:
1465
  )
1466
 
1467
  gr.Markdown(
1468
- "*Requires `MISTRAL_API_KEY`, a Hugging Face token, or an active Hugging Face CLI login.*",
1469
  elem_classes=["mistral-note"],
1470
  )
1471
 
@@ -1480,7 +1484,6 @@ with gr.Blocks(**GRADIO_BLOCKS_KWARGS) as demo:
1480
  inputs=[
1481
  file_input,
1482
  chunk_size,
1483
- hf_token,
1484
  repo_name,
1485
  append_mode,
1486
  min_chars,
@@ -1491,14 +1494,13 @@ with gr.Blocks(**GRADIO_BLOCKS_KWARGS) as demo:
1491
 
1492
  gr.Examples(
1493
  examples=[
1494
- [None, 512, "", "hf-username/my-first-ocr-dataset", False, 20, 3],
1495
- [None, 1024, "", "hf-username/large-chunk-ocr-data", True, 50, 5],
1496
- [None, 0, "", "hf-username/no-split-ocr-data", False, 0, 0],
1497
  ],
1498
  inputs=[
1499
  file_input,
1500
  chunk_size,
1501
- hf_token,
1502
  repo_name,
1503
  append_mode,
1504
  min_chars,
@@ -1520,4 +1522,4 @@ def main():
1520
 
1521
 
1522
  if __name__ == "__main__":
1523
- main()
 
18
  from huggingface_hub import HfApi, get_token
19
  import huggingface_hub
20
  import os
21
+ from mistralai import Mistral
22
  import fitz # pymupdf
23
  from PIL import Image
24
  import io
 
933
  def process_files(
934
  file_paths: list[str],
935
  chunk_size: int,
936
+ hf_token: str | None,
937
  repo_name: str,
938
  append_mode: bool = False,
939
  min_chunk_chars: int = 20,
 
975
  return (
976
  "Error: No valid Hugging Face token found.\n"
977
  "Please either:\n"
978
+ "1. Sign in with Hugging Face when using the Space\n"
979
  "2. Set HF_TOKEN environment variable\n"
980
  "3. Run `huggingface-cli login` in your terminal"
981
  )
 
1356
 
1357
 
1358
  def _gradio_process(
1359
+ file_objs: list[str] | str | None,
1360
+ chunk_size: int,
1361
+ repo_name: str,
1362
+ append_mode: bool,
1363
+ min_chars: int,
1364
+ min_words: int,
1365
+ oauth_token: gr.OAuthToken | None,
1366
+ ) -> str:
1367
+ """Bridge between Gradio inputs, the signed-in user, and core processing."""
1368
+ if oauth_token is None:
1369
+ return "Error: Sign in with Hugging Face before processing files."
1370
  if not file_objs:
1371
  return "Error: No files uploaded."
1372
  if not isinstance(file_objs, list):
 
1375
  return process_files(
1376
  file_paths,
1377
  chunk_size,
1378
+ oauth_token.token,
1379
  repo_name,
1380
  append_mode=append_mode,
1381
  min_chunk_chars=min_chars,
 
1435
 
1436
  with gr.Group(elem_classes=["mistral-section"]):
1437
  gr.Markdown("### Hugging Face output")
1438
+ gr.LoginButton()
1439
  repo_name = gr.Textbox(
1440
  label="Dataset repository",
1441
  placeholder="your-username/your-dataset-name",
1442
  )
 
 
 
 
 
1443
  append_mode = gr.Checkbox(
1444
  label="Append to existing dataset",
1445
  value=False,
 
1469
  )
1470
 
1471
  gr.Markdown(
1472
+ "*Requires `MISTRAL_API_KEY`. Sign in with Hugging Face before pushing a dataset.*",
1473
  elem_classes=["mistral-note"],
1474
  )
1475
 
 
1484
  inputs=[
1485
  file_input,
1486
  chunk_size,
 
1487
  repo_name,
1488
  append_mode,
1489
  min_chars,
 
1494
 
1495
  gr.Examples(
1496
  examples=[
1497
+ [None, 512, "hf-username/my-first-ocr-dataset", False, 20, 3],
1498
+ [None, 1024, "hf-username/large-chunk-ocr-data", True, 50, 5],
1499
+ [None, 0, "hf-username/no-split-ocr-data", False, 0, 0],
1500
  ],
1501
  inputs=[
1502
  file_input,
1503
  chunk_size,
 
1504
  repo_name,
1505
  append_mode,
1506
  min_chars,
 
1522
 
1523
 
1524
  if __name__ == "__main__":
1525
+ main()
pyproject.toml ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [project]
2
+ name = "pdf2dataset"
3
+ version = "0.1.0"
4
+ description = "Convert PDF and image files into structured Hugging Face datasets using Mistral OCR"
5
+ readme = "README.md"
6
+ requires-python = ">=3.10"
7
+ license = { text = "MIT" }
8
+
9
+ dependencies = [
10
+ "gradio[oauth]>=5.20.1",
11
+ "datasets>=3.0.0",
12
+ "huggingface_hub>=0.25.0",
13
+ "mistralai>=1.0.0",
14
+ "pillow>=10.0.0",
15
+ "chonkie>=1.0.0",
16
+ "jsonschema>=4.0.0",
17
+ "python-dotenv>=1.2.1",
18
+ "pymupdf>=1.24.0",
19
+ ]
20
+
21
+ [project.scripts]
22
+ pdf2dataset = "app:main"
23
+
24
+ [tool.hatch.build.targets.wheel]
25
+ packages = ["."]
26
+ only-include = ["app.py"]
27
+
28
+ [build-system]
29
+ requires = ["hatchling"]
30
+ build-backend = "hatchling.build"
requirements.txt DELETED
@@ -1,14 +0,0 @@
1
- gradio>=5.20.1
2
- datasets>=3.0.0
3
- huggingface_hub>=0.25.0
4
- mistralai>=1.0.0
5
- pillow>=10.0.0
6
- chonkie>=1.0.0
7
- jsonschema>=4.0.0
8
- python-dotenv>=1.2.1
9
- pymupdf>=1.24.0
10
- langchain
11
- langchain-community
12
- langchain-openai
13
- fastapi
14
- python-multipart
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
uv.lock ADDED
The diff for this file is too large to render. See raw diff