Power your Windows app with AI: connect C# application with Python model | by Pavlo Horbonos | Towards Data Science

No long intro here:a) we may always run our ML models or neural networks pipelines just in the console;b) there is no reason why we can’t run it on Windows and add some buttons for clicking.
Though, here we face a problem. We can easily develop either some Python model or C# Windows Forms application. But their connection may be a real pain in the process of AI-powered application development. That’s why this piece focuses on the solution for the intermediate communication between C# and Python parts of the project.
For the project, we will use the loan lending club dataset from Kaggle.
Loan lending club dataset is surely well-known data accumulation, so we will skip the code for dataset preparation, cleaning, features selection, analysis, and other staff (since it is not the theme of the article). Check it in the example on my GitHub, if you want. Let’s create a very simple neural network with Keras library and train it to have more or less suitable accuracy:
So, we have the 4-layered neural network with a final accuracy of 70%. Really not the best one, but that is enough for our purposes. By the way, we also created dumps of label encoders and scalers from sk-learn. We used a very handy pickle module:
from pickle import dumpdump(scaler, open(‘scaler.pkl’, ‘wb’))dump(grade_encoder, open(‘grade_encoder.pkl’, ‘wb’))dump(ownership_encoder, open('ownership_encoder.pkl', 'wb'))dump(purpose_encoder, open('purpose_encoder.pkl', 'wb'))
Now our task is:
to write the code for model loading and prediction making;
wrap this code in a simple class;
add the code that receives input parameters in json format;
add the code that returns the output in JSON format.
So, the first step is the purpose we need the model, the second step is just for convenience. But the last two are intermediate stages for our app-to-model connection: JSON is a really convenient format for exchanging between different layers of the solution. Well, talk is cheap, here is our class:
The good part in C# development for Windows Forms is the speed of interface creation: drag and drop few elements, fill some callbacks, check that edit boxes are properly validated, and voila — the primitive app is ready. There is really no reason to show all the code — it is a standard Windows Forms project in Visual Studio 2019. Nevertheless, you can check it in my GitHub. It looks like this:
Nothing special, but we can enter the input parameters for our neural network from the previous step and get the result. And here comes the tricky part.
So, we need a solution for the intermediate layer with C# to Python communication. It consists of two parts: PythonCaller class in the application and the Python aggregator script. As we see from the names, the C# class collects the arguments which should be passed to the model, gets model name and location, and throughs all that info into the calls aggregator script. And the aggregator script handles all jobs with the connection with the model.
Let’s start with the C# part.
As we have stated, all the information exchange takes place in json format. That’s why the first thing we need to do is to connect the Newtonsoft JSON parser library. It is free and can be easily added to Visual Studio through the marketplace. After downloading include it into the project:
using Newtonsoft.Json;
Before the class preparation, we should think about the way of passing input parameters from the GUI part inside the class. Well, since we made a decision to pack the arguments into a JSON object, we will prepare arguments container class. You may know that I am passionate about container design, so you can check my articles about constructing them.
So, back to the container: it is a simple wrap around the dictionary, which collects arguments and can return them as a JSON object with some meta-information included. Of course, it will be passed into the caller class itself.
Now for the main part. Firstly, every instance of the PythonCaller class will be connected to the concrete model script. Secondly, it will use ProcessStartInfo object to call the aggregator script through the Python interpreter. A previously created JSON object with input parameters will serve as the argument to the aggregator script. Implementation is simple:
create an object with a connection to the concrete model class:
transfer call of the selected model’s class method (with PythonCallerArgs container prepared, of course) to the aggregator script:
You may notice, that we have got control over the in-out stream for the script call. It is the way we get the result from the script.
And that is all, the solution is really so simple. We will integrate the class into the application later.
The last part of the solution is calls aggregator itself. It is represented as Python script which gets all JSON-packed information from Windows application and contacts the desired AI model script.
Implementation is simple — get the parameters from the Windows application and transfer them to the model through a specific method call. There are two trick places here. The first one is to import the model’s class into the script, so we can access the desired method. We will use importlib package for these purposes: it can import the module by the path to the code.
The second trick place is to return the result of the call back to the application. But, as you remember, we forced ProcessStartInfo object to get control over the standard output. That’s why we just printed the result into the stream in the last line of the script.
The last step is the integration of the designed class into our application:
And now we can check the whole application and get the result from the AI module
Yes, this solution is not perfect, but tuned once it will connect the power of AI to your application. That’s why you can propose your own working alternatives. And, as always, you can find the whole working example in my GitHub repository: