142 lines
4.7 KiB
Markdown
142 lines
4.7 KiB
Markdown
# 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))
|
||
```
|