Руководство по тестовой платформе

Версия 3.0 — комплексная платформа оценки гибридного поиска и сценарного тестирования.

Содержание

Обзор

Тестовая платформа предоставляет несколько инструментов оценки:

  1. Бенчмарк гибридного поиска — сравнение векторного, графового и гибридного режимов
  2. Комплексный раннер бенчмарков — сценарная оценка с 20 наборами эталонных данных
  3. Бенчмарк классификации интентов — оценка точности классификатора интентов
  4. Бенчмарк символьного выполнения — измерение влияния V2 на taint-анализ
  5. Бенчмарк LLM-дизамбигуации — тестирование классификатора с поддержкой LLM

Быстрый старт

1. Запуск бенчмарка гибридного поиска

python scripts/benchmark_hybrid_retrieval.py --output-dir benchmark_results

Результат:

================================================================================
BENCHMARK SUMMARY
================================================================================
Metric               Vector       Graph        Hybrid       vs Vector    vs Graph
--------------------------------------------------------------------------------
Precision@10         0.2182       0.2000       0.3000       +37.5%       +50.0%
Recall@10            0.4327       0.3543       0.5528       +27.8%       +56.0%
F1@10                0.2864       0.2510       0.3825       +33.6%       +52.4%
MRR                  1.0000       0.6364       1.0000       +0.0%        +57.1%
NDCG@10              0.5304       0.4443       0.6590       +24.3%       +48.3%

2. Запуск комплексного бенчмарка

# Все сценарии, вопросы на русском
python -m tests.benchmark.run_benchmark --language ru

# Быстрый режим (5 вопросов на сценарий)
python -m tests.benchmark.run_benchmark -q --language ru

# Конкретные сценарии
python -m tests.benchmark.run_benchmark --scenarios 01,02,03

3. Запуск с реальными данными (Python API)

from scripts.benchmark_hybrid_retrieval import HybridRetrievalBenchmark
from src.retrieval.vector_store_real import VectorStoreReal
from src.services.cpg_query_service import CPGQueryService

# Инициализация хранилищ
vector_store = VectorStoreReal(persist_directory="chroma_db")
cpg_service = CPGQueryService()

# Создание и запуск бенчмарка
benchmark = HybridRetrievalBenchmark(
    vector_store=vector_store,
    cpg_service=cpg_service,
    output_dir="benchmark_results"
)

import asyncio
report = asyncio.run(benchmark.run_benchmark())
benchmark.save_report(report)

Бенчмарк гибридного поиска

Бенчмарк гибридного поиска (scripts/benchmark_hybrid_retrieval.py) сравнивает три режима: - Только векторный: семантический поиск через ChromaDB - Только графовый: структурный поиск через DuckDB/CPG - Гибридный: комбинация обоих через RRF

Ключевые классы: - HybridRetrievalBenchmark(vector_store, cpg_service, output_dir="benchmark_results") — оркестратор - BenchmarkQuery — запрос с эталонными данными - RetrievalMetrics — метрики для одного запроса - BenchmarkReport — агрегированный отчёт

Аргументы CLI:

python scripts/benchmark_hybrid_retrieval.py [OPTIONS]
Аргумент По умолчанию Описание
--db-path активный проект Путь к DuckDB CPG
--chroma-path chroma_db Путь к ChromaDB
--output-dir benchmark_results Директория для результатов
--modes vector_only graph_only hybrid Режимы поиска

Комплексный раннер бенчмарков

Основной инструмент (tests/benchmark/run_benchmark.py) запускает сценарную оценку всего конвейера CodeGraph.

python -m tests.benchmark.run_benchmark [OPTIONS]

Аргументы CLI:

Аргумент Кратко По умолчанию Описание
--project None Имя проекта (автопереключение)
--scenarios -s все Сценарии через запятую (01,02,03)
--language -l все Фильтр по языку (en/ru)
--difficulty -d все Фильтр: easy/medium/hard/expert
--max-questions -n без лимита Макс. вопросов на сценарий
--quick -q Быстрый режим (5 вопросов)
--mock -m Мок-копилот для тестирования
--trace -t true Трассировка
--no-trace Отключить трассировку
--ragas -r Оценка RAGAS через LLM
--provider -p из конфига Поставщик LLM (gigachat/yandex/openai/local)
--failed-from Перезапуск провалившихся из предыдущего запуска
--question-ids Конкретные ID вопросов
--offset 0 Пропустить N вопросов
--randomize Случайный выбор вопросов

Примеры:

# Перезапуск провалившихся вопросов
python -m tests.benchmark.run_benchmark --failed-from 20260119_073256

# Вопросы 7-12 (пропустить 6, взять 6)
python -m tests.benchmark.run_benchmark --offset 6 --max-questions 6

# Случайная выборка (3 вопроса на сценарий)
python -m tests.benchmark.run_benchmark --randomize --max-questions 3

# Конкретные ID вопросов
python -m tests.benchmark.run_benchmark --question-ids "VULN_EN_002,VULN_EN_004"

Выбор поставщика LLM

Раннер бенчмарков поддерживает несколько поставщиков LLM для оценки RAGAS через аргумент --provider.

Поддерживаемые поставщики

Поставщик Флаг Переменные окружения Модель
GigaChat --provider gigachat GIGACHAT_API_KEY или GIGACHAT_CREDENTIALS GigaChat-2-Pro
Yandex --provider yandex YANDEX_API_KEY, YANDEX_FOLDER_ID qwen3-235b-a22b-fp8/latest
OpenAI --provider openai OPENAI_API_KEY gpt-4
Локальный --provider local LOCAL_MODEL_PATH совместимо с llama.cpp

Примеры использования

# Запуск с Yandex (модель Qwen3)
python -m tests.benchmark.run_benchmark --provider yandex --ragas

# Запуск с GigaChat
python -m tests.benchmark.run_benchmark --provider gigachat --ragas

# Запуск с OpenAI
python -m tests.benchmark.run_benchmark --provider openai --ragas

# Быстрый запуск без RAGAS
python -m tests.benchmark.run_benchmark --provider yandex -q

Конфигурация поставщиков

Поставщики настраиваются в config.yaml:

llm:
  provider: yandex  # Поставщик по умолчанию

  yandex:
    api_key: ${YANDEX_API_KEY}
    folder_id: ${YANDEX_FOLDER_ID}
    model: "qwen3-235b-a22b-fp8/latest"
    base_url: "https://llm.api.cloud.yandex.net/v1"
    timeout: 60

  gigachat:
    auth_key: ${GIGACHAT_AUTH_KEY}
    model: "GigaChat-2-Pro"

  openai:
    api_key: ${OPENAI_API_KEY}
    model: "gpt-4"

Замечания по поставщикам

Yandex Cloud AI Studio: - Использует API, совместимое с OpenAI - Модель по умолчанию: Qwen3 235B (высокое качество) - Соответствует требованиям конфиденциальности: логирование отключено - Поддерживает запросы на русском языке

GigaChat: - Российская языковая модель от Сбера - Наилучший выбор для контента на русском языке - На некоторых системах требуется обработка сертификатов

Локальные модели: - Через llama.cpp / llama-cpp-python - Без затрат на API, полностью автономно - Требует GPU или достаточной мощности CPU

Набор данных для тестирования

Бенчмарк гибридного поиска включает 11 запросов четырёх типов:

Семантические запросы (4 запроса)

Ориентированы на понимание смысла и документации: - “How does PostgreSQL handle transaction commits?” - “What is the purpose of the buffer manager?” - “How does PostgreSQL implement multi-version concurrency control?” - “How does the query optimizer choose between index scan and sequential scan?” (смешанный)

Ожидаемое поведение: - Только векторный: Высокая эффективность (релевантность 80-90%) - Только графовый: Низкая эффективность (релевантность 20-30%) - Гибридный: Наилучшая эффективность

Структурные запросы (4 запроса)

Ориентированы на обход графа и анализ зависимостей: - “Show me the call path from BeginTransactionBlock to CommitTransactionCommand” - “Find all functions that call malloc” - “What are the indirect callers of MemoryContextAlloc (depth 2-3)?” - “Trace the execution path for a SELECT statement with WHERE clause” (смешанный)

Ожидаемое поведение: - Только векторный: Низкая эффективность (релевантность 20-30%) - Только графовый: Высокая эффективность (релевантность 80-90%) - Гибридный: Наилучшая эффективность

Запросы по безопасности (3 запроса)

Требуют одновременно семантического и структурного анализа: - “Find potential SQL injection vulnerabilities in query building functions” - “Identify functions that allocate memory without proper error checking” - “Find buffer overflow risks in string manipulation functions”

Ожидаемое поведение: - Только векторный: Средняя эффективность (релевантность 50-60%) - Только графовый: Средняя эффективность (релевантность 50-60%) - Гибридный: Наилучшая эффективность

Примечание: Запросы, отмеченные (смешанный), требуют как семантического понимания, так и структурного обхода. Они отнесены к семантической/структурной категории по основному значению query_type.

Модули оценки

Платформа включает 4 модуля оценки в tests/benchmark/evaluation/:

IR-метрики (ir_metrics.py)

Стандартные метрики информационного поиска через класс IRMetrics:

Метрика Метод Описание
Precision@K precision_at_k(retrieved, relevant, k) Доля релевантных в топ-K
Recall@K recall_at_k(retrieved, relevant, k) Доля найденных релевантных
F1@K f1_at_k(retrieved, relevant, k) Гармоническое среднее P и R
MRR mrr(retrieved, relevant) Обратный ранг первого релевантного
NDCG@K ndcg_at_k(retrieved, relevant, highly_relevant, k) Градуированное ранжирование
Average Precision average_precision(retrieved, relevant) Площадь под кривой P-R
Hit Rate@K hit_rate_at_k(retrieved, relevant, k) Бинарный индикатор

Значения K по умолчанию: [5, 10, 20]. Метод compute_all() вычисляет все метрики сразу.

Метрики производительности (performance_metrics.py)

Метрики выполнения через класс PerformanceMetrics: - Латентность: min, max, mean, median, p50, p95, p99 - Токены: input, output, total, per-question, per-second - Кеш: попадания, промахи, процент попаданий - Сложность SQL: взвешенная оценка (JOIN +2, подзапрос +3, агрегация +1)

Метрики точности (accuracy_metrics.py)

Качество ответов через класс AccuracyMetrics: - Семантическая схожесть: косинусная через sentence-transformers (модель: paraphrase-multilingual-MiniLM-L12-v2) - Покрытие ключевых слов: проверка наличия с поддержкой русской морфологии - Покрытие функций: precision/recall/F1 для найденных и ожидаемых функций - Паттерн-матчинг: проверка регулярными выражениями - Фактическая точность: композитная оценка

Мультисущностные метрики (multi_entity_metrics.py)

Оценка по 9 типам сущностей через класс MultiEntityIRMetrics:

Тип сущности Вес Описание
functions 1.0 Определения функций
external_functions 0.9 Внешние функции
structs 0.9 Структуры/классы
macros 0.8 Макросы
types 0.7 Типы данных
enums 0.7 Перечисления
callers 0.85 Вызывающие функции
callees 0.85 Вызываемые функции
files 0.95 Исходные файлы

Возможности: нечёткое сопоставление имён функций (подстрока/префикс), кросс-платформенная нормализация путей, взвешенная комбинация метрик.

Сценарное тестирование

Комплексный бенчмарк использует эталонные вопросы, организованные по сценариям:

tests/benchmark/ground_truth/
+-- scenario_01_onboarding/
|   +-- questions_en.yaml
|   +-- questions_ru.yaml
|   +-- questions_en_codegraph.yaml  (для конкретного проекта)
+-- scenario_02_security_audit/
+-- ...
+-- scenario_20_dependencies/

20 директорий сценариев с наборами вопросов на EN + RU. Конфигурация бенчмарка (benchmark_config.yaml) определяет 16 основных сценариев; сценарии 17-20 (редактирование файлов, оптимизация кода, проверка стандартов, зависимости) имеют эталонные данные, но пока не включены в конфиг.

Формат YAML эталонных данных

scenario:
  id: "scenario_01_onboarding"
  name: "Codebase Onboarding"
  mapped_workflow: "onboarding_workflow"

metadata:
  version: "1.0"
  language: "en"
  question_count: 35
  difficulty_distribution:
    easy: 12
    medium: 15
    hard: 8

questions:
  - id: "ONBOARD_EN_001"
    question: "Where is heap_insert defined?"
    category: "definition_search"
    difficulty: "easy"
    postgresql_subsystem: "storage"
    target_function: "heap_insert"
    ground_truth:
      expected_functions: ["heap_insert"]
      expected_files: ["heapam.c"]
      required_keywords: ["heap", "insert", "tuple"]
      keyword_coverage_only: false
    evaluation:
      metrics: ["ir_metrics", "accuracy"]
      semantic_similarity_threshold: 0.7

Ключевые поля ground_truth: - expected_functions, expected_callers, expected_callees — списки сущностей для IR-метрик - expected_structs, expected_macros, expected_types, expected_enums — дополнительные типы - expected_files — ожидаемые исходные файлы - required_keywords — ключевые слова, которые должны быть в ответе - key_patterns — регулярные выражения для проверки - keyword_coverage_only: true — для концептуальных вопросов без конкретных сущностей

Конфигурация

Конфигурация бенчмарка (tests/benchmark/config/benchmark_config.yaml)

benchmark:
  name: "CodeGraph Comprehensive Benchmark"
  version: "2.1"

execution:
  k_values: [5, 10, 20]
  max_parallel_questions: 1
  question_timeout: 60
  enable_tracing: true
  languages: ["en", "ru"]

thresholds:
  easy:
    precision_at_10: 0.3
    recall_at_10: 0.5
    mrr: 0.4
    semantic_similarity: 0.5
    keyword_coverage: 0.5
  medium:
    precision_at_10: 0.2
    recall_at_10: 0.3
    mrr: 0.3
  hard:
    precision_at_10: 0.1
    recall_at_10: 0.2
    mrr: 0.2

success_criteria:
  min_scenario_pass_rate: 0.5
  min_scenarios_passed: 8
  min_overall_pass_rate: 0.5

Дополнительные бенчмарки

Бенчмарк классификации интентов

python -m tests.benchmark.intent_benchmark --language ru --show-failures

Оценка точности классификатора по 17 сценариям. Поддерживает --compare-languages для сравнения EN и RU.

Бенчмарк символьного выполнения

python scripts/benchmark_symbolic_execution.py --db data/projects/codegraph.duckdb

Измерение влияния V2: процент фильтрации ложных срабатываний, накладные расходы по времени/памяти, покрытие парсера.

Бенчмарк LLM-дизамбигуации

python scripts/benchmark_with_llm.py --llm --verbose

Тестирование классификатора с LLM-дизамбигуацией в сравнении с правилами.

Справочник метрик

Precision@K

P@K = (кол-во релевантных в топ-K) / K
  • 1.0 = все результаты в топ-K релевантны
  • 0.0 = ни один результат не релевантен

Recall@K

R@K = (кол-во релевантных в топ-K) / (общее кол-во релевантных)
  • 1.0 = все релевантные документы найдены
  • 0.0 = ни один не найден

F1@K

F1 = 2 * (P * R) / (P + R)

Гармоническое среднее точности и полноты — сбалансированная мера качества ранжирования.

Средний обратный ранг (MRR)

MRR = 1 / (ранг первого релевантного результата)
  • 1.0 = первый результат релевантен
  • 0.5 = второй результат релевантен
  • 0.0 = релевантных результатов нет

Нормализованная дисконтированная кумулятивная выгода (NDCG@K)

NDCG@K = DCG@K / IDCG@K
DCG@K = Σ (2^rel_i - 1) / log2(i + 1)

Градуированная релевантность: высоко релевантно (rel=2) > релевантно (rel=1) > нерелевантно (rel=0). - 1.0 = идеальное ранжирование - 0.0 = наихудшее ранжирование

Пользовательские запросы

Создание пользовательских запросов для бенчмарка гибридного поиска:

from scripts.benchmark_hybrid_retrieval import BenchmarkQuery

custom_queries = [
    BenchmarkQuery(
        id="custom_001",
        query="Your question here",
        query_type="semantic",  # или "structural", "security"
        description="Описание того, что тестируется",
        relevant_node_ids={1001, 1002, 1003, 1004},  # ID узлов CPG
        highly_relevant_node_ids={1001, 1002},        # Наиболее важные
        expected_difficulty="medium"  # "easy", "medium", "hard"
    ),
]

# Запуск с пользовательскими запросами
import asyncio
report = asyncio.run(benchmark.run_benchmark(queries=custom_queries))

Выходные файлы

Бенчмарк гибридного поиска

Два файла в benchmark_results/:

  1. JSON-отчёт (hybrid_benchmark_<timestamp>.json) — полные машиночитаемые результаты: метрики по запросам, агрегированные метрики, ID извлечённых узлов, детализация оценок.

  2. Markdown-отчёт (hybrid_benchmark_<timestamp>.md) — человекочитаемое резюме: сравнительная таблица, ключевые выводы, проценты улучшения.

Комплексный раннер бенчмарков

Результаты в tests/benchmark/results/{RUN_ID}/:

tests/benchmark/results/20260307_120000/
+-- summary.json          # Сводка результатов
+-- scenario_01.json      # Разбивка по сценарию
+-- scenario_02.json
+-- traces/
|   +-- ONBOARD_EN_001.trace
|   +-- VULN_EN_002.trace
+-- metadata.json         # Метаданные запуска

Интерпретация результатов

Как интерпретировать улучшения

Положительные значения (+) — это хорошо:

Гибридный F1@10 против векторного: +33,6%
= Гибридный поиск на 33,6% лучше, чем только векторный

Когда гибридный превосходит: - Семантические запросы: Гибридный >= Векторный > Графовый - Структурные запросы: Гибридный >= Графовый > Векторный - Смешанные запросы: Гибридный > Векторный, Графовый

Пример анализа

Запрос: “How does PostgreSQL handle transaction commits?” - Тип: Семантический - Результаты: - Векторный: P@10=0.60, R@10=0.80, F1@10=0.69 - Графовый: P@10=0.20, R@10=0.30, F1@10=0.24 - Гибридный: P@10=0.70, R@10=0.90, F1@10=0.79

Анализ: - Векторный работает хорошо (семантический запрос) - Графовый справляется хуже (запрос не структурный) - Гибридный лучший: +14,5% по сравнению с векторным (RRF добавляет структурный контекст)

Рекомендации по производительности

Латентность

Гибридный поиск медленнее одиночного источника из-за накладных расходов на параллельное выполнение. Конкретная латентность зависит от объёма данных, оборудования и сложности запроса.

Компромисс: гибридный подход увеличивает латентность ради 30-50% лучшей релевантности.

Кеширование

Для эксплуатации в рабочей среде: 1. Кешируйте часто встречающиеся запросы 2. Предварительно вычисляйте эмбеддинги 3. Используйте пул соединений для DuckDB

Модульные тесты

Запуск тестов метрик:

pytest tests/unit/test_benchmark_metrics.py -v

Покрытие (30 тестов в 8 классах): - TestPrecisionAtK: 5 тестов - TestRecallAtK: 4 теста - TestF1Score: 4 теста - TestMRR: 5 тестов - TestNDCG: 6 тестов - TestBenchmarkQuery: 2 теста - TestRetrievalMetrics: 2 теста - TestBenchmarkDataset: 3 теста

Дополнительные тестовые файлы: - tests/unit/test_benchmark_ir_coverage.py — проверка покрытия IR-метриками всех эталонных вопросов

Рекомендации

1. Разнообразный набор запросов

Включайте запросы разных типов (семантические, структурные, безопасность, смешанные) и сложности (лёгкие, средние, сложные).

2. Репрезентативные эталонные данные

Убедитесь, что эталонные данные отражают реальные оценки: - Явно помечайте узлы с высокой релевантностью - Включайте частичные совпадения - Привлекайте экспертов для проверки

3. Несколько метрик оценки

Не полагайтесь на одну метрику: - F1@10: общее качество ранжирования - MRR: пользовательский опыт (время до первого релевантного) - NDCG@10: градуированная релевантность

4. Анализ ошибок

Анализируйте результаты по каждому запросу: - Какие типы запросов выигрывают от гибридного? - Где каждый режим даёт сбой? - Как улучшить адаптивное взвешивание?

5. Итеративная отладка

Используйте расширенные фильтры: - --failed-from RUN_ID для перезапуска провалов - --offset N --max-questions M для пакетного тестирования - --question-ids для конкретных вопросов

Устранение неполадок

Ошибка: “No module named ‘src.retrieval’”

Решение: запускайте из корневой директории проекта.

Ошибка: “ModuleNotFoundError: VectorStore”

Решение: установите зависимости:

pip install chromadb sentence-transformers duckdb

Ошибка блокировки DuckDB

Решение: убедитесь, что gocpg.exe не запущен (проверьте ps aux | grep gocpg).

Низкие оценки бенчмарка

Решение: проверьте: 1. ChromaDB содержит проиндексированные документы (директория chroma_db/) 2. DuckDB имеет данные CPG (файл *.duckdb валиден) 3. Домен задан корректно (config.yamldomain.name)

Дальнейшие шаги

  1. Запустите бенчмарк гибридного поиска для оценки качества
  2. Запустите комплексный бенчмарк для полной оценки конвейера
  3. Изучите отчёты (JSON + Markdown)
  4. Настройте запросы или эталонные данные для вашего проекта
  5. Используйте --failed-from для итеративного исправления ошибок
  6. Настройте веса RRF на основе результатов

Поддержка

При возникновении проблем: - Создайте задачу (issue) в репозитории на GitHub - Приложите конфигурацию и логи ошибок - Предоставьте пример запроса, который завершается сбоем