@@ -19,7 +19,9 @@ package modelrouter
19
19
import (
20
20
"context"
21
21
"fmt"
22
+ "slices"
22
23
"strconv"
24
+ "strings"
23
25
24
26
appsv1 "k8s.io/api/apps/v1"
25
27
apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -41,9 +43,12 @@ import (
41
43
42
44
const (
43
45
// TODO (varun): cleanup model related identifiers and establish common consensus
44
- modelHeaderIdentifier = "model"
45
- modelIdentifier = "model.aibrix.ai/name"
46
- modelPortIdentifier = "model.aibrix.ai/port"
46
+ modelHeaderIdentifier = "model"
47
+ modelIdentifier = "model.aibrix.ai/name"
48
+ modelPortIdentifier = "model.aibrix.ai/port"
49
+ modelSupportedRoutesIdentifier = "model.aibrix.ai/supported-routes"
50
+ modelEmbeddingsRoute = "embeddings"
51
+ modelChatCompletionsRoute = "chat-completions"
47
52
// TODO (varun): parameterize it or dynamically resolve it
48
53
aibrixEnvoyGateway = "aibrix-eg"
49
54
aibrixEnvoyGatewayNamespace = "aibrix-system"
@@ -107,6 +112,42 @@ func Add(mgr manager.Manager, runtimeConfig config.RuntimeConfig) error {
107
112
return err
108
113
}
109
114
115
+ func getSupportedRoutesMatchFromLabelsOrDefault (labels map [string ]string , modelHeaderMatch gatewayv1.HTTPHeaderMatch ) []gatewayv1.HTTPRouteMatch {
116
+ nameToRoutePathPrefix := map [string ][]string {
117
+ modelEmbeddingsRoute : {"/v1/embeddings" },
118
+ modelChatCompletionsRoute : {"/v1/completions" , "/v1/chat/completions" },
119
+ }
120
+
121
+ var pathPrefixes []string
122
+ if routesLabelValue , ok := labels [modelSupportedRoutesIdentifier ]; ok {
123
+ routes := strings .Split (routesLabelValue , "," )
124
+ for k , route := range nameToRoutePathPrefix {
125
+ if slices .Contains (routes , k ) {
126
+ pathPrefixes = append (pathPrefixes , route ... )
127
+ }
128
+ }
129
+ }
130
+
131
+ // completions and chat completions routes by default
132
+ if len (pathPrefixes ) == 0 {
133
+ pathPrefixes = append (pathPrefixes , nameToRoutePathPrefix [modelChatCompletionsRoute ]... )
134
+ }
135
+
136
+ var routesmatch []gatewayv1.HTTPRouteMatch
137
+ for _ , path := range pathPrefixes {
138
+ routesmatch = append (routesmatch , gatewayv1.HTTPRouteMatch {
139
+ Path : & gatewayv1.HTTPPathMatch {
140
+ Type : ptr .To (gatewayv1 .PathMatchPathPrefix ),
141
+ Value : ptr .To (path ),
142
+ },
143
+ Headers : []gatewayv1.HTTPHeaderMatch {
144
+ modelHeaderMatch ,
145
+ },
146
+ })
147
+ }
148
+ return routesmatch
149
+ }
150
+
110
151
type ModelRouter struct {
111
152
client.Client
112
153
Scheme * runtime.Scheme
@@ -192,6 +233,8 @@ func (m *ModelRouter) createHTTPRoute(namespace string, labels map[string]string
192
233
Value : modelName ,
193
234
}
194
235
236
+ httpRoutesMatch := getSupportedRoutesMatchFromLabelsOrDefault (labels , modelHeaderMatch )
237
+
195
238
httpRoute := gatewayv1.HTTPRoute {
196
239
ObjectMeta : metav1.ObjectMeta {
197
240
Name : fmt .Sprintf ("%s-router" , modelName ),
@@ -208,35 +251,7 @@ func (m *ModelRouter) createHTTPRoute(namespace string, labels map[string]string
208
251
},
209
252
Rules : []gatewayv1.HTTPRouteRule {
210
253
{
211
- Matches : []gatewayv1.HTTPRouteMatch {
212
- {
213
- Path : & gatewayv1.HTTPPathMatch {
214
- Type : ptr .To (gatewayv1 .PathMatchPathPrefix ),
215
- Value : ptr .To ("/v1/completions" ),
216
- },
217
- Headers : []gatewayv1.HTTPHeaderMatch {
218
- modelHeaderMatch ,
219
- },
220
- },
221
- {
222
- Path : & gatewayv1.HTTPPathMatch {
223
- Type : ptr .To (gatewayv1 .PathMatchPathPrefix ),
224
- Value : ptr .To ("/v1/chat/completions" ),
225
- },
226
- Headers : []gatewayv1.HTTPHeaderMatch {
227
- modelHeaderMatch ,
228
- },
229
- },
230
- {
231
- Path : & gatewayv1.HTTPPathMatch {
232
- Type : ptr .To (gatewayv1 .PathMatchPathPrefix ),
233
- Value : ptr .To ("/v1/embeddings" ),
234
- },
235
- Headers : []gatewayv1.HTTPHeaderMatch {
236
- modelHeaderMatch ,
237
- },
238
- },
239
- },
254
+ Matches : httpRoutesMatch ,
240
255
BackendRefs : []gatewayv1.HTTPBackendRef {
241
256
{
242
257
BackendRef : gatewayv1.BackendRef {
0 commit comments