Skip to content

example service enhanced to support training and dynamic calls #14

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion buildproto.sh
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
#! /bin/bash
python3 -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. service/service_spec/example_service.proto
echo `pwd`
python3 -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. singnet/snet-daemon/pricing/pricing.proto --proto_path=/home/adminaccount/singnet/src
python3 -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. singnet/snet-daemon/training/training.proto --proto_path=/home/adminaccount/singnet/src
python3 -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. service/service_spec/example_service.proto --proto_path=/home/adminaccount/singnet/src
43 changes: 41 additions & 2 deletions service/example_service.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import sys
import logging
import uuid

import grpc
import concurrent.futures as futures
Expand All @@ -8,12 +9,14 @@

# Importing the generated codes from buildproto.sh
import service.service_spec.example_service_pb2_grpc as grpc_bt_grpc
from service.service_spec.example_service_pb2 import Result
from service.model_server import ModelServicer
from service.service_spec.example_service_pb2 import Result, ModelId, TrainingResponse
from singnet.snet_daemon.pricing.pricing_pb2 import PriceInCogs
import singnet.snet_daemon.training.training_pb2_grpc as grpc_bt_grpc_training

logging.basicConfig(level=10, format="%(asctime)s - [%(levelname)8s] - %(name)s - %(message)s")
log = logging.getLogger("example_service")


"""
Simple arithmetic service to test the Snet Daemon (gRPC), dApp and/or Snet-CLI.
The user must provide the method (arithmetic operation) and
Expand Down Expand Up @@ -67,6 +70,41 @@ def add(self, request, context):
log.debug("add({},{})={}".format(self.a, self.b, self.result.value))
return self.result

def train_add(self, request, context):
log.debug("GOING TO START TRAINING DATA NOW..................................")

# To respond we need to create a Result() object (from .proto file)
self.result = TrainingResponse()
self.result.model_id = request.model_id
self.result.status = "In Progress"

log.debug("TrainingResponse({},{})".format(self.result.model_id, self.result.status))
return self.result



def dynamic_pricing_train_add(self, request, context):
log.debug("DYNAMIC PRICE method dynamic_pricing_train_add , invoked for train_add")

# To respond we need to create a Result() object (from .proto file)
self.result = PriceInCogs()

self.result.price = 13
log.debug("price returned is {}".format(self.result.price))
return self.result

def dynamic_pricing_add(self, request, context):
# In our case, request is a Numbers() object (from .proto file)
self.a = request.a
self.b = request.b

# To respond we need to create a Result() object (from .proto file)
self.result = PriceInCogs()

self.result.price = 13
log.debug("add({},{})={}".format(self.a, self.b, self.result.price))
return self.result

def sub(self, request, context):
self.a = request.a
self.b = request.b
Expand Down Expand Up @@ -106,6 +144,7 @@ def div(self, request, context):
def serve(max_workers=10, port=7777):
server = grpc.server(futures.ThreadPoolExecutor(max_workers=max_workers))
grpc_bt_grpc.add_CalculatorServicer_to_server(CalculatorServicer(), server)
grpc_bt_grpc_training.add_ModelServicer_to_server(ModelServicer(), server)
server.add_insecure_port("[::]:{}".format(port))
return server

Expand Down
65 changes: 65 additions & 0 deletions service/model_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import sys
import logging
import time
import uuid

import grpc
import concurrent.futures as futures

import service.common

# Importing the generated codes from buildproto.sh
import singnet.snet_daemon.training.training_pb2_grpc as grpc_bt_grpc
from singnet.snet_daemon.training.training_pb2 import ModelDetailsResponse
from singnet.snet_daemon.training.training_pb2 import IN_PROGRESS
from singnet.snet_daemon.training.training_pb2 import CREATED
from singnet.snet_daemon.training.training_pb2 import COMPLETED

logging.basicConfig(level=10, format="%(asctime)s - [%(levelname)8s] - %(name)s - %(message)s")
log = logging.getLogger("model_training")


# Create a class to be added to the gRPC server
# derived from the protobuf codes.
class ModelServicer(grpc_bt_grpc.ModelServicer):
def __init__(self):
# Just for debugging purpose.
log.debug("ModelServicer created")

# The method that will be exposed to the snet-cli call command.
# request: incoming data
# context: object that provides RPC-specific information (timeout, etc).
def create_model(self, request, context):
log.debug("Create Model ")
# AI developer needs to implement this and send back a unique custom ID
self.result = ModelDetailsResponse()
self.result.model_id = "#CLientgeneratedModelId"
self.result.status = CREATED
return self.result

def update_model_access(self, request, context):
log.debug(" daemon will take care of this , AI developer is to just provide a dummy code as below")
# To respond we need to create a Result() object (from .proto file)
self.result = ModelDetailsResponse()
self.result.status = IN_PROGRESS
return self.result

def delete_model(self, request, context):
log.debug("Request to delete the model , ai developer needs to handel this ....")
# To respond we need to create a Result() object (from .proto file)
self.result = ModelDetailsResponse()
self.result.status = COMPLETED
return self.result

def get_all_models(self, request, context):
log.debug(" daemon will take care of this , AI developer is to just provide a dummy code as below")
self.result = ModelDetailsResponse()
return self.result

def get_training_status(self, request, context):
# AI developer to keep track of the training models status and return
log.debug("get training status ")

self.result = ModelDetailsResponse()
self.result.status = IN_PROGRESS
return self.result
39 changes: 36 additions & 3 deletions service/service_spec/example_service.proto
Original file line number Diff line number Diff line change
@@ -1,19 +1,52 @@
syntax = "proto3";

import "singnet/snet-daemon/training/training.proto";
import "singnet/snet-daemon/pricing/pricing.proto";
package example_service;

message AddressList {
repeated string address = 1;
string model_details = 2;
}

message Numbers {
float a = 1;
float b = 2;
//highlight this as part of documentation
string model_id = 3;
}

message Result {
float value = 1;
}
message ModelId {
string model_id = 1;
}
message TrainingRequest {
string link = 1;
string address = 2;
string model_id =3 ;
string request_id =4;
}
message TrainingResponse {
string link = 1;
string model_id =2 ;
string status = 3;//put this in enum
string request_id = 4;
}

service Calculator {
rpc add(Numbers) returns (Result) {}
//AI developer can define their own training methods , if you wish to have a different pricing , please use
// define the pricing method as shown below, dynamic_pricing_train_add, please make sure the i/p is exactly the same
rpc train_add(TrainingRequest) returns (TrainingResponse) {
option (pricing.my_method_option).estimatePriceMethod = "dynamic_pricing_train_add";
option (training.my_method_option).trainingMethodIndicator = "true";
}

//make sure the params to the method are exactly the same as that of the method in which needs dynamic price computation
rpc dynamic_pricing_train_add(TrainingRequest) returns (pricing.PriceInCogs) {}
rpc dynamic_pricing_add(Numbers) returns (pricing.PriceInCogs) {}
rpc add(Numbers) returns (Result) {option (pricing.my_method_option).estimatePriceMethod = "dynamic_pricing_add";}
rpc sub(Numbers) returns (Result) {}
rpc mul(Numbers) returns (Result) {}
rpc div(Numbers) returns (Result) {}
}
}