#!/usr/bin/env python3 """ Загрузка сообщений в Meilisearch. Вход: tasks/snowbike-rag/data/messages.jsonl """ import json import sys import time from pathlib import Path import meilisearch MEILI_URL = "http://127.0.0.1:7700" INDEX_NAME = "snowbike_messages" BATCH_SIZE = 1000 DATA_FILE = Path(__file__).parent.parent / "data" / "messages.jsonl" def wait_for_task(client, task_uid, timeout=300): """Ждём завершения задачи Meilisearch.""" start = time.time() while time.time() - start < timeout: task = client.get_task(task_uid) if task.status in ("succeeded", "failed", "canceled"): return task time.sleep(1) raise TimeoutError(f"Task {task_uid} не завершилась за {timeout}с") def setup_index(client): """Создаём и настраиваем индекс.""" try: index = client.get_index(INDEX_NAME) print(f"Индекс '{INDEX_NAME}' уже существует, используем его") except meilisearch.errors.MeilisearchApiError: print(f"Создаём индекс '{INDEX_NAME}'...") task = client.create_index(INDEX_NAME, {"primaryKey": "id"}) wait_for_task(client, task.task_uid) index = client.get_index(INDEX_NAME) print("Индекс создан") # Настройки индекса print("Настраиваем индекс...") task = index.update_settings({ "searchableAttributes": ["text"], "filterableAttributes": ["topic_id", "date", "from_id"], "sortableAttributes": ["date"], "typoTolerance": { "enabled": True, "minWordSizeForTypos": { "oneTypo": 5, "twoTypos": 9 } }, "stopWords": ["и", "в", "на", "с", "для", "это", "что", "как", "не", "а", "но", "или", "по", "из", "от", "до", "при", "за", "об", "так", "же", "то", "ли", "бы", "да", "нет", "все", "они", "мне", "его"] }) wait_for_task(client, task.task_uid) print("Настройки применены") return index def load_messages(): """Загружаем сообщения из JSONL.""" messages = [] if not DATA_FILE.exists(): print(f"ОШИБКА: файл {DATA_FILE} не найден. Сначала запустите parse_messages.py") sys.exit(1) with open(DATA_FILE, "r", encoding="utf-8") as f: for line in f: line = line.strip() if line: messages.append(json.loads(line)) print(f"Загружено {len(messages)} сообщений из JSONL") return messages def index_messages(index, messages): """Индексируем сообщения батчами.""" total = len(messages) indexed = 0 for i in range(0, total, BATCH_SIZE): batch = messages[i:i + BATCH_SIZE] task = index.add_documents(batch) # Ждём каждые 10 батчей или в конце if (i // BATCH_SIZE) % 10 == 9 or i + BATCH_SIZE >= total: wait_for_task(index._http_requests.session.base_url.replace("/", "").replace("http:", "").replace("https:", "").split(":")[0], task.task_uid) indexed += len(batch) progress = (indexed / total) * 100 print(f" Прогресс: {indexed}/{total} ({progress:.1f}%)", end="\r") print(f"\nИндексация завершена: {indexed} сообщений") def index_messages_v2(client, index, messages): """Индексируем сообщения батчами (простой вариант).""" total = len(messages) task_uids = [] print(f"Загружаем {total} сообщений батчами по {BATCH_SIZE}...") for i in range(0, total, BATCH_SIZE): batch = messages[i:i + BATCH_SIZE] task = index.add_documents(batch) task_uids.append(task.task_uid) indexed = min(i + BATCH_SIZE, total) progress = (indexed / total) * 100 print(f" Отправлено: {indexed}/{total} ({progress:.1f}%)", end="\r") print(f"\nОжидаем завершения индексации...") # Ждём последнюю задачу (все предыдущие уже должны быть выполнены) if task_uids: last_task = wait_for_task(client, task_uids[-1], timeout=600) if last_task.status == "succeeded": print(f"Индексация успешна!") else: print(f"ОШИБКА индексации: {last_task.error}") sys.exit(1) # Финальная статистика stats = index.get_stats() print(f"Документов в индексе: {stats.number_of_documents}") def main(): print("=== Meilisearch Индексация ===") # Подключаемся client = meilisearch.Client(MEILI_URL) try: health = client.health() print(f"Meilisearch: {health}") except Exception as e: print(f"ОШИБКА: не могу подключиться к Meilisearch ({MEILI_URL}): {e}") print("Запустите Meilisearch: ./bin/meilisearch --db-path data/meilisearch --http-addr 127.0.0.1:7700 --no-analytics &") sys.exit(1) # Настраиваем индекс index = setup_index(client) # Загружаем данные messages = load_messages() # Индексируем index_messages_v2(client, index, messages) print("\n✓ Готово!") if __name__ == "__main__": main()