Skip to content
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

Fixed grpc stubs generating services with training #78

Open
wants to merge 2 commits into
base: development
Choose a base branch
from
Open
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
8 changes: 5 additions & 3 deletions snet/sdk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ def create_service_client(self, org_id: str, service_id: str, group_name=None,
lib_generator.generate_client_library()
else:
path_to_pb_files = self.get_path_to_pb_files(org_id, service_id)
pb_2_file_name = find_file_by_keyword(path_to_pb_files, keyword="pb2.py")
pb_2_grpc_file_name = find_file_by_keyword(path_to_pb_files, keyword="pb2_grpc.py")
pb_2_file_name = find_file_by_keyword(path_to_pb_files, keyword="pb2.py", exclude=['training', 'pricing'])
pb_2_grpc_file_name = find_file_by_keyword(path_to_pb_files, keyword="pb2_grpc.py", exclude=['training', 'pricing'])
if not pb_2_file_name or not pb_2_grpc_file_name:
lib_generator.generate_client_library()

Expand Down Expand Up @@ -145,8 +145,10 @@ def get_path_to_pb_files(self, org_id: str, service_id: str) -> str:

def get_module_by_keyword(self, org_id: str, service_id: str, keyword: str) -> ModuleName:
path_to_pb_files = self.get_path_to_pb_files(org_id, service_id)
file_name = find_file_by_keyword(path_to_pb_files, keyword)
file_name = find_file_by_keyword(path_to_pb_files, keyword, exclude=['training', 'pricing'])
# print(f"File name: {file_name}")
module_name = os.path.splitext(file_name)[0]
# print(f"Module name: {module_name}")
return ModuleName(module_name)

def get_service_metadata(self, org_id, service_id):
Expand Down
4 changes: 2 additions & 2 deletions snet/sdk/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ def _get_gas_price(self):
gas_price = self.web3.eth.gas_price
if gas_price <= 15000000000:
gas_price += gas_price * 1 / 3
elif gas_price > 15000000000 and gas_price <= 50000000000:
elif 15000000000 < gas_price <= 50000000000:
gas_price += gas_price * 1 / 5
elif gas_price > 50000000000 and gas_price <= 150000000000:
elif 50000000000 < gas_price <= 150000000000:
gas_price += 7000000000
elif gas_price > 150000000000:
gas_price += gas_price * 1 / 10
Expand Down
21 changes: 20 additions & 1 deletion snet/sdk/client_lib_generator.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import os
from pathlib import Path, PurePath
import shutil

from snet.sdk import StorageProvider
from snet.sdk.utils import ipfs_utils
from snet.sdk.utils.utils import compile_proto, type_converter
from snet.sdk.utils.utils import compile_proto, type_converter, RESOURCES_PATH


class ClientLibGenerator:
Expand Down Expand Up @@ -41,10 +42,28 @@ def generate_client_library(self):
# Receive proto files
self._metadata_provider.fetch_and_extract_proto(service_api_source, library_dir_path)

self.check_protos_and_copy(library_dir_path)

# Compile proto files
compile_proto(Path(library_dir_path), library_dir_path, target_language=self.language)

print(f'client libraries for service with id "{library_service_id}" in org with id "{library_org_id}" '
f'generated at {library_dir_path}')
except Exception as e:
print(e)

def check_protos_and_copy(self, lib_dir_path):
source_dir = RESOURCES_PATH.joinpath("proto")
target_dir = lib_dir_path

files_to_check = ["training.proto", "pricing.proto"]

missing_files = []
for file in files_to_check:
if not os.path.exists(os.path.join(target_dir, file)):
missing_files.append(file)

for file in missing_files:
source_path = os.path.join(source_dir, file)
target_path = os.path.join(target_dir, file)
shutil.copy2(source_path, target_path)
29 changes: 29 additions & 0 deletions snet/sdk/resources/proto/pricing.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
syntax = "proto3";
import "google/protobuf/descriptor.proto";
package pricing;

option go_package = "../pricing";

extend google.protobuf.MethodOptions {
EstimatePrice my_method_option = 9999127;
}
//In Order to Support Dynamic Pricing , we need a way to indicate which of the methods will need dynamic pricing Support
//By Dynamic Pricing , the pricing of the service call will be a variable of the inputs passed.
//The Service Provider is best positioned to determine this
//The below standards are to be followed
// 1) The Input Message for the Pricing RPC call will be exactly same as the Input Message of the Service Call
// 2) The Output Message for the Pricing RPC MUST return PriceInCogs.
// 3) Define the name of the RPC method to be called using Method Option EstimatePrice


//helps determine which method to call for dynamic pricing,
//format is of type "packageName/serviceName/MethodName", Example :"/example_service.Calculator/estimate_add"
//Daemon will invoke the actual RPC method , but will invoke the method defined in the method options before
//to determine the price that needs to be charged for this call
message EstimatePrice {
string estimatePriceMethod = 1;
}
//The Value returned by the Pricing call
message PriceInCogs {
uint64 price = 1;
}
29 changes: 29 additions & 0 deletions snet/sdk/resources/proto/pricing_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions snet/sdk/resources/proto/pricing_pb2_grpc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
"""Client and server classes corresponding to protobuf-defined services."""
import grpc

7 changes: 3 additions & 4 deletions snet/sdk/resources/proto/training.proto
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ message ModelDetails {

//set this to true if you want your model to be used by other AI consumers
bool is_publicly_accessible = 14;

}

message AuthorizationDetails {
Expand Down Expand Up @@ -91,20 +90,20 @@ message UpdateModelRequest {
message ModelDetailsResponse {
Status status = 1;
ModelDetails model_details = 2;

}

service Model {

// The AI developer needs to Implement this service and Daemon will call these
// The AI developer needs to Implement this service (do not copy this in your service proto) and Daemon will call these
// There will be no cost borne by the consumer in calling these methods,
// Pricing will apply when you actually call the training methods defined.
// AI consumer will call all these methods
rpc create_model(CreateModelRequest) returns (ModelDetailsResponse) {}
rpc delete_model(UpdateModelRequest) returns (ModelDetailsResponse) {}
rpc get_model_status(ModelDetailsRequest) returns (ModelDetailsResponse) {}

// Daemon will implement , however the AI developer should skip implementing these and just provide dummy code.

// Daemon will implement, however the AI developer should skip implementing these and just provide dummy code.
rpc update_model_access(UpdateModelRequest) returns (ModelDetailsResponse) {}
rpc get_all_models(AccessibleModelsRequest) returns (AccessibleModelsResponse) {}

Expand Down
4 changes: 2 additions & 2 deletions snet/sdk/resources/proto/training_pb2_grpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class ModelServicer(object):
"""Missing associated documentation comment in .proto file."""

def create_model(self, request, context):
"""The AI developer needs to Implement this service and Daemon will call these
"""The AI developer needs to Implement this service (do not copy this in your service proto) and Daemon will call these
There will be no cost borne by the consumer in calling these methods,
Pricing will apply when you actually call the training methods defined.
AI consumer will call all these methods
Expand All @@ -67,7 +67,7 @@ def get_model_status(self, request, context):
raise NotImplementedError('Method not implemented!')

def update_model_access(self, request, context):
"""Daemon will implement , however the AI developer should skip implementing these and just provide dummy code.
"""Daemon will implement, however the AI developer should skip implementing these and just provide dummy code.
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
Expand Down
2 changes: 1 addition & 1 deletion snet/sdk/service_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ def get_path_to_pb_files(self, org_id: str, service_id: str) -> str:
def get_services_and_messages_info(self):
# Get proto file filepath and open it
path_to_pb_files = self.get_path_to_pb_files(self.org_id, self.service_id)
proto_file_name = find_file_by_keyword(path_to_pb_files, keyword=".proto")
proto_file_name = find_file_by_keyword(path_to_pb_files, keyword=".proto", exclude=['training', 'pricing'])
proto_filepath = os.path.join(path_to_pb_files, proto_file_name)
with open(proto_filepath, 'r') as file:
proto_content = file.read()
Expand Down
6 changes: 4 additions & 2 deletions snet/sdk/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,12 @@ def __exit__(self, exc_type, exc_value, traceback):
pass


def find_file_by_keyword(directory, keyword):
def find_file_by_keyword(directory, keyword, exclude=None):
if exclude is None:
exclude = []
for root, dirs, files in os.walk(directory):
for file in files:
if keyword in file:
if keyword in file and all(e not in file for e in exclude):
return file


Expand Down
Loading