Some checks failed
Tests / Go Tests (push) Has been cancelled
Tests / Python Tests (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / Go Lint (push) Has been cancelled
Tests / Python Lint (push) Has been cancelled
Tests / Security Scan (push) Has been cancelled
Tests / All Checks Passed (push) Has been cancelled
Security Scanning / Secret Scanning (push) Has been cancelled
Security Scanning / Dependency Vulnerability Scan (push) Has been cancelled
Security Scanning / Go Security Scan (push) Has been cancelled
Security Scanning / Python Security Scan (push) Has been cancelled
Security Scanning / Node.js Security Scan (push) Has been cancelled
Security Scanning / Docker Image Security (push) Has been cancelled
Security Scanning / Security Summary (push) Has been cancelled
CI/CD Pipeline / Go Tests (push) Has been cancelled
CI/CD Pipeline / Python Tests (push) Has been cancelled
CI/CD Pipeline / Website Tests (push) Has been cancelled
CI/CD Pipeline / Linting (push) Has been cancelled
CI/CD Pipeline / Security Scan (push) Has been cancelled
CI/CD Pipeline / Docker Build & Push (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / CI Summary (push) Has been cancelled
ci/woodpecker/manual/build-ci-image Pipeline was successful
ci/woodpecker/manual/main Pipeline failed
All services: admin-v2, studio-v2, website, ai-compliance-sdk, consent-service, klausur-service, voice-service, and infrastructure. Large PDFs and compiled binaries excluded via .gitignore.
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
|
|
}
|