Konfigurationsreferenz
Der Standalone-Host (MesoAibe.Service) bindet den Abschnitt Aibe aus appsettings.json
(Beispiel: MesoAibe.Service/appsettings.json) auf
AibeServiceKonfiguration. Die globalen Aibe:Ki-Zugaenge (Extraktion/Embedding/Rerank) gelten
fuer alle Mandanten; Aibe:Mandanten traegt je Eintrag genau einen Mandanten mit seiner
Beleganlage-Staffel, seinen Belegfeldern, optional Fremdsprachen-Mapping und kundenspezifischen
Artikelaufloesungen, seinem WebService-Zugang und seinen Postfaechern.
{
"ConnectionStrings": {
"WinLineXPOSystemConnection": "XpoProvider=MSSqlServer;Server=<SERVER>;Database=CWLSYSTEM;..."
},
"Aibe": {
"IntervallSekunden": 60,
"Ki": {
// Cloud-Variante; fuer lokale Modelle stattdessen ExtraktionBaseUrl/RerankBaseUrl setzen
// (siehe Abschnitt "KI-Zugaenge") oder DOTNET_ENVIRONMENT=Demo verwenden.
"AnthropicApiKey": "<ANTHROPIC_API_KEY>",
"ExtraktionModel": "claude-opus-4-8",
"EmbeddingBaseUrl": "https://api.openai.com/v1",
"EmbeddingApiKey": "<EMBEDDING_API_KEY>",
"EmbeddingModel": "text-embedding-3-small",
"RerankModel": "claude-opus-4-8"
},
"Mandanten": [
{
"Mandant": "500M",
"VkVorlage": "WS_Auftrag",
"Anlage": { "AnlegenAbKonfidenz": 60, "DruckenAbKonfidenz": 80, "DruckOption": "PrintAsOrder" },
"WebService": { "MesonicServerUrl": "http://<MESONIC_SERVER>:80", "Benutzer": "meso", "Passwort": "<MESONIC_PASSWORT>" },
"Postfaecher": [
{ "Typ": "Ordner", "Quelle": "./eingang", "MaxProLauf": 10, "VerarbeitetOrdner": "Verarbeitet", "FehlerOrdner": "Fehler" }
]
}
]
}
}
Globale Dienst-Einstellungen (Aibe)
Direkt unter Aibe (nicht unter Aibe:Mandanten[]) gelesen, ausserhalb der
AibeServiceKonfiguration-Bindung — siehe MesoAibe.Service/Program.cs:
| Feld | Bedeutung |
|---|---|
LogOrdner |
Zielordner der rollierenden Logdatei (mesoaibe-.log, taeglich neu). Default "logs" (relativ zum Programmverzeichnis). |
LogLevel |
Minimales Serilog-Log-Level (Verbose|Debug|Information|Warning|Error|Fatal). Ungueltiger oder fehlender Wert faellt auf "Information" zurueck. Debug schaltet zusaetzlich die LLM-Requests und -Antworten frei (siehe unten). Das Hosting-Framework (Microsoft.*) ist fest auf Warning gedaempft, damit Debug benutzbar bleibt. |
IntervallSekunden |
Abstand zwischen zwei Verarbeitungslaeufen aller Mandanten/Postfaecher. Default 60. |
StammdatenCacheMinuten |
Wie lange Artikel, Preise und Ersatznummern je Mandant zwischengespeichert werden, bevor sie neu aus der Datenbank gelesen werden. Ohne Angabe 5 Minuten, 0 liest bei jedem Zugriff neu. Bis zum Ablauf ist eine frisch in WinLine angelegte Artikelnummer für alle Matching-Stufen unsichtbar, auch für die Fuzzy- und Nummernstufen, die gar nicht am Embedding-Index hängen. Kürzer setzen, wenn Stammdaten häufig während des Betriebs geändert werden — jeder Ablauf kostet einen erneuten Katalog-Load. |
Protokollierung
Je verarbeitetem Dokument entsteht ein abgegrenzter Block: eine Kopfzeile mit Mandant und Kurzbezeichner (Betreff und Absender — nicht der technische Dateiname, der bei Graph-Postfaechern die rund 150 Zeichen lange Message-ID ist), darunter die sechs Schritte mit Ergebnis und Dauer:
────────────────────────────────────────────────────────────
500M "Bestellung 4711" von Austria Sports
1/6 Extraktion 2 Position(en) (12,4 s)
genannt: Partnernr=10004, Name=Austria Sports
2/6 Kunde 10004 Austria Sports GmbH [Kundennummer, 95] (0,1 s)
3/6 Artikel 2 von 2 Position(en) zugeordnet (3,8 s)
1. 3 x Laufschuh Pro 42 -> ART-1042 [Embedding+Rerank, 91]
2. 1 x ART-7788 -> ART-7788 [Artikelnummer, 100]
4/6 Ansprechpartner 7 (Rerank ueber Absendername, 4 Kandidat(en)) (1,9 s)
5/6 Anreicherung 1 Hinweis(e) (0,2 s)
Offenes Angebot AN-2291 passt zu dieser Bestellung: Bestellreferenz
6/6 Entscheid Gesamt-Konfidenz 93 -> AnlegenUndDrucken
WS-Import-XML -> ...\20260829_104812_123_bestellung_10004.xml
WinLine-Beleg angelegt: Belegnummer 100234
Bericht -> ...\20260829_104812_123_bestellung_10004.txt
────────────────────────────────────────────────────────────
Die Schrittzeilen tragen bewusst keinen eigenen Bezeichner. Das ist zulaessig, weil der
AibeWorker Dokumente strikt sequentiell abarbeitet — eine spaetere Parallelisierung muesste
den Bezeichner wieder je Zeile setzen.
Leerlauf (keine neuen Nachrichten) liegt auf Debug und flutet das Log damit nicht mehr im
Abfrageintervall.
LLM-Requests und -Antworten erscheinen bei "LogLevel": "Debug". Bei einem OpenAI-kompatiblen
Endpunkt ist das der tatsaechlich gesendete Request-Body; beim Claude-Client der fachliche Request
(Modell, Inhaltsbloecke, Prompt, Schema), weil das Anthropic-SDK den Wire-Body nicht herausgibt.
Beide Texte werden bei 4000 Zeichen gekuerzt. Voraussetzung ist MesoXPO.Business ab der Version,
die das Prompt-Logging mitbringt.
KI-Zugaenge (Aibe:Ki)
Gelten fuer alle Mandanten. Alle drei Stufen koennen wahlweise gegen die Cloud oder gegen einen OpenAI-kompatiblen Endpunkt (Ollama, vLLM, LM Studio ...) laufen:
| Feld | Bedeutung |
|---|---|
AnthropicApiKey |
Key fuer Claude — versorgt Extraktion und Rerank, wenn keine BaseUrl gesetzt ist. |
ExtraktionBaseUrl |
OpenAI-kompatibler Chat-Endpunkt fuer die Extraktion. Gesetzt gewinnt sie vor AnthropicApiKey. |
ExtraktionApiKey |
Key fuer ExtraktionBaseUrl; leer lassen, wenn der Endpunkt keinen verlangt. |
ExtraktionModel |
Modellname. Default claude-opus-4-8. Bei gesetzter ExtraktionBaseUrl zwingend auf das lokale Modell setzen. |
MaxTokens |
Obergrenze der Antwort-Tokens je Extraktionsaufruf. Default 16384 (Bibliothek ab 4.79-beta34; davor 4096); 0 oder fehlend behaelt den Default. Das Extraktionsschema traegt je Position alle Felder, rund 100 Tokens je Position — 4096 reichten im Pilot fuer 60 Positionen nicht. Eine abgeschnittene Antwort meldet der Dienst als Extraktionsfehler MaxTokens erreicht. |
PdfImmerUeberOcr |
Schickt PDFs auch beim Claude-Client ueber den Text-/OCR-Aufbereiter, statt sie nativ hochzuladen — die Option fuer "Cloud-Modell nutzen, Dokument aber nicht hochladen". Default false; bei gesetzter ExtraktionBaseUrl ohne Wirkung, weil dieser Pfad dort ohnehin gilt. |
PdfAlsBildFuerExtraktion |
Rendert PDFs auf dem lokalen Extraktionspfad (ExtraktionBaseUrl gesetzt oder PdfImmerUeberOcr) seitenweise zu PNG-Bildern (PdfZuBildAufbereiter/DocnetPdfBildQuelle, MesoAibe.Core) und schickt sie einem Vision-faehigen Modell, statt sie ueber den (siehe unten) unwirksamen Tesseract-OCR-Pfad in Text zu wandeln. Erfordert ein Vision-faehiges ExtraktionModel (z.B. qwen2.5vl ueber Ollama). Ohne ExtraktionBaseUrl/PdfImmerUeberOcr (reine Claude-Extraktion, liest PDF nativ) ohne Wirkung. Default false. |
PositionsanzahlPruefen |
Plausibilitaetspruefung der Positionsanzahl: ein zweiter, kleiner LLM-Aufruf zaehlt die Bestellpositionen im Dokument. Weicht die Zaehlung von der extrahierten Anzahl ab, wird einmal neu extrahiert; passt es dann nicht, gilt das Dokument als Extraktionsfehler (Fehlerordner, manuelle Pruefung) statt als verkuerzter Beleg in die Anlage zu gehen. Hintergrund: im Pilot kam eine 60-Positionen-Bestellung einmal als eine Position zurueck. Default true. |
PositionsanzahlToleranz |
Erlaubte Abweichung zwischen gezaehlter und extrahierter Positionsanzahl, z.B. 1 bei Bestellungen mit Fracht- oder Summenzeilen, die das Modell mal zaehlt und mal nicht. Default 0. |
EmbeddingBaseUrl |
OpenAI-kompatibler Embedding-Endpunkt (/embeddings). |
EmbeddingApiKey |
Key fuer den Embedding-Endpunkt. Darf nicht leer sein — sonst gilt die Embedding-Stufe als unkonfiguriert und das Artikelmatching faellt still auf die reine Kaskade zurueck. Bei Endpunkten ohne Key-Pflicht (Ollama) einen beliebigen Dummy eintragen. |
EmbeddingModel |
Modellname der Embedding-Erzeugung. |
RerankBaseUrl |
OpenAI-kompatibler Chat-Endpunkt fuer die Rerank-Stufe. Gesetzt gewinnt sie vor AnthropicApiKey. |
RerankApiKey |
Key fuer RerankBaseUrl; leer lassen, wenn der Endpunkt keinen verlangt. |
RerankModel |
Modellname der Rerank-Stufe. Default claude-haiku-4-5-20251001 — nicht identisch mit ExtraktionModel; wer den Schluessel weglaesst, faehrt anders als wer das Beispiel oben kopiert. Bei gesetzter RerankBaseUrl zwingend auf das lokale Modell setzen. |
Stellschrauben der Semantik-Stufe (Aibe:Ki, optional)
Diese Schlüssel stehen nicht in der ausgelieferten appsettings.json — sie sind Feinjustierung, und ein dort eingefrorener Wert würde spätere Verbesserungen der Bibliotheks-Defaults blockieren. Wer einen Schlüssel weglässt, fährt den Default; wer ihn setzt, übersteuert ihn.
| Schlüssel | Bedeutung | Default |
|---|---|---|
MinAehnlichkeit |
Mindest-Kosinusähnlichkeit, unter der ein Embedding-Kandidat verworfen wird. Modellabhängig — siehe Hinweis unten. | 0.35 |
AutoAcceptKonfidenz |
Ab dieser Konfidenz gilt ein Treffer als sicher und löst keinen Rerank aus. | 90 |
AmbiguitaetsAbstand |
Mindestabstand zwischen bestem und zweitbestem Kandidat, sonst gilt das Ergebnis als mehrdeutig. | 10 |
RerankBestaetigtKonfidenz |
Konfidenz, auf die ein vom Rerank bestätigter Treffer gehoben wird. | 90 |
MaxRerankKandidaten |
Wie viele Kandidaten je Position an das Rerank-Modell gehen. | 5 |
IndexTtl |
Gültigkeitsdauer des im Speicher gehaltenen Vektorindex, z.B. "00:05:00". |
5 Minuten |
IndexFehlerSperre |
Sperrzeit nach einem fehlgeschlagenen Index-Aufbau, z.B. "00:02:00". |
2 Minuten |
IndexZwischenspeicherAlle |
Blockgröße beim Embedding des Index-Deltas; 0 schaltet das Zwischenspeichern ab und ist ein gültiger Wert. |
500 |
MinAehnlichkeit gehört zum Modell, nicht zur Installation. Ein Embedding erzeugt keine absolute Skala: manche Modelle bewerten auch völlig unverwandte deutsche Texte mit 0,6 bis 0,9, andere spreizen weiter. Bei einem Modell mit hohem Grundniveau wird bei 0.35 praktisch jeder Artikel Kandidat — die Semantik-Stufe liefert dann Rauschen statt Signal, und der Rerank bekommt lauter gleich aussehende Vorschläge. Nach einem Wechsel des Embedding-Modells deshalb nicht nur prüfen, ob der richtige Artikel gefunden wird, sondern wie weit richtige und falsche Paare auseinanderliegen, und die Schwelle entsprechend nachziehen.
Ist weder AnthropicApiKey noch RerankBaseUrl gesetzt, registriert der Kern einen
NullKontaktReranker — der Dienst bleibt startfaehig, der Ansprechpartner-Schritt degradiert
aber auf "nur E-Mail-exakt".
Sobald ExtraktionBaseUrl gesetzt oder PdfImmerUeberOcr aktiv ist, liest kein Client mehr
PDF nativ: PDFs laufen dann ueber den PdfZuTextAufbereiter. Der liest je Seite den eingebetteten
Textlayer (PdfPig); Seiten ohne Textlayer (Scans) wuerde er ueber PDFium rendern und per Tesseract
erkennen. Diese OCR-Stufe ist derzeit inaktiv, weil der Kern OcrPdfTextQuelle ohne
tessdata-Verzeichnis registriert. Folgen:
- Reines Scan-PDF — kein Text,
PdfZuTextAufbereiterwirft, die Verarbeitung des Dokuments bricht ab (PDF '<Dateiname>' lieferte keinen Text (OCR fehlgeschlagen)). - Gemischtes PDF (digitale Seiten + Scan-Anhang) — die Scan-Seiten fallen still weg, das Modell sieht nur die Textseiten. Kein Fehler, aber unvollstaendige Extraktion.
- Digital erzeugtes PDF — unauffaellig, der Normalfall bei ERP-Bestellungen.
Alternative zur (derzeit inaktiven) Tesseract-Stufe: PdfAlsBildFuerExtraktion (oben) ersetzt
den Text-Aufbereiter durch PdfZuBildAufbereiter — jede PDF-Seite wird per PDFium (Docnet) zu
einem PNG gerendert und als Bild an ein Vision-faehiges Modell geschickt (auch Scan-PDFs, ohne
Tesseract/tessdata). Voraussetzung ist ein Vision-faehiges ExtraktionModel; ohne eines liefert
das Modell auf die Bild-Anhaenge vermutlich keine brauchbare Extraktion.
Betrieb mit lokalen Modellen (DOTNET_ENVIRONMENT=Demo)
Fuer Praesentationen und den datenschutzkritischen Betrieb liegt eine fertige, geheimnisfreie
Schicht bei: MesoAibe.Service/appsettings.Demo.json richtet alle drei Stufen auf einen lokalen
Ollama-Endpunkt aus. Aktiviert wird sie ueber die Umgebungsvariable:
$env:DOTNET_ENVIRONMENT = "Demo"
.\MesoAibe.Service.exe
Die Schichtung ist appsettings.json → appsettings.Development.json → appsettings.<Umgebung>.json
→ Umgebungsvariablen. Die Umgebungsdatei liegt also ueber der Development.json und ersetzt sie
nicht: sie uebersteuert nur Aibe:Ki, waehrend Datenbank-, WebService- und Postfach-Zugangsdaten
weiter aus der gitignorierten Development.json kommen. DOTNET_ENVIRONMENT=Development fuegt
keine weitere Schicht hinzu — die Development-Datei ist ohnehin fester Bestandteil der Kette.
Vorbereitung auf der Ollama-Seite:
ollama pull qwen2.5:14b-instruct # Extraktion + Rerank
ollama pull bge-m3 # Embedding (mehrsprachig)
Laeuft MesoAibe selbst im Container, zeigt localhost:11434 auf den falschen Container — die
Basis-URLs dann per Umgebungsvariable auf den Ollama-Service (http://ollama:11434/v1) oder den
Host (host.docker.internal) umbiegen; Compose-Beispiel in der Installationsanleitung, Abschnitt
„Lokale Modelle im Container".
Der Ollama-Container braucht ausserdem OLLAMA_CONTEXT_LENGTH (z.B. 16384). Mit dem Default
schneidet Ollama den Prompt aus E-Mail-Text, OCR-gewandeltem PDF und JSON-Schema still ab —
das Ergebnis sind leere oder halbe Extrakte ohne Fehlermeldung.
Beleganlage-Staffel (Aibe:Mandanten[].Anlage)
Die Staffel entscheidet anhand der Gesamtkonfidenz des Belegvorschlags (0-100), was mit ihm passiert — mit einer eigenen, niedrigeren Druckschwelle:
| Feld | Bedeutung |
|---|---|
AnlegenAbKonfidenz |
Ab dieser Konfidenz wird der Beleg automatisch angelegt. 0 = nie automatisch anlegen (immer nur Vorschlag). |
DruckenAbKonfidenz |
Ab dieser (hoeheren) Konfidenz wird der angelegte Beleg zusaetzlich gedruckt. 0 = nie drucken. Wenn gesetzt, muss der Wert >= AnlegenAbKonfidenz sein. |
DruckOption |
Druckform beim Erreichen der Druckschwelle (VoucherPrintOptionEnumeration-Name, Default PrintAsOrder). |
Beispiel 60/80/PrintAsOrder:
| Gesamtkonfidenz | Aktion |
|---|---|
| unter 60 | Nur Vorschlag — kein Beleg wird angelegt |
| 60-79 | Beleg wird angelegt, ohne zu drucken |
| ab 80 | Beleg wird angelegt und gedruckt (PrintAsOrder) |
Ohne vollstaendigen Vorschlag (Extraktion/Matching liefert kein BelegImportDto, z.B. weil der
Kunde nicht eindeutig zugeordnet werden konnte) ist die Aktion unabhaengig von der Staffel immer
NurVorschlag.
Weitere Mandanten-Felder (Aibe:Mandanten[])
| Feld | Bedeutung |
|---|---|
AnsprechpartnerFeld |
Ziel-Kopffeld fuer den ermittelten Ansprechpartner-Key. Default "Ansprechpartner". |
ExtraktionPrompt |
Eigener Extraktions-Prompt fuer diesen Mandanten. Nicht gesetzt/null = BelegfeldOptionen.StandardPrompt. Siehe Eigener Extraktions-Prompt. |
BestelldokumentAnhaengen |
Haengt das eingegangene Bestelldokument (PDF-Anhaenge der Mail, sonst die Roh-.eml) als Beleganhang an. Default true. |
BestelldokumentFormular |
Formularnummer fuer den Bestelldokument-Anhang. Default 0. |
ImportXmlOrdner |
Ordner, in dem die WebService-Import-XMLs archiviert werden (dient der Nachvollziehbarkeit, auch bei NurVorschlag). Nicht gesetzt/null = kein Archiv. |
BerichtOrdner |
Ordner fuer die Textberichte (.txt) dieses Mandanten (ein Bericht je verarbeitetem Dokument). Nicht gesetzt/null = kein Bericht. |
Eigener Extraktions-Prompt (ExtraktionPrompt)
Der Standard-Prompt (BelegfeldOptionen.StandardPrompt in MesoXPO.Business) ist bewusst
allgemein: er verbietet das Raten von Artikelnummern und ordnet bei tabellarischen Bestellungen
die Spaltenwerte den Spaltenkoepfen zu. Was er nicht kennen kann, ist die Beschriftung und
der Aufbau der Artikelnummern dieses Mandanten. Genau das ist der Grund fuer einen eigenen
Prompt — er ersetzt den Standard-Prompt vollstaendig, uebernimm ihn also mit.
Typischer Fehlerfall: die Bestellung nennt die eigene Artikelnummer unter einem mehrdeutigen Label wie „Best.-Nr." (das genauso die Bestellnummer des Kunden bezeichnen koennte), und daneben steht eine kundeneigene Materialnummer. Ohne Hinweis greift die Extraktion die falsche Spalte. Zwei Bausteine helfen: die Liste der Labels, unter denen die eigene Nummer im Kundendokument auftaucht, und ihr Aufbau als Muster samt Beispiel.
Beispiel fuer Artikelnummern der Form vier Ziffern, Leerzeichen, acht Ziffern (7000 00758345):
"ExtraktionPrompt": "Du extrahierst eine Kundenbestellung. Gib NUR die Daten zurueck, die im Dokument stehen — loese nichts gegen Stammdaten auf, rate keine Artikelnummern. Fehlende Felder: Textfelder leer, Zahlen und Daten null.\nBei tabellarischen Bestellungen ordne die Spaltenwerte den Spaltenkoepfen zu: der Wert einer Artikel-/Art.-Nr.-Spalte gehoert nach artikelNummerGenannt (nicht als Menge lesen).\n\nUnsere Artikelnummer (artikelNummerGenannt):\n- Sie steht im Kundendokument unter Beschriftungen wie \"Best.-Nr.\", \"Bestell-Nr.\", \"Ihre Art.-Nr.\", \"Lieferanten-Art.-Nr.\" und ist aufgebaut als vier Ziffern, Leerzeichen, acht Ziffern (Beispiel: \"7000 00758345\").\n- Uebernimm sie mit Leerzeichen nach der vierten Ziffer, auch wenn sie im Dokument ohne Leerzeichen oder mit Bindestrich geschrieben ist. Sonst nichts ergaenzen oder entfernen.\n- NICHT nach artikelNummerGenannt gehoeren: Positions- und Zeilennummern, die Bestellnummer des Kunden im Belegkopf, kundeneigene Materialnummern (\"Mat.-Nr.\"), Zeichnungs- und Normnummern sowie EAN/GTIN (die gehoert nach eanGenannt).\n- Nennt eine Zeile nur eine kundeneigene Nummer und keine unserer Nummern, lass artikelNummerGenannt leer — dann matcht die Bezeichnung."
Regeln, die sich im Pilot bewaehrt haben:
- Das Zielformat ist das WinLine-Format. Steht die Nummer im Artikelstamm mit Leerzeichen,
muss der Prompt die Nummer in dieses Format bringen — die Nummernstufen des Matchings
vergleichen exakt (nur
Trimund Gross-/Kleinschreibung), ein innenliegendes Leerzeichen entscheidet also ueber Treffer oder Nicht-Treffer. - Negativliste mitgeben. „Was gehoert nicht dorthin" wirkt bei mehrdeutigen Labels staerker als eine weitere Positivbeschreibung.
- Braucht der Beleg die kundeneigene Nummer, ist ein internes
Extrakt-Feld der richtige Ort (siehe Belegfelder) — nichtartikelNummerGenanntals Sammelbecken. - Zahlendreher muss der Prompt nicht mehr abfangen. Seit
MesoXPO.Business4.79 ist das Matching auf der Nummer fehlertolerant: eine Nummer, die sich nur in Trennzeichen unterscheidet, trifft mit Konfidenz 94 und wird ohne LLM-Aufruf übernommen; ein Zahlendreher oder ein einzelnes falsches Zeichen erzeugt einen Kandidaten mit Konfidenz 70, der bewusst unter der Auto-Accept-Schwelle liegt und darum geprüft wird — die Rerank-Stufe bekommt dazu jetzt auch die genannte Nummer. Die Zeile „Übernimm sie mit Leerzeichen nach der vierten Ziffer" im Beispiel oben bleibt trotzdem sinnvoll: ein exakter Treffer erreicht 100 und ist belastbarer als ein Schreibweise-Treffer mit 94.
WebService-Zugang (Aibe:Mandanten[].WebService)
| Feld | Bedeutung |
|---|---|
MesonicServerUrl |
Basis-URL des Mesonic Server WebService, z.B. "http://server:80". |
Benutzer |
WinLine-Benutzername. Optional, wenn VorhandeneSessionId gesetzt ist. |
Passwort |
WinLine-Passwort. Optional, wenn VorhandeneSessionId gesetzt ist. |
VorhandeneSessionId |
Alternativ zu Benutzer/Passwort: eine bereits bestehende WinLine-Session-ID. Nicht gesetzt = Anmeldung mit Benutzerdaten. |
Der Mandant kommt nicht aus diesem Abschnitt, sondern aus Aibe:Mandanten[].Mandant.
Angebotssuche (Aibe:Mandanten[].AngebotSuche)
Optionaler Anreicherungsschritt: sucht offene VK-Angebote des gematchten Kunden, die zur eingegangenen Bestellung passen, und meldet sie als Belegreferenz samt Hinweis. Die Ueberleitung Angebot → Auftrag gehoert bewusst nicht dazu — der Schritt informiert, er bucht nicht.
Fehlt der Abschnitt vollstaendig, ist der Schritt aus (es wird gar kein Anreicherer registriert).
Ein vorhandener Abschnitt mit "Aktiv": false verhaelt sich zur Laufzeit ebenso.
Die Bewertung laeuft in zwei Phasen:
- Referenzkriterium — Bestellreferenz bzw. Angebotsnummer, geprueft ueber alle offenen Angebote des Kunden. Das staerkere Kriterium darf nicht an einem Deckel scheitern.
- Positionskriterium — Ueberschneidung der Artikel, nur fuer die verbliebenen Kandidaten
(neueste zuerst) und begrenzt durch
MaxKandidaten, weil hier je Angebot eine Zeilenabfrage anfaellt.
| Feld | Bedeutung |
|---|---|
Aktiv |
Schaltet den Schritt ab, ohne den Abschnitt zu entfernen. Default true. |
ReferenzExtraktFeld |
Name des Extrakt-Felds, das die Bestellreferenz des Kunden traegt (z.B. "bestellreferenz"). Nicht gesetzt = Phase 1 prueft nur den Mail-Betreff. |
PositionsSchwelle |
Mindestanteil der gematchten Vorschlagspositionen, die im Angebot vorkommen muessen (0..1). Default 0.5. |
ZielKopffeld |
Kopf-Zusatzfeld, in das die Laufnummer des ersten gemeldeten Treffers geschrieben wird (durch die Phasenreihenfolge bevorzugt ein Referenztreffer). Nicht gesetzt = kein Feld. |
MaxKandidaten |
Deckel fuer Phase 2. Default 20. Auf Phase 1 hat er keine Wirkung. |
Belegfelder (Kopffelder/Positionsfelder)
Kopffelder und Positionsfelder sind konfigurierbare Zusatzfelder, die zusaetzlich zu den vom
Belegvorschlag gelieferten Kernfeldern in die WinLine-Vorlage geschrieben werden. Jedes Feld
braucht genau eine Wertquelle und — ausser bei internen Extrakt-Feldern (siehe unten) — ein
Ziel-Vorlagenfeld:
| Quelle | Felder | Bedeutung |
|---|---|---|
| KI-extrahiert | Extrakt + Typ |
Extrakt ist der JSON-Property-Name aus der KI-Extraktion, Typ einer von date|string|decimal|int (bei dieser Quelle Pflicht). Beschreibung ist ein optionaler Hinweis fuer Schema und Prompt. |
| Meta-Formatstring | Quelle |
Formatstring mit Platzhaltern {absender}, {absendername}, {betreff}, {dateiname}, {empfangsdatum}. |
| Konstante | Vorgabe |
Fester Vorgabewert. |
MaxLaenge (optional) kuerzt den Endwert auf N Zeichen. Ist nicht genau eine Quelle gesetzt, fehlt
bei Extrakt der Typ oder fehlt bei Quelle/Vorgabe das Vorlagenfeld, scheitert
AibeOptionen.Validiere() beim Start des Mandanten.
Interne Felder: Ein Extrakt-Feld darf ohne Vorlagenfeld stehen. Es wird dann extrahiert
(Schema und Prompt), aber in keinen Beleg geschrieben — es steht nur den Anreicherern zur Verfuegung,
z.B. der kundenspezifischen Artikelaufloesung (siehe unten) als laenge.
Grenze der Extrakt-Felder (Claude-Extraktion): Die Anthropic-API lehnt das Extraktionsschema ab
(Schema is too complex, jede Mail landet im Fehlerordner), wenn zu viele optionale Felder
zusammenkommen. Gemessen am 2026-09-03 mit claude-opus-4-8 und claude-opus-5: mit zwei
Kopf-Extraktfeldern sind acht Positions-Properties (sechs feste plus zwei Extrakt-Felder) noch
zulaessig, neun nicht — unabhaengig von Typ, Beschreibung oder date-Format. Ursache ist die
Zahl optionaler Properties je Objekt (die Grammatik muss jede Reihenfolge zulassen); die Bibliothek
deklariert Extrakt-Felder als optional. Wer mehr Positionsfelder braucht, muss bis zu einer
Bibliotheksaenderung (Felder als required deklarieren, siehe Spec) Felder streichen oder den
OpenAI-kompatiblen Extraktionspfad nutzen.
Beispiel (ein Kopffeld "Vertragsnummer" aus der KI-Extraktion):
"Kopffelder": [
{
"Vorlagenfeld": "Vertragsnummer",
"Extrakt": "Vertragsnummer",
"Typ": "string",
"Beschreibung": "Vom Kunden genannte Vertrags-/Bestellnummer"
}
]
Stammdaten-Fallback (Stammfeld, Gruppe)
WinLine-Importsemantik: Ein in der ExIm-Vorlage angezeigtes Feld wird beim Import erwartet
und bei leerem Wert leer importiert; nur nicht angezeigte Felder fuellt WinLine selbst aus den
Stammdaten. Wer abweichende Lieferangaben aus der Bestellung uebernehmen will, fuehrt die
Lief.*-Felder in der Vorlage und gibt jedem ein Stammfeld als Fallback: ein XPO-Property-Pfad
auf das ermittelte Personenkonto (Konto.<Pfad>, z.B. Konto.Kontoname) oder den Ansprechpartner
(Ansprechpartner.<Pfad>). Regel je Feld: Extrakt, sonst Stammwert, sonst leer — ein Feld mit
Stammfeld wird immer geschrieben. Gruppe haelt eine Adresse zusammen: liefert die
Extraktion fuer ein Feld der Gruppe einen Wert, bekommen die uebrigen Gruppenfelder leer statt
Stammwert (keine gemischten Adressen). Jedes Feld einer Gruppe braucht ein Stammfeld;
Stammfeld ist nur an Kopffeldern zulaessig. Die Pfade prueft AibeOptionen.Validiere() beim
Start; die Stammwerte laedt der immer registrierte StammfeldAnreicherer der Bibliothek. Wird das
Konto nicht gefunden, bleiben die Werte leer und der Bericht enthaelt einen Hinweis.
Beispiel (Lieferadresse aus der Bestellung, Fallback auf das Personenkonto):
"Kopffelder": [
{ "Vorlagenfeld": "Lief.Name", "Extrakt": "liefName", "Typ": "string", "Gruppe": "Lief", "Stammfeld": "Konto.Kontoname",
"Beschreibung": "Abweichender Lieferempfaenger, sonst weglassen" },
{ "Vorlagenfeld": "Lief.Strasse", "Extrakt": "liefStrasse", "Typ": "string", "Gruppe": "Lief", "Stammfeld": "Konto.Strasse" },
{ "Vorlagenfeld": "Lief.PLZ", "Extrakt": "liefPlz", "Typ": "string", "Gruppe": "Lief", "Stammfeld": "Konto.Postleitzahl" },
{ "Vorlagenfeld": "Lief.Ort", "Extrakt": "liefOrt", "Typ": "string", "Gruppe": "Lief", "Stammfeld": "Konto.Ort" }
]
Property-Namen der Stammfelder an den MesoXPO-Modellen (ViewKontenstamm, KontakteStamm) pruefen;
die Pfade werden beim Start validiert, ein Tippfehler faellt also sofort auf. Offen (Pilotlauf):
Der Nachweis der Importsemantik gegen eine Vorlage mit angezeigten Lief.*-Feldern steht noch aus.
Fremdsprachige Bestellungen (Aibe:Mandanten[].Fremdsprachen)
Fremdsprachige Bestellungen treffen die deutsche Artikelbezeichnung nur schwach. Liegt die
Uebersetzung beim Kunden in einem frei nutzbaren Artikel-Textfeld (Zusatzfeld, Notiz, Langtext),
schaltet ein Mapping Sprache → Feld dieses Feld als zusaetzlichen Vergleichstext frei (Stufe 5b
der Matching-Kaskade in MesoXPO.Business). Die Dokumentsprache erkennt die Extraktion
(ISO 639-1, z.B. en); der Orchestrator reicht sie an das Matching durch. Ohne Sprache, bei de
oder ohne Mapping fuer die Sprache bleibt das Verhalten unveraendert. Fehlt der Abschnitt oder ist
FeldJeSprache leer, wird die Stufe gar nicht registriert.
| Feld | Bedeutung |
|---|---|
FeldJeSprache |
ISO-Sprachcode → Feldname der Artikelview: Zusatzfeld1..30, Notiz1..10, Langtext1, Langtext2. Andere Feldnamen oder de als Sprache scheitern beim Start. |
FremdtextDeckel |
Konfidenz-Deckel eines Treffers auf dem Fremdtext (1..85). Default 80 — bewusst unter den 85 der deutschen Bezeichnung, weil Fremdsprachenfelder erfahrungsgemaess weniger konsistent gepflegt sind. |
FremdtextImSuchdokument |
Nimmt die Fremdtexte zusaetzlich ins Embedding-Suchdokument auf. Aendert den Doc-Hash und loest einmalig ein Neu-Embedden der betroffenen Artikel aus. Default false. |
"Fremdsprachen": {
"FeldJeSprache": { "en": "Notiz3", "fr": "Zusatzfeld12" },
"FremdtextDeckel": 80
}
Im Bericht erscheint ein solcher Treffer mit Matchgrund Bezeichnung en (Fuzzy).
Kundenspezifische Artikelaufloesung (Aibe:Mandanten[].ProzedurAufloesungen)
Generischer Anreicherungsschritt fuer Zuordnungsregeln, die nicht in den Dienst gehoeren —
Referenzfall: eine bestellte Kabellaenge auf die passende Charge aufloesen (in WinLine ein
eigener Auspraegungsartikel Haupt<Trennzeichen>NNNNN, Trennzeichen je Mandant in T300 C015).
Je Position mit Treffer ruft der Dienst eine Stored Procedure in der Mandanten-Datenbank mit
dem gesamten Vorgangskontext (JSON) auf; sie liefert die endgueltige Artikelnummer. Konfiguriert
wird nur der Prozedurname — alles Kundenspezifische (Feldnamen, Muster, Einheiten, Regeln) lebt
in appsettings, Prompt-Text und Prozedur, nicht im Dienst. Je Listeneintrag entsteht ein Schritt,
die Reihenfolge ist die Kettenreihenfolge (nach der Angebotssuche).
| Feld | Bedeutung |
|---|---|
Prozedur |
Prozedurname in der Mandanten-DB, optional schema.name. Nur Bezeichner — kein freies SQL. Pflicht. |
NurWennFeld |
Nur aufrufen, wenn die Position dieses Extrakt-Feld traegt (z.B. "laenge"). Nicht gesetzt = jede Position mit Treffer. |
NurChargenartikel |
Nur bei Treffern auf Chargenartikel (T024 C014 = 1, C025 in {0,3,4}). Default false. |
KonfidenzOhneAufloesung |
Konfidenz-Deckel der Position, wenn die Prozedur keine oder mehrere Zeilen liefert oder fehlschlaegt (0..100). Bibliotheks-Default 70. Muss unter Anlage.AnlegenAbKonfidenz liegen (sonst scheitert Validiere() beim Start), damit die Degradierung die automatische Anlage tatsaechlich verhindert — mit der Vorlagen-Staffel 60/80 also hoechstens 59, z.B. 50. |
MaxKandidaten |
Anzahl Kandidaten der Position im Parameter @kandidaten. Default 5. |
Aktiv |
Schaltet den Schritt ab, ohne den Eintrag zu entfernen. Default true. |
Verhalten: Genau eine Ergebniszeile ersetzt den Treffer (Konfidenz bleibt, Matchgrund
+ Prozedur <Name>, der alte Treffer bleibt als UrspruenglicherTreffer sichtbar; das Protokoll
zeigt Treffer ersetzt: alt -> neu). Keine Zeile, mehrere Zeilen und jeder Prozedurfehler
degradieren geschlossen: die Position wird auf KonfidenzOhneAufloesung gedeckelt, ein Hinweis
landet im Bericht, die uebrigen Positionen laufen weiter. Weil die Gesamtkonfidenz das Minimum ueber
alle Positionen ist, faellt ein Beleg mit ungeloester Position damit unter AnlegenAbKonfidenz und
landet in der manuellen Pruefung statt in der automatischen Anlage — gewollt. Der Dienst erzwingt
diese Beziehung: liegt KonfidenzOhneAufloesung nicht unter Anlage.AnlegenAbKonfidenz (bei
Staffel > 0), startet der Mandant nicht.
Vertrag der Prozedur (Details und eine Referenzprozedur fuer den Kabel-Fall: README von
MesoXPO.Business, Abschnitt "Prozedur-Artikelaufloesung"):
- Parameter
@mandant,@kontonummer,@artikelnummer,@konfidenz,@positionsindex,@position,@beleg,@dokument,@kandidaten— benannt gebunden, die Deklarationsreihenfolge in der Prozedur ist frei.@positiontraegt alle Extrakt-Felder der Position unter ihrem Prompt-Namen (JSON_VALUE(@position, '$.laenge')),@belegden Kopf mitspracheund allen Positionen. - Ergebnis: Spalte
Artikelnummer(Pflicht), optionalBezeichnung,Hinweis. Gelesen wird nur das erste Resultset;SET NOCOUNT ONwird erwartet. - Voraussetzung
JSON_VALUE/OPENJSON: SQL Server 2016 oder neuer.
Beispiel (Kabel-Fall: internes Positionsfeld laenge plus Prozedur):
"Positionsfelder": [
{
"Extrakt": "laenge",
"Typ": "decimal",
"Beschreibung": "Bestellte Laenge in Metern, falls die Position eine Laenge nennt (z.B. '305 m', '0,3 km' -> 300). Sonst weglassen."
}
],
"ProzedurAufloesungen": [
{ "Prozedur": "CSS_AibeChargeWaehlen", "NurWennFeld": "laenge", "NurChargenartikel": true, "KonfidenzOhneAufloesung": 50 }
]
Postfaecher (Aibe:Mandanten[].Postfaecher)
Je Eintrag ein Typ (Ordner | Imap | Graph) mit den passenden Feldern (siehe
PostfachOptionen): Ordner braucht nur Quelle (Eingangsverzeichnis); Imap zusaetzlich
ImapHost/ImapPort/ImapSsl/ImapBenutzer/ImapPasswort; Graph zusaetzlich
GraphTenantId/GraphClientId/GraphClientSecret/GraphPostfach (App-Permission
Mail.ReadWrite). MaxProLauf (Default 10) deckelt die pro Lauf gelesenen Dokumente je
Postfach.
| Schluessel | Bedeutung |
|---|---|
Quelle |
Ordner: das Eingangsverzeichnis. Imap/Graph: der ueberwachte Ordner im Postfach, Default Inbox. Unterordner mit / getrennt, z.B. Inbox/Bestellungen; bei Graph steht Inbox als erste Ebene fuer den Posteingang unabhaengig von seinem Anzeigenamen (Posteingang). Bei allen Typen wird nur dieser eine Ordner gelesen, nicht seine Unterordner. |
VerarbeitetOrdner |
Unterordner der Quelle fuer Dokumente, aus denen ein Beleg angelegt wurde. Default Verarbeitet. Wird bei Bedarf angelegt. |
FehlerOrdner |
Unterordner der Quelle fuer Dokumente, deren Verarbeitung oder Beleganlage gescheitert ist. Default Fehler. Wird bei Bedarf angelegt. |
VorschlagOrdner |
Unterordner der Quelle fuer Dokumente, die unter AnlegenAbKonfidenz blieben — es wurde nur ein Vorschlag gemeldet, kein Beleg angelegt. Nicht gesetzt = sie landen im VerarbeitetOrdner und sind dort von echten Belegen nicht zu unterscheiden. Fuer eine Pilotphase mit manueller Nachkontrolle empfiehlt sich ein eigener Ordner, z.B. Vorschlag. |
Die drei Ablageordner liegen bei allen Typen unterhalb der Quelle — ein ueberwachter Ordner
Inbox/Bestellungen bekommt also die Unterordner Bestellungen/Verarbeitet, Bestellungen/Fehler
und ggf. Bestellungen/Vorschlag.
Keine Kommentare vorhanden
Keine Kommentare vorhanden