Skip to Content
ContributePolyphemusOverview

Polyphemus (Development)

Polyphemus is the model-serving service used for adversarial generation workloads. It proxies generation requests to Vertex AI and exposes authenticated REST endpoints.

Runtime and deployment notes

  • Runtime baseline: Python >=3.12
  • Router module: apps/polyphemus/src/rhesis/polyphemus/routers/services.py
  • Request schemas: apps/polyphemus/src/rhesis/polyphemus/schemas/schemas.py
  • Docker image: API-only service image. PyTorch is not bundled in the Polyphemus container; model weights and serving runtime live behind Vertex AI.
  • Dependency shape: Polyphemus depends on backend core only. The SDK, Penelope, Garak, and model-serving stacks live outside the runtime image.

Building the Docker image

Build the Polyphemus image from the repository root. The Dockerfile depends on monorepo paths outside apps/polyphemus, so using apps/polyphemus as the build context will fail.

terminal
# From repository root
docker build -t polyphemus:latest -f apps/polyphemus/Dockerfile .

The image uses a two-stage build: the builder installs dependencies with uv sync --no-dev, and the runtime stage copies only the API service and required backend package files. The builder copies uv and uvx from mirror.gcr.io/astral/uv:0.11.19 for reproducible and reliable Docker builds.

Keep the uv tag and registry mirror aligned with the Dockerfile when upgrading service image builds.

API endpoints

Polyphemus exposes two primary generation endpoints:

EndpointPurposeAuth
POST /generateSingle generation requestBearer token required
POST /generate_batchBatch generation for multiple requestsBearer token required

/generate_batch accepts up to 50 items per call (MAX_BATCH_SIZE).

Request fields

Both endpoints use the same GenerateRequest shape. Batch requests wrap multiple GenerateRequest objects under requests.

FieldTypeDefaultDescription
messagesMessage[]RequiredChat messages with role and content
modelstring | nullpolyphemus-defaultPublic alias resolved by the service
temperaturefloat | null0.7Values less than or equal to 0 are reset to 0.7
max_tokensint | nullNot sentPassed to vLLM only when provided
top_pfloat | null1.0Must be greater than 0 and less than or equal to 1
top_kint | nullNot sentNegative values are ignored
json_schemaobject | nullNot sentEnables structured output and test-generation hardening

The service retries transient Vertex AI failures (429, 500, 502, 503, 504) up to three attempts with exponential backoff.

Environment configuration

Polyphemus reads Vertex AI target configuration from environment variables:

VariableRequiredDescription
POLYPHEMUS_ENDPOINT_IDYesVertex AI endpoint identifier
POLYPHEMUS_PROJECT_IDYesGCP project ID for endpoint invocation
POLYPHEMUS_LOCATIONNoVertex AI region (defaults to us-central1)
POLYPHEMUS_DEFAULT_MODELFor default aliasInternal Vertex/vLLM model backing the polyphemus-default alias
POLYPHEMUS_OPUS_MODELFor opus aliasInternal Vertex/vLLM model backing the polyphemus-opus alias
POLYPHEMUS_BATCH_CONCURRENCYNoMaximum concurrent Vertex calls per batch request (defaults to 10)
VLLM_LOGGING_LEVELNovLLM container log verbosity for Vertex serving (for example, DEBUG, INFO)

If required variables are missing, the service returns HTTP 400 with configuration error details.

Authentication and rate limits

Polyphemus accepts two Bearer-token formats:

Token typeFormatTypical caller
Rhesis API tokenrh-*SDK users, scripts, and notebooks
Delegation JWTJWTBackend service-to-service calls

API tokens are validated through the backend token store and require an active, verified user. Delegation JWTs are validated by the Polyphemus delegation-token validator. Rate limiting uses the authenticated user identity when available.

Batch rate limiting counts the HTTP request, not every item inside requests.

Deployment region variable mapping (v0.2.8+)

Region configuration uses two separate variables depending on context:

ContextVariableSourceWhere it is consumed
GitHub Actions CI/CD workflowREGIONsecrets.REGION (falls back to us-central1).github/workflows/polyphemus.yml
Running Polyphemus servicePOLYPHEMUS_LOCATIONSet to $REGION by the CI workflowapps/polyphemus/src/rhesis/polyphemus/routers/services.py
Vertex model deployment scriptGCP_REGIONSet directly in the local environment (not mapped from REGION)apps/polyphemus/model_deployment/config.py

The workflow maps REGIONPOLYPHEMUS_LOCATION automatically for service deployments. The model deployment script reads GCP_REGION independently; when running it locally you must export GCP_REGION yourself (see apps/polyphemus/model_deployment/.env.example).

vLLM logging level (v0.2.9+)

When deploying Polyphemus to Vertex AI, you can control serving container verbosity with VLLM_LOGGING_LEVEL.

deploy-polyphemus.sh
export VLLM_LOGGING_LEVEL=DEBUG
python apps/polyphemus/model_deployment/deploy.py --skip-existing

If set, deployment injects VLLM_LOGGING_LEVEL into the serving container environment.

Polyphemus deployment separates the lightweight API container from the Vertex AI serving container. Configure vLLM logging on the Vertex deployment, not by installing PyTorch or model runtime dependencies into the Polyphemus API image.

Request hardening and adversarial primer

Polyphemus enforces adversarial behavior on the server side before forwarding a request to Vertex AI. This keeps SDK, platform, and direct API callers aligned even if they assemble messages differently.

The hardening path is:

  1. The service validates that at least one non-system message has content.
  2. It resolves the public model alias (polyphemus-default or polyphemus-opus).
  3. It injects an adversarial primer into the system message if that primer is not already present.
  4. It builds the Vertex AI rawPredict request body.

Structured-output requests and direct conversation requests are handled slightly differently:

Request shapeSystem-message handlingUser-message handling
json_schema presentPrimer is inserted after /no_think and before schema instructionsUser content receives the adversarial attack prefix
No json_schemaConversational primer is prepended to the system messageUser content is unchanged
No system messageA new system message is insertedSame behavior as above for the request shape

The injection is idempotent: if the primer text is already present, Polyphemus does not add it again.

Product callers do not need to add their own adversarial primer. Add domain-specific instructions in the normal system prompt and let the service enforce the shared hardening layer.

Batch request and response format

generate_batch_request.json
{
  "requests": [
    {
      "messages": [
        {
          "role": "user",
          "content": "Summarize this policy document."
        }
      ],
      "temperature": 0.7,
      "max_tokens": 1024
    },
    {
      "messages": [
        {
          "role": "user",
          "content": "Extract key risks from this response."
        }
      ],
      "temperature": 0.2
    }
  ]
}
generate_batch_response.json
{
  "responses": [
    {
      "choices": [
        {
          "message": {
            "content": "..."
          }
        }
      ],
      "model": "vertex_ai/model",
      "usage": {
        "prompt_tokens": 120,
        "completion_tokens": 85
      }
    },
    {
      "error": "Generation timeout"
    }
  ]
}

Batch execution is partially tolerant: one failed item does not fail the whole HTTP request. The failed item returns an error field, and the service logs the exception at error level with stack trace details for operators.

Batch concurrency is capped by POLYPHEMUS_BATCH_CONCURRENCY to avoid overwhelming the shared HTTP pool or Vertex quota. The default is 10.