Skip to content

Galaxy career paths

Galaxy uses existing employee, job and JPM data to suggest a career path and explain an existing path. Both operations use the authenticated Main API and the deployment's configured MongoDB or PostgreSQL backend.

Functional purpose and complete workflow

An employee chooses a target profession in their organization's referential. Galaxy identifies the progression from their current profession to that target. It can return a direct move or a sequence of intermediate professions, together with a short explanation of the development journey. A second operation explains the training needs and skills to develop for a path already selected by the caller.

The term "proximity" describes how well each profession matches the employee. The underlying JPM combines skill coverage and current-job text similarity; its overall score is the maximum of those two components. Galaxy consumes that score without changing it. It is not a probability of promotion, an estimate of success, or a measure of distance between consecutive jobs. Galaxy does not promise a time to proficiency or verify that a vacancy is currently open.

The path operation follows this sequence:

  1. Resolve the tenant and active employee, then identify their current profession from its attached job code. Check that both source and target are available.
  2. Read the employee's existing JPM scores. Exclude neutralized pairs, which represent jobs excluded by matching eligibility rules. A missing target score produces an explicit absence result without a model call.
  3. Gather active, visible scored jobs from the same tenant. Retain only the source and target families, with known levels between the source and target levels. Keep jobs whose proximity is at least as strong as the target's.
  4. Reserve source and target in the catalogue. Order other candidates by ascending level, descending JPM score, then job identifier, and apply max_jobs. The configured cap can therefore limit the professions considered. Source proximity is always green with score 1, even without its own JPM row.
  5. Check whether the bounded catalogue admits any sequence satisfying the rules below. This check considers the required family, level and proximity at each stage. If an intermediate stage cannot be reached, return no_valid_path.
  6. Build the prompt using the selected professions, employee skills, source, target, locale and transition limit. Reject an oversized context before any LLM call. Reuse a validated result when its content fingerprint matches.
  7. Ask the configured model to select a sequence and explain it. The backend checks all identifiers and every transition, then supplies titles, families, levels and scores from the referential. It never repairs a hallucinated ID using a similar title or silently deletes an invalid intermediate step.

The result is one admissible suggested path. The feasibility check establishes that a compliant path exists in the selected catalogue; it does not establish that the model's choice is the uniquely best possible professional trajectory.

Generate a path

POST /api/v1/jpm/galaxy/path accepts a JSON body:

{
  "client_id": "42",
  "user_id": "101",
  "target_job_id": "503",
  "locale": "en-US",
  "data_source": "smartmobility"
}

IDs are non-empty strings (up to 128 characters, without whitespace). They are AIHub entity IDs, not email addresses or application user IDs. locale is optional and nullable; omission uses the employee locale. data_source defaults to smartmobility, its only supported value. Extra fields are rejected. The request requires X-API-Key. A tenant bound to the authenticated context, including a supplied Client-ID header, must match the body's client_id.

The service resolves the current job through attachedJobCode, reads existing JPM scores, excludes neutralized pairs and selects active, visible jobs in the source or target family. It does not import entities, compute embeddings, recalculate scores or publish matching results. Source and target must have positive integer job classifications and a job family.

The response contains path (ordered jobs including source and target), steps (zero-based transitions), description and nullable reason. Every path job contains job_id, title, family, level, proximity and score. Metadata comes from the referential; the model selects identifiers only. Source proximity is green with score 1. Other proximities refer to the employee's JPM score, not to a job-to-job transition score.

The description addresses the employee in two or three concise sentences. Transferable skills are mentioned only when supported by the supplied evidence. When the filtered employee skill list is empty, the narrative explains the proposed progression between professions, families and levels without inferring skills, gaps, mastery, past experience or specific duties. An empty list does not mean the employee has no skills and does not invalidate an otherwise valid path. The description does not promise a promotion.

Mobility rules

  • A same-level or one-level increase uses one direct transition.
  • Larger increases visit every intermediate level. Within a family, each transition increases the level by one.
  • When a larger increase also changes family, first move to the target family at the source level, then progress within that family. This horizontal move counts as an additional transition: family A level 2 to family B level 4 requires three transitions, through B level 2 and B level 3.
  • At most three transitions are permitted. Downward progression and loops are rejected. An unavailable intermediate cannot be invented.
  • Allowed proximities are green → green/orange, orange → orange/red and red → red. In particular, a direct green → red transition is invalid.

The fixed rules and configurable transition limit combine as follows:

Target level minus source level Same family Different family
Negative No downward path No downward path
0 One direct transition One direct horizontal transition
1 One direct transition One direct transition; the family and level may change together
2 Two transitions, through the missing level Three transitions: horizontal move first, then two level increases
3 Three transitions, visiting both missing levels Four would be needed, exceeding the supported maximum
4 or more Exceeds the supported maximum Exceeds the supported maximum

For every row, proximity must also permit each move and the number of transitions must be no greater than max_steps. At max_steps=1, only direct moves can succeed. At max_steps=2, a two-level increase is possible within one family, but the corresponding change of family is not. A same source/target ID returns same_job; it is not a one-step self-transition.

Current proximity Allowed next proximity Forbidden next proximity
Green Green, orange Red
Orange Orange, red Green
Red Red Green, orange

These conditions apply to the final target as well as intermediates. For example, a red target at the same level cannot be reached: the level rule requires a direct move, while the proximity rule forbids green → red. Galaxy does not add an otherwise forbidden intermediate to resolve that conflict.

Examples and absence cases

Situation Result
A2 → A3, target green Direct move
A2 → B2, target orange Direct horizontal move
A2 green → A3 orange → A4 red Valid two-transition progression
A2 green → B2 green → B3 orange → B4 red Valid three-transition family change
A2 → A4 with no available A3 No valid path; no level may be skipped
A2 → B4 without a B2 job No valid path; the initial horizontal stage is missing
A2 → A5 with only green A3 and red A4 No valid path; the green → red intermediate transition is forbidden
A4 → A2 No downward path
Target has only a neutralized JPM result Missing usable target score

Here A/B denote families and the number denotes the job level. Every illustrative intermediate must exist in the actual tenant catalogue and survive eligibility and candidate limits. These examples do not create additional jobs or rules.

The backend checks feasibility before calling the LLM and validates every returned transition. A business absence returns HTTP 200 with empty path/steps, empty description, and reason equal to same_job, missing_target_score or no_valid_path. The last reason can also represent a model abstention; abstentions are not cached.

Explain an existing path

POST /api/v1/jpm/galaxy/rationale accepts the same fields plus the required path_job_ids, an ordered list of two to four distinct IDs including the employee's current job and the requested target:

{
  "client_id": "42",
  "user_id": "101",
  "target_job_id": "503",
  "path_job_ids": ["501", "502", "503"],
  "locale": "fr-FR"
}

The response is {"rationale": "..."}. This reproduces the legacy career-path explanation:

  • The prompt receives the current job title, employee skills and their mastery and motivation, ordered path titles, target title and required hard skills.
  • Employee skills must have origin="User", a non-empty title and a known level strictly below user_skill_max_level. They are sorted by motivation, then mastery. Inferred skills and already maximally mastered skills are omitted.
  • Target hard skills are supplied when a non-neutralized target JPM row exists.
  • The answer addresses the employee supportively and prioritizes one grounded development need, in the selected locale and 20 words or fewer. It must not invent named training courses or qualifications. Generation uses the shared structured-output formats for the selected provider, with one rationale field. The application validates the envelope and word count; invalid output is rejected without truncation or an extra model call.
  • All supplied jobs must exist, be active/visible and belong to the tenant. The rationale explains the supplied path; it does not generate another path or reapply the path generator's grading rules.

Configuration and migration differences

galaxy in src/templates/config_file.json defines these defaults:

Setting Default Meaning
red_max 0.34 Inclusive red score upper bound
orange_max 0.69 Inclusive orange upper bound; higher scores are green
max_steps 3 Maximum transitions (1–3)
max_jobs 400 Candidate prompt cap (2–400), reserving source and target
user_skill_max_level 4 Exclude employee skills at or above this level
max_context_chars 120000 Maximum serialized dynamic prompt size
cache_ttl_seconds 300 Result lifetime; zero disables reuse

Existing configurations without the Galaxy section use these documented defaults. New PostgreSQL initializations receive the same defaults from the canonical Alembic configuration seed; existing configuration rows are not overwritten. MongoDB tenant configurations and the deployment-wide PostgreSQL aihub_config can override them. Legacy tenant feature-switch values are not imported automatically: copy customized thresholds and mastery scales into the applicable AIHub configuration before rollout.

Thresholds use contiguous upper-bound intervals, eliminating gaps between legacy decimal intervals. Contradictory legacy prompt step counts are resolved by counting horizontal mobility explicitly. The La Poste-specific numeric tenant-ID branch is not carried into these general rules. Frontend placeholder scores, career-plan CRUD and the old external /galaxy/compute_paths service are outside these two APIs. AIHub standardized skills are the input: raw legacy userskill provenance and per-skill weights are not reconstructed.

Calls use AIHub's configured default LLM profile, temperature 0.2, a requested 2,000-token output budget and a 60-second provider timeout. The shared provider policy remains authoritative. Successful validated results are cached in memory for up to 512 entries per process. The fingerprint includes tenant, employee, target, path, locale, prompt, supplied data, Galaxy rules and AI configuration. Each request reloads data before reuse. Changes to supplied data or model configuration cause a miss. Entries contain only serialized results and hashes, and disappear on restart; replicas have independent caches. Concurrent misses may make separate model calls.

Provider prompt caching

Galaxy uses the shared build_prompt_messages helper. Stable instructions, mobility examples and the shared context policy form the first system message. The locale, user skills, available professions, source/target IDs and selected path remain in a separate user message. They never change the stable prefix.

Both calls pass the resolved ai_configuration unchanged to call_llm_async, with prompt_cache=True and without a provider/model override or a custom provider cache key. The connector owns model/profile selection, provider dispatch, token policy, cache eligibility, cache-key generation and cost accounting exactly as for other AIHub calls. Its key depends on the task, selected model and stable instruction prefix, not on the user or target job.

Provider caching follows the shared eligibility policy: a supported provider and a sufficiently long stable prefix are required. The path prompt includes the reusable progression examples. The concise rationale prompt can fall below the shared minimum; Galaxy does not lower that threshold or add padding to enable caching. Provider prompt caching and the process-local result cache are separate: the former can reduce the cost of a new generation, while the latter avoids a generation entirely when the validated inputs have not changed.

Errors and operational checks

Missing entities return 404; an employee without an attached job returns 400. Malformed bodies, missing source/target grading or family, oversized prompt context and invalid rationale paths return 422. Tenant mismatch returns 403. Invalid model output returns 502, provider timeout 504, and unexpected failures or invalid deployment configuration 500. Errors use stable codes without provider exception text. Unlike the legacy's empty-string error suppression, generation failures are explicit. Text exceeding the rationale word limit is rejected, never silently truncated.

External content remains in user-role data under the shared context policy. Request budgets, bound query values and tenant predicates complement that separation. Output is plain text; consuming frontends must escape it.

MongoDB uses existing user/job identifier, job-code and JPM user/job pair indexes. The new PostgreSQL candidate read binds tenant and job IDs against the existing job projection; job primary keys and tenant/code indexes cover those reads. No schema migration or new index is required. Repository tests inspect filters and projections; live query plans and model quality require deployment-specific validation.

The generated main HTTP reference is the authoritative source for parameters, schemas, responses and examples.