{ "cells": [ { "cell_type": "code", "execution_count": 1, "id": "477f0fa2", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pandas as pd\n", "import os \n", "from dotenv import load_dotenv\n", "from tqdm import tqdm\n", "\n", "load_dotenv()" ] }, { "cell_type": "code", "execution_count": 2, "id": "ce00fa3f-b017-4dd9-b39b-fc106ff59c61", "metadata": {}, "outputs": [], "source": [ "import sys\n", "from pathlib import Path\n", "\n", "SRC_ROOT = Path().resolve().parents[1]\n", "\n", "sys.path.insert(0, str(SRC_ROOT))\n" ] }, { "cell_type": "code", "execution_count": 3, "id": "28a9a5e2", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/Users/kirill/rag_tg_2025/env/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", " from .autonotebook import tqdm as notebook_tqdm\n", "/Users/kirill/rag_tg_2025/src/config.py:41: UserWarning: Qdrant client version 1.16.2 is incompatible with server version 1.14.1. Major versions should match and minor version difference must not exceed 1. Set check_compatibility=False to skip version check.\n", " qdrant_client = QdrantClient(url=QDRANT_URL)\n" ] } ], "source": [ "from src.evaluation.qa_evaluator import QAEvaluator\n", "from src.rag.rag import RAG" ] }, { "cell_type": "code", "execution_count": 4, "id": "8c548b19-ad11-4515-95dc-1ae687baaff7", "metadata": {}, "outputs": [], "source": [ "rag = RAG(\n", " embed_model_name = \"Qwen/Qwen3-Embedding-0.6B\",\n", " embed_index_name = \"recursive_Qwen3-Embedding-0.6B\"\n", ")" ] }, { "cell_type": "code", "execution_count": 5, "id": "b12d7862-83e2-4fde-a322-892512303e25", "metadata": {}, "outputs": [], "source": [ "test_cases = pd.read_csv(r'/Users/kirill/rag_tg_2025/src/dataset/test_cases.csv')" ] }, { "cell_type": "code", "execution_count": 6, "id": "05fc2a82-27d4-4103-9044-a5b0298956f4", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
message_idoriginal_textstrict_questionreal_question
0130738Итальянский суд принял решение экстрадировать ...Какое решение приняло итальянское судопроизвод...Что там с Кузнецовым — его в Германию выдадут ...
1129361Пять пассажиров автобуса №793 пострадали в ДТП...Сколько пассажиров автобуса №793 пострадали в ...Сколько человек в автобусе 793 пострадали, ког...
2133468Владимир Путин утвердил концепцию государствен...Кто утвердил концепцию государственной миграци...Кто там утвердил новую миграционную концепцию ...
3123139Генпрокуратура и Минюст подали в Верховный суд...Какое юридическое действие предприняли Генерал...Что Генпрокуратура и Минюст сделали с сатанист...
4129894Обломки дрона обнаружили польские пограничники...Где и кем был обнаружен непилотируемый летател...Что там польские пограничники нашли рядом с Бе...
\n", "
" ], "text/plain": [ " message_id original_text \\\n", "0 130738 Итальянский суд принял решение экстрадировать ... \n", "1 129361 Пять пассажиров автобуса №793 пострадали в ДТП... \n", "2 133468 Владимир Путин утвердил концепцию государствен... \n", "3 123139 Генпрокуратура и Минюст подали в Верховный суд... \n", "4 129894 Обломки дрона обнаружили польские пограничники... \n", "\n", " strict_question \\\n", "0 Какое решение приняло итальянское судопроизвод... \n", "1 Сколько пассажиров автобуса №793 пострадали в ... \n", "2 Кто утвердил концепцию государственной миграци... \n", "3 Какое юридическое действие предприняли Генерал... \n", "4 Где и кем был обнаружен непилотируемый летател... \n", "\n", " real_question \n", "0 Что там с Кузнецовым — его в Германию выдадут ... \n", "1 Сколько человек в автобусе 793 пострадали, ког... \n", "2 Кто там утвердил новую миграционную концепцию ... \n", "3 Что Генпрокуратура и Минюст сделали с сатанист... \n", "4 Что там польские пограничники нашли рядом с Бе... " ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "test_cases.head()" ] }, { "cell_type": "code", "execution_count": 7, "id": "93c8f6dc-b210-43b6-ba0d-f555a82e1c93", "metadata": {}, "outputs": [], "source": [ "evaluator = QAEvaluator(\n", " df=test_cases,\n", " text_column=\"original_text\",\n", " temperature=0.0,\n", " api_key=os.getenv(\"OPENROUTER_API_KEY\")\n", ")\n" ] }, { "cell_type": "code", "execution_count": 8, "id": "4e5b93dd-98a2-44ae-862b-41af1ed9f15d", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Всего батчей: 11\n" ] } ], "source": [ "batch_size = 16\n", "question_iterator = evaluator.get_questions(\n", " question_column=\"strict_question\", # или \"real_question\"\n", " batch_size=batch_size\n", ")\n", "\n", "print(f\"Всего батчей: {len(question_iterator)}\")" ] }, { "cell_type": "code", "execution_count": 10, "id": "ffc71d69-c387-4cb4-8dc9-23c197398440", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "100%|█████████████████████████████████████████████████████████████████████████████████| 167/167 [09:47<00:00, 3.52s/it]\n" ] } ], "source": [ "generated_answers = []\n", "\n", "for query in tqdm(test_cases[\"real_question\"]):\n", " results = rag.invoke(query)\n", " generated_answers.append(\n", " (results[\"answer\"], results[\"reason\"])\n", " )" ] }, { "cell_type": "code", "execution_count": 11, "id": "117fabac-a952-40f6-ad3d-0cf74994040d", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
message_idoriginal_textstrict_questionreal_questiongenerated_answergenerated_reason
0130738Итальянский суд принял решение экстрадировать ...Какое решение приняло итальянское судопроизвод...Что там с Кузнецовым — его в Германию выдадут ...Нет, его не выдадут в Германию — решение об эк...Кассационный суд Италии отменил решение апелля...
1129361Пять пассажиров автобуса №793 пострадали в ДТП...Сколько пассажиров автобуса №793 пострадали в ...Сколько человек в автобусе 793 пострадали, ког...ПятьВ контексте в первом пункте указано, что пять ...
2133468Владимир Путин утвердил концепцию государствен...Кто утвердил концепцию государственной миграци...Кто там утвердил новую миграционную концепцию ...Владимир ПутинВ контексте в первом пункте прямо указано, что...
3123139Генпрокуратура и Минюст подали в Верховный суд...Какое юридическое действие предприняли Генерал...Что Генпрокуратура и Минюст сделали с сатанист...Генпрокуратура и Минюст подали в Верховный суд...В контексте указано, что Генеральная прокурату...
4129894Обломки дрона обнаружили польские пограничники...Где и кем был обнаружен непилотируемый летател...Что там польские пограничники нашли рядом с Бе...Да, польские пограничники нашли дрон с надпися...Согласно контексту (пункт 1), обломки дрона об...
\n", "
" ], "text/plain": [ " message_id original_text \\\n", "0 130738 Итальянский суд принял решение экстрадировать ... \n", "1 129361 Пять пассажиров автобуса №793 пострадали в ДТП... \n", "2 133468 Владимир Путин утвердил концепцию государствен... \n", "3 123139 Генпрокуратура и Минюст подали в Верховный суд... \n", "4 129894 Обломки дрона обнаружили польские пограничники... \n", "\n", " strict_question \\\n", "0 Какое решение приняло итальянское судопроизвод... \n", "1 Сколько пассажиров автобуса №793 пострадали в ... \n", "2 Кто утвердил концепцию государственной миграци... \n", "3 Какое юридическое действие предприняли Генерал... \n", "4 Где и кем был обнаружен непилотируемый летател... \n", "\n", " real_question \\\n", "0 Что там с Кузнецовым — его в Германию выдадут ... \n", "1 Сколько человек в автобусе 793 пострадали, ког... \n", "2 Кто там утвердил новую миграционную концепцию ... \n", "3 Что Генпрокуратура и Минюст сделали с сатанист... \n", "4 Что там польские пограничники нашли рядом с Бе... \n", "\n", " generated_answer \\\n", "0 Нет, его не выдадут в Германию — решение об эк... \n", "1 Пять \n", "2 Владимир Путин \n", "3 Генпрокуратура и Минюст подали в Верховный суд... \n", "4 Да, польские пограничники нашли дрон с надпися... \n", "\n", " generated_reason \n", "0 Кассационный суд Италии отменил решение апелля... \n", "1 В контексте в первом пункте указано, что пять ... \n", "2 В контексте в первом пункте прямо указано, что... \n", "3 В контексте указано, что Генеральная прокурату... \n", "4 Согласно контексту (пункт 1), обломки дрона об... " ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "test_cases[\"generated_answer\"] = [p[0] for p in generated_answers]\n", "test_cases[\"generated_reason\"] = [p[1] for p in generated_answers]\n", "test_cases.head()" ] }, { "cell_type": "code", "execution_count": 12, "id": "5e32d246-9a16-4ffc-95c8-542a400efe33", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Оценка ответов: 4%|██▊ | 7/167 [00:18<10:24, 3.90s/it]" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Ошибка при оценке ответа: Failed to parse AnswerEvaluation from completion {}. Got: 4 validation errors for AnswerEvaluation\n", "is_valid\n", " Field required [type=missing, input_value={}, input_type=dict]\n", " For further information visit https://errors.pydantic.dev/2.9/v/missing\n", "relevance_score\n", " Field required [type=missing, input_value={}, input_type=dict]\n", " For further information visit https://errors.pydantic.dev/2.9/v/missing\n", "completeness_score\n", " Field required [type=missing, input_value={}, input_type=dict]\n", " For further information visit https://errors.pydantic.dev/2.9/v/missing\n", "factual_accuracy_score\n", " Field required [type=missing, input_value={}, input_type=dict]\n", " For further information visit https://errors.pydantic.dev/2.9/v/missing\n", "For troubleshooting, visit: https://python.langchain.com/docs/troubleshooting/errors/OUTPUT_PARSING_FAILURE \n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "Оценка ответов: 100%|█████████████████████████████████████████████████████████████████| 167/167 [03:53<00:00, 1.40s/it]\n" ] } ], "source": [ "answers = test_cases[\"generated_answer\"]\n", "metrics = evaluator.evaluate_answers(answers, show_progress=True)" ] }, { "cell_type": "code", "execution_count": 13, "id": "342b07de-a8e5-4336-a83d-611abd192aff", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
total_questionsvalid_answersaccuracyavg_relevanceavg_completenessavg_factual_accuracycombined_score
01671250.7485030.8796410.6976050.8053890.794212
\n", "
" ], "text/plain": [ " total_questions valid_answers accuracy avg_relevance avg_completeness \\\n", "0 167 125 0.748503 0.879641 0.697605 \n", "\n", " avg_factual_accuracy combined_score \n", "0 0.805389 0.794212 " ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "metrics_df = pd.DataFrame(\n", " data=[(\n", " metrics[\"total_questions\"], metrics[\"valid_answers\"], metrics[\"accuracy\"],\\\n", " metrics[\"avg_relevance\"], metrics[\"avg_completeness\"], metrics[\"avg_factual_accuracy\"], \\\n", " metrics[\"combined_score\"]\n", " )],\n", " columns=[\"total_questions\", \"valid_answers\", \"accuracy\", \"avg_relevance\", \"avg_completeness\", \\\n", " \"avg_factual_accuracy\", \"combined_score\"]\n", ")\n", "metrics_df" ] }, { "cell_type": "code", "execution_count": 32, "id": "488b4f03-556a-42a5-811a-1fbe36c5f7be", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
indexquestionansweris_validrelevance_scorecompleteness_scorefactual_accuracy_score
112112На каком уровне оказалась цена нефти марки Ura...Да, цена российской нефти марки Urals в Новоро...True1.00.51.0
3737Согласно официальному сообщению Росавиации, ка...В аэропорту Ярославля введены временные ограни...True1.01.01.0
140140По какому инциденту Следственный комитет Росси...Следственный комитет завел уголовное дело по ф...True1.01.01.0
00Какое решение приняло итальянское судопроизвод...Не знаю.False0.50.00.0
9898Что произошло на фестивале в Пенсильвании, США...На фестивале в Пенсильвании минивэн въехал в т...True1.01.01.0
\n", "
" ], "text/plain": [ " index question \\\n", "112 112 На каком уровне оказалась цена нефти марки Ura... \n", "37 37 Согласно официальному сообщению Росавиации, ка... \n", "140 140 По какому инциденту Следственный комитет Росси... \n", "0 0 Какое решение приняло итальянское судопроизвод... \n", "98 98 Что произошло на фестивале в Пенсильвании, США... \n", "\n", " answer is_valid \\\n", "112 Да, цена российской нефти марки Urals в Новоро... True \n", "37 В аэропорту Ярославля введены временные ограни... True \n", "140 Следственный комитет завел уголовное дело по ф... True \n", "0 Не знаю. False \n", "98 На фестивале в Пенсильвании минивэн въехал в т... True \n", "\n", " relevance_score completeness_score factual_accuracy_score \n", "112 1.0 0.5 1.0 \n", "37 1.0 1.0 1.0 \n", "140 1.0 1.0 1.0 \n", "0 0.5 0.0 0.0 \n", "98 1.0 1.0 1.0 " ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.DataFrame(metrics[\"detailed_results\"]).sample(5)" ] }, { "cell_type": "code", "execution_count": null, "id": "731e781a", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "76ed2ec5", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.12" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": true, "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 5 }