Skip to content

Commit c04d087

Browse files
committed
Use llamastack vector database prototype
1 parent e49e5a1 commit c04d087

5 files changed

Lines changed: 175 additions & 28 deletions

File tree

internal/controller/constants.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ const (
3939
OpenStackLightspeedAppServerNetworkPolicyName = "lightspeed-app-server"
4040
OpenStackLightspeedCertsSecretName = "lightspeed-tls"
4141
OpenStackLightspeedDefaultProvider = "openstack-lightspeed-provider"
42-
OpenStackLightspeedVectorDBPath = "/rag/vector_db/os_product_docs"
42+
RAGInitCopySubPath = "rag-0"
43+
RAGInitCopyDestinationPath = "/rag-data/rag-0"
44+
RAGRuntimeContentPath = "/rag/rag-0"
45+
OpenStackLightspeedVectorDBPath = RAGRuntimeContentPath + "/vector_db/os_product_docs"
4346

4447
ServingCertSecretAnnotationKey = "service.beta.openshift.io/serving-cert-secret-name"
4548

@@ -93,8 +96,13 @@ const (
9396
LCoreConfigFilename = "lightspeed-stack.yaml"
9497
LCoreConfigMapResourceVersionAnnotation = "ols.openshift.io/lcore-configmap-version"
9598
LlamaStackConfigMapResourceVersionAnnotation = "ols.openshift.io/llamastack-configmap-version"
99+
RAGImageAnnotation = "ols.openshift.io/rag-image"
100+
ActiveOCPRAGVersionAnnotation = "ols.openshift.io/active-ocp-rag-version"
96101
LCoreUserDataMountPath = "/tmp/data"
97102
ForceReloadAnnotationKey = "ols.openshift.io/force-reload"
103+
RAGVolumeName = "rag-data"
104+
RAGVolumeMountPath = "/rag"
105+
RAGInitVolumeMountPath = "/rag-data"
98106

99107
// Data Exporter
100108
ExporterConfigVolumeName = "exporter-config"

internal/controller/lcore_config.go

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package controller
1919
import (
2020
_ "embed"
2121
"fmt"
22+
"os"
2223

2324
common_helper "github.com/openstack-k8s-operators/lib-common/modules/common/helper"
2425
apiv1beta1 "github.com/openstack-lightspeed/operator/api/v1beta1"
@@ -197,8 +198,48 @@ func buildLCoreConversationCacheConfig(h *common_helper.Helper, _ *apiv1beta1.Op
197198
}
198199
}
199200

200-
// buildLCoreConfigYAML assembles the complete Lightspeed Core Service configuration and converts to YAML.
201-
// NOTE: MCP servers, quota handlers, and tools approval features are disabled for OpenStack Lightspeed.
201+
func buildLCoreRAGConfig(instance *apiv1beta1.OpenStackLightspeed) map[string]interface{} {
202+
ragIDs := []interface{}{}
203+
for _, rag := range buildLCoreRAGConfigs(instance, instance.Status.ActiveOCPRAGVersion) {
204+
ragID := rag.IndexID
205+
if ragID == "" {
206+
ragID = "rag_" + sanitizeID(rag.Image)
207+
}
208+
ragIDs = append(ragIDs, ragID)
209+
}
210+
211+
return map[string]interface{}{
212+
"inline": []string{
213+
getVectorStoreID(),
214+
},
215+
// NOTE(lpiwowar): RAG will be enabled as a tool once the full migration
216+
// to lightspeed-stack is complete and feature parity has been achieved.
217+
// "tool": ragIDs,
218+
}
219+
}
220+
221+
func buildLCoreBYOKRAGConfig(instance *apiv1beta1.OpenStackLightspeed) []interface{} {
222+
byokRAG := []interface{}{}
223+
for _, rag := range buildLCoreRAGConfigs(instance, instance.Status.ActiveOCPRAGVersion) {
224+
vectorDBID := rag.IndexID
225+
if vectorDBID == "" {
226+
vectorDBID = "rag_" + sanitizeID(rag.Image)
227+
}
228+
229+
byokRAG = append(byokRAG, map[string]interface{}{
230+
"rag_id": getVectorStoreID(),
231+
"rag_type": "inline::faiss",
232+
"embedding_model": "sentence-transformers/all-mpnet-base-v2",
233+
"embedding_dimension": 768,
234+
"vector_db_id": getVectorStoreID(),
235+
"db_path": rag.IndexPath,
236+
"score_multiplier": 1.0,
237+
})
238+
}
239+
240+
return byokRAG
241+
}
242+
202243
func buildLCoreConfigYAML(h *common_helper.Helper, instance *apiv1beta1.OpenStackLightspeed) (string, error) {
203244
// Build the complete config as a map
204245
config := map[string]interface{}{
@@ -211,6 +252,8 @@ func buildLCoreConfigYAML(h *common_helper.Helper, instance *apiv1beta1.OpenStac
211252
"database": buildLCoreDatabaseConfig(h, instance),
212253
"customization": buildLCoreCustomizationConfig(),
213254
"conversation_cache": buildLCoreConversationCacheConfig(h, instance),
255+
"byok_rag": buildLCoreBYOKRAGConfig(instance),
256+
"rag": buildLCoreRAGConfig(instance),
214257
}
215258

216259
// Convert to YAML
@@ -221,3 +264,11 @@ func buildLCoreConfigYAML(h *common_helper.Helper, instance *apiv1beta1.OpenStac
221264

222265
return string(yamlBytes), nil
223266
}
267+
268+
func getVectorStoreID() string {
269+
id := os.Getenv("VECTOR_STORE_ID")
270+
if id == "" {
271+
panic("VECTOR_STORE_ID environment variable is not set")
272+
}
273+
return id
274+
}

internal/controller/lcore_deployment.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ func buildLCorePodTemplateSpec(h *common_helper.Helper, ctx context.Context, ins
5454
llamaCacheMounts := []corev1.VolumeMount{}
5555
addLlamaCacheVolumesAndMounts(&volumes, &llamaCacheMounts)
5656

57+
// Shared RAG content volume
58+
ragMounts := []corev1.VolumeMount{}
59+
addRAGVolumesAndMounts(&volumes, &ragMounts)
60+
5761
// Build env vars
5862
llamaEnvVars, err := buildLlamaStackEnvVars(h, ctx, instance)
5963
if err != nil {
@@ -65,6 +69,7 @@ func buildLCorePodTemplateSpec(h *common_helper.Helper, ctx context.Context, ins
6569
llamaStackMounts := []corev1.VolumeMount{llamaMount}
6670
llamaStackMounts = append(llamaStackMounts, sharedMounts...)
6771
llamaStackMounts = append(llamaStackMounts, llamaCacheMounts...)
72+
llamaStackMounts = append(llamaStackMounts, ragMounts...)
6873

6974
llamaStackContainer := corev1.Container{
7075
Name: "llama-stack",
@@ -112,6 +117,8 @@ func buildLCorePodTemplateSpec(h *common_helper.Helper, ctx context.Context, ins
112117
if err != nil {
113118
return corev1.PodTemplateSpec{}, err
114119
}
120+
annotations[RAGImageAnnotation] = instance.Spec.RAGImage
121+
annotations[ActiveOCPRAGVersionAnnotation] = instance.Status.ActiveOCPRAGVersion
115122

116123
return corev1.PodTemplateSpec{
117124
ObjectMeta: metav1.ObjectMeta{
@@ -120,6 +127,7 @@ func buildLCorePodTemplateSpec(h *common_helper.Helper, ctx context.Context, ins
120127
},
121128
Spec: corev1.PodSpec{
122129
ServiceAccountName: OpenStackLightspeedAppServerServiceAccountName,
130+
InitContainers: []corev1.Container{buildRAGInitContainer(instance)},
123131
Containers: containers,
124132
Volumes: volumes,
125133
},
@@ -248,6 +256,44 @@ func addLlamaCacheVolumesAndMounts(volumes *[]corev1.Volume, mounts *[]corev1.Vo
248256
})
249257
}
250258

259+
// addRAGVolumesAndMounts adds an emptyDir volume shared by init and app containers for RAG content.
260+
func addRAGVolumesAndMounts(volumes *[]corev1.Volume, mounts *[]corev1.VolumeMount) {
261+
*volumes = append(*volumes, corev1.Volume{
262+
Name: RAGVolumeName,
263+
VolumeSource: corev1.VolumeSource{
264+
EmptyDir: &corev1.EmptyDirVolumeSource{},
265+
},
266+
})
267+
*mounts = append(*mounts, corev1.VolumeMount{
268+
Name: RAGVolumeName,
269+
MountPath: RAGVolumeMountPath,
270+
})
271+
}
272+
273+
// buildRAGInitContainer returns an init container that copies vector DB content from the RAG image.
274+
func buildRAGInitContainer(instance *apiv1beta1.OpenStackLightspeed) corev1.Container {
275+
return corev1.Container{
276+
Name: "rag-init",
277+
Image: instance.Spec.RAGImage,
278+
ImagePullPolicy: corev1.PullIfNotPresent,
279+
Command: []string{
280+
"sh", "-c",
281+
fmt.Sprintf(
282+
"mkdir -p %s && cp -a %s/. %s",
283+
RAGInitCopyDestinationPath,
284+
"/rag",
285+
RAGInitCopyDestinationPath,
286+
),
287+
},
288+
VolumeMounts: []corev1.VolumeMount{
289+
{
290+
Name: RAGVolumeName,
291+
MountPath: RAGInitVolumeMountPath,
292+
},
293+
},
294+
}
295+
}
296+
251297
// addUserCAVolumesAndMounts adds user-provided additional CA certificate volume and mount
252298
// if instance.Spec.TLSCACertBundle is set.
253299
func addUserCAVolumesAndMounts(volumes *[]corev1.Volume, mounts *[]corev1.VolumeMount, instance *apiv1beta1.OpenStackLightspeed, volumeDefaultMode int32) {

internal/controller/llama_stack_config.go

Lines changed: 66 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,8 @@ func buildLlamaStackVectorDB(_ *common_helper.Helper, _ *apiv1beta1.OpenStackLig
226226
"table_name": "vector_store",
227227
},
228228
"persistence": map[string]interface{}{
229-
"backend": "kv_default",
230-
"namespace": "vector_persistence",
229+
"backend": "rag_backend",
230+
"namespace": "vector_io:faiss",
231231
},
232232
},
233233
},
@@ -270,6 +270,10 @@ func buildLlamaStackStorage(_ *common_helper.Helper, instance *apiv1beta1.OpenSt
270270
"ca_cert_path": "/etc/certs/postgres-ca/service-ca.crt",
271271
"gss_encmode": "disable",
272272
},
273+
"rag_backend": map[string]interface{}{
274+
"type": "kv_sqlite",
275+
"db_path": "/rag/rag-0/vector_db/os_product_docs/faiss_store.db",
276+
},
273277
}
274278

275279
// Map data stores to backends - all use SQL with table_name
@@ -294,37 +298,34 @@ func buildLlamaStackStorage(_ *common_helper.Helper, instance *apiv1beta1.OpenSt
294298
}
295299
}
296300

297-
func buildLlamaStackVectorDBs(_ *common_helper.Helper, instance *apiv1beta1.OpenStackLightspeed) []interface{} {
298-
vectorDBs := []interface{}{}
301+
func buildLlamaStackVectorStores(_ *common_helper.Helper, instance *apiv1beta1.OpenStackLightspeed) map[string]interface{} {
302+
var vectorDBs map[string]interface{}
299303

300304
// Use RAG configuration from instance if available
301305
rags := buildLCoreRAGConfigs(instance, instance.Status.ActiveOCPRAGVersion)
302306
if len(rags) > 0 {
303-
for _, rag := range rags {
304-
vectorDB := map[string]interface{}{
305-
"embedding_model": "sentence-transformers/all-mpnet-base-v2",
306-
"embedding_dimension": 768,
307-
"provider_id": "faiss",
308-
}
309-
310-
// Use IndexID if specified, otherwise generate a default
311-
if rag.IndexID != "" {
312-
vectorDB["vector_db_id"] = rag.IndexID
313-
} else {
314-
// Generate a simple ID from the image name
315-
vectorDB["vector_db_id"] = "rag_" + sanitizeID(rag.Image)
316-
}
307+
vectorDBs = map[string]interface{}{
308+
"default_embedding_model": map[string]interface{}{
309+
"provider_id": "sentence-transformers",
310+
// "model_id": "all-mpnet-base-v2",
311+
"model_id": "/rag/rag-0/embeddings_model",
312+
},
317313

318-
vectorDBs = append(vectorDBs, vectorDB)
314+
// "embedding_dimension": 768,
315+
"default_provider_id": "faiss",
316+
// "index_path": rag.IndexPath,
319317
}
318+
319+
vectorDBs["vector_store_id"] = getVectorStoreID()
320+
320321
} else {
321322
// Default fallback if no RAG configured
322-
vectorDBs = append(vectorDBs, map[string]interface{}{
323+
vectorDBs = map[string]interface{}{
323324
"vector_db_id": "my_knowledge_base",
324325
"embedding_model": "sentence-transformers/all-mpnet-base-v2",
325326
"embedding_dimension": 768,
326327
"provider_id": "faiss",
327-
})
328+
}
328329
}
329330

330331
return vectorDBs
@@ -337,7 +338,7 @@ func buildLlamaStackModels(_ *common_helper.Helper, instance *apiv1beta1.OpenSta
337338
"model_id": "sentence-transformers/all-mpnet-base-v2",
338339
"model_type": "embedding",
339340
"provider_id": "sentence-transformers",
340-
"provider_model_id": "sentence-transformers/all-mpnet-base-v2",
341+
"provider_model_id": "/rag/rag-0/embeddings_model",
341342
"metadata": map[string]interface{}{
342343
"embedding_dimension": 768,
343344
},
@@ -380,6 +381,47 @@ func buildLlamaStackToolGroups(_ *common_helper.Helper, _ *apiv1beta1.OpenStackL
380381
}
381382
}
382383

384+
func buildLlamaStackRegisteredResources(_ *common_helper.Helper, instance *apiv1beta1.OpenStackLightspeed) map[string]interface{} {
385+
return map[string]interface{}{
386+
"models": []interface{}{
387+
map[string]interface{}{
388+
"model_id": "sentence-transformers/all-mpnet-base-v2",
389+
"model_type": "embedding",
390+
// "provider_model_id": "all-mpnet-base-v2",
391+
"metadata": map[string]interface{}{
392+
"embedding_dimension": 768,
393+
},
394+
395+
"provider_id": "sentence-transformers",
396+
// "provider_model_id": "all-mpnet-base-v2",
397+
"provider_model_id": "/rag/rag-0/embeddings_model",
398+
},
399+
400+
map[string]interface{}{
401+
"model_id": instance.Spec.ModelName,
402+
"model_type": "llm",
403+
"provider_id": "openstack-lightspeed-provider",
404+
"provider_model_id": instance.Spec.ModelName,
405+
"metadata": map[string]interface{}{
406+
"max_tokens": 2048,
407+
},
408+
},
409+
},
410+
"vector_stores": []interface{}{
411+
map[string]interface{}{
412+
"vector_store_id": getVectorStoreID(),
413+
// "model_id": "sentence-transformers/all-mpnet-base-v2",
414+
"provider_id": "faiss",
415+
// "embedding_model": "all-mpnet-base-v2",
416+
// "embedding_model": "sentence-transformers/all-mpnet-base-v2",
417+
"embedding_model": "sentence-transformers//rag/rag-0/embeddings_model",
418+
"embedding_dimension": 768,
419+
// "provider_model_id": "/rag/rag-0/embeddings_model",
420+
},
421+
},
422+
}
423+
}
424+
383425
// buildLlamaStackYAML assembles the complete Llama Stack configuration and converts to YAML
384426
func buildLlamaStackYAML(h *common_helper.Helper, ctx context.Context, instance *apiv1beta1.OpenStackLightspeed) (string, error) {
385427
// Build the complete config as a map
@@ -400,12 +442,12 @@ func buildLlamaStackYAML(h *common_helper.Helper, ctx context.Context, instance
400442
"tool_runtime": buildLlamaStackToolRuntime(h, instance),
401443
"vector_io": buildLlamaStackVectorDB(h, instance),
402444
}
403-
404445
// Add top-level fields
405446
config["scoring_fns"] = []interface{}{}
406447
config["server"] = buildLlamaStackServerConfig(h, instance)
407448
config["storage"] = buildLlamaStackStorage(h, instance)
408-
config["vector_dbs"] = buildLlamaStackVectorDBs(h, instance)
449+
config["vector_stores"] = buildLlamaStackVectorStores(h, instance)
450+
config["registered_resources"] = buildLlamaStackRegisteredResources(h, instance)
409451
config["models"] = buildLlamaStackModels(h, instance)
410452
config["tool_groups"] = buildLlamaStackToolGroups(h, instance)
411453
config["telemetry"] = map[string]interface{}{

internal/controller/ocp_version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import (
3333

3434
const (
3535
// OpenStackLightspeedOCPVectorDBPath - base path for OCP vector databases
36-
OpenStackLightspeedOCPVectorDBPath = "/rag/ocp_vector_db/ocp"
36+
OpenStackLightspeedOCPVectorDBPath = RAGRuntimeContentPath + "/ocp_vector_db/ocp"
3737

3838
// OpenStackLightspeedOCPIndexPrefix - prefix for OCP index names
3939
OpenStackLightspeedOCPIndexPrefix = "ocp-product-docs"

0 commit comments

Comments
 (0)