epub_corrector/README.md

12 KiB

EPUB Corrector RKNN

Correttore e revisore di EPUB italiani per Orange Pi 5 Plus / RK3588.

La pipeline combina:

  • LanguageTool locale per generare i candidati;
  • Hunspell italiano per il controllo lessicale;
  • modello BERT in formato RKNN FP16 sulla NPU RK3588;
  • memoria incrementale di approvazioni, rifiuti e parole da preservare;
  • interfaccia Web per revisione, riscrittura e creazione di una copia EPUB corretta.

Requisiti verificati

  • Orange Pi 5 Plus o altro dispositivo RK3588 / RKNPU v2
  • Linux aarch64
  • Python 3.11
  • RKNNLite 2.3.2
  • RKNN Runtime 2.3.2
  • driver NPU 0.9.8
  • Docker per LanguageTool
  • Git LFS per scaricare il modello RKNN

Installazione in una nuova directory

L'esempio installa il progetto in:

/home/nvme/epub-corrector-new

1. Installa i pacchetti di sistema

sudo apt update
sudo apt install -y \
  git \
  git-lfs \
  python3-venv \
  hunspell \
  hunspell-it \
  unzip

git lfs install

2. Clona il repository

cd /home/nvme

git clone \
  'https://forgit.patachina.it/Fabio/epub_corrector.git' \
  epub-corrector-new

cd /home/nvme/epub-corrector-new

git lfs pull
git lfs checkout

Per l'autenticazione HTTPS usare:

Username: Fabio
Password: Personal Access Token di Forgit

3. Verifica il modello RKNN

Il modello deve misurare circa 214 MB, non pochi byte.

ls -lh \
  rknn/bert-pair-v2-eager-fp16.rknn

sha256sum -c \
  rknn/bert-pair-v2-eager-fp16.sha256

Risultato richiesto:

rknn/bert-pair-v2-eager-fp16.rknn: OK

Se il modello non è stato scaricato:

git lfs pull
git lfs checkout

4. Crea l'ambiente Python

cd /home/nvme/epub-corrector-new

python3 -m venv .venv-rknn
source .venv-rknn/bin/activate

python -m pip install --upgrade \
  pip \
  setuptools \
  wheel

python -m pip install \
  -r requirements-rknn.txt

5. Installa RKNNLite 2.3.2

RKNNLite può richiedere la wheel ufficiale Rockchip compatibile con:

Python 3.11
Linux aarch64
RK3588

Verifica prima se è già disponibile:

python - <<'PY'
from rknnlite.api import RKNNLite
print("RKNNLite disponibile")
PY

Se non è disponibile, trova la wheel usata nella vecchia installazione:

find \
  /home/nvme \
  /home/orangepi \
  -type f \
  -iname '*rknn*lite*.whl' \
  2>/dev/null

Installala indicando il percorso reale:

python -m pip install \
  /percorso/rknn_toolkit_lite2-2.3.2-*.whl

Verifica nuovamente l'importazione.

6. Crea le directory locali

Queste directory non vengono memorizzate nel repository perché possono contenere EPUB o testo protetto da copyright.

mkdir -p \
  output \
  reports \
  runs/ui \
  review_memory

Inizializza la memoria automatica:

printf '%s\n' \
  '{' \
  '  "approved": [],' \
  '  "sentence_rewrites": [],' \
  '  "preserved": [],' \
  '  "rejected": []' \
  '}' \
  > review_memory/auto_memory.json

Per importare la memoria da una precedente installazione:

cp \
  /vecchia/installazione/review_memory/auto_memory.json \
  review_memory/auto_memory.json

La memoria precedente è facoltativa e può contenere decisioni specifiche di altri libri.

7. Aggiorna i percorsi della nuova installazione

Cerca eventuali percorsi assoluti rimasti dalla vecchia directory:

grep -RIn \
  '/home/nvme/epub-gec-experiment' \
  --include='*.py' \
  --include='*.service' \
  --include='*.sh' \
  --include='*.json' \
  .

Sostituiscili con il nuovo percorso:

grep -Rl \
  '/home/nvme/epub-gec-experiment' \
  --include='*.py' \
  --include='*.service' \
  --include='*.sh' \
  --include='*.json' \
  . | \
xargs -r sed -i \
  's|/home/nvme/epub-gec-experiment|/home/nvme/epub-corrector-new|g'

Verifica:

grep -RIn \
  '/home/nvme/epub-gec-experiment' \
  --include='*.py' \
  --include='*.service' \
  --include='*.sh' \
  --include='*.json' \
  . || echo "Nessun vecchio percorso rimasto"

8. Verifica il percorso del tokenizer

Il tokenizer incluso nel repository si trova in:

assets/tokenizer/tokenizer.json

Cerca eventuali riferimenti al vecchio percorso:

grep -RIn \
  'onnx/bert-pair-v2/tokenizer' \
  --include='*.py' \
  .

Se necessario, sostituiscili:

grep -Rl \
  'onnx/bert-pair-v2/tokenizer/tokenizer.json' \
  --include='*.py' \
  . | \
xargs -r sed -i \
  's|onnx/bert-pair-v2/tokenizer/tokenizer.json|assets/tokenizer/tokenizer.json|g'

9. Prepara la cartella degli EPUB

Puoi riutilizzare la cartella esistente:

/home/orangepi/epub-corrector/input

Oppure crearne una nuova:

mkdir -p \
  /home/orangepi/epub-corrector-new/input

Se usi una nuova cartella, aggiorna INPUT in epub-corrector-ui-app/app.py:

sed -i \
  "s|INPUT=Path('/home/orangepi/epub-corrector/input')|INPUT=Path('/home/orangepi/epub-corrector-new/input')|" \
  epub-corrector-ui-app/app.py

10. Avvia LanguageTool

Se il container esiste già:

sudo docker start languagetool-epub

Controlla:

sudo docker ps \
  --filter name=languagetool-epub \
  --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'

Testa l'endpoint locale:

LT_URL="$(
  printf 'http:%s127.0.0.1:8010/v2/check' '//'
)"

curl -sS \
  -X POST \
  -d 'language=it-IT' \
  --data-urlencode 'text=Questa frase contiene un erore.' \
  "$LT_URL" \
  -o /tmp/languagetool-test.json

python -m json.tool \
  /tmp/languagetool-test.json | \
head -n 30

La risposta deve contenere matches.

Se il container non esiste, crealo:

sudo docker run -d \
  --name languagetool-epub \
  --restart unless-stopped \
  -p 127.0.0.1:8010:8010 \
  --memory=1200m \
  -e Java_Xms=128m \
  -e Java_Xmx=768m \
  silviof/docker-languagetool

11. Verifica la NPU

source /home/nvme/epub-corrector-new/.venv-rknn/bin/activate

python - <<'PY'
from pathlib import Path
from rknnlite.api import RKNNLite

model = Path(
    "rknn/bert-pair-v2-eager-fp16.rknn"
)

if not model.exists():
    raise SystemExit(f"Modello assente: {model}")

rknn = RKNNLite(verbose=False)

try:
    result = rknn.load_rknn(str(model))
    print("load_rknn:", result)

    if result != 0:
        raise SystemExit(result)

    result = rknn.init_runtime(
        core_mask=RKNNLite.NPU_CORE_AUTO
    )

    print("init_runtime:", result)

    if result != 0:
        raise SystemExit(result)

    print("MODELLO NPU PRONTO")
finally:
    rknn.release()
PY

Il warning relativo a RKNN_QUERY_INPUT_DYNAMIC_RANGE può essere ignorato: il modello usa forma statica a 128 token.

Installazione della Web UI

12. Crea il servizio systemd

Se la precedente installazione usa ancora la porta 8090, fermala o scegli la porta 8091 per la nuova.

Per disabilitare il vecchio servizio:

sudo systemctl disable --now \
  epub-corrector-ui

Crea un servizio per la nuova directory:

SERVICE_FILE="/etc/systemd/system/epub-corrector-new.service"

sudo sh -c "printf '%s\n' \
'[Unit]' \
'Description=EPUB Corrector New Web UI' \
'After=network.target docker.service' \
'Wants=docker.service' \
'' \
'[Service]' \
'Type=simple' \
'User=orangepi' \
'WorkingDirectory=/home/nvme/epub-corrector-new' \
'ExecStart=/home/nvme/epub-corrector-new/.venv-rknn/bin/python /home/nvme/epub-corrector-new/epub-corrector-ui-app/app.py' \
'Restart=on-failure' \
'RestartSec=5' \
'Environment=PYTHONUNBUFFERED=1' \
'' \
'[Install]' \
'WantedBy=multi-user.target' \
> '$SERVICE_FILE'"

Se vuoi mantenere due installazioni attive, modifica la porta della nuova UI:

sed -i \
  's/port=8090/port=8091/' \
  epub-corrector-ui-app/app.py

Avvia il servizio:

sudo systemctl daemon-reload
sudo systemctl enable --now \
  epub-corrector-new

sudo systemctl status \
  epub-corrector-new \
  --no-pager -l

Controlla la porta:

sudo ss -ltnp | \
grep -E ':8090|:8091'

13. Apri l'interfaccia

Trova l'indirizzo dell'Orange Pi:

hostname -I

Apri dal browser:

http://IP_ORANGE_PI:8090

oppure, se hai scelto la porta alternativa:

http://IP_ORANGE_PI:8091

Uso

  1. Copia gli EPUB italiani senza DRM nella cartella input.
  2. Apri la Web UI.
  3. Avvia LanguageTool, se non è già attivo.
  4. Seleziona il libro.
  5. Premi Analizza.
  6. Revisiona i candidati:
    • Approva proposta;
    • Salva riscrittura;
    • Mantieni e ricorda;
    • Rifiuta.
  7. Premi Crea EPUB corretto.
  8. Verifica il file prodotto nella cartella output.

La memoria viene salvata in:

review_memory/auto_memory.json

La scansione successiva la carica automaticamente.

Validazione dell'EPUB prodotto

unzip -t \
  output/NOME_LIBRO_ui_reviewed.epub

Controlla che mimetype sia il primo file e non sia compresso:

unzip -lv \
  output/NOME_LIBRO_ui_reviewed.epub | \
head -n 10

Apri infine il file con Calibre, Thorium Reader o KOReader e controlla:

  • indice e capitoli;
  • corsivi, link e note;
  • dialoghi;
  • riscritture complete;
  • campioni delle sostituzioni applicate.

Backup della memoria

cp -p \
  review_memory/auto_memory.json \
  "review_memory/auto_memory_$(date +%Y%m%d_%H%M%S).json"

Aggiornamento da Git

cd /home/nvme/epub-corrector-new

git pull
git lfs pull

sha256sum -c \
  rknn/bert-pair-v2-eager-fp16.sha256

sudo systemctl restart \
  epub-corrector-new

Comandi del servizio

sudo systemctl start epub-corrector-new
sudo systemctl stop epub-corrector-new
sudo systemctl restart epub-corrector-new
sudo systemctl status epub-corrector-new --no-pager -l
sudo journalctl -u epub-corrector-new -f

File non inclusi nel repository

Per ragioni di privacy, copyright e dimensione, il repository non contiene:

  • EPUB originali o corretti;
  • report con testo dei libri;
  • memoria personale;
  • dataset di addestramento;
  • ambienti virtuali;
  • ONNX intermedi;
  • log.

Il modello RKNN pronto è invece incluso tramite Git LFS, insieme al tokenizer necessario.

Installazione obbligatoria di RKNNLite e librknnrt

Il modello incluso usa RKNN versione 6, compilato con RKNN Toolkit 2.3.2 per RK3588 / RKNPU v2.

Requisiti verificati:

  • CPython 3.11 aarch64;
  • rknn-toolkit-lite2 2.3.2;
  • librknnrt.so 2.3.2;
  • driver NPU 0.9.6 o successivo.

Il warning RKNN_QUERY_INPUT_DYNAMIC_RANGE è previsto e si può ignorare: il modello ha forma statica a 128 token.

File richiesti dopo git lfs pull:

wheels/rknn_toolkit_lite2-2.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
runtime/aarch64/librknnrt.so
rknn/bert-pair-v2-eager-fp16.rknn
assets/tokenizer/tokenizer.json

Scarica gli oggetti Git LFS

git lfs install
git lfs pull
git lfs checkout
sha256sum -c rknn/bert-pair-v2-eager-fp16.sha256

Crea l'ambiente Python

python3 -m venv .venv-rknn
source .venv-rknn/bin/activate
python -m pip install --upgrade pip setuptools wheel
python -m pip install -r requirements-rknn.txt

Installa RKNNLite 2.3.2

python -m pip uninstall -y rknn-toolkit-lite2
python -m pip install   wheels/rknn_toolkit_lite2-2.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Verifica:

python -c 'from importlib.metadata import version; from rknnlite.api import RKNNLite; print(version("rknn-toolkit-lite2"))'

Deve stampare 2.3.2.

Installa librknnrt 2.3.2

if [ -e /usr/lib/librknnrt.so ]; then
  sudo cp -a /usr/lib/librknnrt.so     "/usr/lib/librknnrt.so.backup-$(date +%Y%m%d_%H%M%S)"
fi

sudo install -m 0755   runtime/aarch64/librknnrt.so   /usr/lib/librknnrt.so

sudo ldconfig

Il warning /lib/librknnrt.so is not a symbolic link non blocca il funzionamento.

Verifica che gli hash coincidano:

sha256sum runtime/aarch64/librknnrt.so /usr/lib/librknnrt.so

Verifica modello e NPU

python -c 'from pathlib import Path; from rknnlite.api import RKNNLite; m=Path("rknn/bert-pair-v2-eager-fp16.rknn"); r=RKNNLite(verbose=False); a=r.load_rknn(str(m)); print("load_rknn:",a); b=r.init_runtime(core_mask=RKNNLite.NPU_CORE_AUTO) if a==0 else -1; print("init_runtime:",b); r.release(); raise SystemExit(0 if a==0 and b==0 else 1)'

Risultato corretto:

librknnrt version: 2.3.2
RKNN Model Information, version: 6
load_rknn: 0
init_runtime: 0

Se compare Invalid RKNN model version 6, il sistema sta ancora caricando un runtime vecchio, tipicamente librknnrt 1.4.0.

Non usare la wheel 2.3.0: incorpora un runtime 1.4.0 incompatibile con il modello versione 6.