- Установите зависимости:
pip install -r requirements.txt - Поднимите OpenSearch:
docker-compose up -d - (Опционально, есть предзагруженные новости в ./data) Если хотите загрузить свежие новости из телеграмма в папку
dataиспользуйтеnews_parser.py, вызовите командуpython news_parser.py --api-id **** --api-hash **** --channel @minsportrf --limit 2000 --out minsportrf_messages.jsonдля выгрузки свежих новостей канала minsportrf. Получитеapi-idиapi-hashтелеграмма через сайтhttps://my.telegram.org/authили по туториалуhttps://tlgrm.ru/docs/api/obtaining_api_id.URLоставьте пустым, вplatformнапишите other. - (опционально) Укажите переменные окружения:
DATA_PATH— путь к директории с JSON-файлами (по умолчанию берётся./dataиз корня репозитория)NEWS_INDEX_NAME— имя индекса OpenSearchFORCE_REBUILD_NEWS_INDEX=1— чтобы принудительно переиндексировать данные при старте сервераOPENSEARCH_RETRY_ATTEMPTS/OPENSEARCH_RETRY_DELAY— сколько раз и с каким интервалом API ждёт доступности OpenSearchMISTRAL_API_KEY— ключ доступа к Mistral API (см. пример вapi_testing.ipynb)
- Запустите API:
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
Все переменные можно задать в
.env(см. пример в корне репозитория) — сервер автоматически подхватывает этот файл при старте. Логи сохраняются вbuild/rag_db.log, а каждый ответ API записывается в директориюoutputs/.
Эндпоинты:
GET /health— проверка статуса и кол-ва документов в индексеGET /news/latest?limit=5— последние новости по датеGET /news/{id}— получить конкретное сообщениеPOST /news/query— поиск по коллекции (LLM решает стратегию, опционально можно задатьforce_mode=vector|text)
После запуска uvicorn можно выполнить запрос на поиск:
curl -s -X POST http://localhost:8000/news/query \
-H "Content-Type: application/json" \
-d '{"query": "Последние новости России", "limit": 3, "force_mode": "vector"}' \
> /dev/null && python scripts/show_summary.pyДля удобства есть скрипт. Сначала указываете текст, потом количество новостей:
./scripts/query_news.sh "Последние новости России" 5Пример ответа (усечённый):
{
"query": "санкции против отрасли",
"limit": 3,
"count": 3,
"results": [
{
"id": "2145",
"date": "2024-05-12T09:47:00",
"text": "…сообщение из Telegram…",
"views": 1234,
"forwards": 56,
"has_media": false,
"channel_title": "MyChannel",
"channel_username": "@mychannel",
"score": 18.42
}
]
}scripts/show_summary.py берёт самый свежий файл outputs/answer_YYYYMMDD-HHMMSS.json (или путь, переданный аргументом) и выводит аккуратно отформатированную сводку + топ новостей на терминал.
- Принимаем запрос. Пользователь вызывает
POST /news/queryс текстом вопроса. - LLM формирует стратегию. Агент на базе
mistral-large-latestрешает, использовать ли SQL, векторный или текстовый поиск и возвращает JSON-план. - Ищем по БД. Согласно плану выполняются SQL/векторные/BM25 запросы к OpenSearch (данные из
mychannel_messages.jsonзаранее проиндексированы). - LLM извлекает факты и суммаризирует. Первый прогон агента вытаскивает сырое содержание из найденных сообщений, второй строит итоговую сводку. Оба текста (
extracted_informationиsummary) возвращаются вместе с исходными документами.
Функции модуля:
- семантический (векторный) поиск
- SQL-like запросы через Elasticsearch SQL endpoint
- Ctrl+F (фразовый / полнотекстовый) поиск
Метрики нужны для оценки качества двух основных элементов нашей RAG системы, а именно, качества отбора новостей из базы данных по запросу и качества фильтрации оценочных суждений. Для оценки качества отбора новостей, используется relevance_ratio - отношение количества новостей после фильтрации и изначального количества подобранных новостей по запросу. Заметим, что низкие значения этой метрики могут быть связаны и с тем, что запрос очень специфический и на него не нашлось подходящих новостей. Однако, при достаточно общем запросе, эта метрика оценивает качество отбора новостей. Для оценки качества фильтрации оценочных суждений используется предобученая модель https://huggingface.co/GroNLP/mdebertav3-subjectivity-multilingual - модель классификации теста на два класса: субъективный или объективный. Под объективностью новости будем понимать вероятность того, что новость объективна, согласно предсказанию модели. Мы используем несколько метрик, для оценки качества фильтрации оценочных суждений: avg_orig_objectivity - средняя объективность отобранных новостей до фильтрации, avg_filtered_objectivity - средняя объективность фильтрованных новостей. avg_irrelevant_objectivity - средняя объективность отброшенных новостей, ratio_subj_to_obj - доля изначально субъективных новостей, которые были преобразованны в объективные и ratio_obj_to_subj - доля изначально объективных новостей, которые были преобразованны в субъективные.