Bahn: aisupport, Analyse-O2C-C2S, awesome-bahn-mcp-servers, beam-mcp,
Confluence_Bot, db-planet-mcp-server, O2C-Harness, project-audit,
Projekt-KIQ-HP, teamlandkarte-mcp
Dhive: Jury-Voting
Privat: CV, NoteGraph (NOTE: NoteGraph needs complete redo after consolidation)
Shared: AI-Orchestrator, OrgMyLife, power_skills_and_more
Shared/references: symphony (read-only)
Bahn repos remain available as independent remotes - this monorepo
pulls them in via subtree, the originals are untouched.
5.8 KiB
5.8 KiB
Design: Capacity→Task Matching and Embedding-based Inference
Context
The system was originally optimized for task→capacity matching and relied on Azure chat completions for role/requirements extraction.
To enable a symmetrical workflow and reduce latency/cost, this change:
- adds tools to browse capacities and match a capacity against open tasks
- reworks role and competence inference to use embeddings only (Data Lake vocabularies)
- preloads and caches role/competence vocab embeddings on startup (with runtime on-demand fallback)
- preloads and caches task text embeddings by
task_id
Key decisions
A. Vocabulary-driven inference (roles + competences)
- Maintain two vocabularies sourced from the Data Lake:
- roles:
teamlandkarte_v_capacity_roles_latestfiltered byactive=trueandstaffing_board_relevant=true - competences: unique values from
beschaffungstool_kmp_skill_latest.skillname__c
- roles:
- Generate embeddings for these vocabularies and store them in the local SQLite embedding cache.
B. Task text embedding stored by task_id
To minimize embedding transaction costs for repeated analysis of the same task:
- build
task_text = f"{title}\n\n{description}"(title optional) - embed
task_textonce - store that embedding under a stable key derived from
task_id(and embedding model/dims)
Explicit cache key formats:
# Role vocabulary entries
key = f"role_vocab:{model}:{dims}:{normalized_role_name}"
# Competence vocabulary entries
key = f"comp_vocab:{model}:{dims}:{normalized_competence_name}"
# Task text embeddings by task_id
key = f"task_id:{model}:{dims}:{task_id}"
Where:
model= embedding model name (e.g.,text-embedding-3-large)dims= embedding dimensions (e.g.,3072)normalized_role_name= normalized role text (trimmed, whitespace-collapsed, lowercased)normalized_competence_name= normalized competence text (trimmed, whitespace-collapsed, lowercased)task_id= database task ID (string or integer, converted to string)
C. Inference logic (embedding similarity)
- Role inference:
- compute cosine similarity between
task_text_embeddingand all role vocabulary embeddings - return the single best matching role with similarity score as a Markdown table:
Role | Similarity
- compute cosine similarity between
- Competence inference (for validation and display):
- compute cosine similarity between
task_text_embeddingand all competence vocabulary embeddings - return top-N competences with similarity scores as a Markdown table:
Competence | Similarity(descending order)
- compute cosine similarity between
Configuration (under [matching.inference]):
[matching.inference]
max_competences = 8 # default: 8; omit to disable limit (no max)
min_similarity = 0.4 # default: 0.4; omit to disable threshold filtering
Configuration rules:
- If
max_competencesis not specified: no limit on number of competences returned. - If
min_similarityis not specified: no threshold filtering applied (include all). - At least one of
max_competencesormin_similarityMUST be specified in config to avoid unbounded results. - Selection rule: if both are set, return top
max_competencesamong those with similarity>= min_similarity.
D. Component structure for vocabulary preload
Component: VocabularyCache
- Location:
src/teamlandkarte_mcp/matching/vocabulary.py(new module) - Responsibilities:
- Fetch role + competence vocabularies from Data Lake via database client
- Normalize and deduplicate vocabulary entries
- Embed missing entries using batch + chunking via
SimilarityEngine.prefetch_embeddings(...) - Store embeddings in SQLite cache with stable keys
- Provide in-memory memoization for fast repeated inference during tool execution
- Initialization: Called from
build_server()after DB client + similarity engine initialization - Refresh strategy: On startup only; no TTL-based refresh during runtime
Task embedding preload:
- Preload all open tasks on startup (no limit).
- Build
task_text = title + "\n\n" + descriptionfor each task (title optional). - Embed only cache-missing
task_idvectors (check SQLite cache first). - Store into SQLite embedding cache with key format:
task_id:{model}:{dims}:{task_id}. - Runtime fallback: if a task embedding is missing during tool execution, embed on-demand (strict semantics).
E. Determinism and strict failure semantics
- Runs are deterministic given fixed models and cached embeddings.
- Azure embedding failures fail the operation immediately.
- The existing global embedding improvements (dedup + batch + layered caches) should be reused.
Data flow
1) Vocabulary refresh
- fetch role list + competence list from Data Lake
- normalize/deduplicate
- embed missing entries via Azure batch API
- store embeddings in SQLite cache
2) Task validation
- fetch task (title+description) + DB skills
- compute/retrieve
task_text_embeddingby task_id - infer:
- top-K roles
- top-K competences
- compare:
- DB skills vs inferred competences (plus similarity thresholds)
- dates (unchanged)
3) Capacity→task matching
- load the target capacity (role + competences + availability)
- list open tasks
- compute/retrieve
task_text_embeddingfor each task - compute overall similarity (role + competences) between the capacity and each task
- categorize + return table-first results (same output conventions as existing matching tools)
Alternatives considered
- Keep chat API for role inference: rejected (latency/cost + redundant).
- Use raw string matching for vocab mapping: rejected (less robust than embeddings).
Risks
- Vocabulary size (competences) may be large → requires batch embedding + caching and careful refresh strategy.
- Model updates can change nearest neighbors → mitigate with pinned model/deployment and cache key including model/dims.