{"id":1457,"date":"2023-11-10T17:30:15","date_gmt":"2023-11-10T17:30:15","guid":{"rendered":"https:\/\/dev95.site\/deploy-coreml-models-on-the-server-with-vapor\/"},"modified":"2023-11-10T17:30:15","modified_gmt":"2023-11-10T17:30:15","slug":"deploy-coreml-models-on-the-server-with-vapor","status":"publish","type":"post","link":"https:\/\/dev95.site\/ar\/deploy-coreml-models-on-the-server-with-vapor\/","title":{"rendered":"Deploy CoreML Models on the Server with Vapor"},"content":{"rendered":"<div id=\"dev95-1277794006\" class=\"dev95-- dev95-entity-placement\"><script async=\"async\" data-cfasync=\"false\" src=\"https:\/\/pl27862732.profitableratecpmnetwork.com\/2ad7a50e0bbc23ac6801d7b77c501463\/invoke.js\"><\/script>\r\n<div id=\"container-2ad7a50e0bbc23ac6801d7b77c501463\"><\/div><\/div><div>\n<p>Get the benefits of Apple\u2019s ML tools server-side.<\/p>\n<figure><img data-recalc-dims=\"1\" decoding=\"async\" alt=\"\" src=\"https:\/\/i0.wp.com\/cdn-images-1.medium.com\/max\/1024\/1%2AXMjKfWYZYPikQ0pJ391YaA.png?w=1280&#038;ssl=1\"><figcaption>SwiftUI client showing image classification results<\/figcaption><\/figure>\n<p>Recently, at <a href=\"https:\/\/www.sovrn.com\/\">Sovrn<\/a>, we had an AI Hackathon where we were encouraged to experiment with anything related to machine learning. The Hackathon yielded some fantastic projects from across the company. Everything from SQL query generators to chatbots that can answer questions about our products and other incredible work. I thought this would be a great opportunity to learn more about Apple\u2019s ML tools and maybe even build something with real business\u00a0value.<\/p><div id=\"dev95-306817251\" class=\"dev95- dev95-entity-placement\"><center>\r\n<script>\r\n  atOptions = {\r\n    'key' : '4ba6b6513c00e0ba76511f798ae56401',\r\n    'format' : 'iframe',\r\n    'height' : 50,\r\n    'width' : 320,\r\n    'params' : {}\r\n  };\r\n<\/script>\r\n<script src=\"https:\/\/www.highrevenueformat.com\/4ba6b6513c00e0ba76511f798ae56401\/invoke.js\"><\/script>\r\n\t<\/center><\/div>\n<p>A few of my colleagues and I teamed up to play with CreateML and CoreML to see if we could integrate some ML functionality into our iOS app. We got a model trained and integrated into our app in several hours, which was pretty amazing. But we quickly realized that we had a few problems to solve before we could actually ship this\u00a0thing.<\/p>\n<ul>\n<li>The model was hefty. It was about 50MB. That\u2019s a lot of space to take up in our app\u00a0bundle.<\/li>\n<li>We wanted to update the model without releasing a new app\u00a0version.<\/li>\n<li>We wanted to use the model in the web browser as\u00a0well.<\/li>\n<\/ul>\n<p>We didn\u2019t have time to solve all of these problems. But the other day I was exploring the <a href=\"https:\/\/vapor.codes\/\">Vapor<\/a> web framework and the thought hit me, \u201cWhy not deploy CoreML models on the\u00a0server?\u201d<\/p>\n<p>Apple provides a few pre-trained models, so today we\u2019ll deploy an image classification model on the server behind a REST API with Vapor and create a SwiftUI client to consume\u00a0it.<\/p>\n<h3>Foreword<\/h3>\n<p>This prototype is just that, a prototype. It\u2019s not meant to be a production-ready solution. It\u2019s meant to be a proof of concept. There will be warnings in the console, and the code won\u2019t be very clean, but it will work and hopefully get your wheels\u00a0turning.<\/p>\n<p>If you want to skip all this, or if you do want to follow along, you can find the source code for this project on\u00a0<a href=\"https:\/\/github.com\/drewalth\/coreml-web-api\">GitHub<\/a>.<\/p>\n<p>Okay, disclaimers over. Let\u2019s get\u00a0started!<\/p>\n<h3>Requirements<\/h3>\n<ul>\n<li>Xcode 15<\/li>\n<li>macOS 14<\/li>\n<li>Homebrew<\/li>\n<li>Apple Developer Account + Physical Device for\u00a0testing<\/li>\n<\/ul>\n<h3>Getting Started<\/h3>\n<p>First start by creating a new directory that will house our Xcode workspace. We\u2019ll call it coreml-web-api\u00a0.<\/p>\n<pre>cd ~\/Desktop &amp;&amp; mkdir coreml-web-api &amp;&amp; cd coreml-web-api<\/pre>\n<p>Now let&#8217;s install Vapor and bootstrap a brand new server. See <a href=\"https:\/\/docs.vapor.codes\/\">the docs<\/a> for more\u00a0details.<\/p>\n<pre>brew install vapor<br>vapor new server -n<br>open Package.swift<\/pre>\n<p>We want our users to be able to upload images for classification so add a new route called classify that supports this. In server\/Sources\/App\/routes.swift\u00a0, clear out all that generated boilerplate, and add in the following:<\/p>\n<pre>import CoreImage<br>import Vapor<br><br>func routes(_ app: Application) throws {<br>    app.post(\"classify\") { req -&gt; [ClassifierResult] in<br>        let classificationReq = try req.content.decode(ClassificationRequest.self)<br>        let imageBuffer = classificationReq.file.data<br>        guard let fileData = imageBuffer.getData(at: imageBuffer.readerIndex, length: imageBuffer.readableBytes),<br>              let ciImage = CIImage(data: fileData)<br>        else {<br>            throw Errors.badImageData<br>        }<br><br>        let classifier = Classifier() \/\/ we'll add this in a sec<br><br>        return try classifier.classify(image: ciImage)<br>    }<br>}<br><br>enum Errors: Error {<br>    case badImageData \/\/ or whatever<br>}<br><br>struct ClassificationRequest: Content {<br>    var file: File<br>}<\/pre>\n<p>Also, bump up the max file size allowed for uploads in configure.swift\u00a0:<\/p>\n<pre>import Vapor<br><br>\/\/ configures your application<br>public func configure(_ app: Application) async throws {<br>    app.routes.defaultMaxBodySize = \"10mb\"<br><br>    \/\/ register routes<br>    try routes(app)<br>}<\/pre>\n<p>Alright, now let&#8217;s write up a Classifier API. First, head over to <a href=\"https:\/\/developer.apple.com\/machine-learning\/models\/\">Apple\u2019s ML page<\/a> to download a pre-trained model of your choosing. In this demo, I\u2019m using the Resnet50 model. We\u2019ll add this to the package in just a\u00a0moment.<\/p>\n<p>Add a new file called Classifier and drop in the following:<\/p>\n<pre>import CoreImage<br>import Vapor<br>import Vision<br><br>struct Classifier {<br>    func classify(image: CIImage) throws -&gt; [ClassifierResult] {<br>        let url = Bundle.module.url(forResource: \"Resnet50\", withExtension: \"mlmodelc\")!<br>        guard let model = try? VNCoreMLModel(for: Resnet50(contentsOf: url, configuration: MLModelConfiguration()).model) else {<br>            throw Errors.unableToLoadMLModel<br>        }<br><br>        let request = VNCoreMLRequest(model: model)<br><br>        let handler = VNImageRequestHandler(ciImage: image)<br><br>        try? handler.perform([request])<br><br>        guard let results = request.results as? [VNClassificationObservation] else {<br>            throw Errors.noResults<br>        }<br><br>        return results.map { ClassifierResult(label: $0.identifier, confidence: $0.confidence) }<br>    }<br><br>    enum Errors: Error {<br>        case unableToLoadMLModel<br>        case noResults<br>    }<br>}<br><br>struct ClassifierResult: Encodable, Content {<br>    var label: String<br>    var confidence: Float<br>}<\/pre>\n<p>Let\u2019s break this\u00a0down.<\/p>\n<p>First, we load the model. Adding a CoreML model to a package is not super straightforward. We need to compile the\u00a0.mlmodelourselves and add some files to Sources\/. We\u2019ll go over that in a few but this wonkiness explains why loading the model might look slightly different from adding one to a standard Xcode\u00a0project.<\/p>\n<p>Once the model is loaded, we prepare the request and the request handler; then we do the classification. To send the results as JSON to the client, we need to remap the results to a structure that conforms to Encodable and Content\u00a0.<\/p>\n<h4>Adding the Model to the\u00a0Package<\/h4>\n<p>This part definitely took me the longest to figure out. Unfortunately, this step is pretty manual; we can\u2019t just drag and drop the model into the project. So, at the root of the server package, add a new folder called MLModelSource and add the Resnet50.mlmodel file here. Create another folder called Resourcesat server\/Sources\/App\/Resources\/\u00a0.<\/p>\n<p>Now, we need to compile the model, add the Swift class to sources, and include the\u00a0.mlmodelc in the package bundle. The compilation steps are repetitive so we\u2019ll place them in a Makefile target. In the project root, create a Makefile:<\/p>\n<pre># ~\/Desktop\/coreml-web-api\/<br>touch Makefile<\/pre>\n<p>And add a compile_ml_modeltarget:<\/p>\n<pre>compile_ml_model:<br>   cd server\/MLModelSource &amp;&amp; <br>   xcrun coremlcompiler compile Resnet50.mlmodel ..\/Sources\/App\/Resources &amp;&amp; <br>   xcrun coremlcompiler generate Resnet50.mlmodel ..\/Sources\/App\/Resources --language Swift<\/pre>\n<p>Next, add this to the executable target inPackage.swift file:<\/p>\n<pre>resources: [<br>    .copy(\"Resources\/Resnet50.mlmodelc\"),<br>]<\/pre>\n<p>The target should look like\u00a0this:<\/p>\n<pre>.executableTarget(<br>    name: \"App\",<br>    dependencies: [<br>        .product(name: \"Vapor\", package: \"vapor\"),<br>    ],<br>    resources: [<br>        .copy(\"Resources\/Resnet50.mlmodelc\"),<br>    ]<br>),<\/pre>\n<p>Okay, now from the project root, run the compile_ml_model target:<\/p>\n<pre>make compile_ml_model<\/pre>\n<p>Awesome!!! Now, we have an amazing server that supports classifying uploaded images using the Resnet50 model. Before we move on to the creating the client, we need to adjust the App scheme to make the server available to a physical device on your\u00a0network.<\/p>\n<p>Open up the scheme editor, and add serve &#8211;hostname 0.0.0.0 to the run arguments.<\/p>\n<figure><img data-recalc-dims=\"1\" decoding=\"async\" alt=\"\" src=\"https:\/\/i0.wp.com\/cdn-images-1.medium.com\/max\/1024\/1%2A9D7VFpFoUNxS6uZPqCVESw.png?w=1280&#038;ssl=1\"><\/figure>\n<p>Sweet. Now, we\u2019ll create a client to do the uploading.<\/p>\n<h3>iOS Client<\/h3>\n<p>OK, in Xcode go to File -&gt; New -&gt; Project and add an iOS app to the workspace. We only need SwiftUI, no tests or SwiftData. I\u2019m giving mine a really clever name of CoreMLWebClient\u00a0\u2026\u00a0poetic.<\/p>\n<p>Great. Now, let&#8217;s do a little config work. Since we\u2019re going to be using the camera, we need to update the Info.plist with the Privacy\u200a\u2014\u200aCamera Usage Description key.<\/p>\n<figure><img data-recalc-dims=\"1\" decoding=\"async\" alt=\"\" src=\"https:\/\/i0.wp.com\/cdn-images-1.medium.com\/max\/1024\/1%2APVfyDXPGfo9-oeQIercJjg.png?w=1280&#038;ssl=1\"><\/figure>\n<p>Nice! In our client, we want to give users the option of using the camera or selecting from the photo library. Create a new file called ImagePicker.swift and paste in the following:<\/p>\n<pre>import SwiftUI<br><br>struct ImagePicker: UIViewControllerRepresentable {<br>    @Binding var sourceType: UIImagePickerController.SourceType<br>    @Environment(.presentationMode) private var presentationMode<br>    var completion: (UIImage) -&gt; Void<br><br>    func makeUIViewController(context: Context) -&gt; some UIViewController {<br>        let picker = UIImagePickerController()<br>        picker.sourceType = sourceType<br>        picker.delegate = context.coordinator<br>        return picker<br>    }<br><br>    func updateUIViewController(_: UIViewControllerType, context _: Context) {}<br><br>    func makeCoordinator() -&gt; Coordinator {<br>        Coordinator(self)<br>    }<br><br>    class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {<br>        var parent: ImagePicker<br><br>        init(_ parent: ImagePicker) {<br>            self.parent = parent<br>        }<br><br>        func imagePickerController(_: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {<br>            if let image = info[.originalImage] as? UIImage {<br>                parent.completion(image)<br>            }<br>            parent.presentationMode.wrappedValue.dismiss()<br>        }<br>    }<br>}<\/pre>\n<p>We\u2019ll use the sourceType binding to switch between the camera and the\u00a0library.<\/p>\n<p>Now, we\u2019ll add a Classifierto handle the image uploading and return the classification results. I\u2019m jumping around a little, but all this will come together in a few. Create a new file called Classifier.swift and add this\u00a0in:<\/p>\n<pre>import Foundation<br>import UIKit<br><br>struct Classifier {<br>    \/\/\/ replace this with your dev machine IP address<br>    \/\/\/ for testing with a physical device.<br>    private let host = \"localhost\"<br><br>    func classify(image: UIImage) async throws -&gt; [ClassifierResult] {<br>        \/\/ Ensure the URL is valid<br>        guard let uploadURL = URL(string: \"http:\/\/(host):8080\/classify\") else {<br>            throw URLError(.badURL)<br>        }<br><br>        \/\/ Convert the image to JPEG data<br>        guard let imageData = image.jpegData(compressionQuality: 1.0) else {<br>            throw URLError(.unknown)<br>        }<br><br>        \/\/ Generate boundary string using a unique per-app string<br>        let boundary = \"Boundary-(UUID().uuidString)\"<br><br>        \/\/ Create a URLRequest object<br>        var request = URLRequest(url: uploadURL)<br>        request.httpMethod = \"POST\"<br>        request.setValue(\"multipart\/form-data; boundary=(boundary)\", forHTTPHeaderField: \"Content-Type\")<br><br>        \/\/ Create multipart form body<br>        let body = createMultipartFormData(boundary: boundary, data: imageData, fileName: \"photo.jpg\")<br>        request.httpBody = body<br><br>        \/\/ Perform the upload task<br>        let (data, response) = try await URLSession.shared.upload(for: request, from: body)<br><br>        \/\/ Check the response and throw an error if it's not a HTTPURLResponse or the status code is not 200<br>        guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {<br>            throw URLError(.badServerResponse)<br>        }<br><br>        \/\/ Decode the data into an array of ClassifierResult<br>        return try JSONDecoder().decode([ClassifierResult].self, from: data)<br>    }<br><br>    \/\/\/ Creates a multipart\/form-data body with the image data.<br>    \/\/\/ - Parameters:<br>    \/\/\/   - boundary: The boundary string separating parts of the data.<br>    \/\/\/   - data: The image data to be included in the request.<br>    \/\/\/   - fileName: The filename for the image data in the form-data.<br>    \/\/\/ - Returns: A `Data` object representing the multipart\/form-data body.<br>    private func createMultipartFormData(boundary: String, data: Data, fileName: String) -&gt; Data {<br>        var body = Data()<br><br>        \/\/ Add the image data to the raw http request data<br>        body.append(\"--(boundary)rn\")<br>        body.append(\"Content-Disposition: form-data; name=\"file\"; filename=\"(fileName)\"rn\")<br>        body.append(\"Content-Type: image\/jpegrnrn\")<br>        body.append(data)<br>        body.append(\"rn\")<br><br>        \/\/ Add the closing boundary<br>        body.append(\"--(boundary)--rn\")<br>        return body<br>    }<br><br>    struct ClassifierResult: Decodable, Identifiable {<br>        let id = UUID()<br>        var label: String<br>        var confidence: Float<br>    }<br>}<br><br>\/\/ Helper function to append string data to Data object<br>private extension Data {<br>    mutating func append(_ string: String) {<br>        if let data = string.data(using: .utf8) {<br>            append(data)<br>        }<br>    }<br>}<\/pre>\n<p>Great! Now on to the UI. Back in ContentView\u00a0, let&#8217;s add an enum called RequestStatus to communicate to the user what is going on\u200a\u2014\u200athis is an easy UX\u00a0win.<\/p>\n<pre>enum RequestStatus {<br>    case loading, success, idle, error<br>}<\/pre>\n<p>Now, we\u2019ll create a view model for ContentView that uses the newly created classifier to upload a photo to the server and share the results with the UI. This is also going to use the new <a href=\"https:\/\/developer.apple.com\/documentation\/observation\">Observation framework<\/a> \u2b50.<\/p>\n<pre>extension ContentView {<br>    @Observable<br>    class ViewModel {<br>        var requestStatus: RequestStatus = .idle<br>        var results: [Classifier.ClassifierResult] = []<br><br>        private var classifier = Classifier()<br><br>        func upload(_ image: UIImage) {<br>            Task { @MainActor in<br>                do {<br>                    requestStatus = .loading<br>                    results.removeAll()<br>                    results = try await classifier.classify(image: image)<br>                    requestStatus = .success<br>                } catch {<br>                    print(error.localizedDescription)<br>                    requestStatus = .error<br>                }<br>            }<br>        }<br>    }<br>}<\/pre>\n<p>Now we need to add some state. This stuff should probably go in the view model, but for now, I\u2019m going to add these as member vars to ContentView\u00a0\u2026<\/p>\n<pre>\/\/ ContentView.swift<br>@State private var selectedImage: UIImage?<br>@State private var isImagePickerPresented = false<br>@State private var viewModel = ViewModel()<br>@State private var sourceType: UIImagePickerController.SourceType = .camera<\/pre>\n<p>Alright, now we\u2019ll do some more UI building. Replace the body variable with\u00a0this:<\/p>\n<pre>    var body: some View {<br>        VStack(spacing: 20) {<br>            HStack(spacing: 20) {<br>                if let image = selectedImage {<br>                    VStack {<br>                        Image(uiImage: image)<br>                            .resizable()<br>                            .scaledToFit()<br>                    }.padding()<br>                        .frame(maxHeight: 350)<br>                }<br>                List {<br>                    ForEach(viewModel.results, id: .id) { result in<br>                        VStack(alignment: .leading) {<br>                            Text(result.label)<br>                                .font(.callout)<br>                            Text(formatAsPercentage(result.confidence))<br>                                .font(.caption2)<br>                        }<br>                    }<br>                }<br>            }<br>            Divider()<br>            HStack(spacing: 20) {<br>                actionButton()<br>                if viewModel.requestStatus == .loading {<br>                    ProgressView()<br>                }<br>            }<br>        }<br>        .sheet(isPresented: $isImagePickerPresented) {<br>            ImagePicker(sourceType: $sourceType) { image in<br>                self.selectedImage = image<br>            }<br>        }<br>    }<\/pre>\n<p>And to address those compiler errors, add two new functions:<\/p>\n<pre>\/\/ ContentView.swift<br>@ViewBuilder<br>private func actionButton() -&gt; some View {<br>    if let image = selectedImage {<br>        Button(\"Upload Image\") {<br>            viewModel.upload(image)<br>        }.buttonStyle(.borderedProminent)<br>    } else {<br>        HStack(spacing: 20) {<br>            Button(\"Camera\") {<br>                sourceType = .camera<br>                isImagePickerPresented = true<br>            }.buttonStyle(.bordered)<br>            Button(\"Photo Library\") {<br>                sourceType = .photoLibrary<br>                isImagePickerPresented = true<br>            }.buttonStyle(.bordered)<br>        }.padding(.bottom, 20)<br>    }<br>}<br><br>\/\/ and<br><br>private func formatAsPercentage(_ value: Float) -&gt; String {<br>    String(format: \"%.2f%%\", value * 100)<br>}<\/pre>\n<p>Heck yeah, you guys. If everything has gone according to plan, you should now be able to create\/select a picture, upload it to the server, classify the dominant object in the picture, and then display the classification results in the\u00a0UI!<\/p>\n<p>If you run into issues, please feel free to reference the source code, or leave a comment\u00a0below.<\/p>\n<p>I hope this project inspires you and gets the gears turning for your next ML\u00a0project.<\/p>\n<p>Cheers!<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/medium.com\/_\/stat?event=post.clientViewed&amp;referrerSource=full_rss&amp;postId=48809a853fae\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<hr>\n<p><a href=\"https:\/\/medium.com\/better-programming\/deploy-coreml-models-on-the-server-with-vapor-48809a853fae\">Deploy CoreML Models on the Server with Vapor<\/a> was originally published in <a href=\"https:\/\/betterprogramming.pub\/\">Better Programming<\/a> on Medium, where people are continuing the conversation by highlighting and responding to this story.<\/p>\n<\/div>\n<div class=\"pvc_clear\"><\/div>\n<p id=\"pvc_stats_1457\" class=\"pvc_stats total_only  \" data-element-id=\"1457\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" version=\"1.0\" viewBox=\"0 0 502 315\" preserveAspectRatio=\"xMidYMid meet\"><g transform=\"translate(0,332) scale(0.1,-0.1)\" fill=\"\" stroke=\"none\"><path d=\"M2394 3279 l-29 -30 -3 -207 c-2 -182 0 -211 15 -242 39 -76 157 -76 196 0 15 31 17 60 15 243 l-3 209 -33 29 c-26 23 -41 29 -80 29 -41 0 -53 -5 -78 -31z\"\/><path d=\"M3085 3251 c-45 -19 -58 -50 -96 -229 -47 -217 -49 -260 -13 -295 52 -53 146 -42 177 20 16 31 87 366 87 410 0 70 -86 122 -155 94z\"\/><path d=\"M1751 3234 c-13 -9 -29 -31 -37 -50 -12 -29 -10 -49 21 -204 19 -94 39 -189 45 -210 14 -50 54 -80 110 -80 34 0 48 6 76 34 21 21 34 44 34 59 0 14 -18 113 -40 219 -37 178 -43 195 -70 221 -36 32 -101 37 -139 11z\"\/><path d=\"M1163 3073 c-36 -7 -73 -59 -73 -102 0 -56 133 -378 171 -413 34 -32 83 -37 129 -13 70 36 67 87 -16 290 -86 209 -89 214 -129 231 -35 14 -42 15 -82 7z\"\/><path d=\"M3689 3066 c-15 -9 -33 -30 -42 -48 -48 -103 -147 -355 -147 -375 0 -98 131 -148 192 -74 13 15 57 108 97 206 80 196 84 226 37 273 -30 30 -99 39 -137 18z\"\/><path d=\"M583 2784 c-38 -19 -67 -74 -58 -113 9 -42 211 -354 242 -373 16 -10 45 -18 66 -18 51 0 107 52 107 100 0 39 -1 41 -124 234 -80 126 -108 162 -133 173 -41 17 -61 16 -100 -3z\"\/><path d=\"M4250 2784 c-14 -9 -74 -91 -133 -183 -95 -150 -107 -173 -107 -213 0 -55 33 -94 87 -104 67 -13 90 8 211 198 130 202 137 225 78 284 -27 27 -42 34 -72 34 -22 0 -50 -8 -64 -16z\"\/><path d=\"M2275 2693 c-553 -48 -1095 -270 -1585 -649 -135 -104 -459 -423 -483 -476 -23 -49 -22 -139 2 -186 73 -142 361 -457 571 -626 285 -228 642 -407 990 -497 242 -63 336 -73 660 -74 310 0 370 5 595 52 535 111 1045 392 1455 803 122 121 250 273 275 326 19 41 19 137 0 174 -41 79 -309 363 -465 492 -447 370 -946 591 -1479 653 -113 14 -422 18 -536 8z m395 -428 c171 -34 330 -124 456 -258 112 -119 167 -219 211 -378 27 -96 24 -300 -5 -401 -72 -255 -236 -447 -474 -557 -132 -62 -201 -76 -368 -76 -167 0 -236 14 -368 76 -213 98 -373 271 -451 485 -162 444 86 934 547 1084 153 49 292 57 452 25z m909 -232 c222 -123 408 -262 593 -441 76 -74 138 -139 138 -144 0 -16 -233 -242 -330 -319 -155 -123 -309 -223 -461 -299 l-81 -41 32 46 c18 26 49 83 70 128 143 306 141 649 -6 957 -25 52 -61 116 -79 142 l-34 47 45 -20 c26 -10 76 -36 113 -56z m-2057 25 c-40 -58 -105 -190 -130 -263 -110 -324 -59 -707 132 -981 25 -35 42 -64 37 -64 -19 0 -241 119 -326 174 -188 122 -406 314 -532 468 l-58 71 108 103 c185 178 428 349 672 473 66 33 121 60 123 61 2 0 -10 -19 -26 -42z\"\/><path d=\"M2375 1950 c-198 -44 -350 -190 -395 -379 -18 -76 -8 -221 19 -290 114 -284 457 -406 731 -260 98 52 188 154 231 260 27 69 37 214 19 290 -38 163 -166 304 -326 360 -67 23 -215 33 -279 19z\"\/><\/g><\/svg><\/i> <img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"16\" height=\"16\" alt=\"Loading\" src=\"https:\/\/i0.wp.com\/dev95.site\/wp-content\/plugins\/page-views-count\/ajax-loader-2x.gif?resize=16%2C16&#038;ssl=1\" border=0 \/><\/p>\n<div class=\"pvc_clear\"><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Get the benefits of Apple\u2019s ML tools server-side. SwiftUI client showing image classification results Recently, at Sovrn, we had an AI Hackathon where we were encouraged to experiment with anything related to machine learning. The Hackathon yielded some fantastic projects<\/p>\n<div class=\"hosteria-entry-more\"><a href=\"https:\/\/dev95.site\/ar\/deploy-coreml-models-on-the-server-with-vapor\/\" class=\"no-underline font-light  group-hover:text-primary-800 dark:group-hover:text-primary-300 py-1\">Read more &gt;&gt;&gt;<\/a><\/div>\n<div class=\"pvc_clear\"><\/div>\n<p id=\"pvc_stats_1457\" class=\"pvc_stats total_only\" data-element-id=\"1457\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" version=\"1.0\" viewbox=\"0 0 502 315\" preserveaspectratio=\"xMidYMid meet\"><g transform=\"translate(0,332) scale(0.1,-0.1)\" fill=\"\" stroke=\"none\"><path d=\"M2394 3279 l-29 -30 -3 -207 c-2 -182 0 -211 15 -242 39 -76 157 -76 196 0 15 31 17 60 15 243 l-3 209 -33 29 c-26 23 -41 29 -80 29 -41 0 -53 -5 -78 -31z\"\/><path d=\"M3085 3251 c-45 -19 -58 -50 -96 -229 -47 -217 -49 -260 -13 -295 52 -53 146 -42 177 20 16 31 87 366 87 410 0 70 -86 122 -155 94z\"\/><path d=\"M1751 3234 c-13 -9 -29 -31 -37 -50 -12 -29 -10 -49 21 -204 19 -94 39 -189 45 -210 14 -50 54 -80 110 -80 34 0 48 6 76 34 21 21 34 44 34 59 0 14 -18 113 -40 219 -37 178 -43 195 -70 221 -36 32 -101 37 -139 11z\"\/><path d=\"M1163 3073 c-36 -7 -73 -59 -73 -102 0 -56 133 -378 171 -413 34 -32 83 -37 129 -13 70 36 67 87 -16 290 -86 209 -89 214 -129 231 -35 14 -42 15 -82 7z\"\/><path d=\"M3689 3066 c-15 -9 -33 -30 -42 -48 -48 -103 -147 -355 -147 -375 0 -98 131 -148 192 -74 13 15 57 108 97 206 80 196 84 226 37 273 -30 30 -99 39 -137 18z\"\/><path d=\"M583 2784 c-38 -19 -67 -74 -58 -113 9 -42 211 -354 242 -373 16 -10 45 -18 66 -18 51 0 107 52 107 100 0 39 -1 41 -124 234 -80 126 -108 162 -133 173 -41 17 -61 16 -100 -3z\"\/><path d=\"M4250 2784 c-14 -9 -74 -91 -133 -183 -95 -150 -107 -173 -107 -213 0 -55 33 -94 87 -104 67 -13 90 8 211 198 130 202 137 225 78 284 -27 27 -42 34 -72 34 -22 0 -50 -8 -64 -16z\"\/><path d=\"M2275 2693 c-553 -48 -1095 -270 -1585 -649 -135 -104 -459 -423 -483 -476 -23 -49 -22 -139 2 -186 73 -142 361 -457 571 -626 285 -228 642 -407 990 -497 242 -63 336 -73 660 -74 310 0 370 5 595 52 535 111 1045 392 1455 803 122 121 250 273 275 326 19 41 19 137 0 174 -41 79 -309 363 -465 492 -447 370 -946 591 -1479 653 -113 14 -422 18 -536 8z m395 -428 c171 -34 330 -124 456 -258 112 -119 167 -219 211 -378 27 -96 24 -300 -5 -401 -72 -255 -236 -447 -474 -557 -132 -62 -201 -76 -368 -76 -167 0 -236 14 -368 76 -213 98 -373 271 -451 485 -162 444 86 934 547 1084 153 49 292 57 452 25z m909 -232 c222 -123 408 -262 593 -441 76 -74 138 -139 138 -144 0 -16 -233 -242 -330 -319 -155 -123 -309 -223 -461 -299 l-81 -41 32 46 c18 26 49 83 70 128 143 306 141 649 -6 957 -25 52 -61 116 -79 142 l-34 47 45 -20 c26 -10 76 -36 113 -56z m-2057 25 c-40 -58 -105 -190 -130 -263 -110 -324 -59 -707 132 -981 25 -35 42 -64 37 -64 -19 0 -241 119 -326 174 -188 122 -406 314 -532 468 l-58 71 108 103 c185 178 428 349 672 473 66 33 121 60 123 61 2 0 -10 -19 -26 -42z\"\/><path d=\"M2375 1950 c-198 -44 -350 -190 -395 -379 -18 -76 -8 -221 19 -290 114 -284 457 -406 731 -260 98 52 188 154 231 260 27 69 37 214 19 290 -38 163 -166 304 -326 360 -67 23 -215 33 -279 19z\"\/><\/g><\/svg><\/i> <img loading=\"lazy\" decoding=\"async\" width=\"16\" height=\"16\" alt=\"Loading\" src=\"https:\/\/dev95.site\/wp-content\/plugins\/page-views-count\/ajax-loader-2x.gif\" border=\"0\" \/><\/p>\n<div class=\"pvc_clear\"><\/div>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"fp_fajr_begins":"","fp_fajr_iqamah":"","fp_dhuhr_begins":"","fp_dhuhr_iqamah":"","fp_asr_begins":"","fp_asr_iqamah":"","fp_maghrib_begins":"","fp_maghrib_iqamah":"","fp_isha_begins":"","fp_isha_iqamah":"","fp_midnight":"","fp_midnight_name":"","fp_sunrise":"","fp_single_prayer_begins_title":"","fp_single_prayer_iqamah_title":"","fp_prayer_times_for_today":"","fp_hijra_date":"","fp_fajr_name":"","fp_dhuhr_name":"","fp_asr_name":"","fp_maghrib_name":"","fp_isha_name":"","fp_sunrise_name":"","fp_currentDate":"","fp_current_time":"","fp_current_title":"","fp_current_location":"","fp_masjid_name":"","fp_prayer_title":"","fp_next_prayer_iqamah_time":"","fp_next_prayer_iqamah_title":"","fp_next_prayer_begins_time":"","fp_next_prayer_begins_title":"","fp_next_prayer_title":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[37],"tags":[],"class_list":["post-1457","post","type-post","status-publish","format-standard","hentry","category-posts"],"a3_pvc":{"activated":true,"total_views":1,"today_views":0},"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Deploy CoreML Models on the Server with Vapor - Dev95<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/dev95.site\/ar\/deploy-coreml-models-on-the-server-with-vapor\/\" \/>\n<meta property=\"og:locale\" content=\"ar_AR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Deploy CoreML Models on the Server with Vapor - Dev95\" \/>\n<meta property=\"og:description\" content=\"Get the benefits of Apple\u2019s ML tools server-side. SwiftUI client showing image classification results Recently, at Sovrn, we had an AI Hackathon where we were encouraged to experiment with anything related to machine learning. The Hackathon yielded some fantastic projectsRead more &gt;&gt;&gt;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/dev95.site\/ar\/deploy-coreml-models-on-the-server-with-vapor\/\" \/>\n<meta property=\"og:site_name\" content=\"Dev95\" \/>\n<meta property=\"article:published_time\" content=\"2023-11-10T17:30:15+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/cdn-images-1.medium.com\/max\/1024\/1*XMjKfWYZYPikQ0pJ391YaA.png\" \/>\n<meta name=\"author\" content=\"dev95\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u0643\u064f\u062a\u0628 \u0628\u0648\u0627\u0633\u0637\u0629\" \/>\n\t<meta name=\"twitter:data1\" content=\"dev95\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u0648\u0642\u062a \u0627\u0644\u0642\u0631\u0627\u0621\u0629 \u0627\u0644\u0645\u064f\u0642\u062f\u0651\u0631\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 \u062f\u0642\u0627\u0626\u0642\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/dev95.site\\\/deploy-coreml-models-on-the-server-with-vapor\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/dev95.site\\\/deploy-coreml-models-on-the-server-with-vapor\\\/\"},\"author\":{\"name\":\"dev95\",\"@id\":\"https:\\\/\\\/dev95.site\\\/#\\\/schema\\\/person\\\/b807805ffe2916206b04d0938bce0298\"},\"headline\":\"Deploy CoreML Models on the Server with Vapor\",\"datePublished\":\"2023-11-10T17:30:15+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/dev95.site\\\/deploy-coreml-models-on-the-server-with-vapor\\\/\"},\"wordCount\":1215,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/dev95.site\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/dev95.site\\\/deploy-coreml-models-on-the-server-with-vapor\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/cdn-images-1.medium.com\\\/max\\\/1024\\\/1*XMjKfWYZYPikQ0pJ391YaA.png\",\"articleSection\":[\"Posts\"],\"inLanguage\":\"ar\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/dev95.site\\\/deploy-coreml-models-on-the-server-with-vapor\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/dev95.site\\\/deploy-coreml-models-on-the-server-with-vapor\\\/\",\"url\":\"https:\\\/\\\/dev95.site\\\/deploy-coreml-models-on-the-server-with-vapor\\\/\",\"name\":\"Deploy CoreML Models on the Server with Vapor - Dev95\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/dev95.site\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/dev95.site\\\/deploy-coreml-models-on-the-server-with-vapor\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/dev95.site\\\/deploy-coreml-models-on-the-server-with-vapor\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/cdn-images-1.medium.com\\\/max\\\/1024\\\/1*XMjKfWYZYPikQ0pJ391YaA.png\",\"datePublished\":\"2023-11-10T17:30:15+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/dev95.site\\\/deploy-coreml-models-on-the-server-with-vapor\\\/#breadcrumb\"},\"inLanguage\":\"ar\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/dev95.site\\\/deploy-coreml-models-on-the-server-with-vapor\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"ar\",\"@id\":\"https:\\\/\\\/dev95.site\\\/deploy-coreml-models-on-the-server-with-vapor\\\/#primaryimage\",\"url\":\"https:\\\/\\\/cdn-images-1.medium.com\\\/max\\\/1024\\\/1*XMjKfWYZYPikQ0pJ391YaA.png\",\"contentUrl\":\"https:\\\/\\\/cdn-images-1.medium.com\\\/max\\\/1024\\\/1*XMjKfWYZYPikQ0pJ391YaA.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/dev95.site\\\/deploy-coreml-models-on-the-server-with-vapor\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/dev95.site\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Deploy CoreML Models on the Server with Vapor\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/dev95.site\\\/#website\",\"url\":\"https:\\\/\\\/dev95.site\\\/\",\"name\":\"Dev95\",\"description\":\"A comprehensive platform for data and knowledge, delivering reliable content that meets the aspirations of readers and enthusiasts.\",\"publisher\":{\"@id\":\"https:\\\/\\\/dev95.site\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/dev95.site\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"ar\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/dev95.site\\\/#organization\",\"name\":\"Dev95\",\"url\":\"https:\\\/\\\/dev95.site\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ar\",\"@id\":\"https:\\\/\\\/dev95.site\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/dev95.site\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/rbrrbr-6.png?fit=512%2C512&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/dev95.site\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/rbrrbr-6.png?fit=512%2C512&ssl=1\",\"width\":512,\"height\":512,\"caption\":\"Dev95\"},\"image\":{\"@id\":\"https:\\\/\\\/dev95.site\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/dev95.site\\\/#\\\/schema\\\/person\\\/b807805ffe2916206b04d0938bce0298\",\"name\":\"dev95\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ar\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a70a73d950838b20cd80d7ebdc955737e802e8cd896044c5473b32b946c0662a?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a70a73d950838b20cd80d7ebdc955737e802e8cd896044c5473b32b946c0662a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a70a73d950838b20cd80d7ebdc955737e802e8cd896044c5473b32b946c0662a?s=96&d=mm&r=g\",\"caption\":\"dev95\"},\"url\":\"https:\\\/\\\/dev95.site\\\/ar\\\/author\\\/mohammad\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Deploy CoreML Models on the Server with Vapor - Dev95","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/dev95.site\/ar\/deploy-coreml-models-on-the-server-with-vapor\/","og_locale":"ar_AR","og_type":"article","og_title":"Deploy CoreML Models on the Server with Vapor - Dev95","og_description":"Get the benefits of Apple\u2019s ML tools server-side. SwiftUI client showing image classification results Recently, at Sovrn, we had an AI Hackathon where we were encouraged to experiment with anything related to machine learning. The Hackathon yielded some fantastic projectsRead more &gt;&gt;&gt;","og_url":"https:\/\/dev95.site\/ar\/deploy-coreml-models-on-the-server-with-vapor\/","og_site_name":"Dev95","article_published_time":"2023-11-10T17:30:15+00:00","og_image":[{"url":"https:\/\/cdn-images-1.medium.com\/max\/1024\/1*XMjKfWYZYPikQ0pJ391YaA.png","type":"","width":"","height":""}],"author":"dev95","twitter_card":"summary_large_image","twitter_misc":{"\u0643\u064f\u062a\u0628 \u0628\u0648\u0627\u0633\u0637\u0629":"dev95","\u0648\u0642\u062a \u0627\u0644\u0642\u0631\u0627\u0621\u0629 \u0627\u0644\u0645\u064f\u0642\u062f\u0651\u0631":"10 \u062f\u0642\u0627\u0626\u0642"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/dev95.site\/deploy-coreml-models-on-the-server-with-vapor\/#article","isPartOf":{"@id":"https:\/\/dev95.site\/deploy-coreml-models-on-the-server-with-vapor\/"},"author":{"name":"dev95","@id":"https:\/\/dev95.site\/#\/schema\/person\/b807805ffe2916206b04d0938bce0298"},"headline":"Deploy CoreML Models on the Server with Vapor","datePublished":"2023-11-10T17:30:15+00:00","mainEntityOfPage":{"@id":"https:\/\/dev95.site\/deploy-coreml-models-on-the-server-with-vapor\/"},"wordCount":1215,"commentCount":0,"publisher":{"@id":"https:\/\/dev95.site\/#organization"},"image":{"@id":"https:\/\/dev95.site\/deploy-coreml-models-on-the-server-with-vapor\/#primaryimage"},"thumbnailUrl":"https:\/\/cdn-images-1.medium.com\/max\/1024\/1*XMjKfWYZYPikQ0pJ391YaA.png","articleSection":["Posts"],"inLanguage":"ar","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/dev95.site\/deploy-coreml-models-on-the-server-with-vapor\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/dev95.site\/deploy-coreml-models-on-the-server-with-vapor\/","url":"https:\/\/dev95.site\/deploy-coreml-models-on-the-server-with-vapor\/","name":"Deploy CoreML Models on the Server with Vapor - Dev95","isPartOf":{"@id":"https:\/\/dev95.site\/#website"},"primaryImageOfPage":{"@id":"https:\/\/dev95.site\/deploy-coreml-models-on-the-server-with-vapor\/#primaryimage"},"image":{"@id":"https:\/\/dev95.site\/deploy-coreml-models-on-the-server-with-vapor\/#primaryimage"},"thumbnailUrl":"https:\/\/cdn-images-1.medium.com\/max\/1024\/1*XMjKfWYZYPikQ0pJ391YaA.png","datePublished":"2023-11-10T17:30:15+00:00","breadcrumb":{"@id":"https:\/\/dev95.site\/deploy-coreml-models-on-the-server-with-vapor\/#breadcrumb"},"inLanguage":"ar","potentialAction":[{"@type":"ReadAction","target":["https:\/\/dev95.site\/deploy-coreml-models-on-the-server-with-vapor\/"]}]},{"@type":"ImageObject","inLanguage":"ar","@id":"https:\/\/dev95.site\/deploy-coreml-models-on-the-server-with-vapor\/#primaryimage","url":"https:\/\/cdn-images-1.medium.com\/max\/1024\/1*XMjKfWYZYPikQ0pJ391YaA.png","contentUrl":"https:\/\/cdn-images-1.medium.com\/max\/1024\/1*XMjKfWYZYPikQ0pJ391YaA.png"},{"@type":"BreadcrumbList","@id":"https:\/\/dev95.site\/deploy-coreml-models-on-the-server-with-vapor\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/dev95.site\/"},{"@type":"ListItem","position":2,"name":"Deploy CoreML Models on the Server with Vapor"}]},{"@type":"WebSite","@id":"https:\/\/dev95.site\/#website","url":"https:\/\/dev95.site\/","name":"Dev95","description":"A comprehensive platform for data and knowledge, delivering reliable content that meets the aspirations of readers and enthusiasts.","publisher":{"@id":"https:\/\/dev95.site\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/dev95.site\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"ar"},{"@type":"Organization","@id":"https:\/\/dev95.site\/#organization","name":"Dev95","url":"https:\/\/dev95.site\/","logo":{"@type":"ImageObject","inLanguage":"ar","@id":"https:\/\/dev95.site\/#\/schema\/logo\/image\/","url":"https:\/\/i0.wp.com\/dev95.site\/wp-content\/uploads\/2026\/07\/rbrrbr-6.png?fit=512%2C512&ssl=1","contentUrl":"https:\/\/i0.wp.com\/dev95.site\/wp-content\/uploads\/2026\/07\/rbrrbr-6.png?fit=512%2C512&ssl=1","width":512,"height":512,"caption":"Dev95"},"image":{"@id":"https:\/\/dev95.site\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/dev95.site\/#\/schema\/person\/b807805ffe2916206b04d0938bce0298","name":"dev95","image":{"@type":"ImageObject","inLanguage":"ar","@id":"https:\/\/secure.gravatar.com\/avatar\/a70a73d950838b20cd80d7ebdc955737e802e8cd896044c5473b32b946c0662a?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/a70a73d950838b20cd80d7ebdc955737e802e8cd896044c5473b32b946c0662a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/a70a73d950838b20cd80d7ebdc955737e802e8cd896044c5473b32b946c0662a?s=96&d=mm&r=g","caption":"dev95"},"url":"https:\/\/dev95.site\/ar\/author\/mohammad\/"}]}},"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/dev95.site\/ar\/wp-json\/wp\/v2\/posts\/1457","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dev95.site\/ar\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dev95.site\/ar\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dev95.site\/ar\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dev95.site\/ar\/wp-json\/wp\/v2\/comments?post=1457"}],"version-history":[{"count":0,"href":"https:\/\/dev95.site\/ar\/wp-json\/wp\/v2\/posts\/1457\/revisions"}],"wp:attachment":[{"href":"https:\/\/dev95.site\/ar\/wp-json\/wp\/v2\/media?parent=1457"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev95.site\/ar\/wp-json\/wp\/v2\/categories?post=1457"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev95.site\/ar\/wp-json\/wp\/v2\/tags?post=1457"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}