LP_2-test / BATCH_TESTING_README.md
DocUA's picture
Clean deployment without large index files
461adca
# Пакетне тестування генерації правових позицій
## Опис функціоналу
Нова закладка "📊 Пакетне тестування" дозволяє проводити масове тестування генерації правових позицій із текстів судових рішень, завантажених з CSV файлу.
## Як користуватися
### 1. Підготовка CSV файлу
CSV файл повинен містити обов'язкову колонку `text` з текстами судових рішень:
```csv
id_lp,text
1,"Текст судового рішення 1..."
2,"Текст судового рішення 2..."
3,"Текст судового рішення 3..."
```
**Приклади тестових файлів:**
- `test_docs/test_sample.csv` - простий приклад для демонстрації
- `test_docs/df_lp_part_cd_test_29_result.csv` - повний набір тестових даних
### 2. Використання інтерфейсу
1. **Відкрийте закладку "📊 Пакетне тестування"**
2. **Виберіть провайдера та модель LLM:**
- Провайдер AI: OpenAI, Anthropic, Gemini, DeepSeek
- Модель генерації: відповідна модель обраного провайдера
3. **Налаштуйте паузу між запитами:**
- Використовуйте слайдер "⏱️ Пауза між запитами (секунди)"
- Діапазон: від 0 до 10 секунд
- За замовчуванням: 1 секунда
- Крок: 0.5 секунди
- **Рекомендації:**
- 0-1 сек: для швидкої обробки малих обсягів
- 1-2 сек: оптимально для більшості випадків
- 3-5 сек: для уникнення rate limits при великих обсягах
- 5-10 сек: для консервативної обробки або при обмеженнях API
4. **Завантажте CSV файл:**
- Натисніть "📁 Завантажте CSV файл з тестовими даними"
- Виберіть ваш CSV файл
- Натисніть "📂 Завантажити CSV файл"
- Перевірте попередній перегляд завантажених даних
5. **Запустіть пакетне тестування:**
- Натисніть "▶️ Запустити пакетне тестування"
- Слідкуйте за прогресом обробки
- Дочекайтеся завершення
6. **Завантажте результати:**
- Після завершення з'явиться кнопка "📥 Завантажити результати"
- Файл буде збережено у папці `test_results/`
- Назва файлу містить назву моделі та мітку часу
### 3. Формат результатів
Результуючий CSV файл містить:
- Всі оригінальні колонки з вхідного файлу
- Нова колонка з назвою моделі (наприклад, `gemini-3.0-flash`, `gpt-4o-mini`, `claude-3-5-sonnet-20241022`)
- У новій колонці - **повний JSON об'єкт** з усіма полями правової позиції
**Приклад результату:**
```csv
id_lp,text,gemini-3.0-flash
1,"Текст судового рішення 1...","{""title"": ""Заголовок позиції"", ""text"": ""Текст правової позиції"", ""proceeding"": ""Кримінальне судочинство"", ""category"": ""Категорія""}"
2,"Текст судового рішення 2...","{""title"": ""Заголовок позиції 2"", ""text"": ""Текст правової позиції 2"", ""proceeding"": ""Цивільне судочинство"", ""category"": ""Категорія 2""}"
```
**Структура JSON об'єкту:**
```json
{
"title": "Заголовок судового рішення",
"text": "Текст короткого змісту позиції суду",
"proceeding": "Тип судочинства",
"category": "Категорія судового рішення"
}
```
**Приклад реального результату:**
```json
{
"title": "Обчислення розміру відшкодування шкоди, заподіяної внаслідок незаконного добування (збирання) або знищення цінних видів водних біоресурсів",
"text": "Обчислення розміру відшкодування шкоди, заподіяної внаслідок незаконного добування (збирання) або знищення цінних видів водних біоресурсів, можливо здійснювати на підставі Такс, затверджених постановою КМУ від 21.11.2011 № 1209, без проведення експертизи.",
"proceeding": "Кримінальне судочинство",
"category": "Встановлення розміру шкоди (стаття 135)"
}
```
### 4. Обробка результатів
Після завантаження CSV файлу з результатами, ви можете:
1. **Парсити JSON у Python:**
```python
import pandas as pd
import json
# Завантажити результати
df = pd.read_csv('test_results/batch_test_results_gemini-3.0-flash_20260103_120000.csv')
# Парсити JSON з колонки моделі
df['parsed'] = df['gemini-3.0-flash'].apply(json.loads)
# Витягти окремі поля
df['title'] = df['parsed'].apply(lambda x: x['title'])
df['text'] = df['parsed'].apply(lambda x: x['text'])
df['proceeding'] = df['parsed'].apply(lambda x: x['proceeding'])
df['category'] = df['parsed'].apply(lambda x: x['category'])
```
2. **Експортувати у зручний формат:**
```python
# Розгорнути JSON в окремі колонки
df_expanded = pd.concat([df.drop(['gemini-3.0-flash', 'parsed'], axis=1),
pd.json_normalize(df['parsed'])], axis=1)
# Зберегти у новий CSV з розгорнутими полями
df_expanded.to_csv('results_expanded.csv', index=False)
```
## Алгоритм роботи
1. **Завантаження CSV файлу** - система зчитує файл та перевіряє наявність колонки `text`
2. **Валідація** - перевірка формату та коректності даних
3. **Пакетна генерація** - для кожного рядка:
- Зчитується текст з колонки `text`
- Виконується генерація правової позиції з використанням `LEGAL_POSITION_PROMPT`
- Повний JSON результат (з усіма полями: title, text, proceeding, category) записується в нову колонку
4. **Збереження** - результати зберігаються у файл з міткою часу
## Технічні деталі
### Використовувані файли та функції
**Основні файли:**
- `interface.py` - інтерфейс користувача (нова закладка)
- `prompts.py` - промпт `LEGAL_POSITION_PROMPT` для генерації
- `main.py` - функція `generate_legal_position()` для генерації
**Нові функції в interface.py:**
```python
async def load_csv_file(file) -> Tuple[str, Optional[pd.DataFrame]]
"""Завантаження та валідація CSV файлу"""
async def process_batch_testing(
df: pd.DataFrame,
provider: str,
model_name: str,
progress=gr.Progress()
) -> Tuple[str, Optional[str]]
"""Пакетна обробка тестових даних"""
```
### Структура директорій
```
Legal_Position_2/
├── test_docs/ # Тестові CSV файли
│ ├── test_sample.csv
│ └── df_lp_part_cd_test_29_result.csv
├── test_results/ # Результати пакетного тестування
│ └── batch_test_results_<model>_<timestamp>.csv
├── interface.py # Інтерфейс з новою закладкою
├── prompts.py # Промпти для генерації
└── main.py # Основна логіка генерації
```
## Обробка помилок
Система обробляє наступні випадки:
- Відсутність колонки `text` у CSV файлі
- Помилки кодування (підтримується UTF-8 та CP1251)
- Помилки генерації для окремих рядків (записується текст помилки)
- Помилки збереження результатів
## Продуктивність
- **Прогрес-бар** - показує поточний стан обробки
- **Послідовна обробка** - рядки обробляються один за одним
- **Пауза між запитами** - налаштовується для уникнення rate limits
- **Час виконання** - залежить від:
- Кількості рядків у CSV файлі
- Швидкості відповіді API провайдера
- Налаштованої паузи між запитами
**Приклад розрахунку часу:**
- 100 рядків × (3 сек на запит + 1 сек пауза) = ~400 секунд (~6.7 хвилин)
- 100 рядків × (3 сек на запит + 0 сек пауза) = ~300 секунд (~5 хвилин)
- 10 рядків × (3 сек на запит + 1 сек пауза) = ~40 секунд
## Підтримувані провайдери та моделі
- **OpenAI**: GPT-4o, GPT-4o-mini, GPT-4-turbo та інші
- **Anthropic**: Claude 3.5 Sonnet, Claude 3 Opus та інші
- **Gemini**: Gemini 3.0 Flash, Gemini 2.0 Flash та інші
- **DeepSeek**: DeepSeek Chat та інші
## Приклади використання
### Приклад 1: Тестування з GPT-4o-mini
1. Виберіть провайдера: OpenAI
2. Виберіть модель: gpt-4o-mini
3. Завантажте файл: `test_docs/test_sample.csv`
4. Запустіть тестування
5. Результат: `test_results/batch_test_results_gpt-4o-mini_20260103_115530.csv`
### Приклад 2: Порівняння моделей
1. Запустіть тестування з GPT-4o-mini
2. Завантажте той самий CSV знову
3. Запустіть тестування з Claude 3.5 Sonnet
4. Порівняйте результати в обох файлах
## Rate Limits та рекомендації
### Обмеження API провайдерів
Різні провайдери мають різні обмеження на кількість запитів:
- **OpenAI:**
- Free tier: ~3 RPM (requests per minute)
- Paid tier: 60-500 RPM залежно від плану
- **Anthropic:**
- Free tier: обмежено
- Paid tier: залежить від підписки
- **Gemini:**
- Free tier: 15 RPM
- Paid tier: вищі ліміти
- **DeepSeek:**
- Залежить від підписки
### Рекомендовані налаштування паузи
| Кількість рядків | Рекомендована пауза | Причина |
|------------------|---------------------|---------|
| 1-10 | 0.5-1 сек | Швидка обробка, мінімальний ризик |
| 10-50 | 1-2 сек | Баланс між швидкістю та надійністю |
| 50-100 | 2-3 сек | Уникнення rate limits |
| 100+ | 3-5 сек | Консервативний підхід |
**Порада:** Якщо ви отримуєте помилки про перевищення ліміту запитів (rate limit errors), збільште паузу на 1-2 секунди.
## Додаткова інформація
- Результати не впливають на інші закладки додатку
- Кожен запуск створює новий файл результатів
- Результати зберігаються локально у папці `test_results/`
- Папка `test_results/` додана в `.gitignore`
- Пауза застосовується між запитами, але не після останнього
- При помилці в одному рядку обробка продовжується для наступних