Αρχιτεκτονική λογισμικού
Η αρχιτεκτονική του PassagePin
Ή, πως τριακόσιες ογδόντα τέσσερις διαστάσεις ανά σελίδα σας βρίσκουν αυτό που ψάχνετε.


NOVA CONSTANT
Αρχιτεκτονική λογισμικού
Ή, πως τριακόσιες ογδόντα τέσσερις διαστάσεις ανά σελίδα σας βρίσκουν αυτό που ψάχνετε.

Με το PassagePin μπορείτε να κάνετε αναζητήσεις σ' έναν φάκελο με αρχεία PDF βάσει θεματολογίας. Μια αναζήτηση με θέμα την «παραγωγή ηλεκτρικής ενέργειας από ηλιακό φως» μπορεί να εντοπίσει μια σελίδα που αφορά τα φωτοβολταϊκά πάνελ, ακόμη κι αν το ερώτημα κι η σελίδα χρησιμοποιούν διαφορετικές λέξεις.
Αυτό επιτυγχάνεται αυτό εξάγοντας το κείμενο από κάθε σελίδα PDF και μετατρέποντάς το σε μια αριθμητική αναπαράσταση, η οποία ονομάζεται «embedding». Κατά την αναζήτηση, δημιουργείται μια αντίστοιχη αριθμητική αναπαράσταση για το ερώτημα του χρήστη, η οποία στη συνέχεια συγκρίνεται με τις αποθηκευμένες αναπαραστάσεις των σελίδων.
Τα αρχεία PDF σας, το ευρετήριο αναζήτησης και το μοντέλο παραμένουν όλα στον υπολογιστή σας. Το PassagePin περιλαμβάνει τόσο το μοντέλο όσο και το απαραίτητο περιβάλλον εκτέλεσης, επιτρέποντας έτσι τη δημιουργία ευρετηρίου και την πραγματοποίηση αναζητήσεων χωρίς σύνδεση στο διαδίκτυο.
Ο πυρήνας του PassagePin είναι μια μηχανή αναζήτησης γραμμένη σε Go, τυλιγμένη σ' ένα Electron desktop app για το γραφικό περιβάλλον. Το user interface είναι γραμμένο σε React με TypeScript και διαχειρίζεται την επιλογή βιβλιοθηκών, την πρόοδο της ευρετηρίασης, τα αποτελέσματα αναζήτησης και τις προεπισκοπήσεις των σελίδων.
Η main process του Electron εκκινεί έναν worker σε Go, ο οποία παραμένει ενεργός για μεγάλο διάστημα κι επικοινωνεί με την κύρια εφαρμογή μέσω JSON, μέσω των standard input/output. Ο worker φορτώνει μία φορά το embedding μοντέλο και το κρατά διαθέσιμο για όλες τις αναζητήσεις και τις εναλλαγές μεταξύ βιβλιοθηκών. Το CLI tool αξιοποιεί τον ίδιο πυρήνα σε Go, ο οποίος είναι υπεύθυνος για την ευρετηρίαση και την αναζήτηση.
Το interface τρέχει σ' ένα sandboxed renderer, χωρίς άμεση πρόσβαση στο Node.js ή το filesystem. Μέσω μιας απομονωμένης γέφυρας, ζητά απ' την main process του Electron να εκτελέσει συγκεκριμένες λειτουργίες. Για παράδειγμα, η επιλογή ενός φακέλου πραγματοποιείται μέσω ενός native διαλόγου, ενώ τα αιτήματα για το άνοιγμα ενός αρχείου PDF ελέγχονται ως προς την ενεργή βιβλιοθήκη.
Κάθε αποθηκευμένη βιβλιοθήκη διαθέτει το δικό της ευρετήριο στον τοπικό κατάλογο δεδομένων της εφαρμογής. Η εναλλαγή μεταξύ βιβλιοθηκών φορτώνει το επιλεγμένο ευρετήριο, χωρίς να μεταβάλλονται τα αρχεία PDF.
Μια σελίδα ενός PDF δεν αποθηκεύεται απαραίτητα ως μια ακολουθία λέξεων. Μπορεί να περιέχει οδηγίες σχεδίασης, συμπιεσμένες ροές δεδομένων, κωδικούς χαρακτήρων που αφορούν συγκεκριμένες γραμματοσειρές, καθώς κι αναφορές σε αντικείμενα που βρίσκονται σ' άλλα σημεία του εγγράφου.
Το PassagePin περιέχει ένα πρόγραμμα ανάγνωσης αρχείων PDF, γραμμένο σε Go. Το πρόγραμμα αυτό αναλύει τη δομή του εγγράφου, ακολουθεί την ιεραρχία των σελίδων κι ερμηνεύει τις οδηγίες κειμένου καθώς και τις αντιστοιχίσεις γραμματοσειρών που απαιτούνται για την εξαγωγή του κειμένου της σελίδας. Ανοίγει το αρχείο PDF μία φορά κατά τη διαδικασία ευρετηρίασης και διαβάζει το περιεχόμενο των σελίδων ανάλογα με τις ανάγκες.
Το πρόγραμμα υποστηρίζει τις συνήθεις δομές PDF και κωδικοποιήσεις κειμένου, ωστόσο δεν αποτελεί μια πλήρη rendering engine αρχείων PDF. Ακολουθεί τη ροή του κειμένου όπως αυτή εμφανίζεται στη ροή περιεχομένου του PDF και συμπεραίνει την ύπαρξη κενών διαστημάτων με βάση τις θέσεις των χαρακτήρων. Ως εκ τούτου, σε περιπτώσεις με πολύπλοκες στήλες ή πίνακες, η σειρά του εξαγόμενου κειμένου ενδέχεται να διαφέρει από τη σειρά με την οποία εμφανίζονται τα στοιχεία στην οπτική απεικόνιση της σελίδας.
Επιπλέον, το PassagePin απαιτεί την ύπαρξη ενός text layer στο αρχείο. Στην περίπτωση μιας σάρωσης που περιέχει αποκλειστικά εικόνες, δεν υπάρχει κείμενο προς εξαγωγή· συνεπώς, απαιτείται οπτική αναγνώριση χαρακτήρων (OCR) προτού καταστεί δυνατή η αναζήτηση στο περιεχόμενο του εγγράφου.
Το PassagePin χρησιμοποιεί το all-MiniLM-L6-v2, ένα μοντέλο sentence-transformer που παράγει embeddings 384 διαστάσεων. Η μηχανή σε Go τρέχει το μοντέλο locally μέσω του ONNX Runtime.
Ένα embedding αναπαριστά κείμενο ως ένα διάνυσμα. Κείμενα με συναφές νόημα μπορούν να παράγουν διανύσματα που δείχνουν προς παρόμοιες κατευθύνσεις, γεγονός που παρέχει στη μηχανή αναζήτησης τη δυνατότητα να συγκρίνει ένα ερώτημα αναζήτησης με μια σελίδα των PDF.
Το μοντέλο MiniLM επεξεργάζεται συνήθως έως και 256 tokens τη φορά. Μια σελίδα PDF μπορεί να είναι πολύ μεγαλύτερη, επομένως το PassagePin χωρίζει τη σελίδα σε διαδοχικά τμήματα. Κάθε τμήμα περιλαμβάνει έως και 254 tokens, στα οποία προστίθενται δύο ειδικά tokens για τις ανάγκες του μοντέλου.
Το μοντέλο επεξεργάζεται κάθε τμήμα ξεχωριστά. Το PassagePin αθροίζει τα token embeddings που προκύπτουν απ' όλα τα τμήματα μιας σελίδας και κανονικοποιεί το συνολικό αποτέλεσμα, δημιουργώντας έτσι ένα ενιαίο διάνυσμα για ολόκληρη τη σελίδα. Έτσι, το διάνυσμα κάθε σελίδας αναπαριστά το σύνολο του κειμένου που περιέχεται σ' αυτή.
Ωστόσο, εδώ γίνεται ένας συμβιβασμός: το μοντέλο δεν μπορεί να αξιοποιήσει το συγκείμενο πέρα απ' τα όρια του κάθε τμήματος, ενώ το τελικό διάνυσμα αντιπροσωπεύει ολόκληρη τη σελίδα. Έτσι, ένα σύντομο συγκριτικά με το συνολικό κείμενο της σελίδας, αλλά σχετικό με την αναζήτηση, απόσπασμα, ενδέχεται να «υποβαθμιστεί» στ' αποτελέσματα της αναζήτησης εξ αιτίας του «άσχετου», αναφορικά με το περιεχόμενο της αναζήτησης, κειμένου που το περιβάλλει στην ίδια σελίδα. Η λογική πίσω απ' αυτή την επιλογή είναι ότι το PassagePin αποσκοπεί πρωτίστως στην εύρηση εκτενών αναλύσεων του προς αναζήτηση θέματος, κι όχι στην εύρεση σχετικών αλλά φευγαλέων αναφορών.
Το PassagePin αποθηκεύει ένα διάνυσμα για κάθε σελίδα που είναι διαθέσιμη προς αναζήτηση. Οι κενές σελίδες, καθώς κι εκείνες απ' τις οποίες δεν προκύπτουν αξιοποιήσιμα tokens (πχ, μια σελίδα που περιέχει μόνο εικόνες), δεν παράγουν κάποιο διάνυσμα· όμως, προσμετρώνται ώστε η εφαρμογή ν' αναφέρει τον σωστό αριθμό κάθε σελίδας.
Η ευρετηρίαση επικαλύπτει την εξαγωγή του PDF με το inference του μοντέλου. Το PassagePin «ταΐζει» παράλληλα δύο PDF σε instances του μοντέλου.
Το ευρετήριο αποθηκεύεται είναι σε μορφή JSON. Περιέχει διαδρομές εγγράφων, αριθμούς φυσικών σελίδων, embeddings, τα hash των αρχείων και των σελίδων, καθώς και πληροφορίες σχετικά με το μοντέλο και την ευρετηρίαση. Το ευρετήριο δεν αποθηκεύει το καθεαυτό κείμενο της σελίδας, όμως μπορεί να περιέχει ευαίσθητες πληροφορίες όπως τα ονόματα των αρχείων PDF. Eπομένως, για όσους ενδιαφέρονται για ζητήματα ιδιωτικότητας, το ευρετήριο θα πρέπει να αντιμετωπίζεται ως τοπικά δεδομένα της εφαρμογής και να μην το μοιράζονται με τρίτους ή να το ανεβάσουν στο διαδίκτυο.
Όταν ένας χρήστης κάνει μια αναζήτηση, το PassagePin εκτελεί την αναζήτηση μέσω της ίδιας διαδικασίας tokenisation και embedding. Συγκρίνει το διάνυσμα του ερωτήματος με κάθε διάνυσμα των σελίδων που έχουν καταχωρηθεί στο ευρετήριο χρησιμοποιώντας ομοιότητα συνημίτονου και, στη συνέχεια, ταξινομεί τα αποτελέσματα κατά βαθμολογία ομοιότητας. Επειδή τα διανύσματα είναι κανονικοποιημένα, η σύγκριση μπορεί να χρησιμοποιήσει το τελικό γινόμενο τους.
Η επιλογή ενός αποτελέσματος αναγκάζει τον worker να διαβάσει ξανά αυτήν τη σελίδα από το PDF και να στείλει το εξαγόμενο κείμενό της στo γραφικό interface. Η εφαρμογή μπορεί επίσης δίνει στον χρήστη τη δυνατότητα ν' ανοίξει το PDF στο επιλεγμένο του πρόγραμμα ανάγνωσης PDF. Ο αναγνώστης ενδέχεται να χρειαστεί να πλοηγηθεί χειροκίνητα στην αναφορεμόνη σελίδα που αναφέρθηκε όταν ανοίγει το πρόγραμμα ανάγνωσης.
Η ανακατασκευή κάθε embedding μετά από μια μικρή αλλαγή θ' σπαταλούσε σπατάλη χρόνου και πόρων. Το PassagePin χρησιμοποιεί δύο επίπεδα από SHA-256 hashes για ν' αποφασίσει τι μπορεί να επαναχρησιμοποιήσει.
Πρώτον, hashάρει κάθε PDF. Εάν ένα πλήρως ευρετηριασμένο αρχείο δεν έχει μεταβληθεί, τότε οι υπάρχουσες σελίδες μπορούν να επαναχρησιμοποιηθούν απ' το ευρετήριο του χωρίς να εξαχθούν ξανά.
Εάν η σύγκριση των hashes δείξει ότι ένα PDF έχει μεταβληθεί, το PassagePin εξάγει τις σελίδες του και συγκρίνει τα hashes των κειμένων τους μ' αυτά του προηγούμενου ευρετηρίου. Αφενός, όταν το κείμενο στον ίδιο αριθμό φυσικής σελίδας εξακολουθεί να ταιριάζει, επαναχρησιμοποιεί το διάνυσμα αυτής της σελίδας. Αφετέρου, ενσωματώνει τροποποιημένες και νέες σελίδες με δυνατότητα αναζήτησης και αφαιρεί σελίδες ή έγγραφα που δεν υπάρχουν πλέον.
Το PassagePin ελέγχει επίσης τις βιβλιοθήκες για αλλαγές κατά την εκκίνηση, όταν επιλέγεται μια βιβλιοθήκη κι όταν ο χρήστης ζητά επανέλεγχο. Ο έλεγχος εκτελείται ως διακριτό process, χωρίς να φορτώνει ένα άλλο αντίγραφο του μοντέλου, επομένως οι αναζητήσεις παραμένουν διαθέσιμες κατά τη διάρκεια του ελέγχου.
Ορισμένες επεξεργασίες ενός PDF τροποποιούν το αρχείο χωρίς να μεταβάλλουν το εξαγόμενο κείμενό του, όπως για παράδειγμα η υπογράμμιση κειμένου στο PDF. Εάν ο έλεγχος επιβεβαιώσει ότι το κείμενο της σελίδας δεν έχει αλλάξει, το PassagePin μπορεί να ενημερώσει το αποθηκευμένο hash του αρχείου χωρίς να δημιουργήσει νέα embeddings. Όταν εντοπίσει τροποποιημένο κείμενο, προστιθέμενα ή αφαιρεμένα αρχεία, ή σφάλματα ανάγνωσης, προσφέρει μια ενημέρωση του ευρετηρίου.
Ένα πρόβλημα σε μία σελίδα δεν καθιστά πάντα το υπόλοιπο αρχείο PDF μη-αξιοποιήσιμο. Εάν η εξαγωγή δεδομένων αποτύχει σε μία συγκεκριμένη σελίδα, το PassagePin μπορεί να διατηρήσει τις υπόλοιπες σελίδες που είναι δυνατό ν' αναζητηθούν και ν' αναφέρει το έγγραφο ως μερικώς ευρετηριασμένο. Σε μεταγενέστερες ενημερώσεις του ευρετηρίου, επιχειρεί εκ νέου την επεξεργασία των εγγράφων που είχαν υποστεί μόνο μερική επεξεργασία.
Σε περιπτώσεις κατεστραμμένων cross-reference tables, το PassagePin μπορεί να επιχειρήσει μια περιορισμένη αποκατάσταση στη μνήμη. Η διαδικασία αυτή επικυρώνει τη δομή του αποκατασταθέντος εγγράφου, αφήνοντας το αρχικό αρχείο PDF ανέπαφο. Εάν η δομή του εγγράφου δεν είναι δυνατό να αναγνωστεί με ασφάλεια, το PassagePin παραλείπει το συγκεκριμένο έγγραφο και αναφέρει το πρόβλημα.
Επιπλέον, το σύστημα ευρετηρίασης ελέγχει τα τροποποιημένα αρχεία PDF τόσο πριν, όσο και μετά, τη διαδικασία εξαγωγής κι embedding. Εάν ένα αρχείο τροποποιηθεί κατά τη διάρκεια αυτής της διαδικασίας, το PassagePin το παραλείπει και ζητά την επανεκτέλεσή της.
Το ολοκληρωμένο ευρετήριο εγγράφεται αρχικά σ' ένα προσωρινό αρχείο, κι ύστερα αντικαθιστά το προηγούμενο ευρετήριο. Σε περίπτωση ακύρωσης ή κρίσιμων σφαλμάτων πριν απ' αυτή την αντικατάσταση, το προηγούμενο αποθηκευμένο ευρετήριο παραμένει διαθέσιμο. Εάν ένα τροποποιημένο αρχείο PDF καταστεί μη-αναγνώσιμο κατά τη διάρκεια μιας επιτυχούς ενημέρωσης, τα παλιά διανύσματα που σχετίζονται με αυτό εξαιρούνται αντί να διατηρηθούν ως τρέχοντα αποτελέσματα.
Το PassagePin πραγματοποιεί αναζητήσεις ανά σελίδα, επομένως επιστρέφει μια υπάρχουσα σελίδα προς ανάγνωση: δεν χρησιμοποιεί κάποια generative AI για να γράψει μια απάντηση.
Το μοντέλο του προορίζεται για την αγγλική γλώσσα, οπότε ενώ αναζητήσεις σε PDF διαφορετικής γλώσσας θα παράξουν αποτελέσματα, αυτά ενδέχεται να είναι χαμηλότερης ποιότηταςδιαφέρουν σε ποιότητα.
Το ευρετήριο παραμένει στην μνήμη όσο μια βιβλιοθήκη είναι ενεργή κι η αναζήτηση συγκρίνει το ερώτημα με κάθε αποθηκευμένο διάνυσμα σελίδας. Κάθε επιπλέον σελίδα που καθίσταται αναζητήσιμη προσθέτει ένα διάνυσμα 384 διαστάσεων στη μνήμη, καθώς και μία σύγκριση ομοιότητας σε κάθε αναζήτηση. Αυτό διατηρεί την απλότητα του ευρετηρίου και της διαδικασίας αναζήτησης, ενώ παράλληλα οδηγεί σε αύξηση της χρήσης της μνήμης και του φόρτου εργασίας της αναζήτησης, ανάλογα με το μέγεθος της βιβλιοθήκης.