LP_2-test / docs /ARCHITECTURE.md
DocUA's picture
Clean deployment without large index files
461adca
|
raw
history blame
24.2 kB

Архітектура додатку

Загальна схема

┌─────────────────────────────────────────────────────────────────┐
│                     GRADIO INTERFACE                            │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐  │
│  │💡Генерація│ │🔍 Пошук  │ │⚖️ Аналіз │ │⚙️ Налаштування  │  │
│  └──────────┘ └──────────┘ └──────────┘ └──────────────────┘  │
└─────────────────────────────────────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────────────┐
│                    SESSION MANAGER                               │
│  ┌────────────────────────────────────────────────────────┐    │
│  │  Session ID: abc-123-def                               │    │
│  │  ├─ legal_position_json: {...}                         │    │
│  │  ├─ search_nodes: [...]                                │    │
│  │  └─ custom_prompts:                                    │    │
│  │     ├─ system: "Ти кваліфікований юрист..."           │    │
│  │     ├─ legal_position: "Дотримуйся інструкцій..."     │    │
│  │     └─ analysis: "Проаналізуй..."                     │    │
│  └────────────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────────────┐
│                         STORAGE                                  │
│  ┌─────────────────┐              ┌──────────────────┐         │
│  │  Memory Storage │   OR         │  Redis Storage   │         │
│  │  (Development)  │              │  (Production)    │         │
│  └─────────────────┘              └──────────────────┘         │
└─────────────────────────────────────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────────────┐
│                      CORE FUNCTIONS                              │
│  ┌──────────────────┐  ┌──────────────┐  ┌─────────────────┐  │
│  │ generate_legal_  │  │ search_with_ │  │ analyze_action  │  │
│  │ position()       │  │ ai_action()  │  │                 │  │
│  └──────────────────┘  └──────────────┘  └─────────────────┘  │
└─────────────────────────────────────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────────────┐
│                      AI PROVIDERS                                │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────────┐  │
│  │  OpenAI  │  │ Anthropic│  │  Google  │  │  DeepSeek    │  │
│  │  GPT-4   │  │ Claude   │  │  Gemini  │  │  Chat        │  │
│  └──────────┘  └──────────┘  └──────────┘  └──────────────┘  │
└─────────────────────────────────────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────────────┐
│                    KNOWLEDGE BASE                                │
│  ┌────────────────────────────────────────────────────────┐    │
│  │  Vector Index + BM25 Index                             │    │
│  │  Правові позиції Верховного Суду України              │    │
│  └────────────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────────┘

Потік даних при генерації правової позиції

1. Користувач вводить текст судового рішення
   │
   ▼
2. interface.py → process_input()
   ├─ Отримує session_id
   ├─ Завантажує сесію з SessionManager
   └─ Витягує custom_prompts з сесії
   │
   ▼
3. main.py → generate_legal_position()
   ├─ Приймає custom_system_prompt
   ├─ Приймає custom_lp_prompt
   └─ Використовує їх замість стандартних
   │
   ▼
4. AI Provider (OpenAI/Anthropic/Gemini/DeepSeek)
   ├─ System Prompt: кастомний або стандартний
   ├─ User Prompt: форматований з court_decision_text
   └─ Генерує JSON відповідь
   │
   ▼
5. Результат зберігається в сесію
   ├─ session.legal_position_json = {...}
   └─ SessionManager.update_session(session)
   │
   ▼
6. Відображення результату користувачу

Потік даних при редагуванні промптів

1. Користувач відкриває "⚙️ Налаштування"
   │
   ▼
2. app.load → load_session_prompts()
   ├─ Отримує session_id
   ├─ Завантажує сесію
   └─ Витягує збережені промпти або стандартні
   │
   ▼
3. Користувач редагує промпти
   │
   ▼
4. Натискає "💾 Зберегти промпти"
   │
   ▼
5. save_custom_prompts()
   ├─ Валідує довжину (max 50,000 символів)
   ├─ session.set_prompt('system', new_value)
   ├─ session.set_prompt('legal_position', new_value)
   ├─ session.set_prompt('analysis', new_value)
   └─ SessionManager.update_session(session)
   │
   ▼
6. Промпти збережено ✅
   (Будуть використані при наступній генерації)

Багатокористувацька архітектура

┌─────────────────────────────────────────────────────────────────┐
│                    MULTIPLE USERS                                │
└─────────────────────────────────────────────────────────────────┘
          │                    │                    │
          ▼                    ▼                    ▼
    ┌──────────┐         ┌──────────┐         ┌──────────┐
    │ User 1   │         │ User 2   │         │ User 3   │
    │ Browser  │         │ Browser  │         │ Browser  │
    └──────────┘         └──────────┘         └──────────┘
          │                    │                    │
          ▼                    ▼                    ▼
    session_id:          session_id:          session_id:
    abc-123              def-456              ghi-789
          │                    │                    │
          └────────────────────┴────────────────────┘
                               │
                               ▼
                    ┌─────────────────────┐
                    │  SESSION MANAGER    │
                    │  (with asyncio.Lock)│
                    └─────────────────────┘
                               │
          ┌────────────────────┼────────────────────┐
          ▼                    ▼                    ▼
    ┌──────────┐         ┌──────────┐         ┌──────────┐
    │Session 1 │         │Session 2 │         │Session 3 │
    │prompts: A│         │prompts: B│         │prompts: C│
    │data: X   │         │data: Y   │         │data: Z   │
    └──────────┘         └──────────┘         └──────────┘

    ✅ Повністю ізольовані!

Структура даних UserSessionState

@dataclass
class UserSessionState:
    # Унікальний ідентифікатор сесії
    session_id: str  # UUID4 (наприклад: "abc-123-def-456")

    # Згенерована правова позиція
    legal_position_json: Optional[Dict[str, Any]] = {
        "title": "Заголовок правової позиції",
        "text": "Текст позиції...",
        "proceeding": "Цивільне судочинство",
        "category": "Категорія справи"
    }

    # Результати пошуку
    search_nodes: Optional[List[NodeWithScore]] = [
        NodeWithScore(
            node=Document(
                text="Текст правової позиції...",
                metadata={"lp_id": "123", "url": "..."}
            ),
            score=0.85
        ),
        ...
    ]

    # 🆕 Кастомні промпти користувача
    custom_prompts: Dict[str, str] = {
        'system': "Ти - кваліфікований юрист...",
        'legal_position': "Дотримуйся інструкцій...",
        'analysis': "Проаналізуй рішення..."
    }

    # Метадані сесії
    created_at: datetime
    last_activity: datetime

Життєвий цикл сесії

┌─────────────────────────────────────────────────────────────┐
│ 1. СТВОРЕННЯ СЕСІЇ                                          │
│    ├─ Користувач відкриває додаток                         │
│    ├─ generate_session_id() → UUID4                        │
│    ├─ SessionManager.get_session(session_id)               │
│    └─ Нова сесія зберігається в storage                    │
└─────────────────────────────────────────────────────────────┘
                         │
                         ▼
┌─────────────────────────────────────────────────────────────┐
│ 2. АКТИВНА СЕСІЯ (0-30 хв)                                 │
│    ├─ Користувач генерує позиції                           │
│    ├─ Користувач налаштовує промпти                        │
│    ├─ Користувач виконує пошук/аналіз                      │
│    └─ last_activity оновлюється при кожній дії             │
└─────────────────────────────────────────────────────────────┘
                         │
                         ▼
┌─────────────────────────────────────────────────────────────┐
│ 3. ПЕРЕВІРКА НА ЕКСПІРАЦІЮ                                 │
│    └─ Background cleanup task (кожні 5 хв)                 │
│       ├─ session.is_expired(30 minutes)?                   │
│       │  ├─ YES → видалити сесію                           │
│       │  └─ NO → залишити активною                         │
│       └─ Повторювати...                                    │
└─────────────────────────────────────────────────────────────┘
                         │
                         ▼
┌─────────────────────────────────────────────────────────────┐
│ 4. ВИДАЛЕННЯ СЕСІЇ                                         │
│    ├─ Сесія видалена з storage                             │
│    ├─ Пам'ять звільнена                                    │
│    └─ Кастомні промпти втрачено                            │
└─────────────────────────────────────────────────────────────┘

Безпека та ізоляція

Thread-safe операції

class SessionManager:
    def __init__(self):
        self._lock = asyncio.Lock()  # 🔒 Для thread-safety

    async def get_session(self, session_id):
        async with self._lock:  # Блокування доступу
            # Тільки один запит обробляється одночасно
            session = await self.storage.get(session_id)
            return session

    async def update_session(self, session):
        async with self._lock:  # Блокування доступу
            session.update_activity()
            await self.storage.set(session)

Ізоляція даних

┌───────────────────────────────────────────────────────────┐
│  ГАРАНТІЇ БЕЗПЕКИ                                         │
├───────────────────────────────────────────────────────────┤
│  ✅ Session ID генерується криптографічно (UUID4)        │
│  ✅ Неможливо вгадати чужий session_id                   │
│  ✅ Дані зберігаються тільки в межах сесії               │
│  ✅ Автоматичне видалення застарілих даних               │
│  ✅ Thread-safe операції через asyncio.Lock              │
│  ✅ Немає глобального стану (окрім SessionManager)       │
└───────────────────────────────────────────────────────────┘

Інтеграція з існуючим кодом

До (Legacy)

# interface.py
state_lp_json = gr.State()  # Gradio state
state_nodes = gr.State()

def process_input(...):
    # Генерація без кастомних промптів
    legal_position_json = generate_legal_position(
        input_text, input_type, comment, provider, model
    )
    return output, legal_position_json  # Повертаємо в Gradio state

Після (з Session Manager)

# interface.py
session_id_state = gr.State(value=generate_session_id)  # 🆕 Унікальний ID

async def process_input(..., session_id: str):
    # Завантажуємо сесію
    manager = get_session_manager()
    session = await manager.get_session(session_id)

    # Витягуємо кастомні промпти
    custom_system = session.get_prompt('system', SYSTEM_PROMPT)
    custom_lp = session.get_prompt('legal_position', LEGAL_POSITION_PROMPT)

    # Генерація з кастомними промптами
    legal_position_json = generate_legal_position(
        input_text, input_type, comment, provider, model,
        custom_system_prompt=custom_system,  # 🆕
        custom_lp_prompt=custom_lp            # 🆕
    )

    # Зберігаємо в сесію
    session.legal_position_json = legal_position_json
    await manager.update_session(session)

    return output, legal_position_json, session_id

Переваги нової архітектури

┌────────────────────────────────────────────────────────────┐
│  ПЕРЕВАГИ                                                  │
├────────────────────────────────────────────────────────────┤
│  ✅ Повна ізоляція між користувачами                      │
│  ✅ Персоналізація промптів для кожного користувача       │
│  ✅ Підготовка до deployment на Hugging Face Spaces       │
│  ✅ Можливість використання Redis для масштабування       │
│  ✅ Автоматична очистка пам'яті                           │
│  ✅ Thread-safe для багатопоточності                      │
│  ✅ Легка розширюваність (додавання нових полів)          │
│  ✅ Централізоване управління станом                      │
└────────────────────────────────────────────────────────────┘

Майбутні покращення

Фаза 1: Повна міграція на Session Manager

┌───────────────────────────────────────────────────────────┐
│  ПОТОЧНИЙ СТАН                                            │
│  ├─ session_id_state ✅ (реалізовано)                    │
│  ├─ state_lp_json ⚠️ (legacy, дублюється)               │
│  └─ state_nodes ⚠️ (legacy, дублюється)                 │
└───────────────────────────────────────────────────────────┘
                         │
                         ▼
┌───────────────────────────────────────────────────────────┐
│  МАЙБУТНЄ                                                 │
│  ├─ session_id_state ✅ (єдине джерело істини)          │
│  ├─ Всі дані в SessionManager                             │
│  └─ Видалити legacy states                                │
└───────────────────────────────────────────────────────────┘

Фаза 2: Розширені можливості

┌───────────────────────────────────────────────────────────┐
│  НОВІ FEATURES                                            │
│  ├─ Експорт/імпорт промптів (JSON/YAML)                  │
│  ├─ Бібліотека шаблонів промптів                         │
│  ├─ Версіонування промптів (історія змін)                │
│  ├─ A/B тестування різних промптів                       │
│  └─ Метрики якості генерації                             │
└───────────────────────────────────────────────────────────┘

Висновок

Нова архітектура забезпечує:

  • 🔒 Безпеку: повна ізоляція між користувачами
  • ⚡ Продуктивність: ефективне управління пам'яттю
  • 🎨 Гнучкість: персоналізація для кожного користувача
  • 🚀 Масштабованість: готовність до production deployment

Система готова до використання на Hugging Face Spaces та інших хмарних платформах!