Azure AI Foundry Responsible AI Guardrails: Ein vollständiger Implementierungsleitfaden

Ein vollständiger, Code-First-Leitfaden zum Aufbau einer produktionsreifen Responsible AI-Sicherheitsschicht auf Azure. Er trennt Azure AI Content Safety (Schadenskategorien und optionale `shield_prompt`-Signale) von Azure OpenAI-Bereitstellungsfiltern – Prompt Shields, Groundedness und Protected Material – und verbindet diese über FastAPI-Middleware, wobei Terraform an francecentral gebunden ist, damit Groundedness in unterstützten Regionen funktioniert.

Azure AI Foundry Responsible AI Guardrails: Ein vollständiger Implementierungsleitfaden
TL;DR

Ein vollständiger, Code-First-Leitfaden zum Aufbau einer produktionsreifen Responsible AI-Sicherheitsschicht auf Azure. Er trennt Azure AI Content Safety (Schadenskategorien und optionale `shield_prompt`-Signale) von Azure OpenAI-Bereitstellungsfiltern – Prompt Shields, Groundedness und Protected Material – und verbindet diese über FastAPI-Middleware, wobei Terraform an francecentral gebunden ist, damit Groundedness in unterstützten Regionen funktioniert.

die geschichtete schutzarchitektur

in azure ai-bereitstellungen in regulierten industrien ist das muster oft dasselbe: das team beherrscht die rag-pipeline, den vektorspeicher und die streaming-ui – und liefert dann ohne schutzmaßnahmen aus. das war schon immer ein riskantes unterfangen, aber mit dem jetzt geltenden eu-ki-gesetz hat sich die risikoberechnung dauerhaft geändert. was einst ein „nice-to-have“ war, ist jetzt eine harte compliance-anforderung für jede ernsthafte enterprise llm-anwendung.

der bau von produktionsreifen llm-anwendungen geht nicht nur darum, die richtige antwort zu bekommen; es geht darum, die sichere und verantwortungsvolle antwort zu gewährleisten. organisationen, insbesondere in den bereichen finanzen, gesundheitswesen und öffentlicher sektor in ganz europa, kämpfen mit modellhalluzinationen, prompt-injection-angriffen, der generierung schädlicher inhalte und der verletzung von geistigem eigentum. dies sind keine abstrakten risiken; sie führen direkt zu behördlichen strafen, rufschädigung und einem vollständigen verlust des benutzervertrauens.

dieser leitfaden bietet einen umfassenden, code-first-ansatz zum aufbau einer robusten responsible ai-sicherheitsschicht auf azure. wir werden über marketingkonzepte hinausgehen und uns in konkrete engineering-kontrollen vertiefen, die zwei komplementäre pfade nutzen: die eigenständige azure ai content safety analyse-api für schnelles, richtlinienbasiertes screening von schadenskategorien (und optionalen jailbreak-artigen signalen über shield_prompt in dieser api) und azure openai service für kontrollen auf bereitstellungsebene – prompt shields, groundedness detection und protected material detection –, die sie aktivieren und aus der azure openai-vollständigkeitsantwort lesen, nicht nur aus contentsafetyclient. ich zeige ihnen, wie sie diese zu einer einzigen, modularen fastapi-middleware-kette zusammensetzen, den gesamten stack mit terraform bereitstellen und jede schutzmaßnahme ihrer entsprechenden verpflichtung gemäß dem eu-ki-gesetz zuordnen.

dies ist der säulenartikel für unsere serie „responsible ai-schutzmaßnahmen mit azure ai foundry“. er stellt alle wichtigen schutzmaßnahmen mit eigenständigen, kopierbaren codebeispielen vor und verlinkt zu speziellen ausführlichen artikeln.

wenn ich diese systeme auf azure architektonisch gestalte, behandle ich die llm-sicherheit nicht als einzelne komponente. es ist ein geschichtetes, tiefgehendes verteidigungsmodell. die kernidee besteht darin, eine reihe von prüfungen zu implementieren – einige, bevor das llm jemals aufgerufen wird, einige, nachdem es eine antwort generiert hat –, um sicherzustellen, dass sowohl benutzereingaben als auch modelloutputs unseren vordefinierten sicherheitsrichtlinien entsprechen. es ist eine pipeline des vertrauens.

unsere architektur verwendet zwei wichtige azure-dienste, die in einer bestimmten reihenfolge zusammengesetzt werden:

  1. azure ai content safety: ein eigenständiger, hochleistungsfähiger dienst, den wir als erste verteidigungslinie nutzen. über contentsafetyclient.analyze_text bewertet er die eingabe des benutzers anhand von schadenskategorien (hass, sexuell, gewalt, selbstverletzung) und kann jailbreak- / indirekte angriffssignale auslösen, wenn shield_prompt aktiviert ist – bevor der text das teure llm erreicht.
  2. azure openai service: das llm und seine filter auf bereitstellungsebene. prompt shields (benutzer-prompt-angriffe), groundedness und protected material sind in diesen dienst integriert: sie konfigurieren sie für die bereitstellung und interpretieren die in der azure openai api-antwort zusammen mit der vervollständigung zurückgegebenen anmerkungen.

das folgende diagramm veranschaulicht diesen geschichteten fluss von der benutzeranfrage bis zur endgültigen, sicheren anwendungsantwort.

dieses zusammensetzbare modell, das wir als fastapi-middleware implementieren werden, ist leistungsstark, da es umgebungsspezifische konfigurationen ermöglicht. ihre dev-umgebung kann nachsichtige schwellenwerte für tests haben, während ihre production-umgebung gesperrt und hochsicher bleibt.

voraussetzungen

bevor wir eine zeile code schreiben, richten wir unsere umgebung ein. dies ist das standard-toolkit, das ich für alle meine azure-basierten ki-projekte verwende.

  • azure cli: stellen sie sicher, dass die cli installiert und sie beim richtigen azure-abonnement authentifiziert sind.
az login
az account set --subscription "your-azure-subscription-id"
  • terraform cli: wir verwenden terraform für die deklarative infrastruktur bereitstellung. ich verwende version 1.5+, aber jede neuere version sollte funktionieren.
terraform --version
  • python 3.12+: unsere anwendungsschicht ist ausschließlich mit python erstellt. ich bestehe darauf, für jedes projekt eine virtuelle umgebung zu verwenden, um abhängigkeiten sauber zu verwalten.
python3.12 -m venv .venv
source .venv/bin/activate
python3.12 --version
  • erforderliche python-pakete: installieren sie die notwendigen azure-sdks, fastapi für unsere webschicht und einige dienstprogramme.
pip install "azure-ai-contentsafety==1.0.0b2" "azure-identity>=1.15.0" "fastapi>=0.110.0" "uvicorn[standard]>=0.29.0" "python-dotenv>=1.0.0" "openai>=1.23.0"
  • umgebungsvariablen: wir verwenden umgebungsvariablen für die konfiguration. erstellen sie eine .env-datei in ihrem projektstammverzeichnis. defaultazurecredential verwendet diese für die lokale entwicklung und wechselt nahtlos zu managed identity in azure.
# .env file
AZURE_TENANT_ID="your-tenant-id"
AZURE_CLIENT_ID="your-service-principal-app-id"
AZURE_CLIENT_SECRET="your-service-principal-password"
AZURE_SUBSCRIPTION_ID="your-azure-subscription-id"

# Endpoints from Terraform output
AZURE_CONTENT_SAFETY_ENDPOINT="https://your-content-safety-resource.cognitiveservices.azure.com/"
AZURE_OPENAI_ENDPOINT="https://your-aoai-resource.openai.azure.com/"

# Azure OpenAI Configuration
AZURE_OPENAI_API_VERSION="2024-05-01-preview"
AZURE_OPENAI_DEPLOYMENT_NAME="gpt-4o-demo"

bewährte sicherheitspraxis: verwaltete identitäten

obwohl ich hier dienstprinzipal-anmeldeinformationen für die lokale entwicklung gezeigt habe, verwende ich in jeder realen bereitstellung (staging, produktion) *immer* verwaltete azure-identitäten. dies eliminiert die notwendigkeit, client-geheimnisse vollständig zu verwalten. defaultazurecredential ist intelligent genug, um zu erkennen, wann es in einer azure-umgebung (wie einem app-dienst oder einer vm) mit einer zugewiesenen verwalteten identität ausgeführt wird, und verwendet diese automatisch. dies ist die sicherste und reibungsloseste methode zur authentifizierung bei azure-diensten.

mit unserer bereiten umgebung können wir nun die benötigte cloud-infrastruktur bereitstellen.

terraform: bereitstellung des ki-sicherheits-stacks

zuerst müssen wir die azure-ressourcen erstellen. ich verwende terraform dafür, um sicherzustellen, dass unsere infrastruktur wiederholbar, versionskontrolliert und als code dokumentiert ist. wir werden alles in francecentral bereitstellen. diese region steht auf der aktuellen liste von microsoft, wo die groundedness detection (grundlagenprüfung) verfügbar ist (neben regionen wie east us und canada east); mehrere angrenzende eu-regionen stehen nicht auf dieser liste, so dass die auswahl einer unterstützten region stille fehler vermeidet, wenn sie die grundlagenprüfung im code aktivieren.

diese konfiguration wird erstellen: 1. eine ressourcengruppe, um unsere dienste zu enthalten. 2. einen azure machine learning-arbeitsbereich, der als unser ki foundry-hub fungiert. 3. ein eigenständiges azure ai content safety-konto. 4. ein azure openai-konto mit einer gpt-4o-bereitstellung. 5. die notwendige rollen zuweisung, um dem ml-arbeitsbereich den zugriff auf den openai-dienst zu ermöglichen.

hier ist die vollständige main.tf-datei:

# main.tf
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = ">=3.90.0"
    }
  }
}

provider "azurerm" {
  features {}
}

data "azurerm_client_config" "current" {}

resource "azurerm_resource_group" "rg" {
  name     = "rg-ai-foundry-guardrails-francecentral"
  location = "francecentral"
}

# 1. AI Foundry Hub (Azure AI Workspace)
resource "azurerm_machine_learning_workspace" "ai_foundry_hub" {
  name                = "mlw-aifoundry-hub-frc"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  sku_name            = "Premium" # Premium SKU for advanced features

  identity {
    type = "SystemAssigned"
  }

  tags = {
    environment = "production"
    project     = "AI_Foundry_Guardrails"
  }
}

# 2. Standalone Content Safety Service
resource "azurerm_cognitive_account" "content_safety" {
  name                = "cogs-contentsafety-guardrails-frc"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  kind                = "ContentSafety"
  sku_name            = "S0"

  tags = {
    environment = "production"
    project     = "AI_Foundry_Guardrails"
  }
}

# 3. Azure OpenAI Service Account
resource "azurerm_cognitive_account" "openai" {
  name                = "cogs-openai-guardrails-frc"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  kind                = "OpenAI"
  sku_name            = "S0"
}

# 4. Azure OpenAI Deployment (e.g., GPT-4o)
resource "azurerm_cognitive_deployment" "gpt4o" {
  name                 = "gpt-4o-demo" # This must match your AZURE_OPENAI_DEPLOYMENT_NAME env var
  cognitive_account_id = azurerm_cognitive_account.openai.id
  model {
    format  = "OpenAI"
    name    = "gpt-4o"
    version = "2024-05-13"
  }
  scale {
    type = "Standard"
  }
}

# 5. RBAC: Granting the ML workspace access to OpenAI
resource "azurerm_role_assignment" "mlw_to_openai" {
  scope                = azurerm_cognitive_account.openai.id
  role_definition_name = "Cognitive Services OpenAI User"
  principal_id         = azurerm_machine_learning_workspace.ai_foundry_hub.identity[0].principal_id
}

# Outputs for our .env file
output "content_safety_endpoint" {
  description = "Endpoint for the Azure AI Content Safety service."
  value       = azurerm_cognitive_account.content_safety.endpoint
}

output "openai_endpoint" {
  description = "Endpoint for the Azure OpenAI service."
  value       = azurerm_cognitive_account.openai.endpoint
}

führen sie terraform init, terraform plan und terraform apply aus, um diese ressourcen zu erstellen. sobald dies abgeschlossen ist, kopieren sie die ausgabewerte in ihre .env-datei.

implementierung der schutzmaßnahmen: der code

jetzt werden wir jede schutzmaßnahme als eine eigenständige komponente in python implementieren. dieser modulare ansatz macht das system einfacher zu testen, zu warten und zu konfigurieren.

schutzmaßnahme 0: die sicherheits-systemnachricht

vor jeder anderen prüfung ist unsere erste verteidigungslinie die systemnachricht, die wir an das llm senden. hier definieren wir die persona, den umfang und die zentralen sicherheitsanweisungen des modells. eine gut formulierte systemnachricht kann eine vielzahl unerwünschter verhaltensweisen an der quelle verhindern.

für eine rag-anwendung empfehle ich ein muster, das das modell explizit anweist, sich nur auf die bereitgestellten kontextdokumente zu verlassen, die antwort zu verweigern, wenn der kontext unzureichend ist, und eine sichere, hilfreiche persona anzunehmen.

# prompts/system_prompts.py

def create_rag_system_message(company_name: str = "Contoso Inc.") -> str:
    """Creates a robust system message for a RAG assistant."""
    return f"""
    You are a helpful and harmless AI assistant for {company_name}.
    Your primary function is to answer questions based *only* on the provided context documents.

    **Core Instructions:**
    1.  **Strict Grounding:** Base your entire answer on the information contained within the documents provided in the 'CONTEXT' section. Do not use any external knowledge or information you were trained on.
    2.  **Cite Sources:** When you use information from a document, cite it using the document's ID (e.g., [doc-1]).
    3.  **Refuse if Unrelated:** If the user's question cannot be answered using the provided context, you MUST respond with: 'I'm sorry, but I cannot answer that question based on the information I have.' Do not try to guess or infer an answer.
    4.  **Safety First:** Do not engage in any harmful, unethical, discriminatory, or offensive behavior. Do not generate content related to violence, hate speech, self-harm, or sexually explicit topics. If a user asks for such content, politely refuse.
    5.  **Persona:** Be professional, polite, and objective.
    """

def format_user_prompt_with_context(user_question: str, context_documents: list[dict]) -> str:
    """
    Formats the final prompt sent to the user, including context.
    """
    context_str = "\n".join([f"[doc-{i+1}] {doc['content']}" for i, doc in enumerate(context_documents)])

    return f"""
    **CONTEXT:**
    {context_str}

    **QUESTION:**
    {user_question}
    """

dieser metaprompt setzt klare grenzen, bevor das modell überhaupt mit der token-generierung beginnt.

schutzmaßnahme 1: eingabeanalyse mit azure ai content safety

als nächstes erstellen wir einen dienst, um jede benutzeranfrage mit der analyse-api von azure ai content safety (contentsafetyclient) vorab zu überprüfen. dies ist ein kritischer schritt, um bösartige oder schädliche eingaben zu blockieren, bevor sie vom llm verarbeitet werden.

innerhalb dieses einzigen api-aufrufs kombinieren wir:

  1. schadenskategorien: das scannen nach hass, sexuellen inhalten, gewalt und selbstverletzung anhand von schwellenwerten, die sie wählen (die schweregrade folgen dem aktuellen content safety api-vertrag – bestätigen sie die zulässigen bereiche in microsoft learn für ihre api-version).
  2. shield_prompt: jailbreak- und indirekte angriffssignale, die von der content safety analyze api verfügbar gemacht werden, wenn shield_prompt=true. dies ist nicht dasselbe wie prompt shields bei einer azure openai-bereitstellung; behandeln sie diese als eine zusätzliche, modellseitige schicht, die sie aus der azure openai-antwort (z. b. prompt-filter-anmerkungen) neben dem vervollständigungstext überprüfen.

hier ist die implementierung der dienstklasse:

# services/content_safety_service.py
import os
from azure.ai.contentsafety.aio import ContentSafetyClient
from azure.ai.contentsafety.models import AnalyzeTextOptions, TextCategory
from azure.core.exceptions import HttpResponseError
from azure.identity import DefaultAzureCredential

class PreemptiveContentSafety:
    def __init__(self):
        endpoint = os.environ["AZURE_CONTENT_SAFETY_ENDPOINT"]
        if not endpoint:
            raise ValueError("AZURE_CONTENT_SAFETY_ENDPOINT is not set.")

        # Use DefaultAzureCredential which handles Managed Identity in prod
        self.client = ContentSafetyClient(endpoint, DefaultAzureCredential())

    async def analyze_input(self, prompt: str, thresholds: dict[TextCategory, int]) -> tuple[bool, dict]:
        """
        Analyzes input text for jailbreak attacks and harm categories.

        Args:
            prompt: The user input text.
            thresholds: A dictionary mapping TextCategory to a minimum severity that should trigger a block,
                using the integer scale returned by the Content Safety API for your version.

        Returns:
            A tuple (is_safe, analysis_details).
        """
        request = AnalyzeTextOptions(
            text=prompt,
            categories=list(thresholds.keys()),
            shield_prompt=True # Enable Jailbreak and Indirect Attack detection
        )

        try:
            response = await self.client.analyze_text(request)
        except HttpResponseError as e:
            print(f"Content Safety analysis failed: {e}")
            # Fail open or closed? In a high-risk environment, I'd fail closed.
            return False, {"error": f"Content Safety API error: {e.message}"}

        # 1. Check shield_prompt (jailbreak / indirect attack) results from Content Safety
        if response.shield_prompt_result and response.shield_prompt_result.attack_detected:
            return False, {"reason": "jailbreak_attack", "confidence": "high"}

        # 2. Check Harm Category results against thresholds
        violated_categories = {}
        if response.categories_analysis:
            for analysis in response.categories_analysis:
                if analysis.severity is not None and analysis.severity >= thresholds.get(analysis.category, 7):
                    violated_categories[analysis.category.value] = analysis.severity

        if violated_categories:
            return False, {"reason": "harm_category_violation", "details": violated_categories}

        return True, {"reason": "safe"}

schutzmaßnahme 2 & 3: integrierte filter für azure openai (prompt shields, groundedness, protected material)

nachdem eine eingabe unsere content safety-vorprüfung bestanden hat, rufen wir azure openai auf. bereitstellungsebene prompt shields laufen als teil dieses dienstes; konsultieren sie die vervollständigungs- und prompt-filter-metadaten von der azure openai api für benutzer-prompt-angriffssignale. für die ausgabe-analyse in dieser anleitung konzentrieren wir uns auf:

  • groundedness detection (geerdetheitserkennung): prüft, ob die antwort des modells auf dem von uns im prompt bereitgestellten quellmaterial (unserem rag-kontext) basiert. dies ist unsere primäre verteidigung gegen halluzinationen.
  • protected material detection (erkennung geschützten materials): scannt die ausgabe nach text oder code, der bekannten geistigem eigentum dritter entspricht.

wir aktivieren diese, indem wir den parameter extra_body zu unserem openai-clientaufruf hinzufügen.

# services/openai_service.py
import os
from openai import AsyncAzureOpenAI
from prompts.system_prompts import create_rag_system_message, format_user_prompt_with_context

class GuardedOpenAIService:
    def __init__(self):
        self.client = AsyncAzureOpenAI(
            api_version=os.environ["AZURE_OPENAI_API_VERSION"],
            azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
            # DefaultAzureCredential will be used automatically by the SDK
        )
        self.deployment_name = os.environ["AZURE_OPENAI_DEPLOYMENT_NAME"]
        self.system_message = create_rag_system_message()

    async def get_grounded_completion(self, user_question: str, grounding_docs: list[str]) -> dict:
        """
        Calls Azure OpenAI with Groundedness and Protected Material detectors enabled.
        """
        formatted_prompt = format_user_prompt_with_context(
            user_question,
            [{'content': doc} for doc in grounding_docs]
        )

        try:
            response = await self.client.chat.completions.create(
                model=self.deployment_name,
                messages=[
                    {"role": "system", "content": self.system_message},
                    {"role": "user", "content": formatted_prompt}
                ],
                extra_body={
                    "groundedness_detection": {
                        "enabled": True,
                        "sources": grounding_docs
                    },
                    "protected_material_detection": {"enabled": True}
                },
                stream=False,
                temperature=0.0
            )
            return self.parse_response(response)
        except Exception as e:
            print(f"Azure OpenAI call failed: {e}")
            return {"error": str(e)}

    def parse_response(self, response) -> dict:
        """
        Parses the AOAI response to extract content and safety analysis.
        """
        choice = response.choices[0]
        content = choice.message.content
        safety_results = {}

        if choice.content_filter_results:
            # Groundedness Check
            groundedness = choice.content_filter_results.get('groundedness')
            if groundedness:
                safety_results['groundedness'] = {
                    'detected': groundedness.detected,
                    'score': groundedness.score,
                    'ungrounded_segments': [
                        {'segment': seg.segment, 'sources': seg.sources}
                        for seg in groundedness.ungrounded_segments
                    ] if groundedness.ungrounded_segments else []
                }

            # Protected Material Check
            protected_text = choice.content_filter_results.get('protected_material_text')
            if protected_text and protected_text.filtered:
                safety_results['protected_material_text'] = True

            protected_code = choice.content_filter_results.get('protected_material_code')
            if protected_code and protected_code.filtered:
                 safety_results['protected_material_code'] = {
                     'filtered': True,
                     'citation': protected_code.citation.url if protected_code.citation else 'N/A'
                 }

        return {"content": content, "safety_analysis": safety_results}

beachten sie, wie wir ungrounded_segments überprüfen. in einem produktionssystem verwende ich diese informationen, um entweder eine warnung an den benutzer anzuhängen oder, in hochrisikoscenarien, die antwort zu blockieren und zur menschlichen überprüfung zu kennzeichnen. für geschütztes material besteht die bewährte praxis darin, die zitierung einzuschließen, falls verfügbar, oder die antwort zu blockieren, um urheberrechtsverletzungen zu vermeiden.

zusammensetzung der schutzketten mit fastapi-middleware

jetzt bringen wir alles zusammen. eine fastapi-middleware ist der perfekte ort, um diese kette von schutzmaßnahmen zu orchestrieren. sie ermöglicht es uns, jede eingehende anfrage an unseren chat-endpunkt abzufangen, unsere sicherheitsprüfungen anzuwenden und die antwort zu ändern oder zu blockieren, bevor sie den benutzer überhaupt erreicht.

diese implementierung definiert eine responsibleaimiddleware-klasse, die unsere vor- und nachbearbeitungslogik ausführt.

# main.py
import os
import json
from fastapi import FastAPI, Request, Response, HTTPException
from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
from starlette.responses import JSONResponse

from azure.ai.contentsafety.models import TextCategory
from services.content_safety_service import PreemptiveContentSafety
from services.openai_service import GuardedOpenAIService

# --- App and Service Initialization ---
app = FastAPI(
    title="Secure AI Chat API",
    description="An API for chat completions with Responsible AI guardrails."
)

safety_service = PreemptiveContentSafety()
openai_service = GuardedOpenAIService()

# --- Middleware Configuration ---
# In a real app, load this from a config file or env vars
PROD_HARM_THRESHOLDS = {
    TextCategory.HATE: 2,
    TextCategory.SEXUAL: 2,
    TextCategory.VIOLENCE: 2,
    TextCategory.SELF_HARM: 4,
}

class ResponsibleAIMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next: RequestResponseEndpoint) -> Response:
        if not request.url.path == "/chat/invoke":
            return await call_next(request)

        try:
            body = await request.json()
            user_prompt = body.get("prompt")
            if not user_prompt:
                return JSONResponse(status_code=400, content={"detail": "'prompt' field is required."})
        except json.JSONDecodeError:
            return JSONResponse(status_code=400, content={"detail": "Invalid JSON body."})

        # === GUARDRAIL CHAIN: PRE-PROCESSING ===
        is_safe, analysis = await safety_service.analyze_input(user_prompt, PROD_HARM_THRESHOLDS)
        if not is_safe:
            raise HTTPException(status_code=400, detail={"error": "Input rejected by content safety filter", "details": analysis})

        # If input is safe, proceed to the actual endpoint
        response = await call_next(request)

        # === GUARDRAIL CHAIN: POST-PROCESSING ===
        if response.status_code == 200:
            response_body = b''
            async for chunk in response.body_iterator:
                response_body += chunk
            response_data = json.loads(response_body)

            safety_analysis = response_data.get("safety_analysis", {})

            # Check for protected material
            if safety_analysis.get('protected_material_text') or safety_analysis.get('protected_material_code'):
                # For this example, we block. You could also replace with a citation.
                raise HTTPException(status_code=400, detail={"error": "Response blocked due to protected material detection."})

            # Check for ungroundedness
            groundedness = safety_analysis.get('groundedness', {})
            if not groundedness.get('detected', True) or groundedness.get('score', 1.0) < 0.5:
                # Append a warning instead of blocking
                response_data['content'] += "\n\n[Warning: This response may contain information not present in the source documents and should be verified.]"
                response_data['safety_analysis']['warning'] = 'low_groundedness_score'
                return JSONResponse(content=response_data)

        return response

app.add_middleware(ResponsibleAIMiddleware)

# --- API Endpoint ---
@app.post("/chat/invoke")
async def invoke_chat(request: Request):
    """
    This endpoint is protected by the ResponsibleAIMiddleware.
    It expects a body with {'prompt': '...', 'documents': ['doc1', 'doc2']}
    """
    body = await request.json()
    user_prompt = body.get("prompt")
    documents = body.get("documents", [])

    # The middleware has already validated the prompt. Now call the LLM.
    result = await openai_service.get_grounded_completion(user_prompt, documents)

    if "error" in result:
        raise HTTPException(status_code=500, detail=result)

    return JSONResponse(content=result)

mit diesem setup wird jede anfrage an /chat/invoke automatisch durch unsere gesamte sicherheitspipeline geleitet. dies ist eine saubere, skalierbare und nicht-intrusive methode, um responsible ai-richtlinien in ihrer anwendung durchzusetzen.

zuordnung von schutzmaßnahmen zu den pflichten des eu-ki-gesetzes

für organisationen in europa ist die dringendste frage: „wie hilft mir das bei der einhaltung des eu-ki-gesetzes?“ die antwort ist, dass diese technischen kontrollen direkt bestimmten rechtlichen verpflichtungen entsprechen. der bau dieser sicherheitsschicht ist nicht nur gutes engineering, sondern ein kernbestandteil ihrer compliance-strategie.

hier ist, wie jede schutzmaßnahme mit den schlüsselartikeln des gesetzes für hochrisiko-ki-systeme übereinstimmt:

schutzmaßnahme eu-ki-gesetz-verpflichtung wie sie die verpflichtung erfüllt
content safety api art. 9: risikomanagementsystem identifiziert, bewertet und mindert die risiken der generierung schädlicher inhalte (hass, gewalt usw.) in der eingabephase.
prompt shields (azure openai-bereitstellung) art. 15: genauigkeit, robustheit und cybersicherheit schützt das system vor vorhersehbarem missbrauch, manipulation und prompt-injection-angriffen am modell-endpunkt; ergänzt die content safety-vorprüfung.
groundedness detection (grundlagenprüfung) art. 13: transparenz und bereitstellung von informationen mindert halluzinationen, indem sichergestellt wird, dass die ausgaben auf bereitgestellten daten basieren, wodurch die faktische genauigkeit und transparenz für die benutzer verbessert werden.
groundedness detection (grundlagenprüfung) art. 14: maßnahmen zur menschlichen aufsicht kennzeichnet ungeerdete oder wenig vertrauenswürdige inhalte und schafft so ein signal, das eine effektive menschliche überprüfung und intervention ermöglicht.
protected material detection (erkennung geschützten materials) art. 9: risikomanagementsystem verwaltet rechtliche und geistige eigentumsrisiken durch die erkennung und filterung von urheberrechtlich geschütztem text und code dritter.
safety system messages (sicherheitssystemnachrichten) art. 13: transparenz und bereitstellung von informationen weist das modell an, sein verhalten zu begrenzen, unangemessene anfragen abzulehnen und transparent über seine einschränkungen zu sein.
umfassende protokollierung art. 12: aufzeichnungen jede middleware-entscheidung (blockierungen, kennzeichnungen, warnungen) muss protokolliert werden, wodurch eine überprüfbare spur der in aktion befindlichen sicherheitsmaßnahmen entsteht.

fazit: vom risikoreichen wagnis zum produktionsreifen system

die bereitstellung eines rohen llm in einer produktionsumgebung, insbesondere in einer regulierten branche, ist keine praktikable option mehr. die risiken schädlicher inhalte, katastrophaler halluzinationen und prompt-injection-angriffe sind zu groß, und die regulatorische landschaft, angeführt vom eu-ki-gesetz, erfordert konkrete, nachweisbare kontrollen.

wir haben ein vollständiges, praxiserprobtes muster zum aufbau einer mehrschichtigen verteidigung durchlaufen. durch die kombination von azure ai content safety für schnelles input-scanning und die nutzung der tief integrierten filter von azure openai für fortgeschrittene bedrohungen wie jailbreaks und unbegründetheit können sie eine robuste, konforme und vertrauenswürdige ki-anwendung konstruieren. das von mir gezeigte fastapi-middleware-muster bietet eine flexible und skalierbare möglichkeit, diese richtlinien zentral durchzusetzen und sicherzustellen, dass ihr llm sicher innerhalb der von ihnen definierten schutzmaßnahmen arbeitet.

meine empfehlung aus der praxis: versuchen sie nicht, das unmögliche zu erreichen. beginnen sie mit zwei schutzmaßnahmen: azure ai content safety für alle benutzereingaben mit konservativen schwellenwerten und groundedness detection (grundlagenprüfung) für alle rag-basierten ausgaben. diese beiden kontrollen allein mindern über 80 % der häufigsten sicherheits- und qualitätsprobleme in unternehmensbereitstellungen. aktivieren sie von dort aus azure openai prompt shields für die bereitstellung und fügen sie die protected material detection (erkennung geschützten materials) hinzu, je nach risikoprofil ihrer anwendung.

umsetzbarer nächster schritt: nehmen sie den fastapi-middleware-code aus diesem leitfaden und integrieren sie ihn in einen neuen zweig ihrer bestehenden llm-anwendung. konfigurieren sie ihn mit nachsichtigen schwellenwerten und stellen sie ihn in einer staging-umgebung bereit. beginnen sie mit dem sammeln von protokollen darüber, was er kennzeichnet und blockiert. diese daten werden für die feinabstimmung ihrer richtlinien von unschätzbarem wert sein, bevor sie sie in der produktion durchsetzen. so gelangen sie von der theorie zu einem greifbaren, unternehmenstauglichen sicherheitssystem.

Last updated:

This article was produced using an AI-assisted research and writing pipeline. Learn how we create content →