Migrate all repos into monorepo context folders
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.
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
# Anforderungsdokument
|
||||
|
||||
## Einleitung
|
||||
|
||||
Das bestehende LLM-Volltext-Matching (`llm_fulltext`) führt für jede Kapazität bzw. Aufgabe einen separaten, sequenziellen LLM-Aufruf an die Azure OpenAI API durch. Bei einer größeren Anzahl von Kandidaten (z. B. 20–50 Kapazitäten) führt dies zu inakzeptablen Wartezeiten, da jeder Aufruf einzeln auf die API-Antwort wartet.
|
||||
|
||||
Dieses Dokument beschreibt die Anforderungen für die Einführung eines **Batching-Mechanismus**, der mehrere LLM-Aufrufe parallel (concurrent) an die Azure OpenAI API sendet, um die Gesamtlaufzeit des Matchings signifikant zu reduzieren. Es wird dabei die asynchrone Parallelisierung (concurrent requests) genutzt, nicht die Azure Batch API (die für Offline-Verarbeitung gedacht ist und keine Echtzeit-Antworten liefert).
|
||||
|
||||
## Glossar
|
||||
|
||||
- **LLM_Fulltext_Matcher**: Bestehendes Modul (`matching/llm_fulltext_matcher.py`), das den LLM-basierten Volltext-Vergleich durchführt und Kategorien direkt zuweist.
|
||||
- **AzureOpenAIClient**: Wrapper für Azure-OpenAI-Chat-Completions in `azure/openai_client.py`.
|
||||
- **Batch**: Eine Gruppe von LLM-Anfragen, die gleichzeitig (concurrent) an die Azure OpenAI API gesendet werden.
|
||||
- **Batch_Size**: Maximale Anzahl gleichzeitig laufender LLM-Anfragen innerhalb eines Batches.
|
||||
- **Concurrency_Limit**: Obergrenze für die Anzahl paralleler HTTP-Anfragen an die Azure OpenAI API, um Rate-Limits nicht zu überschreiten.
|
||||
- **Rate_Limit**: Von Azure OpenAI auferlegte Begrenzung der Anfragen pro Zeiteinheit (Requests per Minute / Tokens per Minute).
|
||||
- **Semaphore**: Synchronisationsmechanismus zur Begrenzung der gleichzeitigen Zugriffe auf eine Ressource.
|
||||
- **MCP_Server**: Der Teamlandkarte MCP-Server (`mcp_server.py`).
|
||||
- **Capacity**: Frozen Dataclass `Capacity` in `models.py`.
|
||||
- **Task**: Frozen Dataclass `Task` in `models.py`.
|
||||
- **Capacity_Profile**: Aggregiertes Volltext-Profil einer Kapazität.
|
||||
- **Task_Profile**: Aggregiertes Volltext-Profil einer Aufgabe.
|
||||
|
||||
## Anforderungen
|
||||
|
||||
### Anforderung 1: Parallele LLM-Aufrufe mit konfigurierbarer Concurrency
|
||||
|
||||
**User Story:** Als Nutzer möchte ich, dass das LLM-Volltext-Matching mehrere Kapazitäten bzw. Aufgaben gleichzeitig bewertet, damit die Gesamtwartezeit bei vielen Kandidaten deutlich sinkt.
|
||||
|
||||
#### Akzeptanzkriterien
|
||||
|
||||
1. WHEN `match_capacities` oder `match_tasks` mit einer Liste von Kandidaten aufgerufen wird, THE LLM_Fulltext_Matcher SHALL alle LLM-Aufrufe für die Kandidaten concurrent (nicht sequenziell) ausführen, begrenzt durch das konfigurierte Concurrency_Limit.
|
||||
2. THE LLM_Fulltext_Matcher SHALL ein Concurrency_Limit verwenden, das die maximale Anzahl gleichzeitig laufender LLM-Anfragen auf einen konfigurierbaren Wert begrenzt.
|
||||
3. THE LLM_Fulltext_Matcher SHALL als Standard-Concurrency_Limit den Wert 5 verwenden, wenn kein anderer Wert konfiguriert ist.
|
||||
4. WHEN das Concurrency_Limit erreicht ist, THE LLM_Fulltext_Matcher SHALL weitere LLM-Anfragen zurückhalten, bis ein laufender Aufruf abgeschlossen ist, ohne Anfragen zu verwerfen.
|
||||
5. THE LLM_Fulltext_Matcher SHALL die Concurrency-Begrenzung über einen asyncio-Semaphore implementieren, sodass die Event-Loop nicht blockiert wird.
|
||||
|
||||
### Anforderung 2: Konfiguration des Concurrency-Limits
|
||||
|
||||
**User Story:** Als Entwickler möchte ich das Concurrency-Limit über die Konfigurationsdatei anpassen können, damit ich es an die Rate-Limits meines Azure-OpenAI-Deployments anpassen kann.
|
||||
|
||||
#### Akzeptanzkriterien
|
||||
|
||||
1. THE MCP_Server SHALL in `config.toml` unter `[azure_openai]` einen optionalen Schlüssel `max_concurrency` akzeptieren, der das Concurrency_Limit für parallele LLM-Aufrufe festlegt.
|
||||
2. WHEN `azure_openai.max_concurrency` nicht in `config.toml` gesetzt ist, THE MCP_Server SHALL den Standardwert 5 verwenden.
|
||||
3. IF `azure_openai.max_concurrency` auf einen Wert kleiner als 1 gesetzt ist, THEN THE MCP_Server SHALL beim Start einen `ConfigError` mit beschreibender Meldung werfen.
|
||||
4. IF `azure_openai.max_concurrency` auf einen Wert größer als 20 gesetzt ist, THEN THE MCP_Server SHALL beim Start einen `ConfigError` mit beschreibender Meldung werfen, da ein zu hoher Wert Rate-Limit-Fehler provoziert.
|
||||
5. THE AzureOpenAIConfig SHALL ein Feld `max_concurrency` vom Typ `int` mit Standardwert 5 enthalten.
|
||||
|
||||
### Anforderung 3: Ergebniskonsistenz bei paralleler Verarbeitung
|
||||
|
||||
**User Story:** Als Nutzer möchte ich, dass die Ergebnisse des parallelen Matchings identisch zu denen des sequenziellen Matchings sind, damit die Umstellung auf Batching keine funktionalen Unterschiede verursacht.
|
||||
|
||||
#### Akzeptanzkriterien
|
||||
|
||||
1. THE LLM_Fulltext_Matcher SHALL nach Abschluss aller parallelen LLM-Aufrufe die Ergebnisse in derselben deterministischen Sortierreihenfolge liefern wie bisher (primär nach Kategorie, sekundär nach `item_id` aufsteigend).
|
||||
2. THE LLM_Fulltext_Matcher SHALL bei paralleler Verarbeitung dieselbe Fehlerbehandlung anwenden wie bei sequenzieller Verarbeitung: fehlgeschlagene Aufrufe erscheinen in der Fehlerliste, erfolgreiche in `by_category`.
|
||||
3. THE LLM_Fulltext_Matcher SHALL sicherstellen, dass die Reihenfolge der Eingabe-Kandidaten keinen Einfluss auf die Sortierung der Ausgabe hat.
|
||||
4. THE LLM_Fulltext_Matcher SHALL bei paralleler Verarbeitung keine Race-Conditions bei der Zuordnung von LLM-Antworten zu Kandidaten aufweisen; jede Antwort wird exakt dem zugehörigen Kandidaten zugeordnet.
|
||||
|
||||
### Anforderung 4: Fehlerbehandlung bei Rate-Limit-Überschreitung
|
||||
|
||||
**User Story:** Als Entwickler möchte ich, dass das System bei Rate-Limit-Fehlern der Azure OpenAI API robust reagiert, damit einzelne 429-Fehler nicht den gesamten Matching-Lauf abbrechen.
|
||||
|
||||
#### Akzeptanzkriterien
|
||||
|
||||
1. WHEN ein LLM-Aufruf innerhalb eines Batches mit einem HTTP-429-Fehler (Rate Limit Exceeded) fehlschlägt, THE AzureOpenAIClient SHALL den Aufruf nach einer exponentiellen Backoff-Pause erneut versuchen (bestehendes Retry-Verhalten).
|
||||
2. WHEN ein LLM-Aufruf nach Ausschöpfung aller Retries endgültig fehlschlägt, THE LLM_Fulltext_Matcher SHALL diesen Kandidaten in der Fehlerliste ausweisen, ohne die parallele Verarbeitung der übrigen Kandidaten zu beeinflussen.
|
||||
3. THE LLM_Fulltext_Matcher SHALL sicherstellen, dass ein Fehler bei einem einzelnen Kandidaten nicht zum Abbruch oder zur Verzögerung der Verarbeitung anderer Kandidaten führt.
|
||||
4. IF alle LLM-Aufrufe eines Batches fehlschlagen, THEN THE LLM_Fulltext_Matcher SHALL ein Ergebnis mit leeren Kategorien und einer vollständigen Fehlerliste zurückgeben, ohne eine Exception zu werfen.
|
||||
|
||||
### Anforderung 5: Beibehaltung der bestehenden Schnittstelle
|
||||
|
||||
**User Story:** Als Entwickler möchte ich, dass die öffentliche Schnittstelle des LLM_Fulltext_Matcher unverändert bleibt, damit bestehende Aufrufer (MCP_Server, Tests) ohne Anpassung weiterhin funktionieren.
|
||||
|
||||
#### Akzeptanzkriterien
|
||||
|
||||
1. THE LLM_Fulltext_Matcher SHALL die Signaturen von `match_capacities` und `match_tasks` unverändert beibehalten (gleiche Parameter, gleicher Rückgabetyp `LlmFulltextResult`).
|
||||
2. THE LLM_Fulltext_Matcher SHALL den Rückgabetyp `LlmFulltextResult` (mit `by_category` und `errors`) unverändert beibehalten.
|
||||
3. WHEN der LLM_Fulltext_Matcher mit einer leeren Kandidatenliste aufgerufen wird, THE LLM_Fulltext_Matcher SHALL sofort ein leeres Ergebnis zurückgeben, ohne LLM-Aufrufe zu starten.
|
||||
4. THE LLM_Fulltext_Matcher SHALL das neue `max_concurrency`-Feld als optionalen Konstruktor-Parameter akzeptieren, mit Standardwert 5.
|
||||
|
||||
### Anforderung 6: Logging und Beobachtbarkeit
|
||||
|
||||
**User Story:** Als Entwickler möchte ich nachvollziehen können, wie viele LLM-Aufrufe parallel laufen und wie lange das Batching insgesamt dauert, damit ich Performance-Probleme diagnostizieren kann.
|
||||
|
||||
#### Akzeptanzkriterien
|
||||
|
||||
1. WHEN ein Batch-Matching gestartet wird, THE LLM_Fulltext_Matcher SHALL eine Log-Nachricht auf Level INFO ausgeben, die die Anzahl der Kandidaten und das konfigurierte Concurrency_Limit enthält.
|
||||
2. WHEN ein Batch-Matching abgeschlossen ist, THE LLM_Fulltext_Matcher SHALL eine Log-Nachricht auf Level INFO ausgeben, die die Gesamtdauer, die Anzahl erfolgreicher Kategorisierungen und die Anzahl der Fehler enthält.
|
||||
3. WHEN ein einzelner LLM-Aufruf innerhalb des Batches fehlschlägt, THE LLM_Fulltext_Matcher SHALL eine Log-Nachricht auf Level WARNING ausgeben, die die `item_id` und den Fehlergrund enthält.
|
||||
|
||||
### Anforderung 7: Abwärtskompatibilität mit Score-Modus
|
||||
|
||||
**User Story:** Als Nutzer möchte ich, dass das Batching ausschließlich den LLM-Volltext-Modus betrifft und der Score-Modus unverändert bleibt.
|
||||
|
||||
#### Akzeptanzkriterien
|
||||
|
||||
1. WHEN `matching_method = "score"` verwendet wird, THE MCP_Server SHALL das bestehende Score-basierte Matching ohne Änderungen ausführen.
|
||||
2. THE LLM_Fulltext_Matcher SHALL ausschließlich für den Modus `llm_fulltext` verwendet werden; der Score-Modus nutzt weiterhin den bestehenden `Matcher` und `SimilarityEngine`.
|
||||
3. THE MCP_Server SHALL keine neuen Abhängigkeiten oder Konfigurationsparameter einführen, die den Score-Modus beeinflussen.
|
||||
Reference in New Issue
Block a user