docfgp 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- docfgp-0.1.0/.gitignore +10 -0
- docfgp-0.1.0/LICENSE +21 -0
- docfgp-0.1.0/PKG-INFO +84 -0
- docfgp-0.1.0/README.md +60 -0
- docfgp-0.1.0/docs/applications.md +30 -0
- docfgp-0.1.0/docs/evaluation.md +55 -0
- docfgp-0.1.0/docs/methodology.md +65 -0
- docfgp-0.1.0/pyproject.toml +49 -0
- docfgp-0.1.0/scripts/__init__.py +1 -0
- docfgp-0.1.0/scripts/_evaluation.py +342 -0
- docfgp-0.1.0/scripts/evaluate_office.py +54 -0
- docfgp-0.1.0/scripts/evaluate_rvl_cdip.py +129 -0
- docfgp-0.1.0/src/docfgp/__init__.py +6 -0
- docfgp-0.1.0/src/docfgp/cli.py +49 -0
- docfgp-0.1.0/src/docfgp/extract.py +274 -0
- docfgp-0.1.0/src/docfgp/fingerprint.py +288 -0
- docfgp-0.1.0/src/docfgp/minhash.py +81 -0
- docfgp-0.1.0/src/docfgp/normalize.py +49 -0
- docfgp-0.1.0/src/docfgp/ocr.py +111 -0
- docfgp-0.1.0/src/docfgp/py.typed +0 -0
- docfgp-0.1.0/src/docfgp/schemas.py +222 -0
- docfgp-0.1.0/src/docfgp/visual.py +72 -0
- docfgp-0.1.0/src/docfgp/winnowing.py +32 -0
- docfgp-0.1.0/tests/test_algorithms.py +64 -0
- docfgp-0.1.0/tests/test_end_to_end.py +210 -0
- docfgp-0.1.0/tests/test_evaluators.py +51 -0
docfgp-0.1.0/.gitignore
ADDED
docfgp-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Zices
|
|
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.
|
docfgp-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: docfgp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Generate deterministic fingerprints for documents
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Keywords: document,fingerprint,minhash,pdf
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Requires-Python: >=3.11
|
|
11
|
+
Requires-Dist: pillow<14,>=10
|
|
12
|
+
Requires-Dist: pypdfium2<6,>=4.30
|
|
13
|
+
Provides-Extra: benchmark
|
|
14
|
+
Requires-Dist: datasets<5,>=3; extra == 'benchmark'
|
|
15
|
+
Requires-Dist: psutil>=6; extra == 'benchmark'
|
|
16
|
+
Provides-Extra: dev
|
|
17
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
18
|
+
Requires-Dist: mypy>=1.15; extra == 'dev'
|
|
19
|
+
Requires-Dist: psutil>=6; extra == 'dev'
|
|
20
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
21
|
+
Requires-Dist: reportlab>=4; extra == 'dev'
|
|
22
|
+
Requires-Dist: ruff>=0.11; extra == 'dev'
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# DocFGP
|
|
26
|
+
|
|
27
|
+
[](https://pypi.org/project/docfgp/)
|
|
28
|
+
[](https://pepy.tech/projects/docfgp)
|
|
29
|
+
[](https://github.com/iamzices/docfgp-document-fingerprint/actions/workflows/ci.yml)
|
|
30
|
+
[](LICENSE)
|
|
31
|
+
|
|
32
|
+
DocFGP creates text and visual fingerprints for finding duplicates, near-duplicates, and shared passages across document formats.
|
|
33
|
+
|
|
34
|
+
## Features
|
|
35
|
+
|
|
36
|
+
- PDF, DOCX, PPTX, PNG, JPEG, TIFF, BMP, and WebP support
|
|
37
|
+
- Exact, near-duplicate, and partial-match
|
|
38
|
+
- OCR and visual fingerprints for scanned documents
|
|
39
|
+
|
|
40
|
+
## Requirements
|
|
41
|
+
|
|
42
|
+
- Python 3.11+
|
|
43
|
+
- [office2pdf](https://github.com/developer0hye/office2pdf)
|
|
44
|
+
- [Tesseract 5](https://github.com/tesseract-ocr/tesseract)
|
|
45
|
+
|
|
46
|
+
## Installation
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install docfgp
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Python API
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from docfgp import Fingerprinter
|
|
56
|
+
|
|
57
|
+
fingerprint = Fingerprinter().fingerprint("report.pdf")
|
|
58
|
+
record = fingerprint.to_dict()
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
| Field | Description |
|
|
62
|
+
| --- | --- |
|
|
63
|
+
| `schema_version` | Fingerprint data format version |
|
|
64
|
+
| `algorithm_version` | Feature-generation version |
|
|
65
|
+
| `source_format` | Detected input format |
|
|
66
|
+
| `byte_size` | Original file size in bytes |
|
|
67
|
+
| `page_count` | Number of pages or image frames |
|
|
68
|
+
| `exact_hashes` | Raw and canonical-text SHA-256 hashes |
|
|
69
|
+
| `lookup_keys` | Word, character, passage, and visual candidate keys |
|
|
70
|
+
| `minhash` | Word-shingle MinHash sketch |
|
|
71
|
+
| `char_minhash` | Character-shingle MinHash sketch |
|
|
72
|
+
| `shingle_counts` | Hashed five-word shingle occurrence counts |
|
|
73
|
+
| `shingle_total` | Total five-word shingle occurrences |
|
|
74
|
+
| `shingle_unique` | Distinct five-word shingle hashes |
|
|
75
|
+
| `passage_anchors` | Selected passage fingerprints |
|
|
76
|
+
| `page_hashes` | Per-page visual hashes and lookup keys |
|
|
77
|
+
| `quality` | Evidence status, page provenance, and warnings |
|
|
78
|
+
| `parameters` | Parameters used to construct the fingerprint |
|
|
79
|
+
|
|
80
|
+
## CLI
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
docfgp report.pdf > report.fingerprint.json
|
|
84
|
+
```
|
docfgp-0.1.0/README.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# DocFGP
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/docfgp/)
|
|
4
|
+
[](https://pepy.tech/projects/docfgp)
|
|
5
|
+
[](https://github.com/iamzices/docfgp-document-fingerprint/actions/workflows/ci.yml)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
DocFGP creates text and visual fingerprints for finding duplicates, near-duplicates, and shared passages across document formats.
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- PDF, DOCX, PPTX, PNG, JPEG, TIFF, BMP, and WebP support
|
|
13
|
+
- Exact, near-duplicate, and partial-match
|
|
14
|
+
- OCR and visual fingerprints for scanned documents
|
|
15
|
+
|
|
16
|
+
## Requirements
|
|
17
|
+
|
|
18
|
+
- Python 3.11+
|
|
19
|
+
- [office2pdf](https://github.com/developer0hye/office2pdf)
|
|
20
|
+
- [Tesseract 5](https://github.com/tesseract-ocr/tesseract)
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pip install docfgp
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Python API
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
from docfgp import Fingerprinter
|
|
32
|
+
|
|
33
|
+
fingerprint = Fingerprinter().fingerprint("report.pdf")
|
|
34
|
+
record = fingerprint.to_dict()
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
| Field | Description |
|
|
38
|
+
| --- | --- |
|
|
39
|
+
| `schema_version` | Fingerprint data format version |
|
|
40
|
+
| `algorithm_version` | Feature-generation version |
|
|
41
|
+
| `source_format` | Detected input format |
|
|
42
|
+
| `byte_size` | Original file size in bytes |
|
|
43
|
+
| `page_count` | Number of pages or image frames |
|
|
44
|
+
| `exact_hashes` | Raw and canonical-text SHA-256 hashes |
|
|
45
|
+
| `lookup_keys` | Word, character, passage, and visual candidate keys |
|
|
46
|
+
| `minhash` | Word-shingle MinHash sketch |
|
|
47
|
+
| `char_minhash` | Character-shingle MinHash sketch |
|
|
48
|
+
| `shingle_counts` | Hashed five-word shingle occurrence counts |
|
|
49
|
+
| `shingle_total` | Total five-word shingle occurrences |
|
|
50
|
+
| `shingle_unique` | Distinct five-word shingle hashes |
|
|
51
|
+
| `passage_anchors` | Selected passage fingerprints |
|
|
52
|
+
| `page_hashes` | Per-page visual hashes and lookup keys |
|
|
53
|
+
| `quality` | Evidence status, page provenance, and warnings |
|
|
54
|
+
| `parameters` | Parameters used to construct the fingerprint |
|
|
55
|
+
|
|
56
|
+
## CLI
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
docfgp report.pdf > report.fingerprint.json
|
|
60
|
+
```
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Applications
|
|
2
|
+
|
|
3
|
+
DocFGP generates fingerprints for document collections. The application stores them, indexes their keys, scores candidate pairs, and makes ingestion decisions.
|
|
4
|
+
|
|
5
|
+
## Using a fingerprint in a collection
|
|
6
|
+
|
|
7
|
+
1. Generate a fingerprint with `Fingerprinter().fingerprint(path)`.
|
|
8
|
+
2. Inspect `quality.status`, page provenance, and warnings. An `insufficient_evidence` result supports raw-byte identity only.
|
|
9
|
+
3. Store the serialized result with its schema and algorithm versions. Index the exact hashes and the relevant entries of `lookup_keys`.
|
|
10
|
+
4. Retrieve candidate fingerprints through those indexes. Compare only compatible versions and calculate the evidence needed for the application's decision.
|
|
11
|
+
|
|
12
|
+
## Questions the evidence can answer
|
|
13
|
+
|
|
14
|
+
| Question | Relevant evidence | Interpretation |
|
|
15
|
+
| --- | --- | --- |
|
|
16
|
+
| Are the files byte-identical? | Raw SHA-256 | Equality establishes byte identity. |
|
|
17
|
+
| Did extraction produce the same text across formats? | Nonempty canonical SHA-256 and extraction quality | Equality establishes identity of normalized extracted tokens; layout can differ. |
|
|
18
|
+
| Are the documents broadly similar? | Word and character MinHash, reached through LSH keys | Sketch agreement estimates set resemblance. |
|
|
19
|
+
| Is one document substantially contained in another? | Passage anchors, then hashed-shingle occurrence counts | Anchors retrieve candidates; directional counts quantify shared textual features. |
|
|
20
|
+
| Do scanned pages look alike? | Per-page perceptual hashes and visual keys | Hamming distance describes visual similarity. |
|
|
21
|
+
|
|
22
|
+
For example, if a document with 100 hashed five-word occurrences shares 95 occurrences with a document containing 1,000, coverage is 95% **from the smaller document's direction** and 9.5% from the larger document's direction. Coverage counts shared hashed five-word occurrences. Retain the counts in both fingerprints for this calculation; MinHash estimates set resemblance.
|
|
23
|
+
|
|
24
|
+
## Decisions and limits
|
|
25
|
+
|
|
26
|
+
Raw-hash equality establishes byte identity. Canonical-text equality establishes equality of extracted normalized tokens. Shared templates, repeated footers, and OCR errors can affect approximate and visual scores. The application should define its review or skip policy using the relevant modality, page coverage, and extraction quality.
|
|
27
|
+
|
|
28
|
+
For a native PDF and its scanned counterpart, OCR text and page hashes provide separate retrieval routes. Their effectiveness depends on recognition and rendering quality. The available evidence and measured results are described in [Methodology](methodology.md) and [Evaluation](evaluation.md).
|
|
29
|
+
|
|
30
|
+
Fingerprinting runs locally on the CPU. DOCX/PPTX conversion uses office2pdf; scanned-text recognition uses Tesseract. The application owns storage and retrieval.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Evaluation
|
|
2
|
+
|
|
3
|
+
This report covers two completed checks: cross-format retrieval on the office2pdf business golden corpus and validation of the published RVL-CDIP duplicate metadata. The retrieval figures below come from the Office corpus.
|
|
4
|
+
|
|
5
|
+
## Office source-to-PDF retrieval
|
|
6
|
+
|
|
7
|
+
The [business golden corpus](https://github.com/developer0hye/office2pdf/blob/main/tests/golden_mocks/business/README.md) pairs 10 DOCX and 10 PPTX files with PDF exports from Microsoft Office. The evaluator fingerprinted the 20 Office sources once, indexed their fingerprint evidence, then fingerprinted and queried the 20 PDF exports once each. The 20 manifest pairs were positives; the other 380 source/PDF pairs were treated as negatives.
|
|
8
|
+
|
|
9
|
+
The run took place on **9 November 2026** on Windows with Python 3.14.7, office2pdf 0.10.0, Tesseract 5.5.3, and an AMD Ryzen 5 7500F.
|
|
10
|
+
|
|
11
|
+
| Measure | Result |
|
|
12
|
+
| --- | ---: |
|
|
13
|
+
| Historical candidates / queries | 20 / 20 |
|
|
14
|
+
| Positive / negative pairs | 20 / 380 |
|
|
15
|
+
| Precision | 1.000 |
|
|
16
|
+
| Recall | 1.000 |
|
|
17
|
+
| Retrieval recall | 1.000 |
|
|
18
|
+
| Recall@10 | 1.000 |
|
|
19
|
+
| False-positive rate | 0.000 |
|
|
20
|
+
| CPU / wall time | 15.08 / 14.09 seconds |
|
|
21
|
+
| Sampled peak RAM | 150.24 MB |
|
|
22
|
+
|
|
23
|
+
The corpus is small and synthetic. Office observations informed the final native-text provenance rule, so these numbers describe performance on a development corpus. Accuracy on other collections requires independent evaluation.
|
|
24
|
+
|
|
25
|
+
## RVL-CDIP metadata validation
|
|
26
|
+
|
|
27
|
+
The evaluator joined the `documents` and `pairs` configurations of [RVL-CDIP Duplicates](https://huggingface.co/datasets/stefan-hf/rvlcdip-duplicates) at revision `457749089e2b729d8b82f64166a379a0c6c4e21e`. The check validated query IDs, original image-path agreement, and consistency between each query's duplicate flag and its pair judgments.
|
|
28
|
+
|
|
29
|
+
| Split | Queries with judgments | Positive pairs | Other judged pairs | Excluded query without judgments |
|
|
30
|
+
| --- | ---: | ---: | ---: | ---: |
|
|
31
|
+
| Validation | 40,000 | 69,172 | 330,828 | 0 |
|
|
32
|
+
| Test | 39,999 | 68,290 | 331,700 | 1 |
|
|
33
|
+
|
|
34
|
+
This check measured label and path consistency. The dataset's pairs cover ten same-class candidates per query selected by another system, and its duplicate labels are heuristic. The evaluator scores precision and false-positive rate on judged pairs and reports predictions on unjudged pairs separately. The accuracy figures above come from the Office retrieval run.
|
|
35
|
+
|
|
36
|
+
## Retrieval and scoring protocol
|
|
37
|
+
|
|
38
|
+
The corpus evaluators share a sequential protocol. They fingerprint each historical candidate once and retain fingerprint-derived evidence in a temporary disk-backed index. Each query is fingerprinted once. Exact hashes, MinHash bands, and visual keys retrieve candidates from that index. Candidate indexing and ranking use fingerprints; corpus labels enter after ranking to score the results. The temporary index is deleted after the run.
|
|
39
|
+
|
|
40
|
+
For a retrieved pair, the text score is the larger of word and character MinHash agreement. Equal raw hashes or equal nonempty canonical hashes score 1. The visual score greedily assigns distinct page-hash pairs and divides their summed similarity by the larger page count. When every page on both sides has usable native text and OCR was not attempted, the text score takes precedence over visual layout. Otherwise the larger score is used. A score of at least **0.8** is counted as a predicted match. This threshold is an evaluator policy. These corpora measure document equivalence, so the evaluators omit shingle occurrence counts; applications can retain counts for directional overlap calculations.
|
|
41
|
+
|
|
42
|
+
Precision is $TP/(TP+FP)$, recall is $TP/(TP+FN)$, and false-positive rate is $FP/(FP+TN)$. Retrieval recall counts labeled positives reached by any lookup key before score filtering. Recall@K counts labeled positives in the first K ranked candidates, divided by all labeled positives. The report includes raw pair counts to make each denominator visible.
|
|
43
|
+
|
|
44
|
+
CPU time combines Python process time with sampled child-process time. Peak RAM is the maximum sampled resident memory of the process tree at 10 ms intervals; short-lived peaks can be missed. A document-processing failure stops a run instead of yielding a complete-looking report.
|
|
45
|
+
|
|
46
|
+
## Reproducing the Office run
|
|
47
|
+
|
|
48
|
+
Install the library with its development dependencies, obtain the business golden corpus and the office2pdf and Tesseract executables, then run from the repository root:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install ".[dev]"
|
|
52
|
+
python -m scripts.evaluate_office /path/to/business --office2pdf /path/to/office2pdf --tesseract /path/to/tesseract
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The command prints the metrics and counts as JSON. Record the corpus revision, command, hardware, operating system, Python version, and converter/OCR versions with any subsequent result. Corpus evaluations are separate from CI.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Methodology
|
|
2
|
+
|
|
3
|
+
DocFGP computes a `DocumentFingerprint` for PDF, DOCX, PPTX, PNG, JPEG, TIFF, BMP, and WebP files.
|
|
4
|
+
|
|
5
|
+
## From file to evidence
|
|
6
|
+
|
|
7
|
+
| Stage | Implementation | Result |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| Input validation | Format signature, file size, and Office package checks | Identified format or an explicit error |
|
|
10
|
+
| Office conversion | [office2pdf](https://github.com/developer0hye/office2pdf) converts DOCX/PPTX to a temporary PDF | A common page representation |
|
|
11
|
+
| Page extraction | [pypdfium2](https://github.com/pypdfium2-team/pypdfium2) extracts PDF text and renders pages; Pillow decodes images | Text, page images, and extraction provenance |
|
|
12
|
+
| OCR when indicated | [Tesseract](https://github.com/tesseract-ocr/tesseract) runs on a bounded page image | Recognized text and mean word confidence |
|
|
13
|
+
| Feature construction | SHA-256, shingles, MinHash, winnowing, and perceptual hashing | A versioned, serializable fingerprint |
|
|
14
|
+
|
|
15
|
+
Pages are processed in order. Native PDF text is used when it has word tokens and valid decoded characters. OCR is attempted when native text is missing or invalid, or when an embedded image covers at least half of a page. When an image-heavy page also has native text, OCR replaces that text if its mean recognized-word confidence is at least 60 and it contributes at least three new tokens. For missing or invalid native text, accepted OCR needs confidence of at least 30. Page quality records OCR attempts, results, and warnings. These thresholds are deterministic text-selection rules.
|
|
16
|
+
|
|
17
|
+
## Text representation
|
|
18
|
+
|
|
19
|
+
Selected page text is normalized with Unicode NFKC, case folding, whitespace compaction, and joining of words divided by a line-break hyphen. Unicode word tokenization retains numbers. The **canonical text** is the ordered token sequence joined with spaces. A second representation removes punctuation and spacing from canonical text before character shingling. It tolerates some OCR spacing differences while retaining letters and digits.
|
|
20
|
+
|
|
21
|
+
Reading order and OCR quality influence the token sequence. Canonical equality means that the *extracted and normalized tokens* match.
|
|
22
|
+
|
|
23
|
+
## Fingerprint components
|
|
24
|
+
|
|
25
|
+
| Component | Construction | Intended use |
|
|
26
|
+
| --- | --- | --- |
|
|
27
|
+
| Raw hash | SHA-256 of original bytes | Byte identity |
|
|
28
|
+
| Canonical hash | SHA-256 of nonempty canonical text | Exact extracted-text identity across formats |
|
|
29
|
+
| Word features | Consecutive five-token shingles, each hashed with SHA-256 | Text resemblance and occurrence counts |
|
|
30
|
+
| Character features | Consecutive 13-character shingles of the tolerant text | Retrieval across some OCR differences |
|
|
31
|
+
| MinHash | 512 deterministic components for each shingle set | Approximate set similarity |
|
|
32
|
+
| LSH keys | 32 bands of 16 MinHash components per sketch | Indexed candidate retrieval |
|
|
33
|
+
| Passage anchors | Rightmost minimum word-shingle hash in each 32-shingle window | Retrieval of shared passages |
|
|
34
|
+
| Page hashes | 64-bit perceptual hash per nonblank rendered page; four 16-bit lookup keys | Visual candidate retrieval |
|
|
35
|
+
|
|
36
|
+
Exact hashes and text-feature identifiers use SHA-256 for stable values across Python processes. MinHash permutations are derived from fixed seed material. Empty feature sets yield empty sketches and lookup-key groups. The current result uses schema version `1.1` and algorithm version `1.3`; it also records feature parameters, per-page provenance, warnings, and a quality status.
|
|
37
|
+
|
|
38
|
+
For two documents with word-shingle sets $S_A$ and $S_B$, the fraction of equal MinHash components estimates set Jaccard similarity:
|
|
39
|
+
|
|
40
|
+
$$
|
|
41
|
+
J(S_A,S_B)=\frac{|S_A\cap S_B|}{|S_A\cup S_B|}.
|
|
42
|
+
$$
|
|
43
|
+
|
|
44
|
+
With 32 bands of 16 components, the usual independent-MinHash model gives a probability of at least one shared band of $1-(1-s^{16})^{32}$ at Jaccard similarity $s$. Empirical retrieval recall also depends on extraction quality and the implemented hash family. The sketch estimates *set* similarity and discards repetition. The underlying resemblance and containment approach is described by [Broder](https://www.cs.princeton.edu/courses/archive/spr05/cos598E/bib/broder97resemblance.pdf).
|
|
45
|
+
|
|
46
|
+
Occurrence counts retain repetition. If $c_A(h)$ is the number of occurrences of shingle hash $h$ in A, the application can calculate
|
|
47
|
+
|
|
48
|
+
$$
|
|
49
|
+
I(A,B)=\sum_h\min(c_A(h),c_B(h)),\qquad
|
|
50
|
+
C(A\mid B)=\frac{I(A,B)}{\sum_h c_A(h)}.
|
|
51
|
+
$$
|
|
52
|
+
|
|
53
|
+
Coverage is directional because $C(A\mid B)$ and $C(B\mid A)$ use different denominators. A value of 0.95 means that 95% of A's **hashed five-word shingle occurrences** also occur in B, up to hash collision. Set `include_shingle_counts=True` to retain the counts for this calculation.
|
|
54
|
+
|
|
55
|
+
Winnowing provides a separate route to partial matches. A contiguous passage of at least 36 identical normalized words contains a complete window of 32 five-word shingles and therefore shares an anchor under this selection rule. Shorter or edited passages depend on the anchors they retain. Repeated boilerplate can also share anchors. This method measures shared surface text. See the [winnowing paper](https://www.cs.princeton.edu/courses/archive/spr05/cos598E/bib/p76-schleimer.pdf).
|
|
56
|
+
|
|
57
|
+
Page perceptual hashes use a 32×32 grayscale discrete cosine transform. Their Hamming distance describes visual similarity independently of text coverage. Candidate retrieval through visual keys requires at least one matching 16-bit chunk; the application can then compare complete page hashes.
|
|
58
|
+
|
|
59
|
+
## Limits and reproducibility
|
|
60
|
+
|
|
61
|
+
Default limits are 50 MB per file, 200 pages, 8 million decoded pixels per page, 2 million extracted characters, and 200,000 distinct word or character shingles. PDF rendering uses 96 DPI for page hashes and up to 180 DPI for OCR, subject to the pixel limit; standalone images retain their source dimensions within that limit. External processes have a 60-second timeout; the document has a 180-second cooperative deadline. Configuration can change these limits.
|
|
62
|
+
|
|
63
|
+
`quality.status` identifies the available text and visual evidence. `insufficient_evidence` retains the raw hash and has empty approximate lookup-key groups. Invalid documents and exceeded processing limits raise `FingerprintError`; OCR failure can leave a warning and a visual-only result. Temporary conversion and OCR files are removed after the call. The cooperative deadline is checked between in-process decoding stages; services accepting untrusted uploads should also apply operating-system resource limits.
|
|
64
|
+
|
|
65
|
+
Fixed feature parameters and deterministic serialization support repeatable results. Changes in office2pdf, PDFium, Pillow, Tesseract, fonts, or OCR language can change extracted evidence, so experiments should record those versions and settings.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling>=1.27"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "docfgp"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Generate deterministic fingerprints for documents"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
keywords = ["document", "fingerprint", "minhash", "pdf"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Operating System :: OS Independent",
|
|
17
|
+
]
|
|
18
|
+
dependencies = ["pypdfium2>=4.30,<6", "Pillow>=10,<14"]
|
|
19
|
+
|
|
20
|
+
[project.optional-dependencies]
|
|
21
|
+
dev = ["pytest>=8", "ruff>=0.11", "mypy>=1.15", "build>=1.2", "psutil>=6", "reportlab>=4"]
|
|
22
|
+
benchmark = ["psutil>=6", "datasets>=3,<5"]
|
|
23
|
+
|
|
24
|
+
[project.scripts]
|
|
25
|
+
docfgp = "docfgp.cli:main"
|
|
26
|
+
|
|
27
|
+
[tool.hatch.build.targets.wheel]
|
|
28
|
+
packages = ["src/docfgp"]
|
|
29
|
+
|
|
30
|
+
[tool.hatch.build.targets.sdist]
|
|
31
|
+
exclude = ["/.github", "/.gitattributes", "/uv.lock"]
|
|
32
|
+
|
|
33
|
+
[tool.pytest.ini_options]
|
|
34
|
+
testpaths = ["tests"]
|
|
35
|
+
pythonpath = ["."]
|
|
36
|
+
|
|
37
|
+
[tool.ruff]
|
|
38
|
+
line-length = 100
|
|
39
|
+
target-version = "py311"
|
|
40
|
+
extend-exclude = [".tools"]
|
|
41
|
+
|
|
42
|
+
[tool.ruff.lint]
|
|
43
|
+
select = ["E", "F", "I", "B", "UP", "D"]
|
|
44
|
+
ignore = ["D203", "D213", "D413"]
|
|
45
|
+
|
|
46
|
+
[tool.mypy]
|
|
47
|
+
python_version = "3.11"
|
|
48
|
+
files = ["src/docfgp", "scripts"]
|
|
49
|
+
ignore_missing_imports = true
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Standalone benchmark evaluators distributed with the source repository."""
|