SRC-10: spracherkennung-ocr-qualitaetsbewertung
Spracherkennung für OCR-Texte und Qualitätsbewertung (Konfidenzwert), um schlechte OCR-Ergebnisse kenntlich zu machen. Letztes Ticket vor QA-03. - ocr/language.go: RecognizeWithLanguageAndConfidence erkennt ein Bild einzeln je Kandidatensprache (deu/eng) im Tesseract-TSV-Modus — die Sprache mit höherem Konfidenzwert gewinnt, derselbe Lauf liefert den Konfidenzwert direkt mit. - search: neue Felder ocr_language/ocr_confidence (Migrationen 0006/0007, gleiches ALTER-Muster wie SRC-05), in Document/Result gespiegelt. Client.AttachmentsBelowConfidence filtert gezielt auf niedrige Konfidenz, schließt Dokumente ohne OCR-Anhang aus. - Regressionsbug gefunden und behoben: reindex.go (SRC-09) kannte die neuen OCR-Spalten nicht, Reindex wäre mit "unknown column" fehlgeschlagen. Prüfungen (alle real durchgeführt, siehe mail/docs/SRC-10-PRUEFPROTOKOLL.md): 1. TestRecognizeWithLanguageAndConfidence_MultilingualCorpus: deutsches und englisches Testbild real korrekt als deu/eng erkannt. 2. TestRecognizeWithLanguageAndConfidence_DegradedImageLowersConfidence: künstliche Verschlechterung senkt Konfidenz real von 91,76 auf 28,21. 3. TestAttachmentsBelowConfidence_QueryReturnsExpectedResults: Abfrage unterhalb Schwelle liefert real genau die erwarteten 2 von 4 Treffern. Kein Umbau: Search/Facets/SearchWithFilters/Index/Delete-Verhalten sonst unverändert, dedup/indexworker/storage/crypto/encstorage/savedsearch unverändert. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HhgFcLS8tYMhDJpP74C6AQ
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
bd37de529f
commit
1a246abdb3
@@ -142,6 +142,8 @@ func (c *Client) SearchWithFilters(ctx context.Context, tenantSlug, queryText st
|
||||
Subject: hit.Source.Subject,
|
||||
Score: hit.Score,
|
||||
SentAtUnixEpoch: hit.Source.SentAtUnixEpoch,
|
||||
OCRLanguage: hit.Source.OCRLanguage,
|
||||
OCRConfidence: hit.Source.OCRConfidence,
|
||||
})
|
||||
}
|
||||
return results, nil
|
||||
@@ -230,6 +232,56 @@ func (c *Client) Facets(ctx context.Context, tenantSlug, queryText string, filte
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// AttachmentsBelowConfidence liefert alle Dokumente eines Mandanten, deren
|
||||
// OCR-Konfidenzwert UNTER threshold liegt (SRC-10 Akzeptanzkriterium 3:
|
||||
// gezielt für manuelle Nachbearbeitung auffindbar). Dokumente ohne
|
||||
// OCR-Anhang (ocr_confidence bleibt 0) tauchen hier NICHT auf — 0 ist
|
||||
// "kein Wert", nicht "schlechtester Wert" (siehe Document-Feldkommentar) —
|
||||
// daher zusätzlicher Filter ocr_confidence > 0.
|
||||
func (c *Client) AttachmentsBelowConfidence(ctx context.Context, tenantSlug string, threshold float64) ([]Result, error) {
|
||||
payload := map[string]any{
|
||||
"index": IndexName,
|
||||
"query": map[string]any{
|
||||
"bool": map[string]any{
|
||||
"must": []map[string]any{
|
||||
{"equals": map[string]any{FieldTenantSlug: tenantSlug}},
|
||||
{"range": map[string]any{FieldOCRConfidence: map[string]any{"gt": 0}}},
|
||||
{"range": map[string]any{FieldOCRConfidence: map[string]any{"lt": threshold}}},
|
||||
},
|
||||
},
|
||||
},
|
||||
"sort": []map[string]any{{FieldOCRConfidence: "asc"}},
|
||||
"limit": searchResultLimit,
|
||||
}
|
||||
body, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("search: konfidenzanfrage serialisieren: %w", err)
|
||||
}
|
||||
|
||||
respBody, err := c.doSearchWithSwapRetry(ctx, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var parsed searchResponse
|
||||
if err := json.Unmarshal(respBody, &parsed); err != nil {
|
||||
return nil, fmt.Errorf("search: antwort parsen: %w", err)
|
||||
}
|
||||
|
||||
results := make([]Result, 0, len(parsed.Hits.Hits))
|
||||
for _, hit := range parsed.Hits.Hits {
|
||||
results = append(results, Result{
|
||||
MessageID: hit.Source.MessageID,
|
||||
Subject: hit.Source.Subject,
|
||||
Score: hit.Score,
|
||||
SentAtUnixEpoch: hit.Source.SentAtUnixEpoch,
|
||||
OCRLanguage: hit.Source.OCRLanguage,
|
||||
OCRConfidence: hit.Source.OCRConfidence,
|
||||
})
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
type facetResponse struct {
|
||||
Aggregations map[string]struct {
|
||||
Buckets []struct {
|
||||
|
||||
Reference in New Issue
Block a user