Skip to content

Repository files navigation

ProjectChat — AI ассистент для проектов

Интеллектуальный инструмент для работы с проектами, документами и AI-ассистентом. Поддерживает загрузку документов, автоматическую анонимизацию PII данных, общение с AI моделями и создание артефактов.

ProjectChat — AI Assistant for Projects

Основные возможности

  • Управление проектами — создание, редактирование, организация проектов
  • Работа с документами — загрузка PDF, DOCX, TXT файлов с автоматической анонимизацией
  • AI-чат — общение с DeepSeek/OpenRouter моделями на основе документов проекта
  • Артефакты — сохранение результатов работы AI в структурированном виде
  • Безопасность — шифрование API ключей, опциональная аутентификация
  • Кастомизация — темы, настройки AI параметров, шаблоны промптов

Архитектура

  • Бэкенд: FastAPI (Python 3.11+), асинхронный SQLite через aiosqlite
  • Фронтенд: один статический HTML-файл с Vanilla JavaScript (без фреймворков)
  • Парсинг документов: на клиенте (PDF.js для PDF, FileReader для TXT)
  • Анонимизация: на клиенте, использует регулярные выражения из Chrome-расширения
  • AI-клиент: поддержка OpenAI-совместимых API с потоковой передачей

Установка и запуск

Запуск за 5 минут (рекомендуется)

git clone https://github.com/Vitalymt/AI-project-chat-anonimaizer.git
cd AI-project-chat-anonimaizer
chmod +x setup.sh
./setup.sh

После запуска открой URL с портом из .env (PORT, по умолчанию 8000):

  • http://localhost:<PORT>
  • или http://<IP_машины>:<PORT>

Что ожидать от первой Docker-сборки

  • Первая сборка может занять 3-10 минут.
  • Это нормально: подтягиваются Python-зависимости и языковая модель spaCy (ru_core_news_sm).
  • Повторные перезапуски значительно быстрее.

Ручной запуск (без setup.sh)

  1. Создайте .env из шаблона:

    cp .env.example .env
  2. Укажите в .env минимум:

    • AI_PROVIDER
    • API ключ выбранного провайдера
    • PORT (по умолчанию 8000)
  3. Запустите через Docker Compose:

    docker compose up -d --build
  4. Проверьте здоровье сервиса:

    curl -sS http://localhost:<PORT>/api/health

AUTH и health-check

  • По умолчанию используется AUTH_ENABLED=false (подходит для личного локального использования).
  • Если включить AUTH_ENABLED=true, endpoint /api/health требует Basic Auth.
  • Для проверок используйте:
    curl -u "$AUTH_USERNAME:$AUTH_PASSWORD" -sS http://localhost:<PORT>/api/health

Использование

Целевой сценарий (продуктовая логика)

  1. Создайте проект.
  2. Загрузите документы и дождитесь обезличивания.
  3. ИИ использует обезличенный контекст и формирует структурную память в Obsidian.
  4. Продолжайте работу в чате: план, риски, вопросы заказчику, транскрипты встреч.
  5. Переключайтесь между проектами — память и записи строго изолированы по project_id.

1. Создание проекта

  • Нажмите "Новый проект" в левой панели
  • Укажите название и цель проекта
  • Проект создастся с папками для оригинальных файлов и артефактов

2. Загрузка документов

  • Перейдите на вкладку "Документы"
  • Нажмите "Загрузить документ"
  • Выберите PDF или TXT файл
  • Файл будет обработан на клиенте:
    • Текст извлекается (PDF.js для PDF)
    • PII данные анонимизируются
    • Анонимизированный текст отправляется на сервер
    • Оригинальный файл сохраняется локально

3. Работа с чатами

  • На вкладке "Чаты" создайте новый чат
  • Введите сообщение - ответ будет приходить потоково
  • AI использует контекст загруженных документов
  • История сообщений сохраняется

4. Сохранение артефактов

  • В правой панели нажмите "Сохранить"
  • Сохраните важные результаты как артефакты
  • Артефакты сохраняются в БД и в файлы

4.1 Что есть что: документы / артефакты / vault

  • Документы — входные источники контекста (файлы, которые вы загружаете в проект).
  • Артефакты — результаты работы внутри ProjectChat (заметки/выводы в интерфейсе сервиса).
  • Vault (Obsidian) — внешняя долговременная память проекта, синхронизируемая через WebDAV.

4.2 Режимы записи в Vault

  • auto — структурная автозапись артефактов (по policy и confidence).
  • manual — разовая ручная запись ответа кнопкой Сохранить в Vault (ручное).
  • observe — пошаговая запись для визуального контроля в Obsidian (Пошаговая запись в Obsidian).

Примечание: прямой tool-вызов write_note из auto-loop отключен, чтобы не смешивать свободную запись и структурную память.

5. Настройки AI

  • Нажмите "Настройки" в верхней панели
  • Выберите провайдера (OpenRouter/DeepSeek)
  • Введите API ключ (валидируется при проверке и сохранении)
  • Выберите модель из пресетов или укажите вручную
  • При переключении провайдера не нужно вводить ключ повторно, если он уже сохранен
  • Параметр Автозапись в Vault управляет поведением памяти:
    • off — без автозаписи,
    • summary — только _summary.md,
    • structured — summary + структурные артефакты.

5.1 Контракт сохранения ключей (важно)

  • Ключи OpenRouter и DeepSeek хранятся отдельно.
  • Поле ключа в UI всегда открывается пустым: это защищает от отправки маски ****xxxx обратно на сервер.
  • Если поле ключа пустое при сохранении, текущий ключ не меняется.
  • Маскированные значения вида ****xxxx сервер отклоняет с ошибкой валидации.
  • Для очистки ключа предусмотрен отдельный backend-флаг (CLEAR_*_API_KEY), пустая строка без флага не перетирает ключ.

5.2 Диагностика провайдеров

  • GET /api/settings теперь возвращает:
    • OPENROUTER_API_KEY_CONFIGURED, DEEPSEEK_API_KEY_CONFIGURED
    • OPENROUTER_API_KEY_SOURCE, DEEPSEEK_API_KEY_SOURCE (env или db)
  • GET /api/settings/provider-health показывает активного провайдера, модель и наличие ключа по каждому провайдеру.
  • POST /api/settings/validate-key выполняет реальную проверку ключа через API провайдера.

5.3 Режим автозаписи памяти

  • VAULT_AUTOSAVE_MODE=off — автозапись отключена.
  • VAULT_AUTOSAVE_MODE=summary — обновляется только Projects/<project-id>/_summary.md.
  • VAULT_AUTOSAVE_MODE=structured — summary + структурные артефакты (risks/decisions/analysis).

6. Vault не виден: 60-сек чеклист

  • Проверьте .env: OBSIDIAN_ENABLED=true
  • Перезапустите сервис: docker compose --profile vault up -d --build
  • Откройте GET /api/settings и убедитесь, что OBSIDIAN_ENABLED=true
  • Откройте GET /api/vault/status и смотрите action_hint
  • Если vault выключен, в интерфейсе появится баннер с подсказкой, как включить

7. Runbook: "агент пишет — Obsidian показывает"

  1. Preflight на VM
    • OBSIDIAN_ENABLED=true в .env
    • WebDAV поднят (docker compose --profile vault up -d)
    • GET /api/vault/status возвращает vault_runtime_enabled=true
  2. Preflight в Obsidian (Windows)
    • Установите Community plugin Remotely Save
    • Remote Service: WebDAV
    • Server URL: http://<VM_IP>:<WEBDAV_PORT>
    • Username/Password: из .env (WEBDAV_USER / WEBDAV_PASSWORD)
  3. Режим наблюдения
    • В чате нажмите Наблюдать в Obsidian под ответом AI
    • Агент пишет заметку порциями в режиме append
    • В интерфейсе появляется статус записи и путь файла
  4. Когда ждать обновление
    • Обновления появляются после sync-цикла плагина
    • Для мгновенного эффекта нажмите Sync вручную
    • Это near-real-time, а не посимвольный стрим
  5. Разница между кнопками
    • Сохранить в Vault (ручное) — разовая ручная запись текущего ответа в выбранный путь.
    • Пошаговая запись в Obsidian — запись крупного ответа частями для визуального контроля наполнения заметки.
    • Автозапись (если включена) работает отдельно по policy из настроек.

7.1 Что проверять в trace

  • write_modeauto|manual|observe.
  • artifact_type — тип структурной записи (summary, risks, decisions, analysis).
  • links_created — какие wikilinks добавлены в hub-note.
  • artifact_written.warning — диагностические предупреждения post-write.

7.2 Runbook по bugfix-first (UX/стриминг)

  1. Переключение чатов во время генерации
    • Отправьте сообщение в чате A и сразу перейдите в чат B.
    • Ожидание: в B видно статус фоновой генерации, ответ не пропадает и сохраняется в A.
    • Проверьте возврат в A: сообщение ассистента на месте, без повторной перерисовки чужой истории.
  2. Timeout/abort без технического шума
    • Нажмите Отмена во время ответа ИИ.
    • Ожидание: показывается понятное сообщение (Запрос отменен), без текста BodyStreamBuffer was aborted.
    • Для длинного ответа проверьте idle-timeout: пользователь видит понятный timeout-текст.
  3. Вкладка Документы без глобального затухания
    • Переключайтесь между Чаты и Документы несколько раз.
    • Ожидание: нет полноэкранного overlay, только локальное состояние списка документов.
  4. Проверка ENABLE_STREAMING
    • Выключите ENABLE_STREAMING в настройках и отправьте сообщение.
    • Ожидание: ответ приходит цельным блоком (без по-чанковой отрисовки), но корректно сохраняется в БД.
    • Включите обратно и убедитесь, что ответ снова идет постепенно.
  5. Vault project-scope
    • Вызовы /api/vault/tree|search|note|reindex должны выполняться только с project_id.
    • Путь/папка вне Projects/<project-id> должны возвращать 403.

8. Проверка корректности Obsidian-режима

  • Откройте ответ ИИ и раскройте блок Что читал AI:
    • видны tool-вызовы, аргументы, длительность и статусы ok/error,
    • видно решение write/skip, artifact_type, artifact_confidence, decision_reason.
  • Если решение write, в trace будет:
    • путь записанной заметки,
    • список созданных связей (wikilinks) между hub-note и артефактом.
  • Если решение skip, ИИ не пишет в Vault и объясняет причину в trace.

9. Как отличить автозапись от ручной записи

  • Автозапись: возникает без кнопки, только для структурных артефактов (analysis/risks/decisions/summary/meeting-notes) при confidence выше порога.
  • Ручная запись: инициируется кнопкой Сохранить в vault или явной командой пользователя.
  • Для автозаписи используются канонические пути в Projects/<project>/... и обновляется /_summary.md со связями.

10. SSH tunnel: ошибка Connection refused

Если при туннеле с Windows:

ssh -N -L 8002:localhost:8002 -p 2222 openclaw@<VM_IP>

видите:

channel X: open failed: connect failed: Connection refused

это означает, что SSH-подключение к VM есть, но приложение на VM не слушает localhost:8002.

Проверьте и исправьте на VM:

ss -tlnp | awk '$4 ~ /:8002$/ || $4 ~ /:8081$/ || $4 ~ /:2222$/'
curl -sS -m 5 http://localhost:8002/api/health

Если API не поднят:

./.venv/bin/uvicorn main:app --host 0.0.0.0 --port 8002

Если нужен Vault sync и нет WebDAV:

docker compose --profile vault up -d webdav

После этого снова запускайте SSH-туннель.

ТЗ стабилизации (P0/P1)

Цель

Сделать сервис пригодным для регулярного использования: предсказуемое сохранение настроек, стабильная авторизация к AI-провайдерам, прозрачная диагностика и быстрый smoke-прогон.

Обязательные требования

  1. Сохранение настроек
    • Изменение неключевых настроек работает без повторного ввода API-ключа.
    • Пустой API-ключ не перетирает существующий ключ.
    • Маскированные ключи запрещены к сохранению.
  2. Провайдеры и модели
    • Ключи OpenRouter/DeepSeek независимы.
    • Модели выбираются через пресеты + ручной ввод.
    • Переключение провайдера не сбрасывает сохраненные ключи.
  3. Диагностика 401
    • При отсутствии ключа пользователь получает понятную подсказку до вызова модели.
    • При 401 Unauthorized возвращается actionable-сообщение с инструкцией проверить ключ.
  4. Проверка ключа
    • В UI кнопка "Проверить ключ" делает реальный API-запрос к backend.
    • Ошибки проверки отображаются явно в модальном окне настроек.

Smoke / Regression чеклист

  1. Открыть настройки, изменить только MAX_TOKENS, сохранить, убедиться что POST /api/settings возвращает ok=true.
  2. Нажать "Проверить ключ" с некорректным ключом, получить внятную ошибку.
  3. Сохранить настройки с маской ****xxxx, убедиться что сервер отклоняет запрос.
  4. Сохранить с пустым ключом, убедиться что ключ не стирается (или сервер возвращает "нет изменений").
  5. Запустить чат и убедиться, что ответ от AI приходит без 401 для валидного ключа.
  6. Проверить GET /api/settings/provider-health.

Структура проекта

project-chat/
├── main.py                 # FastAPI приложение и все роуты
├── ai_client.py           # Клиент для DeepSeek / OpenRouter (SSE)
├── database.py            # Инициализация БД и CRUD-функции
├── config/
│   └── settings.py       # Чтение .env и глобальные константы
├── static/
│   ├── index.html        # Весь фронтенд (три панели)
│   ├── patterns.js       # Регулярные выражения PII
│   ├── anonymizer.js     # Логика анонимизации на клиенте
│   ├── app.js           # Основная логика фронтенда
│   └── style.css        # Стили в темной теме
├── data/                 # Директория данных
│   ├── database.db      # SQLite база
│   └── projects/        # Файлы проектов
├── Dockerfile
├── requirements.txt
├── setup.sh             # Интерактивный скрипт установки
└── README.md

База данных

Схема SQLite:

-- Проекты
CREATE TABLE projects (
    id TEXT PRIMARY KEY,
    name TEXT NOT NULL,
    goal TEXT,
    created_at TEXT NOT NULL,
    updated_at TEXT NOT NULL
);

-- Документы
CREATE TABLE documents (
    id TEXT PRIMARY KEY,
    project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
    name TEXT NOT NULL,
    description TEXT,
    filename TEXT NOT NULL,
    file_type TEXT NOT NULL,
    original_path TEXT,
    anonymized_text TEXT,
    anonymization_log TEXT,
    created_at TEXT NOT NULL,
    status TEXT NOT NULL DEFAULT 'ready'
);

-- Чаты
CREATE TABLE chats (
    id TEXT PRIMARY KEY,
    project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
    name TEXT NOT NULL,
    created_at TEXT NOT NULL
);

-- Сообщения
CREATE TABLE messages (
    id TEXT PRIMARY KEY,
    chat_id TEXT NOT NULL REFERENCES chats(id) ON DELETE CASCADE,
    role TEXT NOT NULL,
    content TEXT NOT NULL,
    created_at TEXT NOT NULL
);

-- Артефакты
CREATE TABLE artifacts (
    id TEXT PRIMARY KEY,
    project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
    chat_id TEXT,
    name TEXT NOT NULL,
    content TEXT NOT NULL,
    file_path TEXT,
    created_at TEXT NOT NULL
);

-- Настройки
CREATE TABLE settings (
    key TEXT PRIMARY KEY,
    value TEXT NOT NULL
);

Анонимизация PII

Приложение использует клиентскую анонимизацию с регулярными выражениями для:

  • Российских телефонов
  • Email адресов
  • ИНН, СНИЛС
  • Паспортных данных
  • Банковских карт
  • Адресов
  • И других персональных данных

Процесс:

  1. Файл обрабатывается на клиенте
  2. PII заменяются на маркеры [PII_TYPE_N]
  3. Создается карта замен
  4. На сервер отправляется анонимизированный текст + карта
  5. Оригинальный файл хранится локально

API эндпоинты

Проекты

  • GET /api/projects - список проектов
  • POST /api/projects - создать проект
  • GET /api/projects/{id} - детали проекта + документы + чаты
  • DELETE /api/projects/{id} - удалить проект

Документы

  • POST /api/projects/{id}/documents - загрузить документ
  • GET /api/projects/{id}/documents - список документов
  • DELETE /api/projects/{id}/documents/{doc_id} - удалить документ

Чаты

  • POST /api/projects/{id}/chats - создать чат
  • GET /api/projects/{id}/chats - список чатов
  • GET /api/projects/{id}/chats/{chat_id}/messages - история сообщений
  • POST /api/projects/{id}/chats/{chat_id}/messages - отправить сообщение (SSE)

Артефакты

  • POST /api/projects/{id}/artifacts - сохранить артефакт
  • GET /api/projects/{id}/artifacts - список артефактов

Настройки

  • GET /api/settings - текущие настройки
  • POST /api/settings - обновить настройки

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

  • Все ID - UUID v4
  • Анонимизация PII на клиенте
  • Валидация API ключей при сохранении
  • Ограничение размера файлов (50 MB)
  • Проверка существования ресурсов
  • SQL инъекции предотвращаются параметризованными запросами

Разработка

Требования

  • Python 3.11+
  • Node.js (для разработки фронтенда)
  • Docker (для контейнеризации)

Установка для разработки

# Клонирование
git clone <repository-url>
cd project-chat

# Виртуальное окружение
python -m venv venv
source venv/bin/activate  # Linux/Mac
# или venv\Scripts\activate  # Windows

# Зависимости
pip install -r requirements.txt

# Запуск
uvicorn main:app --host 0.0.0.0 --port 8000 --reload

Структура фронтенда

Фронтенд реализован на Vanilla JavaScript с использованием:

  • marked.js - рендеринг Markdown
  • highlight.js - подсветка кода
  • PDF.js - обработка PDF файлов
  • CSS Grid/Flexbox - трехпанельный интерфейс

Стабилизация состояния UI

  • Для регрессионной проверки сценариев H1/H2/H5/H3-H4 используйте чеклист: docs/state-stability-checklist.md

Лицензия

MIT

Поддержка

Для сообщений об ошибках и предложений создавайте issue в репозитории проекта.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages