Skip to content

Commit 59e6651

Browse files
author
Paweł Kędzia
committed
Add speakleash guardrails: Flask API (sojka_guard_app.py), SojkaModelConfig, and run_sojka_guardrail.sh launch script.
1 parent 0043b28 commit 59e6651

File tree

4 files changed

+118
-0
lines changed

4 files changed

+118
-0
lines changed

llm_router_services/guardrails/speakleash/__init__.py

Whitespace-only changes.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from __future__ import annotations
2+
3+
from dataclasses import dataclass
4+
5+
from llm_router_services.guardrails.inference.config import GuardrailModelConfig
6+
7+
8+
@dataclass(frozen=True)
9+
class SojkaModelConfig(GuardrailModelConfig):
10+
pipeline_batch_size: int = 64
11+
min_score_for_safe: float = 0.5
12+
min_score_for_not_safe: float = 0.5
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import os
2+
from typing import Any, Dict
3+
4+
from flask import Flask, request, jsonify
5+
6+
from llm_router_services.guardrails.constants import SERVICES_API_PREFIX
7+
from llm_router_services.guardrails.inference.factory import (
8+
GuardrailClassifierModelFactory,
9+
)
10+
from llm_router_services.guardrails.speakleash.config import SojkaModelConfig
11+
12+
# -----------------------------------------------------------------------
13+
# Environment prefix – all configuration keys start with this value
14+
# -----------------------------------------------------------------------
15+
_ENV_PREFIX = "LLM_ROUTER_SOJKA_GUARD_"
16+
17+
app = Flask(__name__)
18+
19+
MODEL_PATH = os.getenv(f"{_ENV_PREFIX}MODEL_PATH", None)
20+
if not MODEL_PATH:
21+
raise Exception(
22+
f"Sojka guardrail model path is not set! "
23+
f"Export {_ENV_PREFIX}MODEL_PATH with proper model path"
24+
)
25+
26+
# Keep only a single constant for the device (CPU by default)
27+
DEFAULT_DEVICE = int(os.getenv(f"{_ENV_PREFIX}DEVICE", "-1"))
28+
29+
# -----------------------------------------------------------------------
30+
# Build the guardrail object via the factory, passing the Sojka‑specific config
31+
# -----------------------------------------------------------------------
32+
guardrail = GuardrailClassifierModelFactory(
33+
model_type="text_classification",
34+
model_path=MODEL_PATH,
35+
device=DEFAULT_DEVICE,
36+
config=SojkaModelConfig(),
37+
)
38+
39+
40+
# -----------------------------------------------------------------------
41+
# Endpoint: POST /api/guardrails/sojka_guard
42+
# -----------------------------------------------------------------------
43+
@app.route(f"{SERVICES_API_PREFIX}/sojka_guard", methods=["POST"])
44+
def sojka_guardrail():
45+
"""
46+
Accepts a JSON payload, classifies the content and returns the aggregated results.
47+
"""
48+
if not request.is_json:
49+
return jsonify({"error": "Request body must be JSON"}), 400
50+
51+
payload: Dict[str, Any] = request.get_json()
52+
try:
53+
results = guardrail.classify_chunks(payload)
54+
return jsonify({"results": results}), 200
55+
except Exception as exc: # pragma: no cover – safety net
56+
return jsonify({"error": str(exc)}), 500
57+
58+
59+
# -----------------------------------------------------------------------
60+
# Run the Flask server (only when executed directly)
61+
# -----------------------------------------------------------------------
62+
if __name__ == "__main__":
63+
host = os.getenv(f"{_ENV_PREFIX}FLASK_HOST", "0.0.0.0")
64+
port = int(os.getenv(f"{_ENV_PREFIX}FLASK_PORT", "5000"))
65+
app.run(host=host, port=port, debug=False)

run_sojka_guardrail.sh

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/usr/bin/env bash
2+
# ------------------------------------------------------------------
3+
# Launch the NASK‑PIB Guardrail API using Gunicorn (2 workers)
4+
# ------------------------------------------------------------------
5+
# Required environment variables (can be overridden when invoking the script):
6+
# LLM_ROUTER_SOJKA_GUARD_FLASK_HOST – bind address (default: 0.0.0.0)
7+
# LLM_ROUTER_SOJKA_GUARD_FLASK_PORT – port (default: 5000)
8+
# LLM_ROUTER_SOJKA_GUARD_MODEL_PATH – model path / hub identifier
9+
# LLM_ROUTER_SOJKA_GUARD_DEVICE – device for the transformer pipeline
10+
# (-1 → CPU, 0/1 → GPU) (default: -1)
11+
# ---------------------------------------------------------------
12+
13+
# Set defaults if they are not already defined in the environment
14+
: "${LLM_ROUTER_SOJKA_GUARD_FLASK_HOST:=0.0.0.0}"
15+
: "${LLM_ROUTER_SOJKA_GUARD_FLASK_PORT:=5001}"
16+
: "${LLM_ROUTER_SOJKA_GUARD_MODEL_PATH:=speakleash/Bielik-Guard-0.1B-v1.0}"
17+
: "${LLM_ROUTER_SOJKA_GUARD_DEVICE:=0}"
18+
19+
# Export them so the Python process can read them
20+
export LLM_ROUTER_SOJKA_GUARD_FLASK_HOST
21+
export LLM_ROUTER_SOJKA_GUARD_FLASK_PORT
22+
export LLM_ROUTER_SOJKA_GUARD_MODEL_PATH
23+
export LLM_ROUTER_SOJKA_GUARD_DEVICE
24+
25+
# Show the configuration that will be used
26+
echo "Starting Sojka Guardrail API with Gunicorn (2 workers):"
27+
echo " HOST = $LLM_ROUTER_SOJKA_GUARD_FLASK_HOST"
28+
echo " PORT = $LLM_ROUTER_SOJKA_GUARD_FLASK_PORT"
29+
echo " MODEL = $LLM_ROUTER_SOJKA_GUARD_MODEL_PATH"
30+
echo " DEVICE = $LLM_ROUTER_SOJKA_GUARD_DEVICE"
31+
echo
32+
33+
# ---------------------------------------------------------------
34+
# Run Gunicorn
35+
# -w 2 → 2 worker processes
36+
# -b host:port → bind address
37+
# guardrails.speakleash.sojka_guard_app → import the Flask app object
38+
# ---------------------------------------------------------------
39+
gunicorn -w 1 -b \
40+
"${LLM_ROUTER_SOJKA_GUARD_FLASK_HOST}:${LLM_ROUTER_SOJKA_GUARD_FLASK_PORT}" \
41+
llm_router_services.guardrails.speakleash.sojka_guard_app:app

0 commit comments

Comments
 (0)