Головна / Статті

OrgGraph AI: Шаблон знань для даних HR без необхідності ручного кодування.

Як LLM виявляє схему графа з будь-якого файлу Excel або CSV, завантажує її до Neo4j за допомогою динамічного Cypher та відповідає на запитання щодо штату через чат-агента LangGraph.

Видавець: REACTAPP.TOP7 хв читання1644 слів

Джерела: Building a Fully Agentic Employee Knowledge Graph: **OrgGraph AI — using LangGraph & Neo4j**

Великі компанії мають більше даних про своїх співробітників, ніж будь-коли раніше, проте підбір персоналу все ще ґрунтується на припущеннях. Ієрархія відділу кадрів знаходиться у Workday, а розподіл проєктів — у Jira. Навички, рівні компетентності та сертифікати залишаються у старих порталах навчання. Потім з’являється проєкт із високим пріоритетом, і керівник з реалізації запитує, хто в офісах у Мумбаї чи Пуні володіє розширеними знаннями Python, має сертифікат AWS, розуміється на AI/ML, має досвід роботи над банківськими проєктами та водночас має вільні ресурси.

Відповісти на це запитання займає близько тижня, якщо це взагалі вдається. Факти існують, але вони заховані у окремих системах, які не можуть аналізувати взаємозв’язки між різними елементами.

OrgGraph AI — це система, створена для подолання цієї прогалини. Вона приймає необроблені організаційні дані у будь-якому форматі Excel чи CSV, за допомогою LLM самостійно формує схему графа, завантажує все до Neo4j та потім відповідає на запитання простою мовою. Жодна логіка домену не закодована жорстко ніде.

Взаємозв’язки важливіші за записи

Стандартні інструменти HR базуються на плоских SQL-таблицях. Для них легко отримати інформацію про всіх співробітників у Бангалорі чи про всіх, хто використовує Python. Однак вони стикаються з складними запитаннями, які вимагають одночасного аналізу кількох вимірів взаємозв’язків. Граф знань уможливлює чотири типи роботи:

  1. Точне формування штату. Знайти одну людину, яка володіє навичкою A, сертифікатом B, працює у місці C та має вільні ресурси, за один прохід, замість чотирьох окремих об’єднань даних.
  • Раннє виявлення прогалин у навичках. Порівняйте поточні навички з вимогами майбутніх проєктів. Ви можете дізнатися, що відділ даних та штучного інтелекту не має достатньох знань Kubernetes для роботи над проєктами у третьому кварталі, поки ще є час вжити заходів.
  • Планування наступності та співпраця. Поєднайте молодого розробника в Сіднеї з досвідченим архітектором поблизу, який використовує схожий технологічний стек, або знайдіть внутрішніх експертів для швидких консультацій замість найму зовнішніх фахівців.
  • Аналіз організаційної мережі. Створіть ланцюги звітності, виявіть окремі точки відмов у структурах управління та побачте, які найкращі співробітники перевантажені роботою, перш ніж вони виснажаться.
  • Що означає відсутність жорсткого кодування

    Більшість проєктів з графами знань мають одну неприємну таємницю: схема є жорстко закодованою. Інженер читає таблицю, вирішує, що співробітники — це вузли, навички також є вузлами, а ребро HAS_SKILL їх поєднує, пише спеціальний код Cypher для кожної entитету та використовує його. Потім відділ кадрів додає таблицю Certifications або перейменовує PrimarySkill на TechStack, і весь процес припиняє працювати.

    OrgGraph AI змінює цю ситуацію. Штучний інтелект вирішує, якою має бути схема. Для будь-якого табличного файлу система:

    1. аналізує дані, включаючи типи стовпців, кардинальність та можливі іноземні ключі
    2. виводить схему графа на основі структурованих результатів роботи ШІ, перевірених за допомогою Pydantic
    3. динамічно генерує та виконує запити Cypher типу MERGE
    4. аналізує готовий граф, щоб чат-агент міг здійснювати запити до нього

    Ніхто не створює карт наживо, і жоден синтаксис не пишеться заздалегідь. Якщо завтра замінити дані кадрів на логістику ланцюга постачання, той самий кодовий фундамент створить абсолютно інший граф. Набір даних для тестування був синтетичним — приблизно десять аркушів, — і пайплайн обробляє все, що йому надається.

    Чотири фази

    Система працює у чотирьох фазах, організованих за допомогою Python, LangChain, LangGraph, Pydantic та Neo4j.

    Фаза 1: аналіз метаданих

    Перш ніж буде використано будь-який LLM, MetadataProfiler аналізує необроблені дані локально та створює компактний структурний «відбиток». Це свідоме рішення щодо конфіденційності. Справжні записи співробітників ніколи не потрапляють до моделі. Вона отримує назви стовпців, типи даних, кількість унікальних значень у кожному стовпці та кілька зразків значень.

    Найціннішим інструментом профілювальника є автоматичне виявлення іноземних ключів. Він позначає стовпець як ймовірний іноземний ключ, коли його значення переважно знаходяться у стовпці первинного ключа в іншому місці:

    # Simplified FK detection logic from profiler.py
    overlap = col_values & ref_values
    if len(overlap) / len(col_values) >= 0.8:
        fk_candidates.append({
            "source_table": tname,
            "source_column": col,
            "target_table": ref_table,
            "target_column": ref_col,
            "match_pct": round(len(overlap) / len(col_values) * 100, 1),
        })
    

    У наборі даних HR це показує, що Manager_Employee_ID у таблиці Employees збігається з Employee_ID у рівні понад 80%, що свідчить про самореферентні взаємозв’язки типу REPORTS_TO. Це натякає на те, що ШІ не змогло визначити ієрархію лише за назвами стовпців.

    Етап 2: виявлення схеми

    Профіль передається ШІ, яке можна налаштувати між OpenAI GPT-4o, Google Gemini та Groq; запит формулюється так, ніби це головний архітектор баз даних у вигляді графів.

    Ключовою інженерною проблемою є те, що ШІ генерують текст у вільній формі, тоді як бази даних у вигляді графів вимагають суворої структури. Функція with_structured_output() від LangChain подолує цю проблему, змушуючи модель повертати перевірений об’єкт Pydantic:

    # The LLM is coerced to return this exact structure
    class GraphMappingModel(BaseModel):
        nodes: List[NodeMapping]           # What becomes a Node?
        relationships: List[RelationshipMapping]  # What becomes an Edge?
        notes: str                         # LLM's reasoning notes
    class NodeMapping(BaseModel):
        label: str                   # e.g., "Employee"
        source_table: str            # e.g., "Employees"
        primary_key_column: str      # e.g., "Employee_ID"
        properties: List[PropertyMapping]  # All columns to map
    class RelationshipMapping(BaseModel):
        type: str                    # e.g., "HAS_SKILL"
        from_node_label: str         # e.g., "Employee"
        to_node_label: str           # e.g., "Skill"
        from_key_column: str         # FK column in source table
        to_key_column: str           # PK column of target node
        properties: List[PropertyMapping]  # Edge properties
    

    GraphMappingModel виступає як контракт для всієї системи. Його створює агент схеми, а споживає двигун імпорту. Якщо перевірка провалюється, запит до LLM подається знову, тож жодна некоректна схема не потрапляє до Neo4j.

    Етап 3: динамічний імпорт Cypher

    За наявності перевіреної схеми двигун на льоту генерує параметризовані запити Cypher. Не існує шаблонів чи операторів switch для кожного типу ентитета. Він читає карту відповідностей та створює оператори MERGE та SET для кожного типу вузла та зв’язку:

    # Dynamically generated Cypher from the mapping — zero hardcoding
    UNWIND $rows AS row
    MERGE (n:Employee {employee_id: row.employee_id})
    SET n.full_name = row.full_name,
        n.designation = row.designation,
        n.date_of_joining = row.date_of_joining,
        n.annual_ctc_lpa = toFloat(row.annual_ctc_lpa)
    

    Оскільки ім’я схеми, отримане шляхом аналізу, є ім’ям первинного ключа, двигун використовує MERGE, а не CREATE, що робить процес ідемпотентним. Його виконання тричі з однаковими даними дає таку саму структуру без дублікатів. Крім того, він здійснює перетворення типів (toInteger(), toFloat()), перетворює NaN на None та ігнорує рядки, у яких первинний ключ дорівнює null.

    Набір даних для демонстрації — це не простий приклад: 151 співробітник у 13 взаємопов’язаних таблицях, зокрема 935 записів про навички, 285 записів про призначення до проєктів, 107 сертифікатів, 313 відгуків та 453 записи про навчання, розподілених між 10 відділами та 10 глобальними офісами.

    Етап 4: чат GraphRAG з агентом

    Шар чату — це не просто перекладач тексту у формат Cypher. Це чотиривузлова машина станів LangGraph із вбудованою системою відновлення від помилок:

    User Question
        ↓
    ┌─────────────┐
    │   Planner   │ → Analyzes intent, extracts entities, maps to schema
    └──────┬──────┘
           ↓
    ┌─────────────┐
    │  CypherGen  │ → Generates Cypher query using schema + few-shot examples
    └──────┬──────┘
           ↓
    ┌─────────────┐     ┌─── Error? ───→ Retry CypherGen (up to 2x)
    │  Executor   │ ────┤
    └──────┬──────┘     └─── Success ──→
           ↓
    ┌──────────────┐
    │ Synthesizer  │ → Formats raw graph data into natural language
    └──────────────┘
    

    Три характеристики роблять його адаптивним.

    Інтроспекція схеми під час виконання. Під час запуску агент отримує актуальну схему з Neo4j, яка вказує, які типи вузлів та зв’язків існують, їхні властивості та способи їхнього з’єднання. Ця схема використовується у кожному запиті, тож агент ніколи не припускає, що міститься в базі даних.

    Самостійно створені приклади типу „куди-що“. Багато систем GraphRAG закодовують приклади на мові Cypher як константи. Тут ШІ сам створює такі приклади на основі актуальної схеми та вибраних даних, і вони автоматично оновлюються після того, як новий завантажений даний змінює схему.

    Повторні спроби з урахуванням помилок. Якщо створений запит зазнає невдачі, повідомлення про помилку потрапляє назад до вузла CypherGen, який виправляє запит та намагається знову, до двох разів. Це робить агента значно стійким до синтаксичних проблем у крайніх випадках.

    Проблеми корпоративного рівня

    Приватність. Штучний інтелект бачить лише структуру, а не людей. Імена стовпців, їхні типи та кардинальність — ось усе, що виходить з інструменту аналізу, а особисті дані залишаються на вашому сервері.

    Гнучкість постачальника. Модель LLM Factory дозволяє перемикатися між OpenAI, Gemini та Groq, змінивши лише одну змінну середовища:

    # .env: LLM_PROVIDER=gemini | openai | groq
    llm = get_llm()  # Returns the configured ChatModel
    

    Жодних змін у коді та жодного замикання на постачальника.

    Незвідані дані. Корпоративні таблиці ніколи не є чистими. Механізм імпорту справляється з зайвими пробілами, різними форматами дат, несподіваними значеннями NaN та ключами первинної таблиці типу null, пропускаючи або конвертуючи проблемні рядки замість того, щоб зупинитися.

    Від завантаження до відповідей

    Фронтенд — це панель керування Streamlit. Користувач завантажує файл Excel або CSV у бічній панелі та спостерігає за роботою потоку в реальному часі: аналіз, виявлення схеми, імпорт, а потім ініціалізація агента. Після цього вони просто спілкуються.

    Окрема демонстрація використовує Vis.js для візуалізації графів на основі фізичних законів та GSAP для анімацій, які запускаються під час прокрутки. Вузли завантажуються під дією сил гравітації та відштовхування з поступовим розкриттям. Клацання на будь-який вузол відкриває панель з його властивостями та пов’язаними зв’язками. Симульоване чат-вікно відображає як відповідь у природній мові, так і запит Cypher, створений для її отримання.

    Більше, ніж HR

    Ця архітектура не прив’язана лише до HR. Той самий код може бути використаний для створення графа знань для управління IT-активами, де відображаються сервери, програми, команди та залежності між ними. Він може відстежувати постачальників, матеріали, склади та логістичні маршрути в ланцюзі постачання, або пов’язувати дослідників, наукові праці, установи та джерела фінансування в науковій мережі.

    Саме до пайплайнів даних, які адаптуються до даних замість того, щоб інженери примушували дані вписуватися у жорсткі схеми, рухається архітектура агентів, і цей проєкт є одним із зразків такої реалізації.