This commit is contained in:
Тимур Абайдулин
2026-03-10 16:33:39 +03:00
commit 84b8246562
11 changed files with 1898 additions and 0 deletions

141
README.md Normal file
View File

@@ -0,0 +1,141 @@
# wiki_embedding
Семантический поиск по страницам Яндекс Вики через pgvector + OpenAI embeddings.
## Что делает
- Обходит раздел «Управление Аналитики» Яндекс Вики через API и Playwright
- Сохраняет содержимое страниц в Supabase (PostgreSQL)
- Генерирует векторные embeddings через OpenAI `text-embedding-3-small`
- Позволяет делать семантический поиск по ~700 страницам на русском и английском
## Стек
| Компонент | Технология |
|-----------|-----------|
| Хранилище | Supabase (PostgreSQL 17) |
| Векторный поиск | pgvector, cosine similarity (`<=>`) |
| Embeddings | OpenAI `text-embedding-3-small` (1536 dims) |
| Wiki API | Яндекс Вики API v1 (`api.wiki.yandex.net/v1`) |
| Браузерный краулер | Playwright + Chromium headless |
| Язык | Python 3.12 |
## Структура файлов
```
wiki_embedding/
├── wiki_sync.py # Главный скрипт синхронизации (API → Supabase → embeddings)
├── wiki_embeddings.py # Генерация embeddings и семантический поиск
├── yandex_wiki.py # Краулер через Яндекс Вики API v1
├── wiki_tree_crawler.py # Playwright-краулер для страниц с {% tree %}
├── wiki_check_slugs.py # Проверка покрытия ROOT_SLUGS
├── wiki_auth.py # Сохранение браузерной сессии для Playwright
├── supabase.py # SupabaseManager — подключение и операции с БД
├── requirements.txt # Зависимости
└── .env # Credentials (не коммитить)
```
## Настройка
### 1. Установить зависимости
```bash
pip install -r requirements.txt
playwright install chromium
```
### 2. Создать .env
```
# Яндекс OAuth-токен (работает для Трекера и Вики)
YT=y0_...
ORG_ID=7405124
# Supabase
SUPABASE_HOST=aws-1-eu-north-1.pooler.supabase.com
SUPABASE_PORT=5432
SUPABASE_USER=postgres.xeakxxnriopsmaxdioke
SUPABASE_PASSWORD=...
SUPABASE_DB=postgres
# OpenAI
OPENAI_API_KEY=sk-...
```
### 3. Сохранить браузерную сессию (один раз)
```bash
python wiki_auth.py
```
Откроется браузер — залогинься в wiki.yandex.ru, нажми Enter.
## Запуск
### Полная синхронизация
```bash
python wiki_sync.py
```
Обходит все 642 slug-а из `ROOT_SLUGS`, обновляет `wiki_pages`, генерирует embeddings.
### Обнаружить новые страницы через Playwright
```bash
python wiki_tree_crawler.py
```
Открывает страницы с `{% tree %}` в headless-браузере, находит дочерние slug-и которых нет в базе.
### Проверить покрытие
```bash
python wiki_check_slugs.py
```
Показывает какие `{% tree %}` страницы не покрыты ROOT_SLUGS.
### Семантический поиск (из кода)
```python
import sys
sys.path.insert(0, '/Users/at/code/wiki_embedding')
from supabase import SupabaseManager
from wiki_embeddings import search
db = SupabaseManager()
db.connect()
results = search(db, 'твой запрос', limit=5)
for r in results:
print(r['similarity'], r['title'])
print(r['content_text'][:500])
db.close()
```
Similarity > 0.5 — хорошее совпадение.
## Cron (ежедневная синхронизация)
```
0 3 * * * cd /Users/at/code/wiki_embedding && /usr/bin/python3 wiki_sync.py >> logs/wiki_sync.log 2>&1
```
## Как устроен поиск
1. При индексировании каждая страница → вектор через OpenAI (title + content)
2. При поиске запрос → вектор тем же способом
3. pgvector находит страницы с минимальным косинусным расстоянием (`<=>`)
4. Возвращается `1 - distance` как similarity (0..1)
Точный поиск без индекса (IVFFlat не используется — при < 10k векторов даёт плохие результаты).
## Схема БД
```sql
-- Содержимое страниц
wiki_pages (id, slug, title, page_type, modified_at, content_hash, value JSONB)
-- Векторные embeddings
wiki_embeddings (id, slug, title, content_text, content_hash, embedding vector(1536))
```