8.1 KiB
Home AI Assistant
Домашний ИИ-ассистент с REST API, веб-интерфейсом и помидоро-таймером. LLM — OpenRouter (по умолчанию DeepSeek).
Возможности (MVP)
- Чат с потоковыми ответами (SSE)
- Управление помидоро из чата через tool calling
- REST API для внешних клиентов (Telegram-бот, мобильное приложение)
- Веб-морда: вкладки «Чат» и «Помидоро»
Быстрый старт
1. Настройка окружения
cp .env.example .env
Заполните в .env:
OPENROUTER_API_KEY=sk-or-v1-...
BACKEND_PORT=8080
FRONTEND_PORT=3080
Если порт занят (например, 3000 уже используется Gitea), смените FRONTEND_PORT на свободный.
2. Запуск через Docker
docker compose up --build
- Backend API: http://localhost:${BACKEND_PORT:-8080}
- Web UI: http://localhost:${FRONTEND_PORT:-3080}
- Healthcheck: http://localhost:8080/api/v1/health
Порты в .env:
| Переменная | По умолчанию | Назначение |
|---|---|---|
BACKEND_PORT |
8080 | API с хоста |
FRONTEND_PORT |
3080 | Веб-морда с хоста |
VITE_DEV_PORT |
5173 | Frontend при npm run dev |
TAIGA_PORT |
9000 | Taiga (фаза 2) |
GITEA_PORT |
3000 | Gitea HTTP (фаза 2) |
GITEA_SSH_PORT |
222 | Gitea SSH (фаза 2) |
QDRANT_PORT |
6333 | Qdrant HTTP (фаза 3) |
3. Локальная разработка
Backend:
cd backend
python -m venv .venv
.venv\Scripts\activate # Windows
pip install -r requirements.txt
uvicorn app.main:app --reload --port 8080
Frontend:
cd frontend
npm install
npm run dev
Vite dev-server: http://localhost:5173 (проксирует /api на backend).
REST API
| Method | Path | Описание |
|---|---|---|
| GET | /api/v1/health |
Healthcheck |
| POST | /api/v1/chat/sessions |
Создать чат-сессию |
| GET | /api/v1/chat/sessions |
Список сессий |
| GET | /api/v1/chat/sessions/{id} |
История сообщений |
| POST | /api/v1/chat/sessions/{id}/messages |
Отправить сообщение (SSE) |
| DELETE | /api/v1/chat/sessions/{id} |
Удалить сессию |
| GET | /api/v1/pomodoro/status |
Статус таймера |
| POST | /api/v1/pomodoro/start |
Старт {duration_min, task_note} |
| POST | /api/v1/pomodoro/pause |
Пауза |
| POST | /api/v1/pomodoro/resume |
Продолжить |
| POST | /api/v1/pomodoro/stop |
Стоп {result, completed} |
| GET | /api/v1/pomodoro/history |
История сессий |
| GET | /api/v1/projects |
Проекты Taiga + привязка Gitea |
| POST | /api/v1/projects/sync-taiga |
Синхронизировать проекты из Taiga |
| PUT | /api/v1/projects/{slug}/gitea |
Привязать Gitea repo |
| POST | /api/v1/work-items |
Создать фичу/баг → Taiga + Gitea |
| GET | /api/v1/work-items |
Список work items |
| POST | /api/v1/webhooks/gitea |
Webhook для автозакрытия по push |
Taiga + Gitea (фаза 2)
Taiga и Gitea работают на хосте (не в Docker):
- Taiga:
127.0.0.1:9000→taiga.grigowashere.ru - Gitea:
127.0.0.1:3000→git.grigowashere.ru
Контейнер backend достучится через host.docker.internal (настроено в docker-compose.yml).
Настройка .env
TAIGA_BASE_URL=http://host.docker.internal:9000
TAIGA_USERNAME=...
TAIGA_PASSWORD=...
TAIGA_PUBLIC_URL=https://taiga.grigowashere.ru
GITEA_BASE_URL=http://host.docker.internal:3000
GITEA_TOKEN=... # Settings → Applications → Generate Token
GITEA_PUBLIC_URL=https://git.grigowashere.ru
GITEA_WEBHOOK_SECRET=... # произвольная строка
Первый запуск
# 1. Синхронизировать проекты Taiga (ID подтянутся автоматически)
curl -X POST http://localhost:8080/api/v1/projects/sync-taiga
# 2. Привязать Gitea repo к проекту Taiga
curl -X PUT http://localhost:8080/api/v1/projects/home-assistant/gitea \
-H "Content-Type: application/json" \
-d '{"gitea_owner":"Grigo","gitea_repo":"Home_assistant","default_branch":"main"}'
Gitea webhook
В репозитории: Settings → Webhooks → Add Webhook:
- URL (выбери один вариант):
- Рекомендуется:
https://assistant.example.com/api/v1/webhooks/gitea— nginx →127.0.0.1:${BACKEND_PORT} - Если Gitea в Docker:
http://172.17.0.1:${BACKEND_PORT}/api/v1/webhooks/gitea— не127.0.0.1(это localhost контейнера Gitea)
- Рекомендуется:
- Content type:
application/json - Secret: значение
GITEA_WEBHOOK_SECRET - Events: Push
Проверка из контейнера Gitea: docker exec gitea wget -qO- http://172.17.0.1:8202/api/v1/health
Test delivery в Gitea должен вернуть 200, не 0.
Автозакрытие по коммиту
В сообщении коммита:
fix: кнопка сохранения
Closes gitea #12, taiga #45
Закроются Gitea issue #12 и Taiga story #45 (если только один ref — второй найдётся по связи в БД).
Чат
«Заведи баг: кнопка не сохраняет настройки» → create_work_item → Taiga story + Gitea issue + ветка feature/45-....
Структура проекта
backend/ FastAPI, OpenRouter, SQLite, помидоро
frontend/ React + Vite, чат и таймер
data/ SQLite БД (создаётся автоматически)
Память и контекст (фаза 3a)
Долгосрочная память в SQLite, без векторов:
| Слой | Что хранит |
|---|---|
| Профиль | имя, timezone, language, notes |
| Факты | устойчивые знания с категорией и важностью |
| Сводка чата | краткое содержание длинной сессии |
В system prompt на каждый ответ: персонаж → память → помидоро → проекты.
История чата обрезается до 40 последних сообщений; раннее — в session_summaries.
Автоизвлечение: после каждого ответа LLM анализирует ход диалога и сохраняет
устойчивые факты (source=auto). Отключить: MEMORY_AUTO_EXTRACT=false.
UI: вкладка /memory — профиль, факты, JSON-снимок для отладки.
Tools
remember_fact— «запомни, что…»recall_memories— поиск по памятиforget_memory— удалить факт по idupdate_profile— имя, часовой пояс и т.д.update_session_summary— сжать тему длинного чата
API
| Method | Path | Описание |
|---|---|---|
| GET | /api/v1/memory |
снимок памяти (+ ?session_id=) |
| GET/PUT | /api/v1/profile |
профиль |
| GET/POST | /api/v1/memory/facts |
список / создать факт |
| DELETE | /api/v1/memory/facts/{id} |
забыть |
| PUT | /api/v1/memory/sessions/{id}/summary |
сводка чата |
Следующие фазы
- Фаза 4: инструменты с обращением к внешним API
- Фаза 5: RAG по файлам, Qdrant (если понадобится семантика)
- Проактивные чаты по расписанию
- Фитнес-трекер
Модель
По умолчанию: deepseek/deepseek-chat через OpenRouter. Альтернатива для болтовни: google/gemini-2.0-flash.