github.com/alwaysproblem/mlserving-tutorial@v0.0.0-20221124033215-121cfddbfbf4/TFserving/ClientAPI/go/README.md (about) 1 # GO API 2 3 ## Build your own go TFclient (optional) (old version) 4 5 - Thanks to [Maxim Khitrov](https://gist.github.com/mxk) and [datainq](https://github.com/datainq/go-mnist-client). Here is [reference](https://gist.github.com/mxk/b86769306037c9dc49b44d52764cbbdc) 6 7 - requirement 8 - [go installation](https://golang.org/doc/install) 9 ```text 10 go >= 1.11 11 protoc == 3.6.1 12 ``` 13 14 - setup a new directory and the structure is like this: 15 16 ```text 17 ---client (your new directory name) 18 | 19 ---pkg (for go modules) 20 | 21 ---src (for customed modules and source files) 22 | 23 ---bin (fo go binary files) 24 ``` 25 26 - copy `dockerfile` to your own directory and build docker image through dockerfile 27 28 ```bash 29 # assume that you are under go directory. 30 cp dockerfile <your> 31 # docker build -t <tag>:<label> path -f <dockerfile> 32 docker build -t alwaysproblem/tfclient-go:build path -f dockerfile 33 ``` 34 35 - build inside docker 36 37 ```bash 38 $ docker run --rm -ti --name goenv -v `pwd`:/work alwaysproblem/tfclient-go:build /bin/bash 39 ``` 40 41 <!-- TODO: simplify these with bash run in docker --> 42 43 ```bash 44 root@8c768509e690:/work# cd src 45 root@8c768509e690:/work/src# git clone -b r1.15 https://github.com/tensorflow/tensorflow.git 46 root@8c768509e690:/work/src# git clone -b r1.14 https://github.com/tensorflow/serving.git 47 root@8c768509e690:/work/src# go run protoc.go # ignore the warning but this procedure only works under specific protoc version 48 root@8c768509e690:/work/src# go mod init client 49 root@8c768509e690:/work/src# go mod edit -replace=github.com/tensorflow/tensorflow/tensorflow/go/core=./proto/tensorflow/core 50 root@8c768509e690:/work/src# go mod edit -replace=github.com/alwaysproblem/tensorflow_serving=./proto/tensorflow/serving 51 root@8c768509e690:/work/src# cd proto/tensorflow/core && go mod init github.com/tensorflow/tensorflow/tensorflow/go/core && cd - 52 root@8c768509e690:/work/src# cd proto/tensorflow/serving && go mod init github.com/alwaysproblem/tensorflow_serving && cd - 53 root@8c768509e690:/work/src# rm -rf tensorflow/ serving/ 54 root@8c768509e690:/work/src# exit 55 ``` 56 57 ## Build your own go TFclient (optional) (new version) 58 59 - [TFServing 2.3](https://github.com/Alwaysproblem/TFServing-setup-tutorial/tree/tfclient-golang-r2.3/go) 60 61 - run server 62 *if you forget to run in the first place.* 63 ```bash 64 $ ROOT=/Users/yongxiyang/Desktop/TFServing-setup-tutorial/ 65 $ docker run --rm -p 8500:8500 -p 8501:8501 --mount type=bind,source=$ROOT,target=/models --mount type=bind,source=$ROOT/config/versionlabels.config,target=/models/versionctrl.config -it tensorflow/serving --model_config_file=/models/versionctrl.config --model_config_file_poll_wait_seconds=60 --allow_version_labels_for_unavailable_models 66 ``` 67 68 - run the test on the client 69 - install dependency 70 71 ```bash 72 # assume you are in go directory 73 $ cd src 74 $ source env.sh 75 $ bash basic-run-env.sh 76 ``` 77 78 - run go client for a simple example 79 **don't forget source env.sh** 80 - request data from server 81 82 ```bash 83 # run under src directory 84 $ bash run.sh main/predict-service.go # test on local host 85 # model_spec:{name:"Toy" version:{value:1} signature_name:"serving_default"} outputs:{key:"output_1" value:{dtype:DT_FLOAT tensor_shape:{dim:{size:3} dim:{size:1}} float_val:10.805429 float_val:14.010123 float_val:17.214817}} 86 ``` 87 88 - request different model name 89 90 ```bash 91 $ go run main/predict-service.go --model_name Toy 92 # model_spec:{name:"Toy" version:{value:2} signature_name:"serving_default"} outputs:{key:"output_1" value:{dtype:DT_FLOAT tensor_shape:{dim:{size:3} dim:{size:1}} float_val:0.999035 float_val:0.99973494 float_val:0.9999273}} 93 $ go run main/predict-service.go --model_name Toy_double 94 # model_spec:{name:"Toy_double" version:{value:1} signature_name:"serving_default"} outputs:{key:"output_1" value:{dtype:DT_FLOAT tensor_shape:{dim:{size:3} dim:{size:1}} float_val:6.8030167 float_val:8.262094 float_val:9.72117}} 95 ``` 96 97 - request different version through the version number 98 99 ```bash 100 $ go run main/predict-service.go --model_name Toy --model_version 1 101 # model_spec:{name:"Toy" version:{value:1} signature_name:"serving_default"} outputs:{key:"output_1" value:{dtype:DT_FLOAT tensor_shape:{dim:{size:3} dim:{size:1}} float_val:10.805429 float_val:14.010123 float_val:17.214817}} 102 $ go run main/predict-service.go --model_name Toy --model_version 2 103 # model_spec:{name:"Toy" version:{value:2} signature_name:"serving_default"} outputs:{key:"output_1" value:{dtype:DT_FLOAT tensor_shape:{dim:{size:3} dim:{size:1}} float_val:0.999035 float_val:0.99973494 float_val:0.9999273}} 104 ``` 105 106 - request different version through the version annotation 107 108 ```bash 109 $ go run main/predict-service.go --model_name Toy --model_version_label stable 110 # model_spec:{name:"Toy" version:{value:1} signature_name:"serving_default"} outputs:{key:"output_1" value:{dtype:DT_FLOAT tensor_shape:{dim:{size:3} dim:{size:1}} float_val:10.805429 float_val:14.010123 float_val:17.214817}} 111 ``` 112 113 - request multiple task model <!-- TODO: --> 114 115 ```bash 116 ``` 117 118 - request model status 119 120 ```bash 121 $ go run main/model-status.go --model_name Toy 122 # model_version_status:{version:2 state:AVAILABLE status:{}} model_version_status:{version:1 state:AVAILABLE status:{}} 123 ``` 124 125 - request model metadata 126 127 ```bash 128 $ go run main/predict-model-metadata.go --model_name Toy 129 # model_spec:{name:"Toy" version:{value:2}} metadata:{key:"signature_def" value:{[type.googleapis.com/tensorflow.serving.SignatureDefMap]:{signature_def:{key:"__saved_model_init_op" value:{outputs:{key:"__saved_model_init_op" value:{name:"NoOp" tensor_shape:{unknown_rank:true}}}}} signature_def:{key:"serving_default" value:{inputs:{key:"input_1" value:{name:"serving_default_input_1:0" dtype:DT_FLOAT tensor_shape:{dim:{size:-1} dim:{size:2}}}} outputs:{key:"output_1" value:{name:"StatefulPartitionedCall:0" dtype:DT_FLOAT tensor_shape:{dim:{size:-1} dim:{size:1}}}} method_name:"tensorflow/serving/predict"}}}}} 130 ``` 131 132 - reload model through gRPC API 133 134 ```bash 135 $ go run main/model-reload.go --model_name Toy 136 # model Toy reloaded sucessfully 137 ``` 138 139 - request model log 140 141 ```bash 142 $ go run main/predict-log.go --model_name Toy # --model_version 1 --model_version_label stable 143 # model_spec:{name:"Toy" version:{value:2} signature_name:"serving_default"} outputs:{key:"output_1" value:{dtype:DT_FLOAT tensor_shape:{dim:{size:3} dim:{size:1}} float_val:0.999035 float_val:0.99973494 float_val:0.9999273}} 144 # log_metadata:{model_spec:{name:"Toy" signature_name:"serving_default"}} predict_log:{request:{model_spec:{name:"Toy" signature_name:"serving_default"} inputs:{key:"input_1" value:{dtype:DT_FLOAT tensor_shape:{dim:{size:3} dim:{size:2}} float_val:1 float_val:2 float_val:1 float_val:3 float_val:1 float_val:4}}} response:{model_spec:{name:"Toy" version:{value:2} signature_name:"serving_default"} outputs:{key:"output_1" value:{dtype:DT_FLOAT tensor_shape:{dim:{size:3} dim:{size:1}} float_val:0.999035 float_val:0.99973494 float_val:0.9999273}}}} 145 ``` 146 147 - GO gRPC api 148 1. framework TensorProto 149 150 ```go 151 type TensorProto struct { 152 state protoimpl.MessageState 153 sizeCache protoimpl.SizeCache 154 unknownFields protoimpl.UnknownFields 155 156 Dtype DataType `protobuf:"varint,1,opt,name=dtype,proto3,enum=tensorflow.DataType" json:"dtype,omitempty"` 157 // Shape of the tensor. TODO(touts): sort out the 0-rank issues. 158 TensorShape *TensorShapeProto `protobuf:"bytes,2,opt,name=tensor_shape,json=tensorShape,proto3" json:"tensor_shape,omitempty"` 159 // Version number. 160 // 161 // In version 0, if the "repeated xxx" representations contain only one 162 // element, that element is repeated to fill the shape. This makes it easy 163 // to represent a constant Tensor with a single value. 164 VersionNumber int32 `protobuf:"varint,3,opt,name=version_number,json=versionNumber,proto3" json:"version_number,omitempty"` 165 // Serialized raw tensor content from either Tensor::AsProtoTensorContent or 166 // memcpy in tensorflow::grpc::EncodeTensorToByteBuffer. This representation 167 // can be used for all tensor types. The purpose of this representation is to 168 // reduce serialization overhead during RPC call by avoiding serialization of 169 // many repeated small items. 170 TensorContent []byte `protobuf:"bytes,4,opt,name=tensor_content,json=tensorContent,proto3" json:"tensor_content,omitempty"` 171 // DT_HALF, DT_BFLOAT16. Note that since protobuf has no int16 type, we'll 172 // have some pointless zero padding for each value here. 173 HalfVal []int32 `protobuf:"varint,13,rep,packed,name=half_val,json=halfVal,proto3" json:"half_val,omitempty"` 174 // DT_FLOAT. 175 FloatVal []float32 `protobuf:"fixed32,5,rep,packed,name=float_val,json=floatVal,proto3" json:"float_val,omitempty"` 176 // DT_DOUBLE. 177 DoubleVal []float64 `protobuf:"fixed64,6,rep,packed,name=double_val,json=doubleVal,proto3" json:"double_val,omitempty"` 178 // DT_INT32, DT_INT16, DT_INT8, DT_UINT8. 179 IntVal []int32 `protobuf:"varint,7,rep,packed,name=int_val,json=intVal,proto3" json:"int_val,omitempty"` 180 // DT_STRING 181 StringVal [][]byte `protobuf:"bytes,8,rep,name=string_val,json=stringVal,proto3" json:"string_val,omitempty"` 182 // DT_COMPLEX64. scomplex_val(2*i) and scomplex_val(2*i+1) are real 183 // and imaginary parts of i-th single precision complex. 184 ScomplexVal []float32 `protobuf:"fixed32,9,rep,packed,name=scomplex_val,json=scomplexVal,proto3" json:"scomplex_val,omitempty"` 185 // DT_INT64 186 Int64Val []int64 `protobuf:"varint,10,rep,packed,name=int64_val,json=int64Val,proto3" json:"int64_val,omitempty"` 187 // DT_BOOL 188 BoolVal []bool `protobuf:"varint,11,rep,packed,name=bool_val,json=boolVal,proto3" json:"bool_val,omitempty"` 189 // DT_COMPLEX128. dcomplex_val(2*i) and dcomplex_val(2*i+1) are real 190 // and imaginary parts of i-th double precision complex. 191 DcomplexVal []float64 `protobuf:"fixed64,12,rep,packed,name=dcomplex_val,json=dcomplexVal,proto3" json:"dcomplex_val,omitempty"` 192 // DT_RESOURCE 193 ResourceHandleVal []*ResourceHandleProto `protobuf:"bytes,14,rep,name=resource_handle_val,json=resourceHandleVal,proto3" json:"resource_handle_val,omitempty"` 194 // DT_VARIANT 195 VariantVal []*VariantTensorDataProto `protobuf:"bytes,15,rep,name=variant_val,json=variantVal,proto3" json:"variant_val,omitempty"` 196 // DT_UINT32 197 Uint32Val []uint32 `protobuf:"varint,16,rep,packed,name=uint32_val,json=uint32Val,proto3" json:"uint32_val,omitempty"` 198 // DT_UINT64 199 Uint64Val []uint64 `protobuf:"varint,17,rep,packed,name=uint64_val,json=uint64Val,proto3" json:"uint64_val,omitempty"` 200 } 201 ``` 202 203 2. PredictRequest proto 204 205 ```go 206 type PredictRequest struct { 207 state protoimpl.MessageState 208 sizeCache protoimpl.SizeCache 209 unknownFields protoimpl.UnknownFields 210 211 // Model Specification. If version is not specified, will use the latest 212 // (numerical) version. 213 ModelSpec *ModelSpec `protobuf:"bytes,1,opt,name=model_spec,json=modelSpec,proto3" json:"model_spec,omitempty"` 214 // Input tensors. 215 // Names of input tensor are alias names. The mapping from aliases to real 216 // input tensor names is stored in the SavedModel export as a prediction 217 // SignatureDef under the 'inputs' field. 218 Inputs map[string]*framework.TensorProto `protobuf:"bytes,2,rep,name=inputs,proto3" json:"inputs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` 219 // Output filter. 220 // Names specified are alias names. The mapping from aliases to real output 221 // tensor names is stored in the SavedModel export as a prediction 222 // SignatureDef under the 'outputs' field. 223 // Only tensors specified here will be run/fetched and returned, with the 224 // exception that when none is specified, all tensors specified in the 225 // named signature will be run/fetched and returned. 226 OutputFilter []string `protobuf:"bytes,3,rep,name=output_filter,json=outputFilter,proto3" json:"output_filter,omitempty"` 227 } 228 ``` 229 230 3. PredictResponse proto 231 232 ```go 233 // Response for PredictRequest on successful run. 234 type PredictResponse struct { 235 state protoimpl.MessageState 236 sizeCache protoimpl.SizeCache 237 unknownFields protoimpl.UnknownFields 238 239 // Effective Model Specification used to process PredictRequest. 240 ModelSpec *ModelSpec `protobuf:"bytes,2,opt,name=model_spec,json=modelSpec,proto3" json:"model_spec,omitempty"` 241 // Output tensors. 242 Outputs map[string]*framework.TensorProto `protobuf:"bytes,1,rep,name=outputs,proto3" json:"outputs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` 243 } 244 ``` 245 246 4. ModelSpec proto 247 248 ```go 249 // Metadata for an inference request such as the model name and version. 250 type ModelSpec struct { 251 state protoimpl.MessageState 252 sizeCache protoimpl.SizeCache 253 unknownFields protoimpl.UnknownFields 254 255 // Required servable name. 256 Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` 257 // Optional choice of which version of the model to use. 258 // 259 // Recommended to be left unset in the common case. Should be specified only 260 // when there is a strong version consistency requirement. 261 // 262 // When left unspecified, the system will serve the best available version. 263 // This is typically the latest version, though during version transitions, 264 // notably when serving on a fleet of instances, may be either the previous or 265 // new version. 266 // 267 // Types that are assignable to VersionChoice: 268 // *ModelSpec_Version 269 // *ModelSpec_VersionLabel 270 VersionChoice isModelSpec_VersionChoice `protobuf_oneof:"version_choice"` 271 // A named signature to evaluate. If unspecified, the default signature will 272 // be used. 273 SignatureName string `protobuf:"bytes,3,opt,name=signature_name,json=signatureName,proto3" json:"signature_name,omitempty"` 274 } 275 // for VersionChoice 276 type ModelSpec_Version struct { 277 // Use this specific version number. 278 Version *wrappers.Int64Value `protobuf:"bytes,2,opt,name=version,proto3,oneof"` 279 } 280 281 type ModelSpec_VersionLabel struct { 282 // Use the version associated with the given label. 283 VersionLabel string `protobuf:"bytes,4,opt,name=version_label,json=versionLabel,proto3,oneof"` 284 } 285 ``` 286 287 5. Prediction Log Proto 288 289 ```go 290 type PredictLog struct { 291 state protoimpl.MessageState 292 sizeCache protoimpl.SizeCache 293 unknownFields protoimpl.UnknownFields 294 295 Request *PredictRequest `protobuf:"bytes,1,opt,name=request,proto3" json:"request,omitempty"` 296 Response *PredictResponse `protobuf:"bytes,2,opt,name=response,proto3" json:"response,omitempty"` 297 } 298 ``` 299 300 6. MutilInferenceLog 301 302 ```go 303 type MultiInferenceLog struct { 304 state protoimpl.MessageState 305 sizeCache protoimpl.SizeCache 306 unknownFields protoimpl.UnknownFields 307 308 Request *MultiInferenceRequest `protobuf:"bytes,1,opt,name=request,proto3" json:"request,omitempty"` 309 Response *MultiInferenceResponse `protobuf:"bytes,2,opt,name=response,proto3" json:"response,omitempty"` 310 } 311 ``` 312 313 7. PredictionLog 314 315 ```go 316 // Logged model inference request. 317 type PredictionLog struct { 318 state protoimpl.MessageState 319 sizeCache protoimpl.SizeCache 320 unknownFields protoimpl.UnknownFields 321 322 LogMetadata *LogMetadata `protobuf:"bytes,1,opt,name=log_metadata,json=logMetadata,proto3" json:"log_metadata,omitempty"` 323 // Types that are assignable to LogType: 324 // *PredictionLog_ClassifyLog 325 // *PredictionLog_RegressLog 326 // *PredictionLog_PredictLog 327 // *PredictionLog_MultiInferenceLog 328 // *PredictionLog_SessionRunLog 329 LogType isPredictionLog_LogType `protobuf_oneof:"log_type"` 330 } 331 ``` 332 8. model_server api 333 334 <!-- TODO: finish the handbook , get rid of todo and comment-->