No description
  • Python 97.1%
  • Dockerfile 1.5%
  • Shell 1.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-08-27 09:17:17 +03:00
.streamlit init 2026-08-26 17:19:37 +03:00
examples init 2026-08-26 17:19:37 +03:00
pii_sanitizer Enhance file upload functionality to support .pdf and .docx formats, update README with new format details, and improve error handling during file loading. 2026-08-27 09:15:13 +03:00
scripts Add .env.example for LAN-IP configuration, update .gitignore, modify compose.yml and README for LAN-IP usage, enhance deploy.sh for .env validation 2026-08-26 17:23:19 +03:00
tests Enhance file upload functionality to support .pdf and .docx formats, update README with new format details, and improve error handling during file loading. 2026-08-27 09:15:13 +03:00
.dockerignore init 2026-08-26 17:19:37 +03:00
.env.example Add .env.example for LAN-IP configuration, update .gitignore, modify compose.yml and README for LAN-IP usage, enhance deploy.sh for .env validation 2026-08-26 17:23:19 +03:00
.gitignore Add .env.example for LAN-IP configuration, update .gitignore, modify compose.yml and README for LAN-IP usage, enhance deploy.sh for .env validation 2026-08-26 17:23:19 +03:00
app.py Enhance file upload functionality to support .pdf and .docx formats, update README with new format details, and improve error handling during file loading. 2026-08-27 09:15:13 +03:00
compose.yml Update compose.yml to add Tailscale IP configuration for Streamlit service 2026-08-27 09:17:17 +03:00
Dockerfile init 2026-08-26 17:19:37 +03:00
README.md Enhance file upload functionality to support .pdf and .docx formats, update README with new format details, and improve error handling during file loading. 2026-08-27 09:15:13 +03:00
requirements-dev.txt init 2026-08-26 17:19:37 +03:00
requirements.txt Enhance file upload functionality to support .pdf and .docx formats, update README with new format details, and improve error handling during file loading. 2026-08-27 09:15:13 +03:00

DashkaGPT / PII Sanitizer

Локальное обезличивание русскоязычных текстов перед ручной отправкой в ChatGPT или другой внешний AI-сервис.

Приложение не отправляет исходные тексты, найденные персональные данные, mapping или любые другие данные во внешние API. Вся обработка выполняется на вашем компьютере (или внутри изолированного Docker-контейнера в LAN).

Назначение

  1. Найти потенциальные персональные данные в .txt / .md / .pdf / .docx или во вставленном тексте.
  2. Пройти этап ручной review (исключить false positive / добавить пропуски).
  3. Заменить подтверждённые сущности на placeholder'ы.
  4. Скачать clean-текст и mapping.json.
  5. При необходимости восстановить исходный текст по mapping.

Требования (локальная разработка)

  • macOS / Linux
  • Python 3.11+
  • Доступ в интернет только для установки зависимостей из PyPI. После установки приложение работает офлайн.

Установка (Mac / без Docker)

cd /path/to/DashkaGPT
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements-dev.txt

Запуск (Mac)

source .venv/bin/activate
streamlit run app.py

Откройте локальный URL (обычно http://localhost:8501).

Тесты

source .venv/bin/activate
pytest -q

Безопасность

  • Обработка только локальная; HTTP-запросы наружу приложением не выполняются.
  • Telemetry Streamlit отключена (browser.gatherUsageStats = false).
  • Содержимое документов не логируется в server logs.
  • Загруженные файлы читаются в память и не сохраняются приложением на диск.
  • Mapping содержит исходные персональные данные. Не загружайте этот файл во внешние AI-сервисы.
  • Модели Natasha входят в Docker image (preload на этапе build) — runtime без сети для анализа документов.

Что ищется (MVP)

Тип Источник
ФИО (PERSON) Natasha NER + entity resolution
Email / телефоны / ИНН / СНИЛС / паспорт / карты / счета / БИК / IP regex (+ checksum где применимо)
OTHER только вручную на этапе review

Структура

DashkaGPT/
├── app.py
├── requirements.txt
├── requirements-dev.txt
├── Dockerfile
├── compose.yml
├── .streamlit/config.toml
├── pii_sanitizer/
├── examples/
├── scripts/deploy.sh
└── tests/

Целевая директория на сервере: /opt/pii-sanitizer.

Проект живёт как отдельный Compose project pii-sanitizer.

Порт публикуется только на LAN-IP Beelink (не на всех интерфейсах):

ports:
  - "${BEELINK_LAN_IP}:8501:8501"

Внутри контейнера Streamlit слушает 0.0.0.0:8501.

Перед docker compose up на сервере создайте /opt/pii-sanitizer/.env:

cp .env.example .env
# укажите реальный LAN-IP Beelink, например:
# BEELINK_LAN_IP=192.168.1.50

На Mac (перед выкладкой)

source .venv/bin/activate
pytest -q

Передача кода на сервер

Подставьте свои значения вместо <BEELINK_USER> и <BEELINK_IP>:

rsync -av --delete \
  --exclude '.git' \
  --exclude '.venv' \
  --exclude '__pycache__' \
  --exclude '.pytest_cache' \
  --exclude '.mypy_cache' \
  --exclude '.DS_Store' \
  --exclude '*.log' \
  --exclude '.env' \
  ./ <BEELINK_USER>@<BEELINK_IP>:/opt/pii-sanitizer/

Или:

BEELINK_USER=<BEELINK_USER> BEELINK_IP=<BEELINK_IP> ./scripts/deploy.sh
# сразу build+up:
BEELINK_USER=<BEELINK_USER> BEELINK_IP=<BEELINK_IP> ./scripts/deploy.sh --up

На сервере

cd /opt/pii-sanitizer
cp -n .env.example .env
# отредактируйте BEELINK_LAN_IP=<LAN-IP Beelink>
nano .env

docker compose build
docker compose up -d

Проверка

docker compose ps
docker compose logs --tail=50
curl -s http://127.0.0.1:8501/_stcore/health

UI в LAN:

http://<BEELINK_LAN_IP>:8501

Обновление

# с Mac: rsync (как выше), затем на сервере:
cd /opt/pii-sanitizer
docker compose build
docker compose up -d

Остановка только этого проекта

cd /opt/pii-sanitizer
docker compose down

Ресурсы

В compose.yml по умолчанию:

  • CPU limit: 2.0
  • RAM limit: 3G

При необходимости измените cpus / mem_limit (и блок deploy.resources) под нагрузку Beelink.

Docker security (кратко)

  • non-root user UID 10001
  • read_only: true + tmpfs на /tmp и /home/appuser/.streamlit
  • cap_drop: ALL, no-new-privileges:true
  • нет volume для uploads/mapping — данные только в RAM/session

Smoke test после deploy

Используйте examples/smoke_deploy.txt (вымышленные данные):

  1. UI открывается.
  2. «Найти ПДн» находит PERSON / PHONE / EMAIL / …
  3. В review можно исключить сущность и добавить OTHER (14825).
  4. «Сформировать» → скачать clean + mapping.
  5. Вкладка «Восстановить» возвращает исходный текст.

Mapping (v2)

{
  "[[PERSON_0001]]": {
    "type": "PERSON",
    "canonical": "иванов иван иванович",
    "occurrences": [
      "Иванов Иван Иванович",
      "Иванова Ивана Ивановича"
    ]
  }
}

Форматы загрузки

Формат Извлечение Результат обезличивания
.txt, .md как есть (UTF-8 / CP1251) тот же тип файла
.pdf текстовый слой (pypdf), без OCR .txt
.docx параграфы и таблицы (python-docx) .txt

Файлы читаются только в память и не сохраняются на диск.

Ограничения первой версии

  • PDF: нужны страницы с текстовым слоем; сканы без OCR не поддерживаются; пароли — только «пустой» decrypt.
  • DOCX: старый .doc не поддерживается; колонтитулы/текстовые поля Word могут не попасть в извлечение.
  • Нет HTML/CSV/XLSX.
  • Нет HTTPS/nginx/домена (только LAN :8501).
  • Ручной ввод на review — только точное совпадение строки.
  • Regex могут давать false positive / пропускать нестандартные форматы.
  • Контейнер не хранит историю документов между рестартами (это намеренно).