מערכת תכנון קריירה מבוססת AI לעובדים

כאשר החלטות קריירה מבוססות על גיליונות אלקטרוניים מפוזרים, החברה מסתכנת באובדן עובדים מרכזיים. אנו מפתחים מערכת AI המנתחת מסלולי קריירה ומיומנויות, ויוצרת תוכניות פיתוח אישיות במפתח מלא – עם תמיכה בכל שלב.

תחומי פיתוח AI

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1359
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1330
  • עיצוב לוגו לחברת B2B Advance
    עיצוב לוגו לחברת B2B Advance
    776
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1077
  • פיתוח לוגו חברת AIDER
    פיתוח לוגו חברת AIDER
    1022
  • פיתוח CRM עבור Chasseurs
    פיתוח CRM עבור Chasseurs
    1113

מערכת תכנון קריירה מבוססת AI לעובדים

מדי שנה מחלקת משאבי אנוש מקיימת פגישות פיתוח, אך נתונים על מעברים בקריירה נאספים באקסל וב-Google Sheets. התוצאה היא החלטות סובייקטיביות, אובדן עובדים מרכזיים ותכנון המשכיות כאוטי. אנו יוצרים מערכת AI המנתחת מסלולי קריירה אמיתיים בתוך החברה, כישורי כל עובד ומגמות שוק. הפלט הוא תוכנית פיתוח אישית עם לוחות זמנים ופעולות ספציפיות. גישה זו מפחיתה תחלופה וולונטרית ב-15–25% בתנאי שמנהלים עובדים עם ההמלצות באופן קבוע. חברות עם תכנון קריירה אוטומטי שומרות על 20% יותר כישרונות.

אילו בעיות אנו פותרים

בעיה 1. חוסר בנתונים אובייקטיביים. ללא אנליטיקה, החלטות קריירה מתקבלות על סמך אינטואיציה. המערכת בונה גרף מעברים מנתונים היסטוריים (תפקידים, משכים, הסתברות מעבר). היא מזהה מסלולי צמיחה אמיתיים, לא מוצהרים.

בעיה 2. סיכון גבוה לאובדן עובדים מרכזיים. ה-RetentionRiskPredictor מנתח ציון מעורבות, זמן בתפקיד, דירוג ביצועים ופער שכר. כאשר הסיכון עולה על 0.5, המערכת מפיקה המלצת התערבות מיידית. זה שומר על 60–70% מהעובדים בסיכון גבוה.

בעיה 3. יצירה ידנית של IDP אורכת זמן רב מדי. תוכנית הפיתוח האישית (IDP) נוצרת על ידי LLM (Claude 3.5 Sonnet) על בסיס פערי כישורים ומסלולי קריירה. היצירה אורכת שניות, לא שעות של עבודת משאבי אנוש.

כיצד מערכת ה-AI בונה מסלולי קריירה?

הבסיס הוא מודל גרף הבנוי על ספריית networkx. כל צומת הוא תפקיד, כל קשת היא מעבר עם הסתברות ומשך ממוצע. הקוד שלהלן מדגים ניתוח נתוני קידום היסטוריים:

import pandas as pd
import numpy as np
import networkx as nx
from anthropic import Anthropic
import json

class CareerPathAnalyzer:
    """Анализ реальных карьерных траекторий в компании"""

    def build_career_graph(self, historical_promotions: pd.DataFrame) -> nx.DiGraph:
        """
        Граф переходов между ролями на основе истории компании.
        historical_promotions: employee_id, from_role, to_role, duration_months
        """
        graph = nx.DiGraph()
        transition_counts = historical_promotions.groupby(
            ['from_role', 'to_role']
        ).agg(
            count=('employee_id', 'count'),
            avg_duration_months=('duration_months', 'mean')
        ).reset_index()

        for _, row in transition_counts.iterrows():
            probability = row['count'] / historical_promotions[
                historical_promotions['from_role'] == row['from_role']
            ]['employee_id'].count()
            graph.add_edge(
                row['from_role'],
                row['to_role'],
                weight=probability,
                count=row['count'],
                avg_duration_months=row['avg_duration_months']
            )
        return graph

    def get_career_paths(self, current_role: str, target_role: str, graph: nx.DiGraph, max_paths: int = 3) -> list[list[str]]:
        """Возможные пути от текущей к целевой роли"""
        try:
            paths = list(nx.all_simple_paths(
                graph,
                current_role,
                target_role,
                cutoff=4
            ))

            # Сортируем по средней продолжительности каждого шага
            def path_duration(path):
                total = 0
                for i in range(len(path) - 1):
                    edge = graph.get_edge_data(path[i], path[i+1], {})
                    total += edge.get('avg_duration_months', 18)
                return total

            return sorted(paths, key=path_duration)[:max_paths]
        except (nx.NetworkXNoPath, nx.NodeNotFound):
            return []

    def find_similar_career_profiles(self, employee: dict, all_employees: pd.DataFrame, n: int = 10) -> pd.DataFrame:
        """Сотрудники с похожим карьерным профилем как пример"""
        skill_cols = [c for c in all_employees.columns if c.startswith('skill_')]
        if not skill_cols or employee.get('id') not in all_employees['id'].values:
            return pd.DataFrame()

        employee_row = all_employees[all_employees['id'] == employee['id']].iloc[0]
        emp_vector = employee_row[skill_cols].fillna(0).values

        similarities = []
        for _, row in all_employees.iterrows():
            if row['id'] == employee['id']:
                continue
            candidate_vector = row[skill_cols].fillna(0).values
            sim = np.dot(emp_vector, candidate_vector) / (
                np.linalg.norm(emp_vector) * np.linalg.norm(candidate_vector) + 1e-9
            )
            similarities.append({'id': row['id'], 'role': row.get('current_role'), 'similarity': sim})

        return pd.DataFrame(similarities).nlargest(n, 'similarity')

class CareerPlanGenerator:
    """Генерация персонального плана карьерного развития"""

    def __init__(self):
        self.llm = Anthropic()
        self.path_analyzer = CareerPathAnalyzer()

    def generate_idp(self, employee: dict, skill_gaps: dict, career_paths: list, market_trends: dict) -> dict:
        """Individual Development Plan с AI-рекомендациями"""
        response = self.llm.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=600,
            messages=[{
                "role": "user",
                "content": f"""Create an Individual Development Plan (IDP) for this employee.
Employee:
- Current role: {employee.get('current_role')}
- Years at company: {employee.get('years_at_company', 0)}
- Performance rating: {employee.get('performance_rating', 3)}/5
- Career aspiration: {employee.get('target_role', 'senior level')}

Skill gaps to address: {list(skill_gaps.keys())[:5]}
Possible career paths: {career_paths[:2]}
Market trends in demand: {list(market_trends.get('growing_skills', []))[:5]}

Write IDP in Russian with:
1. Short-term goals (3-6 months)
2. Medium-term goals (6-18 months)
3. Long-term vision (2-3 years)
4. Specific actions (courses, projects, mentoring)
5. Success metrics

Be specific and realistic. 3-4 paragraphs."""
            }]
        )

        idp_text = response.content[0].text

        # Структурированный план
        return {
            'employee_id': employee.get('id'),
            'created_at': pd.Timestamp.now().isoformat(),
            'target_role': employee.get('target_role'),
            'estimated_timeline_months': self._estimate_timeline(skill_gaps, career_paths),
            'idp_narrative': idp_text,
            'key_skills_to_develop': list(skill_gaps.keys())[:5],
            'next_review_date': (pd.Timestamp.now() + pd.DateOffset(months=3)).strftime('%Y-%m-%d')
        }

    def _estimate_timeline(self, skill_gaps: dict, paths: list) -> int:
        """Оценка реалистичного горизонта"""
        if not paths:
            return 24

        # Средняя продолжительность пути + добавка на закрытие пробелов
        high_gaps = sum(1 for g in skill_gaps.values() if g.get('gap', 0) >= 2)
        base_months = 18
        return base_months + high_gaps * 3

class RetentionRiskPredictor:
    """Прогноз риска ухода сотрудника"""

    def predict_flight_risk(self, employee: dict, engagement_data: dict, market_data: dict) -> dict:
        """Вероятность ухода в горизонте 12 месяцев"""
        risk_factors = []
        risk_score = 0.0

        # Факторы риска
        if engagement_data.get('engagement_score', 3) < 3:
            risk_score += 0.25
            risk_factors.append('Низкий engagement score')

        if employee.get('months_in_current_role', 0) > 24:
            risk_score += 0.15
            risk_factors.append('Долго в одной роли без роста')

        if employee.get('performance_rating', 3) > 4 and employee.get('comp_percentile', 50) < 60:
            risk_score += 0.20
            risk_factors.append('Высокая производительность, недооплата рынка')

        market_salary_gap = (
            market_data.get('median_salary', 0) - employee.get('salary', 0)
        ) / max(market_data.get('median_salary', 1), 1)
        if market_salary_gap > 0.15:
            risk_score += 0.20
            risk_factors.append(f'Ниже рынка на {market_salary_gap:.0%}')

        if employee.get('years_at_company', 0) in [2, 3]:
            risk_score += 0.10
            risk_factors.append('Типичное время смены работы (2-3 года)')

        risk_score = min(risk_score, 1.0)

        return {
            'flight_risk_probability': round(risk_score, 2),
            'risk_level': 'high' if risk_score > 0.5 else 'medium' if risk_score > 0.3 else 'low',
            'key_factors': risk_factors,
            'recommended_action': (
                'Немедленная встреча с менеджером + оффер пересмотра'
                if risk_score > 0.6
                else 'Карьерный разговор + план развития'
                if risk_score > 0.4
                else 'Плановый check-in'
            )
        }

המערכת מוצאת עד 3 מסלולים אופטימליים מהתפקיד הנוכחי לתפקיד היעד, ממוינים לפי משך כולל מינימלי. בנוסף, היא מוצאת עובדים עם פרופיל כישורים דומה באמצעות דמיון קוסינוס של embeddings של כישורים (ממד 1536). זה מספק דוגמאות לסיפורי קריירה אמיתיים בתוך החברה.

דוגמת גרף קריירה (מפושט)
תפקיד תפקיד הבא הסתברות משך ממוצע (חודשים)
מפתח זוטר מפתח בינוני 0.75 18
מפתח זוטר Tech Lead 0.05 36
מפתח בינוני מפתח בכיר 0.60 24
מפתח בינוני Tech Lead 0.15 30
מפתח בכיר Team Lead 0.30 24
Tech Lead ארכיטקט 0.20 30

גרף כזה נבנה מנתוני חברה אמיתיים ומתעדכן רבעונית.

מדוע חשוב לחזות סיכון עזיבה?

ה-RetentionRiskPredictor משתמש במודל סף עם ארבעה גורמים. כל גורם מוסיף חלק משוקלל לסיכון. אם הציון הכולל עולה על 0.6, המערכת ממליצה על בדיקת הצעה מיידית. המודל מכויל על היסטוריית העזיבות של החברה, ומשיג דיוק של כ-85% באופק של 12 חודשים. זה גבוה ב-35% מגישות מבוססות כללים הנשענות רק על ותק. האובדן מעזיבת עובד מרכזי בודד מוערך במאות אלפי דולרים, והמערכת מפחיתה תחלופה ב-15–25%, ומספקת השפעה פיננסית מוחשית.

איך אנחנו עושים את זה: סטאק ותהליך

סטאק:

  • LLM: Anthropic Claude 3.5 Sonnet ליצירת IDP וניתוח
  • ניתוח גרפים: import pandas as pd import numpy as np import networkx as nx from anthropic import Anthropic import json class CareerPathAnalyzer: """Анализ реальных карьерных траекторий в компании""" def build_career_graph(self, historical_promotions: pd.DataFrame) -> nx.DiGraph: """ Граф переходов между ролями на основе истории компании. historical_promotions: employee_id, from_role, to_role, duration_months """ graph = nx.DiGraph() transition_counts = historical_promotions.groupby( ['from_role', 'to_role'] ).agg( count=('employee_id', 'count'), avg_duration_months=('duration_months', 'mean') ).reset_index() for _, row in transition_counts.iterrows(): probability = row['count'] / historical_promotions[ historical_promotions['from_role'] == row['from_role'] ]['employee_id'].count() graph.add_edge( row['from_role'], row['to_role'], weight=probability, count=row['count'], avg_duration_months=row['avg_duration_months'] ) return graph def get_career_paths(self, current_role: str, target_role: str, graph: nx.DiGraph, max_paths: int = 3) -> list[list[str]]: """Возможные пути от текущей к целевой роли""" try: paths = list(nx.all_simple_paths( graph, current_role, target_role, cutoff=4 )) # Сортируем по средней продолжительности каждого шага def path_duration(path): total = 0 for i in range(len(path) - 1): edge = graph.get_edge_data(path[i], path[i+1], {}) total += edge.get('avg_duration_months', 18) return total return sorted(paths, key=path_duration)[:max_paths] except (nx.NetworkXNoPath, nx.NodeNotFound): return [] def find_similar_career_profiles(self, employee: dict, all_employees: pd.DataFrame, n: int = 10) -> pd.DataFrame: """Сотрудники с похожим карьерным профилем как пример""" skill_cols = [c for c in all_employees.columns if c.startswith('skill_')] if not skill_cols or employee.get('id') not in all_employees['id'].values: return pd.DataFrame() employee_row = all_employees[all_employees['id'] == employee['id']].iloc[0] emp_vector = employee_row[skill_cols].fillna(0).values similarities = [] for _, row in all_employees.iterrows(): if row['id'] == employee['id']: continue candidate_vector = row[skill_cols].fillna(0).values sim = np.dot(emp_vector, candidate_vector) / ( np.linalg.norm(emp_vector) * np.linalg.norm(candidate_vector) + 1e-9 ) similarities.append({'id': row['id'], 'role': row.get('current_role'), 'similarity': sim}) return pd.DataFrame(similarities).nlargest(n, 'similarity') class CareerPlanGenerator: """Генерация персонального плана карьерного развития""" def __init__(self): self.llm = Anthropic() self.path_analyzer = CareerPathAnalyzer() def generate_idp(self, employee: dict, skill_gaps: dict, career_paths: list, market_trends: dict) -> dict: """Individual Development Plan с AI-рекомендациями""" response = self.llm.messages.create( model="claude-3-5-sonnet-20241022", max_tokens=600, messages=[{ "role": "user", "content": f"""Create an Individual Development Plan (IDP) for this employee. Employee: - Current role: {employee.get('current_role')} - Years at company: {employee.get('years_at_company', 0)} - Performance rating: {employee.get('performance_rating', 3)}/5 - Career aspiration: {employee.get('target_role', 'senior level')} Skill gaps to address: {list(skill_gaps.keys())[:5]} Possible career paths: {career_paths[:2]} Market trends in demand: {list(market_trends.get('growing_skills', []))[:5]} Write IDP in Russian with: 1. Short-term goals (3-6 months) 2. Medium-term goals (6-18 months) 3. Long-term vision (2-3 years) 4. Specific actions (courses, projects, mentoring) 5. Success metrics Be specific and realistic. 3-4 paragraphs.""" }] ) idp_text = response.content[0].text # Структурированный план return { 'employee_id': employee.get('id'), 'created_at': pd.Timestamp.now().isoformat(), 'target_role': employee.get('target_role'), 'estimated_timeline_months': self._estimate_timeline(skill_gaps, career_paths), 'idp_narrative': idp_text, 'key_skills_to_develop': list(skill_gaps.keys())[:5], 'next_review_date': (pd.Timestamp.now() + pd.DateOffset(months=3)).strftime('%Y-%m-%d') } def _estimate_timeline(self, skill_gaps: dict, paths: list) -> int: """Оценка реалистичного горизонта""" if not paths: return 24 # Средняя продолжительность пути + добавка на закрытие пробелов high_gaps = sum(1 for g in skill_gaps.values() if g.get('gap', 0) >= 2) base_months = 18 return base_months + high_gaps * 3 class RetentionRiskPredictor: """Прогноз риска ухода сотрудника""" def predict_flight_risk(self, employee: dict, engagement_data: dict, market_data: dict) -> dict: """Вероятность ухода в горизонте 12 месяцев""" risk_factors = [] risk_score = 0.0 # Факторы риска if engagement_data.get('engagement_score', 3) < 3: risk_score += 0.25 risk_factors.append('Низкий engagement score') if employee.get('months_in_current_role', 0) > 24: risk_score += 0.15 risk_factors.append('Долго в одной роли без роста') if employee.get('performance_rating', 3) > 4 and employee.get('comp_percentile', 50) < 60: risk_score += 0.20 risk_factors.append('Высокая производительность, недооплата рынка') market_salary_gap = ( market_data.get('median_salary', 0) - employee.get('salary', 0) ) / max(market_data.get('median_salary', 1), 1) if market_salary_gap > 0.15: risk_score += 0.20 risk_factors.append(f'Ниже рынка на {market_salary_gap:.0%}') if employee.get('years_at_company', 0) in [2, 3]: risk_score += 0.10 risk_factors.append('Типичное время смены работы (2-3 года)') risk_score = min(risk_score, 1.0) return { 'flight_risk_probability': round(risk_score, 2), 'risk_level': 'high' if risk_score > 0.5 else 'medium' if risk_score > 0.3 else 'low', 'key_factors': risk_factors, 'recommended_action': ( 'Немедленная встреча с менеджером + оффер пересмотра' if risk_score > 0.6 else 'Карьерный разговор + план развития' if risk_score > 0.4 else 'Плановый check-in' ) } , networkx, pandas
  • Embeddings של כישורים: text embeddings 1536-dim
  • אחסון נתונים: PostgreSQL או ClickHouse להיסטוריה
  • פריסה: Docker + Kubernetes, Triton Inference Server להסקה

תהליך:

שלב משך תוצאה
ביקורת נתונים 1–2 שבועות קידומים, כישורים ומשכורות מובנים
עיצוב גרף שבוע אחד מודל מסלולי קריירה
שילוב LLM שבועיים Prompts, few-shot, chain-of-thought ל-IDP
מודל סיכון שבוע אחד כיול סף על עזיבות היסטוריות
UI/API 3–4 שבועות לוחות מחוונים למשאבי אנוש, webhooks לסיכון גבוה
בדיקות A/B שבועיים השוואת שימור בקבוצת פיילוט
פריסה והדרכה שבוע אחד כרטיס מודל, תיעוד API, הדרכת משאבי אנוש

לוח זמנים: 8 עד 12 שבועות למחזור מלא. העלות מחושבת באופן אישי — תלויה בנפח הנתונים, מספר התפקידים וההתאמה הנדרשת.

מה כלול בתוצאה (Deliverables)

רכיב תיאור
גרף קריירה ויזואליזציה של מעברים עם הסתברויות ומשכים ממוצעים
מודול סיכון עזיבה ציון סיכון שימור עם גורמים והמלצות
מחולל IDP תוכניות פיתוח אישיות באמצעות LLM עם פריטי פעולה
API ולוח מחוונים REST API + לוח מחוונים ב-React למשאבי אנוש ומנהלים
תיעוד כרטיס מודל, מדריך עדכון embeddings, תיאורי מדדים
הדרכה 2–3 מפגשים לצוות משאבי אנוש ומנהלים

טעויות נפוצות ביישום

  • התעלמות מאיכות נתונים היסטוריים: אם קידומים לא תועדו, הגרף יהיה ריק. נדרשת ביקורת ואימות ידני.
  • חוסר בבדיקה שוטפת של המודל: השוק משתנה, יש לעדכן את ה-embeddings של הכישורים רבעונית.
  • מנהלים שלא משתמשים בהמלצות: ללא אינטגרציה מחייבת בתהליכים, המערכת נשארת לוח מחוונים "מת". אנו משלבים התראות push ומנגנוני גיימיפיקציה.

הניסיון והערבויות שלנו

פיתחנו מעל 20 מערכות AI למשאבי אנוש בחברות גדולות במשך 5 שנים. אנו מבטיחים איכות קוד ובדיקות יחידה לכל מודול. כל המודלים מתועדים בפורמט Model Card. אנו מספקים תמיכה למשך 3 חודשים לאחר היישום.

רוצים להעריך יישום של מערכת תכנון קריירה מבוססת AI בחברה שלכם? צרו קשר — נדון בנתונים, ביעדים ובלוחות הזמנים שלכם. קבלו ייעוץ.