2026-06-15 03:15:08 +00:00
2026-06-15 03:15:08 +00:00
2026-06-15 03:15:08 +00:00
2026-06-14 06:26:16 +00:00
2026-06-15 03:15:08 +00:00
2026-06-09 09:36:48 +03:00
2026-06-11 11:55:10 +03:00
2026-06-09 09:36:48 +03:00
2026-06-10 12:03:05 +03:00

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

Порты в .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:9000taiga.grigowashere.ru
  • Gitea: 127.0.0.1:3000git.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 — удалить факт по id
  • update_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 сводка чата

Фитнес-трекер

Профиль, дневник (еда/вода/вес/тренировки), калькуляторы TDEE, LLM-оценка ккал/БЖУ, lookup wger + Open Food Facts, напоминания в чат (💪), вкладка /fitness.

Чат: «обед: гречка 200г, курица 150г», «выпил 300 мл воды», «жим 80×5×3».

Списки покупок

Несколько списков, позиции с количеством, отметка «куплено». Вкладка /shopping, tools в чате (add_shopping_items, list_shopping_lists, …).

Чат: «добавь молоко и хлеб в продукты», «что в списке покупок», «отметь молоко купленным».

Homelab API (фаза 4)

Интеграции с домашней инфраструктурой:

Сервис URL по умолчанию Назначение
Open-Meteo http://192.168.1.109:8085 Погода СПб в контексте и tool get_weather
ComfyUI http://192.168.1.109:8188 fallback / рофл-watcher
RP Chat (aiChatBot) http://host.docker.internal:8201 generate_image: sd-prompt + Anima; appearance в /character
Netdata http://host.docker.internal:19999 Алерты warning/critical → notice в чат

Утренний дайджест (MORNING_DIGEST_HOUR=8): погода + RSS (Habr, r/programming по умолчанию).
По запросу: «что на улице», «будет ли дождь» → get_weather; полный брифинг → get_morning_briefing.

Переменные — в .env.example (секция Homelab).

Проверка доступности

В образе backend нет curl/wget. Удобнее всего — API-диагностика (из контейнера или с хоста):

curl -s http://localhost:${BACKEND_PORT:-8202}/api/v1/homelab/status | python3 -m json.tool

Или изнутри backend через Python:

docker compose exec backend python -c "
import httpx
for url in [
    'http://192.168.1.109:8085/v1/forecast?latitude=59.93&longitude=30.33&current=temperature_2m',
    'http://192.168.1.109:8188/system_stats',
    'http://host.docker.internal:19999/api/v1/info',
]:
    try:
        r = httpx.get(url, timeout=10)
        print(url, '->', r.status_code, r.text[:120])
    except Exception as e:
        print(url, '-> ERROR', e)
"

По умолчанию Anima (как в aiChatBot): COMFYUI_UNET + COMFYUI_CLIP + COMFYUI_VAE + style LoRA.
COMFYUI_CHECKPOINT оставь пустым. Для SD1.5/Pony — укажи checkpoint и очисти COMFYUI_UNET.

Следующие фазы

  • RAG по файлам (Qdrant)
  • Telegram-бот
  • Taiga/fitness в утреннем дайджесте
  • Графики веса, LLM-мотивация в напоминаниях

Модель

По умолчанию: deepseek/deepseek-chat через OpenRouter. Альтернатива для болтовни: google/gemini-2.0-flash.

S
Description
No description provided
Readme 1.2 MiB
Languages
Python 72.5%
TypeScript 22.3%
CSS 5.1%
Dockerfile 0.1%