# Welcome to LatticaAI

LatticaAI is a state-of-the-art **FHE-as-a-service**, powered by off-the-shelf acceleration hardware, to enable secure processing of encrypted workloads.

Our platform provides data privacy and integrity by utilizing homomorphic encryption (FHE) and a client/server usage flow of encrypting, evaluating, and decrypting.

<figure><img src="/files/XqMDFYEiW6JXwbNUaS5a" alt="" width="524"><figcaption><p>FHE client/server usage flow of <em>Encrypt, Evaluate, Decrypt</em></p></figcaption></figure>

This documentation provides detailed instructions on deploying and running encrypted workloads, ensuring you have all the information needed to use our services effectively.

### Prerequisites

This documentation assumes a basic understanding of client/server architecture and fully-homomorphic encryption ([FHE](https://www.lattica.ai/fully-homomorphic-encryption)) terminology.


# Conceptual Guide

This page provides an overview of how our system operates, the roles of each actor, and the process required for setup and ongoing use.

## Actors

<mark style="color:blue;">⫸</mark> **Workload Provider**: The organization that owns and manages the Privacy-preserving compute workload. The workload provider sets up the system, uploads the executable logic, and handles operations such as resource management and credit maintenance.&#x20;

<mark style="color:blue;">⫸</mark> **End User**: The individual interacting with a deployed computation by sending encrypted queries. They use a provider-issued access token to securely communicate with the system.

<mark style="color:blue;">⫸</mark> **LatticaAI Backend**: Our cloud-based core system securely manages providers data, he compute artifacts, access tokens, and financial transactions. It handles all encrypted queries and responses.

<mark style="color:blue;">⫸</mark> **Worker**: A hardware accelerator that runs encrypted computations. We currently use GPUs, but our hardware-agnostic architecture - powered by [**HEAL**](https://platformdocs.lattica.ai/www.lattica.ai/HEAL), our integration layer, enables support for any FHE-compatible acceleration hardware.

***

## System Workflow and Stages

LatticaAI’s platform is organized into five key stages, combining one-time setup and ongoing operations across different roles. Each stage defines a specific set of responsibilities handled via either the **Lattica Web Console** (or **Python SDK)** or the [**Query Client**](/architecture-overview/query-client), depending on the actor.

Below is a breakdown of each stage, detailing the responsibilities, timing, and actors involved.

<figure><img src="/files/ISGwsRTgRvTgkAmDCM9q" alt=""><figcaption><p>Diagram of system workflow and stages</p></figcaption></figure>

{% stepper %}
{% step %}

### AI Provider Workspace Preparation (One-Time Setup)

*Prepares your environment to support encrypted computation processing.*

* **Account Creation**: Register on the LatticaAI platform.
* **Consultation and Confirmation**: [Contact us](http://www.lattica.ai/company#contact-us) to verify your workload's compatibility with the homomorphic encrypted processing.
* **Computation Management Tooling:** Use the **Web Console** or [install ](/how-to-guides/client-installation/how-to-install-management-client)the **Management Client** to manage computation onboarding and operations.
* **Computation Submission**: [Submit your computation](/how-to-guides/workload-lifecycle/how-to-deploy-workload) via the chosen interface. LatticaAI prepares it for secure execution and notifies you when it’s ready.

{% hint style="danger" %}
Typically a one-time setup. Only revisit if your computation or infrastructure undergoes major changes.
{% endhint %}
{% endstep %}

{% step %}

### Interaction Setup (As Needed)

*Manages access and financial readiness for secure computation.*

* [**Access Token Generation**](/how-to-guides/access-control/how-to-create-user-access-token): Create tokens to control who can access your deployed computation.
* [**Credit Management**](/platform-workflows/credit-management): Maintain credit balance to keep worker nodes active. If credits run out, workers will automatically shut down.
  {% endstep %}

{% step %}

### End-User Workspace Setup (One-Time Setup)

*Sets up the environment for secure, encrypted communication with your deployed computation.*

* [**Query Client Installation**](/how-to-guides/client-installation/how-to-install-query-client): Installs the [query client](/architecture-overview/query-client) on the user device.
* [**Evaluation Key Generation**](/how-to-guides/secure-query-processing/how-to-upload-evaluation-key): Generates an evaluation key (EVK) for encrypted data transmission and secure execution.
  {% endstep %}

{% step %}

### Worker Lifecycle Management (Ongoing)

*Optimizes compute usage and cost through manual control of worker activity.*

* **Worker Activation/Deactivation**:  [Start ](/how-to-guides/resource-management/how-to-start-worker)workers when needed; [stop ](/how-to-guides/resource-management/how-to-stop-worker)them when idle to control costs.
  {% endstep %}

{% step %}

### Secure Query Processing (Ongoing)

*Executes encrypted queries from end users to your deployed computation.*

* [**Query Submission**](/how-to-guides/secure-query-processing/how-to-execute-query): The end user sends encrypted input for secure execution.
* **Encrypted Response**: The worker processes the query and returns a fully encrypted result.
  {% endstep %}
  {% endstepper %}

{% hint style="info" %}
🔧 **Note:**\
Most provider-side activities (Stages 1, 2, and 4) can be performed either via the **Management Client's** Python SDK (for integration into your systems) or through our **Web Console** (for ease of use).\
End-user operations (Stages 3 and 5) are handled exclusively through the **Query Client**.
{% endhint %}

***

## Summary of Responsibilities

| Actor             | Responsibilities                                                                                                                                                     |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| AI Provider       | Initial account setup, workload configuration, token and credit management, worker administration, and Lattica Query Client deployment in the end-user's environment |
| End User          | Evaluation Key generation, ongoing query submission                                                                                                                  |
| LatticaAI Backend | Manages accounts, execution resources, access tokens, and encrypted data handling throughout the process.                                                            |
| Worker            | Executes homomorphic computations in the cloud as directed by the  provider, based on available credits                                                              |

***

## Pricing Model

Our platform uses a credit system.&#x20;

Workload providers are charged for active worker time and must maintain enough credits to keep the service running.

Workers remain active while credits are available, but the provider can also stop them manually. \
When credits run out, all active workers automatically shut down.&#x20;

This approach optimizes resource usage and helps providers control their costs effectively.

***

## Key Points

<mark style="color:blue;">⫸</mark>  **Cost Control with Credits**: Workload providers must maintain enough credits to activate and keep workers running. If credits are depleted, active workers will automatically stop.

<mark style="color:blue;">⫸</mark>  **One-Time vs. Ongoing Tasks**: Workspace Preparation and End-User Connection Setup are one-time tasks, while Worker Management and Query Processing are ongoing, based on resource needs.

<mark style="color:blue;">⫸</mark>  **Encryption Throughout**: All interactions with the workloads are encrypted, ensuring end-to-end data privacy.


# Pricing

Usage-based pricing for Lattica's compute services.

{% hint style="info" %}
Lattica currently offers pricing on a case-by-case basis depending on deployment requirements, workload characteristics, and support needs.

To discuss your use case and receive pricing information, please contact us at: **<hello@lattica.ai>**

We will work with you to determine the best configuration and pricing for your needs.
{% endhint %}

***


# Architecture Overview

The LatticaAI platform enables **secure processing of encrypted computations**, including AI inference workloads, encrypted vector search, and programs. It uses homomorphic encryption and purpose-built acceleration hardware to perform computation without exposing raw data.

The system consists of **client applications** for management and execution, a **backend control plane**, and **hardware accelerators** to perform secure computation.

<img src="/files/SP5puu6UhgOu4ogJn6Gu" alt="Diagram of the main components in the LatticaAI system." class="gitbook-drawing">

## Components

### 1. LatticaAI Clients

<mark style="color:blue;">⫸</mark> The Management Client enables the **Computation Provider** to onboard and manage computations:

&#x20;  <mark style="color:blue;">►</mark> Submit encrypted computations for execution.

&#x20;  <mark style="color:blue;">►</mark> Configure access controls and resource assignments.

&#x20;  <mark style="color:blue;">►</mark> Allocate and monitor compute resources.

After submission, the computation is prepared and registered in the backend, becoming available for secure execution at an assigned execution endpoint.

<mark style="color:blue;">⫸</mark> The **Query Client** facilitates secure interactions with deployed computations.

&#x20;  <mark style="color:blue;">►</mark> It encrypts input data before sending it to the backend for computation.

&#x20;  <mark style="color:blue;">►</mark> The backend processes queries using the homomorphic-ready logic and returns encrypted results.

&#x20;  <mark style="color:blue;">►</mark> The client decrypts the results locally, ensuring data privacy throughout the process.

<table data-card-size="large" data-view="cards" data-full-width="false"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Management Client</strong></td><td>Enables Computation <strong>Providers</strong> to control deployment, manage user permissions, and oversee system resources</td><td></td><td><a href="/files/zPshHASYLP32RdlzS63b">/files/zPshHASYLP32RdlzS63b</a></td><td><a href="/pages/pEVhWbKsWPalGMCO6cmP">/pages/pEVhWbKsWPalGMCO6cmP</a></td></tr><tr><td><strong>Query Client</strong>  </td><td><strong>End users</strong> use this client to access the deployed secured computation.</td><td></td><td><a href="/files/GedAzeqWjCILZucGabbj">/files/GedAzeqWjCILZucGabbj</a></td><td><a href="/pages/DeQLM1YR2UewMJvDwqGJ">/pages/DeQLM1YR2UewMJvDwqGJ</a></td></tr></tbody></table>

***

### 2. LatticaAI **Backend**

<mark style="color:blue;">⫸</mark> **Interaction Manager:** Routes requests to the appropriate encrypted computation.

<mark style="color:blue;">⫸</mark> **Hardware Acceleration:** Currently optimized for GPU-based execution, with a flexible architecture designed to support future hardware acceleration technologies.

***


# Management Client

The Management Client is designed for **Computation Providers** to manage all aspects of computation setup, integration, and resource management. Providers can perform these activities using either the **Lattica Web Console** or the **Python SDK**.

{% hint style="info" %}
Before using either option, you must **sign up** on the Lattica Console to create an account and receive your **Account ID**.
{% endhint %}

{% stepper %}
{% step %}

### Installing the Management Package (Python SDK)

If you choose to use the Python SDK, [install](/how-to-guides/client-installation/how-to-install-management-client) the **Management Client package.** This package provides all functionalities needed for deploying computations, managing tokens, and controlling workers.
{% endstep %}

{% step %}

### Model Compilation and Integration

The Management Client enables Workload Providers to deploy and manage their computations in Lattica’s system.

* **Deployment Options**:
  * Use the **Web Console** for an intuitive user interface.
  * Use the **Python SDK** for programmatic integration.
* **Process**:
  * [Deploy](/how-to-guides/workload-lifecycle/how-to-deploy-workload) workload to LatticaAI’s backend
  * Workloads can be [managed](/how-to-guides/workload-lifecycle/how-to-modify-workload-settings) (updated, activated, or deactivated) after deployment.

{% hint style="warning" %}
**Note**: The model will be ready for processing only after LatticaAI builds the **homomorphic-ready model** in the backend.&#x20;

After LatticaAI confirms the model's successful creation, the provider can begin using it for encrypted data processing.
{% endhint %}
{% endstep %}

{% step %}

### Access Token Management

The Management Client provides tools to manage **User Access Tokens**, which control secure access to deployed computations.

* **Token Functions**:
  * [Create ](/how-to-guides/access-control/how-to-create-user-access-token)new tokens.
  * [Activate or deactivate](/how-to-guides/access-control/how-to-modify-user-access-token-setting) tokens.
  * [Assign ](/how-to-guides/access-control/how-to-assign-token-to-workload)or [reassign ](/how-to-guides/access-control/how-to-remove-tokens-assignment)tokens to specific workload.

These activities can be performed via the Web Console or the Python SDK.
{% endstep %}

{% step %}

### Worker (GPU) Management

After workloads and tokens are set up, Providers can control computational resources by managing **workers**.

* **Worker Functions**:
  * [Start](/how-to-guides/resource-management/how-to-start-worker) or [stop ](/how-to-guides/resource-management/how-to-stop-worker)**workers** as needed for active operations.
  * [Monitor ](/how-to-guides/resource-management/how-to-monitor-worker-performance)worker performance and optimize resource allocation.

Providers can perform these activities through the Web Console or Python SDK, giving full control over runtime and resources.
{% endstep %}
{% endstepper %}


# Query Client

{% hint style="info" %}
**Access Requirements**

To interact with a workload, an end-user will need a unique access key—called a Token—provided by the workload service provider using LatticaAI. This token is crucial for establishing secure connections with the computations and maintaining private communication through the Query Client.

> **Try Our** [**Demo**](https://www.lattica.ai/workloads)**!**
>
> LatticaAI offers demo models using a predefined token. No special permissions needed—just explore the Query Client’s features and experience secure, encrypted interactions firsthand.
> {% endhint %}

***

## Interaction Options

**LatticaAI** offers a **TypeScript SDK** for queries within web environments and a **Python SDK** for integrating secure query capabilities in native applications. We also maintain a [**GitHub repository**](https://github.com/Lattica-ai/lattica_fhe_core), containing the core Fully Homomorphic Encryption (FHE) logic, which covers key generation, encryption, and decryption.

***

## Query Client: Key Functions and Flow

{% hint style="info" %}
**Note on Query Semantics**\
The term *query* is used generically to describe an encrypted request sent for secure execution. Depending on the workload, a query may represent an inference request or a vectorized search operation.
{% endhint %}

The Query Client process consists of three stages:

{% stepper %}
{% step %}

### Environment Preparation&#x20;

[Set up an environment](/how-to-guides/client-installation/how-to-install-query-client) to support the Query Client.&#x20;
{% endstep %}

{% step %}

### One-Time Action: Cryptographic Key Generation

* Once the environment is ready, generate a pair of cryptographic keys—an **evaluation key** and a **secret key**.&#x20;
  * The secret key protects all future interactions with the computation, securing your data every step of the way.
  * The evaluation key is public and accelerates the computation of these interactions to reduce latency.
* This key generation is a one-time process and doesn't need to be repeated for each query.
  {% endstep %}

{% step %}

### Ongoing Process: Query Execution

With the environment ready and keys generated, you can start executing queries. The Query Client enables you to run multiple queries securely, using the same pair of generated keys to protect all data exchanges throughout your session.
{% endstep %}
{% endstepper %}

***

***


# Platform Workflows

The workflow level in LatticaAI’s documentation provides high-level overviews of major functionalities and features. Workflows are designed to help Computation providers understand the purpose, scope, and structure of various system components before diving into detailed instructions or technical specifics.

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><h4>Account Management</h4></td><td><a href="/files/TBrvGg8yGoGUQhHpVHtR">/files/TBrvGg8yGoGUQhHpVHtR</a></td><td><a href="/pages/RCCPD5GTKZmi9156mrXm">/pages/RCCPD5GTKZmi9156mrXm</a></td></tr><tr><td><h4>Workload Management</h4></td><td><a href="/files/UPVYaPucDS7I2khCwftm">/files/UPVYaPucDS7I2khCwftm</a></td><td><a href="/pages/TxJ20tPm5d3u0DTNMZ5B">/pages/TxJ20tPm5d3u0DTNMZ5B</a></td></tr><tr><td><h4>User Access Management</h4></td><td><a href="/files/kQ1G6ucDNqGy0Fl562cM">/files/kQ1G6ucDNqGy0Fl562cM</a></td><td><a href="/pages/Mgg2iv8SCWFEGjZ6aMUN">/pages/Mgg2iv8SCWFEGjZ6aMUN</a></td></tr><tr><td><h4>Credit Management</h4></td><td><a href="/files/QQzxgo0hbBU29abD8weO">/files/QQzxgo0hbBU29abD8weO</a></td><td><a href="/pages/LrG96wTVXhMYdRzpCiWF">/pages/LrG96wTVXhMYdRzpCiWF</a></td></tr><tr><td><h4>Worker Management</h4></td><td><a href="/files/m3cG9FiZdQu2yZjUMSKZ">/files/m3cG9FiZdQu2yZjUMSKZ</a></td><td><a href="/pages/OuXhGZJIRQgClNqXkfw8">/pages/OuXhGZJIRQgClNqXkfw8</a></td></tr><tr><td><h4>Query Submission    </h4></td><td><a href="/files/ptL54e3XkEsaCNKw0a4Z">/files/ptL54e3XkEsaCNKw0a4Z</a></td><td><a href="/pages/e5RJewdnRjKh3yDskx6p">/pages/e5RJewdnRjKh3yDskx6p</a></td></tr></tbody></table>


# Account Management

Account Management is the starting point for accessing and managing all features of the LatticaAI platform.

## Getting Started: Sign Up

To begin using LatticaAI services, **Computation providers** must first create an account. The registration process requires basic information, and an **Account ID** will be assigned upon successful completion.

{% hint style="info" %}
**Account ID**: This unique identifier provides access to all system features outlined in the \[[Conceptual Guide](/conceptual-guide)].<br>

💡Registration is not required for end-user activities performed through the Query Client. End-users rely on access tokens provided by the Computation Provider and do not interact directly with the LatticaAI platform's account management system.
{% endhint %}

***

## Managing Account Information

After creating your account, you can update your contact details, such as email address and phone number, through the **Account Settings** page.

***

## The Web Console and Dashboard

After registration, you'll get access to the **web console** - a central hub for managing your services. The **Dashboard** is your main landing page, showing key metrics and quick links to manage your account.

<figure><img src="/files/FrbgItFKng9gkwrCKQvd" alt=""><figcaption><p>Model Dashboard</p></figcaption></figure>

### Main Dashboard Sections

1. **Account Balance**
   * Track your available credits and estimated runtime
2. **Model Overview**
   * Monitor active models and their performance at a glance
3. **Individual Model Details**\
   Each model section shows:
   * **Performance Data**: Current metrics and configuration status
   * **User Access Control**: Active user access tokens
   * **Resource Usage**: Active worker status
4. **Sidebar Tools**\
   Direct access to:
   * **Model Controls (Dashboard)**
   * **Tokens (User Access) Settings**
   * **Finance Center**
   * **Account Details Setting**

***

## Quick Links to How-To Pages

For detailed instructions, refer to the following guides:

* \[[How-To: Update Account Information](/how-to-guides/account-and-finance-operations/how-to-update-account-information-and-generate-license)]

***


# Workload Management

Workload Management allows providers to securely deploy and manage their Privacy-preserving workloads on the LatticaAI platform.

## Prerequisite: Providers Registration

To access LatticaAI’s Workload Management features, providers must:

* **Sign Up:** Register on the LatticaAI platform and complete the onboarding details.
* **Choose Your Management Interface:**
  * Use the **Web Management Console** for a streamlined, browser-based experience\
    —or—
  * [**Install the Management Client**](/how-to-guides/client-installation/how-to-install-management-client) if you prefer to integrate directly via our SDK.

Both options support full workload deployment and management workflows - choose the one that fits your development style.

***

## Workload Management Workflow

To use your Privacy-preserving workloads with LatticaAI, follow these steps:

{% stepper %}
{% step %}

### Consultation and Workload Deployment

[Contact us](https://platformdocs.lattica.ai/platform-workflows/www.lattica.ai/company#contact-us) to evaluate whether your AI model is suitable for encrypted data processing.

If the model is compatible, [deploy it ](/how-to-guides/workload-lifecycle/how-to-deploy-workload)to the LatticaAI backend using the Management Client.&#x20;
{% endstep %}

{% step %}

### Homomorphic-Ready Model Creation

LatticaAI will transform the deployed model to create a homomorphic-ready version for encrypted data processing. Once this process is complete:

* The model's status in the system will change from **"Pipeline Pending"** to **"Active"**.
* The updated status will be visible in the Web Console, allowing the provider to manage and utilize the model for encrypted data interactions.
  {% endstep %}

{% step %}

### Manage Your Model

After deployment, you can manage your workload through the **web console** or **Python SDK**.

[**Change Workload Settings**](/how-to-guides/workload-lifecycle/how-to-modify-workload-settings):

* **Status**: Set the model as **active** or **inactive**.

  <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p>Queries can only run on active workloads that have at least one linked worker assigned to process the requests.</p></div>
* **Name and Description**: Update the workload’s name or description to keep records accurate.
  {% endstep %}
  {% endstepper %}

***

## Quick Links to How-To Pages

For detailed steps, refer to the following guides:

* \[How-To: [Install Management Client](/how-to-guides/client-installation/how-to-install-management-client)]
* \[How-To: [Deploy Model](/how-to-guides/workload-lifecycle/how-to-deploy-workload)]
* \[How-To: [Update Model Setting Parameters](/how-to-guides/workload-lifecycle/how-to-modify-workload-settings)]

***


# User Access Management

### **Token-Based Access**

Access to AI models is granted through **User Access Tokens**, which are:

<mark style="color:blue;">⫸</mark> **Model-Specific**: Each token is tied to a **single AI model** and cannot be used with other models.

<mark style="color:blue;">⫸</mark> **User-Specific**: A token grants access to **one user** only.

***

### User Access Management Flow

1. **Create User Access Tokens**

   AI Providers initiate the creation of tokens, specifying the model the token will access.

   <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p>Tokens can be created without being assigned to a specific model initially. These tokens can later be assigned to a model as needed.</p></div>

2. **Assign Tokens** \
   Assign a token to a specific AI model to enable secure access.

3. **Reassign Tokens**

   Reassignment requires two actions: first, remove the current assignment to make the token unassigned, and then assign it to the new model.

4. **Update Token Attributes**

   AI Providers can update attributes such as token description or status (active/cancelled).

5. **View Token Details**

   AI providers can view a token’s full definition, including its assigned model, status, and expiration date.

***

### Quick Links to How-To Pages

For detailed steps, refer to the following pages:

* \[How-To: [Create User Access Token](/how-to-guides/access-control/how-to-create-user-access-token)]
* \[How-To: [Assign a Token to Model](/how-to-guides/access-control/how-to-assign-token-to-workload)]
* \[How-To: [Remove Token’s Assignment](/how-to-guides/access-control/how-to-remove-tokens-assignment)]
* \[How-To: [Update Token Attributes or Status](/how-to-guides/access-control/how-to-modify-user-access-token-setting)]
* \[How-To: [View Tokens Details](/how-to-guides/access-control/how-to-see-list-of-tokens)]

***


# Query Submission

End-users interact with Workloads on LatticaAI by submitting queries through the Query Client. This document provides an overview of the steps required to submit queries.

{% hint style="info" %}

#### Public Models for Demonstration

For providers who want to showcase their AI models and demonstrate how they operate with homomorphic encryption, LatticaAI offers the option to create a dedicated **Demo Web Page**. This page allows potential users to interact securely with the model without the need to set up a separate Query Client or define individual access tokens.

Once the demo page is created, a unique link will be provided to the AI provider. This link can be used in presentations, marketing materials, or shared directly with potential customers, making it easy to highlight the model’s capabilities and secure processing in a real-world scenario.

Providers can explore[ **LatticaAI’s demo**](https://www.lattica.ai/workloads) as an example of how the demo page works.
{% endhint %}

## Overview

* **Query Client**:

  All end-user activities are performed via the **Query Client**, which handles secure data encryption and communication with the LatticaAI backend.
* **Access Token**:

  Each user receives a unique **Access Token** from the Computation Provider. This token is specific to the user and the computation it is associated with. The token is used for authentication and is required for all communications with LatticaAI.

{% hint style="info" %}
LatticaAI provides a Python and TypeScript SDK packages for query submission, allowing providers to implement their own user interface for end-users. It is the AI provider’s responsibility to build the UI using the provided SDK packages.
{% endhint %}

***

## Query Submission Workflow

<img src="/files/y4GCGHmcsZx8yxyw3Tls" alt="Communication phases between the Query Client and an Access Point." class="gitbook-drawing">

{% stepper %}
{% step %}

### **H**andshake

The first step in query submission is the **handshake** process.&#x20;

* The Query Client establishes a connection with the corresponding computation using the **Access Token**.
* The handshake ensures the client receives all necessary metadata related to the computation.
  {% endstep %}

{% step %}

### G**enerate Encryption Key (evk)**

Before submitting queries, the user must create a pair of encryption keys:

* **Secret Key**: Used to encrypt and decrypt messages.
* **Evaluation Key**: Sent to the LatticaAI backend to enable efficient computation.

{% hint style="info" %}
&#x20;This is a one-time setup. The same keys can be reused for all interactions with the computation.
{% endhint %}
{% endstep %}

{% step %}

### E**ncrypt the Query**

The user encrypts the query message using their **Secret Key**.
{% endstep %}

{% step %}

### S**end the Encrypted Query**

* The encrypted query and **Access Token** are transmitted to the LatticaAI backend for processing.
* LatticaAI verifies the token, processes the query, and returns the result as an encrypted message.
  {% endstep %}

{% step %}

### D**ecrypt the Result**

The user decrypts the encrypted result using their **Secret Key** to obtain the final output.
{% endstep %}
{% endstepper %}

***

{% hint style="info" %} <mark style="color:blue;">⫸</mark> Queries can only be processed when a worker is running for the associated model.

<mark style="color:blue;">⫸</mark> Computation Providers are responsible for running and monitoring workers through our console or Python SDK
{% endhint %}

***

## Quick Links to Related How-To Pages

* \[How-To: [Generate Evaluation Key](/how-to-guides/secure-query-processing/how-to-upload-evaluation-key)]
* \[How-To: [Encrypt Input Message](/how-to-guides/secure-query-processing/how-to-encrypt-input-message)]
* \[How-To: [Execute Query](/how-to-guides/secure-query-processing/how-to-execute-query)]
* \[How-To: [Decrypt Output data](/how-to-guides/secure-query-processing/how-to-decrypt-output-data)]

***


# Credit Management

{% hint style="info" %}
**Credits for Worker Operations**

<mark style="color:blue;">⫸</mark> Credits are consumed based on workers' active runtime.

<mark style="color:blue;">⫸</mark> Workers can only operate if sufficient credits are available.

<mark style="color:blue;">⫸</mark> If credits are depleted, all active workers are automatically stopped.
{% endhint %}

## Credit Management Workflow

{% stepper %}
{% step %}

### Adding Credits

To ensure sufficient credits for operations, Computation providers can purchase credits at any time.
{% endstep %}

{% step %}

### Monitoring Balance and Usage

Regularly check your account balance to avoid interruptions in worker activity.
{% endstep %}

{% step %}

### Reviewing Transaction History

Keep track of past payments and credit usage by accessing the transaction history.
{% endstep %}

{% step %}

### Managing Credit Alerts (Coming Soon)

In future releases, providers will be able to set alerts for low credit levels, ensuring timely top-ups and uninterrupted service.
{% endstep %}
{% endstepper %}

## Quick Links to How-To Pages

For detailed steps, refer to the following guides:

* \[How-To: [View Credit Balance and Add Credit to Your Account](/how-to-guides/account-and-finance-operations/how-to-view-credit-balance-and-add-credit-to-your-account)]
* \[How-To: [Monitor Balance and Usage](/how-to-guides/account-and-finance-operations/how-to-monitor-balance-and-usage)]
* \[How-To: [View Transaction History](/how-to-guides/account-and-finance-operations/how-to-view-payment-transaction-history)]


# Worker Management

This workflow provides a high-level overview of managing workers, including running, monitoring, and stopping them.

## Fundamentals

1. **Worker-Model Relationship**
   * Each worker operates for a **single workload**, created and managed by the Workload Provider.
   * **One Worker, One Workload**: Workers cannot process multiple workloads, but a single workload can be deployed on multiple workers simultaneously.
2. **Credit-Based Payment**
   * Workload Providers pay for workers’ runtime using credits purchased in advance.
   * The worker continuously deducts credits while in operation.
3. **Requirements to Start a Worker**
   * The workload must be **active**.
   * The provider’s account must have **sufficient credits** to sustain the worker.
4. **Query Processing and Worker Runtime**\
   When an end user submits a query using a valid **access token**, the request is routed to a **worker** running the workload associated with that token.
   * **Workers** execute encrypted queries.
   * **Workload Providers** are billed based on the **runtime of active workers**, not the number of queries processed.
   * **Performance Considerations:** High query volumes on a single worker may impact response times - scale worker sessions accordingly for optimal performance.
5. **Scaling Workers**
   * Providers can start additional workers for the same workload if performance drops due to high query volume.
   * There is **no limit** to the number of workers that can run for a workload simultaneously.
6. **Monitoring Worker Performance**
   * Providers can monitor worker performance by viewing:
     * **Average Query Time**: The average processing time for a query on the workload.
     * **Current Query Time**: The real-time processing time for queries on the workload.
7. **Stopping Workers**
   * Workers can be stopped manually at any time.
   * If credits are depleted, workers are automatically stopped.

***

## Worker Management Workflow

{% stepper %}
{% step %}

### S**tart Worker**

Before starting a worker, verify that your account has sufficient credits and check that your workload is properly activated in the system.
{% endstep %}

{% step %}

### M**onitor Performance**

Regularly check query performance metrics (average and current query time). Add workers if needed to maintain optimal performance.
{% endstep %}

{% step %}

### S**top Worker**

Stop workers when they are no longer needed or when credit consumption needs to be managed.
{% endstep %}
{% endstepper %}

***

## Future Functionality

1. **Performance Notifications**\
   Workload Providers will receive alerts when worker performance drops below a defined threshold.
2. **Worker Usage Reports**\
   A detailed report of worker usage will help providers analyze and optimize their resource utilization.
3. **Scheduler for Worker Management**\
   Workload Providers will be able to define schedules to start and stop workers automatically, eliminating the need for manual operations. This functionality will help align worker usage with predictable query loads and save credits during low-demand periods.

***

## Quick Links to How-To Pages

For detailed steps, refer to the following guides:

* \[How-To: [Start Worker](/how-to-guides/resource-management/how-to-start-worker)]
* \[How-To: [Stop Worker](/how-to-guides/resource-management/how-to-stop-worker)]
* \[How-To: [Monitor Worker Performance](/how-to-guides/resource-management/how-to-monitor-worker-performance)]

***


# How-To Guides

Here you’ll find answers to "How do I...?" questions. The main goal of these guides is to help you finish certain tasks.&#x20;

## Installation

* How-To [Install Management Client](/how-to-guides/client-installation/how-to-install-management-client)
* How-To[ Install Query Client](/how-to-guides/client-installation/how-to-install-query-client)

<mark style="color:blue;">﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌</mark>

## Deployment Client

### Account Management

* How-To: [Update Account Information](/how-to-guides/account-and-finance-operations/how-to-update-account-information-and-generate-license)

### Model Management

* How-To: [Deploy AI Model](/how-to-guides/workload-lifecycle/how-to-deploy-workload)
* How-To: [Modify Model Details](/how-to-guides/workload-lifecycle/how-to-modify-workload-settings)

### User Access Management

* How-To: [Create User Access Token](/how-to-guides/access-control/how-to-create-user-access-token)
* How-To: [Assign a Token to Model](/how-to-guides/access-control/how-to-assign-token-to-workload)
* How-To: [Remove Token’s Assignment](/how-to-guides/access-control/how-to-remove-tokens-assignment)
* How-To: [Update Token Attributes or Status](/how-to-guides/access-control/how-to-modify-user-access-token-setting)
* How-To: [View Tokens Details](/how-to-guides/access-control/how-to-see-list-of-tokens)

### Worker Management

* How-To: [Start Worker](/how-to-guides/resource-management/how-to-start-worker)
* How-To: [Stop Worker](/how-to-guides/resource-management/how-to-stop-worker)
* How-To: [Monitor Worker Performance](/how-to-guides/resource-management/how-to-monitor-worker-performance)

### Credit Management

* How-To: [View Credit Balance and Add Credit to Your Account](/how-to-guides/account-and-finance-operations/how-to-view-credit-balance-and-add-credit-to-your-account)
* How-To: [Monitor Balance and Usage](/how-to-guides/account-and-finance-operations/how-to-monitor-balance-and-usage)
* How-To: [View Transaction History](/how-to-guides/account-and-finance-operations/how-to-view-payment-transaction-history)

<mark style="color:blue;">﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌</mark>

## Query Client

* How-To: [Generate Evaluation Key ](/how-to-guides/secure-query-processing/how-to-upload-evaluation-key)
* How-To: [Encrypt Input Message](/how-to-guides/secure-query-processing/how-to-encrypt-input-message)
* How-To: [Run Query](/how-to-guides/secure-query-processing/how-to-execute-query)
* How-To: [Decrypt Output Data](/how-to-guides/secure-query-processing/how-to-decrypt-output-data)


# Client Installation

This how-to documentation group includes functionalities required to set up and configure the Query and Management clients. It covers client installation and initialization, ensuring a smooth start to using the LatticaAI.

<mark style="color:blue;">﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌</mark>

* How-To [Install Management Client](/how-to-guides/client-installation/how-to-install-management-client)
* How-To[ Install Query Client](/how-to-guides/client-installation/how-to-install-query-client)

{% hint style="info" %}
Our client packages are currently available for Ubuntu 2024.04 only.
{% endhint %}


# How-To: Install Management Client

### Description:

This package should be used by an admin of your organization.

It provides the code for managing the compute machines (the machines that runs your models),

And the code for managing models and tokens.

{% tabs %}
{% tab title="🧊 Python SDK" %}
Install the management client package:

```python
pip install lattica-management
```

{% endtab %}
{% endtabs %}


# How-To: Install Query Client

### Description:

This package should be used by a user of your organization wanting to query your models.

{% tabs %}
{% tab title="🧊 Python SDK" %}

Install the query client package:

```python
pip install lattica-query
```

{% endtab %}

{% tab title="📦TypeScript SDK" %}
Install the package:

```bash
npm install @Lattica-ai/query
```

{% endtab %}
{% endtabs %}


# Workload Lifecycle

Features in this  how-to documentation group  manage the end-to-end lifecycle of workloads. This includes registering, deploying, updating, activating, and deactivating workloads, as well as tracking their readiness for encrypted data processing.

<mark style="color:blue;">﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌</mark>

* How-To: [Deploy AI Model](/how-to-guides/workload-lifecycle/how-to-deploy-workload)
* How-To: [Modify Model Details](/how-to-guides/workload-lifecycle/how-to-modify-workload-settings)


# How-To: Deploy Workload

Deploying an AI model to LatticaAI involves consultation, registration, submission, and homomorhic-ready model preparation. This guide walks you through the process.

{% hint style="warning" %}

### Important: Contact LatticaAI First

For **AI model deployments**, contact LatticaAI to discuss your model’s parameters. This consultation ensures that the model is compatible with encrypted data processing and can be successfully prepared as a homomorphic-ready workload.
{% endhint %}

<img src="/files/bvfGwHkUHd2ogh1qvhHy" alt="Diagram of the AI Model deployment process" class="gitbook-drawing">

{% stepper %}
{% step %}

### Register the Model

Before deployment, the AI model must be registered in the system to receive a unique identifier (**modelId**).

1. Use the **Management Client** via Python SDK to register the model.
2. Provide the required details during registration:
   * **Model Name**: This is a **mandatory field** and must be unique across the system.
   * **Optional Parameters**: You can include additional metadata, such as:
   * Description
   * Input type
   * Output type
3. **After registration,** a unique **model ID** will be generated and provided.

{% hint style="info" %}
**Model Management**: Once the model is registered, you can manage its settings (e.g., activate/deactivate, modify parameters) through the web console or Python SDK.
{% endhint %}
{% endstep %}

{% step %}

### Submit the AI Model LatticaAI Backend

Using the **Management Client or our Console**, submit the AI model associated with the registered **modelId**.
{% endstep %}

{% step %}

### Build the Homomorphic-Ready Model

After the AI model is submitted, LatticaAI prepares the model to process encrypted data securely.

1. Mastery builds the **Homomorphic Pipeline Model** from the submitted AI model.
2. During this process, the model status will remain **"Pending Pipeline"**.
3. Once the model is ready, its status will update to **"Active"**, and Mastery will notify you.

**Tracking**: You can monitor the model's status in the web console.

{% hint style="warning" %}
Currently, building a Homomorphic Pipeline requires the **Help Desk Service** assistance.

**Future Feature**: Automatic homomorphic-ready model creation from AI provider models will be supported in future releases.
{% endhint %}
{% endstep %}
{% endstepper %}

***

{% tabs %}
{% tab title="🌐Console" %}

<figure><img src="/files/Ids1NIvtldBVa0eNagTE" alt=""><figcaption></figcaption></figure>

1. **Open the Models Dashboard**
   * Click **Add Model** on the main dashboard. This opens a sidebar where you’ll enter your new model’s details.
2. **Provide Model Details**
   * **Name (required)**: Must be unique within your account.
   * **Description (optional)**: Briefly explain what your model does.
   * **Input/Output Types (optional)**: Specify whether your model uses images, audio, text, or vectors.
   * **Model Visibility (currently private only)**: Future versions will allow public sharing.
   * **Auto Restart (always On)**: A future release will offer manual restarts.
3. **Upload the AI Model File**
   * While not mandatory during initial registration, **the model file must be provided before any queries can run** (so it can be translated into a homomorphic-ready version).
   * If you have the file, click **Choose your Model here**. A placeholder diagram confirms the upload.
4. **Save Your Model**
   * **Nothing is saved until you click “Add.”** Changes, including file uploads, are only committed after pressing **Add** and seeing a success message.

{% hint style="warning" %}
Even if you receive a success message after providing all details, the model is not immediately ready for queries. We first need to build the homomorphic pipeline from your model, which can take additional time depending on its complexity. \
Once the homomorphic version is created and deployed, the model status changes to **Active**. For more information on model statuses, see our “[Model Settings](/how-to-guides/workload-lifecycle/how-to-modify-workload-settings)” documentation.
{% endhint %}
{% endtab %}

{% tab title="🧊Python SDK" %}

```python

# Create Plain Model
import LatticaManagement

# Authenticate
lattica = LatticaManagement("your_license_from_lattica_console")

# Register a new model...
model_id = lattica.create_model("model_name")

# Upload model...
with open("MyModel.pth", 'rb') as model_file:
    lattica.upload_plain_model_file(model_file, model_id)
    
```

{% endtab %}
{% endtabs %}


# How-To: Modify Workload Settings

Our system's workloads have configurable parameters that control their behavior. You can modify these after deploying your workload.

Each workload has two types of parameters:

There are **parameters you can change** and **parameters you can only view**. The system sets some parameters to default values:

#### **Updatable Parameters**:

| Name                 | Description                                                                                                                             | Is this information accessible to end-users or it is restricted to system providers only | Allowed Values                                                               |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| **Name**             | Define workload name. It should be unique.                                                                                              | End-user can see the inf                                                                 | Any non-empty string                                                         |
| **Status**           | Set the workload as **Active** (default) or **Canceled**.                                                                               | End-user can see the inf                                                                 | <p><code>ACTIVE</code>, <code>INACTIVE,</code> <br><code>UPLOADED</code></p> |
| **Description**      | A customizable free text field for workload details.                                                                                    | The info is restricted to providers                                                      | Any string, or none at all                                                   |
| **Input Type**       | Define the model’s input type (e.g., picture, audio, text, vector).                                                                     | <p>The info is restricted to providers <br>(Applies to AI models only)</p>               | `TEXT`, `PICTURE`, `AUDIO`, `VECTOR`                                         |
| **Output Type**      | Specify the model’s output type (e.g., picture, audio, text, vector).                                                                   | <p>The info is restricted to providers <br>(Applies to AI models only)</p>               | `TEXT`, `PICTURE`, `AUDIO`, `VECTOR`                                         |
| **Model Visibility** | Choose between **Private** (default, restricted access) or **Public** (accessible via the demo page).                                   | <p>The info is restricted to providers<br>(Applies to AI models only) </p>               | `PRIVATE`, `PUBLIC`                                                          |
| **Auto Restart**     | Allowing the model’s worker to restart if it fails automatically. Alternatively, a manual restart can be set. This is set On by default | The info is restricted to providers                                                      | `True, False`                                                                |

#### **View-Only Parameters** (for reference only - The info is restricted to AI providers ):

* **Model ID**: The unique identifier for the model.
* **Creation Date**: The date the model was created.
* **Model Version**: Current version number of the model.
* **Average Performance**: The average time to process queries on the model.

### Model Status Rules

{% hint style="info" %}
**Note on workload status**

The detailed status lifecycle described below applies to **AI models**.

For other workload types, the status model is simplified to **Active** and **Inactive**.
{% endhint %}

<figure><img src="/files/eqM9PBiVgNOl6svtyFGf" alt=""><figcaption></figcaption></figure>

1. Model status can be in one of three valid values: ACTIVE, INACTIVE, or UPLOADED.
2. A model that is registered without a plain model file is created with status INACTIVE.
3. When the first plain file is uploaded, the model status changes to UPLOADED.
4. A model can only have ACTIVE status if there is a valid homomorphic pipeline model defined in our server.
5. Users can cancel the model at any time (changing its status to INACTIVE); however,
6. It is not possible to change the model status when there is a worker active for the model.

{% tabs %}
{% tab title="🌐Console" %}

<figure><img src="/files/OF3CTKHMBgh75gjmIY9D" alt=""><figcaption></figcaption></figure>

1. **Navigate to Model Settings**
   * From the main dashboard, locate your AI model, click the **three dots** button next to it, and select **"View More"** to access the model parameters page.
2. **Update Parameters**
   * Adjust the **updatable parameters** as needed. You can change the **Status**, **Description**, **Input/Output Type**, **Model Visibility**, and **Auto Restart** settings directly in the portal.
3. Check Plain model file status and upload file when needed.
   * Missing plain model file: A black upload icon appears with a link if you didn't upload during Model Registration.
   * Pending homomorphic pipeline: Model icon shows red when file is uploaded but pipeline isn't built yet.&#x20;

     <div data-gb-custom-block data-tag="hint" data-style="warning" class="hint hint-warning"><p>You cannot upload a new model file until the pipeline is built. Contact support if you need to replace the model.</p></div>
   * Complete setup: File icon turns green when homomorphic pipeline is created. You can upload a new plain model file at this stage.
4. **Save Changes**
   * After updating the desired parameters, click **Save**. You’ll receive a **confirmation** if changes are applied successfully or an **error** message if an issue occurs.
     {% endtab %}

{% tab title="🧊Python SDK" %}

```python
# Update Model

import LatticaManagement

# Authenticate
lattica = LatticaManagement("your_license_from_lattica_console")

# Register a new model...
model_id = lattica.create_model("model_name")

# update model status and other properties
lattica.update_model(model_id,
	description="Best model ever",
	status="INACTIVE", 
	input_type="PICTURE",
	output_type="TEXT",
	model_visibility="PUBLIC"
  )
  
```

{% endtab %}
{% endtabs %}


# Access Control

This how-to documentation group focuses on managing user access tokens, which provide secure permissions for interacting with specific workloads. It includes token creation, assignment and modification.

<mark style="color:blue;">﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌</mark>

* How-To: [Create User Access Token](/how-to-guides/access-control/how-to-create-user-access-token)
* How-To: [Assign a Token to Model](/how-to-guides/access-control/how-to-assign-token-to-workload)
* How-To: [Remove Token’s Assignment](/how-to-guides/access-control/how-to-remove-tokens-assignment)
* How-To: [Update Token Attributes or Status](/how-to-guides/access-control/how-to-modify-user-access-token-setting)
* How-To: [View Tokens Details](/how-to-guides/access-control/how-to-see-list-of-tokens)


# How-To: Create User Access Token

This guide explains how to create a User Access Token using two methods: the Web Console and the Python  SDK.

* **Workload-Specific**: Tokens created are specific to one user and one workload. Unassigned tokens can be linked to a workload later.
* **Expiration**: Tokens are valid for 30 days and must be renewed upon expiration.
* **Token Management**: After creation, tokens can be updated, or reassigned, or their status (active/cancelled) can be changed as needed.

{% tabs %}
{% tab title="🌐 Console - For a Specific Model" %}
Follow these steps to create a token for a specific model through the LatticaAI web console:

<figure><img src="/files/5EtHvRswNCVcA1V4AELM" alt=""><figcaption><p>Create Token Flow</p></figcaption></figure>

{% stepper %}
{% step %}

### Navigate to Workload's Token Management

Go to the **Token Management** section of the specific Workload on the dashboard.
{% endstep %}

{% step %}

### Create a New Token

* Click **Create Token**.
* Enter a **name** for the token for easy identification.
* Specify the **Workload** to which the token will be linked.

  <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p><em>Optional</em>: Leave the workload field empty if you want to create an unassigned token.</p></div>

{% endstep %}

{% step %}

### Generate

Click **Generate** to generate the token.\
The new token will appear in the list, where you can manage its attributes, status, or assignment.
{% endstep %}

{% step %}

### Copy the Token Value

After the token is generated, the system displays the token value. Copy this token value for future use.&#x20;

{% hint style="warning" %}
The token is not stored in the system and cannot be retrieved later.
{% endhint %}
{% endstep %}

{% step %}

### Review and Confirm

* Verify all token details.
* Click **Done** to save the token.
  {% endstep %}

{% step %}

### Delete if Incorrect

If the token details were entered incorrectly, click **Delete** to remove the token and start the process again.
{% endstep %}
{% endstepper %}
{% endtab %}

{% tab title="🌐 Console - From the Tokens List Page" %}
You can create tokens directly from the **Tokens List** page. This process is useful for creating unassigned tokens or managing tokens centrally.

<figure><img src="/files/olOmE4iRVXmhI4qy3DaR" alt=""><figcaption></figcaption></figure>

1. **Navigate to the Tokens Page**\
   Log in to the web console and go to the **Tokens** section.
2. **Click "Add Token"**
   * Click the **Add Token** button to open the token creation window.
   * Fill in the token details
     * &#x20;Note: The end user cannot use unassigned tokens until they are linked to a model.
3. **Generate the Token**\
   Click **Generate Token** to create the token.
4. **Copy the Token Value**
   * After the token is generated, the system displays the token value.
   * **Important**: Copy this token value for future use. The token is not stored in the system and cannot be retrieved later.
5. **Review and Confirm**
   * Verify all token details.
   * Click **Done** to save the token.
6. **Delete if Incorrect**
   * If the token details were entered incorrectly, click **Delete** to remove the token and start the process again.
     {% endtab %}

{% tab title="🧊 Python SDK" %}
{% hint style="info" %}
Keep the generated token in a secure place!
{% endhint %}

```python
# Generate Token

import LatticaManagement

# Authenticate
lattica = LatticaManagement("your_license_from_lattica_console")

# Register a new model...
model_id = lattica.create_model("model_name")

# Generate a token
token_id, token = lattica.generate_query_token(model_id, "token_name")

```

{% endtab %}
{% endtabs %}


# How-To: Modify User Access Token Setting

After creating a User Access Token, you can update its parameters to reflect new requirements. This includes modifying its **name**, **note**, **expiration date**, **status**, and **model assignment**.

**Note**: Workload assignment is only possible for tokens that are not currently assigned to any model. To reassign a token, you must first remove the existing assignment, making the token unassigned, and then assign it to the desired model.

This guide provides instructions for making these changes using the **web console** and the **Python SDK**.

***

### Parameters that may be modified

| Field          | Description                                                               | Is this information accessible to end-users or it is restricted to system providers only | Allowed Values                    |
| -------------- | ------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | --------------------------------- |
| name           | New name for the token.                                                   | End-user can see the info                                                                | Any non-empty string              |
| note           | Updated note for additional context.                                      | The info is restricted to AI providers                                                   | Any string, or none at all        |
| expriationDate | Set a new expiration date within the allowed range.                       | End-user can see the info                                                                | Valid Unix timestamp (BigInt)     |
| status         | Update the token's status (`active` or `cancelled`).                      | End-user can see the info                                                                | `ACTIVE`, `CANCELED`, `SUSPENDED` |
| modelId        | Assign the token to a model. This is only possible for unassigned tokens. | Users can view the name associated with a model by providing its model ID                | Valid `modelId` string or `None`  |

***

{% tabs %}
{% tab title="🌐Console" %}
Follow these steps to modify token parameters through the web console:

<figure><img src="/files/Xmf0ltrF8RjEdYVF4owX" alt=""><figcaption></figcaption></figure>

1. **Navigate to the Tokens Page**\
   Log in to the web console and go to the **Tokens** section. Use the filters or sorting options to locate the token you want to modify.
2. **Access the Edit Options**
   * Click the **three dots** button next to the token you want to modify.
   * Select the **Edit** option from the dropdown menu.
3. **Modify the Parameters**\
   In the edit window, you can update the following:
   * **Name**: Update the descriptive name of the token.
   * **Note**: Add or change the note for the token.
   * **Expiration Date**: Adjust the token's expiration date within the allowed limits.
   * **Status**: Activate or cancel the token.
   * **Model Assignment**: If the token is unassigned, you can assign it to a model.
4. **Delete the Token** \
   If the token is no longer needed, select the **Delete** option from the dropdown menu to remove it.
5. **Save Changes**\
   Click **Update Token** to save your changes. The token’s updated details will appear in the token list.
   {% endtab %}

{% tab title="🧊Python SDK" %}
Use the following code snippet to modify token parameters programmatically:

```python
# Update Token
import LatticaManagement

# Authenticate
lattica = LatticaManagement("your_license_from_lattica_console")

# Get a token_id...
token_id = lattica.list_tokens()[0].token_id

# Update the token's attributes
lattica.update_token(token_id, status="CANCELED")

# Alternative 1:
# Cancel token
lattica.cancel_token(token_id)
```

{% endtab %}
{% endtabs %}


# How-To: Remove Token's Assignment

This guide explains how to remove a token’s assignment using both the **web console** and the **Python SDK**.

{% hint style="info" %}
While unassigned, the token cannot be used by the end-user until it is linked to a new workload.
{% endhint %}

***

{% tabs %}
{% tab title="🌐Console" %}
Follow these steps to remove a token’s assignment through the web console:

<figure><img src="/files/HgczFsXnX8HUQuepguGN" alt=""><figcaption><p>Remove Token's Assignment</p></figcaption></figure>

1. ### Navigate to Workload's Token Management

   Go to the **Token Management** section of the specific Workload on the dashboard.
2. ### Access the Token Tab

   In the model’s details page, navigate to the **Token** tab to view all tokens associated with the model.
3. ### **Find the Required Token and Remove the Assignment**
   * Click the **"x"** next to the token's assignment field.
   * Confirm the action by clicking the **Remove** button.

The token will now be unassigned and available for reassignment to another workload.
{% endtab %}

{% tab title="🧊 Python SDK" %}
You can also remove a token's assignment using the SDK. The following code demonstrates how to unassign a token:

```python
# Unassign Token from Model

import LatticaManagement

# Authenticate
lattica = LatticaManagement("your_license_from_lattica_console")

# Get a model_id and a token_id...
model_id = lattica.list_models()[0].model_id
token_id = lattica.list_tokens(model_id=model_id)[0].token_id

# Unassign token from model
lattica.unassign_token_from_model(token_id, model_id)
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}

### Reassigning the Token

After removing the token’s assignment, you can reassign it to a different workload using the **token modification functionality**. For detailed steps on assigning a token to a Workload, see: \[How-To: [Assign Token to Workload](/how-to-guides/access-control/how-to-assign-token-to-workload)].
{% endhint %}


# How-To: Assign Token to Workload

A **User Access Token** provides access permission for a specific user to a specific workload. Tokens can be assigned to a workload either during their [creation ](/how-to-guides/access-control/how-to-create-user-access-token)or later if the token is unassigned. This guide explains how to assign a token to a model using the **web console**, focusing on assignment from the **Workload's Details Management Screen**

## Via Token's Attributes Modification (Web Console or Python SDK)

Tokens can be assigned to models by modifying their attributes. This method allows you to assign tokens from the **Tokens Page** in the web console or through the Python SDK.\
For detailed instructions, see: \[How-To: [Modify Token's Parameters](/how-to-guides/access-control/how-to-modify-user-access-token-setting)].

## Via the Workload's Details Management Screen

{% tabs %}
{% tab title="🌐Console " %}
Follow these steps to assign a token directly from the model's details screen:

<figure><img src="/files/L95QrT2Zhp8PH82HgeI2" alt=""><figcaption><p>Assign Token to a Model</p></figcaption></figure>

{% stepper %}
{% step %}

### **Navigate to Workload's Details Management**

Go to the Models section. Find and click the model you want. Then click the button showing the model's token information.
{% endstep %}

{% step %}

### **Access the Token Tab**

In the model's details screen, navigate to the **Token** tab.
{% endstep %}

{% step %}

### **Start Typing the Token's Name**

Begin typing the name of the unassigned token you want to assign.
{% endstep %}

{% step %}

### **Select the Required Token**

A dropdown list will appear showing unassigned tokens that match the substring you typed.

* Choose the desired token from the list.
* If the required token does not exist, you can create a new one using the "Add Token" option.

{% hint style="warning" %}
**Unassigned Tokens Only**: Only unassigned tokens can be linked to a model. If a token is currently assigned, remove the existing assignment first (see: \[How-To: [Remove Token's Assignment](/how-to-guides/access-control/how-to-remove-tokens-assignment)]).
{% endhint %}
{% endstep %}

{% step %}

### **Save the Assignment**

Click the **Save** button to confirm the token assignment. The token will now be linked to the model.
{% endstep %}
{% endstepper %}
{% endtab %}

{% tab title="🧊 Python SDK" %}

```python
# Assign Token to Model

import LatticaManagement

# Authenticate
lattica = LatticaManagement("your_license_from_lattica_console")

# Get a model_id and a token_id...
model_id = lattica.list_models()[0].model_id
token_id = lattica.list_tokens()[0].token_id

# Assign token to model
lattica.assign_token_to_model(token_id, model_id)
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
When a token is reassigned from one model to another, a **new Evaluation Key (EVK)** must be generated for the new model. For instructions, refer to: \[[How-To: Generate Evaluation Key](/how-to-guides/secure-query-processing/how-to-upload-evaluation-key)].
{% endhint %}


# How-To: See List of Tokens

The **Tokens** page in the web console provides a comprehensive view of all User Access Tokens created under your account. This page allows you to monitor token details, find specific tokens using filters or sorting options, and manage your tokens efficiently.

***

### Understanding the Tokens Parameters

* **Token Name**: The descriptive name of the token.
* **Creation Date**: The date and time when the token was created.
* **Expiration Date**: The token's expiration date
* **Status**: Indicates whether the token is **active or** **canceled**
* **Model Assignment**: Specifies the AI model the token is assigned to. If unassigned, this field is blank.
* **Evaluation Key**: Indicates whether an **Evaluation Key (EVK)** has been generated for the token and assigned model. EVKs are required for encrypted queries.

***

### Parameters that may be modified

| Field     | Type | Required | Description                                                               | Allowed Values                    |
| --------- | ---- | -------- | ------------------------------------------------------------------------- | --------------------------------- |
| status    | str  | No       | Filter tokens by their current status.                                    | `ACTIVE`, `CANCELED`, `SUSPENDED` |
| modelId   | str  | No       | Filter tokens associated with a specific model ID.                        | Valid `modelId` UUID string       |
| issueDate | int  | No       | Filter tokens issued on a specific date (Unix timestamp in milliseconds). | Valid Unix timestamp (BigInt)     |

***

{% tabs %}
{% tab title="🌐Console" %}
The **Tokens** page displays a table with detailed information about each token.&#x20;

<figure><img src="/files/4anR9ei6iAELt6LoxdSB" alt=""><figcaption><p>Token List</p></figcaption></figure>

### Accessing the Tokens Page

1. **Log In**\
   Log in to the LatticaAI web console using your credentials.
2. **Navigate to the Tokens Page**\
   From the main menu, select **Tokens** to access the list of all tokens associated with your account.

The **Tokens** page offers tools to filter and sort the token(s) you need
{% endtab %}

{% tab title="🧊 Python SDK" %}
The LatticaAI SDK provides an API call to retrieve the list of tokens associated with your account. This allows customers to implement custom filtering and sorting logic in their own systems.

Use the following code snippet to fetch the tokens list:

```python
# List Tokens

import LatticaManagement

# Authenticate
lattica = LatticaManagement("your_license_from_lattica_console")

# Choose a model
model_id = lattica.list_models()[0].model_id

# List Tokens
tokens = lattica.list_tokens(status="ACTIVE", model_id=model_id)
```

{% endtab %}
{% endtabs %}


# Resource Management

Functionalities in this how-to documentation group are dedicated to managing workers that process model queries. It includes starting, stopping, and monitoring workers, as well as managing resource allocation to optimize performance.

<mark style="color:blue;">﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌</mark>

* How-To: [Start Worker](/how-to-guides/resource-management/how-to-start-worker)
* How-To: [Stop Worker](/how-to-guides/resource-management/how-to-stop-worker)
* How-To: [Monitor Worker Performance](/how-to-guides/resource-management/how-to-monitor-worker-performance)


# How-To: Start Worker

Starting a worker allows the associated workload to process end-user queries. This guide explains how to start a worker for a specific workload.

***

{% hint style="info" %}

* **Credit Balance**: Check that you have enough credits in your account to run the worker.
* **Worker Scaling**: You can run as many workers as needed for each model. If queries are slow due to high demand, start more workers to improve performance.
  {% endhint %}

***

{% tabs %}
{% tab title="🌐Console" %}
Log in to the web console to access the **Main Page**, where modules for each of your models are displayed and identify the module corresponding to the model for which you want to start a worker.

<figure><img src="/files/oljEHmcOkUdBSEVqC1Xm" alt=""><figcaption><p>Start Worker</p></figcaption></figure>

{% stepper %}
{% step %}

### S**tart a New Worker**

* In the model’s module, click the **"Add Worker"** button.
* This action will start a new worker dedicated to processing queries for the selected model.
  {% endstep %}

{% step %}

### V**iew Running Workers**

* Expand the **Worker Section** within the model’s module to view all currently running workers.
* The section lists each worker along with its **start time**, allowing you to monitor activity.
  {% endstep %}
  {% endstepper %}
  {% endtab %}

{% tab title="🧊Python SDK" %}

```python
# Start Worker

import LatticaManagement

# Authenticate
lattica = LatticaManagement("your_license_from_lattica_console")

# get list of models
models = lattica.get_models()

# Start a new worker session. Returns an Active worker session id.
worker_session_id = lattica.start_worker(models[0].model_id) 
```

{% endtab %}
{% endtabs %}

***


# How-To: Stop Worker

Stopping a worker allows you to manage resource usage and control credit consumption for your account. This guide explains how to stop a worker for a specific model.

{% tabs %}
{% tab title="🌐Console" %}
Log in to the web console to access the **Main Page**, where modules for each of your models are displayed and identify the module corresponding to the model for which you want to stop a worker.

<figure><img src="/files/6Tx6jgrL8O8exWmLnymC" alt=""><figcaption><p>Stop Worker</p></figcaption></figure>

{% stepper %}
{% step %}

### E**xpand the Worker Section**

* Click the expander in the model’s module to open the **Worker Section**.
* This section lists all currently running workers for the model, along with their **start times**.
  {% endstep %}

{% step %}

### S**top the Worker**

* Find the worker you wish to stop in the list.
* Click the **"x" (remove)** button next to the worker's details to stop it.
  {% endstep %}
  {% endstepper %}

After the worker is stopped, it will no longer appear in the list of active workers for the model.
{% endtab %}

{% tab title="🧊Python SDK" %}

```python
# Stop Worker

import LatticaManagement

# Authenticate
lattica = LatticaManagement("your_license_from_lattica_console")

# get model and worker_session
models = lattica.get_models()[0].model_id
worker_session_id = lattica.list_worker_sessions(model_id=model_id)[0].worker_session_id

# Start a new worker session. Returns an Active worker session id.
lattica.stop_worker(worker_session_id)
```

{% endtab %}
{% endtabs %}


# How-To: Monitor Worker Performance

Monitoring worker performance helps ensure optimal query processing and identifies when additional workers may be needed to maintain performance. This guide explains how to monitor worker performance for a specific model using the web console.

{% tabs %}
{% tab title="🌐Console" %}
Log in to the web console to access the **Main Page**, where modules for each of your models are displayed, and identify the module corresponding to the model for which you want to monitor a worker's performance.

<figure><img src="/files/xQfbNcCopxbzwKMaDNlN" alt=""><figcaption><p>Worker Performance</p></figcaption></figure>

The model's performance metrics are displayed below its name:

1. **Current Load**: Shows the average query processing time in the last 5 minutes.
2. **Average Load**: Indicates the model's average query processing time over the past month.
3. **Active Workers**: Lists the number of workers currently running for the model.
   {% endtab %}

{% tab title="🧊 Python SDK" %}

```python
import lattica_common.auth_local_state as auth
import lattica_common.app_api as agent_app

# Notice your account token expires every 30 days and it's up to you to renew it
auth.set_session_token("your_account_token_you_got_in_your_email")

# Retrieve all active workers for a specific model
active_workers = agent_app.worker.get_active_workers("model_id")

# Iterate through each active worker and get detailed worker information
for active_worker in active_workers:
    # Retrieve worker information using the workerSessionId
    worker_session_id = active_worker.workerSessionId

    # In case of failur this function throws
    worker_info = agent_app.worker.get_worker_info(worker_session_id)
    
    # Print or process the worker information as needed
    print(f"Worker Session ID: {worker_session_id}")
    print(f"Worker Info: {worker_info}\n")

```

{% endtab %}
{% endtabs %}

***

### **Compare Current Load and Average Load**

If the **Current Load** is significantly higher than the **Average Load**, it indicates increased query traffic or reduced performance. In this case, consider starting additional workers to distribute the load.

***


# Secure Query Processing

This how-to documentation group covers every step required for secure query processing: **encrypting input data**, **submitting queries** to models, **receiving encrypted results**, and **decrypting** the output. For deeper insight into the underlying FHE logic - such as key generation and encryption/decryption - visit our [GitHub repository](https://github.com/Lattica-ai/lattica_fhe_core).

<mark style="color:blue;">﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌</mark>

* How-To: [Generate Evaluation Key ](/how-to-guides/secure-query-processing/how-to-upload-evaluation-key)
* How-To: [Encrypt Input Message](/how-to-guides/secure-query-processing/how-to-encrypt-input-message)
* How-To: [Run Query](/how-to-guides/secure-query-processing/how-to-execute-query)
* How-To: [Decrypt Output Data](/how-to-guides/secure-query-processing/how-to-decrypt-output-data)


# How To: Upload Evaluation Key

The Evaluation Key (EVK) enables efficient low-latency interactions with a specific Workload. To upload this key, you’ll need a User Access Token provided by the customer for the specific workload.

This process consists of two parts: generating a key pair (secret and evaluation keys) and publishing the EVK to Lattica’s backend.&#x20;

## Overview of the Process

{% stepper %}
{% step %}

### G**enerate Key Pair**:

* A **Secret Key** is generated and remains securely in the Query Client. Only the end-user has access to this key, which is later used for encrypting and decrypting messages.
* An **Evaluation Key (EVK)** is also generated. This key is used during query processing for validation and secure computations.
  {% endstep %}

{% step %}

### P**ublish Evaluation Key**:

The generated EVK is uploaded to Lattica’s backend. This ensures the backend is configured for processing encrypted queries for the specified workload.
{% endstep %}
{% endstepper %}

{% hint style="info" %}
The Evaluation Key is generated only once per setup and can be used for ongoing encrypted interactions.
{% endhint %}

Use the following code snippet to upload an Evaluation Key.&#x20;

Ensure you have the **User Access Token** ready, as this token specifies the workload for which the secret and evaluation keys will be generated.

{% tabs %}
{% tab title="🧊 Python SDK" %}

```python
import lattica_common.app_api as agent_app
​
# Notice your query token expires in 30 days
query_token = "the_query_token_you_got_using_the_generate_user_token"

# user_data is a tuple of: 
# (serialized_context, serialized_secret_key, serialized_homseq)
# which you need for encrypting the query and querying the model
user_data = agent_app.user.query_offline_phase(query_token)

```

{% endtab %}

{% tab title="📦 TypeScript SDK" %}

```typescript
import { LatticaQueryClient } from 'lattica-query-client';

const client = new LatticaQueryClient('your-jwt-query-token');

// Uploaded the EK
const initialized = await client.init();
if (!initialized) {
  console.error('Initialization failed: The EK was not successfully uploaded.');
  throw new Error('EK upload failed.');
}
console.log('EK uploaded successfully.');
```

{% endtab %}
{% endtabs %}

### Parameters

* **JWT Access Token**: A unique identifier created by the AI Provider.&#x20;


# How-To: Encrypt Input Message

### Prerequisites

1. **Encryption Keys**:

   * A **Secret Key** must be defined in the Query Client to encrypt and decrypt messages.
   * The corresponding **Evaluation Key** must be deployed in LatticaAI.

   <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p>If the key pair is already defined, you do not need to create it again.</p></div>
2. **User Access Token**:
   * The user must have a valid **Access Token**, which provides permission to interact with the workload.
   * Tokens are unique to each user and workload.

***

Use the following code snippet to encrypt the input message. The encryption process takes the **User Access Token** and the **message to be encrypted** as parameters:

{% tabs %}
{% tab title="🧊 Python SDK" %}

```python
import lattica_common.app_api as agent_app
​
# Notice your query token expires in 30 days
query_token = "the_query_token_you_got_using_the_generate_user_token"

# user_data is a tuple of: 
# (serialized_context, serialized_secret_key, serialized_homseq)
# which you need for encrypting the query and querying the model
user_data = agent_app.user.query_offline_phase(query_token)

dataset = pd.read_csv('data/mnist_data.csv').values / 255
data = torch.tensor(dataset[0])
serialized_ct = agent_app.user.encrypt(user_data, dataset)
```

{% endtab %}

{% tab title="📦TypeScript SDK" %}

```javascript
import { LatticaQueryClient } from 'lattica-query-client';

const client = new LatticaQueryClient('your-jwt-query-token');

// Uploaded the EK
const initialized = await client.init();
if (!initialized) {
  console.error('Initialization failed: The EK was not successfully uploaded.');
  throw new Error('EK upload failed.');
}
console.log('EK uploaded successfully.');

// The data you want to encrypt
const inputTensor = ....;

// Encrypt the provided input
const ct = await client.encrypt(pt);
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
This step focuses on a specific part of the query process: Input message encryption. \
If you prefer to perform **encryption, query execution, and decryption** in a single command, refer to \[How-To: [Encrypt, Execute, and Decrypt in One Step](/how-to-guides/secure-query-processing/how-to-encrypt-execute-and-decrypt-in-one-step)].
{% endhint %}


# How To: Execute Query

Executing a query allows an end-user to interact securely with an workload on the LatticaAI platform. This guide explains how to submit an encrypted query using the Query Client.

### Prerequisites

1. **Encrypted Message**:\
   The input [message must be encrypted ](/how-to-guides/secure-query-processing/how-to-encrypt-input-message)using the **Secret Key** in the Query Client.
2. **User Access Token**:\
   The user must have a valid **Access Token**, specific to the workload being queried. Tokens are validated by LatticaAI during the query process.

***

Use the following code snippet to execute the query. Provide the **User Access Token** and the **encrypted message** as parameters:

{% tabs %}
{% tab title="🧊Python SDK" %}

```python
import lattica_common.app_api as agent_app
​
# Notice your query token expires in 30 days
query_token = "the_query_token_you_got_using_the_generate_user_token"

# user_data is a tuple of: 
# (serialized_context, serialized_secret_key, serialized_homseq)
# which you need for encrypting the query and querying the model
user_data = agent_app.user.query_offline_phase(query_token)

dataset = pd.read_csv('data/mnist_data.csv').values / 255
data = torch.tensor(dataset[0])
serialized_ct = agent_app.user.encrypt(user_data, dataset)

serialized_ct_res = agent_app.user.apply_hom_pipeline(serialized_ct)
```

{% endtab %}

{% tab title="📦TypeScript SDK" %}

```javascript
import { LatticaQueryClient } from 'lattica-query-client';

const client = new LatticaQueryClient('your-jwt-query-token');

// Uploaded the EK
const initialized = await client.init();
if (!initialized) {
  console.error('Initialization failed: The EK was not successfully uploaded.');
  throw new Error('EK upload failed.');
}
console.log('EK uploaded successfully.');

// The data you want to encrypt
const inputTensor = ....;

// Encrypt the provided input
const ct = await client.encrypt(pt);

// Send your encrypted query to and get a resopnse
const ct_res = await latticaClient.apply_query(ct);
```

{% endtab %}
{% endtabs %}

**Process the Response**

* If the query is successful, the result will be returned as an **encrypted response**.
* [Decrypt ](/how-to-guides/secure-query-processing/how-to-decrypt-output-data)the response using your **Secret Key** to obtain the result.

{% hint style="info" %}
This step focuses on a specific part of the query process: Query Execution. \
If you prefer to perform **encryption, query execution, and decryption** in a single command, refer to \[How-To: [Encrypt, Execute, and Decrypt in One Step](/how-to-guides/secure-query-processing/how-to-encrypt-execute-and-decrypt-in-one-step)].
{% endhint %}


# How-To: Decrypt Output Data

After receiving the encrypted output from a query request, the end-user must decrypt the message using their Secret Key. This guide explains how to perform the decryption process.

***

### Prerequisites

1. **Encrypted Output**:\
   The output must be retrieved from a successful query execution.
2. **Secret Key**:\
   The user’s **Secret Key** is required to decrypt the message.

Use the following code snippet to decrypt the output data. \
Provide the **User Access Token** and the **encrypted output message** as parameters:

{% tabs %}
{% tab title="🧊Python SDK" %}

```python
import lattica_common.app_api as agent_app
​
# Notice your query token expires in 30 days
query_token = "the_query_token_you_got_using_the_generate_user_token"

# user_data is a tuple of: 
# (serialized_context, serialized_secret_key, serialized_homseq)
# which you need for encrypting the query and querying the model
user_data = agent_app.user.query_offline_phase(query_token)

dataset = pd.read_csv('data/mnist_data.csv').values / 255
data = torch.tensor(dataset[0])
serialized_ct = agent_app.user.encrypt(user_data, dataset)

serialized_ct_res = agent_app.user.apply_hom_pipeline(serialized_ct)

serialized_pt = agent_app.user.decrypt(serialized_ct_res)
```

{% endtab %}

{% tab title="📦TypeScript SDK" %}

```javascript
import { LatticaQueryClient } from 'lattica-query-client';

const client = new LatticaQueryClient('your-jwt-query-token');

// Uploaded the EK
const initialized = await client.init();
if (!initialized) {
  console.error('Initialization failed: The EK was not successfully uploaded.');
  throw new Error('EK upload failed.');
}
console.log('EK uploaded successfully.');

// The data you want to encrypt
const inputTensor = ....;

// Encrypt the provided input
const ct = await client.encrypt(pt);

// Send your encrypted query to and get a resopnse
const ct_res = await latticaClient.apply_query(ct);

// Decrypt your query result
const pt_res = await latticaClient.decrypt(ct_res);
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
This step focuses on a specific part of the query process: Output message decryption. \
If you prefer to perform **encryption, query execution, and decryption** in a single command, refer to \[How-To: [Encrypt, Execute, and Decrypt in One Step](/how-to-guides/secure-query-processing/how-to-encrypt-execute-and-decrypt-in-one-step)].
{% endhint %}


# How-To: Encrypt, Execute, and Decrypt in One Step

LatticaAI provides a streamlined way to perform **end-to-end query execution** in a single command using our SDK. Instead of calling separate functions for encryption, query submission, and decryption, this method allows users to provide an input and receive the decrypted output in one step.

This functionality is available in both **Python** and **TypeScript SDKs**.

***

### **Prerequisites**

Before executing a complete query, ensure that:

1. **A valid User Access Token is available**, provided by the Provider for a specific workload.
2. **An Evaluation Key (EVK) is generated and published** to the LatticaAI backend.
   * See: \[How-To: [Upload Evaluation Key](/how-to-guides/secure-query-processing/how-to-upload-evaluation-key)]

***

### **Executing a Query in One Command**

Use the following code snippet to encrypt the input message. The encryption process takes the **User Access Token** and the **message to be encrypted** as parameters:

{% tabs %}
{% tab title="🧊Python SDK" %}

```python
import torch
import matplotlib.pyplot as plt
from lattica_query.lattica_query_client import QueryClient

# Authenticate
client = QueryClient("user_token_from_lattica_console")

# Generate keys and upload the evaluation key to the server.
(
    context,
    secret_key,
    client_blocks,
) = client.generate_key()


# Run multiple encrypted queries
image1 = plt.imread('image1.png')
pt1 = torch.Tensor(image1)
result1 = client.run_query(context, secret_key, pt1, client_blocks)

image2 = plt.imread('image2.png')
pt2 = torch.Tensor(image2)
result2 = client.run_query(context, secret_key, pt2, client_blocks)

```

{% endtab %}

{% tab title="📦TypeScript SDK" %}

```typescript
import { LatticaQueryClient, imageToTensor } from '@Lattica-ai/lattica-query-client';

// Authenticate
const client = new LatticaQueryClient("user_token_from_lattica_console");

// Generate keys and upload the evaluation key to the server.
await client.init();

// Run multiple encrypted queries
const pt1 = await imageToTensor(imageDataUrl1);
const res1 = await client.runQuery(pt1);

const pt2 = await imageToTensor(imageDataUrl2);
const res2 = await client.runQuery(pt2);
```

{% endtab %}
{% endtabs %}


# Account and Finance Operations

This how-to documentation group handles all account-related activities, including account creation, updating contact details, viewing account information, and managing finance.

<mark style="color:blue;">﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌</mark>

* How-To: [Update Account Information](/how-to-guides/account-and-finance-operations/how-to-update-account-information-and-generate-license)
* How-To: [View Credit Balance and Add Credit to Your Account](/how-to-guides/account-and-finance-operations/how-to-view-credit-balance-and-add-credit-to-your-account)
* How-To: [Monitor Balance and Usage](/how-to-guides/account-and-finance-operations/how-to-monitor-balance-and-usage)
* How-To: [View Transaction History](/how-to-guides/account-and-finance-operations/how-to-view-payment-transaction-history)


# How-To: View Payment Transaction History

The **Transaction History** feature in the web console allows you to track all financial transactions associated with your account. This includes payment details, credits received, and a summary of your financial activity over time. You can also view your current credit balance and add credits directly from this page.

***

### Steps to View Transaction History

{% tabs %}
{% tab title="🌐Console" %}

<figure><img src="/files/4IZb6lQgiRNb8iyg5G6P" alt=""><figcaption><p>Finance Data</p></figcaption></figure>

{% stepper %}
{% step %}

### N**avigate to the Finance Page**

* Log in to the web console using your credentials.
* Go to the **Finance** page, where you will see the **Finance Dashboard**.
  {% endstep %}

{% step %}

### V**iew Payment Transactions**

* The dashboard displays a detailed list of all payment transactions.
* For each transaction, you can see:
  * **Billing Amount**: The payment amount.
  * **Charge Date**: The date of the transaction.
  * **Credits Amount**: The number of credits added to your account.
    {% endstep %}

{% step %}

### **Explore the Summary Chart**

* The dashboard also includes a **summary chart** of monthly payments over the past year.
* Use the summary chart to understand your payment patterns and plan for future credit needs.
* **Future Feature**: This chart will also show a monthly breakdown of credit usage in upcoming releases.
  {% endstep %}

{% step %}

### C**heck Your Current Credit Balance**

* The page prominently displays your account's current credit balance.
* This lets you quickly see whether additional credits are needed to maintain operations.
  {% endstep %}

{% step %}

### M**ake a New Payment**

* Use the **Add Credits** option on the dashboard to purchase additional credits.
* Payments are processed instantly, and credits are added to your account immediately.
  {% endstep %}
  {% endstepper %}
  {% endtab %}

{% tab title="🧊 Python SDK" %}

```python
import lattica_common.auth_local_state as auth
import lattica_common.app_api as agent_app

# Notice your account token expires every 30 days and it's up to you to renew it
auth.set_session_token("your_account_token_you_got_in_your_email")

transactions = agent_app.account.get_transactions_history()

```

{% endtab %}
{% endtabs %}

***


# How-To: Update Account Information and Generate License

Log in to the LatticaAI web console to update account information using your credentials. Once logged in, follow the steps below.

***

## Steps to Update Account Information

<figure><img src="/files/ndYPbCEhDAe5tFUTCwlI" alt=""><figcaption></figcaption></figure>

{% stepper %}
{% step %}
Use the **sidebar menu** to go to the **Account Details** section.
{% endstep %}

{% step %}
V**iew Your Account ID**

{% hint style="info" %}
The account ID field is **view-only** and cannot be edited.
{% endhint %}
{% endstep %}

{% step %}
E**dit Contact Information**

Click Edit to start editing

Click Save to save your changes&#x20;
{% endstep %}

{% step %}
**Generate new License**
{% endstep %}
{% endstepper %}

***

{% tabs %}
{% tab title="🧊 Python SDK" %}

```python
import lattica_common.auth_local_state as auth
import lattica_common.app_api as agent_app

# Notice your account token expires every 30 days and it's up to you to renew it
auth.set_session_token("your_account_token_you_got_in_your_email")

params = {
    "companyName": "Tech Innovators Inc.",    # Optional: New company name
    "contactName": "Jane Doe",                # Optional: New contact person name
    "email": "jane.doe@techinnovators.com",   # Optional: Updated unique email address
    "phoneNumber": "+1-555-123-4567",         # Optional: Updated contact phone number
}

transactions = agent_app.account.update_account_info(params)

```

{% endtab %}
{% endtabs %}


# How-To: View Credit Balance and Add Credit to Your Account

This guide explains how to view your credit balance and add credits to your account using the web console.

***

### Accessing the Credit Balance

You can access your credit balance from two locations in the web console:

1. **Main Page of the Console**
   * Log in to the web console, and your credit balance will be prominently displayed on the main page.
2. **Finance Dashboard**
   * Navigate to the **Finance Page** and access the **Finance Dashboard** for a detailed view of your financial activity.

***

{% tabs %}
{% tab title="🌐Console" %}
On either page, you’ll find the following credit-related information:

<figure><img src="/files/yAwg11SGReqU2TPoNLcl" alt=""><figcaption><p>Balance</p></figcaption></figure>

{% stepper %}
{% step %}

### R**emaining Credit Balance**

* Displays the current amount of credits available in your account.
* These credits are used to pay for **worker runtime**.
  {% endstep %}

{% step %}

### E**stimated Usage Time**

* Provides an approximate estimate of how long the remaining credits will allow your workers to operate.
* **Note**: This calculation depends on the type of workers you are running and their usage rate, so it is an approximation.
  {% endstep %}

{% step %}

### L**ast Payment Date**

Shows the date of your most recent payment, helping you track when credits were last added.
{% endstep %}

{% step %}

### Adding Credits

* Click the "Add Credit" Button
* Follow the prompts to enter your payment information
* Confirm your payment to complete the transaction.
  {% endstep %}
  {% endstepper %}

{% endtab %}

{% tab title="🧊 Python SDK" %}

```python
import lattica_common.auth_local_state as auth
import lattica_common.app_api as agent_app

# Notice your account token expires every 30 days and it's up to you to renew it
auth.set_session_token("your_account_token_you_got_in_your_email")

credits = agent_app.account.get_credits_balance()

if credits < 100:
    try:
        # Add credits to the account
        agent_app.account.add_credits(200)
        print(f"Added {CREDITS_TO_ADD} credits to your account successfully.")
    except Exception as e:
        # Handle any errors that occur during the credit addition
        print(f"Failed to add credits: {e}")
else:
    print("Sufficient credits available. No need to add more credits.")

```

{% endtab %}
{% endtabs %}


# How-To: Monitor Balance and Usage

***

### Accessing the Balance and Usage Dashboard

Log in to the web console to access the **Main Page**, which provides an overview of your account’s balance and usage.

***

### Monitoring Credit Balance and Usage

{% tabs %}
{% tab title="🌐Console" %}
The dashboard displays the following key metrics:

<figure><img src="/files/rwKMYvivU6mbY8vWs1Cj" alt=""><figcaption></figcaption></figure>

{% stepper %}
{% step %}

### C**redit Balance**

* **Available Credits**: Shows the current amount of credits remaining in your account.
* **Approximate Remaining Usage Time**: Provides an estimate of how long workers can run on the remaining credits, calculated as the total runtime across all workers in your account.

{% hint style="info" %}

* The approximate time represents the total runtime for all workers. For example, if the remaining usage time is estimated at 4 days and you run 4 workers in parallel, your credits will last for 1 day of operation for all 4 workers.
* This calculation is approximate because the platform may support different types of workers in the future, each with varying usage rates. Currently, the estimate is based on the default worker type.
  {% endhint %}
  {% endstep %}

{% step %}

### W**orker Runtime Summary**

* **Total Worker Runtime**: Displays the total runtime of all workers associated with your account.
* **Per-Model Breakdown**: This shows runtime usage for each AI model, helping you identify which models consume the most resources.
  {% endstep %}

{% step %}

### E**nd-User Query Summary**

* **Total Queries**: This shows the total number of end-user queries processed across all models.
* **Per-Model Breakdown**: Displays query statistics for each AI model, helping you understand which models are queried most frequently.
  {% endstep %}
  {% endstepper %}

### Custom Periods for Worker Runtime and Queries

Both **Worker Runtime Summary** and **End-User Query Summary** can be viewed for the following periods:

* **Daily**: Statistics for the last 24 hours.
* **Monthly**: Statistics for the last calendar month.
* **Yearly**: Statistics for the last calendar year.
  {% endtab %}

{% tab title="🧊 Python SDK" %}

```python
from datetime import datetime

import lattica_common.auth_local_state as auth
import lattica_common.app_api as agent_app

# Function to convert a datetime object to Unix timestamp in milliseconds
def to_unix_millis(dt: datetime) -> int:
    return int(dt.timestamp() * 1000)
    

# Notice your account token expires every 30 days and it's up to you to renew it
auth.set_session_token("your_account_token_you_got_in_your_email")

credits = agent_app.account.get_credits_balance()

# Example Date Range 1: January 1, 2024 to January 31, 2024
start_date1 = to_unix_millis(datetime(2024, 1, 1))
end_date1 = to_unix_millis(datetime(2024, 1, 31, 23, 59, 59))

# In the given dates range, returns a list of worker sessions runtime per model
# of the account.
account_worker_sessions = agent_app.account.get_worker_sessions(start_date1, end_date1)

# Example Date Range 2: February 1, 2024 to February 28, 2024
start_date2 = to_unix_millis(datetime(2024, 2, 1))
end_date2 = to_unix_millis(datetime(2024, 2, 28, 23, 59, 59))

# In the given dates range, returns a list of queries done per model of the account
account_models_usage = agent_app.account.get_queries_per_model(start_date2, end_date2)

```

{% endtab %}
{% endtabs %}

***


# Demo Tutorials

### Explore Our Live Demos

Our demos let you run real AI models directly in your browser: <https://www.lattica.ai/workloads>

Each demo showcases a different use case powered by **homomorphic encryption**, allowing you to experience fully encrypted AI processing end-to-end.

#### What you’ll get:

✅ Fully encrypted query and response flow

✅ No need to install the Query Client

✅ No registration or token management - everything’s ready to go


# Image Sharpening with LatticaAI Demo Tutorial

<div data-full-width="true"><figure><img src="/files/99EXzD9OAPf80ta0JETA" alt=""><figcaption></figcaption></figure></div>

## Overview of the Model

Our **Image Sharpening** model enhances the clarity and detail of an input image by applying a specialized 2D filter through convolution.

* **Input Format**: RGB image tensor of shape `(3, 200, 200)`, with pixel values in the `[0,1]` range.
* **Output**: Sharpened image preserving original dimensions.

The equivalent pytorch code for the operator is:

{% code overflow="wrap" %}

```python
import torch
import torch.nn.functional as F
import matplotlib.pyplot as plt


# Load image as numpy ndarray (ignore alpha channel if it exists)
np_img = plt.imread('house.png')[..., :3]  # shape format (H, W, C)
assert np_img.shape[-1] == 3, "Image must have 3 channels"

# Keep values in range [0, 255]
if np_img.max() <= 1:
  np_img *= 255

# Convert to PyTorch tensor and arrange dimensions as (C, H, W)
pt = torch.tensor(np_img, dtype=torch.float).permute(2, 0, 1)
# Resize image to expected input size
pt = F.interpolate(pt.unsqueeze(0), size=(200, 200), mode='bilinear').squeeze(0)  # shape (3, 200, 200)

# Define sharpening kernel
sharpen_kernel = torch.tensor([[0, -1, 0], [-1, 5, -1], [0, -1, 0]], dtype=torch.float)

# Apply convolution for each channel separately (3 for RGB)
res = F.conv2d(pt, sharpen_kernel.expand(3, 1, 3, 3), groups=3, padding=1)
# Clamp to range [0, 255]
res = torch.clamp(res, 0, 255)

# Display the original and sharpened images
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.title("Original Image")
plt.imshow(pt.permute(1, 2, 0) / 255)
plt.axis("off")

plt.subplot(1, 2, 2)
plt.title("Sharpened Image")
plt.imshow(res.permute(1, 2, 0) / 255)
plt.axis("off")

plt.show()
```

{% endcode %}

## Achieving Full Privacy with LatticaAI

This demo is the only one that uses *RBGV* encryption scheme (the others are using *CKKS* scheme). The reason for this is that the plaintext tensor (image pixels) can be accurately represented in integer values, and the convolution kernel has integer values (as opposed to most machine learning models where either the input and/or the weights are floating point numbers).

In order to convert this simple code to use homomorphic operations, all you need are the following few extra steps:

1. Install Lattica python package and obtain a JWT token
2. Generate encryption keys
3. Replace the actual convolution with our function that will:
   1. &#x20;preprocess the image and encrypt it
   2. send the encrypted data to the cloud for computation
   3. receive and decrypt the encrypted result using your private key&#x20;

Everything else remains the same.

{% hint style="info" %}
First [install](/demo-tutorials/zooming-into-each-step-of-demo-run-with-latticaai-flow#installation-and-setup) our client package
{% endhint %}

{% tabs %}
{% tab title="🧊 Python SDK" %}

```python
from lattica_query.auth import get_demo_token
from lattica_query.lattica_query_client import QueryClient

model_id = "imageEnhancement"
my_token = get_demo_token(model_id)

client = QueryClient(my_token)

context, secret_key, client_blocks, = client.generate_key()

# `pt` and `res` are torch.Tensor, same as in the plain example above
res = client.run_query(context, secret_key, pt, client_blocks)

# Display the original and sharpened images...
```

{% endtab %}

{% tab title="📦 TypeScript SDK" %}

```typescript
import { getDemoToken, LatticaQueryClient } from '@Lattica-ai/lattica-query-client';

const modelId = "imageEnhancement"
const token = await getDemoToken(modelId);

const client = new LatticaQueryClient(myToken);

await client.init();

const result = await client.runQuery(pt);
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
See our [step-by-step guide](/demo-tutorials/zooming-into-each-step-of-demo-run-with-latticaai-flow) for a detailed explanation of each step in this flow. \
To use the image sharpening model use the  **imageEnhancement** model ID
{% endhint %}

***


# Sentiment Analysis with LatticaAI Demo Tutorial

<div data-full-width="true"><figure><img src="/files/zxOU6GxTBFocuFx1yIfx" alt=""><figcaption></figcaption></figure></div>

### Overview of the Model <a href="#overview-of-the-model" id="overview-of-the-model"></a>

Our **Sentiment Analysis** model is trained on the [Sentiment140 Kaggle dataset](https://www.kaggle.com/datasets/kazanova/sentiment140). This dataset is a collection of 1.6 million tweets that have been labeled with sentiment polarity- positive or negative, and is commonly used for sentiment analysis and natural language processing tasks.

We trained a **logistic regression** sentiment classifier using the Term Frequency-Inverse Document Frequency (**TF-IDF**) approach:

TF-IDF is a numerical representation of text useful for transforming text into a numerical format suitable for machine learning. It measures how important a word is within a document relative to the entire corpus. It consists of:

* Term Frequency (TF): The number of times a word appears in a document.
* Inverse Document Frequency (IDF): A measure that reduces the weight of commonly occurring words and increases the weight of rare words.

Here is a sample code for inferring sentiment from text using the trained model:

{% file src="/files/6VUBUEkVcOCkzS96Mp81" %}
dictionary containing the vocabulary and the IDF scores
{% endfile %}

{% file src="/files/yXJ8yIDS9k7et9ZouCbH" %}

{% file src="/files/s4rgm87kYzhkqr0GA6Vx" %}

```python
import re
import numpy as np
import json
import torch


def preprocess_text(text: str) -> str:
    # Remove links, special characters, and digits
    text = re.sub(r'http\S+|www\S+|https\S+', '', text, flags=re.MULTILINE)  # Remove URLs
    text = re.sub(r'[^a-zA-Z\s]', '', text)  # Remove non-alphabetic characters
    text = text.lower()  # Convert to lowercase
    text = text.strip()  # Remove leading/trailing whitespaces
    return text


def txt2tfidf(s: str, vocab: dict[str, int], idf: list[float]) -> torch.Tensor:
    s_clean = preprocess_text(s)
    all_words = s_clean.split()
    relevant_words = set(s_clean.split()).intersection(vocab.keys())

    res = np.zeros(len(vocab))
    for w in relevant_words:
        w_idx = vocab[w]
        w_cnt = all_words.count(w)
        w_idf = idf[w_idx]
        w_tfidf = w_cnt * w_idf
        res[w_idx] = w_tfidf

    return torch.tensor(res / np.linalg.norm(res))


# load tfidf data
with open('sentiment_tfidf.json', 'r') as f:
    tfidf_data = json.load(f)
    
# load the coef matrix and intercept vector of the trained logistic regression model
W = np.load('coef.npy')  # shape (1,5000)
b = np.load('intercept.npy')  # shape (1,)

txt = 'this is the best day of my life'

# transform text to numerical representation
pt = txt2tfidf(txt, tfidf_data['vocabulary'], tfidf_data['idf'])  # shape (5000,)

# calculate the logistic regression prediction
res = pt @ W.T + b

# the predicted sentiment is the sign of the logit
sentiment = "POSITIVE" if res > 0 else "NEGATIVE"
print(f"Predicted sentiment: {sentiment}")
```

## Achieving Full Privacy with LatticaAI

{% hint style="info" %}
First [install](/demo-tutorials/zooming-into-each-step-of-demo-run-with-latticaai-flow#installation-and-setup) our client package
{% endhint %}

{% tabs %}
{% tab title="🧊 Python SDK" %}

```python
from lattica_query.auth import get_demo_token
from lattica_query.lattica_query_client import QueryClient

model_id = "sentimentAnalysis"
my_token = get_demo_token(model_id)

client = QueryClient(my_token)

context, secret_key, client_blocks, = client.generate_key()

# `pt` and `res` are torch.Tensor, same as in the plain example above
res = client.run_query(context, secret_key, pt, client_blocks)
```

{% endtab %}

{% tab title="📦 TypeScript SDK" %}

```typescript
import { getDemoToken, LatticaQueryClient } from '@Lattica-ai/lattica-query-client';

const modelId = "sentimentAnalysis"
const token = await getDemoToken(modelId);

const client = new LatticaQueryClient(myToken);

await client.init();

// pt is the result of tfidf encoding, as in the python example above
const result = await client.runQuery(pt);
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
See our [step-by-step guide](/demo-tutorials/zooming-into-each-step-of-demo-run-with-latticaai-flow) for a detailed explanation of each step in this flow. \
To use the image sharpening model use the  **sentimentAnalysis** model ID
{% endhint %}


# Health Analysis with LatticaAI Demo Tutorial

<div data-full-width="true"><figure><img src="/files/1mE2nSZeM9sdmRH5eFTw" alt=""><figcaption></figcaption></figure></div>

## Overview of the Model

Our **Health Analysis** model is trained on the [Disease Prediction Kaggle dataset](https://www.kaggle.com/datasets/kaushil268/disease-prediction-using-machine-learning). This dataset is designed to facilitate the application of machine learning to the medical field, aiding physicians by automating disease diagnosis based on symptoms.

The dataset consists of **131 binary columns** representing different symptoms that a person may experience, and maps symptoms to **41 different diseases**, allowing classification based on input symptoms.

We trained **multi-class logistic regression** model,  implemented the equivalent fully homomorphic model and deployed it to our cloud service for secure inference.

* **Input Format**: binary vector of length `131`.
* **Output**: Probability vector of length `41` that represents the possible diseases.

The equivalent pytorch code for the inference is:

{% file src="/files/rkaIBxNRlGoMeTJ5KphB" %}
List of 131 possible symptoms
{% endfile %}

{% file src="/files/GJEIvjLSwlbmrSFalC35" %}
List of 41 disease
{% endfile %}

{% file src="/files/9AxirP5Ko9xVwnp2DiQN" %}

{% file src="/files/vBKaPxf6OqEXooYVKBhq" %}

```python
import torch
import json
import numpy as np


# load the symptoms and diseases mappings
with open('symptoms.json', 'r') as f:
    symptoms = json.load(f)

with open('diseases.json', 'r') as f:
    diseases = json.load(f)

# load the coef matrix and intercept vector of the trained logistic regression model
W = np.load('coef.npy')  # shape (41,131)
b = np.load('intercept.npy')  # shape (41,)

# create binary vector of length 131, corresponding to the mapping symptoms.json
pt = torch.zeros(131, dtype=torch.float64)
pt[symptoms['Continuous Sneezing']] = 1
pt[symptoms['Shivering']] = 1
pt[symptoms['Chills']] = 1
pt[symptoms['Watering From Eyes']] = 1

# calculate the logistic regression prediction
res = torch.nn.functional.softmax(pt @ W.T + b, dim=0)

# the predicted disease according to the mapping diseases.json
disease = diseases[res.argmax().item()]
print(f"Predicted disease: {disease}")
```

## Achieving Full Privacy with LatticaAI

{% hint style="info" %}
First [install](/demo-tutorials/zooming-into-each-step-of-demo-run-with-latticaai-flow#installation-and-setup) our client package
{% endhint %}

{% tabs %}
{% tab title="🧊 Python SDK" %}

```python
from lattica_query.auth import get_demo_token
from lattica_query.lattica_query_client import QueryClient

model_id = "healthPrediction"
my_token = get_demo_token(model_id)

client = QueryClient(my_token)

context, secret_key, client_blocks, = client.generate_key()

# `pt` and `res` are torch.Tensor, same as in the plain example above
pt = torch.randint(0, 2, (131,), dtype=torch.float64)

res = client.run_query(context, secret_key, pt, client_blocks)
```

{% endtab %}

{% tab title="📦 TypeScript SDK" %}

```typescript
import { getDemoToken, LatticaQueryClient } from '@Lattica-ai/lattica-query-client';

const modelId = "healthPrediction"
const token = await getDemoToken(modelId);

const client = new LatticaQueryClient(myToken);

await client.init();

const pt = [1, 1, 0, , 0, 1,...];
const result = await client.runQuery(pt);
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
See our [step-by-step guide](/demo-tutorials/zooming-into-each-step-of-demo-run-with-latticaai-flow) for a detailed explanation of each step in this flow. \
To use the image sharpening model use the  **healthPrediction** model ID
{% endhint %}


# Digit Recognition with LatticaAI Demo Tutorial

<div data-full-width="true"><figure><img src="/files/xMziL4MrLV0OAG6sqWT2" alt=""><figcaption><p>Digit Recognition flow</p></figcaption></figure></div>

## Overview of the Model

Our **Digit recognition** model is trained on the [MNIST dataset](https://www.kaggle.com/datasets/kaushil268/disease-prediction-using-machine-learning). This dataset is a collection of grayscale images of handwritten digits (0–9), each 28×28 pixels in size. We added some preprocessing and data augmentations to the training data, for better performance on real world sketches of handwritten digits.

The model architecture is FCNN (fully-connected neural network):

1. Input Layer: flattens the 28x28 image into a 784-dimensional vector.
2. Hidden Layer: a fully connected layer with 50 neurons and **square** activation.
3. Output Layer: a fully connected layer with 10 neurons (one for each digit) and a softmax activation.

{% hint style="info" %}
The reason we chose to use square activation instead of the popular ReLU activation, is that homomorphic operation are better suited for polynomial operators, and square is the simplest and lowest degree non-linear operator that we can use as layer activation.
{% endhint %}

<figure><img src="/files/xeY1TcoNZLg7YyXC5y7J" alt="" width="149"><figcaption><p>model architecture</p></figcaption></figure>

Here is a sample code for inferring digit from an image using the trained model:

{% file src="/files/IN7eAUudZpjlwLoGhhry" %}

{% file src="/files/jlCpxaFPsGkECOcUFQYQ" %}

```python
import torch
import matplotlib.pyplot as plt


def inference(l1_weight, l1_bias, l2_weight, l2_bias, x):
    x = x.flatten()
    x = l1_weight @ x + l1_bias
    x = x ** 2
    x = l2_weight @ x + l2_bias
    return torch.nn.functional.softmax(x, dim=0)


# load model weights
model_dict = torch.load("digits_recognizer.pth", map_location="cpu")

# digit inference
img = plt.imread("digit.png")[..., 0]
pt = torch.tensor(img)

res = inference(
    model_dict["fc1.weight"], model_dict["fc1.bias"],
    model_dict["fc2.weight"], model_dict["fc2.bias"],
    pt,
)

plt.figure()
plt.imshow(img)
plt.title(f"Prediction: {res.argmax().item()}")
plt.axis("off")

plt.show()
```

## Achieving Full Privacy with LatticaAI

{% hint style="info" %}
First [install](/demo-tutorials/zooming-into-each-step-of-demo-run-with-latticaai-flow#installation-and-setup) our client package
{% endhint %}

{% tabs %}
{% tab title="🧊 Python SDK" %}

```python
import torch
import matplotlib.pyplot as plt

from lattica_query.auth import get_demo_token
from lattica_query.lattica_query_client import QueryClient


model_id = "sketchToNumber"
my_token = get_demo_token(model_id)

client = QueryClient(my_token)

context, secret_key, client_blocks, = client.generate_key()

# SECURE digit inference
img = plt.imread("digit.png")[..., 0]
pt = torch.tensor(img)

# `res` is torch.Tensor, same as in the plain example above
res = client.run_query(context, secret_key, pt, client_blocks)

# Display the image and prediction as above...
```

{% endtab %}

{% tab title="📦 TypeScript SDK" %}

```typescript
import { getDemoToken, LatticaQueryClient } from '@Lattica-ai/lattica-query-client';

const modelId = "sketchToNumber"
const token = await getDemoToken(modelId);

const client = new LatticaQueryClient(myToken);

await client.init();

// pt is an mnist image in the form of number[], as in the python example above
const result = await client.runQuery(pt);
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
See our [step-by-step guide](/demo-tutorials/zooming-into-each-step-of-demo-run-with-latticaai-flow) for a detailed explanation of each step in this flow. \
To use the image sharpening model use the **sketchToNumber** model ID
{% endhint %}


# Zooming Into Each Step of Demo Run with LatticaAI flow

## Installation & Setup

Before you begin, ensure you have the following:

* **Python 3.10+** installed on your client machine.
* **Install Lattica query package.**

{% tabs %}
{% tab title="🧊 Python SDK" %}

```python
pip install lattica_query
```

{% endtab %}

{% tab title="📦 TypeScript SDK" %}

```typescript
npm install "@Lattica-ai/lattica-query-client"
```

{% endtab %}
{% endtabs %}

***

## Authentication & Model ID

You need an authentication JWT token to interact with our cloud infrastructure. This token validates your requests and ensures secure communication.

Each public model we run on the cloud has its own unique **modelID**. The specific modelID for each demo is provided in its corresponding tutorial.

1. **Request an authentication Token**: Run the code below.&#x20;
2. **Store the Token** securely for subsequent operations.

{% tabs %}
{% tab title="🧊 Python SDK" %}

```python
from lattica_query.auth import get_demo_token

# Use the model ID provided in the specific demo tutorial (e.g., 'imageEnhancement', 'sentimentAnalysis')
model_id = "demoModelId"
my_token = get_demo_token(model_id)
```

{% endtab %}

{% tab title="📦 TypeScript SDK" %}

```typescript
import { getDemoToken } from '@Lattica-ai/lattica-query-client';

// Use the model ID provided in the specific demo tutorial (e.g., 'imageEnhancement', 'sentimentAnalysis')
const modelId = "demoModelId"
const token = await getDemoToken(modelId);
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
In our web demo version, the client logic is initialized automatically in your browser—no separate install or setup is required. The web page manages your authentication and sets the appropriate Model ID behind the scenes.
{% endhint %}

***

## Generating & Registering Keys

We supply a class that handles all the local calculations and communications to the LatticaAI server. Initialize this class using the token you obtained.

{% tabs %}
{% tab title="🧊 Python SDK" %}

```python
from lattica_query.lattica_query_client import QueryClient


client = QueryClient(my_token)
```

{% endtab %}

{% tab title="📦 TypeScript SDK" %}

```typescript
import { LatticaQueryClient } from '@Lattica-ai/lattica-query-client';

const client = new LatticaQueryClient(myToken);
```

{% endtab %}
{% endtabs %}

Our encryption scheme relies on a **secret key** (which stays on your machine) and an **evaluation key (EVK)** (sent to LatticaAI cloud server).

{% hint style="info" %}
One key pair can be reused for multiple demo sessions.
{% endhint %}

{% tabs %}
{% tab title="🧊 Python SDK" %}

```python
context, secret_key, client_blocks, = client.generate_key()
```

{% endtab %}

{% tab title="📦 TypeScript SDK" %}

```typescript
await client.init();
```

{% endtab %}
{% endtabs %}

***

## Process the requested query

You can now encrypt it and send it securely to the cloud for processing.

{% tabs %}
{% tab title="🧊 Python SDK" %}
{% code overflow="wrap" %}

```python
result = client.run_query(context, secret_key, pt, client_blocks)
```

{% endcode %}
{% endtab %}

{% tab title="📦 TypeScript SDK" %}

```typescript
const result = await client.runQuery(pt);
```

{% endtab %}
{% endtabs %}

The **run\_query** method works in 4 steps:

1. Prepares your input using the model's preprocessing rules
2. Takes your secret key to encrypt the data into a secure format
3. Sends your encrypted data to LatticaAI server and waits for the response
4. Decrypts what comes back and turns it into a ready-to-use PyTorch tensor

Here are snippets of the inner implementation of **run\_query** method:

{% tabs %}
{% tab title="🧊 Python SDK" %}
{% code overflow="wrap" %}

```python
import lattica_query.query_toolkit as toolkit_interface


# apply preprocessing on plain text
pt = toolkit_interface.apply_client_block(client_block, context, pt)

# enctypt and get ct (cipher text)
ct = toolkit_interface.enc(context, secret_key, pt, pack_for_transmission=True)

# send to server and recieve enrypted cipher text
ct_res = self.worker_api.apply_hom_pipeline(ct, block_index=client_block.block_index+1)

# decrypt and get result plain text
pt_dec = toolkit_interface.dec(context, secret_key, ct_res)
```

{% endcode %}
{% endtab %}
{% endtabs %}

***


