Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions api/v1/aiplatform_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,8 @@ type VectorDBStorageSpec struct {

// FeatureSpec defines the features to enable in the AIPlatform
type FeatureSpec struct {
// Name of the feature, e.g. "saia" or "seca"
// +kubebuilder:validation:Enum=saia;seca
// Name of the feature, e.g. "saia", "seca" or "slim"
// +kubebuilder:validation:Enum=saia;seca;slim
Name string `json:"name,omitempty"`
// ServiceAccountName is the name of the service account to use for the feature
ServiceAccountName string `json:"serviceAccountName,omitempty"`
Expand Down
97 changes: 97 additions & 0 deletions config/configs/applications.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ applications:
SERVICE_NAME: "ai_platform_models"
SKIP_VERIFICATION: "true"
USE_SYSTEM_PERMISSIONS: "true"
{{- if .Replicas.Gemma431bIt }}
- args:
application_name: Gemma431bIt
deployment_configs:
Expand Down Expand Up @@ -170,6 +171,8 @@ applications:
# Airgap k0s has no Redis; cloud sets this to "False" and wires
# RESPONSES_REDIS_ADDRESS to its in-namespace Redis StatefulSet.
DISABLE_RESPONSES_API_REDIS: "True"
{{- end }}
{{- if .Replicas.GptOss20b }}
- args:
application_name: GptOss20b
deployment_configs:
Expand Down Expand Up @@ -274,6 +277,8 @@ applications:
# See Gemma431bIt above for rationale. Must be "True" in airgap (no
# Redis) so vLLM uses NoOpOpenAIServingResponses.
DISABLE_RESPONSES_API_REDIS: "True"
{{- end }}
{{- if .Replicas.UaeLarge }}
- args:
application_name: UaeLarge
deployment_configs:
Expand Down Expand Up @@ -352,6 +357,8 @@ applications:
SERVICE_NAME: "ai_platform_models"
SKIP_VERIFICATION: "true"
USE_SYSTEM_PERMISSIONS: "true"
{{- end }}
{{- if .Replicas.AllMinilmL6V2 }}
- args:
application_name: AllMinilmL6V2
deployment_configs:
Expand Down Expand Up @@ -424,6 +431,8 @@ applications:
SERVICE_NAME: "ai_platform_models"
SKIP_VERIFICATION: "true"
USE_SYSTEM_PERMISSIONS: "true"
{{- end }}
{{- if .Replicas.BiEncoder }}
- args:
application_name: BiEncoder
deployment_configs:
Expand Down Expand Up @@ -493,6 +502,8 @@ applications:
SERVICE_NAME: "ai_platform_models"
SKIP_VERIFICATION: "true"
USE_SYSTEM_PERMISSIONS: "true"
{{- end }}
{{- if .Replicas.MbartTranslator }}
- args:
application_name: MbartTranslator
custom_deployment_import_path: mbart_translator:MbartTranslatorDeployment
Expand Down Expand Up @@ -553,6 +564,8 @@ applications:
SERVICE_NAME: "ai_platform_models"
SKIP_VERIFICATION: "true"
USE_SYSTEM_PERMISSIONS: "true"
{{- end }}
{{- if .Replicas.XlmRobertaLanguageClassifier }}
- args:
application_name: XlmRobertaLanguageClassifier
deployment_configs:
Expand Down Expand Up @@ -631,6 +644,7 @@ applications:
SERVICE_NAME: "ai_platform_models"
SKIP_VERIFICATION: "true"
USE_SYSTEM_PERMISSIONS: "true"
{{- end }}
- args:
application_name: PromptInjectionTfidf
custom_deployment_import_path: prompt_injection_tfidf:PromptInjectionTfidfDeployment
Expand Down Expand Up @@ -670,6 +684,84 @@ applications:
SERVICE_NAME: "ai_platform_models"
SKIP_VERIFICATION: "true"
USE_SYSTEM_PERMISSIONS: "true"
{{- if .Replicas.FmTimeseries }}
# FmTimeseries is a slim-feature model (see config/configs/features/slim.yaml).
# .Replicas.FmTimeseries is only populated when the "slim" feature is enabled,
# so this whole application is rendered only then — with saia alone it would
# otherwise emit "<no value>" for the replica counts and break the serve config.
- args:
application_name: FmTimeseries
# Cisco Time Series Model (CTSM) — a 250M-param decoder-only time-series
# forecaster served as a custom PyTorch deployment (NOT vLLM), so it has
# no engine_args / tensor_parallel_size / gpu_memory_utilization. It shares
# a GPU (num_gpus: 0.1). Weights are staged from HuggingFace
# (cisco-ai/cisco-time-series-model-1.0) to model_artifacts/fm_timeseries;
# CHECKPOINT_FILE names the checkpoint inside that prefix.
custom_deployment_import_path: fm_timeseries.main:FMTimeseriesDeployment
deployment_configs:
FMTimeseriesDeployment:
options:
autoscaling_config:
max_replicas: {{.Replicas.FmTimeseries}}
min_replicas: {{.Replicas.FmTimeseries}}
ray_actor_options:
num_gpus: 0.1
deployment_type: custom_deployment
model_definition:
model_config:
num_layers: 25
model_id: fm_timeseries
model_loader:
blob_storage:
# Only the checkpoint is needed — CiscoTsmMR reads its model config
# from inside torch_model.pt (loaded_checkpoint["config"]), not from
# config.json. artifacts_list restricts the download to exactly these
# files under blob_prefix, so this must name a file that exists in
# the bucket (verified: model_artifacts/fm_timeseries/torch_model.pt).
artifacts_list:
- torch_model.pt
blob_prefix: model_artifacts/fm_timeseries
name: FmTimeseries
import_path: main:create_serve_app
route_prefix: /fm_timeseries
runtime_env:
working_dir: "file:///home/ray/ray/applications/generic_application.zip"
env_vars:
API_VERSION: "v1"
APPLICATION_NAME: fm_timeseries
# Checkpoint filename inside blob_prefix. The public HF repo ships
# torch_model.pt (the deployment builds the path as
# <local_dir>/CHECKPOINT_FILE), so this must match a staged artifact.
CHECKPOINT_FILE: torch_model.pt
ARTIFACTS_S3_BUCKET: "{{.ArtifactBucketName}}"
S3_BUCKET: "{{.ArtifactBucketName}}"
ARTIFACTS_PROVIDER: "{{.ArtifactsProvider}}"
CLOUD_PROVIDER: "{{.CloudProvider}}"
S3COMPAT_OBJECT_STORE_ENDPOINT_URL: "{{.S3CompatObjectStoreEndpointUrl}}"
S3COMPAT_OBJECT_STORE_ACCESS_KEY: "{{.S3CompatObjectStoreAccessKey}}"
S3COMPAT_OBJECT_STORE_SECRET_KEY: "{{.S3CompatObjectStoreSecretKey}}"
# AWS / boto3 standard credential names — populated whenever the
# operator can load credentials from spec.objectStorage.secretRef. For
# CLOUD_PROVIDER=aws these are the values boto3 reads (the S3COMPAT_*
# names above are only consumed by the s3compat shim). Both code paths
# share the same source-of-truth Secret keys (s3_access_key /
# s3_secret_key) so emitting both pairs is safe — each provider only
# reads its own. AWS_REGION lets boto3 resolve the default regional S3
# endpoint when no AWS_ENDPOINT_URL is set; required for any AWS S3
# bucket outside us-east-1 to avoid PermanentRedirect on the first call.
AWS_ACCESS_KEY_ID: "{{.S3CompatObjectStoreAccessKey}}"
AWS_SECRET_ACCESS_KEY: "{{.S3CompatObjectStoreSecretKey}}"
AWS_REGION: "{{.Region}}"
AWS_DEFAULT_REGION: "{{.Region}}"
ENABLE_AUTHN: "false"
ENABLE_AUTHZ: "false"
SERVICE_EXTERNAL_NAME: "ai-platform-models"
SERVICE_INTERNAL_NAME: "ai_platform_models"
SERVICE_NAME: "ai_platform_models"
SKIP_VERIFICATION: "true"
USE_SYSTEM_PERMISSIONS: "true"
{{- end }}
{{- if .Replicas.CrossEncoder }}
- args:
application_name: CrossEncoder
deployment_configs:
Expand Down Expand Up @@ -743,6 +835,8 @@ applications:
SERVICE_NAME: "ai_platform_models"
SKIP_VERIFICATION: "true"
USE_SYSTEM_PERMISSIONS: "true"
{{- end }}
{{- if .Replicas.E5LanguageClassifier }}
- args:
application_name: E5LanguageClassifier
deployment_configs:
Expand Down Expand Up @@ -821,6 +915,8 @@ applications:
SERVICE_NAME: "ai_platform_models"
SKIP_VERIFICATION: "true"
USE_SYSTEM_PERMISSIONS: "true"
{{- end }}
{{- if .Replicas.PromptInjectionCrossEncoder }}
- args:
application_name: PromptInjectionCrossEncoder
deployment_configs:
Expand Down Expand Up @@ -886,6 +982,7 @@ applications:
SERVICE_NAME: "ai_platform_models"
SKIP_VERIFICATION: "true"
USE_SYSTEM_PERMISSIONS: "true"
{{- end }}
- args:
application_name: PromptInjectionClassifier
deployment_type: classification_model_deployment
Expand Down
11 changes: 11 additions & 0 deletions config/configs/features/slim.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
applicationScale:
FmTimeseries: 1
Comment thread
spl-arif marked this conversation as resolved.
instanceScale:
L40S:
l40s-1-gpu: 1
H100:
h100-1-gpu: 1
H100_NVL:
h100-nvl-1-gpu: 1
RTX_PRO_6000_BLACKWELL:
rtx-pro-6000-blackwell-1-gpu: 1
3 changes: 2 additions & 1 deletion config/crd/bases/ai.splunk.com_aiplatforms.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1054,10 +1054,11 @@ spec:
description: FeatureSpec defines the features to enable in the AIPlatform
properties:
name:
description: Name of the feature, e.g. "saia" or "seca"
description: Name of the feature, e.g. "saia", "seca" or "slim"
enum:
- saia
- seca
- slim
type: string
scaleFactor:
description: ScaleFactor is the desired fixed number of replicas
Expand Down
3 changes: 2 additions & 1 deletion config/crd/bases/ai.splunk.com_aiservices.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1045,10 +1045,11 @@ spec:
description: Feature defines the features to be enabled for the AIService
properties:
name:
description: Name of the feature, e.g. "saia" or "seca"
description: Name of the feature, e.g. "saia", "seca" or "slim"
enum:
- saia
- seca
- slim
type: string
scaleFactor:
description: ScaleFactor is the desired fixed number of replicas
Expand Down
1 change: 1 addition & 0 deletions config/manager/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ patches:
\ - name: RELATED_IMAGE_RAY_WORKER\n value: \"667741767953.dkr.ecr.us-west-2.amazonaws.com/ml-platform/ray/ray-worker-gpu:build-17\"\n
\ - name: RELATED_IMAGE_WEAVIATE\n value: \"semitechnologies/weaviate:stable-v1.28-007846a\"\n
\ - name: RELATED_IMAGE_SAIA_API\n value: \"667741767953.dkr.ecr.us-west-2.amazonaws.com/ml-platform/saia/saia-api:build-1\"\n
\ - name: RELATED_IMAGE_SLIM_API\n value: \"667741767953.dkr.ecr.us-west-2.amazonaws.com/ml-platform/slim/slim-api:build-1\"\n
\ - name: RELATED_IMAGE_POST_INSTALL_HOOK\n value: \"667741767953.dkr.ecr.us-west-2.amazonaws.com/ml-platform/saia/saia-data-loader:build-1\"\n
\ - name: RELATED_IMAGE_FLUENT_BIT\n value: \"fluent/fluent-bit:1.9.6\"\n -
name: RELATED_IMAGE_OTEL_COLLECTOR\n value: \"otel/opentelemetry-collector-contrib:0.122.1\"\n
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1054,10 +1054,11 @@ spec:
description: FeatureSpec defines the features to enable in the AIPlatform
properties:
name:
description: Name of the feature, e.g. "saia" or "seca"
description: Name of the feature, e.g. "saia", "seca" or "slim"
enum:
- saia
- seca
- slim
type: string
scaleFactor:
description: ScaleFactor is the desired fixed number of replicas
Expand Down
11 changes: 10 additions & 1 deletion helm-chart/splunk-ai-operator/crds/ai.splunk.com_aiservices.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1019,6 +1019,14 @@ spec:
type: string
type: object
x-kubernetes-map-type: atomic
aiPlatformScheme:
default: http
description: AIPlatformScheme specifies the URL scheme for the AI
Platform service ("http" or "https")
enum:
- http
- https
type: string
aiPlatformUrl:
description: AIPlatformUrl specifies the URL for the AI Platform (deprecated,
use AIPlatformRef)
Expand All @@ -1037,10 +1045,11 @@ spec:
description: Feature defines the features to be enabled for the AIService
properties:
name:
description: Name of the feature, e.g. "saia" or "seca"
description: Name of the feature, e.g. "saia", "seca" or "slim"
enum:
- saia
- seca
- slim
type: string
scaleFactor:
description: ScaleFactor is the desired fixed number of replicas
Expand Down
2 changes: 2 additions & 0 deletions helm-chart/splunk-ai-operator/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ spec:
value: {{ .Values.saiaApiImage }}
- name: RELATED_IMAGE_SAIA_API_V2
value: {{ .Values.saiaApiV2Image }}
- name: RELATED_IMAGE_SLIM_API
value: {{ .Values.slimApiImage }}
- name: RELATED_IMAGE_POST_INSTALL_HOOK
value: {{ .Values.saiaSchemaImage }}
- name: RELATED_IMAGE_OTEL_COLLECTOR
Expand Down
3 changes: 3 additions & 0 deletions helm-chart/splunk-ai-operator/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ saiaApiImage: "docker.io/splunk/saia-api:1.1.0"
saiaApiV2Image: "docker.io/splunk/saia-api-v2:1.1.0"
saiaSchemaImage: "docker.io/splunk/saia-data-loader:1.1.0"

# SLIM API image
slimApiImage: "docker.io/splunk/slim-api:1.0.0"

# OpenTelemetry Collector sidecar image
otelCollectorImage: "docker.io/otel/opentelemetry-collector-contrib:0.122.1"

Expand Down
2 changes: 1 addition & 1 deletion helm-chart/splunk-ai-platform/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ serviceAccountName: ""
gpuInstanceType: "g6.24xlarge"

# List of defined features to enable in the AI platform
# Options include: saia, seca
# Options include: saia, seca, slim
features: []
# Example:
# - name: "saia"
Expand Down
2 changes: 2 additions & 0 deletions pkg/ai/features/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import (
"github.com/splunk/splunk-ai-operator/pkg/ai/features/common"
"github.com/splunk/splunk-ai-operator/pkg/ai/features/saia"
"github.com/splunk/splunk-ai-operator/pkg/ai/features/seca"
"github.com/splunk/splunk-ai-operator/pkg/ai/features/slim"
)

var FeatureFactories = map[string]common.FeatureFactory{
"saia": &saia.SaiaFactory{},
"seca": &seca.SecaFactory{},
"slim": &slim.SlimFactory{},
}
21 changes: 21 additions & 0 deletions pkg/ai/features/slim/factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package slim

import (
"context"

aiv1 "github.com/splunk/splunk-ai-operator/api/v1"
"github.com/splunk/splunk-ai-operator/pkg/ai/features/common"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/tools/record"
"sigs.k8s.io/controller-runtime/pkg/client"
)

type SlimFactory struct{}

func (f *SlimFactory) New(ctx context.Context, c client.Client, scheme *runtime.Scheme, ai *aiv1.AIService, recorder record.EventRecorder) (common.FeatureHandler, error) {
return &SlimReconciler{
Client: c,
Scheme: scheme,
Recorder: recorder,
}, nil
}
44 changes: 44 additions & 0 deletions pkg/ai/features/slim/factory_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package slim

import (
"context"
"testing"

aiv1 "github.com/splunk/splunk-ai-operator/api/v1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/tools/record"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
)

func TestSlimFactory_New(t *testing.T) {
s := runtime.NewScheme()
_ = scheme.AddToScheme(s)
_ = aiv1.AddToScheme(s)

factory := &SlimFactory{}
fakeClient := fake.NewClientBuilder().WithScheme(s).Build()
recorder := record.NewFakeRecorder(10)

aiService := &aiv1.AIService{
ObjectMeta: metav1.ObjectMeta{
Name: "test-service",
Namespace: "default",
},
}

handler, err := factory.New(context.Background(), fakeClient, s, aiService, recorder)

require.NoError(t, err)
require.NotNil(t, handler)

// Verify it returns a SlimReconciler
reconciler, ok := handler.(*SlimReconciler)
assert.True(t, ok, "Expected handler to be *SlimReconciler")
assert.NotNil(t, reconciler.Client)
assert.NotNil(t, reconciler.Scheme)
assert.NotNil(t, reconciler.Recorder)
}
Loading
Loading