Package: faststan
FastSTANEasily deploy NATS and NATS Streaming subscribers using Python.FeaturesDefine subscribers using sync and async python functionsAutomatic data parsing and validation using type annotations and pydanticSupport all subscription configuration available in stan.py and nats.pyStart subscriptions or services from command linePublish messages from command lineQuick startInstall the package from pypi:pipinstallfaststanUsing the command lineCreate your first NATS subscriber:Create a file namedapp.pyand write the following lines:frompydanticimportBaseModelclassNewEvent(BaseModel):name:strdatetime:intdefon_event(event:NewEvent):print(f"INFO :: Received new message:{event}")Start your subscriber:natssubstartdemo--functionapp:on_eventPublish a message:natspubdemo--name"John Doe"--datetime1602661983NATS Streaming behave the same way:Define your subscription:frompydanticimportBaseModelclassGreetings(BaseModel):message:strdefon_event(event:NewEvent)->Greetings:print(f"Info :: Received new request.")returnGreetings(message=f"Welcome to{event.name}!"Start it usingstan sub startcommand:stansubstartdemo--functionapp:on_eventAnd publish message usingstan pubcommand:stanpubdemo--name"John Doe"Using Python APIIn this example, we will build a machine learning service that perform a prediction using an ONNX model. This service will be impletended using the [request/reply] pattern.Before running the example, make sure you have the dependencies installed:onnxruntimenumpyhttpximportasynciofromtypingimportList,Dictfromfaststan.natsimportFastNATSfrompydanticimportBaseModel,validatorfromhttpximportAsyncClientimportnumpyasnpimportonnxruntimeasrtasyncdefload_predictor(app:FastNATS,url:str="https://s3-per-grenoble.ams3.digitaloceanspaces.com/models/rf_iris.onnx",)->None:"""Load an ONNX model and return a predictor for this model."""asyncwithAsyncClient()ashttp_client:http_response=awaithttp_client.get(url)sess=rt.InferenceSession(http_response.content)input_name=sess.get_inputs()[0].namelabel_name=sess.get_outputs()[0].nameproba_name=sess.get_outputs()[1].namedefpredict(data:np.ndarray):"""Perform prediction for given data."""returnsess.run([label_name,proba_name],{input_name:data})app.state["predictor"]=predictclassEvent(BaseModel):"""Incoming data expected by the predictor."""values:np.ndarraytimestamp:int@validator("values",pre=True)defvalidate_array(cls,value):"""Cast data to numpy array with float32 precision.A ValidationError will be raise if any error is raised in this function."""returnnp.array(value,dtype=np.float32)classConfig:# This must be set to True in order to let pydantic handle numpy typesarbitrary_types_allowed=TrueclassResult(BaseModel):"""Result returned by the predictor."""probabilities:List[Dict[int,float]]# Example: [{ 0: 0.25, 1:0.75}, {0: 0.15, 1: 0.85}]labels:List[int]# Example: [1, 1]app=FastNATS()app.state={}awaitload_predictor(app)awaitapp.connect()@app.reply("predict")defpredict(event:Event)->Result:print(f"{event.timestamp}:: Received new event data")labels,probas=app.state["predictor"](event.values)return{"probabilities":probas,"labels":labels.tolist()}awaitapp.start()You can now publish messages on the service:fromfaststanimportFastNATSasyncwithFastNATS()asnats_client:reply_msg=awaitnats_client.request_json("predict",{"values":[[0,0,0,0]],"timestamp":1602661983})print(f"Received a reply:{reply_msg}")