Services: Admin-Compliance, Backend-Compliance, AI-Compliance-SDK, Consent-SDK, Developer-Portal, PCA-Platform, DSMS Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
183 lines
5.8 KiB
Go
183 lines
5.8 KiB
Go
package api
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"github.com/breakpilot/ai-compliance-sdk/internal/rag"
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// RAGHandler handles RAG search requests
|
|
type RAGHandler struct {
|
|
ragService *rag.Service
|
|
}
|
|
|
|
// NewRAGHandler creates a new RAG handler
|
|
func NewRAGHandler(ragService *rag.Service) *RAGHandler {
|
|
return &RAGHandler{
|
|
ragService: ragService,
|
|
}
|
|
}
|
|
|
|
// Search performs semantic search on the legal corpus
|
|
func (h *RAGHandler) Search(c *gin.Context) {
|
|
query := c.Query("q")
|
|
if query == "" {
|
|
ErrorResponse(c, http.StatusBadRequest, "Query parameter 'q' is required", "MISSING_QUERY")
|
|
return
|
|
}
|
|
|
|
topK := 5
|
|
if topKStr := c.Query("top_k"); topKStr != "" {
|
|
if parsed, err := strconv.Atoi(topKStr); err == nil && parsed > 0 {
|
|
topK = parsed
|
|
}
|
|
}
|
|
|
|
collection := c.DefaultQuery("collection", "legal_corpus")
|
|
filter := c.Query("filter") // e.g., "regulation:DSGVO" or "category:ai_act"
|
|
|
|
// Check if RAG service is available
|
|
if h.ragService == nil {
|
|
// Return mock data when RAG is not available
|
|
SuccessResponse(c, gin.H{
|
|
"query": query,
|
|
"topK": topK,
|
|
"results": h.getMockResults(query),
|
|
"source": "mock",
|
|
})
|
|
return
|
|
}
|
|
|
|
results, err := h.ragService.Search(c.Request.Context(), query, topK, collection, filter)
|
|
if err != nil {
|
|
ErrorResponse(c, http.StatusInternalServerError, "Search failed: "+err.Error(), "SEARCH_FAILED")
|
|
return
|
|
}
|
|
|
|
SuccessResponse(c, gin.H{
|
|
"query": query,
|
|
"topK": topK,
|
|
"results": results,
|
|
"source": "qdrant",
|
|
})
|
|
}
|
|
|
|
// GetCorpusStatus returns the status of the legal corpus
|
|
func (h *RAGHandler) GetCorpusStatus(c *gin.Context) {
|
|
if h.ragService == nil {
|
|
SuccessResponse(c, gin.H{
|
|
"status": "unavailable",
|
|
"collections": []string{},
|
|
"documents": 0,
|
|
})
|
|
return
|
|
}
|
|
|
|
status, err := h.ragService.GetCorpusStatus(c.Request.Context())
|
|
if err != nil {
|
|
ErrorResponse(c, http.StatusInternalServerError, "Failed to get corpus status", "STATUS_FAILED")
|
|
return
|
|
}
|
|
|
|
SuccessResponse(c, status)
|
|
}
|
|
|
|
// IndexDocument indexes a new document into the corpus
|
|
func (h *RAGHandler) IndexDocument(c *gin.Context) {
|
|
var req struct {
|
|
Collection string `json:"collection" binding:"required"`
|
|
ID string `json:"id" binding:"required"`
|
|
Content string `json:"content" binding:"required"`
|
|
Metadata map[string]string `json:"metadata"`
|
|
}
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
ErrorResponse(c, http.StatusBadRequest, err.Error(), "INVALID_REQUEST")
|
|
return
|
|
}
|
|
|
|
if h.ragService == nil {
|
|
ErrorResponse(c, http.StatusServiceUnavailable, "RAG service not available", "SERVICE_UNAVAILABLE")
|
|
return
|
|
}
|
|
|
|
err := h.ragService.IndexDocument(c.Request.Context(), req.Collection, req.ID, req.Content, req.Metadata)
|
|
if err != nil {
|
|
ErrorResponse(c, http.StatusInternalServerError, "Failed to index document: "+err.Error(), "INDEX_FAILED")
|
|
return
|
|
}
|
|
|
|
SuccessResponse(c, gin.H{
|
|
"indexed": true,
|
|
"id": req.ID,
|
|
"collection": req.Collection,
|
|
"indexedAt": now(),
|
|
})
|
|
}
|
|
|
|
// getMockResults returns mock search results for development
|
|
func (h *RAGHandler) getMockResults(query string) []SearchResult {
|
|
// Simplified mock results based on common compliance queries
|
|
results := []SearchResult{
|
|
{
|
|
ID: "dsgvo-art-5",
|
|
Content: "Art. 5 DSGVO - Grundsätze für die Verarbeitung personenbezogener Daten: Personenbezogene Daten müssen auf rechtmäßige Weise, nach Treu und Glauben und in einer für die betroffene Person nachvollziehbaren Weise verarbeitet werden.",
|
|
Source: "DSGVO",
|
|
Score: 0.95,
|
|
Metadata: map[string]string{
|
|
"article": "5",
|
|
"regulation": "DSGVO",
|
|
"category": "grundsaetze",
|
|
},
|
|
},
|
|
{
|
|
ID: "dsgvo-art-6",
|
|
Content: "Art. 6 DSGVO - Rechtmäßigkeit der Verarbeitung: Die Verarbeitung ist nur rechtmäßig, wenn mindestens eine der folgenden Bedingungen erfüllt ist: Einwilligung, Vertragserfüllung, rechtliche Verpflichtung, lebenswichtige Interessen, öffentliche Aufgabe, berechtigtes Interesse.",
|
|
Source: "DSGVO",
|
|
Score: 0.89,
|
|
Metadata: map[string]string{
|
|
"article": "6",
|
|
"regulation": "DSGVO",
|
|
"category": "rechtsgrundlage",
|
|
},
|
|
},
|
|
{
|
|
ID: "ai-act-art-6",
|
|
Content: "Art. 6 AI Act - Klassifizierungsregeln für Hochrisiko-KI-Systeme: Ein KI-System gilt als Hochrisiko-System, wenn es als Sicherheitskomponente eines Produkts verwendet wird oder selbst ein Produkt ist, das unter die in Anhang II aufgeführten Harmonisierungsrechtsvorschriften fällt.",
|
|
Source: "AI Act",
|
|
Score: 0.85,
|
|
Metadata: map[string]string{
|
|
"article": "6",
|
|
"regulation": "AI_ACT",
|
|
"category": "hochrisiko",
|
|
},
|
|
},
|
|
{
|
|
ID: "nis2-art-21",
|
|
Content: "Art. 21 NIS2 - Risikomanagementmaßnahmen: Wesentliche und wichtige Einrichtungen müssen geeignete und verhältnismäßige technische, operative und organisatorische Maßnahmen ergreifen, um die Risiken für die Sicherheit der Netz- und Informationssysteme zu beherrschen.",
|
|
Source: "NIS2",
|
|
Score: 0.78,
|
|
Metadata: map[string]string{
|
|
"article": "21",
|
|
"regulation": "NIS2",
|
|
"category": "risikomanagement",
|
|
},
|
|
},
|
|
{
|
|
ID: "dsgvo-art-35",
|
|
Content: "Art. 35 DSGVO - Datenschutz-Folgenabschätzung: Hat eine Form der Verarbeitung, insbesondere bei Verwendung neuer Technologien, aufgrund der Art, des Umfangs, der Umstände und der Zwecke der Verarbeitung voraussichtlich ein hohes Risiko für die Rechte und Freiheiten natürlicher Personen zur Folge, so führt der Verantwortliche vorab eine Abschätzung der Folgen der vorgesehenen Verarbeitungsvorgänge für den Schutz personenbezogener Daten durch.",
|
|
Source: "DSGVO",
|
|
Score: 0.75,
|
|
Metadata: map[string]string{
|
|
"article": "35",
|
|
"regulation": "DSGVO",
|
|
"category": "dsfa",
|
|
},
|
|
},
|
|
}
|
|
|
|
return results
|
|
}
|