From 6154ffd1bbd4d7651f5e5a5e0a37e06ebba1953b Mon Sep 17 00:00:00 2001 From: Dan Sun Date: Fri, 3 Jun 2022 19:42:30 -0400 Subject: [PATCH] Initial inference graph API implementation (#1910) * Add inference graph API Signed-off-by: Dan Sun * Implement inference graph API Signed-off-by: Dan Sun * add validation and splitter Signed-off-by: Dan Sun * Fix inference graph status Signed-off-by: Dan Sun * Refactor knative reconciler Signed-off-by: Dan Sun * Resolve service urls Signed-off-by: Dan Sun * Improve logging Signed-off-by: Dan Sun * add switch and root node configuration. Signed-off-by: Dan Sun * Update docs/samples/graph/README.md Signed-off-by: Dan Sun * Add inference router dockerfile Signed-off-by: Dan Sun * Fix comments and error handling Signed-off-by: Dan Sun * Updating single routerType to sequence for more flexisble composition Signed-off-by: Dan Sun * Some InferenceGraph code streamlining - Avoid unnecessary goroutine use - Avoid most unnecessary unmarshal+remarshals - Deduplicate logic between router types - Handle async errors in ensemble case - Don't require stepName to be set - Return http error response when applicable - Simplify pickupRoute func - Fix incorrect log parameter syntax - Add webhook validation for unique step names and inference targets Signed-off-by: Nick Hill Signed-off-by: Dan Sun * Fix inference graph spec Signed-off-by: Dan Sun * Add condition tests Signed-off-by: Dan Sun * Update graph doc Signed-off-by: Dan Sun * rename service to serviceName Signed-off-by: Dan Sun Co-authored-by: iamlovingit Co-authored-by: Nick Hill --- Makefile | 24 +- cmd/manager/main.go | 25 +- cmd/router/main.go | 206 +++++++++++ cmd/router/main_test.go | 347 ++++++++++++++++++ config/configmap/inferenceservice.yaml | 8 + config/crd/kustomization.yaml | 2 +- .../serving.kserve.io_inferencegraphs.yaml | 122 ++++++ config/default/webhookcainjection_patch.yaml | 9 + .../development/configmap/ko_resolve_router | 1 + config/rbac/role.yaml | 20 + config/webhook/manifests.yaml | 27 ++ docs/samples/graph/README.md | 217 +++++++++++ docs/samples/graph/ensemble.yaml | 30 ++ docs/samples/graph/ensembleNode.png | Bin 0 -> 57033 bytes docs/samples/graph/graph.png | Bin 0 -> 89854 bytes docs/samples/graph/sequence.yaml | 31 ++ docs/samples/graph/singleNode.png | Bin 0 -> 26360 bytes docs/samples/graph/splitter.yaml | 32 ++ docs/samples/graph/splitterNode.png | Bin 0 -> 57590 bytes docs/samples/graph/switch.yaml | 47 +++ docs/samples/graph/switchNode.png | Bin 0 -> 55530 bytes go.mod | 5 +- go.sum | 6 + hack/image_patch_dev.sh | 10 + hack/violation_exceptions.list | 1 + .../templates/webhookconfiguration.yaml | 27 ++ pkg/apis/serving/v1alpha1/inference_graph.go | 257 +++++++++++++ .../v1alpha1/inference_graph_validation.go | 174 +++++++++ pkg/apis/serving/v1alpha1/v1alpha1.go | 1 + .../serving/v1alpha1/zz_generated.deepcopy.go | 160 ++++++++ pkg/apis/serving/v1beta1/openapi_generated.go | 103 ++++++ pkg/apis/serving/v1beta1/swagger.json | 55 +++ .../v1alpha1/inferencegraph/controller.go | 224 +++++++++++ .../inferencegraph/knative_reconciler.go | 177 +++++++++ router.Dockerfile | 22 ++ .../serving.kserve.io_inferenceservices.yaml | 121 ++++++ 36 files changed, 2484 insertions(+), 7 deletions(-) create mode 100644 cmd/router/main.go create mode 100644 cmd/router/main_test.go create mode 100644 config/crd/serving.kserve.io_inferencegraphs.yaml create mode 100644 config/overlays/development/configmap/ko_resolve_router create mode 100644 docs/samples/graph/README.md create mode 100644 docs/samples/graph/ensemble.yaml create mode 100644 docs/samples/graph/ensembleNode.png create mode 100644 docs/samples/graph/graph.png create mode 100644 docs/samples/graph/sequence.yaml create mode 100644 docs/samples/graph/singleNode.png create mode 100644 docs/samples/graph/splitter.yaml create mode 100644 docs/samples/graph/splitterNode.png create mode 100644 docs/samples/graph/switch.yaml create mode 100644 docs/samples/graph/switchNode.png create mode 100644 pkg/apis/serving/v1alpha1/inference_graph.go create mode 100644 pkg/apis/serving/v1alpha1/inference_graph_validation.go create mode 100644 pkg/controller/v1alpha1/inferencegraph/controller.go create mode 100644 pkg/controller/v1alpha1/inferencegraph/knative_reconciler.go create mode 100644 router.Dockerfile diff --git a/Makefile b/Makefile index 46ec457c210..562796fbe83 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ HAS_LINT := $(shell command -v golint;) # Image URL to use all building/pushing image targets IMG ?= kserve-controller:latest AGENT_IMG ?= agent:latest +ROUTER_IMG ?= router:latest SKLEARN_IMG ?= sklearnserver XGB_IMG ?= xgbserver LGB_IMG ?= lgbserver @@ -10,7 +11,7 @@ PYTORCH_IMG ?= pytorchserver PMML_IMG ?= pmmlserver PADDLE_IMG ?= paddleserver ALIBI_IMG ?= alibi-explainer -AIX_IMG ?= aix-explainer +AIX_IMG ?= aix-explainer STORAGE_INIT_IMG ?= storage-initializer CRD_OPTIONS ?= "crd:maxDescLen=0" KSERVE_ENABLE_SELF_SIGNED_CA ?= false @@ -23,7 +24,7 @@ KSERVE_CONTROLLER_MEMORY_LIMIT ?= 300Mi $(shell perl -pi -e 's/cpu:.*/cpu: $(KSERVE_CONTROLLER_CPU_LIMIT)/' config/default/manager_resources_patch.yaml) $(shell perl -pi -e 's/memory:.*/memory: $(KSERVE_CONTROLLER_MEMORY_LIMIT)/' config/default/manager_resources_patch.yaml) -all: test manager agent +all: test manager agent router # Run tests test: fmt vet manifests envtest @@ -37,6 +38,10 @@ manager: generate fmt vet lint agent: fmt vet go build -o bin/agent ./cmd/agent +# Build router binary +router: fmt vet + go build -o bin/router ./cmd/router + # Run against the configured Kubernetes cluster in ~/.kube/config run: generate fmt vet lint go run ./cmd/manager/main.go @@ -90,8 +95,8 @@ deploy-dev-alibi: docker-push-alibi ./hack/alibi_patch_dev.sh ${KO_DOCKER_REPO}/${ALIBI_IMG} kustomize build config/overlays/dev-image-config | kubectl apply -f - -deploy-dev-aix: docker-push-aix - ./hack/aix_patch_dev.sh ${KO_DOCKER_REPO}/${AIX_IMG} +deploy-dev-aix: docker-push-aix + ./hack/aix_patch_dev.sh ${KO_DOCKER_REPO}/${AIX_IMG} kustomize build config/overlays/dev-image-config | kubectl apply -f - deploy-dev-storageInitializer: docker-push-storageInitializer @@ -108,12 +113,14 @@ undeploy: kustomize build config/default | kubectl delete -f - kubectl delete validatingwebhookconfigurations.admissionregistration.k8s.io inferenceservice.serving.kserve.io kubectl delete validatingwebhookconfigurations.admissionregistration.k8s.io trainedmodel.serving.kserve.io + kubectl delete validatingwebhookconfigurations.admissionregistration.k8s.io inferencegraph.serving.kserve.io kubectl delete mutatingwebhookconfigurations.admissionregistration.k8s.io inferenceservice.serving.kserve.io undeploy-dev: kustomize build config/overlays/development | kubectl delete -f - kubectl delete validatingwebhookconfigurations.admissionregistration.k8s.io inferenceservice.serving.kserve.io kubectl delete validatingwebhookconfigurations.admissionregistration.k8s.io trainedmodel.serving.kserve.io + kubectl delete validatingwebhookconfigurations.admissionregistration.k8s.io inferencegraph.serving.kserve.io kubectl delete mutatingwebhookconfigurations.admissionregistration.k8s.io inferenceservice.serving.kserve.io # Generate manifests e.g. CRD, RBAC etc. @@ -130,6 +137,9 @@ manifests: controller-gen perl -pi -e 's/storedVersions: null/storedVersions: []/g' config/crd/serving.kserve.io_trainedmodels.yaml perl -pi -e 's/conditions: null/conditions: []/g' config/crd/serving.kserve.io_trainedmodels.yaml perl -pi -e 's/Any/string/g' config/crd/serving.kserve.io_trainedmodels.yaml + perl -pi -e 's/storedVersions: null/storedVersions: []/g' config/crd/serving.kserve.io_inferencegraphs.yaml + perl -pi -e 's/conditions: null/conditions: []/g' config/crd/serving.kserve.io_inferencegraphs.yaml + perl -pi -e 's/Any/string/g' config/crd/serving.kserve.io_inferencegraphs.yaml #remove the required property on framework as name field needs to be optional yq d -i config/crd/serving.kserve.io_inferenceservices.yaml 'spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.*.properties.*.required' #remove ephemeralContainers properties for compress crd size https://github.com/kubeflow/kfserving/pull/1141#issuecomment-714170602 @@ -188,9 +198,15 @@ docker-push: docker-build-agent: docker build -f agent.Dockerfile . -t ${KO_DOCKER_REPO}/${AGENT_IMG} +docker-build-router: + docker build -f router.Dockerfile . -t ${KO_DOCKER_REPO}/${ROUTER_IMG} + docker-push-agent: docker push ${KO_DOCKER_REPO}/${AGENT_IMG} +docker-push-router: + docker push ${KO_DOCKER_REPO}/${ROUTER_IMG} + docker-build-sklearn: cd python && docker build -t ${KO_DOCKER_REPO}/${SKLEARN_IMG} -f sklearn.Dockerfile . diff --git a/cmd/manager/main.go b/cmd/manager/main.go index 9e7eb85546f..d939ae6bf3f 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -22,6 +22,7 @@ import ( "github.com/kserve/kserve/pkg/apis/serving/v1alpha1" "github.com/kserve/kserve/pkg/apis/serving/v1beta1" "github.com/kserve/kserve/pkg/constants" + graphcontroller "github.com/kserve/kserve/pkg/controller/v1alpha1/inferencegraph" trainedmodelcontroller "github.com/kserve/kserve/pkg/controller/v1alpha1/trainedmodel" "github.com/kserve/kserve/pkg/controller/v1alpha1/trainedmodel/reconcilers/modelconfig" v1beta1controller "github.com/kserve/kserve/pkg/controller/v1beta1/inferenceservice" @@ -36,7 +37,7 @@ import ( "k8s.io/client-go/tools/record" knservingv1 "knative.dev/serving/pkg/apis/serving/v1" ctrl "sigs.k8s.io/controller-runtime" - client "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/config" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" @@ -158,6 +159,20 @@ func main() { os.Exit(1) } + //Setup Inference graph controller + inferenceGraphEventBroadcaster := record.NewBroadcaster() + setupLog.Info("Setting up InferenceGraph controller") + inferenceGraphEventBroadcaster.StartRecordingToSink(&typedcorev1.EventSinkImpl{Interface: clientSet.CoreV1().Events("")}) + if err = (&graphcontroller.InferenceGraphReconciler{ + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("v1alpha1Controllers").WithName("InferenceGraph"), + Scheme: mgr.GetScheme(), + Recorder: eventBroadcaster.NewRecorder(mgr.GetScheme(), v1.EventSource{Component: "InferenceGraphController"}), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "v1alpha1Controllers", "InferenceGraph") + os.Exit(1) + } + log.Info("setting up webhook server") hookServer := mgr.GetWebhookServer() @@ -170,6 +185,14 @@ func main() { setupLog.Error(err, "unable to create webhook", "webhook", "v1alpha1") os.Exit(1) } + + if err = ctrl.NewWebhookManagedBy(mgr). + For(&v1alpha1.InferenceGraph{}). + Complete(); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "v1alpha1") + os.Exit(1) + } + if err = ctrl.NewWebhookManagedBy(mgr). For(&v1beta1.InferenceService{}). Complete(); err != nil { diff --git a/cmd/router/main.go b/cmd/router/main.go new file mode 100644 index 00000000000..2aa5f3647a4 --- /dev/null +++ b/cmd/router/main.go @@ -0,0 +1,206 @@ +/* +Copyright 2022 The KServe Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "os" + "strconv" + "time" + + "github.com/tidwall/gjson" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + + "math/rand" + + "github.com/kserve/kserve/pkg/apis/serving/v1alpha1" + flag "github.com/spf13/pflag" +) + +var log = logf.Log.WithName("InferenceGraphRouter") + +func callService(serviceUrl string, input []byte) ([]byte, error) { + resp, err := http.Post(serviceUrl, "application/json", bytes.NewBuffer(input)) + if err != nil { + log.Error(err, "An error has occurred from service", "service", serviceUrl) + return nil, err + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Error(err, "error while reading the response") + } + return body, err +} + +func pickupRoute(routes []v1alpha1.InferenceStep) *v1alpha1.InferenceStep { + r := rand.New(rand.NewSource(time.Now().UnixNano())) + //generate num [0,100) + point := r.Intn(99) + end := 0 + for _, route := range routes { + end += int(*route.Weight) + if point < end { + return &route + } + } + return nil +} + +func pickupRouteByCondition(input []byte, routes []v1alpha1.InferenceStep) *v1alpha1.InferenceStep { + if !gjson.ValidBytes(input) { + return nil + } + for _, route := range routes { + if gjson.GetBytes(input, route.Condition).Exists() { + return &route + } + } + return nil +} + +func timeTrack(start time.Time, name string) { + elapsed := time.Since(start) + log.Info("elapsed time", "node", name, "time", elapsed) +} + +func routeStep(nodeName string, graph v1alpha1.InferenceGraphSpec, input []byte) ([]byte, error) { + log.Info("current step", "nodeName", nodeName) + defer timeTrack(time.Now(), nodeName) + currentNode := graph.Nodes[nodeName] + + if currentNode.RouterType == v1alpha1.Splitter { + return executeStep(pickupRoute(currentNode.Steps), graph, input) + } + if currentNode.RouterType == v1alpha1.Switch { + route := pickupRouteByCondition(input, currentNode.Steps) + if route == nil { + return input, nil //TODO maybe should fail in this case? + } + return executeStep(route, graph, input) + } + if currentNode.RouterType == v1alpha1.Ensemble { + ensembleRes := make([]chan map[string]interface{}, len(currentNode.Steps)) + errChan := make(chan error) + for i := range currentNode.Steps { + step := ¤tNode.Steps[i] + resultChan := make(chan map[string]interface{}) + ensembleRes[i] = resultChan + go func() { + output, err := executeStep(step, graph, input) + if err == nil { + var res map[string]interface{} + if err = json.Unmarshal(output, &res); err == nil { + resultChan <- res + return + } + } + errChan <- err + }() + } + // merge responses from parallel steps + response := map[string]interface{}{} + for i, resultChan := range ensembleRes { + key := currentNode.Steps[i].StepName + if key == "" { + key = strconv.Itoa(i) // Use index if no step name + } + select { + case response[key] = <-resultChan: + case err := <-errChan: + return nil, err + } + } + return json.Marshal(response) + } + if currentNode.RouterType == v1alpha1.Sequence { + var responseBytes []byte + var err error + for i := range currentNode.Steps { + step := ¤tNode.Steps[i] + request := input + if step.Data == "$response" && i > 0 { + request = responseBytes + } + + if step.Condition != "" { + if !gjson.ValidBytes(responseBytes) { + return nil, fmt.Errorf("invalid response") + } + // if the condition does not match for the step in the sequence we stop and return the response + if !gjson.GetBytes(responseBytes, step.Condition).Exists() { + return responseBytes, nil + } + } + if responseBytes, err = executeStep(step, graph, request); err != nil { + return nil, err + } + } + return responseBytes, nil + } + log.Error(nil, "invalid route type", "type", currentNode.RouterType) + return nil, fmt.Errorf("invalid route type: %v", currentNode.RouterType) +} + +func executeStep(step *v1alpha1.InferenceStep, graph v1alpha1.InferenceGraphSpec, input []byte) ([]byte, error) { + if step.NodeName != "" { + // when nodeName is specified make a recursive call for routing to next step + return routeStep(step.NodeName, graph, input) + } + return callService(step.ServiceURL, input) +} + +var inferenceGraph *v1alpha1.InferenceGraphSpec + +func graphHandler(w http.ResponseWriter, req *http.Request) { + inputBytes, _ := ioutil.ReadAll(req.Body) + if response, err := routeStep(v1alpha1.GraphRootNodeName, *inferenceGraph, inputBytes); err != nil { + log.Error(err, "failed to process request") + w.WriteHeader(500) //TODO status code tbd + w.Write([]byte(fmt.Sprintf("Failed to process request: %v", err))) + } else { + w.Write(response) + } +} + +var ( + jsonGraph = flag.String("graph-json", "", "serialized json graph def") +) + +func main() { + flag.Parse() + logf.SetLogger(zap.New()) + inferenceGraph = &v1alpha1.InferenceGraphSpec{} + err := json.Unmarshal([]byte(*jsonGraph), inferenceGraph) + if err != nil { + log.Error(err, "failed to unmarshall inference graph json") + os.Exit(1) + } + + http.HandleFunc("/", graphHandler) + + err = http.ListenAndServe(":8080", nil) + if err != nil { + log.Error(err, "failed to listen on 8080") + os.Exit(1) + } +} diff --git a/cmd/router/main_test.go b/cmd/router/main_test.go new file mode 100644 index 00000000000..204100ba01e --- /dev/null +++ b/cmd/router/main_test.go @@ -0,0 +1,347 @@ +package main + +import ( + "encoding/json" + "fmt" + "github.com/kserve/kserve/pkg/apis/serving/v1alpha1" + "github.com/stretchr/testify/assert" + "io/ioutil" + "knative.dev/pkg/apis" + "net/http" + "net/http/httptest" + "testing" +) + +func TestSimpleModelChainer(t *testing.T) { + // Start a local HTTP server + model1 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + _, err := ioutil.ReadAll(req.Body) + if err != nil { + return + } + response := map[string]interface{}{"predictions": "1"} + responseBytes, err := json.Marshal(response) + _, err = rw.Write(responseBytes) + })) + model1Url, err := apis.ParseURL(model1.URL) + if err != nil { + t.Fatalf("Failed to parse model url") + } + defer model1.Close() + model2 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + _, err := ioutil.ReadAll(req.Body) + if err != nil { + return + } + response := map[string]interface{}{"predictions": "2"} + responseBytes, err := json.Marshal(response) + _, err = rw.Write(responseBytes) + })) + model2Url, err := apis.ParseURL(model2.URL) + if err != nil { + t.Fatalf("Failed to parse model url") + } + defer model2.Close() + + graphSpec := v1alpha1.InferenceGraphSpec{ + Nodes: map[string]v1alpha1.InferenceRouter{ + "root": { + RouterType: v1alpha1.Sequence, + Steps: []v1alpha1.InferenceStep{ + { + StepName: "model1", + InferenceTarget: v1alpha1.InferenceTarget{ + ServiceURL: model1Url.String(), + }, + }, + { + StepName: "model2", + InferenceTarget: v1alpha1.InferenceTarget{ + ServiceURL: model2Url.String(), + }, + Data: "$response", + }, + }, + }, + }, + } + input := map[string]interface{}{ + "instances": []string{ + "test", + "test2", + }, + } + jsonBytes, _ := json.Marshal(input) + res, err := routeStep("root", graphSpec, jsonBytes) + var response map[string]interface{} + err = json.Unmarshal(res, &response) + expectedResponse := map[string]interface{}{ + "predictions": "2", + } + fmt.Printf("final response:%v", response) + assert.Equal(t, expectedResponse, response) +} + +func TestSimpleModelEnsemble(t *testing.T) { + // Start a local HTTP server + model1 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + _, err := ioutil.ReadAll(req.Body) + if err != nil { + return + } + response := map[string]interface{}{"predictions": "1"} + responseBytes, err := json.Marshal(response) + _, err = rw.Write(responseBytes) + })) + model1Url, err := apis.ParseURL(model1.URL) + if err != nil { + t.Fatalf("Failed to parse model url") + } + defer model1.Close() + model2 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + _, err := ioutil.ReadAll(req.Body) + if err != nil { + return + } + response := map[string]interface{}{"predictions": "2"} + responseBytes, err := json.Marshal(response) + _, err = rw.Write(responseBytes) + })) + model2Url, err := apis.ParseURL(model2.URL) + if err != nil { + t.Fatalf("Failed to parse model url") + } + defer model2.Close() + + graphSpec := v1alpha1.InferenceGraphSpec{ + Nodes: map[string]v1alpha1.InferenceRouter{ + "root": { + RouterType: v1alpha1.Ensemble, + Steps: []v1alpha1.InferenceStep{ + { + StepName: "model1", + InferenceTarget: v1alpha1.InferenceTarget{ + ServiceURL: model1Url.String(), + }, + }, + { + StepName: "model2", + InferenceTarget: v1alpha1.InferenceTarget{ + ServiceURL: model2Url.String(), + }, + }, + }, + }, + }, + } + input := map[string]interface{}{ + "instances": []string{ + "test", + "test2", + }, + } + jsonBytes, _ := json.Marshal(input) + res, err := routeStep("root", graphSpec, jsonBytes) + var response map[string]interface{} + err = json.Unmarshal(res, &response) + expectedResponse := map[string]interface{}{ + "model1": map[string]interface{}{ + "predictions": "1", + }, + "model2": map[string]interface{}{ + "predictions": "2", + }, + } + fmt.Printf("final response:%v", response) + assert.Equal(t, expectedResponse, response) +} + +func TestInferenceGraphWithCondition(t *testing.T) { + // Start a local HTTP server + model1 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + _, err := ioutil.ReadAll(req.Body) + if err != nil { + return + } + response := map[string]interface{}{ + "predictions": []map[string]interface{}{ + { + "label": "cat", + "score": []float32{ + 0.1, 0.9, + }, + }, + }, + } + responseBytes, err := json.Marshal(response) + _, err = rw.Write(responseBytes) + })) + model1Url, err := apis.ParseURL(model1.URL) + if err != nil { + t.Fatalf("Failed to parse model url") + } + defer model1.Close() + model2 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + _, err := ioutil.ReadAll(req.Body) + if err != nil { + return + } + response := map[string]interface{}{ + "predictions": []map[string]interface{}{ + { + "label": "dog", + "score": []float32{ + 0.8, 0.2, + }, + }, + }, + } + responseBytes, err := json.Marshal(response) + _, err = rw.Write(responseBytes) + })) + model2Url, err := apis.ParseURL(model2.URL) + if err != nil { + t.Fatalf("Failed to parse model url") + } + defer model2.Close() + + // Start a local HTTP server + model3 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + _, err := ioutil.ReadAll(req.Body) + if err != nil { + return + } + response := map[string]interface{}{ + "predictions": []map[string]interface{}{ + { + "label": "beagle", + "score": []float32{ + 0.1, 0.9, + }, + }, + }, + } + responseBytes, err := json.Marshal(response) + _, err = rw.Write(responseBytes) + })) + model3Url, err := apis.ParseURL(model3.URL) + if err != nil { + t.Fatalf("Failed to parse model url") + } + defer model3.Close() + model4 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + _, err := ioutil.ReadAll(req.Body) + if err != nil { + return + } + response := map[string]interface{}{ + "predictions": []map[string]interface{}{ + { + "label": "poodle", + "score": []float32{ + 0.8, 0.2, + }, + }, + }, + } + responseBytes, err := json.Marshal(response) + _, err = rw.Write(responseBytes) + })) + model4Url, err := apis.ParseURL(model4.URL) + if err != nil { + t.Fatalf("Failed to parse model url") + } + defer model4.Close() + + graphSpec := v1alpha1.InferenceGraphSpec{ + Nodes: map[string]v1alpha1.InferenceRouter{ + "root": { + RouterType: v1alpha1.Sequence, + Steps: []v1alpha1.InferenceStep{ + { + StepName: "step1", + InferenceTarget: v1alpha1.InferenceTarget{ + NodeName: "animal-categorize", + }, + }, + { + StepName: "step2", + InferenceTarget: v1alpha1.InferenceTarget{ + NodeName: "breed-categorize", + }, + Condition: "predictions.#(label==\"dog\")", + }, + }, + }, + "animal-categorize": { + RouterType: v1alpha1.Switch, + Steps: []v1alpha1.InferenceStep{ + { + StepName: "model1", + InferenceTarget: v1alpha1.InferenceTarget{ + ServiceURL: model1Url.String(), + }, + Condition: "instances.#(modelId==\"1\")", + }, + { + StepName: "model2", + InferenceTarget: v1alpha1.InferenceTarget{ + ServiceURL: model2Url.String(), + }, + Condition: "instances.#(modelId==\"2\")", + }, + }, + }, + "breed-categorize": { + RouterType: v1alpha1.Ensemble, + Steps: []v1alpha1.InferenceStep{ + { + StepName: "model3", + InferenceTarget: v1alpha1.InferenceTarget{ + ServiceURL: model3Url.String(), + }, + }, + { + StepName: "model4", + InferenceTarget: v1alpha1.InferenceTarget{ + ServiceURL: model4Url.String(), + }, + }, + }, + }, + }, + } + input := map[string]interface{}{ + "instances": []map[string]string{ + {"modelId": "2"}, + }, + } + jsonBytes, _ := json.Marshal(input) + res, err := routeStep("root", graphSpec, jsonBytes) + var response map[string]interface{} + err = json.Unmarshal(res, &response) + expectedModel3Response := map[string]interface{}{ + "predictions": []interface{}{ + map[string]interface{}{ + "label": "beagle", + "score": []interface{}{ + 0.1, 0.9, + }, + }, + }, + } + + expectedModel4Response := map[string]interface{}{ + "predictions": []interface{}{ + map[string]interface{}{ + "label": "poodle", + "score": []interface{}{ + 0.8, 0.2, + }, + }, + }, + } + fmt.Printf("final response:%v\n", response) + assert.Equal(t, expectedModel3Response, response["model3"]) + assert.Equal(t, expectedModel4Response, response["model4"]) +} diff --git a/config/configmap/inferenceservice.yaml b/config/configmap/inferenceservice.yaml index cb38b2d3d25..910ab78c508 100644 --- a/config/configmap/inferenceservice.yaml +++ b/config/configmap/inferenceservice.yaml @@ -188,6 +188,14 @@ data: "cpuRequest": "100m", "cpuLimit": "1" } + router: |- + { + "image" : "kserve/router:latest", + "memoryRequest": "100Mi", + "memoryLimit": "1Gi", + "cpuRequest": "100m", + "cpuLimit": "1" + } deploy: |- { "defaultDeploymentMode": "Serverless" diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 40b09b35a67..38000559939 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -12,7 +12,7 @@ resources: - serving.kserve.io_trainedmodels.yaml - serving.kserve.io_clusterservingruntimes.yaml - serving.kserve.io_servingruntimes.yaml - +- serving.kserve.io_inferencegraphs.yaml patchesJson6902: # Fix for https://github.com/kubernetes/kubernetes/issues/91395 - target: diff --git a/config/crd/serving.kserve.io_inferencegraphs.yaml b/config/crd/serving.kserve.io_inferencegraphs.yaml new file mode 100644 index 00000000000..6b8915003ad --- /dev/null +++ b/config/crd/serving.kserve.io_inferencegraphs.yaml @@ -0,0 +1,122 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.0 + creationTimestamp: null + name: inferencegraphs.serving.kserve.io +spec: + group: serving.kserve.io + names: + kind: InferenceGraph + listKind: InferenceGraphList + plural: inferencegraphs + shortNames: + - ig + singular: inferencegraph + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.url + name: URL + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + nodes: + additionalProperties: + properties: + routerType: + enum: + - Sequence + - Splitter + - Ensemble + - Switch + type: string + steps: + items: + properties: + condition: + type: string + data: + type: string + name: + type: string + nodeName: + type: string + serviceName: + type: string + serviceUrl: + type: string + weight: + format: int64 + type: integer + type: object + type: array + required: + - routerType + type: object + type: object + required: + - nodes + type: object + status: + properties: + annotations: + additionalProperties: + type: string + type: object + conditions: + items: + properties: + lastTransitionTime: + type: string + message: + type: string + reason: + type: string + severity: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + observedGeneration: + format: int64 + type: integer + url: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/default/webhookcainjection_patch.yaml b/config/default/webhookcainjection_patch.yaml index 3abeca18f6c..570a03b454e 100644 --- a/config/default/webhookcainjection_patch.yaml +++ b/config/default/webhookcainjection_patch.yaml @@ -26,3 +26,12 @@ metadata: cert-manager.io/inject-ca-from: $(kserveNamespace)/serving-cert webhooks: - name: trainedmodel.kserve-webhook-server.validator +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: inferencegraph.serving.kserve.io + annotations: + cert-manager.io/inject-ca-from: $(kserveNamespace)/serving-cert +webhooks: + - name: inferencegraph.kserve-webhook-server.validator diff --git a/config/overlays/development/configmap/ko_resolve_router b/config/overlays/development/configmap/ko_resolve_router new file mode 100644 index 00000000000..99f7cde803e --- /dev/null +++ b/config/overlays/development/configmap/ko_resolve_router @@ -0,0 +1 @@ +image: ko://github.com/kserve/kserve/cmd/router diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 5f90ddbcfa4..8d86419ccc1 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -210,6 +210,26 @@ rules: - get - patch - update +- apiGroups: + - serving.kserve.io + resources: + - inferencegraphs + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - serving.kserve.io + resources: + - inferencegraphs/status + verbs: + - get + - patch + - update - apiGroups: - serving.kserve.io resources: diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml index d4404675e81..84fa4f7ecf1 100644 --- a/config/webhook/manifests.yaml +++ b/config/webhook/manifests.yaml @@ -108,3 +108,30 @@ webhooks: - UPDATE resources: - trainedmodels +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + creationTimestamp: null + name: inferencegraph.serving.kserve.io +webhooks: + - clientConfig: + caBundle: Cg== + service: + name: $(webhookServiceName) + namespace: $(kserveNamespace) + path: /validate-serving-kserve-io-v1alpha1-inferencegraph + failurePolicy: Fail + name: inferencegraph.kserve-webhook-server.validator + sideEffects: None + admissionReviewVersions: ["v1beta1"] + rules: + - apiGroups: + - serving.kserve.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - inferencegraphs diff --git a/docs/samples/graph/README.md b/docs/samples/graph/README.md new file mode 100644 index 00000000000..10703f7d13c --- /dev/null +++ b/docs/samples/graph/README.md @@ -0,0 +1,217 @@ +- [**Inference Graph**](#inference-graph) + - [**1. Problem Statement**](#1-problem) + - [**2. KServe Inference Graph**](#2-kserve-inference-graph) + - [**2.1 Inference Graph**](#21-inference-graph) + - [**2.2 Single Node**](#22-single-node) + - [**2.3 Switch Node**](#23-switch-node) + - [**2.4 Ensemble Node**](#24-ensemble-node) + - [**2.5 Splitter Node**](#25-splitter-node) + +# **Inference Graph** +## **1. Problem Statement** + +Production inference pipelines are often composed of multiple inference services, models need to be chained together to produce the final prediction result. +For example, a face recognition pipeline may need to find the face area first and then compute the features of the faces to match the face database. +These two models depend on each other, and the first model’s output is the second model’s input. Another example is the NLP pipeline, it is common to run document classification +first and then run downstream named entity detection or text summary tasks. + +KServe inference graph is designed for this. + +## **2. KServe Inference Graph** +![image](graph.png) + +### **2.1 Inference Graph** +As the above image shows, an inference graph is made up of a list of `nodes`, and each `node` consists of several steps with `InferenceService` or `Node` as the targets which is highly composable. +Every graph must have a root node named `root`, when an inference request hits the graph, it executes the request starting from the `root` node of the DAG. If the graph has other `nodes` in the `Sequence`, +it will pass the `$request` or `$response` of the root node as input data to the `next node`. There are four `node` types that are supported: ***Sequence***, ***Switch***, ***Ensemble***, ***Splitter***. + + +### **2.2 Sequence Node** +**Sequence Node** allows users to connect multiple `InferenceServices` or `Nodes` in a sequence. The `steps` field defines the steps executed in sequence and returns a response after the last step on the sequence. +User can choose to pass `$request` or `$response` from each step as the input data to the next `InferenceService` or node in the sequence. + +![image](singleNode.png) +```yaml +... +root: + routerType: Sequence + steps: + - serviceName: isvc1 + - serviceName: isvc2 + data: $request +... +``` + +***Test steps*** + +1. Deploy the `InferenceService` and `InferenceGraph` [yaml](sequence.yaml) +```shell +kubectl apply -f sequence.yaml +``` +2. Wait for `InferenceService` and `InferenceGraph` to be ready. +```shell +kubectl get pods +NAME READY STATUS RESTARTS AGE +model-chainer-00001-deployment-6bf7cf7776-zn5p4 2/2 Running 0 32s +sklearn-iris-predictor-default-00001-deployment-8495cbf8cbdqfjg 2/2 Running 0 52s +xgboost-iris-predictor-default-00001-deployment-7b86bcdcf-7njrl 2/2 Running 0 50s + +kubectl get isvc +NAME URL READY PREV LATEST PREVROLLEDOUTREVISION LATESTREADYREVISION AGE +sklearn-iris http://sklearn-iris.default.10.166.15.29.sslip.io True 100 sklearn-iris-predictor-default-00001 80m +xgboost-iris http://xgboost-iris.default.10.166.15.29.sslip.io True 100 xgboost-iris-predictor-default-00001 80m + +kubectl get ig +NAME URL READY AGE +model-chainer http://model-chainer.default.10.166.15.29.sslip.io True 5s +``` +3. Test `InferenceGraph`. +```shell +curl http://model-chainer.default.10.166.15.29.sslip.io -d @./iris-input.json +``` +***Expected result*** +```shell +{"predictions":[1,1]} +``` + + +### **2.3 Switch Node** +**Switch Node** allows users to select a step to execute the request by matching the `condition`, it returns the response back as soon as it matches the condition for one of the steps +in order. + +![image](switchNode.png) +```yaml +mymodel: + routerType: Switch + steps: + - serviceName: isvc1 + condition: "target == \"blue\"" + - serviceName: isvc2 + condition: "target == \"green\"" +``` +We use `https://github.com/tidwall/gjson` to parse and match the condition and [here](https://github.com/tidwall/gjson/blob/master/SYNTAX.md) is the `GJSON` syntax reference. + +***Test steps*** + +1. Deploy the `InferenceService` and `InferenceGraph` [yaml](./switch.yaml) +```shell +kubectl apply -f switch.yaml +``` +2. Wait for `InferenceService` and `InferenceGraph` to be ready. +```shell +kubectl get pods +NAME READY STATUS RESTARTS AGE +blue-predictor-default-00002-deployment-855665bc49-m5vxt 2/2 Running 0 3m26s +green-predictor-default-00002-deployment-7485d64dbd-dgmbx 2/2 Running 0 3m26s +model-switch-00001-deployment-7ff47cdbb8-vxgp7 2/2 Running 0 28s + +kubectl get isvc +NAME URL READY PREV LATEST PREVROLLEDOUTREVISION LATESTREADYREVISION AGE +blue http://blue.default.10.166.15.29.sslip.io True 100 blue-predictor-default-00002 3d7h +green http://green.default.10.166.15.29.sslip.io True 100 green-predictor-default-00002 3d7h + +kubectl get ig +NAME URL READY AGE +model-switch http://model-switch.default.10.166.15.29.sslip.io True 35s +``` +3. Test `InferenceGraph`. +```shell +curl http://model-switch.default.10.166.15.29.sslip.io +``` +***Expected result*** +```shell +{"mymodel":{"server_counter":0,"target":"green","target_counter":2}} +``` + +### **2.4 Ensemble Node** +Scoring a case using a model ensemble consists of scoring it using each model separately, then combining the results into a single scoring result using one of the pre-defined combination methods. +Tree Ensemble constitutes a case where simple algorithms for combining results of either classification or regression trees are well known. +Multiple classification trees, for example, are commonly combined using a "majority-vote" method. Multiple regression trees are often combined using various averaging techniques. + +![image](ensembleNode.png) + +```yaml +root: + routerType: Ensemble + routes: + - serviceName: sklearn-iris + - serviceName: xgboost-iris +``` + +***Test steps*** + +1. Deploy the `InferenceService` and `InferenceGraph` [yaml](ensemble.yaml) +```shell +kubectl apply -f switch.yaml +``` +2. Wait for `InferenceService` and `InferenceGraph` to be ready. +```shell +kubectl get pods +NAME READY STATUS RESTARTS AGE +ensemble-model-00001-deployment-7d48f984b6-qqqsh 2/2 Running 0 32s +sklearn-iris-predictor-default-00001-deployment-8495cbf8cbdqfjg 2/2 Running 0 52s +xgboost-iris-predictor-default-00001-deployment-7b86bcdcf-7njrl 2/2 Running 0 50s + +kubectl get isvc +NAME URL READY PREV LATEST PREVROLLEDOUTREVISION LATESTREADYREVISION AGE +sklearn-iris http://sklearn-iris.default.10.166.15.29.sslip.io True 100 sklearn-iris-predictor-default-00001 80m +xgboost-iris http://xgboost-iris.default.10.166.15.29.sslip.io True 100 xgboost-iris-predictor-default-00001 80m + +kubectl get ig +NAME URL READY AGE +ensemble-model http://ensemble-model.default.10.166.15.29.sslip.io True 15m +``` +3. Test `InferenceGraph`. +```shell +curl http://ensemble-model.default.10.166.15.29.sslip.io -d @./iris-input.json +``` +***Expected result*** +```shell +{"sklearn-iris":{"predictions":[1,1]},"xgboost-iris":{"predictions":[1,1]}} +``` + +### **2.5 Splitter Node** +**Splitter Node** allows users to split traffic to multiple targets using a weighted distribution. + +![image](splitterNode.png) +```yaml +root: + routerType: Splitter + routes: + - serviceName: sklearn-iris + weight: 20 + - serviceName: xgboost-iris + weight: 80 +``` + +***Test steps*** + +1. Deploy the demo `InferenceService` and `InferenceGraph` [yaml](./splitter.yaml) +```shell +kubectl apply -f splitter.yaml +``` +2. Wait for `InferenceService` and `InferenceGraph` to be ready. +```shell +kubectl get pods +NAME READY STATUS RESTARTS AGE +splitter-model-00001-deployment-c5ccc95d5-lxhnb 2/2 Running 0 15m +sklearn-iris-predictor-default-00001-deployment-8495cbf8cbdqfjg 2/2 Running 0 15m +xgboost-iris-predictor-default-00001-deployment-7b86bcdcf-7njrl 2/2 Running 0 15m + +kubectl get isvc +NAME URL READY PREV LATEST PREVROLLEDOUTREVISION LATESTREADYREVISION AGE +sklearn-iris http://sklearn-iris.default.10.166.15.29.sslip.io True 100 sklearn-iris-predictor-default-00001 80m +xgboost-iris http://xgboost-iris.default.10.166.15.29.sslip.io True 100 xgboost-iris-predictor-default-00001 80m + +kubectl get ig +NAME URL READY AGE +splitter-model http://splitter-model.default.10.166.15.29.sslip.io True 15m +``` +3. Test `InferenceGraph`. +```shell +curl http://splitter-model.default.10.166.15.29.sslip.io -d @./iris-input.json +``` +***Expected result*** +```shell +{"treeModel":{"predictions":[1,1]}} +``` diff --git a/docs/samples/graph/ensemble.yaml b/docs/samples/graph/ensemble.yaml new file mode 100644 index 00000000000..1406db17aa4 --- /dev/null +++ b/docs/samples/graph/ensemble.yaml @@ -0,0 +1,30 @@ +--- +apiVersion: "serving.kserve.io/v1beta1" +kind: "InferenceService" +metadata: + name: "sklearn-iris" +spec: + predictor: + sklearn: + storageUri: "gs://kfserving-examples/models/sklearn/1.0/model" +--- +apiVersion: "serving.kserve.io/v1beta1" +kind: "InferenceService" +metadata: + name: "xgboost-iris" +spec: + predictor: + xgboost: + storageUri: "gs://kfserving-examples/models/xgboost/iris" +--- +apiVersion: serving.kserve.io/v1alpha1 +kind: InferenceGraph +metadata: + name: ensemble-model +spec: + nodes: + root: + routerType: Ensemble + steps: + - serviceName: sklearn-iris + - serviceName: xgboost-iris diff --git a/docs/samples/graph/ensembleNode.png b/docs/samples/graph/ensembleNode.png new file mode 100644 index 0000000000000000000000000000000000000000..973059f6120940a42a674b091528d2f9d758d8b6 GIT binary patch literal 57033 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 DE62c~ literal 0 HcmV?d00001 diff --git a/docs/samples/graph/graph.png b/docs/samples/graph/graph.png new file mode 100644 index 0000000000000000000000000000000000000000..02aae480c8c65bea1fce0d137ece767f7e775025 GIT binary patch literal 89854 zcmeFY2b9xR*ER}-4goTu1VRge00T2vmStOX%eLIRTqzS5xyzO<7umGXLMN1A2)%_K z`p`lPJsElnA@mYR=)IT!81lZ!_x}0r{nonoUw5s$vet~P(UDHsXYXe}d!Icc^jg{b z)f-hWSFYUq3c18su3W_t<;qoPU9~c}(>PJ>CHN}O7-d+w;OrjMmX~pGA!=yVAk4C^HxKBkr0dIixyldlfxZDB`uYd~?5VsX9 zg5Q1!3pqT<@$Px2kBt1$5mLwj9kkIn-GN9V%J^Hs82DQeNswXi4Q_)^oe6x{z%Rrp zf{-FXTW~3&=`d*}U8+E$6&FWfK_Scsx7(=Xght(pD+br$K!^liGSVH2=3eo{o$10r z6g&5Drl&>Z+f%yc{<_i23wLaI;UVv(DOxQTZiM4VtvZwCXf(EfLQ z2rR6NL>Qh_&w;$5G+0Imlla(-L&p(-9pl3=Cx`?>GKj0O1u&f)Y!%oE+)T^3BD*pq z(*#XYJ>M)by44!KL+0jc{8Cri6}O-PB@79}`Vh}5l4@l_fsfW0MN(0g@G87vGMxz+ z5KUMbvNEKQ5E0=RDYL=1v zY`6{L2*kp)l8*5Rp;iT^BOf$TopCt&2Bj@qcA=Kbt)M2sL z9!;T2e?%}DAI>XD6^N21W1KWDNuRRK_;S3ri?sSTI2R6O%NxeRA|fs zp@U0uQ#>rd4`wK{LrLp{a01iw0!ocLnKnw~MyZ$;^1`YV<&Ie5f(XZvNI{6yOQ(`H zqstxCie;vxQ7H95QbWkYP3LpwjFeSj1R+$l!hs-pS<@l5`m}^XlR1g*m;xZ!# zO(!C9k&5*xRXn5F4x~xu?9PQa!DkwX2nRou9B4ZRdw^|WHpbzNq`-xcal|2cBqf!) zFbY?B)lN)?6Or78gq04F9v5VttSKRLc)=Z>gz#vrK00es#-jvkc6zix(@c8Co`_qt zMqer+Q{ve`B5B|&19qC_sepxGbRwXSp-E%fDF=UrUAdV>6_yZB9n=UNnJ6R4=}|DC zH?bUx9usjfC96Ob2`Fmf!U;JCN=U&nFmBpUrtH#~mK#v$P&X>IWrS{(C1J2?^wEf0 zP1!A3xh%w_gEp_1tA_<_#Oov#-V8z+1!P2(vGch$r!59yp+r;{7KivYt4A#h@m*3q zp>vt7X*@>rtu8P-n?&O^S@hAM7QwV&XudZDJ|z-9Kjc;W6yREs^f6(Khw0QFk3dbk z^-@@um9Zg(ij$0Kk*qQuh^aFQQ(C43dKyq9a6$&jS&kNlGiHHDE;Gu)QcrGI6#h6E z0{4JU9a@4@OnP>zFL~K5niEr}SQJpv# zj+jh%!Ybk>qDT@?i4%}hj>%)3Y}lXhN^?fQc;#VFz>Qi^YXY`MBC#Mp#$*$EcUCG>#1j%_LXn7TB}rWf zRb`!WgEubs8%%zhRAEFqtHA^Au*hRcm_6B8L=>=Q{1RS>Ho!VzTujEqs8U55gKUCS z?7&FMlSxB6)7!vY;E}kV!ew`83XCVP*AsCG}B8uc5=dl7N zO?xQZY(aIhOqMbGn5@#o(O7VRdpK?h+4aB$i3N!S$E}L#lT;kM?9sKon~c zAW0UY-C~T=p&UF26c=}joqnNC#m6C|*Njjwl6xV@Bf>ByXQ7yx%R1zaFdr~9oDr!F zYA9gLI`up>N;?^UQe)6k3O$x|>H-O`(1;_Dz+tjwlWD-}aE752s!S>z%WC8i5f;}) zQ8|?{@gN_a(PSB)!<5Zn7Lw(LfL?$hPlztvpp8-sWL``It(Yb6wahjD7W-eE2 zhd4MiQwPC9lRA+Ahz(D>bIc3|{1pEerTcIAoeP0E1|^5< zSI0O77AG&}i~?T(RGRZAzheRsUzpTJJ#VQaEJZASts7y|Ig+Oj+9hH&hQ@W=kd6TO zB+(PJiquJD34;Q`k zVSzN3wvic=CxSu3V2mqQ%D4#u6R@d_C}V~~VN5CZxG<^35(GX8ml2o&_5*QZ7)K%r zrc4;ER01`oP?OB(gxo2aPn;1;g9IEPwGhVRAr>EHaF{7$TyBslq$!c!=U15g{2=Sl z&?=Qz4wDX@M2kyEDJMV$gF0`@=u7CqP)-B*kRoZ+5QAk|RtQlB7v!=cSu0kH zajO6mnq_)L+^w~`B2kZ(h-MO`NTOGZBDBD0%ZfFItia1AV?n<`tqJgTZ;7JY?2)IX zd|HpeKE%yYIfSV|1`inGq%vekN!@&rK^}zUI&+3=&*7IL8?gYUBFc#@jGFywy;v2X z9b#h;!u2VID;EUf&WK-**g{?($#<)~dXFdV&v1>BtT~f2PROi^3c09LYXkII3nDm; zR)qLT9M#BhUfiVj3p9$T2F+11zLZD@(^(;p2ua|q#|Ib$P&k3huSQcMt52unD!mX& zDBKoIE{VD%3Im_-j*AgKoV0Rp{) zQYNiA#L1Xbk{oHFT|u=$9Ej^Qm*2{=1N)Ru#xZb5D+Gy!#W^GjKh^1y?P;zhjX4wWO$2;|JT6y z7uci2fkc9g{|os342sR_f`XJ!55;&KtIkP_^$rX6ulSdCxzQ+Js^>v^h100^pgf7# z#F1p7h>q4d=p-o=TR`OCc4abRrN|rMgw^^GW#9%Rb~Mfrlc>rXjtB%U(ga1bK9?F6 zq;WC8V=U^C>9B}Hp^a&IT3C^wU>`{;<<687XX6Sqfl8!7sZnLggvg9UYc<8h92u+j zr?fJo8KKjmpw*%d=(g4GyBw%v5KxyYlC|Nc~ z2l#ru4OPlflt;m6FiTkR95M#Al1#vyj_B2DDsESEIKn8`1X2ii%w@}@Y<6E1VK`|p z6`4j(dqQTOm+>1^coJ4nPN|Er*#Zs`BXk8qDvO)7OSw|;s>0wh!|_i~>P?N7z&OIJDGXRWW>rZAa#t9Z2301dL;)d2~5h3Dm*4l&WwF>yG9|GhTOE& z1a>@-hAFeqXw^FHF%y9pDKP`3C_M-wV9dgXAQ1D1= z479_H#qaTPz?GgKk0$+=Sjz6V;&N6j7Ra*Ns7M$Q7!zoOG$a*j6_k)zVv?j+#EL{d zBrB&>5w1OG2__7=bp`YWqfJRbvaCqvr9_Zbl?*WmPOw2#EkR9u;G#2lMo#$S4xt}H zn^h)rNd5?E9DKDfmX2Bi zStSv3Dx4-|&=HM`bIw-kcM(K7qCq2!K%sURaVi;%h)n{clGFiL?=>P$o|4Sv%D71< z%6GylLEH_D53?y5CS!I5R8~j>44yQY%~Cj>Gc>~NHv6iu#Acr9)c=cyx@ zlg-HDY6y`4*vh6=;$TeVcZbkGSeR1rJP9Eh=gA!wq22(YJT@5xy~Z3Cwaw%~Qg#aq z5`Na0pVh@ZysXhBkc4efiBSzhauQ3(tQn5MWlJ#<2FcBl8wF;Adr~Qgk*637BWDEx zj}3?zgYh&b5y&kp2wpIe2-DyOSntAw>Lg^fNu5EVTShCiD9>URX?gN^R^qk=l#oQ} zP#V=KzZ4-7x|okJ7_uUs!KAV4WnP~O38MrfrGr*MI0B_Zj4z^cvnp;hskY}PLh5k4BOGO&VTy_&tPaGN{50eWx)5JT%3$BB<1?AY@F8S zLVLyAq^n%2cZ4aci^maVl8`1#d148<+(oHCqQ)uHFebkpLlR`lue0bWvq*(y^$wd( znegDdJy8hP1(6%po`dM2*d>s_uO&yyzH zEKTP?!NQBiQIReKCt#0A!Gs)m+TsiF)p1&aQ%*y`=hOrAXJ@YCgK4~ zV4}1+J#dOm)+FJ{S%M}<5|k*$v%0blG~hro_NY1RwP=`tRmoMmD1%QJ)arDafS08c zjszA>h~jQd#N{Orlhw!97&394(<|1<`C5k_ur}NX7y#}|G6Gdf=E)J9q(_IQlvpU5 zAsH-_0_d%ByF3boMeMbTrCivQiG#ox5?fp`3oT7~&9St}>4{|AZrl_#Qye9lgK&|F zA2sT=gdwRl>yjRgSnV`n-WbaG{aj(-l#d@H1E@}FmN{67 zQf*ebROS?xR)kr`YG6&ANG9l#LCPfJmC95pjz#CzhAFw+Xa>@DGJss-9*Z|;88*b0 z%lkUO5kFsIMu&pLuOrQgEvbdZ)4mfAv;lS=60z+Wo33a4BsqRnKIA^aM*&z49) zX1yDrrpRE(0i`oX%PEgplD0>^PPx)!@Pdd3bgWa@C`8UGOevWmEJbuk#+t#AkTjj7 z+Ug_uCMy5YC0WPJTK^4`N!eL!x4G$x8(n*avRbs&l%HCkdm^ z>r1duDhmPvf|A0Nnq<;C+U5+}`DSiPjx(f%RoFF*N6si629gVs4yFZa+7e>r}5}!6(SNd2|#nn99u>@n`{JV3d}KqbLF6sE&aNe%PFe`Q$ncX-SF9 z2x$lVi8&G0;DOixCX8y+0fbUvsRSpU&;n|%aa!D*R1$H^H6S&^m)kwsEX@(bIcO+E zWx=~)3m%WbF*Xy4f{fClZj%bE7p(uUNt<*a;r9P4cF84e z;_6UR0SE)f84f|pa9GG-Fs;C8*i7U8P>2Rc4Nh*(LpW04luW_ZBPz2r>$gT=!2XyR z;(>w;ALTISpcZGmAcW<;V;neUpj8?*CL)bVKjOecRyPhKAtY4q!&=lJd7X4i4V-jF4bq_k zl;VMeNh|~8hInjTK!voth?3$<`6?=CPRjU6i$fySab1Yt5Ju%rjol#?+CUV71w}!V z9U%kel+gwAsYE2o5@97v7`y?aRmC-mQn^kkSWYKg@lZIU+L2eeR`Et@gm~6p}KWgwN#17P-1hh}8muqzZwX9Iw z%E2RgP9)?3MuiEz-jtN$xf(;!DQ8B%enFb4hRysfH6);OlT#f^V`V6ggPU z`3Maq1&B(rewoZ~%p!{`n4&ik0bDA1THv^%UwJsmSHslzX{8- zX?+N>gMCU#aj!ao8gM5kNO%bXQ~Pj?m6(;dUzFQTJx>4_n8cU%SOXG+D(6geESo?8 zeaE?mm^#6@We!LoK~tfyN)RM;7(x4@D8Z#Iu+RyzJsw`}C=?umWs$Hp84L&rjTR*G zF{9V2GlZ1EpxUXGI7GU)gL(OMF2&AuSnaSpXcZC(TE+-TPsV5kugHQ4My1ozGK&yZ z$&+3ypRc67X^t$zPwSFuB2KzMw1WkVM3`dqX<3=D^-HUCo=VjHH1+7Hl+z%-I0KcuIXe$xa3In3g)td+$9+wLoBghmv#Fsco zqmO}EO^BOuB_mc7W%ED@#4MqMK8V6X5ve4@=aLe4M(pRtO<{tFX>A(9%TMdUY9a}@ z-7duZ)-VJJu*Yjvm}rrgHags5qsSmhd&NO8Mp&(6a7@GVfZVH2L2(j(vzTF&PJt`| zQkzOQ2qRQ%%;zI5jK=D4`ORtrhn0llTp>7YN+dugR;rPw{a8R30N9ApkW@j1%@Tnh zfFW+uPz=|II#4}JAyISOn2HmMsMP4pxRZECGSu0z6<6f$9`2;!T? zMkz0Y%c9Ouf=(t3rjSM9pj@h`U#NBSba9+?#9RWMm7fO5b6)@rOHr=hAprCm=Venq zfm)qI97l|G5^`@K88=%)gab`r2{aQjShci2MMTIX?h}S$35=iQ=(Iein@eSMF+gi| zDyzxGu?9V;%#`pM#eBZVWX%!^ng9tDbx^1$JlZJFXY(qgf~ZF)gL&3q&@XZ$F4Pzh zc>{Jhr1wams3l@VU3{%D;AG?|$XR1%tJT8j1N@XSnRSBs`3MkI=g_N3J%}4Ih+_li zL~nf~&+Y}4MVQqVw!vYc)F%h+xImwFd6WLEPGyv$1U3VY;{gioBaG7*of zW&9o&osyYC7(}Y$0yj+L00|`dJVIU~h%*|!+HG<9Ec$Sk2n%FxLsraaQtFH{#79FE zC{L0j&a74|%)lOR4s|1Okg6iHc7WxW(v@ODeA1tOn^Xcfz)vQX1(}UZHfqf=Z!XAe zKrUrW_PpR`s z{+b^;f0oZI82&@uq179zU}2 zCU^QhX?Q!@O{crl=MLKE)`QcbE!Sqg>DA{}rTVtd2M&1i;?A~8qbrxM+Pz$bI$xBl z*u31Im-=-TTh@B@u({$_-7<=5{Tt!~k{{NMK73A`A8Qf_&(ziai3G*46vY5jMd4ve?{LQdRn`u!vE z|Gubl<+&s7{<+4#EVo?w51LP`+U-At@W%t)TkfdxSK0je-Vgt6i!JhH?Z2B}`KrUq zAtUa-_jfWcS6;5&pFRJSQPc7+^=)zasUa#C;zeoF~ zgPnE%vh$?ki>VS4z15TVR-KN2`Tehxiz3}#J)GFdJm?^LZ8}^e81VYp!e0Fzop`*n zcDE~=(`RCP?Gr!KtX|RY{*SHso*(M;`E`=@CTJ^-Zhf|A%gMRY8mId`IeV-0n05_0 zxz{@WPW40dQ+zbtc~I*5;)RaEmETv!HO=}x96zRMmtVTRdT4raX;g>smPbFWDgR#O z;%}lI7k~YQt=rx2-+TO1kLan7qnn*8wmx67Y;{@wx{F_a{0sguu@9Gy_+TL1w zviF*WGqd@f&deLzafzqv)Vh^NfB04fkE+UzZ?lEjH%XM+q3+eH$s0SoQ^?g_BCCJ= z?D5rU(W|zn_x3is_5FLbORIhO*_F-x_Z6(Som}4QY-qr%N0Sv#H(Z?>%5QS^sHy|? zRhP$KuZ^7jZiw}RH_I)K!2EANUvT90kKwt@}S(FS@53{7w_T8Cb4` zp^!@32)8`LtE$Q&^<%2`r zQco`qJ3S+P&c5tk{-#U7{MWad+;g>KZ|hgHJ8XN&ZGBp4HuWQTr#~?p_y<*zZ z<=>TQJO2KSYtyxt6)G0DUH|6wi__a%VMD zaQEJ^Yfo5(R;=J8E>;@EzyTjgyCFuD`pZ#vyC> z9`0G4(vim>b-B`E^$#u3b;oC|p1D9b>-OptA9UZN@4eljD=k2O17`qhJjLAJaJklv zGaJ{u=(Tp{pasx%$D3DAijH+&boId0(DJ~IZ`X`1C_RilICTc>=xSBD-Te+uM;COx zKg||+c`5(1yz$jf44rTmIEyZQzAM=o=zOW=J@JFW@#z!c9(~Tr-#vM;`QhIZ(6qL z_IK#Qu5VsGctFe0y#!jn^Lk1=Z=?e>_GyRPia+t|{Egny>Ds?7U`NKaqfIcyU-de(r~8#Pn7yLX>l zFf9@UrrL8%-&un{d54{`Pri`Xojm39#&7qyPN>4Oweg3XrB!yh$D*J4&g6RwR()Eu z@`#w)S5mNM@AVC@U%fb#K9D!}V8y}9QVTqyb*OA*B4yccJZ@&mv62)w66D- z?5~>(KfX32-TN_8Fy{AT3%?rE5Z<$8fqDjAqM6gN%d>uG=$-HXw53lvy|rSaQ^m6< zo*d-7toYWh zI!LU~@AD_e#~!)iYBfh%Y50kjPkY98*F&cd(vsG1cMP30tKVb$>Db;TYf|RH%Ar$` z!Z9+tul%v8_YKSPPi(F>mHT7imWReZzs(sIzuP4Bvoi(c>631|pcxUEdTdnTcmAz6 zenR}=vfee;PwhQ`e83*l2*`foy~{RS8mVO$FM7J6;v{;{_>#u_;PD@({2W*~h$C*G}PT-?sa9CH6R7 zZ|ceTk$r`m+Fv_Lbno4@e$zg$U;2CRa`dks8Ch+Nc}M&A-;siGEh`L{D5e(dss0vB z#@9JK_;p#k71P&lIh#7YF+Awyj8zZ2XYOvV(xCCY)QOH4zIbo-9mS#zPtNsOrkTb+ zQQz?V@vYFS=Z}^ai)`N?8R)RgCwm4(v9l{z&YcQ5%X@)**Y0gLpmXRlAWCU_o9$?s z%~-jZYkc^{nXUa^DEH3$Hjfn7D~ng3wWwwz@>azZ&qAht+dM70^;GF#BKgaR)-(N% zpBC<)R#v_D(%uIb8Rn@w%~aH^%H3T3l>ThP5y(K>Y|^-JR{!i{{g!6SrSqSg?~niG z?)ax4)<3iBlg>pK?QgUW{jv3|#2`cR`bUA^uK@(Pr5$i-L~C{b-ZM&y8nheG zKmUfff1h0+$cVi)_x?dsTw>th_@?dM-%_3C%PTH1|K}!RMPqP&sH=!m7mwJ_|!L5ZqZ{Vz5I@o zH@~H}(k%dL$$fo`$A3dcF4p&)9@6aUqu0lD-DXV8n1+upkp@)HXDc=wxg7~UQ{5fp zZh5?IjaGg8<(W(OO)t5)xXs$s>=zdX*IxZf+0)kl*{{9$W0t#bEL%Tw#m^g7kG@}{ zuwAG2Km1Tul>K@@mn9wM&+onV;+pGAmR=qH$@LzmICP>X}Fd(POt_-m2& z1AeXLf%@*DZ{32tD$#ndtoGd=k&Wcg%cl41p7?!nd$+W;%5Q*r7R;)~b>6R3w@Yz8 zjHy-~U(pm_d#0^F%Q^YpcdI2W*&)-OpEN>b-`@tNmo8fue^X`0*mEb3e!TW&`xYbe z^G1~JmkrWBb(CIFRv6vY_S+|&H}BF68Zu;N+0@l5J0`CecaiKL{9N+vRNG#gQlO%? z?XhnTBbC>BkDmgD82~cKtUG^a>x+XUB*8MRah>dN=^6R%NxOSVccsr|uHEcYR_EA9 zC+<&fdL5~USW{zzN91>xzTa#_qwAf{5VP`sm}@jJC$?3adezXl!V8D8KChbHQEPF> zu4Pv`-v8lK=G>-hGy4Sly{dO$UWp?=Lf{)eCT9jbqH0;gaNVS3zyeKzxwVqe`>g@KLJcCA|( zt&$v8{lHfxCo6>?z~^}D#(yfaTz|5;+B;e?{9_>g4F{@T9{5)LKYviQLD%Jedf*qv zQx{r2UNm!D#o4Si z(u|2kgkW2Jee=~;fFj;~(+T7w(4e5ZcOFUk`t8FTMWXg?y8cPPlbn)Hm?`nABlr>1pRXMcXxCWTjLo}VoF z4n8Q{x#e47wL6VIyGX1Zyn~s0vkUob(c;fbUrOgLUOle#CTDu4-Y!Z1)QqdT*L8bq zrxvB#T$tXiTiMHFM|aE)Oj*FaFlfP36mZd{)syFjz2lj?MgpGs?SjGE-$F?DGgYsQ zs8|nJ+Z?&m>$?O*E?U&KQ_JbS=AF#HoPR{? z(!V~slQa4AnrnZZSk%1d6s~hs!GIsKAg0@P9%?YtdCI39BY?ot*6|jJ=LcQJ9hXvsi-h~U9H-qKHFXm;Nt## zzau`6REr8)%vd`2hqCU*fxly?_gnejmsQW+=v>WMRl<{pHnEAgc!-Ebmo3 zOPT~M=j)Pri+{Z{a>0$_;op>OyRs<%`!aBvJF4P}yUP<7TO7VV@1w5Iq9h4l)O(f;?Re#HShBiFv2b$SZ5xg6TT_gF zSh{kdtjLU9+`SPkNU4UBN!D>OE?`iUFa-flQCxJKNnq@p7ujfiL>?>)9@3aHg}}&#+&Bz3O3i}oiF0urq@j@S&9UYxA9Hxa$=S7)zT$bTW>y7*gmo6 z@mC+e_eYFZxA_xZm&o`mui4O*~jNV6R^-oNnt#tOlS^VJ;eMuM$o zV)w4OU|Usn&ytfnYQK6mrAc17L9Ppqx%KO|E^PV3@WnqbsdRGOwugFY$=Yw)oC)r0 zJ)lCHtr>wQSX}^c>TxCIvF0Mv?xn zoNB+=$eh(djSp5WZrzF$YvLj=SDVH`CF%9`=F{X>i<0ZbFFSQ zm1h8@k6iqvn**Cz)W)GQmb%U32F`VtzA$d+uV1+f-?y-M1b`!C%tz3USNRvaH^eT^ znA-B|-$b@euA%9=HF|fbDA<cJT|suN2uFo#P$ zg+JgmM)6K;e7&TCX>Q5YZf9B^mP?57;b%*ORoYH#Jz(-SdY%5-!5NyN3kEN^QMJRw z{Y7}2O?lrOCw}V-$nb&1(N+faDap{)GkEn^6^~myRk5Ue{rcaPO0->jpLlttLA^sO zW|-@B`ftGRX4Nac=#a^~Dh@u-VaU>x=AH6R?JKSAQ)+%yrCDFj`A2Q1VXFB3QMZDN zN0yvfbZ&I&`Y-W)1+!wK*vgXIk#B7reja<)EtRJ8y@t-~LfOBAqW~5u$@ng06iS`|Ox^!fdJAb4sFJXX* z7sA_x@0fV1V(F&hrpCebd*^-FG`zL>yeESS)<0UqbuU?R`oo8RMl+1D@&Uj2h22Kk~^UXg+mfryb3&xOGSMcKg#o z>gkXh)fGLbb?ukcZhO{gfud^Q=aq9hE$CQj`lMc;j#s^&Z<%&uh4zc9(Pl+Q&@zs3 zou+x?N~f?q&Bubs^e)Q|-*!8`Y}meF>A|myFD_^`_!+V!zms*)99N+&zhUnM7JvWy zZla+E>-sxGd*H3wK=`S_?D-(L_ zeD1nus-e}pOdodWWW&9(RvJ;25cvH<+BVa!d zVyy{?`N%=`y9M;J!Wqp68X9)#*m`r{*#57fh+xypM&`05c@4;KDrt6HI6OzpRNQ@i zzfSn^@{V)ENqfBUJJ0&P0Hl=9?^^W^;YdyQp<`Nk7k$2bb?ed_lV2}pBj&jySAST1 z_EUqh6DQD)rB*dL*K1$vo@0vk9prshZ%9eidHd%qscwGJ*lk`1cz=PtuJW!zC`kD#p<#CKN4&4Rv?kT96pr% zcOriv_mk!Wk)9u`?DA*Qb^9t-n*0adUsPPK#Rs)2yo2#v&U0L_0?;WUDo<|yqr37| zujGL|{-=M*;~O=fU-*9Df+l5y7POkS(5@b#n)ZP-z8#aOHx#hX_$MJux z=~A`kdG!vBYxKn`b-PwS?Gl*y|H9Y#>p98();5h~$&o%DSebV4x zssBHlz(PjmPDDD3vwvCBpO+&*WAW3rS1SB_9)Eea`#nI+M*8Hn-%bBd`R2xHo@>nO zHnitoUikB}%}hXi@74VMZ%=nx<{B?899QGddHiLB-5{fyKl76=e{h@sGO>ZXK%??y z-FW%GyzuYK*(`vF-S9V6{!W79a*ZQqVTFHt!ctdPZu}zl%ZGm}!938|=AP+?N`E`0 ze>U~4PX4p0@BGw1mipGJ|DRjx4u9e2+bcB~y@zA@Yt7e8kF zb%qZr_xjqfj?-V!dz8)!PiHkd^u?NH2W@TD-7i(D{Z;Z#lU}@2`UnzCv#G_WYE^ji0DeS227M2$24>s&z5kf4WbTz`0D1pEUe!M<`Kt!~ zvnT)W+RQ)N^^bP_pF`w-wCf-3`bWF|@0rU#cJhy%{QucbKG-|$z{B5#b$eC1Y|G)W;x6hy4I|vFJR}OryiUXA9skpkLzW0Vwppx;YIpQiG zb3O89&tF~~*6ik^lSSz_^?S3<9_h15YT=C3>fH^BHd|ipe)SFSc~Rpj3&%4PF6RpR z*5_*2K%rH5cRg#VMsW5x|9syE!tb<-JwxO~-e~aurPKG`=-+haN>Gk=>VV+<&90w< z+PJ3XgJfRq<_9MVLc=9LPFrIeEgUPD2I>L!@_+Hq%YPPLwY&b~A3pucHV+@Or1QFU zRce03`Mz-LQ`aU?9QQ4#Ggy0T!If)GlE)3V@s^g4!z)EUzIbxN+4$9=lWSj;PQ(x9 z9yuM^bimp9@@V+x>V1XNYX9DL;dGa^S8~!>Q0w{AD)-(A&EH&^s0$xJPL_gW#h+jG zS`_H>;DCSvrGaZe^%i=K*nJP=+3r-FSGqR0=xc4pOrO~38Ym|nmaANPu<^&&FYerV z9cd5h-(rb5bNB4p={7uF(vKT!I_pJ-J^K3fi)iTBf-#z@ydSk)9uZG|B^rGko4MI8 zZK*sreYa~@Z1bs#Esi)s%gD0)>g&6`e!BAd$YUx-8WT$z!ak&fEvIP z>wXEg6SR9iK`~%*-ILayv7w{-k;0jot5g1Cfx7YXRm=Cw5Xs!&Cb&u#92H(EA8(}D zbBCorD``wE>Z-M|ytxzO}=r!)p$N!I|ZZ=<}9B&5VvG zK>1J?P`L8znOM6Oo8yl+Oo4qJKTy`D!GzZ43TD^sX%woP7+f^q)rqYy@2h$Q=1&U$ z*lKcV?QSm*KWaB8lq<=5x@=C#^fpUB-!r=5@}hp@dVW@2!)NOBEU#gh+nPt5E zn<&@QqxQ^!R6lxDXcSoaBr|!r5zjxaNB@lvkE$AUZa-%F;9+~s7W?jMdkP$-D;pH` zg=C*EmbZKks?>XR&Kx@u-SmU9w5lA%7 zzi3Ns*>!JcpQNNk!M?+TORf+4&4+aPx);5@QsINvXCB^Nc>E4sGO+2D;xP{a3|wiv zbpI!>O!-fjEM0!RY1hFEs@$E`|M}wCU$yDC*|bpm(~6>QeI6c>X#}HZ|M(g{)Y+Y@ z1Kzrz%C5n+I<{HZ;n9Gd?+Z4N?M2hN^jWtFpTDB=GIC$Z?TgHr4KZ}zf$F^`K5yJ9 z_3f<j@oGOz6dP>}2e#hLnA=G~`~CwpBRa&C4#2X}7Gas^b44uYk>MZYSURufE$ z*Dd(`#o_hQqD{Y+^iW@}EjZE6Q1eD~Fn9FP<41oRVAx+fHgmM_WCNw6`ih&~`>g`U zrXN;Xt9*!lLcKqJ5f4^QZ~f`P!KYq>8T1-a^VN!0URkq#yeX3T)hcD%egG0Cc>~+8 zk6e0saZCPqdBg5`?89*jYtH&mE8MP`)^zK`Itywxs@5gX*m7K(8*Kl4BE^B%mmg1VoZemYg$91__dBa%_Tt(4;0q zOP-DId(-c`_p7Oys;QZ&`;S!?efHUBpLNz=>silwc6XvWbOf;6qbMa+qgDXPtGf{c=DQp!{+OGYhoAseyVFtleehzTJx6d+Z6;~9!CNSWP$O9SSfuljJUvRBVW>4$ zYKA5&S}w;!GV2Xv4E zL6py(ykd$vifee61@f7@@H;S{kNl4h*6T8jn%}+r zMXQFou23HR5(0e9bk&>#U-T1$s@Jj*L2<}I}xc$|5n@2j6ptM?sV`dqz}Bf zvLTb)__AmQsr=Qis*|C|37O`ZWqLVszqCHu*c~m(_q--VWhTfi2k|B2YpPZW}ozCZ|x(%?UKGKxpzQLw~c0I z`l5Ll=4GUfD(}K$L#-ahu6=%=z;$iE&qozU{6J>^G5^aJEF@@_a1Pg^Bow)qM{uB} z5h-h(rEf&^)coN{zD~cr-wD`ukbq^q?yEgKROxj4erDcUf((xjUatQ2Zl?i0lE4Sf zvIzdF8K^Y#sqY3_AP*4@v$9f=Y&za0ZgEd(aj&5z5e5{z(>w}tU@viG0P z2JKB7-dZF<ks>*CXfBmI5uHZ8AZ!FF>c4(jvOICtqgY!h z7X?f*;UrOcB~bDik?P54;t!P~(l7!9&ke=Su7k&n5Qd5S47%}|y)@=GmMn)>ewsXt zrE018X*VB0#=$bQA{{IYNc!nL-DDH5C*NF7Smmel!w}d>(be z3sJ;@NfEgO;#2CcVy$h(v}LERIu1SQco5YWB78VuW*BSsDL}KHuPq;Eq26^*B9WOH z@lJ1i&Imn{*CctY__hC9Ej3Pxv^K?%_{LPYKGM2H`w75 zrknQWM~@nREeLd6Cx|?joGUV{BM+5o_Gn4^Ae|OW%v>AT@09fUhpzcCR*&)i74=CK zeSK|~MY)4pnw)YlDOP6|Z5vZHHDYR?VZv-unTt^3l(lf_p8G#B$8R{Y@)Yg{Nv_d{ zCE^83)e^FrsXj^99YDN#8EFN=V&@iH8jirD>(9!uD8FZ)-z9Q6;IjrBJ;H(r+rQ9; za#hmoYgVt=nFtUuDgyyTzd7m3gFeIR9A7t-uv|yx;6>UGmBg+2k`4hxOi}^)8-3+5 zun!(hGl&@o;ELt3B|PF|yREk%d=4opBRp2uVXvp7>AZK#Xq-%|Ic_R*Cw#@57LlIv zEqXEMd@MASMr2$9B3|yG%l2C6!4vf!BTm(6xJEhG>tBgBFRx&ol-y{$W%@ z{#hSM&6idpPDgSzW*o42`WW)$8Pwm}u>-BmzRxD(^k+r!*tI)YdNObCWcW|(mk~KM z<0zG?=YfaLE&5Dl@-9p4R(Ik6U#vY69+ouTF?eB$lS_W>GqoHIE|gDWS+zPd(uFos zcKkucn{~@zVIuu^ige~%RyVVy%tvi-`Oqv`=AKjYiUeNr^g6?H@0`v)nH<@Ck|VKm zH?*pOEvWH?YT90Q0yznlVE0Hc%FFfQ#fE5`#S?qWlAm#gbkQKV2_hijF6P%b%6qx6 zw{~i&i>qe6ij-lZ*(-bU@#F*%nJ}f_%h!(;z+0x~qv;bnE`P)4DBUpPAQKu-4g&H? zslNr}!1Yl^t^iH}6g&4Fx%fOzD`@0mtqZFxbBWeV6{M4}PZ57Tc&(CZ#GiD8TuuA3 z#U!zWC`gLvYm31!O2vo3_gk4&iX(6uaeeXWnW zN^|Ph4W@7c^0nxt7sv5!h!Fl+Ntz7dxuOaWs;0xh{z3QHmjA|4X{_8*sH6m+_0Ja| zezn!UoeH`<%pYE-Q&a6U{61e9&7-^d)x3a6hw+A7XXK}P&;VA;f7?;6xQV%YTO&)I zhR9myDf$5mM8~b;>O2Ota=20xXO%~Wq;gnyzzq1m+AJHK^@`@x#is$S1 zQoXB}`vzqs%N?=kn;9QzDyc-gsvrFkEPQ;eFjI>_c>4{KM|P5TO@|;rLWwXbU7tpu zj>~rJQI%mm6;Z3dD$R%$hAvnk&s#G`ONU{oX3F#7ox}=am{dAwChKDlRl^HWS%0f3 z4L>MMFVY~0JvO;-q)ZkhH6>zQ-pA{LTA$a|Q*~@QgTnFUw?C2djYs_6g&($q+$JVi ziuJT;rpuo)!2gT3;zI+Kmay2UhxnBnnmhsf@#j=4jzRJ7GgD3K*FMTU9V(LQW>CkI zqC0y;tL+z6k)bsyZ^LR*tdE^%%OIial4@>ooRHC^CUNED^l0?jv#;i?ncMGjj%Cv? zq`#MO)mi^cY~vqS-!=*LzFRpyhc6<0-A|~3L_39VXw1W7pF6$Hb6EkIvxN$lNFy~R}5W27^l zy^$CuBC)qERDA2yGbgtZ%Gv0I>{$P0a$lDgb(4yva-YHP3{uUc=Hx&l8gQasYIwKn z_Biw4uYHqT#kADRR2UeBpDCV;?*boOKK&ds9%AKC*1RB%EtGM+kDkBh zAPCH`s1%?M)p0SacZ>8?t&G@elTCeSy7z`bc)nZE2_+X`euAiUHN?yeD+}2-<_?ib z9)G;^>UzgugpClBRNB<%{7KKYqlV4BI{j$O-m`MjS9q+4#h?c$UdirRI1_@HOYQ4R zIwD3#gz1xor?YkppIJhmOVF0)s--{2)?-78_jFtIewkmxx@_>8OdC65UU{Bj&d}Uy z^pHsfIm|}9Qn%IU@+_j!{*h*i6g7}cF&A3(Vnuc-D!i!3A4aA4Ie<{FzQ-{wo7U#1q)T zFI`&1A~)G6P`*9DRA(!9fYkHhtl;W{$QlU%Usk(| zpKL-nBCRe+nYq*|86F>x(teQDRPcBx*e8?N#J6c;;D_W^mnszISZY9Va7(4_ep!!y z!APg3WCgK{eG`$OlnbFJy2}(It7)U6pyCIKa0!;WY~1#GDe>uU5wqdfD`hg*vl8aA#$QUH}W%&owXVfbYj zSP|CPDw{d zrJC6If+T|{e9%;ph^7aB{JhEz;PS+(S}GnoHA7-$ z>kCl_-puELvH)whNs;%yd?IkQ@SVsUeqU<=p-o7*tY%_1Ez#W$PIk+aAn?amUU+nB zT&Th#nJ`(+@%I{2O_$3uNJ|7XHm0(NW{sy8!7Jh?kYZpBH`Ygl|G5;_|0kBB@@{bB z#VT{c!Klt*k7Lv1T3CYa;s>@baA!q@bSF1`i?aQ3LJU7=fb2e~8z9Gx{Vw|@6F`If zM69vzk>+=IbECJin#W({Od}u>ds87&fRI((cMgU79391F*}gD8&?;zlzWteBS~~20 zWDbZ<1tw*{n_?U`1T-Z9M>i20skBC_A||@XtBdoN%=%61MOC@fzF)Yb zd35w9i`GVapmSMnhX-U?ilw|V50-qlYPUq8XP&57uU~ry;|Ciqc0=pMb>k@%5HP)o z5^Y|>V4Hx#N6I1IiR0P~>aWEBBn1Vf0wk!=xGa|ed>IOqB@95bwgOiN$O_{dj@R;w zib3enqYcdK1cVbCAOLVGW(TE$O=Be_Xww*2au|V(gYd&Ti<8?}Xy)8U%r2cw=7F)q3mWHlG&mNAa z_~}JyB}`D7Il7;@ZcWS>c^pb(_NvLKD@Vs(^qn7_P$vkv7kS$cekbheu-AGEwHaKae;`Ai|1DU0>O_3-JhTN^mD|J*W$Fn|LGxh^v*OKm4bg?E_ zpc@X365s>R@FpeGso>?x{5=h`>;By6Z8Q9Ss$q-0B=kCG6SPU?Y@txF&j_TNmeXVV zd9T|%?WNPkv+6Ak9Q<@EIjj-A*#*sI2l;Mx(*(6!Z<#kzIbcnMD2%|=ak86hrsQn# z-u=UGk}7p(vtBz6NRQS^1?S*@yUd1>D@8KYl@6#xRIkDt0q3T(#C!WY1^pY{NJsaU zk5ezv7&t}$7O2YkUR>kdsq76L8m@Dz3>)LiAGkrn+^ce-fSaf7jl7Ac2JGgxi8JFX)XN$YFX*G zse~se;h?1f^c&7h_y4ZEfj+iPRDN;e6z`1d>@^E5pEV!$^hp34&*-|{22Bbh@fN zO33D?)w;L-a--k#x#7Zfh#~q!U=GQMy5&?{IOyuO4$&vT>`D7@z=ZFn452^s$AQLnX53hgbSnqVRw$v*aF>t?~<$*M>x9IOoN%SzcxCrq&;>A+qw zJTwgUih5qUK{XjlbL!XIZxb>=V_-Y)qo9CWTRj(ZCBxkEvi5k=0Hjyo z&DUWh7*ODwD$pyR?zb&&fEQK_$#0@AYrnp~=5a84?G%o7dG7lFu&SN|$dwH!gJuXh zetUCeavTT$ffcZx+DkErNl4BGsLRb!){Uqu2v7j673ssRfLXEq0m+#iP+|;wm~XZF zv+EE5|5L2_1*SmqrZT@!Q%jN|FGSU|o*I~Pk?d2;LkxW81F}X=13vJ@vSY%zr$1j} zq*%wV4h8p~K0z6JCA)1nfAZNI5OVcraJv!^NE@I$4lLhY!M@}p# zJW6(Z-x z$tNr>))&7M|gU7rFVY!Dx8F7hLcd3fQB^X#E_>0z9eSZ6wbmbLCzKDB^ z9P_d3$NJ+4ZyhfIY9HYq(Zu8$9LI*G=UGcO{lb`drIT$9+uCJTxZeq{cJXX|^(X|W zw#11%b@<%CXaAuuc`segX{zX8dCY6wGv&(FbYnm6j%3)=$=M{{);0FhYWvaGlD3nk zW(KCgo+;_Z9!KmaJK4sUh2{!F_o=C@#=S@po*gas`nKelgn|{UB$RQysbjrBpSC{4 zbG-x;E}*B1+=OO`Tnr^3HhSHuOZ%Hn+efw*LfLJQ71JZUGu3*rt=Z*`6+FDXPLq(j z<->jYz1Wccq?2rsqYbvh!@6Nmu0iSV^^LisIGd)qv}yvpsUvgrzjSZX0Ew`K-JusH zAk?vbE?6A579{0&c2>pSFj}wA;P|n2e9YL^2<=}C+Qe^)*yQs#*dgs2YkYS4_~6<| zkr~^B;;Q5Z4;1AlD$9Gr8tjWb*i zg{=tt4RnNP8G%^Rs?qULOq^Y002!S7I(}Kcj78(u2i|>mkcDox8jp?rwtS%7nQ?uA z$_qm)`PT*BK5V*-#s2!fvgihZ>W#hqR7IEaKoB9l9RNc+&qcit?Yz+!_uqz*^OS*T zWcW9~pt0?X0!J6{x<31Z%57><;^}r7mql}P>fDEQmisG%MYH{Y>9Ar{2g=EYZ#TgA z*oUG41=x~H{=)$TRCp(@5ePq?dtzW;8Dj{YG~bkPZh3!mtjW*Mz1M5K5G9pQb4|V& zXx$8az^9DATgJ9)X zt1Y`YxW%eb`YcF87Yku0Ki^V9pRglwt8R}O^vu4VFS5((Qz%xhyhgBPp5l{yq)6qE z{a~)^y5Z-V{&koAO1@c35tWn+m;Ftls|!m!^;F*i|Ps@b2Kp!Lg4Jn#p@c`&uBo zAQ9=T$IqiDIy>*69!nkN6|j`gQG#wp5zBx4zdgNT$X$8PrQx4BcmVEd2p-2FG?VEx=&6 za>^!usSN`V^a5{;VsC}bX!lK#?q}+}>H}9JWm^z2Iu>i6DZMvJ$8t58tLh)Id@Nit z2mF9fGaz2jlaMj}%;j5Aprj{nnFx6f?{uT(RKKpiK2|tGR0&uY#p*KaljYfz9wu2( zd1;VYij?a2#;2SeZHC5|2zt0{>6@N&WwqmHqiNZo#gWy%+f`DX+ko_y7;UudP(OiTML z=F`EZz=iq*8aj(8qV}A5T?Crx6kRh=FQ_3#6oAn~?OV2_oq$;ilcKo!!UxIxWE8asUbg*kPT-=05v zfrdYbP>B4wQ$pUCG{%5c{f=`hI$%Z2u)IL1maaF?EkHpXS(|;5<6b zC<%f};C;oS;0^ zq4SiGYPKoGfR6Y4h|De}nc3pRWA=XNUc`vP3X^2jmz~ zZK|=eXQ1@+8s~t{2aB*jdR16I6vFE>oqpIok_-2VQ*0n^;9Xv$g})rmf)1~o6r#Sv zHUdLz$o|E_Mp|S!&NUwH55rm_j+7L-YoTZxZ**lGGFa9v1Yh9i9d}(CB152ZHEH;L zzxI6+6g?%NwsHx&>q!y4Z*u@@Z0@MMxhG~^1kqk9Ji#MCG;Il?MIqq)3YuLC`cZ2N zG6TqrChk__LuH~00h2+9IZCdsB=^?=Af~OiWdT8m+ViVl^SB&AcA!!~>cR-}-?b1a zv9n)Ml}L-?Bj{7S3A>W6>(CY$^8|ifFOtxzE)3pJ)zqhqtWN4De^ga)usX@iHen@G zL9tacXygMab3+e|y1D;&i8FN+hpC+NJ?qndI@8_2q-HaOydNo38KfB{TX+$3X5S*!md1)Aq{;aVs zTTDG&nQjj2%1B?0S_Q|IdHD1G z@K1*7_e-KNHGUIQ37fWauM;K*w__}y>xQ!PI;BOlQCHgH9F|ed5V%6B*F`&!8vPbf zsKy)Z)Q>C_$rKk+s$?~9@q+R;$_^Fb43=)$4N>s-7KFkJZM&uYGlwpvy-==R{ zu)!5MW()sNx#c0xOE0e{84*rp*K~0nh^|$MC}24lXwaE5vac#naPS_e#q`>le1(p) zlOciccAb=xX#Zs7x4DxrGgO*1MH$uibjV|!vmv7p?ps&D@^pDq!r}E+J>LwkebUi% z+93v0T+IlH0SHyMPw|U6X$IDD80T&+fFMF1EWFOv(P22=i8J2FBdkIyVZ?rL`Quh@ ztCvDW!mF5#y(TFSk9{yx*OkW0LLKY7jt$)#ywMx!b;z0yszu+iU2b+s4Fi{$7<5Ca znKRcLFX-m0xRlr~d3D>tojVD~FPTKni+VV@&3SUi2H}D3kYdU*R5G+D;H==}h-?CF zM(teuFu^*77nb&=yz#WVAsdcZ%by&<;ldVa1zGP8lD#w-v7l>IkZpdLYzCv@)TE-G z2#7a)nibZ8?g*0V9B79*`$xvNeF09Fk8LgIPNmItxoR~L+OuNPAZ{Yta52#+{G#LM z5{2o$XUCJoDzDTR0|}@%*KV&~%eT9}SOdh+lzL`HM*5>4YE1X*J7+CH=IvMvdw`DG z#%x?k2HjY5zdoIgo+Lv^zU2v}4#+8L=^}G-MF-s86}e3E-sM5dW|`|7`yGW5{w zg_dDA`=^3l!f>V$GElfE*#Z2TyAX?k%)^{QO;`sF(NS1-HPF66RT2hkR_kFW=G*9t z!n>ZYPn7pJI0$XRCb1P4f~BHUd1hXvY?S5eZHcV4B{$#;Pg32#cyV~o{KrPUBv2lW z(}o}F=UW(WL8q~y>z%!GVZ`AAoq`)NM-N2y%8M1Za(N8Ac@hqf&!9G2640ee*k=Mh zBcE`}QO5Gqa-R+j^jFCJueu7uhqLtbvV3!!s@`XPy+j8XrU++$b&sy;0SU`Vh>SUJ zx*DFPe8cI!J^Xvt`XpVCJ$iPStE@O%%z=K>tF87y)Wfu5FFCR#KF(0*IZ5T75E)}% z{@GFEyaHMxt&nWHIRFYGb2&F#E{&UF{?rl}H!eccDTitxRAaV6jhJbot*gdhjTKMU zV34!MeAz&%(%8snlGMnGcHL>HtLRImes$3xF=yi|Z%RLZ@3S8wQ&WXxhF|Eh8oc@q z;Seh%db_O5njoTbG~sFKOU$e#^X=-9gRceY948f3OZqyE^#0*9J_%zStt|f>B=gd# z@izj@!Hl_urF4io zQ|BGL#Ns+XDb@#6)d0&sLn9rV+=|5jZHU8Q1rU~>vJ+@%(AwV}Darw!+dFGr8!uGl zSmZ^tflwt6DD$aX{*%*=50biqGfJ%S1l7gaXkoTRkx<^I023S!uWnEFJiRY;zTJCP zeG)u_{wd0A{v_PnDKW{{?)fkDL}q%D`)UoTQ9Q3riw}n_>X2fqJ?Eodem+Nk?Eqd065kh_8D}#Mm^@868w~`)88S4%2B-K)y_Ko*$e9k(Y z`q;I1HxIFOEi#9-Y-y(vU>N|rnH}>PLC5Kxh@i}m11v2fFFFRk`9cG$qPn{_!^%VIY)6tLZQ#hp`GXkAw z1d#hOc`g~ei|A5#yA8}6EwAL>W5IQHJnB;90p|){D}1_zmq1g_{0OTLcBH8+v0gH9 zurpG6xYyrgQT~p>*}7)Z;e^VOIJx_^grQzOg2O6EN=xlgKZY>4+hsPi(FRlt(r{qo z5?XYT@EC&ksY>Ja76$h95M=_hWZx;l=1>W7FA6bK}H=l7wuU?@TW*8BE{``H}a-atoE)-AO0c#SPiBqMDAARpP6 z3Kh_AS8(_xWG@-CJsc`{mbb9$a{6H09fvb~#Q86uu)OG(?U@PZUkJiYk_{+%w=hoR z8U6O>IaObhZ5=u`_Z?HD{C(*opjIaY_~n0(A^<~Ta(y_0JHWAO&b-c!N%`B-P-C1q zx3hn5YCdOOdl7YX*Dp%ZH4B|O7At0Iw-6-{{_>5}&-t9Chd7(|^O@Ffw}}z=$e%3p z+BUkmB%Gn`kiLtQ(=~ktyj6q*v$1H*XBUoA0LQKRrs$Yi6&!5B^lH^&&lCzzgQ~`rmj&d#+n}Qq zS`FZ{JAuQ<{ZA^8%~bVl<*zlKaPQ7Spy=Be^ME9$xwC!&1ipZidzGe=(xeQsisMwk zYn;~rNsF`L5X#p(@*Fo*&Di%KiN|_utf8nkWt_>Jx72f~(%o)7iEHvg@L~t2*sU%N zTVc84h5fMsj4{(@iqSqw8>cQMhG%~%Frud5D^0@ckT3HTjF~!_Ue-IYF{){(g-Kzhdix)0g z4nEe`Ix3&127I!}0b8NtRnQRe;p7$7^lrJk<`2P%r45+D2PD%vZ%^0N_$R)Jpz<(~ z{>A1tw$g#WL+vV)d!tlZs@#{ziEJ-%RYg zQ46G$H44)Pks7nmrlzN8X#+1n+C|3eawJ1XYclArz@l>gg_MR;N$d>66rV#uRQZkHYwyo zj-3D6EWpQ>TU^dj0sw7OY8s;HlkbjO|tuR=~%Y61?sKS zhe+R)vr`70)7qVIA@fje$C~-;@bPe=sg(}qSGI(!x?xKn9SrRe5n}pLNl@sSedDax z;X;!8gb=k-)iRD-uTfz;TtBKEx@ESAZh6U9Jzh0eRwLpyqZ+54FbA3=(AKM~oPSmh zB4wx`by3(#D2Mu;c83IS_W9bKc2A)n~+dBNb8`^?QhN0A(W@NN;FLpud(_@c-O{`hP@|tvN29|@z@8k&qZAW?Z-^ZS(8X2bL6GW zA#Xs)kSn|YqqSc*P&r%ZoQT_>Tr_}5s;7n2z?IOzyg|`W#s2=qB@i3wwlRg=Y!Hh& zBio=MEy8xifOJaY1Z~rFdR&*kl+M01s`=O}{UBkgogL*9PId8v2Y#FvhAvWDMEfgn zrKFoXwtV>t-3xjG-ROdGMpxc$fT!!=aoX0MwfjP?I(qqAE5kMS^}lDfDlEJ9-X%-g zIQFxe&L|MsQ9Vm<57Ty1=)0=MrW>D?>DH`lA;}@udbf4V!IB7eHM#jnOMw6PN4w_( zI01>6wBjjHkX(^ic2kX!-5)M)s=bvO5~77OV+a~z#>zFAF}C^2fm0M)mLY>aPdCAn zX2xt3uoai(JM?G3@~(d>3m&m}eO^=8gc04e9Hmr0qpcKu7dVlM~(Y(xmT?S5xkqDtwdLu6tUsZj~dmyc|7#F>S6lxnoO$z;7W2u*hMZY|F(2Qxh9oR zn*1DHx5u_e1|4jBGWW%8x~~s$m=jsF(5d;7s_~my0eS6GK$+`H60@6lTotM};Lm8u zZP8o8VaT<*5};r5k^P0N_vOI^6b_xQJ+$gp(n9S{f9-6dN;_ZpN$)r0B+I>@gpTXTx0NY z_}5CWt#^kOl_eB4K1AA={M?93@hdGHw}zQ*#tydHH-wFqYp+{~GLzT{Uc{=k+J6lo z>+X6Hf4Y+omugU4HZ=!XC+o96qtRShS7_5$=+52Ne4ZqMTvZJ<@fgD|?k;So^e3D|d z$W;Hs*B2GztyGtg8?cV&v(s#*ynmAumcOz2kbT6hvlf@KSB|a1(BteYz$BgO^ zo#Z8Dkjsw(io@tvO<$1K#mptf{S3L}5O58sGHV4(32F)jCwX-Jp;I8(^pFCzu{mQO zND3nXmFaV2>@4fv+v0iWo=Jd)x{C#3C%}lQs_w=aBO1;JxcjHxW?N8^wqEU@yEt83 zBbniGNJO3~Doj>{P9A{tX3OWaROr0NGP&&f!8$UPkiMW_3uao~dV(oeMsv++_Fe{w z*mpO|NIx3(EOUtNv~AqOeF89s%IwVSCh!`Sr0Dv(0Sm!UB*i4**S4ZPknhg&5Z64$X#3csAwPGJqJhl1} z`_0;thi6n19JrteF&up+xYOoYd3_{qjWJi`bh}l%$@h$vlJHOOAPzEhLApq$wJwOt z)REC4;8o+sz9MzE9(kbKj6}-mdP|cc%H>p) zojW4@j-D6*TF1tRX1=K(3fJq#TaeRD{5#S@t3gpSycnB#M$38M{p8rPhdr`~-YF9u zq9^<14^lLq*xP$^eqGC^_UjIj>*KYuAQ0xcaL5dJKpL6zsHM6)be|B#b2oSjx?;VU z();MBpa6S8R`=e0pAK`l@k#II`?CeS6+P$x13CI%9H=~&CkCtK~#ev-3{^m|%XQ%n><<426 zdLDWcdFxx&DL&_6-MNoeX^+y47foV&tM1%qN;p1r4PmQzw&ZigdFJ-4KXupp+q zxCstQQPw?U##8ZyjkWAr#cP$FfV-4Dy1x&&OTf>Q^nQ$e_t0BLp^u@h;Iby`M~yCS zIxnO4{nZQ`QZEM$z{0lL-?Ouo5|-O5L0!KVqNVk^_RAB%m6GHXLA3*HosG!)xvSXO z>t)p8jtuwj^50#G!dGm?Q*G>9xK*LYFE(thtYrQM%rzoA$qYwDy|&)ncM!0Sdd@bXZ(F2Zq8%YB(|>$wd-9_dHkR5v z1m6_QN2)7mp9$1XtgF(lW3u|3r0Wu%B1RYs9TG%PGVVq3?MSD9c)wT)hCB}Rt{{G7 zPW^J-E1h*f`zmWbZ%PNLekR;d&2K)bkAuH45MAd&aq@GIv!Ek@thRuzGBOUo%deVs3v4=_SAdTU zDQICv+9(5MqpKh0M_oAy+N%zca=ZFeItjRND=t8J1I&;2ddh~EEP{B;2hwQ`5nI;8 zMg{z%y!DR?M}+;)?*y-f*zKN#{Yl_5`-{K@fMxa2->f2l5+_N?6Vdf6B#QR!R4 zEykBFS!Oo8%n$+cOMy_rVh9b27*cf`tah}O6p2!3o^y3k^OGS3|UVxDz~AQae%8urHOpaTv#HLF6^wlYHQ-)gL3 z-TvcmWuw_1s0-!Vzq-{Qo~n- zI;m5Zk_@|YLVECp-$c73;y;OYP~ekBz_TnD)`D^WMryjGhz0&TiWtWx*no?xYR>?^ z6{mSb`4@?g`TqimPwi#eB@?jX_t$jE1RMv#hX0Q<0huE^Np(|4W|*1)*j+xe1>W=?P|mnu9MD@p=js;J}ne#Bv5hk!66NVef;^{&fN_bK;*|wm5U+UJS*ccP`rPx^J<145A5tiR3 z0qLED>04_$bw3T_QUDE-OiB%u8+#PJ8u1-?li!+g1Oh3x4%#1=wD~*1Y5PF;O#XP{ zIm7PawYD0d$tJ-dA4)(&lxfZ+VvNH_(f{p9pe)H-f;%We@s3xqm)G9^eXWPb$03}c zJ(g87iYNS@qCm~EULf>)5SW@Nc{lXVuauPBz&|zK{$VDu%)c;=M|LdQm)PeU{=AAeR)_$PEg_WDa8~$R0#(g7!D+|*Rfp<`s z@5%JHo}S15(9<(@18t^%7xe#!n&+R2epWYVh@@L7^Z%~5`AA??2o_4$|4#S6f*e76z2ckADd`vEM&)9KPb&z1R?3;)0}l?KnE zJ=|<^DNK4A(NO*-d~NFZmlzksonG0=-M>yUG!{-`6h9G z<$mMsr}x#wDon7>s?DEx-?^b~hXn^?-kdIo*^|@5Bje2taDbK6n;Uno(1~LO{Xs}` z_0Ru&Be=p!w9}eYPxL?j@V8%yt77HIGUT|bKK?gX|NhaBz(4K=|C(1e3jW8if4lnk z4QW`eYBCUM3bNe$*L(ltN86HbLZnWen2Z0@J?@ZzY2IX|B)RqXng8SJ-_P`mR$Q9S zw>nDaKi%U-2$&{T3_k9M|78*W8tU{;DjlKNbQjxyx(Ajtn5Mrx4z}b!FX2B=#P^13 zWDxb{&zS#o4}Ur^O^M8R{8-jj7p{qX$5<0nzgEmIHR2yLfB=Qjxv#KPAMGX-Cf zk5k;J&)IwM6V)k)B7(7JxCAq(1{2JR8SCusWHL_2Fp?P@BM?{mf-tiOsBa=M$RDP(&_h*VL;1X%OMFZwl z3`r&ZZwK&J{^ollua8Jes+P`)JDa{7PJ56KxixZ`XE|>xZjg|Y&^{Er8?5$_=nFDVc@KzZ{Y^~UbW{}Euk-@d*4ZE z+OFX68CyQVe`~t@MtmqrQ@EZG96dy3g>1TsL)8_)aq|@X&{ax^CHP(E2r+`3h=o)RLp zvCFtFb-Cfm5y^g(2VL5zJF4RpjXVtu0?)}wys?tsx6>{t->MC>y6rBe@6%3YjeZn` zs9en6YLG)Me7Tb00{JPIqxKmQ5Pu)NkVY2?J)+@|LC4i3d$!O;Np&AbBwPN<6ni3ZkK{BXs8xiH|i$^eZ5oK1Q zTttZe?@fL``Hyl2AI#8V&fwEGxKdtX6csq%rgcTDiQf7y3J&I5PA!hWu!m|8s-J29 z$Z&b7d~K-a@gCh+jx5TwZ+d+(i!QQaS1$ec238_(g8ba-RJb5j{H0W0ujwPV!f2G) z@M9-uzBBUbH!=!>WKPafUA2T8 zOB-olv8lRYI!bVVT{>NT4+BZ0wQ04C)=eNWsyY7@jc}wI5$l!@afgxTX{a#Gft8A z)_j$L95Z|EvriB@r?WN@P1}Xg_`Yj5uXkX{q8?luH*?Q$IsdF8h>B=v^khm363=aN@)_}6=o*OqW~bGD{9{U0tv0x}g{w^tKW1jH|r_gW288itxs3w@$@gWD2>LK1(67lLoK=1xPQ*Wz18 zrr(37dUNA37A{_hlh+C3>*H3Mt1X0Az%Z#@eca%a+ho4Bn&`cJycy}rF?%1xPdm%u zbj+8otwf$iRQNvG;cTi-pKhjNyRpoVp|1uvHi!R6)-t?#rw1(Xqialijtt-GLx`rc zX;%~92|N=-{lQh^!G2|^hM)O5m=ugJB>t~St#@qEi_qeYQk;};hCaCS7IpKzVd(qx zKz4GsJZTeMCUHT_`;TFM^k8!CQSV$4l(xJ3be98JV*Tqtt?P(pL>DR5IY+?>QTn_3 z7E=a`uE=)^BNmbTp0 z$oS@=5#5iHmLkjVJ4s$;nSVuYj}@E@x#MK)RrS9qOCyP1o|UrpWl_BoUec$dS$8+OV%@&A#!}x~D(#{;SrtrMZ?gtf9d>y#5!2@Rfc3_RKREd*U_vYs@nRv*CZwHbt{^@a<~GkWPf!S{z;&wb)*k( zIa%~Eyljc%E8VV?AemZOGG0uG)Iu+Xw9;kBYLfJAECoN!qCBs}t-@j^PWORSHj0*u zoj_%1FVaBw7M~0ozkqIQbNf|ZZHtnpd~ad7PhPb@@4iZ?!JsZ zsSvgGs(`FlJRX~d*)Ku;Z*yHlqT#Wo&ELEd^;QLLG&~4z9`-8PRG6dugfLFJ!l;K* zjfdRI)U%AnrsYNoKCa5gB~~#0qU+Hz(R=?nm%+Vz39aA0-7q(2WMShF52nNWzN<;H z)RF!ebMvR({3pwqfVaVHx9pKE1C87t?Q*yEBobW_Goyj7=dA1XosWNt)`p%2sgj^x zwNAAXj}>v0IJx@QBvC3B7Mj>OT%m_4>d~0uN;BeOlVBgQbaw>^b6@jZUG0=pmQa57 z;MEwkak-{bGcnGxlb%E5|lg1FbM{8QhK}Jii@}+f`f3O{x6Gumj)WwQNu6 z>bOq<18sJ?@dNF~`^GHAh=SlGWpb!Ne(nyUgyv=S5|6y*jNng)MPo!T=o=3kxjCdG-D|L+kh;QCL0t z$4g5@OXqvXvWkjZGQ5f3R|4JzP#1L4kGLnrEx(YF8kxY2i2C4aZLThB&bt z8x7av<39Umc)Le>oRB`cX4BFrE%U|u2omRX#gi@xkLAA2`)AU0JSJ)ym!A2JDB&-c zDX|rSvIf!HdIH)OORBQ31Q)n)2U0(ftzGwY(q}Pq$Z-&p|5k_t$uV^dCp{1MswrFf zW}N-_FdMV)a1IeM@fodgUQ(Sljb487KK(*<;soFS?G<d!{vD_FWLLy(N1qYTDcCz%A)h}Q3z6TLtMBrq&Mhz=w|EK*xRWZQ zy;^b$ebH4if+(NkTuP9ek34@)`8yvymJm;IV2vtY;-`wes=($_VfTZ;fQ`GEL4Zvs z9FLDKGKE@e+=!3e5u*Hcq|`KQt9waaGabLbsgmA0?y8|m(K1E&J~}U+o%7}g=7o{bjuri$+indTSQObsSJM;Z4I^LIQThyeLUt`kq!j}U(8VuN z+;1qV$vwJ0&W2}rtE`(_Bm-sMGeE;1$(d%Z7{9pA}qi?$*Q)q<-EU z{|8@h85L)=Y>Ork+@0VSAh^2+53a%8-5r9vyEN|Z?jAe@3-0djypQa6_dDZ^J05>& z=&!45t(rC0oV9f45tzpN z=em1wxEu~Oa%-Q&Pq+D~t7oQJK#d6Xh~jjxiIS$~C(Suh4dO@IH^i}WoMx|x{(mrWeiTFlgwbOJ!oMKC?Elf`qJTQ#b;7FL6^&cU z3jx0O7GZJuJ>b_&545iAPl320c&?!>JTS0zkMA#Voaov9NF)Mc_CQV~6U|v&?^zbu z?jAj<(9ql7pl{&~1F)+U0e&06MMe3>asJy8m7v8>3gb8jj@2zOAss8|OL;@6(q+d8 zM3$mgg|?^~J-RUVFGc_50r0L8+BfKTBEm#N~Vu zNiO>FHn@iqx^t_BkH(FxEgy$-u-taNcv=|njBlcPr)t@PGygh>aG6A(TqPCcJGkl7 zVGuh7Vp0-o1xCy7p1gmf* zGW~RhzyF|eNWxDg>wmj`Ni{sL`ga?no>9f4^}lk>sh_h&e#VQNtoZ2tk^aK|H6iSM zm)BKrL{r9j=|lqFYmC?PBPi1X6k~v@u#%F^1P zPRI{O9#xr30C%A2d5}jEdv7m_g7#hyIf#h@(??!h(De2!qsbfcFJP0XLc84QAyds# z_m#z#tLA=77f}73>x@Kqtb~4pcSbz5g~u!5MUMR;?$ZvL`uSH31Ra`0e-%R@ zXJ7T>Tj<)@KxD0}EDNChOx}mvi;azix_jO1Y>b_NU`U;T_YD&^2g}?2w-I>}6Wykd z1dM?lcf^OFoU!~#PT@7WAilRakk*?@z>~|J>wrd3TS_Rw^h2TqWuQ) z0t=$%NE3w*=XL@BfbkPG=cUH4W;4cy`Fug;hp@_R(3SWH8R-cjT6-`{Dm{P4VYH>w z?ZKr4v^Og?Mb)Pjn~|P{1>{SxU=K8TwS`Q9>6XNXzWPA1`Uwpk^E1VUDzzgd1#O(~ zU=1$_5)v$b)LOit!01QE73!+ZA?;#E=zd|`3a5ge))<$`EeTcYJeo2$VW6)s3VZjb z?Sk@h?2Vz;-uhcX?35=sN~YOw#GtYX$@C=sInFvP`Rl_#=u8e6$e^G_U1X!R+Gz#N zdm|W6Q7;5EF)aBgUx3T0myZ?q`%^Y>f{Jw1)I+1EAM#3FtBik+00 zIw21zomSEp)Bj2*oiT`7zcaW&f=$z0Y8^7^Lq|T(JqD+UbBvoTmab!BurOCuMl79r zh#F8iU3xTQ!+#>;JNgPGu#w1Q3iysePJkXmnY^c4?x#h8zIG>qg#0}qwn749?1`h3 zqPen9i?;Q3+X0ElpnRiUy|oe#>_0&&*wBppLZK34T**2%&{@XcbJ;6=mlM#J|286gRNPfv z{qd6);3}mgzYzbgARI{>Il2=}h#Kq4H9=bw}b2URT}LE zK(>^%4pW_J_nF<(Kqe;>)*NbH7?K~C8@W3jzoZ)rKW?!OkA3wWb3tT}7Y)`H-{T5+ zz*N+qbsO2Rs%HE;TV`;!mN59fj^m;VdEUE8QWMoP&`c&$*C&derNdC@HZ88 z#A#F}U2CJTY|+l*-!vZzcgd%*%W?9MkEC}NV<`5qHSsGE=gcEi(xl`6IM|Yq!IP># zhFSk~RQx49(qDSjyJRI_&;y_HcWxUp;b+G%^BL*soM*}mH|;v54k6C_q6}5ulONs9 zR+-GKcE&oB0JVns?5 z)ofgzXRVEW>mgYN;8;sMLcm?09F-&##=eHG~<`j;<*#7xh`hUDbuw->?T=}_?S@GJzAtBNkayT@UD=~Qr* z*7HbLlD9w{sQM=5sJAvxkQq>dxb_6MuI` zgPf>PYXlR)(~Fw41oaK6O4$*!6Tjh|lVb`0Bm*%hyJwm7nR!8C*03H$DBS?SelzNV~LS?mREsW(>v85b0w?bP2;1iqqF${)>g zKr9NP?&bH7H}P6qwt5ZH@t8DLqz=|phJF4sVw@@3jq*^3tfEqKNX%+jEvGQU&wN zN{4^`zHsv$;ji)j-?3QJEl~pYra@uCc)fFT7>Y!TO`GVJ_!aUMv0aV3#r!~%sE+LF z%8Lr{X#2da9foisz~WtY`~pdfs~Q+wXDoYApMr|x!t3V9KL~#mOvU&5qwNN{-3wg1 z`sQi#?EER0^BfMkHx@3({7FK5Ty(f$$hFH1qv7fDuP@MB|Wzv7I7|<_*0+8f#R!_SvZuLN(9TY zkiE6aiz}b*(i84;y{y&yo1-dSz1uYvqJn~gl>05PojXN7oS+9Ziek`n`2sc%mlxt{ zmS>5x4j*^S#6x~nstwSB4n`(xd%SXd{EqAJi8UV#g&u~eNO=7VShTe;34PlKFa9G+ z2{z!PYr4^)o;j96;Zon+nx->a!IzhpU)&svjA$C080qhv!Py;8S?7~cQ0d$p&Qu_Y zMr6X1l9GCIdN&o&H@l-48}FJf z<|2@La>9L7wxH}XQDGDj;pwgIYRq$p_O2TH($fB+56Vfz+#dDyufrpRPpMRUxhAJG zVOOMl#lVdX6p(;%S|>{(@_T{oY28f&Ov5xhvtYK*%NXS=wOCtXh@w}bJ7s7x8C`x4 zT@?ef8h0DVrqQBK7P=GlfYWgnDOfgeJ^E(pH*qr~xfj z+HI_1Mu*?_cwC?T76Qob-8?q`+^zL2=z;4R8bUXQ3x_>(@U(Cc6e3g=4+NYI0{jUR zktj%v<^dBS7%?yvbO?2s(e4R>dwV)y@(nWY;H^r4%V`G|vs^9wDCcg&&?Y*F)qLH@ zKs2v4i!drEKzE>P>35}>K?LDr?x4?F`{$x6%|7-l&xpYW3t}BQ)lO08Z6WB*xcK#> zjnLS$PJelDsP5q@Vo^}ID~;Jzn`$Cb z@TNvf-?x0XWhp#-H{c)>nk?8D;BAO4tuz@ukavtQr>Kn=1@b$Ee?owbm6;?t@5U|X ziAS&}c4a~j4ZEcE3KyMM(Bb5Rq@?8f zd^wV4240NqRdww`pJ!P3_jS2C-W0E(T7pbpDdULUj-V|WQ;zm!tptc%hvZQmG|=6w z$-VQY_*}SfK^R^@)-m{1;qysZ;jf43Xu4jX9XpTaLmIXsQLAm8=2jj58@!GW52}UpY5(5UuEAqbmhSG4 zn>!3eqnH7EPP*3`bip+m`GOYR#h3|*c-Tbn9Fo|P;(LqxeRuRqLL?E}Gtp-V!AtWp)fVgcxeGk?3L>;-X|!_jc9Y$wDd%bSvfC@8;b>39L|jJ6Li-53pC>y@Kv zH{;!Hnt|97b>%Tf)GWbU(4~k~nbX(Jh|Sl`K1Y`t_=TF?VB|O}(F5T`vkp2aCoUk3zK@))3! z_w9N{vFUgt_`lIF7YiNkkjM`l>4>S&h%J%t;JkUPd3$nsAbP)E!tI3R(dCJ59XA|t z+|1+D7wc4BFsoMO9PKlX%nz!JX9ljZSq&zK`-q-7Th-hY*+(){B+s7SRn~q;^xS3X zeArQae!L?$@+j09p!iCQAX`_f1G6^&XDe|2x6)@FHM6f1beca8>yk>RH5shL_xvOR zM|=SZlabOhixN79!JlWZ;`u^IycH!K>tC|<08ZVf@V(BLTIPHDa3*_(kQ(Yv{Ubn1 z3RvIaQ2~0rQ*-79UY+9Cl*fGT4b)xo%ijAWhis;~&ucJtzg-_$@C9crdKP{JIY&PC z;HgfcM;_y6B)qjrgX^$ZE-JKqybbO1V06B3+vi^QqET;sRgfow1F2qbjzsuY zdVjtWwLevWm1MI};k;bxd~bEd32&i`q>81g+;+Yi1yo20Uu>sL!p*2d-l`IW{T-6u z>x^sbYaK%j#y@;$?w!Fb%V~4u(6=W1ZFdfHs0b>5G&yC}nzA^JLEW1fKm5|m^132@ z)$GEjczr>`S7#NhaP~)jq(s%*bIw-(Ia$~2{pdhix#sq>;Ht~7CiZt7$?qjF`tNc+ znme~64Bk?T@adlMj+M7#G2T#&htECbHKy!dLF&KUTEwq==GSzeejD673ix>P+ksiq z(B@FmsZ>JS+u8n1E~92UT`8i$k$yY}f97b>+(PrdN1<-A8rs0{$<>M{H)YU`v1dNy zZgVCY-s6v?|67g1PRP?uuj3O~tL#b3gDa#!!7k+kkG4o#qY4kNoK4=?Yc)&1<&to9ya4+Ne>RPR znF5)<3MxqL9NhUwYuv<*+>j<>YM8L*w8|eWhqS+~f7_-ieV9|qT42i3DvLSaaV9F| zaN^c=)F?LJ6aKFZXY!=<5wxOcz3KU_nB=VJLM^`j(nKHg1_~5rj4%w?3{E%fwkE6o z*ca}sam2!utGfv_hNf!a?JWjJ3uO&89`%PiZTQ2_5gPOKTaS5;Kb98sFYea#2hQLU z%0g0Rg{z(zAWCpD3rBcEQ!pgR$*a~p^!nGWM|k5JkGX?`q}7XAHBxy)=T2KAvMA~Y z5*3?-udZVOKCVD*YY-@J3#&o*H%)o!Ko`$Q-@rGnj7T5neq6k}w6uL~MV%l7mggh@gH?Kx-QX7xML#73%c(cx| zCwhOaCI0da@y!{s5sxe43YVRTn;naH&^zdJp4iv7cu+D_@|;zo2Z{)ud);92+Y>$c zOEdDHAfEs?w81Vrrkm$uhm2-NwLB7(ItuyW+JgOBGk^eXwa4fm2Ds@EmUg}njUqy# zS3B6ldh~fdR4`G=9F&hLFv|#T(31jKGd8N;=7|gZ`pqSp=cAs_4R)+4Xx%BYN7|${ z+sSJ)d@IKf^W#j+)3IrB@bor1Dd`%NaH6X8puXd(p|7&UPX;H5j)$wN2UR{zyUiX) zIL?G^LEa$TytQtm>hn9Nk+Vk2AEBu_-a&d<5knDfZ&pmHaS1;W%93-PUqtuk%HHZW zr||@)plG5%&Pt?u~}w{q?>zPutHhv(3xxa z^2K_%Xu4xzWqunY{`73N5#Hc9Yr?>?y1u%8t7UJwme04UTYP>wzB!jpb$cg=Onn$d z>9jnn{*IO3t5IvdK!U24>LJ%?Ga@%P^}pN@J00mh(0`xdS~=dCAMef0O?Y~BZ39*r zA18!`%h_N%2DN*;c9q&?aZ zuwXYf@3RKk2{}ThLZGGaUt=%3xV@iC?4xt{4a9WX*5uShA&dj|7MfXH`xBM=;A!%y@&UF#@WPDpz=T~Fnn)K=8EUSa>yV2QFz z_YD3mD6%(_nizY!DAJx4r49!8y2mpg#(quoHphb7UOaz|z~+Tn8+(wbuw#rwQ>a6+ zr^UnfGBlmb$uZ631Bjm!C5sus2(B!KDRBOYG&qOgNAt*s9TF79=qMmRn1KeiY4>%3eLg8q5 zL4Axk_~3zc6NcV;S@oS;sG~%)^^%=N;|3R9L_`jqS{vIw`ePoW@ga@Uor65wz?Deu z!oK)UiJ{c*-K8_{pod*%lmDXy@DX4Q;B5vkY>rP(_m5ZY-PqCcj>C7bR|{XA_hiC?L{eM3(yC zw+WH?Ol9zOy;258Es_+EuOMs9iySl!%`Eq2dJPt4qTj+k*>&kwrKcoy(yTBbZnc25 zSpM<;?dNmt%HYFlOcIz!K1mm)BX||zigwOJ*}I|4*(^m{Jw;Ko*S%g1*<}9BV!Okl z(SB{Ze5-nJBNs(HxH@i2zaz-iOTJW<^vUFf2nvF{H&|ig35)2-Fw0|f7%7^(Wz%0| z@F46s_|qst>dAdEixHTJ!15m=M-cNK>Y$zJhx>hpoKxr9x%P9lD?ywBYE}hNsrcmj zE^W2#F=g{yNuK@Ss$=WlnA4SW`8B>6EX<9wm#3Po1-l*Nxh~l^*)1LV2Z%09n)&-M zHRi+(CJ?MM0f54SC1+4D>xp>76*Wzu zD$TAtO%q5DR9$V(tBM0(b=pxKB-AUhV)n#0%e4^YBNc!-!VDvU5F%Vv#WW5J3u9RC zsM%-rq*9-|QiglE5+Nzv$~;LwA83x&uI@p1-lbOyJnevLKfjv{>Iw%gquRXs%FJ*v z`j_5w2tBbA!~_d=LHs z<&$wBgeh=hn7=Ljo5w33a2x+s>59g7;@jxc9mD?oY0o^XjCCCY*F}F!^-8{GP0n2u zvv5K!m*@8NL3UE6;{0y|)G$==Y9x36CpY(VJZjI50+mq^(zo<`z=Sle{ zv)hauO$MWU%V(zn*n$x-V_22+r17%yztn3*0kq$udLfvqB=Q{^4kWt#<(#~4d(EU$ z`B0*6qZnA2`uolqcFI!6z_SIdxOJV^PS0)TwRb*Mtk$4yb!J6}y#!?%8*PkcB~wOs z_`LqymXGEk4w*YoVs=j(5KSv6~_rqeMS6I&#k(>;a)oVUjRuYEw~ z*#V}|nEbp_(c^@fR5D`-DCcK6Sx+Q3Zy6D7^zHVpem0gyxyP0C`?>kAKI%I z_uV|kUd3t{V?&}NeaqS?JYT?x<6oLIwb0f)WLHGM*{MIZCR7Qbj+&DId|aH>%@aUk zp^07hCGeS@Ti=F1f_qCx_iwXkcHqM@E27;$xspt&-pp%cva2d6gq;^-1I$#Sb0$60 z0oha&_Pavii%eGUaL%(b_B7{G|A3JWJeN*~H$>%HYf!q2H4)?2kN$19y$O%3ayI9> z6?zl}1sjVmayv&l-rAYaa$6XUSS;G=rJA$}^vQjbf36aRrmw7+YwIo;4q?y-28vZX zaDa}dfnexe>M&c5R$e*_a39j~@a>WB1|ly0Mq18@Y)J2Fml_Py0CY?M;#QHy#Kr}R zvFE+(o_~X*K1v%6l%|XpS#N6Z<40uPGxE9GkY%KKg~)@?aDSA#{^dUULB+Z&B$n1o z&&<5s@@CCEH{I6B4()iVM7&?x9Dpz=--7kkgFB!P?K5!2NzVU!K%(|g)(D8&$s+rZ z11lXMMMfv2tFMc8biFff-?EWf>rVpcOF8mpx4+`Wp*EIXeaGyxS+>O1NVG8%00iNk z{doAmXGrUCs&gS}RwYeQZ-3=5^bL~ML;2W2A(x^P0{2v9aDVI~GAXpro;XHDvdg^n zrgMSAs`rV@Wj{zW*?1pa6Pyn5@NA9rF~5W5=k_&T1~g1xND_UgH${*#Bw#!;W(!l^ z^Ll<2NQ7k8HP(p7l>@sanS>Wvt~k?EIJ<@e6z&iiEK%RkS|`}8)q)*}O=>Qix)KaK z(>O62Ean8uu1#kS|Dw&k`EY$6TKKd>N5S|p2MV$0?kY9kLC{Dvtq17*v)!~VW>p+t zs##M&mj{5Z=BFz(Ally?9(2I&5O~`8?HR2OK$^)a5_=Cb*0Eo~Um0o|1mo4yI+%Ld zU9=v%-1#xX$}Q`wZZ}0&^<5vuMM$(J0@#;O%O)^nje955A%_HR*xh!6Xk4_X39AH+ zWnc_D9kgvF0aYZF&>fi}i1~Q&&N7hDm|pmboK{C5)$?9wAuXYYqB(I2rH(-7I`C?k zjw#@KlW)GmoLM|LU|(}YgnrSdld}YJ2Km#+lILcOOQ-!EW#LH*J}zD)6H;b|VhwP? zF(^L&`@3`L`irLE=&dpjVrZ{KUnR$WlUL;nS`|>TAqaePx2H<^VFcXkRTxD0(RDl^ z_N0tIUt;f(hxrw^Eyk(SX^)@7)scUWe(hSa_L8LU{Q4e|<<+!#mEv--)yZ~$nK0>f zR!2{eYyRmV$KeBj9XJ(Mu+c9EG}%eXsD%YuKjmL;sT9xWG*yt4rYHjk(Uj~}&h>x1 z^TcZ=X6nayj=7zX3>NRZoS}tujEFGsVZ2^}Bks#1gpEIzFj5uZfl;Xq_plBGq`M>N zDQxXBTqcpV_Xu#xd+>j)&m8;N6-~0O%I355F>CH|XK;C-lP2gZLoj?)ln4d2C1I^? zp0GYDdJ}=lq9WDJ1p(8YdbdGcSq%NIWmLK)+Q+ZRF(c6$IoiRijbX+5uNerkA~hwP zez^A%dXi==LH|9c-($bUy8I(nvM-*uZMOg%m%q#0EaLH+XRs%U8TDEu-Oh3C!z_ue zUXvW@%4eXdaB>bk?_NO*wFbO`D7fkR1h&dGRa%w4a z!k;;A9}YAV)V9e@i4QYAyJZpcGFZ=iay&TSMbitPjzj5iC-$R|@$)4(omE#+4}FNKS=r|E+c)beuzI{OixHDo=(!qv9Lx=rT@?M6$;L0DN$_@KfeJ4Yr$%`l7 zl~$C!3x(CQ3>z*csn6v;?^HDdl2b*K5D`lx|G5XLKi@*)iH?`yuX}b!FiF)+eUK#1P>1up(RIlYA`pq~R!E{C>0Hj2}78jHXS76=7#V?vZ%#X;w|X^F&%lU$_#t;RyVibZq4^9)^wU#^6Mb&7 z7wpABo|0q!=yR>!cUVAZLmszg9{kgpo479K^{621*;P2h8_W1+vfYWEWSSE<45dgK za8(fB_Z0bG$W(pYUvtSG5lHO_B}pC^sbkFQ8Jm#V@z%Hc5tHgmJ^B{#)|_gy5)N2^ z=HTJDt${s}g~j8>p(~RX+sS8f$e7O*r4rRCPy1B#h5FRWI=o` zELc@Va6p`_uv9*k$tNiyW=`R^g{bhmg~S;~3WI%PcK=39*dZcO*`;Q_OE6Xfe7K#w z>?9Z<5}70%k>e&Nb-056UYV@luQHq0Npm|O8-=12zf825-(hG3|3|v^LB`6X81VLJ zS{cr4e0jGm?DQ_yh>lYvJEXp}_VNY`3^J&w_iN;^|q#f*dPR z*bcAp-ks5oT+jzVX%T)eEj0g@&4`nDI*^j_WSkmN2v}LV;!TjYcGalI%fDHww~IIz z-0v}i8qNdDB6q81VGjO%>1Hx5hZJ9c)w2@#?2L8axcGrtD=jeSih#>{y`)GosGo4bv!w4xq>LZYcLfE&c<&NZSkBVmNb)s{Q z%ZzV)ns!zs&Nc5ECNBn58`OOkLDjFnvpId$`E5h1|+y=O-5E|2(b?-GeDLD+r6iMo8@v_8y|jFQ>*4wznWm zQ#jBQ41B(Z!5P1FR*4v75h$Ag3e0wZTweHD>`SRT91K^ zb#^2vh6@V|b8|2Vq1x*2XJ-We2G~f)N({b^Gbs@gUzv|Nnqv@Q!M!A4e&j@ngiS)t zhzI%@zpvtV0GV|hoFssncV#yM*&c2)Tj5k4Nb5@u%j2g4F0bXOxTYl(ez1^;fT(l# z1XWz2R>za7#iKO-FeXz7>ZuR{5^JZ;6vs-mh+IaJPoT9H7u>8U!YBYg9tLO})@V^m zxcj;LLmu>JB1bH*wql49yxN}5$Wm+oUPnK9`p9=UWQNrX1l06Bpsw!$9ldiBPkzr* zmf%y0oZ%_#74=!@@R>&zp`g@3q@OGW$GE3# zgC}$NaKdUi(nkJ=Ig;AX(=hFPhm{>M_@w(e&OV@1+ma(KCKru{NX=4fba^7BDMQ1D|Ix(FpLZD39gv6LY>13P}BT)J-z3``RsB-tNn%}HRBqNM+>ChP=Nb>X{+-HBkWWo!% zK2l=fmjKg>TRRe*DxnGC6b)L6;Y3EjG)njK*5SnQwJZTu0fxJa7aEa-xWz7opnlV05aA{8DGC81!4;#*xkzr6G- zOQ*)e!_&2}fCGL~($c8lgr#zdtE-V89v+5AMih3xeBp$!v$G3{3iXXlWc4ijL^Rbz zOjTA+s>dj zW~lOkfjTTEK1$u|Da<^Y#2AUBP~a0T1*npU1XRZ~emw%5uzX6h?gWsaUZ^LkuT@)< z{-m$g`MIswnzz^Qg6~)?X4AqJ$*NV_1F@uH)h3hLWM9a0ZK7Qmve$I)pCC=GG)f_- znWt^{dT5t@T%p(+8;cc-*h-blAZ={Mqo%ww6{V!$3HUri+FZ_vxv6m*%4P*ua1hpY z&nT5MCI>}CNKO>Tc7d$PGq|O6&&Z6Ppe+sGoMGNYuiGL8bCNFQH|9SQOlEcR~Ypx}KAQY8R0oEW{keG;A?$A%VX7@vK zKz^e3ZQxiw;q9Ew{QB@qnBruL;uyg(|A+9yoAu=b{JCa^po29Bl?%yfj`x_T@BuL) zYO#CbnzK^(uOlwHxELZdSg6)3Rt)ZlG&oys@ds|8)gM1(HT_eHAB6ORjc~-OZ(y2R z|2Ydgyv&7;l!*&$Je~a;a2r=5b<@Hl19ca0pL)>uWV)U;3S{X+*5IOaER9pwCTd{w z^VAA%)*k51aChGJMqOlw5eAjE`Z#@8MZ2_iC6Uqcil}T@uIC$&N=#{<=o@7Ouw!ZU zZe3*Oeg@}FIi)_%vbhg9ch;*XiBH+tdo66eBb5TfwD1Z`rSc~Ol?h2aTis7{emnKK zD(o9vgw&CGPIHPGD=`W6coUUtIz2a~Tz+~Dz@5L?KPPU!dl5KN98>a@gtpsAj6UXlL4 zfl${ve-03zNZNA!0ZUUchO*pE2v{34#*;_zjCMv)?3q#BTI?N5PvKQ@PxZI1-fOLr zn)k!2_W#YY#QtjXit%tE?p=+3`3yM4o<0U89rKENxJ~6d^hklvfo*)>g9*JbU1?~s zrza7EvQ~*3MKg%8*M%Dc-g==EeC+u6$5v^jo|`c_K^9k_-?C@(wI`DCsqzeKjve4j z7~H?EC4J8r=T5ra*8Yp7%P;pk(E};WCWwWyS%~1^;96;_qnOOUfk{#xW0}0T@qFnc zi`>7>AqMQWu2d)1mv{c`&sE@ZxtxyG++nRSK5%$Hb08A(Ma+#a<|zMZY#+?C*n2NQ zLrx)QMOs*-)5xf?QN~VQQ~8)K>^3%O{;Fp~o0lNddU#vm@DHbOrJlRrfEsyoBQk$` zEx#Am{6(&xF34fZlmjwqhE<{Aq=5ewt|VGTK*fm4Q2Y4!?`31Q_?~%@lq3HA6eqaZ zYA&aw3Ug=50B2o2GgPee;|EWTCSO@w>WP=GV}}1}II}{U*dhiwL}|_-mWY#0U0*mc z&O=0bKV1>byr{Zs;92OeN|?XHgn z7q}PmWV2RB#=8SA_1M~0+f3-0m};jAq+Oah;qH_Pol+!rhG+@riTPAeIx?038z*$A zl$fURN1T~+p%o$|Z2KSEbhOlcpkSEh&zMm3+z$2EE&=`p*0TQcCVW>n?~p+un3d4# zMtQFQB3d4`3A=zZd1Id+{kGFzS68=R4R&NiGUmdNdYY8IZ>kj{qP?(pDx-@RU1Bez zAQMZ>bD!tM3@5F=Ec!~Us=F_;gBD>GvYwLm^Fh%aDL)t9>UdgDoxB0IZL?ozc|H2Y zd?oSjh|!OGl|X|fZ3a909V0{r8Hv6294wH*d#N(=)Esm2)gO%-A3=kEz28ELz~@%M zB3G-q0ImVt1ZL|GMLT%+#=L%0yCD9Q*L1qp?Yrf{pxgc76BHC2asK?E?M5$zhwfkV%)r_LvP~?GMYU2cgc!eW#nq#JN!`;`EugpTXziQf zlABM-`b$0L7E#{p|39su7O!_Q#Gtw)dqM17^}Vrdtd~bpd;2=ZyQPPAX3CIA;lTp5 z;c#gGf6h=v+@uM*@`1#E&d|G6u9+#ooP;sugMvD?=dO>V$>i~qx;J< zqth1bXs+tdFEgXXK}9tmz#_Lnh#=Ocf`2iae~`$EwQ^S^6h%z3%NT^{CHropL-@&w zV0E=S4tUgE$VGz2_DVc=d~m*h4N|$brK4_!qc);^OD&}nwWOj;H{gV3 zv#!uRSk?so{#Tt)Y_dDdUx~e(n4;d{7Jk70d){gfn90B|LWV!hb4~sl7yRRVV`n;K zcmH?~6NFw@OL=4rU3;eK8`^-80S>;gPM974X9~dj7l7QWB$_afk^+nECat&8`@6O( zB4Br6z7fWPe&27HD(QC@_3!QHlni%y2IeX>031?Q!8!40Vr;BG4Cwco?E3vU!#S@; z8}q;^ZUribhpMB4dX_WZ5}`|@nzFM$;Lh3nOdSK`<-S#JNMB!kPoU&^;?7L#5^lE? zWf2rJw-A|0F>5`>WxR^@ZCwN?T(}+Md6ivq24>cvnwr>44A$M*n$1nrVYu*E4Y`10 zP0mc?J<=01#JFh(JtK2?9Wl6jZnfT_*bZgM!>FsBThDDVU}s9=U3!t&t3svw#T7gq zVL&;~Hyh>(Sg;)d1WQ#CN~( zx5an_>}1%=d3p3s4#B>QQ2-yPaBhx)jXgM4s?bv;(#@${I7h%v@FT2)eYd3$C^<7I zBLRK8f2eO^5i;o`tKMfND1hvP;HCg%Q__*yV1V^0d-_6$K~ra}p@-oi-41Aedgpwa z%ngF(JN=;$MD6sxCOw~XSK00NKCI?(>lvDdMDyVk!a1}r{OGdgl?)r1DjIETzn`Bg z0YJ398$RkGRc_OG;QwXF0al`byh14rGGic#0qM7tbZlUx0e0gq6Nmcnx}_DQiw5(~ zTL0yS`#X6DJO;$%rk|3;nA%g{M#D=7sOo*Wq*wStOOl$!_Q_Fypg40DM1Z~}kX z$>oy^#ik;P$Y4ssUdoqJDqx1B2*u`%eG=Wpj8R(>GTwtut>c!`>d-ws05`C>;31;` zl@$?sSptqFUt`c{cnceJXBsO;0pvg~9kOyn)>rh;NuR^rMNsPepa+2_0$F+6|0{Y< zzgz-!7(k;Yl^r1y$~M%uoE}){R9=z2lck-&@R3Yn>n(sq98IUT(LBibJbBsmDzK0z z_k6jfP#GlVJwqnIrHYn9z*a;OD-b`iGoY#X2|(H?j2j%D+cAaYpXRGH=B=U6VNiDn zM2hI}`u=3FL=Z5m+iJ2Rm=0WG*jC$Nt`La4*Wp<>i~Zh(?EdeFV4e7u?0`Q0qz zAP;gU2hftHW^l82n)2U_yt6f#pQD}tE)>dA%y-B!33<8)G>6P4OQcv_CWF)9a+H0ZLYjm?N1Is)i%7pBUl!h{HSHSGlC(XpCf=)!u1XHYkw99-aVZ4jkY#iN8&XX_?~O>U3(_y?1-HF`ce1ssAA9$O4Re zB3FUx14i{A64mPYm4&yE*C1ifA(8UELK_T4&E~gJK0ZI}W&OCDcem8&(m21cUg(4b z?&A`%wXI$^m}TjP!=hWiEGWaC^T{tH=QyDNVq~ck-0T@PaPTRnnYr?k{5@T`{-ule zCMoEu4@6sKd6W_Aan%^fVfV-}N24)0$1q$O^*;CrUP)*dQ1wh1+S>sU+8>KelD|L! z?tEw?UlExtdTV>x*uw~cF(8LyI|YCo5h*(Ysc00kWkf5i<%y1kp3P2xiuBUq2$_ZR zd)}TL$vse!fREkVV_LKj^&KOxZ@xp<{z^_ZjQ^trkb!hGNyG(#Gj|$Z%Mdc65P`zK zYS=_4T7j5Xxo^zEIsfbt10CtX&p-aLF%vgLzi{9IsTGdERxTVCmV?s}$^)6u15$UM zSoHeYS(UZR?}q4z2w^#3q{$gCxX;>$o`I~)*q}ro`aWRR^~U}_W%IowzMQ)|*RBsg zVIJQzUev8jD_fPK$9tadI)#)Ksd7oveD)Ci8UFk)x!C?CR~L|6&o%Q6CTva<{jFY; zT?-vP6tCJ1BJ(-%yh%Xl)F5dTt^i`nbaSCI#e(Vh*ILB4zCwg^;A&CxX{`jW-SPC` zbX6OJUr1eWbgvy^F1cY@6aWIIX-3LM(;)NQ`2U;^44U{>S1nN@yJh8e+etgMb z8A{{7POzO^0%9-U0fXqk4sE)HC2q2C;)H7k+1 zBjf{@!);FGd~5c6U@EVuQ0^{%BDd5Tn~l65JUPOC8^G=#94K8AQJH%F}asL* z%LAcpCk9+%ZTRy6Wu*KEz#Q}jA>dAB3xdyGIUdc?8tGAyk$uX^$q9)L7t@m`9vd55 zKimw;?j~X>UV=W+a1kCqZ1@qqX9R`Ti5Kn+TGXG;m&kb9T_SdP>jO?gN=k^IADBv|V0~D~=veL1cU4)! zwfrv*4i3$2ZQ+vNk5T6*0Q#5P`*HDoz}J|=L)#|k&ck5loN<4(rRZKjzJC%rX5uX! z-g5>lfDHqKZEaNfrPj7B*+1;ILG4My-o&JS0p}_LwaOHTs-XD^bqQ^D5C2_y=Ulo^-@U5v~ zq~HtO7S56Do*ls8WzSI86EEfnEy&OR^!Bv&#^AYLWLv#w zLSNVcv!Wxx|7H4vD)!Uo2nb{XLf76Ao$O{FciulTQ3CtC$q%T ztwQHk;%qCvg8VNl$VNl32O0R4kNSy@beU2P6*qYlNCtmL)~ZcL1uq10#dW^_bbQs1 z4JlLqDOUtEldB43z}AZ?lgSer%}2$53i?a*LzS?wm)~lU1sxMpe#>Iy1+m*YiYLAq+E1rY|41>k`67!>5pb=5298;?|MLDAmzi);7 zO+|80q7q*etuP%I!z{^#W$)aNfqS62@UZ#)=$j~fw+DDou8pkT8OGP+V;BmqX*V~z zltkgN;BobzwzaR1;>F@h60sojTBp$JD~F z>t8z&LbDd8rqysf>yO2b9K&q)$jfvroJ+&$}Z|wQ9!y|x4T^>7H81at$&m|u4oQ%ccy+Hi`{|}cluCn+7&gGkUeMdm zH={1y*!CR@{DIxFyE$IrP4K+5bh4x0A?Rs|aBWkkCK6sTB)x*jeG4q>>xhP02lN!5 zN(P*zeg4YlKt?_HfP4`6qr7aqN$hiaMIs6r2~0Fp2#`ctzunYU{gd!hx<`yEyZ8b+ z1`mv#$L6wIOv1a*y;PIEQY%o*vYg0nSv3E0w=PPH>F&u_5A7k zwV*)hU-uJ(yY;cNDcBm~wb)Uwv=CqWrT_jbny&G&ATG=D-{v5mq`}qSL*tpS9UkA^ z+VvK@*-~v)AL;~9WG*Q9_L;ADNV>Fo`$M6rq3`Cm?Enkbw=3r@^kFFY-;Zm;_#T8u z=c}5`q67G@%|Lh#c>6yN3EDOFTAg4M&7=G8{8^$JjJUti0e4lvf@xI(8(|_G2xm-z zp_C9&tR|ni+Ujk(+5*OB{~Do_pZTXNi8==4A96}2D?oRpnt|0BPVZn&u%^}a6>u)v_@)djTsZ(y&V|s9eEnQmj{bd z9qLu(+d;w_Q1HQ_dC^fe1eXkNshA&)2GfcRQw3{~Thb|#4we^;YoCBQnY{rps4BJIeQf?Wdz)@7q)3c#9R`q1@Lv*uyl6GtO?R$2@xqO zUS61yduy&w(eFcQ5qn8>TD`bHAdqXDko8<~j6JbemO_-fPMq8BBmF=AW+GapjPYg` z-~G&AHXN?jQz#0Ad)JX_I-aekUSZ)Z$Ic=p+A^X>WlK6qOa=(ONXh6QF=aa)-ScwW*ys6Un2MO6RD!6)RhV4$ z`=^&gii`^F8n|R;{mDDdeeIlwvDWeCy9NuCK9}@v=G3?NV|iSm(`)-w=<0Nu2v2V4 zNa{LY7xw5e1_nXEO0dlwSUM+*zXnvQ1TylDEP9Or_g9B5RwvW+KpNi{_zs>Yi>|EX ztJ}eJ=Slm8TyoiHqty)gO+!0$xVw!hob!mHX~nsLnzf3(Cym#|^QzAMNC%k&gztTG zECFD+o^?3Q?D|N{^>##fmX9+fngc(WQZ>Zn(|9nPFd+DBTFXY=oclwcnY-q@-Z1Ib zZP&rc;22#bL9Wb~pcLhwL-*_g{kPhK?qPBvK1w+zzYJBm!PkO3BB_9{=VOu;_XiLXmL#4kQliVih>O zHd$*A=W$!Tt~R;cFwOQv+`7Y1ELWPjD(XcwP!SOBM*j>=O<~np&rDiJl<78Xo<37* zv3ulcJXucO4(z|9(=0+hxmCudO9w6V#gWDVk<^C0w$F}kc61bLPY$^I&xT14U83@i>VMrLpO?u*KkVpWbDDK(8cs zjR;t78{7YZDgYE|e^20@$;mKfkAjP%>5l;40=`>0Us|n zeLzO;0n9`qbro1QYLqepBL*Km;5dAxyFA`%s-%^VHI`?3Qm@tGim``>ME&FHaL%QR z7+l)oc?Q$|bWKG2!%}Tv%5=D}%5kl@wLs$l{M9_J?D!>9KfFFoGf6d4mMXjZDGpeH zYQJb~Y`iy_heV4_%;!qCa+pF;_FX(p3?4Pdqu;NE>@Tv7*G9|}VJNj6N8IN=n{{M{ zI1&NE*w|Py2QI--P`u@Di?IxW5p&fH5ut|tkOLIPjlR1-13N!c$EvmTL&?$6_r`h) zGvCZ?77cs}J;Q`+aa02fmb z9{R9r^I-I$s$an$ZtK|V72S>9P;XWajyVB*+xIf)@mOQ@DnWU9)T0>!j0m_s@CtHB z>r3H!2OJ5~Mshxnw+TZ&KNvNckMFgY>g~=BE7~KS%_Qouo!=SOOrj8J*#32N>t)1w z4|YS|-NJHA&d zQq6Nb-8j5%4zcjrbgq zDsHjTmVobl5>dE8_S4gov3>a+9uWi+g^05!4{PrIDzC8lwN|SceHbbcqPMrVf$3Va z8&ZE9X+N;wE&8{g?4YE}!?oQp;cAV=n31VzFebIE<3p`*AdDUj3#J`|dhunqTc_{C z^~PvA|1t@!d`?bImD84_-XHgv3sh%k=gpS>z2YR^G35=X!Rmq?>< zFY<}PTiOi{$C0^5|17toxAZH@`)31oqSS_$;KDsR`_4SMAAO~~HQ1fhyt;H884cDm zh=3Es+bRBqNZV|FQg2O+$b)8WbdX7-np{@{sge_GRe z{1iq`cr1=lUMW%&C0Y21OXQ5q3Fg>up=5r&zZY_4uyj{CG*}SV+MT_fWP^MmpW6<| zM~NuhnF(njce&%;7$UCDJSRec?>z0}|3qheTXv6kcl#jRmzzo%6b`E`8zDd#rJJ1svh_s$Z}c%>QBfG$>v+7-iVBD7c`Q=W zF>rE7czAG&BAq=7L=lYyB;4k6*T`LLwC<`8F%c_5j8Vy#Cs3@+{0Va1i7P)J7b51f z^y7l;Cam!akr-e-R}K!7Ag%10++SJ&#=T{RHkc;SE}yVOh2Z4p=a;7c>C-3WDieuO z!4Q5N4-XGTK!(}GVQXh65|ne`NXefdg^u7xHAz4~;8ay$(C#;a;7^5~U{^Rkgoq$R z01^L6xkyVb_oD|`?&Vn~qy7tKdo+y=s~v3@>YGR~>y|p#v+yz+F{-Pnsfns2Xtq#o z_LJ2Z#^UoP8$@C|Cinak#b^CyXS!>G=}KctPw#dM196||B3idG1D==(tT0Lnc9?7T z>(iD^`updp5IN^CA&!hGk56X6$h;_ZgEpVP0yZr-e*K=zxO?n`wA5oYx@P?&x}OQg zU@Mi(^^*Vbw~B}<&zhc7RF4`{cF1bu$qEY}oLpc~N*X;}A4Lw=mQBLYVWT|ZSJZZi zQxNOe{{2R+*I|uGLq}bv6>5+sqX+hTP{K&P2Qbz{Q{ zdFvxFdXH8 zoaW*gosVW4vdXk%hJR^Rlw|1vV2Qs$aIKtUsh{Jp1O|e`Y=uQJ>Zn-=6p#=!FB!)U zA68S`6O8{v|EqfZ9jaAn^!7wJutbuX(KOCbV7QHapYYqX{7wdgPSq*e{S#B;EmLKyIDC4 zob;n;=wfE!zj}rYwRPuvk+?HGd~fqUx1zSGhbxi@gq-##GR9$RZ5C%K;lUG^W*N~F zm!d7=L1K=X$Gw&BqT|YvqV$^#R>4?UkXjLz#ClitNQ3FU`wvY)QQEbCHzl&s^E`!| zb`2GU*L8tKQ`>c-K``KS^a+>kfzE{V7R3SYh# zYskfg>{U{{jeXBijj$oQi3hF(+Q5v(GDN8e6H;jx0ug&>C<0@yx%4F{m9iQf)|?Uj zpC9iM3nWOsZsW>&|GuY6h(Nq5V_*o3cy4#v>eExUQ!uo*{HP$1plVulv=lFfwli^*v1K-%C$0<_vSp_;^x=_?stH)@TsK`p34( zsO6zd?)eARvQSlmNin7;wMrwA<1yEmC=i--X6BzXDxLUov3A)BbviF}_1=#Z7<4(j z#Qg5jhpFYc3GrDBNp>-tyYU{;vbXC|6{7+W_R9Xqn5g$>RI1?jMY9HV*6PfML}16A z(R6G*9tsMWZ8q^PR0Of@Co$22q9XbmcG1vsR8{ha{8;$B1OC=S^J!8r@e_cIEMJKs zUawY=wy#fdhG}Go6By|?*=vtZ$=I%1AIKzeSST_JVtofb20JH$hq_lMVr+!4p(7I3 z=5{iAX71g4P`N=@{KPwSVyuz$6WNV#X<5mXV|I478;gy+uUSPbDl~tS7n}~<=&v(9 zveKOaw|hm0nNpM=!}{do4BDS%MP7}V+8Yyq>6-<*%Tp0rmSlKyvy=Xrb82Gp?1d(m zdyeO4mME+Cyi?()nfS&ly>9Z$2P?ev`S+20;ZN}pB=C>%?`-GA6b@wSHK&$mOcbXCqf?=*UwvKTCBHL5i>+(|gFz=W{63A7S`{RF%kr{VLo z;$mWUT8sz0gUW02qUn@U(>D*}KV!@kRNdhY+RtW+hr!AdvvLoRdi`pnMY_pNfIbEZY}&vIxsgZA96w+`9nh!m^VDJ#+MDb(FLzVqaE zsSa`!s{JX~sx=W*B;^~Mt1WGV!QgRzM1M}>LP$u!h=_>_bwjmDqBFq6qE%9UpS+FC z3!WML1}&M*R$F3@hB~i;V8)o3GVthCk^L3ZhhMX#>YaPp&$YITa7*qEeSyS})s={E zkPbz^zTZCgEwBA&Ze{hBB2}?+<0}iM3ajZ%9d4&anWU6YYcgFvs+lXr3Hf=13Xbdp z2{v|5uM0*=G$9vZ{=zVuYexifxL(5o$_oEAFjZPT<%;jxJ_^v3I|V}SlBOvzT5F5T zV~VD~V0!PJQ0*#5lQ9%)iGE22iA(d4RTm-Vsnd1_2l-EAiG(hGo6kbjYXvUst5W1b zjl~PAox1R$(92`uMbd_@rJ$+g6Y5P__#O91t)Kbz{J}HY;>&XE&_Q1T;H;&WRrHC} zAePuQkY~lYp+Z5NW}Sj&6I?8;ZgB3nx_~-4TihvGIj8k>!~+Mc8Wn#Ys$TjJX>m;g z`t_?kx#UKzFW8h22l9#I@xboAm4r3*y5UL#pufPRM#2jFUE~Sjmn-^u%(K82*jsEw zaY3VwfUjd&({=!25%w(jAulqyuTn&&sz_@>=)KRApyTHF3{i%jB!_yIOQy@8@=B-S ztPjk87ue6Y@92J-*Yu3P?FK4A=nCcVGX7X-CtHod_TMXq6P#8!_pO#-Z?~hw1=V>d zqPVa<2mm{1ZnpdePsvR>8Io|xW_?0Qq-H5F6k=NxLXdZhQ3Du^WmiT-2txJ-Q4qud z$l=BQL!^wjcHKaZXsK$WvT>PdPL3IW(wZ53zQaY(L)tA7X~CR*%hl|Z=2tIOCH&HlB)d5>|cQ=h@Y>1^FP&j@t2~ml9J2nRFw`( zOoxGo$m-OhAnin>9EK1U*zA1K3}Jf83pI0I^^aM=20^E5G6(!-RB88|QrF@`b1K2S zT6lfKoDy>?#ht&2;X{5>H!F8PfET#YnJ#5HRr_u&pJ3Mi@e(5}mgqeTi{JiU-LLl$ zN7vXdg~}qS_I{R(R|J>4>3D>-rNL4C6`8`%x%gj8_wZoMY<`IA*?t-xVLIh~a#@=&4l7vpbT=}{*cV3h~p5k$v-i}+{JE2UY7wXRrUIj@J5Qn`3qg1uXRPu;ar6a zyyal+(bwO=Cg2#X_2aenxQ*`cf+oL6u`g{tU`2UVvy3gI>Gu9-3B9ir2VbzB{XpPJ zg%oxb&ed-`DU&X-EVu+S$@j?FHQPIfc%K@};w8VU81^fY1h%FNh>D6;+K!mC_*}st zKoFJ*PPca%FF%e;I5bjG&insF1j2S%&SMi>#!!Els*CTSAyyOFj#{5WA{w17O%Pd! zXU6-Sah(9NK8z+T8qB=6jeJB~K%ts;s0)Bj>~1*)hbr4lVsqB6`qp#h!S+Yq*$PNU zutgkDrOu~4`!pV~XuQ?K-Q5Pj(=Ov7!7hB#sV$UzQq_YyHz79;x}WHICy^6Kj~Zv= z0zjZR3WSZ;i=ll-2A%@l-FO~smZxMf57G`325~DQHbdnQSD!Yv;H#kPsCw6r?mH@{BF}4CQBg?AP8ERN^AU)m zS|}&hUumP;q-$vkre}b>VdONJg~!T$SuHl?dwTmfW?FB?X_^1RACX#!vTY48swG*( z=+sS=iB*thaN&>bw1|cLBHC(V<*}ZM0?^XmK|)#fHH7mGSLjfgfyig__!%&BEpBEH zF;GpRh*O-;lA~oexj=&^mx|Q(td)S8Yo@$H@psXoa?4MFKi9?&&AEpni$4N{{Tu5Y zKHRe#Q6s$l|B!F7b83o@haRPU|9FM^bTEC{*$EuabN}Lxn|>($RCD-MQUKmvB-uXQ zZB&;}jV>{bIcnNsyoel?CF*~*05!Cgo;xsUe6EVgLtlO6B80yQvtlR^HD{|^XtrE? zg%&h?E4MwsN~Q|onab*2=LKgUFCE3&S%GX=Gc2qrdNqwe$>9jS>t2#4IEM|Ty)n9T zm43Z6;5S|7Cj&g@f6FqL4?vFqd%pS;06fnqG6G69obyyxD}@I6=t|GR><>9 zl#|$sb?U6G8`K)I8D>WzPZr8LLt5hW{jNvj=u7nuJH+r(D`3VV60peC{tP@Vn)J=L zKmU*2kPT9#b@6?97I3#+gS=e{-^=wsxIC+ovRtSt8U@RpiHF2WBoSisrilPgV6?t? zo4BA&Rr;5TsA%v+fwwBq000m;MgW1sC$~4qtq)tSQ&+sM_Ht8Y~v0X`Kae&UbF)N& zJ8b*od6eQ@<^cf0MZh-T^bTjEeY2gz(p2u?eOliJSd9shUAD|ou%HnYU)|xi<7oUb zFut6KI>FeE#iw)^fyA3g4ydAW=Xtx+{W$n8u-iNr17LMzD)XSM*=4wy2`W_9J>uD% z0ZOfGbh=pjER4#TZ}x;|^FL`3rOP(FYIfg`%t(L8_WvEYD9CbT zV(}crv{q+3UyZwTW7m7U^5^{)Q!iH3Szu<-2>&;+tQ9$R@G*Uac681vrmsbXk z2@|0Rmd>n!ErAXzA!0HpQCNI1OL>)(ic=-hv3ah-UOuOm8yli<`K`%u7PC_zLN!*i zL=;T{^9qqRm7LEJ$f>x}LFYsbabICz1h^JD+qJEwd4PTU(n}gS$Z3 z6GcXcr~&#`el%`$1JP%D?2%wPu1nS5uXY*mHNKHi!DM_7cx_=q-5a6MJ5^Wf-)-JhQJ=DsYF}6LM=VzOrW_L{|e8u16~~u`!KnJa`I#`=Bnh;J}mUNeHRW!`L6gA zp}1t33$C*`SP*t}2%Q>M-bwzgSkkQSfT#zgKbANOU@W2uIKnhj>=1v{Ic`wkn{#yK zvZ=j~5lNaQgfjhlC#TE7JmRCl1hf{2ebqvK#^;i8{xIsD5vYxd^(wPJZ<6K;q?C#! z+m!R@X1&4-eDPmzDR&5R{{~B&9~%Fb z3l7K^4G?saA>5uJQs>Ed`O6=LvDM_ott!d{klMO3JmnYu6}R4hZ9_ssO^z>N&*39S zSoPoIkNIOmT#H}_d>Ppj=!g>{Hq(J0a5@X8Tdyrg%&Ve`qwx3lueF+jb32@s_{DA( z&tfRZtnTyW3$~!o?VIzjS+(`yXry7mt&{^hx)Gc=2c?HsshWH9B}|X+9*w_#%~ix| zEe3E!G$|>mkMn-mp-8w1K6bxFgDTzDgl=tS4Ov-P<9!58l*j<;LoNRiBA9;PxyoHI z-|e!cB6|XKwvf^BpxZ6givS^Ta;Gdj9A0{QFrEK1l((>i^Cks`e1@Q>KTmtAuFAbx zLO6m^0(h1y*=71C0MxUQ{9TtLgK_9y)lqCCqS=(3=1+@i449@<8gw)KB4t?U&)tRr)O$8aD>t)7R%H zs>0mAOs7%H!|=T%`koo(EHPkVXnN&mcmGQmT+E^IbfL-t_e81}&^FQ=T9aJq^K89P zx<4-Cfz7BMf<;@c)8u(ZVIb%o<6cfoZFs*`5a-yr_3;?g5|dnE&>^%=nVpkkY;6+R za(Dh(G8U?r;HG?bU~Ymcn;QYS{GKdnnS`cAd~+uTM`}aTZz*aY5#?d{kRBg#OCPef zo^T2V@{d&rDiKQ2Vw-c~_+L2!jJZvJ5~g%7)A5%^+Zvf}ztNpq9G>OJd^n=+(!4z-$+Ma_0EOF-4ebaEU#fwoN=+?-rnN? z*y=lEc_SmsK-)0h_>lpU1!R}*4k|Qc`EwV4H4|fyX7|S&RFPj*cI+9`6_uE=9r4Kv-3EcAN4u!WIsWm5nVZw27eFq9GvN&VAdt zGE~jpn+NJ5?#_rLQJ#MGC{-hq1v_AO0WiV#xOXo;v(YP|KiawDNB$iz{|Vjje}qF^ z{yr1wB4|;nwH_wB!#HHVFX*?*<1<9-u*|+&1A+Zwu`9qAf;)fTgg_@uRc8gKDl%+veQ5@9QPi9{tSBx-W$Le&@EIn01IT*Kcn-9^%8KFi8p6_l00i;NtT zz?Ay7%}+txL=^bba?nX1V4WtiA|S|;Up&dO+i$x%1_b@AO;#VH;&pGWG`5RknwXua-C#5+0L{Qg>VRIy*c2j2eWQm9_B!5m6%3pH`n5<}PS&now*cQ9|2^N3&C_oujJ8ja1U4>l&dAb|ZbX!W zfQyw5`|}B?JN<#h*vu?8yB9IjF`>nAa4Yl5$Jh7W*=`-0L90((1d9p)g7Oq=FuV;< zvw0YnS24?~P=JCFz zK*akdh^u1#hMs$(`KW}|YLaSxY3L?Ym9E?W{u1F;=h%@UMja)Qd#rQ0v!fC15`kp@ z$NH@zF{psKC3^-b8o2#a#?u&|m>^Uka{p1xO71!RkEN9ZWGye3A06J2QpQQBB#o+I zq2}L->sB|<0??MIgIR{~$I-=?N~+5cg0WD^FaGzY zuZKlH3mn$n(A=j^-L*N#wUg0?qRj)3$0ka|U8W$6;9j|!QM_D0!azZ_iRE{f$Fi0m zS<-GbWj?R7n4`#b*Ka(ToUB_lNIwFt69t@^IDIVyni8#}1^ZDLA{8O3=o-vmV zz6#Yv;m2B)hwkIz3m%~F&`R8mwA|X=4T~Y-?({u0UKsNzc@Qd8DdEE-(>9DMD4;Dj zYzZj*HuI{|%0hN)!IVr-YI;tfrn?{@(HdXUxZ8<8Qc4q0!Qt z9osw{>BJ+~M?}Q!xmIX!+o^OwOy(4GHO1Igmm)d$CDlj7X-P$B3SaN%i_vz9fd@jE zHN!B78xkL(1Y}^f5XjK`-gfPO58Z^dmK<&Ho?9Ha# zi^%r%+JGrWdTmj1cqbioD(alYEOu#XeJ(N$!4z;7z`c)9?HZ5b1pyMHY_o#=M(_pA zD{Rxy^zZPMT~;sA=xu*c%#q)(uKs<}|3>JsW(WlvvbLbz)|tiy`zebMon(ad+v2h9?Ae2}%|od$xH;DvcTOhh5;h~{f8fA-nQ&*aQhz*T+4v2 z*mIn)Rv41?<3CY_JL7P@)loz6RYAJ>oGpN1Oplay8fk|@&kV~ccBkyOnJ3@ZE8=ho z%cjwg`+1z5U1|SZ^axE*M{$CCdZCMkW_K|i7@1r=?m@b>0EAZRCJo&!{j8d+qcj&BI8s9!7_UIrdW#Hl~2x?kXs+;`!?XC0SO*E{JtzWrUJ=?n= ziJN|JE!j2QmN;!@KT4!UZNyC^PTNtWdO-!o$ap{>g5l7f(D7F7xO z?ALJn3o%@DTQ<<8>67xe`uGQvZs4u0s z=EuKW$V4r(Gn2!8Hb@V`u~p%>;7^ZZo>3R}-AEWk$=!LQ3UY|}dojPB&dU8E$fZbw zl~omW3~SSL{o)dT6Vs)uNAV_O1duLb%IuEht=|Rr-%Ql_YkHUiL z#0oE6qZnD6Q@Ggpq#C%oev17FLesU8bG2U+hF$=~3~!GY#~UojS8G{%z{O?Zb2;J5 z4@YA&VJ8S<;}OT@xoBD=2HP$Y^R|+P<%dP$MoN>(M#zY#<`aJnX8aA=8yYIZhQ@1& zl(N7!Q?AnC&O}Cf*Tswp4wf<_NJyU16dsPV)f5x@GrKzuC1K6rkys(ONuyl-f>w3v z8d+nGAc)H{tt!Ql)69OPac_P&3qR8<`XlxPmg{r@NRTG~O~!zItQS@PYLLzGvIlO} z8N_l)6)xm&)%DSQM z-zPJllSQ&cf2kGDU9_RX{zap;H=HB=@6{G3FLkvp-0ufn&dJ!h5Hx|GsJ8y5oTP6- zA`uNuxsak~%Gl_?vq>Ag=AlP=HS{p-qj4n$1_o}aQyE~;sAKBor26oQC&;w5M z&0cv#sYOz+ZGUV!-M4l+!f8yFSy^))>vLW#2&c%=1GlS%-{SzplEM+)CQ=0Z=k41% zxd=R{m^UZ;ap%Py1`qzO7`3i3*yW%d>wmbVibLw$g?7NTV4iv+GwfW1m3u0(MMPJ( zN(8bGUP>wq`J9j(OMws(NOB_1(%`kR_0(lE99GZJm<`$j6m04dBFTEm&aY8Kq4tAU z9~4mrR`maa^8VaB$FglH!4aMMn?H(i8fJyYD<&}4ZfARw@Dd>s2DW{H6zO55wrK45=I z(0Jw`Ej8Sl{*8=6&3g-pUb4aH2<)7_&BUi$dT%?CnhY6?W%eDNt5B(53rYuLS256} z-cM}j9}$yJ@(Y0q|L9$$%H{5=BEA+kF6SY^7TA2?upg>=o`!BaRmXdOLlD9}5(>$Y z(jI2^T9v90EW>%#`L2kwMb_I1M&7#(BBfkKpMf~G7obHLMnLSm37HOW;;saFouf~^ zWCT6Jrd1hjz+f|ckxo5+Z+Ez}6MDAQxAnyDApe^c$xL?W^GcmE(hL52_*8Oi_v|XJ z-C}K6Yip~rzRk*5fzofs?E#e#A4HLT1AXw(+=|hteYRod; zXO0{&>GL2}o2_wCy3TZ4?X2XO$&hMpJ1-c$zYLW+C{-WiyYIQ^(IOSUV-n6nY{g0F zjjmXsKU`RPSTa85#D$}|yXAh#65MK!z8EL0L2DDyYW5=a z+n>|G&>p^J{#l)2x8R9S8SW}-P>|-6%8_9cgMS!+{@)1%0w;i8Io{o0%@xJwd+#cr z0n(0Ot~)Tj{&GtXdQvNn&!*-uGG@fT%C-;Fd$O=t#-w#`B@eYP# zvf0`^W2B33&-@CS!XuG^%S?H9h&5&k^MlMHW3$o?Q}7y+;&{-a6S1cM{;n;gD93$_ zEgH)A`Fkl`dH+Ba*L%CfR)NJ+G>>ZN2mhpvQ&3eb*?C(eIE7#y;J=aY_>+; zW%++S%W-_Po7rCN+K>0+uBhr^}h<*~) zhsJmONeFx3FhKH(@xtm_U%$^KCTr*%<(D+o6cbr^x1O}+D`=p=|I)d`m^@zLFLZe@ zgJd>zaE$i^09z(Yvv%{RV{p@D>S(^+mr{A>DWuh+CgkC5K94O} z57i}WgM5tQM$Fsk_V(@e-$XpSrMke9k`l6oaXQ@vpgGU+cHH>({yxht>UwXw4G9r% zxH&`Y*Fqd9iUiaY)z3oGwYW%VHuysX(7D0>4U=3L%nPhlog=G7WDPgK9f7X*OFPQA4(o5E_>*Vb;A7f#GnMMQj1t~50? zG;9H1zyXk9FCc3IlvOC(&cmU6Tzcb`_NG9`PxesJq1l>4OY7;u5mL+5byqUW#=vhO zp>tlSSh-#k4?oae6S zj;4T(a(Nk*4TXqz>FOqu%?3`aHljDek1#$`JcfK--GX?hDz9ZRejJ|m*iRNi*QLRP zv{!9kwqzjy1sp^Otc?%h7O~< zU?VfXKql!7^C>ZnzAZ@9t zLI4PIW3ykx+`P8N7N%%`(l(w})8N=ayAHq!J%{{}Onh-*(~t_eI(j==E9>i|CiJwS zno>BdEKmD${YKL+d!@J<4r{F{&{X^Yiaax{E> zi(R+wDc|42W?A4}eH#U;;l!&vT_h|>Znt1}!jAjTA#56Mrm%oduVLDLxY}m~v*p|i zvSa)XgSVF=^2{)LlPk}UE#ojqWN=T-9#jy* zz0K>nzs>dYSBlvOie3txs_QqBvHRrK)i_OBKm2~`*L%W;p&evuy!Ht+X(=vTyoS;v z+JcgmXyW9hALT}&x~GAaE`&qVj@_YJ_itH}+W zu_n`hvDHC-yFi}F!qVUj3ZF(XX&v*%u>Nj|V&n2m(Dt<nnPB8&6p5XuHLH za9WTq;Qqu+Z6@UZg5s{zBVo+=I;JN@klrV)aMDnqpO6rTXlD>aLkGF@6fIb!GSmto z%_G*Er^j1qv^HL5vq5%y({=O!lI0qikj9U8iWc^eG4&Hvjt8*+D0xyYuh>-#eLrw? z%Ksf*IPg$hZN3c$E!|6iH{9o~reBH@?P;?ER>y=^qZnq(9od!mJzJLl`@0?$sOO+D z!=4%FPcVk$cp{!ID6Nnt_s&tuCFp0hd>#z2gN~BlD{@mcFJ; z_9JJzWq>H9I5>)S64k_aYYG8h%WO#1>SRjn@z;rhPt2R*MXrY|MA(MXxoq5U)6T~O z3#rL6xAv=Y77!*9i$Z_G;f16*C=N;BjZJFLe@%fz@L)p;twQo>yG0;7lYKAXK&zR7 z^{@PhX!B-cYoc}|ZcR-p*1M}?no2IORmp+T%WGM}L=UvcS<&lR4h0~v^Z$jwcu9BJ zL!%X<$jOM_zXsS*=y)}k+$o;~`k^Up92pNMe(Rs>-VHQHl_F`ed7a|l%o^OOQtOZq z@!PG@Ll?_bk9jnKA+|=dK^Y*-zUMAlU!ngFWg~@lG$k<(mpUWGLMHj55pROWYB*R& z1QO2ltopF5+MIXq{&MtJ4coCP{u3I?I@?_#`X|%^Z<=(N)%w3$04e#7t{w03>^h{h z^RFw6dBsedheQ!r{UBC%PrN>t1kc3p;l_YDl(9eobBO=X9D@IQNlza)gS6r@LTFI* zCW>nq4ZK^s(hqMO2P~*{GzsZapUAGnV^_7q-S5J>m&X~v49+MfL*f)?9#NR!=k0ra z@rMx+NJ@7vynH^TV0$x+xng4c2rK+nle`_(PVM&SMIfc0#Ek3=Yvzd&GRX`n?dW5a z)SQ87=lKf00QVLTNOhCpdR`9KzPm9&KVfAs=uFS{v}WG()jm3R`~dsl{?A*z+6Rxh zGHliHOdXmz%TGw-t!G-hGolh@h0}i>b?bu{IdoNEVo&&!wK;PgwXE9hbBL{Hog}jVZLK__=ES95z%}soIRzHK@g00(#WRAGB83I4 zQgnz@tfX86CS~kk5w{+1^vOjxD7hko5(qxPUa)y@FRab792J_iIFDQ%V+3b5l`h|2ikA!PparU4Bval1pFkw6RLA&%u)Vktc(~9bgq}N>e6gv z>W!Kkt1{^%jCsJ$$pQ*i6=vmsFj?87nJS63u5p3uD(9p-`(Bo zex9VqLXA<4w>(-}S|*DjIIMM*l22jkV1mMWIji}_#f|xdp_WAi6>wLNF%S6Q19$0C zFoU}F^Y~6wveHCT6l1Y^S&W;F#~I0aS5xYMv3(?vAai6~NXBukzlQGHOllMTCX!tW z(T*^a4|KS10YLEkA@7%Ra~XgD?ds}+0i-z8Csq=K5 zu^{!N3pDp_sUT-W)Fa-I1Gi#I!{^*mYQrwd)5pIqExu1b9$qFArLta5p9x2fRthX` zvG>B8QHjr(w61WlhYh83o_nlw|Hpr*P>dEvT~nm2J2rQuKc)BHhvq2z6V9a`m-7hZJC&Qfpgvg&)n}| zU|L+8qb32uLhkb^oH&v#r$L+?ct7RrNOVaJ#> zG?!nZefhoU@hC8_1j3EW-f25Lo7**&xTJ)0hQusy>4dK;$K#~k`%emG;G=LW(}M2F zK}>++-dYR|4>f&?M7cfb@&9m%CVn>AJ5i}Ec1bXu`e&Bg=~mna6{)}WPHp4o5*zqa zF~9FJ@;1v}w2=98=hIUd6vbBS4()iQ1zwFq?Ms<9PIn)g#D+;|(-;RPWbfjMAI<3C zXHlV6S+-<`A_kjr^hT3s7}>T&!IVoSs`SW-8Gj(w#%=Z7U% z%xLC_cuctQF5M>5CYIMkySvVAHb;0oFF}uja83q-cDl3OKaB;9EiD69-xW}B{zF>+ zp(svL;6U)B@HjKUMLAbl@Y5atzSsPnTmz3%7USGW_wq9G)xnppXqjN;V)1Wt8O*P% zWRzQc*JGoUirF$QR&nmv02g=D;zy8}A14JQ$T#WsHm2d$-kZ2hBt|qIFZ$t+ru`X(h=J2TI&Kc*lphz8ukfCQi|1XXqM003%i!M* zH3%=*zx?ZW$bmXjj87xHs~md5ZhqnWWuv>6#|}ssg9AE@c=+ZwHtJTE+ui6fseAg@ zcShtudlWw*JWU9Py(5N1Kq9pd+#HGO*|kls1S%(r8@UJj4|g*$#ISu zocFRsnnMHQURkbSk@^a4o@1eb8ZX}XE?!BLd2vhR0Dti>@RDJI+hhr zQ@7K4w!`-sq)Oxc(2p!R(iHruBC^@_eZ;_)j(V%Ci07TJ#CisB*W&@^J{NiTJM^;6 z^IVM~i_#@KIKj&0z7Zefc!3n5$VA(L2(dZH7pV(I^S9*LftZ{4#$zu%%5~mj2H!n^ zn6We%jj$w9pFA}xokLWwO(jF640d&*F ze-N5x1bz(MHW*1SgMD5|V;FsHZ-1fN;Pgi#_lq7zzFk_Rj7<1I+s#z9#~QbM)(7NF z{!4kFc7PploeW^W3TsL*6kcf2y?bY}3Q`Dp2K?d{08nfqBn;Bs`tp5Z9Y7cJnBuVkgfG!shiVoVkS+<=2vx(-QPkwG`02h8h-hLf_c+dscS3CiM*ib`2WmJ#WO=6h@AF*)V&<`iUIN6z#KdP>YDb z5zlcd=uYfc6wsQSGabTomg{_wL1<;ObQ304K^B-A1$ zUcHL2T5zIKeDFwm(dyXU=J-V)o5kP&h~q09qcSB~yUd#GtR2)?k9{~lnjm7DJL)^F zfh9Zz43%aQa5{0|jS@xFPPJ69ds8cQcss^ z;D?6F&Na<7v-B^zed2Jrr2?`VU$p`~b=F{o@1C9je{r?rgnTp^7ondwhTNQ0ONYIb zhy*0Nl@Ml8D1z+dj?<|^Fn;rgHf#|vgMx7Q_5>JD#w8bln;281I+^lZ(rl-PKy;HvJ#$`CdqBypEXq1vk%naJE)Y(Nh=ESH##ubaNi=$*$Yb)k0WVAt9yR!F@e|T z(#%<~so%v*c6e>rkpxKr#Uv<$@-2W?UUYwf5gKz?sv%Exd?zRje8Kf_-XHXE;`v@x z3~RnOg^sjoAV?uOozN|KYg$G?B08_IrWt15Bo~VGBMc5wFbGA6iHl+4y#3~T1M41Lj>e9* zH)sv%d^g&&H0My`JN5p9&1(38q8s|?!>F*U-Q=q;{0;rfxGv!FOZ$~5!cEIO%O|o_ zUR#sDr|{%2s{MN3B$k|Fr#IT9@440W)g`ZICp{T=g~JnYS<{^O6%5;7*14#1(-q)c zDl_~eC01*D^y(d)(PP(7amkYjyK0UE!nXlpxd>jo7-U${tX`|#aU21gePvg?%`TLS z4W;9RdAbj)Kufn*$DW6xv?*k}GYv?Mm7iL48{IeIUz2emQ@`}+tGzKzK!+aShi}`r zsuY-5yV}jk6a|%OER2nUQU`K)M^$F&<+g4>l1md6mT0R$NunVS(DMGHvNFZr9k3;9~Mg8shbtsYsTbH`&7rRK<^w@iCBX?KsL zsa!r(EgpBcn*$0;-2TQnBJRhF;gba;`LdgM{22NbK)K-A6-$u1nmWap?QK$b0~S;-VT3LCGh`mQZ!q~tS1a5H_1$eYtE+b2BjKh5?4CP^48iA0v~ z{j4Mm<#r>A&Y>zdWC~95NcNd&U;x@u1N#Q`%DI`H?+NbtIHy%3C5RhIdIJB{0reO- z=OqiJ0)f`jobCsi7LLIF4W@-%N z;&;2c4N`CB$Ww2jg05C;EMV}`B5h89s`pD3I2){3R2=%zS2DJ9hY}b2Zq3|E*+ODX z$1Kg`Z<@0e00Ou!=-aKA)pwjNsTwgnx^OBk|RD8V9Ud`_z<3da7s zl(N-un@ANuEDboM(97$$5;u`DBAe3WRe@C^Dl?Sh&uG8`9-h(4p z>X9GIGWIF#R^cFDC&Qw7#|b^`l4Rqy@U_+Do6Dgr3D+bRkF1|ze~OE(+Pp6#(Lxo> z2PTe+mAM$!->v<9oZ>`8y3MT=m+nxYtr!QuF31Q_As*_H-gtqGk5X~0(v@Txu)NwI z0;#qasalhek|D%VSbeDL-T5gLPIUL5Xxhlg{9Xfb~B!lprJF zsOF@$^UbQ0S6~B0kdPnt%a>~=aNlqIC?J_4z#SjN`PNgK&HlaE(%%m^Z-t%1-{)*k z1J{zDc7M8VyO0EOOZpag5n_O*S#RU0+%mJ(+yQP>e_ zMAxSVl-rtNFAe&+Q;c2zgsE?cZ$HFEg}+CWPV<#r72Howq{3|A+xLHs9jb6$$@fYi zfFv?|t=&Ftv*HeyTOE*OuAewV^sI$lnEeBe39AlZdoZ zA7J_Ur!q!Jxe?8N3@*I*_*7x-wdI0~H?g1sY0N4#keU20q#pUA6*!mh-BA}R#MZTc zhw#V%nzK!t-?-B`5&K1}zs&rN<&3(k&C^2^fjN7=yhXs{1UV-i#$zRVgxo{eLr6Pv zM;|-&cpi(bWe(u}e;tuvQQosGnNjVsY3F)y{lM4bLs>$E*w+5-l~`^gy0}FJqgi90Qh0Z$K=0*A_#5$CGeVeb0Fb+V7vTBPWlF z|E#@i&)M#MiJq# zIMEq!R9XMR7%QkX;&7+XO26|xoBYp8pt`vM={j~?g6c6fVs>LSr0DvTG0=by8{LWf zt+=QF;%=$VYTox^<<3NR(xIOXfQYqIXaBL@;+kfh(6zeWLulx@vvRSF3daj@1F^I=bE zh5I?TCeIp3>a}I1FB3?Py8tSIB{&~C0E7e@K5qQIkltNZ@cGCkc+Ux(^C9c&N}vIy zKRtcM)}IS7ud_wM{v5T=ftpmvirUt^h^?n7W2JmNGQWO`c~5UpOA)I%sRcwIR$uyB z{>$s2E%NR?UWO%!#6xyj@3LH7VlkCs3VPq$!ATSezli>jhq(z4U7u9l)LkSz;K+!U zLm8mV*03^=)j9KU1%LjxSG;?fy_Gc#v&{hjbKalU?!^*W&$SG@u`bGa{fa!Y_fFj8aXiSfMK)@p9q<^=j{TI9}d_J>IGdd6)pV9u6Y!eX;Ri&)D zX$G>aNCZ@L4F&u$D9J@Oi-`Ip31iWF02|9Hv}@Cr%{W5<*{1$CvwgHh{(fT;z{pqe z;^dln&hb*!4X)EHqNuwJ2uALb`fSxy5m2n)ObuAdL;-H5?Nzp0r#~HnUM-Z?7=nK;@ zkN7j@sVv~J4f+1sjG+}Xr<${Q4k*g-9Ltyq_Rxy9oxctqe59o7(h#P0cT(QL z!K&np4!->G!G{aVlO?6A^I}sWg0S|8Dx<*C%drnfVzusvxvC_)NyD(_-!G~gWhE3X z{m%w|ebiW1`Px=R#XJqy&)uWniR}XT3O8~p)U(L>j$ge{!=A3p7ZK^QwsBI5ZIy|R zkF z7ZyXG8UE#psDw5Snn?vtaE+G*AtJqYLjeGm9;JmIwwn9mw1g(vS5&N?4GrM-)dk5F zq!3A@Kf^H7-K~4SP&~J#PX@67>Y2jR!UPvR81dT{flwkzwHdD*kS@O}#E()Z$Z5vg zI$HG0GmB43Y+CvKxFyScD8wM6r+Y#Xg&t=?T2z$%@<=#_VKb31JK{{=Yw0^Mu|bP4 zttaFWk{xjVGi{k( zIe&!S{$9c^oY*Ngo0ItM-?twP%r3b82Y|`mhzk`RT{X%=PF+9#&_6n`u8*XUus2Q! z=jY>$0R795-DqL=|2Oh_du0l0nHBN4d^s9}K9OgQ?v^oFO123uAI+UL0}@N|u4PA{c^iW0FO~5T{o-AQj*ScBP40VUR+Irho*a!n|G{Jh z5YDu7UhiC01h2ct3*8;UK$8C9*VjV;a~D*AaIuL#oXI_YzGqCXPBN6Ovf`_CB?mjZ zrbUi_ze_)C^exJ3)V|0DWOiqHB?1Dok@A*Rzbv5Hv3Zn-@paA{$3g4-!3&Norg1xY z8r9S>8G3&3!V9T)QiuC#J$3_yWg;lQaqF(U@_D$ z`8sDAsLw@)A1W$bvmBOOh`=BcuOsRpEf?BJWKzR7C zUH@3B3C@idQl8li74t!w*q6b=3PD8rsD-+Wsz2)UAK6Ub7Bq%Wk~6-@Z+D_}WJ}jl zK1NF{Wae{nz}^>d4GK=H0}kBP=L6Rip#UbxvBP2#%#-KY@Nom~UA~IpvSVEMO50%(qWI_SAv{!KIAtyX#4!GIL($$t)>`B8|xJq|LAetm&t>B`f4P< z&Dc>3+A+|-2Syl>6OKy37=XO5@1)tuw_UJIpK+?Nb}pN_A^z3wEV3(t&NZ1HU!Y-41n zkOQ~Wzf!l?e+EQU-5__hnXoXqNCnq>%%E;F1#bkOnbR z%o1Y@VAgiLe(QXF?;`(ZMCBzR16PaalC0B^&;oh?RSph;;3J3!hq(1aQOnbfJv=vAGgOZ5d#4}OcTK%EZCdqR~nWBok`E3<{ z>x4MsWujub@=H2S1z8Vq$jlC&M?)LUL{b6D=@z{wbe3brRXas9Pi@*BAoY! zH+r5Y_}?x?4lFen5?lY|+yx9~&%wtWXyI8V>^kD~yO4e@%dbq6`AKbDaL7%w&gpA( zv$@%-gz`ub8D1^(OQMgGgHmPKx~7H@p;of1>o;8CPJeZMW1xXO@fNFbte~Vz_pHj3 zkkb42ksX5SlSHw16;DP!9z^;xUTaSGMP=JIM!ylnP`=HZcQL=TGbK(~N5sZr+oV;b zE8$dY%2YJ`z-cYuH-+yvWj!$EUYM!KnWl)Rw6R!VSQC>%^Fb|;BN#chFcEvq+;wLJHsnYDh- zR{F-2vptEe5}G?HPi!~r_46THk-gjAvkLpJcE{Vsp)cbZNTFr+= z7H`4_GzP%~UD<1^g`lUU@obH;Qc2w={}949M0GxWA5}Uf(2UaKc?Y6;Y=EpYS%6yA z$za@|?dRiII0O_#^{&FO;Yyh@cb=!B4i%Um?lvM!W5UQIx&@hSf2^gbzHVb&gM<}h zH=@;hK~O#2I$wb=_B*$A^Mw!5rAA0x>^ z*IExUfGn)+x~rg3$QLL+YzlZ(VpHTTegk>$$b1@2fP1=IrcW#lGEobCd0 zH*gMk(iuq_p=;3icom_u1N;VaSj?i;1W&;rI1MyVhbo@uY2(a>_*S%w3Vw-`j> z(A&UZ!eXW6uyxkeW^E5&1FQ7+t&WFI9i1ihGjWPy_{a~uK3X%x=vM#r=L~;Y`ho1p zD8@E-67A^55}%L9(NUP~vnj;L`%5Qlz3YCi^w*~){S>91DW#6mVKD9D8H>-$?yY5g z$fiyNrHUXI7#{(J!Zi0PWrW+4$5$9;({s()oJzSo3=nZ zDl903%KzST`XrGm&WT?k2e27gP(jJaNMh~B;s&X;?W3MIi9y$Fm|PLtiRioU(-ucLl z)I^SV{pYi$7Z=2mrr4N%o;zIIrN4(A-Wou#0IollnD{_49dHT?3{|%yPZ0NcB0*~u zHvAVq`rk!X+`q)+<4HIf(Xbl_!(#HXIzFxdu`SUDDHWRcjFzJ6iP@&xJmG`j1%T5; z|Bch+jG3Bzohs8GoaGM6nvgasEFpTMHpGugFwPX)O!Ll<=i9sNH1A;;31)*}7_nqR z{s5Q5!lh{2#i&=*LdcX);*XlemNg10sD<;xHses73zR2vUy*BHV69zz8{U&C6^2)r zV(2T)!(3H+49vmH#F=co^mW8W$x!=SQ8@T0#236|8*jQ>zJW6Kv}(7Oy$%*Cp{tXZq!|s60S9CO03v)0SBsEOTBk~zQqN9YIK8-4 zLMY>3ncF;b10F{v8DKt_LA)kubG_c5QRa&B<#Lc?hXX%1!QMc{W7!}Bt+i$tq4gQwM#Xyoej zriQPzke;ZwmgO-L{s9Ybiz}bup|QzX2YdC;pR)+J2ujaguWU~;$Zf2QwXcra3~=GE z`_*1A-3F6WLIdIkJ;;q^wpx>`DV{}@9AW5O*-Pi%>S~F95teMj$ZhR)6Z(y3Lw)4q zOasa9^d5nR7OPJ^bEeMlfXGfL_Jd+CI!Y&2g%~qCb!d|!o*ES`r;zt~JCz8LmXZwL z-Z!x-Lbrav_N>59cJFuYW7@;cZ&!6!I?OY<*OIRtFphmrsN3({D~=aiJ}xy@daRAY z8OlO}=RSl=bRQ5hNx{J*Mx)SdiWj_C5}4)VqHp1yET-MItuMA~P*oL^8qK6iNKncA zB2sueOP!vn!^K50ti;BlxyBaaS^Qxt!fedTwcKFSuZo`ETay+xTUP9wc?R-mBGZJ1 z=!Wz}B_?|`iS3zNq#x%q0z~Be!38DF6!Lx;6SuLlo9S0zYVhwxM-5RO&G{55mCx^5 zt%!^PQg+h-A1`_*$bCYMnYsEz>3p1`_^abhs6>t4nJhp?iW0;h7rB3(69lBv)#sjq zbVG^MHFWcDXh$^SG!7RCcS(;YZy;*?b7wU>7Hp~tt1OIT<>%#DYYwC01!-?+eIWVq zE=1(>WfAdHjOp#VNakFq&_wT0a>7GpC7(?1#qSI(wrQ#^O^i5|f1h8Ihm5(>FSx9F zb|{?qI?7*IvRaKTn(KmXYUD;Nyh7Jj{bk9?Me<|6gJviDl3E^SXLObMmg>CyJ308S ze8M_fg#R10@5Hyw&7c{QmbbCRpHEY3CtW^RY9?7g$F)=-qvY41rX+(yp{mAX7a}s^ z={(SkE~tr{p_A`?TYOBsAU-t;6tHvXTW4kB*!eE>4Fe0c)(!2eVM0~7J? zqq<)vIuSXkvd!hof*m`#VTU*IE}Y;;XI$sUv~bv1UT~Pw-syz*_Kt<^+2l=WWfuOw zUbVHdnoU!J*cuzl9N6pUp&umEZS#cv4-nv4d~d_47e+k&!Bv-q+LB99I7f%iMLkX} z@4h^*guE3ZKdvFATR16ZtrpO-albe3>8hW<*-J!7JZ=0_$*(tMnrFVCvRl)i_!R>4k_4*tySK>;<=NGG_FnD~R89uAt^^2~nk!jzb#RqA+I4tzjy zd{DziH(6D6Dj*v+6v3eojbUr&Dr!pI9{Ji}@>DcT>NW#cZbXaT1uT}vl#~wsklaW! zW(k~~nhCHf{<-Y-oP;9ci=i~M{R47!Ny)Tf3;eR?pUNSUUc)0Jnwpy0dwY9o0eN^a ziZ*t3^1Z#77grc1MXgE(ne8^6^94IQ?%U99tGx{`-5R@~WM;YVIJqB&LsmZ28i5iEqy}nR@0KWyV_=MCz-bc!s^~Z!LN$9Ut*IM(Mi(dN}B#imqHs zPl?X3+=zy~ZanIgoCZ!-#Sh1jTGa>GEUpo$uq*%udnkNQ-q4{4VM*$k$nOnS&TR?_ z*am9B`MbZW-_c1I3>7D0smjTPik0Zd$&P5r+0>{`?$9S1<|=!3r~(5uN^ll2UNUY8 zx|gN-{s0BE8yY>urL)$THB@{$B3;?v-_r_s$_WjnQVXWE6vaUeNzBSBJUl#|7PZn; z$r_f6R5vs%AC7##4K*MCDXD4n2|y9U|J>K7%GTe~sOB)&b0A zE}Rf`N@ybpK2)O7^@raxay#Lz=e~#JEZgfM+z)KlH|qzaf?5kVdw5aeV7wIlj%dzg zFR;kZ8X=)1+4qw0{z74N~!$@*^x$QoMwJt(d)VF=xyS2D*pOYluN$MRRuK;SQFL2L?W z)`YjaX{bcjgtO^0l+7cEJRKCBACa%*D$~=>6Mw!4!ge&|x!-qKoydNe>J8HK`Hd$J z37+Nfnf(MAyZ8ahs4JYD0ftSb`%0<8e%D_LPz8P*$^XVjIBv46tZV*3;=t zwla$;ELr9j}BHo%V8qeoRtqL4AtH_rBubU7`wIGAx3 z3a}9liOZgk6G8lWSeb{0wrUP|#yo2-4-P>Kwf;kWSy7$V5_vl*K`hdzX0?>T< z4+V6myu`Hujt^re!dM1pw4=u6`Ji+OTI3Pd)cRDFyrzES#ez!VSkP4>j?S2+mvgaX z57%!B?|jU`-qcwM$H(KrI|$~pWi((Bg#>$15nv(JIg}Ftyg${?0YBzlwmWL`thLYn zn>w^B@a;l$_s2A_s-L{sy2q~d2;~1P2;GM}vgS+GCQ~gY5o>hL# zAfx-EsTNpJ#?6@x^&*ZFB8VL9YdhyJbculhZz2;2BK}%9dIBu&rWc@22Az+jGubkB zR~&tFyXp4x2vCG7ks75mzBJwHww~wdbYWTv&XmV@W3F8Ejs+56c^*ah4O2lw>lwr$ z*e)-xue?l_6Tpm5!Wi~fgjh&T9_1weENflgpibC#n;^h>2mAqv6^%E*rt$1pqqOuh zyY;?$oQvAz^bHkMy8i5V2C!V>DWETF7`SNH?@I^)Du4bDDyMcOJT>c$IOzV|_)BHV z#gGU>FsNAJciSx|yUEBLdKK4YkN`v6pwqE-&T0-#fc;va(=&G_JN(W`gX;dIEd;3l z>tNB9M^1jfUC?ZRX#uo>K5iMI!6EB+ZAPiO3v6R6RHo~A$P3|jLOl(ilK$q9*T!K& z#d|&s_W@u3(Zp0}OtXN7_t^(3Ma>G&;dD}lLOrGxbI({Xp2wH?1&Q|IFZ zDebn`&RN$xKVZMEx-N0!VCx>Klq#n_gKwVo(s3lv+I!EF1>F_*@s}ZD3|VveqRy`* z@)NvIZh~8mIxg;|WD)dEw(eIfZQTU;l#KBYSri}-6MBz+$FaimEvU}+(w2l+3lq}r zLH`nk%gSJ)L(|G^rRiQ$`zpWugIwJ3U296zFdki7A2QGf-wb() z65-~U|8RNYiUQqL(S0<+t{%-YB8UGTt=a{;OG92vm%}k9f$r*nX=VGp+AkgSQWo$ya^s|_Ez3T9 z`7g0($Q5r5sL?9pX0ue@0ynlJfsltc?-Z?}rg|ENV;FgN6;oTw4y3Pkya&OZcT$jt zmF%4I?;zv?wVJ8~N|i%RUo2oC(RCMiXt(ot)#^;%4D4o#Q?aie2~_nnTgcrIkn~LW ziTaCC13(sZmb4>4$oXYkf&_kl4;Y8QMgp95ZX7h}Y2;eez*!*6wC=0%5VO`%1-iGJ zvD59*8~<@h^Q*%NT0!TAyw5ey^Ycr9D^q|8o`6A*uq*^yihRCjOVG1|8rprJlcyyQ z!CrxPIN+rDJDbw_Jm4%EuY;^L|4M0rExwH+ZUDELU$23E^^tyZGKl8mtFmN=r*p7tq1{p8;(CeBQw(5Aj>eOU0Lgm=?;l zVElk>S@VhKZS8RhNd5zo#Y+KF(rdy6)Ai~}Y|K+2qykh+b5Fw*gh#CK*RiD)HR2W7 zjkYGfVm$UbmFXGycee56{QypSC|J&fY%Q0%`U0XNjUI#qPFsN$buD$oi)xUQTKQn!S3baN;5EX50MxWQc z`uW0uNLfj`%3I*BsDq>4%nx^sB%QFPs_GrI!(M3_Pa3i*ML0+t4-;+tvKaLaI`yvZ z79mtZvngea5}wn++H%b1N8vnaD{y&wJN+K+sMxOr(0w~xO bf}W5Mg#;a6em^jP1AelSiV~G##$W#nYH1{6 literal 0 HcmV?d00001 diff --git a/docs/samples/graph/sequence.yaml b/docs/samples/graph/sequence.yaml new file mode 100644 index 00000000000..eff225aa83c --- /dev/null +++ b/docs/samples/graph/sequence.yaml @@ -0,0 +1,31 @@ +--- +apiVersion: "serving.kserve.io/v1beta1" +kind: "InferenceService" +metadata: + name: "sklearn-iris" +spec: + predictor: + sklearn: + storageUri: "gs://kfserving-examples/models/sklearn/1.0/model" +--- +apiVersion: "serving.kserve.io/v1beta1" +kind: "InferenceService" +metadata: + name: "xgboost-iris" +spec: + predictor: + xgboost: + storageUri: "gs://kfserving-examples/models/xgboost/iris" +--- +apiVersion: serving.kserve.io/v1alpha1 +kind: InferenceGraph +metadata: + name: model-chainer +spec: + nodes: + root: + routerType: Sequence + steps: + - serviceName: sklearn-iris + - serviceName: xgboost-iris + data: $request diff --git a/docs/samples/graph/singleNode.png b/docs/samples/graph/singleNode.png new file mode 100644 index 0000000000000000000000000000000000000000..77d72c84461de43faf587bb3aa4e2f8e0bc9edde GIT binary patch literal 26360 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 p5?Aq%_2=5GIIa` literal 0 HcmV?d00001 diff --git a/docs/samples/graph/switch.yaml b/docs/samples/graph/switch.yaml new file mode 100644 index 00000000000..2d2afcc6d9b --- /dev/null +++ b/docs/samples/graph/switch.yaml @@ -0,0 +1,47 @@ +apiVersion: "serving.kserve.io/v1beta1" +kind: "InferenceService" +metadata: + name: "blue" +spec: + predictor: + minReplicas: 1 + containers: + - image: iamlovingit/bgtest:latest + name: custom + env: + - name: "target" + value: "blue" +--- +apiVersion: "serving.kserve.io/v1beta1" +kind: "InferenceService" +metadata: + name: "green" +spec: + predictor: + minReplicas: 1 + containers: + - image: iamlovingit/bgtest:latest + name: custom + env: + - name: "target" + value: "green" +--- +apiVersion: "serving.kserve.io/v1alpha1" +kind: InferenceGraph +metadata: + name: model-switch +spec: + nodes: + root: + routerType: Sequence + steps: + - serviceName: green + - nodeName: mymodel + data: $response + mymodel: + routerType: Switch + steps: + - serviceName: blue + condition: "target == \"blue\"" + - serviceName: green + condition: "target == \"green\"" diff --git a/docs/samples/graph/switchNode.png b/docs/samples/graph/switchNode.png new file mode 100644 index 0000000000000000000000000000000000000000..5fb822634f230e3fcde4bb02b7ae6efee47a529f GIT binary patch literal 55530 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 literal 0 HcmV?d00001 diff --git a/go.mod b/go.mod index d6d68525caf..6305903a67b 100644 --- a/go.mod +++ b/go.mod @@ -23,8 +23,10 @@ require ( github.com/spf13/cobra v1.2.1 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.7.0 + github.com/tidwall/gjson v1.14.1 go.uber.org/zap v1.19.1 google.golang.org/api v0.61.0 + google.golang.org/protobuf v1.27.1 istio.io/api v0.0.0-20200715212100-dbf5277541ef istio.io/client-go v0.0.0-20201005161859-d8818315d678 k8s.io/api v0.22.3 @@ -87,6 +89,8 @@ require ( github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.6.0 // indirect github.com/prometheus/statsd_exporter v0.21.0 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.0 // indirect go.opencensus.io v0.23.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.6.0 // indirect @@ -103,7 +107,6 @@ require ( google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12 // indirect google.golang.org/grpc v1.42.0 // indirect - google.golang.org/protobuf v1.27.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect diff --git a/go.sum b/go.sum index 404393669ee..2ececfbd931 100644 --- a/go.sum +++ b/go.sum @@ -960,6 +960,12 @@ github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= +github.com/tidwall/gjson v1.14.1 h1:iymTbGkQBhveq21bEvAQ81I0LEBork8BFe1CUZXdyuo= +github.com/tidwall/gjson v1.14.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= diff --git a/hack/image_patch_dev.sh b/hack/image_patch_dev.sh index fa89724ae3f..da1a0a8a694 100755 --- a/hack/image_patch_dev.sh +++ b/hack/image_patch_dev.sh @@ -34,6 +34,8 @@ spec: EOF AGENT_IMG=$(ko resolve -f config/overlays/development/configmap/ko_resolve_agent| grep 'image:' | awk '{print $2}') +ROUTER_IMG=$(ko resolve -f config/overlays/development/configmap/ko_resolve_router| grep 'image:' | awk '{print $2}') + if [ -z ${AGENT_IMG} ]; then exit; fi cat > config/overlays/${OVERLAY}/configmap/inferenceservice_patch.yaml << EOF @@ -67,4 +69,12 @@ data: "cpuRequest": "100m", "cpuLimit": "100m" } + router: |- + { + "image" : "${ROUTER_IMG}", + "memoryRequest": "100Mi", + "memoryLimit": "500Mi", + "cpuRequest": "100m", + "cpuLimit": "100m" + } EOF diff --git a/hack/violation_exceptions.list b/hack/violation_exceptions.list index c3f91d9c0a9..dd5d1786b74 100644 --- a/hack/violation_exceptions.list +++ b/hack/violation_exceptions.list @@ -1,4 +1,5 @@ API rule violation: list_type_missing,./pkg/apis/serving/v1alpha1,BuiltInAdapter,Env +API rule violation: list_type_missing,./pkg/apis/serving/v1alpha1,InferenceGraphList,Items API rule violation: list_type_missing,./pkg/apis/serving/v1alpha1,ServingRuntimePodSpec,Containers API rule violation: list_type_missing,./pkg/apis/serving/v1alpha1,ServingRuntimePodSpec,Tolerations API rule violation: list_type_missing,./pkg/apis/serving/v1alpha1,ServingRuntimePodSpec,Volumes diff --git a/manifests/charts/templates/webhookconfiguration.yaml b/manifests/charts/templates/webhookconfiguration.yaml index d24e7980f9b..b72c51113fd 100644 --- a/manifests/charts/templates/webhookconfiguration.yaml +++ b/manifests/charts/templates/webhookconfiguration.yaml @@ -107,3 +107,30 @@ webhooks: - UPDATE resources: - trainedmodels +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + creationTimestamp: null + name: inferencegraph.serving.kserve.io +webhooks: + - clientConfig: + caBundle: Cg== + service: + name: $(webhookServiceName) + namespace: $(kserveNamespace) + path: /validate-serving-kserve-io-v1alpha1-inferencegraph + failurePolicy: Fail + name: inferencegraph.kserve-webhook-server.validator + sideEffects: None + admissionReviewVersions: ["v1beta1"] + rules: + - apiGroups: + - serving.kserve.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - inferencegraphs diff --git a/pkg/apis/serving/v1alpha1/inference_graph.go b/pkg/apis/serving/v1alpha1/inference_graph.go new file mode 100644 index 00000000000..dcec2dc7e50 --- /dev/null +++ b/pkg/apis/serving/v1alpha1/inference_graph.go @@ -0,0 +1,257 @@ +/* +Copyright 2022 The KServe Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" +) + +// InferenceGraph is the Schema for the InferenceGraph API for multiple models +// +k8s:openapi-gen=true +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="URL",type="string",JSONPath=".status.url" +// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" +// +kubebuilder:resource:path=inferencegraphs,shortName=ig,singular=inferencegraph +type InferenceGraph struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + Spec InferenceGraphSpec `json:"spec,omitempty"` + Status InferenceGraphStatus `json:"status,omitempty"` +} + +// InferenceGraphSpec defines the InferenceGraph spec +type InferenceGraphSpec struct { + // Map of InferenceGraph router nodes + // Each node defines the router which can be different routing types + Nodes map[string]InferenceRouter `json:"nodes"` +} + +// InferenceRouterType constant for inference routing types +// +k8s:openapi-gen=true +// +kubebuilder:validation:Enum=Sequence;Splitter;Ensemble;Switch +type InferenceRouterType string + +// InferenceRouterType Enum +const ( + // Sequence Default type only route to one destination + Sequence InferenceRouterType = "Sequence" + + // Splitter router randomly routes the requests to the named service according to the weight + Splitter InferenceRouterType = "Splitter" + + // Ensemble router routes the requests to multiple models and then merge the responses + Ensemble InferenceRouterType = "Ensemble" + + // Switch routes the request to the model based on certain condition + Switch InferenceRouterType = "Switch" +) + +const ( + // GraphRootNodeName is the root node name. + GraphRootNodeName string = "root" +) + +// +k8s:openapi-gen=true + +// InferenceRouter defines the router for each InferenceGraph node with one or multiple steps +// +// ```yaml +// kind: InferenceGraph +// metadata: +// name: canary-route +// spec: +// nodes: +// root: +// routerType: Splitter +// routes: +// - service: mymodel1 +// weight: 20 +// - service: mymodel2 +// weight: 80 +// ``` +// +// ```yaml +// kind: InferenceGraph +// metadata: +// name: abtest +// spec: +// nodes: +// mymodel: +// routerType: Switch +// routes: +// - service: mymodel1 +// condition: "{ .input.userId == 1 }" +// - service: mymodel2 +// condition: "{ .input.userId == 2 }" +// ``` +// +// Scoring a case using a model ensemble consists of scoring it using each model separately, +// then combining the results into a single scoring result using one of the pre-defined combination methods. +// +// Tree Ensemble constitutes a case where simple algorithms for combining results of either classification or regression trees are well known. +// Multiple classification trees, for example, are commonly combined using a "majority-vote" method. +// Multiple regression trees are often combined using various averaging techniques. +// e.g tagging models with segment identifiers and weights to be used for their combination in these ways. +// ```yaml +// kind: InferenceGraph +// metadata: +// name: ensemble +// spec: +// nodes: +// root: +// routerType: Sequence +// routes: +// - service: feast +// - nodeName: ensembleModel +// data: $response +// ensembleModel: +// routerType: Ensemble +// routes: +// - service: sklearn-model +// - service: xgboost-model +// ``` +// +// Scoring a case using a sequence, or chain of models allows the output of one model to be passed in as input to the subsequent models. +// ```yaml +// kind: InferenceGraph +// metadata: +// name: model-chainer +// spec: +// nodes: +// root: +// routerType: Sequence +// routes: +// - service: mymodel-s1 +// - service: mymodel-s2 +// data: $response +// - service: mymodel-s3 +// data: $response +// ``` +// +// In the flow described below, the pre_processing node base64 encodes the image and passes it to two model nodes in the flow. +// The encoded data is available to both these nodes for classification. The second node i.e. dog-breed-classification takes the +// original input from the pre_processing node along-with the response from the cat-dog-classification node to do further classification +// of the dog breed if required. +// ```yaml +// kind: InferenceGraph +// metadata: +// name: dog-breed-classification +// spec: +// nodes: +// root: +// routerType: Sequence +// routes: +// - service: cat-dog-classifier +// - nodeName: breed-classifier +// data: $request +// breed-classifier: +// routerType: Switch +// routes: +// - service: dog-breed-classifier +// condition: { .predictions.class == "dog" } +// - service: cat-breed-classifier +// condition: { .predictions.class == "cat" } +// ``` +type InferenceRouter struct { + // RouterType + // + // - `Sequence:` chain multiple inference steps with input/output from previous step + // + // - `Splitter:` randomly routes to the target service according to the weight + // + // - `Ensemble:` routes the request to multiple models and then merge the responses + // + // - `Switch:` routes the request to one of the steps based on condition + // + RouterType InferenceRouterType `json:"routerType"` + + // Steps defines destinations for the current router node + // +optional + Steps []InferenceStep `json:"steps,omitempty"` +} + +// +k8s:openapi-gen=true +// Exactly one InferenceTarget field must be specified + +type InferenceTarget struct { + // The node name for routing as next step + // +optional + NodeName string `json:"nodeName,omitempty"` + + // named reference for InferenceService + ServiceName string `json:"serviceName,omitempty"` + + // InferenceService URL, mutually exclusive with ServiceName + // +optional + ServiceURL string `json:"serviceUrl,omitempty"` +} + +// InferenceStep defines the inference target of the current step with condition, weights and data. +// +k8s:openapi-gen=true + +type InferenceStep struct { + // Unique name for the step within this node + // +optional + StepName string `json:"name,omitempty"` + + // Node or service used to process this step + InferenceTarget `json:",inline"` + + // request data sent to the next route with input/output from the previous step + // $request + // $response.predictions + // +optional + Data string `json:"data,omitempty"` + + // the weight for split of the traffic, only used for Split Router + // when weight is specified all the routing targets should be sum to 100 + // +optional + Weight *int64 `json:"weight,omitempty"` + + // routing based on the condition + // +optional + Condition string `json:"condition,omitempty"` +} + +// InferenceGraphStatus defines the InferenceGraph conditions and status +// +k8s:openapi-gen=true + +type InferenceGraphStatus struct { + // Conditions for InferenceGraph + duckv1.Status `json:",inline"` + // Url for the InferenceGraph + // +optional + URL *apis.URL `json:"url,omitempty"` +} + +// InferenceGraphList contains a list of InferenceGraph +// +k8s:openapi-gen=true +// +kubebuilder:object:root=true +type InferenceGraphList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + // +listType=set + Items []InferenceGraph `json:"items"` +} + +func init() { + SchemeBuilder.Register(&InferenceGraph{}, &InferenceGraphList{}) +} diff --git a/pkg/apis/serving/v1alpha1/inference_graph_validation.go b/pkg/apis/serving/v1alpha1/inference_graph_validation.go new file mode 100644 index 00000000000..240218f859e --- /dev/null +++ b/pkg/apis/serving/v1alpha1/inference_graph_validation.go @@ -0,0 +1,174 @@ +/* +Copyright 2022 The KServe Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "fmt" + "k8s.io/apimachinery/pkg/util/sets" + + "regexp" + + "k8s.io/apimachinery/pkg/runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/webhook" +) + +const ( + // InvalidGraphNameFormatError defines the error message for invalid inference graph name + InvalidGraphNameFormatError = "The InferenceGraph \"%s\" is invalid: a InferenceGraph name must consist of lower case alphanumeric characters or '-', and must start with alphabetical character. (e.g. \"my-name\" or \"abc-123\", regex used for validation is '%s')" +) + +const ( + // GraphNameFmt regular expressions for validation of isvc name + GraphNameFmt string = "[a-z]([-a-z0-9]*[a-z0-9])?" +) + +var ( + // logger for the validation webhook. + validatorLogger = logf.Log.WithName("inferencegraph-v1alpha1-validation-webhook") + //GraphRegexp regular expressions for validation of graph name + GraphRegexp = regexp.MustCompile("^" + GraphNameFmt + "$") +) + +// +kubebuilder:webhook:verbs=create;update,path=/validate-inferencegraph,mutating=false,failurePolicy=fail,groups=serving.kserve.io,resources=pods,versions=v1alpha1,name=inferencegraph.kserve-webhook-server.validator + +var _ webhook.Validator = &InferenceGraph{} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (ig *InferenceGraph) ValidateCreate() error { + validatorLogger.Info("validate create", "name", ig.Name) + + if err := validateInferenceGraphName(ig); err != nil { + return err + } + + if err := validateInferenceGraphRouterRoot(ig); err != nil { + return err + } + + if err := validateInferenceGraphStepNameUniqueness(ig); err != nil { + return err + } + + if err := validateInferenceGraphSingleStepTargets(ig); err != nil { + return err + } + + if err := validateInferenceGraphSplitterWeight(ig); err != nil { + return err + } + return nil +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (ig *InferenceGraph) ValidateUpdate(old runtime.Object) error { + validatorLogger.Info("validate update", "name", ig.Name) + + return ig.ValidateCreate() +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (ig *InferenceGraph) ValidateDelete() error { + validatorLogger.Info("validate delete", "name", ig.Name) + return nil +} + +// Validation of unique step names +func validateInferenceGraphStepNameUniqueness(ig *InferenceGraph) error { + nodes := ig.Spec.Nodes + for nodeName, node := range nodes { + nameSet := sets.NewString() + for _, route := range node.Steps { + if route.StepName != "" { + if nameSet.Has(route.StepName) { + return fmt.Errorf("Node \"%s\" of InferenceGraph \"%s\" contains more than one step with name \"%s\"", + nodeName, ig.Name, route.StepName) + } + nameSet.Insert(route.StepName) + } + } + } + return nil +} + +// Validation of single step inference targets +func validateInferenceGraphSingleStepTargets(ig *InferenceGraph) error { + nodes := ig.Spec.Nodes + for nodeName, node := range nodes { + for i, route := range node.Steps { + target := route.InferenceTarget + count := 0 + if target.NodeName != "" { + count += 1 + } + if target.ServiceName != "" { + count += 1 + } + if target.ServiceURL != "" { + count += 1 + } + if count == 0 { + return fmt.Errorf("Step %d (\"%s\") in node \"%s\" of InferenceGraph \"%s\" does not specify an inference target", + i, route.StepName, nodeName, ig.Name) + } + if count != 1 { + return fmt.Errorf("Step %d (\"%s\") in node \"%s\" of InferenceGraph \"%s\" specifies more than one of nodeName, serviceName, serviceUrl", + i, route.StepName, nodeName, ig.Name) + } + } + } + return nil +} + +// Validation of inference graph name +func validateInferenceGraphName(ig *InferenceGraph) error { + if !GraphRegexp.MatchString(ig.Name) { + return fmt.Errorf(InvalidGraphNameFormatError, ig.Name, GraphNameFmt) + } + return nil +} + +//Validation of inference graph router root +func validateInferenceGraphRouterRoot(ig *InferenceGraph) error { + nodes := ig.Spec.Nodes + for name := range nodes { + if name == GraphRootNodeName { + return nil + } + } + return fmt.Errorf("root node not found, InferenceGraph needs a node with name 'root' as the root node of the graph") +} + +//Validation of inference graph router type +func validateInferenceGraphSplitterWeight(ig *InferenceGraph) error { + nodes := ig.Spec.Nodes + for name, node := range nodes { + weight := 0 + if node.RouterType == Splitter { + for _, route := range node.Steps { + if route.Weight == nil { + return fmt.Errorf("InferenceGraph[%s] Node[%s] Route[%s] missing the 'Weight'", ig.Name, name, route.ServiceName) + } + weight += int(*route.Weight) + } + if weight != 100 { + return fmt.Errorf("InferenceGraph[%s] Node[%s] splitter node: the sum of traffic weights for all routing targets should be 100", ig.Name, name) + } + } + } + return nil +} diff --git a/pkg/apis/serving/v1alpha1/v1alpha1.go b/pkg/apis/serving/v1alpha1/v1alpha1.go index a70db3264a4..c99bf4c032e 100644 --- a/pkg/apis/serving/v1alpha1/v1alpha1.go +++ b/pkg/apis/serving/v1alpha1/v1alpha1.go @@ -51,4 +51,5 @@ func Resource(resource string) schema.GroupResource { func init() { SchemeBuilder.Register(&TrainedModel{}, &TrainedModelList{}) + SchemeBuilder.Register(&InferenceGraph{}, &InferenceGraphList{}) } diff --git a/pkg/apis/serving/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/serving/v1alpha1/zz_generated.deepcopy.go index 2359efd8e74..36a2d09146c 100644 --- a/pkg/apis/serving/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/serving/v1alpha1/zz_generated.deepcopy.go @@ -110,6 +110,166 @@ func (in *ClusterServingRuntimeList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InferenceGraph) DeepCopyInto(out *InferenceGraph) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InferenceGraph. +func (in *InferenceGraph) DeepCopy() *InferenceGraph { + if in == nil { + return nil + } + out := new(InferenceGraph) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *InferenceGraph) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InferenceGraphList) DeepCopyInto(out *InferenceGraphList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]InferenceGraph, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InferenceGraphList. +func (in *InferenceGraphList) DeepCopy() *InferenceGraphList { + if in == nil { + return nil + } + out := new(InferenceGraphList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *InferenceGraphList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InferenceGraphSpec) DeepCopyInto(out *InferenceGraphSpec) { + *out = *in + if in.Nodes != nil { + in, out := &in.Nodes, &out.Nodes + *out = make(map[string]InferenceRouter, len(*in)) + for key, val := range *in { + (*out)[key] = *val.DeepCopy() + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InferenceGraphSpec. +func (in *InferenceGraphSpec) DeepCopy() *InferenceGraphSpec { + if in == nil { + return nil + } + out := new(InferenceGraphSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InferenceGraphStatus) DeepCopyInto(out *InferenceGraphStatus) { + *out = *in + in.Status.DeepCopyInto(&out.Status) + if in.URL != nil { + in, out := &in.URL, &out.URL + *out = new(apis.URL) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InferenceGraphStatus. +func (in *InferenceGraphStatus) DeepCopy() *InferenceGraphStatus { + if in == nil { + return nil + } + out := new(InferenceGraphStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InferenceRouter) DeepCopyInto(out *InferenceRouter) { + *out = *in + if in.Steps != nil { + in, out := &in.Steps, &out.Steps + *out = make([]InferenceStep, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InferenceRouter. +func (in *InferenceRouter) DeepCopy() *InferenceRouter { + if in == nil { + return nil + } + out := new(InferenceRouter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InferenceStep) DeepCopyInto(out *InferenceStep) { + *out = *in + out.InferenceTarget = in.InferenceTarget + if in.Weight != nil { + in, out := &in.Weight, &out.Weight + *out = new(int64) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InferenceStep. +func (in *InferenceStep) DeepCopy() *InferenceStep { + if in == nil { + return nil + } + out := new(InferenceStep) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InferenceTarget) DeepCopyInto(out *InferenceTarget) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InferenceTarget. +func (in *InferenceTarget) DeepCopy() *InferenceTarget { + if in == nil { + return nil + } + out := new(InferenceTarget) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ModelSpec) DeepCopyInto(out *ModelSpec) { *out = *in diff --git a/pkg/apis/serving/v1beta1/openapi_generated.go b/pkg/apis/serving/v1beta1/openapi_generated.go index aa53cb31fd6..60d5d4da610 100644 --- a/pkg/apis/serving/v1beta1/openapi_generated.go +++ b/pkg/apis/serving/v1beta1/openapi_generated.go @@ -33,6 +33,8 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "./pkg/apis/serving/v1alpha1.BuiltInAdapter": schema_pkg_apis_serving_v1alpha1_BuiltInAdapter(ref), "./pkg/apis/serving/v1alpha1.ClusterServingRuntime": schema_pkg_apis_serving_v1alpha1_ClusterServingRuntime(ref), "./pkg/apis/serving/v1alpha1.ClusterServingRuntimeList": schema_pkg_apis_serving_v1alpha1_ClusterServingRuntimeList(ref), + "./pkg/apis/serving/v1alpha1.InferenceGraph": schema_pkg_apis_serving_v1alpha1_InferenceGraph(ref), + "./pkg/apis/serving/v1alpha1.InferenceGraphList": schema_pkg_apis_serving_v1alpha1_InferenceGraphList(ref), "./pkg/apis/serving/v1alpha1.ModelSpec": schema_pkg_apis_serving_v1alpha1_ModelSpec(ref), "./pkg/apis/serving/v1alpha1.ServingRuntime": schema_pkg_apis_serving_v1alpha1_ServingRuntime(ref), "./pkg/apis/serving/v1alpha1.ServingRuntimeList": schema_pkg_apis_serving_v1alpha1_ServingRuntimeList(ref), @@ -245,6 +247,107 @@ func schema_pkg_apis_serving_v1alpha1_ClusterServingRuntimeList(ref common.Refer } } +func schema_pkg_apis_serving_v1alpha1_InferenceGraph(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "InferenceGraph is the Schema for the InferenceGraph API for multiple models", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), + }, + }, + "spec": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("./pkg/apis/serving/v1alpha1.InferenceGraphSpec"), + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("./pkg/apis/serving/v1alpha1.InferenceGraphStatus"), + }, + }, + }, + }, + }, + Dependencies: []string{ + "./pkg/apis/serving/v1alpha1.InferenceGraphSpec", "./pkg/apis/serving/v1alpha1.InferenceGraphStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + } +} + +func schema_pkg_apis_serving_v1alpha1_InferenceGraphList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "InferenceGraphList contains a list of InferenceGraph", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), + }, + }, + "items": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-list-type": "set", + }, + }, + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("./pkg/apis/serving/v1alpha1.InferenceGraph"), + }, + }, + }, + }, + }, + }, + Required: []string{"items"}, + }, + }, + Dependencies: []string{ + "./pkg/apis/serving/v1alpha1.InferenceGraph", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + } +} + func schema_pkg_apis_serving_v1alpha1_ModelSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/pkg/apis/serving/v1beta1/swagger.json b/pkg/apis/serving/v1beta1/swagger.json index 33e3d130b8d..6687cb062a3 100644 --- a/pkg/apis/serving/v1beta1/swagger.json +++ b/pkg/apis/serving/v1beta1/swagger.json @@ -93,6 +93,61 @@ } } }, + "v1alpha1.InferenceGraph": { + "description": "InferenceGraph is the Schema for the InferenceGraph API for multiple models", + "type": "object", + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + "type": "string" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "default": {}, + "$ref": "#/definitions/v1.ObjectMeta" + }, + "spec": { + "default": {}, + "$ref": "#/definitions/v1alpha1.InferenceGraphSpec" + }, + "status": { + "default": {}, + "$ref": "#/definitions/v1alpha1.InferenceGraphStatus" + } + } + }, + "v1alpha1.InferenceGraphList": { + "description": "InferenceGraphList contains a list of InferenceGraph", + "type": "object", + "required": [ + "items" + ], + "properties": { + "apiVersion": { + "description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + "type": "string" + }, + "items": { + "type": "array", + "items": { + "default": {}, + "$ref": "#/definitions/v1alpha1.InferenceGraph" + }, + "x-kubernetes-list-type": "set" + }, + "kind": { + "description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + "type": "string" + }, + "metadata": { + "default": {}, + "$ref": "#/definitions/v1.ListMeta" + } + } + }, "v1alpha1.ModelSpec": { "description": "ModelSpec describes a TrainedModel", "type": "object", diff --git a/pkg/controller/v1alpha1/inferencegraph/controller.go b/pkg/controller/v1alpha1/inferencegraph/controller.go new file mode 100644 index 00000000000..e88694f22e9 --- /dev/null +++ b/pkg/controller/v1alpha1/inferencegraph/controller.go @@ -0,0 +1,224 @@ +/* +Copyright 2022 The KServe Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// +kubebuilder:rbac:groups=serving.kserve.io,resources=inferencegraphs,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=serving.kserve.io,resources=inferencegraphs/status,verbs=get;update;patch +// +kubebuilder:rbac:groups=serving.knative.dev,resources=services,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=serving.knative.dev,resources=services/finalizers,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=serving.knative.dev,resources=services/status,verbs=get;update;patch +package inferencegraph + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/go-logr/logr" + v1alpha1api "github.com/kserve/kserve/pkg/apis/serving/v1alpha1" + "github.com/kserve/kserve/pkg/apis/serving/v1beta1" + "github.com/kserve/kserve/pkg/constants" + "github.com/pkg/errors" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" + apierr "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/tools/record" + "knative.dev/pkg/apis" + knservingv1 "knative.dev/serving/pkg/apis/serving/v1" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/reconcile" +) + +// InferenceGraphReconciler reconciles a InferenceGraph object +type InferenceGraphReconciler struct { + client.Client + Log logr.Logger + Scheme *runtime.Scheme + Recorder record.EventRecorder +} + +// InferenceGraphState describes the Readiness of the InferenceGraph +type InferenceGraphState string + +const ( + InferenceGraphNotReadyState InferenceGraphState = "InferenceGraphNotReady" + InferenceGraphReadyState InferenceGraphState = "InferenceGraphReady" +) + +type RouterConfig struct { + Image string `json:"image"` + CpuRequest string `json:"cpuRequest"` + CpuLimit string `json:"cpuLimit"` + MemoryRequest string `json:"memoryRequest"` + MemoryLimit string `json:"memoryLimit"` +} + +func getRouterConfigs(configMap *v1.ConfigMap) (*RouterConfig, error) { + + routerConfig := &RouterConfig{} + if agentConfigValue, ok := configMap.Data["router"]; ok { + err := json.Unmarshal([]byte(agentConfigValue), &routerConfig) + if err != nil { + panic(fmt.Errorf("Unable to unmarshall agent json string due to %v ", err)) + } + } + + //Ensure that we set proper values for CPU/Memory Limit/Request + resourceDefaults := []string{routerConfig.MemoryRequest, + routerConfig.MemoryLimit, + routerConfig.CpuRequest, + routerConfig.CpuLimit} + for _, key := range resourceDefaults { + _, err := resource.ParseQuantity(key) + if err != nil { + return routerConfig, fmt.Errorf("Failed to parse resource configuration for router: %q", + err.Error()) + } + } + + return routerConfig, nil +} + +func (r *InferenceGraphReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + _ = context.Background() + + // Fetch the InferenceService instance + graph := &v1alpha1api.InferenceGraph{} + if err := r.Get(ctx, req.NamespacedName, graph); err != nil { + if apierr.IsNotFound(err) { + // Object not found, return. Created objects are automatically garbage collected. + // For additional cleanup logic use finalizers. + return reconcile.Result{}, nil + } + return reconcile.Result{}, err + } + + r.Log.Info("Reconciling inference graph", "apiVersion", graph.APIVersion, "graph", graph.Name) + configMap := &v1.ConfigMap{} + err := r.Client.Get(ctx, types.NamespacedName{Name: constants.InferenceServiceConfigMapName, Namespace: constants.KServeNamespace}, configMap) + if err != nil { + r.Log.Error(err, "Failed to find config map", "name", constants.InferenceServiceConfigMapName) + return reconcile.Result{}, err + } + routerConfig, err := getRouterConfigs(configMap) + if err != nil { + return reconcile.Result{}, err + } + // resolve service urls + for node, router := range graph.Spec.Nodes { + for i, route := range router.Steps { + isvc := v1beta1.InferenceService{} + if route.ServiceName != "" { + err := r.Client.Get(ctx, types.NamespacedName{Namespace: graph.Namespace, Name: route.ServiceName}, &isvc) + if err == nil { + if isvc.Status.Address != nil && isvc.Status.Address.URL != nil { + if graph.Spec.Nodes[node].Steps[i].ServiceURL == "" { + graph.Spec.Nodes[node].Steps[i].ServiceURL = isvc.Status.Address.URL.String() + } + } else { + r.Log.Info("inference service is not ready", "name", route.ServiceName) + return reconcile.Result{Requeue: true}, errors.Wrapf(err, "service %s is not ready", route.ServiceName) + } + + } else { + r.Log.Info("inference service is not found", "name", route.ServiceName) + return reconcile.Result{Requeue: true}, errors.Wrapf(err, "Failed to find graph service %s", route.ServiceName) + } + } + } + } + //@TODO check raw deployment mode + desired := createKnativeService(graph.ObjectMeta, graph, routerConfig) + err = controllerutil.SetControllerReference(graph, desired, r.Scheme) + if err != nil { + return reconcile.Result{}, err + } + knativeReconciler := NewGraphKnativeServiceReconciler(r.Client, r.Scheme, desired) + ksvcStatus, err := knativeReconciler.Reconcile() + if err != nil { + r.Log.Error(err, "failed to reconcile inference graph ksvc", "name", graph.GetName()) + return reconcile.Result{}, errors.Wrapf(err, "fails to reconcile inference graph ksvc") + } + + r.Log.Info("updating inference graph status", "status", ksvcStatus) + graph.Status.Conditions = ksvcStatus.Status.Conditions + //@TODO Need to check the status of all the graph components, find the inference services from all the nodes and collect the status + for _, con := range ksvcStatus.Status.Conditions { + if con.Type == apis.ConditionReady { + if con.Status == "True" { + graph.Status.URL = ksvcStatus.URL + } else { + graph.Status.URL = nil + } + } + } + if err := r.updateStatus(graph); err != nil { + r.Recorder.Eventf(graph, v1.EventTypeWarning, "InternalError", err.Error()) + return reconcile.Result{}, err + } + + return ctrl.Result{}, nil +} + +func (r *InferenceGraphReconciler) updateStatus(desiredGraph *v1alpha1api.InferenceGraph) error { + graph := &v1alpha1api.InferenceGraph{} + namespacedName := types.NamespacedName{Name: desiredGraph.Name, Namespace: desiredGraph.Namespace} + if err := r.Get(context.TODO(), namespacedName, graph); err != nil { + return err + } + + wasReady := inferenceGraphReadiness(graph.Status) + if equality.Semantic.DeepEqual(graph.Status, desiredGraph.Status) { + // If we didn't change anything then don't call updateStatus. + // This is important because the copy we loaded from the informer's + // cache may be stale and we don't want to overwrite a prior update + // to status with this stale state. + } else if err := r.Status().Update(context.TODO(), desiredGraph); err != nil { + r.Log.Error(err, "Failed to update InferenceGraph status", "InferenceGraph", desiredGraph.Name) + r.Recorder.Eventf(desiredGraph, v1.EventTypeWarning, "UpdateFailed", + "Failed to update status for InferenceGraph %q: %v", desiredGraph.Name, err) + return errors.Wrapf(err, "fails to update InferenceGraph status") + } else { + r.Log.Info("updated InferenceGraph status", "InferenceGraph", desiredGraph.Name) + // If there was a difference and there was no error. + isReady := inferenceGraphReadiness(desiredGraph.Status) + if wasReady && !isReady { // Moved to NotReady State + r.Recorder.Eventf(desiredGraph, v1.EventTypeWarning, string(InferenceGraphNotReadyState), + fmt.Sprintf("InferenceGraph [%v] is no longer Ready", desiredGraph.GetName())) + } else if !wasReady && isReady { // Moved to Ready State + r.Recorder.Eventf(desiredGraph, v1.EventTypeNormal, string(InferenceGraphReadyState), + fmt.Sprintf("InferenceGraph [%v] is Ready", desiredGraph.GetName())) + } + } + return nil +} + +func inferenceGraphReadiness(status v1alpha1api.InferenceGraphStatus) bool { + return status.Conditions != nil && + status.GetCondition(apis.ConditionReady) != nil && + status.GetCondition(apis.ConditionReady).Status == v1.ConditionTrue +} + +func (r *InferenceGraphReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&v1alpha1api.InferenceGraph{}). + Owns(&knservingv1.Service{}). + Complete(r) +} diff --git a/pkg/controller/v1alpha1/inferencegraph/knative_reconciler.go b/pkg/controller/v1alpha1/inferencegraph/knative_reconciler.go new file mode 100644 index 00000000000..051941e9556 --- /dev/null +++ b/pkg/controller/v1alpha1/inferencegraph/knative_reconciler.go @@ -0,0 +1,177 @@ +/* +Copyright 2022 The KServe Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package inferencegraph + +import ( + "context" + "encoding/json" + "fmt" + "github.com/golang/protobuf/proto" + v1alpha1api "github.com/kserve/kserve/pkg/apis/serving/v1alpha1" + "github.com/kserve/kserve/pkg/constants" + "github.com/kserve/kserve/pkg/utils" + "github.com/pkg/errors" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" + apierr "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/util/retry" + "knative.dev/pkg/kmp" + "knative.dev/serving/pkg/apis/autoscaling" + knservingv1 "knative.dev/serving/pkg/apis/serving/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + logf "sigs.k8s.io/controller-runtime/pkg/log" +) + +var log = logf.Log.WithName("GraphKsvcReconciler") + +type GraphKnativeServiceReconciler struct { + client client.Client + scheme *runtime.Scheme + Service *knservingv1.Service +} + +func NewGraphKnativeServiceReconciler(client client.Client, + scheme *runtime.Scheme, + ksvc *knservingv1.Service) *GraphKnativeServiceReconciler { + return &GraphKnativeServiceReconciler{ + client: client, + scheme: scheme, + Service: ksvc, + } +} + +func (r *GraphKnativeServiceReconciler) Reconcile() (*knservingv1.ServiceStatus, error) { + desired := r.Service + existing := &knservingv1.Service{} + err := r.client.Get(context.TODO(), types.NamespacedName{Name: desired.Name, Namespace: desired.Namespace}, existing) + if err != nil { + if apierr.IsNotFound(err) { + log.Info("Creating inference graph knative service", "namespace", desired.Namespace, "name", desired.Name) + return &desired.Status, r.client.Create(context.TODO(), desired) + } + return nil, err + } + // Return if no differences to reconcile. + if semanticEquals(desired, existing) { + return &existing.Status, nil + } + + // Reconcile differences and update + // knative mutator defaults the enableServiceLinks to false which would generate a diff despite no changes on desired knative service + // https://github.com/knative/serving/blob/main/pkg/apis/serving/v1/revision_defaults.go#L134 + if desired.Spec.ConfigurationSpec.Template.Spec.EnableServiceLinks == nil && + existing.Spec.ConfigurationSpec.Template.Spec.EnableServiceLinks != nil && + *existing.Spec.ConfigurationSpec.Template.Spec.EnableServiceLinks == false { + desired.Spec.ConfigurationSpec.Template.Spec.EnableServiceLinks = proto.Bool(false) + } + diff, err := kmp.SafeDiff(desired.Spec.ConfigurationSpec, existing.Spec.ConfigurationSpec) + if err != nil { + return &existing.Status, errors.Wrapf(err, "failed to diff inference graph knative service configuration spec") + } + log.Info("inference graph knative service configuration diff (-desired, +observed):", "diff", diff) + existing.Spec.ConfigurationSpec = desired.Spec.ConfigurationSpec + existing.ObjectMeta.Labels = desired.ObjectMeta.Labels + existing.Spec.Traffic = desired.Spec.Traffic + err = retry.RetryOnConflict(retry.DefaultRetry, func() error { + log.Info("Updating inference graph knative service", "namespace", desired.Namespace, "name", desired.Name) + return r.client.Update(context.TODO(), existing) + }) + if err != nil { + return &existing.Status, errors.Wrapf(err, "fails to update inference graph knative service") + } + return &existing.Status, nil +} + +func semanticEquals(desiredService, service *knservingv1.Service) bool { + return equality.Semantic.DeepEqual(desiredService.Spec.ConfigurationSpec, service.Spec.ConfigurationSpec) && + equality.Semantic.DeepEqual(desiredService.ObjectMeta.Labels, service.ObjectMeta.Labels) && + equality.Semantic.DeepEqual(desiredService.Spec.RouteSpec, service.Spec.RouteSpec) +} + +func createKnativeService(componentMeta metav1.ObjectMeta, graph *v1alpha1api.InferenceGraph, config *RouterConfig) *knservingv1.Service { + bytes, err := json.Marshal(graph.Spec) + if err != nil { + return nil + } + annotations := componentMeta.GetAnnotations() + if annotations == nil { + annotations = make(map[string]string) + } + labels := componentMeta.GetLabels() + if labels == nil { + labels = make(map[string]string) + } + + // User can pass down scaling class annotation to overwrite the default scaling KPA + if _, ok := annotations[autoscaling.ClassAnnotationKey]; !ok { + annotations[autoscaling.ClassAnnotationKey] = autoscaling.KPA + } + + annotations[autoscaling.MinScaleAnnotationKey] = fmt.Sprint(constants.DefaultMinReplicas) + + labels = utils.Filter(componentMeta.Labels, func(key string) bool { + return !utils.Includes(constants.RevisionTemplateLabelDisallowedList, key) + }) + service := &knservingv1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: componentMeta.Name, + Namespace: componentMeta.Namespace, + Labels: componentMeta.Labels, + }, + Spec: knservingv1.ServiceSpec{ + ConfigurationSpec: knservingv1.ConfigurationSpec{ + Template: knservingv1.RevisionTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: labels, + Annotations: annotations, + }, + Spec: knservingv1.RevisionSpec{ + PodSpec: v1.PodSpec{ + Containers: []v1.Container{ + { + Image: config.Image, + Args: []string{ + "--graph-json", + string(bytes), + }, + Resources: v1.ResourceRequirements{ + Limits: v1.ResourceList{ + v1.ResourceCPU: resource.MustParse(config.CpuLimit), + v1.ResourceMemory: resource.MustParse(config.MemoryLimit), + }, + Requests: v1.ResourceList{ + v1.ResourceCPU: resource.MustParse(config.CpuRequest), + v1.ResourceMemory: resource.MustParse(config.MemoryRequest), + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + //Call setDefaults on desired knative service here to avoid diffs generated because knative defaulter webhook is + //called when creating or updating the knative service + service.SetDefaults(context.TODO()) + return service +} diff --git a/router.Dockerfile b/router.Dockerfile new file mode 100644 index 00000000000..5e1dc151b92 --- /dev/null +++ b/router.Dockerfile @@ -0,0 +1,22 @@ +# Build the inference-router binary +FROM golang:1.17 as builder + +# Copy in the go src +WORKDIR /go/src/github.com/kserve/kserve +COPY go.mod go.mod +COPY go.sum go.sum + +RUN go mod download + +COPY pkg/ pkg/ +COPY cmd/ cmd/ + +# Build +RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o router ./cmd/router + +# Copy the inference-router into a thin image +FROM gcr.io/distroless/static:latest +COPY third_party/ third_party/ +WORKDIR /ko-app +COPY --from=builder /go/src/github.com/kserve/kserve/router /ko-app/ +ENTRYPOINT ["/ko-app/router"] diff --git a/test/crds/serving.kserve.io_inferenceservices.yaml b/test/crds/serving.kserve.io_inferenceservices.yaml index 22365496d33..6b06189f202 100644 --- a/test/crds/serving.kserve.io_inferenceservices.yaml +++ b/test/crds/serving.kserve.io_inferenceservices.yaml @@ -1773,6 +1773,127 @@ status: --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.0 + creationTimestamp: null + name: inferencegraphs.serving.kserve.io +spec: + group: serving.kserve.io + names: + kind: InferenceGraph + listKind: InferenceGraphList + plural: inferencegraphs + shortNames: + - ig + singular: inferencegraph + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.url + name: URL + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + nodes: + additionalProperties: + properties: + routerType: + enum: + - Sequence + - Splitter + - Ensemble + - Switch + type: string + steps: + items: + properties: + condition: + type: string + data: + type: string + name: + type: string + nodeName: + type: string + serviceName: + type: string + serviceUrl: + type: string + weight: + format: int64 + type: integer + type: object + type: array + required: + - routerType + type: object + type: object + required: + - nodes + type: object + status: + properties: + annotations: + additionalProperties: + type: string + type: object + conditions: + items: + properties: + lastTransitionTime: + type: string + message: + type: string + reason: + type: string + severity: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + observedGeneration: + format: int64 + type: integer + url: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.4.0