Static Agent Export and Import

Example usage of Static Agent Export and Import APIs

Introduction

This new feature allows users to export an agent from one workflow, and import a static copy of it into a different workflow, on the same cluster or on a different one (e.g. to promote an agent to a higher environment). The imported agent does not need to be re-trained.


Preconditions

  • The feature flag modelExportEnabled must be enabled on the cluster.
  • The user creating the export must have Manager access to the cluster
  • The user importing the agent must have Manage All Data permissions
  • The agent to be exported must successfully trained

Types of Agents Supported

  • The following types of agents may be exported:
  • Image and Document Classification (Custom V1)
  • Document Extraction (Custom V2)
  • Form Extraction

📘

Note: All OCR providers are supported.


Types of Agents Not Supported

  • Image and Document Multi-Classification (Custom V1)
  • Image Extraction (object detection)
  • Unbundling (doc-splitting)
  • GenAI OOTB agents
  • GenAI Extraction agents

Supported Functionality of Imported Agents

  • Submissions to imported agents can be sent and reviewed. Submission result files will contain predictions and labels in the “component_results” section, not the “model_results” section.
  • Filters can be added to imported Classification agents.
  • Linked Labels can be added to imported Document Extraction agents.
  • Imported agents can be removed from a workflow.

Limitations of Imported Agents

  • Imported agents are Static. They cannot be customized or modified.
  • There is no corresponding Agent task page for an imported agent.
  • Imported agents cannot be re-trained.
  • Metrics are not available for imported agents.
  • Fields in an imported agent cannot be deleted, added, or modified.
  • Import and Export of agents is available via API only (not in the UI).

Agent Export

Call the CreateModelExport class to create an export of an agent in a workflow:

def **init**(self, 
             model_id: int,
             wait: bool = True,
             request_interval: int | float = 5) -> None

Create a model export.
Available on 6.14+ only.
Params:  model_id - the model id.
         wait - wait for the export to complete.  Defaults to True.
         request_interval - the interval between requests in seconds.  Defaults to 5.
Copied from: CreateModelExport

Agent export will produce a ZIP file that contains:

  • model.pkl: the agent pickle file
  • Metadata.json: a file of metadata with information about the agent.

🚧

Note that these files should not be modified after export.


{  
   "task_type":"annotation",  
   "model_type":"table",  
   "model_options":{  
      "id":802,  
      "domain":"standard",  
      "high_quality":false,  
      "interlabeler_resolution":"all",  
      "sampling_strategy":"random_oversample",  
      "seed":9823,  
      "test_split":0.2,  
      "weight_by_class_frequency":null,  
      "word_predictor_strength":null,  
      "model_training_options":{  
         "use_partial_data":true,  
         "use_autolabeled_data":true  
      },  
      "predict_options":null  
   },`
`   "labelset":{  
      "id":933,  
      "target_names":[  
         {  
            "created_at":1730079573.410494,  
            "created_by":4,  
            "updated_at":1730079573.410494,  
            "updated_by":null,  
            "id":2930,  
            "labelset_id":933,  
            "name":"Year",  
            "position":0,  
            "active":true,  
            "target_type":"text"  
         },  
         {  
            "created_at":1730079573.410494,  
            "created_by":4,  
            "updated_at":1730079573.410494,  
            "updated_by":null,  
            "id":2931,  
            "labelset_id":933,  
            "name":"TotalExpenses",  
            "position":1,  
            "active":true,  
            "target_type":"text"  
         },`
`         {  
            "created_at":1730079573.410494,  
            "created_by":4,  
            "updated_at":1730079573.410494,  
            "updated_by":null,  
            "id":2932,  
            "labelset_id":933,  
            "name":"TotalIncome",  
            "position":2,  
            "active":true,  
            "target_type":"text"  
         }  
      ],`
`      "fields":\[  
         {  
            "id":218768,  
            "name":"Year",  
            "workflow_id":689,  
            "datatype":"text",  
            "input_config":{  
               "strip_whitespace":false,  
               "strip_punctuation":false  
            },  
            "format_config":{  
            },  
            "validation_config":[  
            ],  
            "multiple":true,  
            "required":true  
         },`
`         {  
            "id":218769,  
            "name":"TotalExpenses",  
            "workflow_id":689,  
            "datatype":"text",  
            "input_config":{  
               "strip_whitespace":false,  
               "strip_punctuation":false  
            },  
            "format_config":{  
            },  
            "validation_config":[  
            ],  
            "multiple":true,  
            "required":true  
         },`
`         {  
            "id":218770,  
            "name":"TotalIncome",  
            "workflow_id":689,  
            "datatype":"text",  
            "input_config":{  
               "strip_whitespace":false,  
               "strip_punctuation":false  
            },  
            "format_config":{  
            },  
            "validation_config":[  
            ],  
            "multiple":true,  
            "required":true  
         }  
      ],`
`      "field_links":[  
         {  
            "id":386768,  
            "workflow_id":689,  
            "component_id":1604,  
            "target_id":2930,  
            "target_name":"Year",  
            "field_id":218768  
         },  
         {  
            "id":386769,  
            "workflow_id":689,  
            "component_id":1604,  
            "target_id":2931,  
            "target_name":"TotalExpenses",  
            "field_id":218769  
         },  
         {  
            "id":386770,  
            "workflow_id":689,  
            "component_id":1604,  
            "target_id":2932,  
            "target_name":"TotalIncome",  
            "field_id":218770  
         }  
      ]  
   },`
`   "dataset":{  
      "id":737,  
      "type":"document",  
      "ocr_engine":"readapi_tables_v1",  
      "configs":{  
         "nest":false,  
         "chars":[  
            "doc_index",  
            "page_num",  
            "page_index",  
            "text",  
            "block_index",  
            "confidence",  
            "position"  
         ],  
         "pages":[  
            "dpi",  
            "image",  
            "thumbnail",  
            "page_num",  
            "doc_offset",  
            "ocr_statistics",  
            "size",  
            "text"  
         ],  
         "blocks":[  
            "doc_offset",  
            "page_num",  
            "page_offset",  
            "text",  
            "block_type",  
            "position"  
         ],`
`         "tokens":[  
            "block_offset",  
            "doc_offset",  
            "page_num",  
            "style",  
            "page_offset",  
            "text",  
            "position"  
         ],  
         "languages":[  
            "ENG"  
         ],  
         "top_level":"page",  
         "ocr_engine":"readapi_tables_v1",  
         "reblocking":[  
            "style",  
            "list",  
            "inline-header"  
         ],  
         "auto_rotate":true,  
         "excel_tables":false,  
         "include_lines":false,  
         "single_column":false,  
         "ocr_statistics":[  
            "mean_confidence",  
            "mode_confidence",  
            "median_confidence"  
         ],`
`         "table_read_order":"row",  
         "spreadsheet_converter_version":4  
      }  
   },  
   "source_host":"<https://clustername.us-east-1.indico-dev.indico.io">,  
   "source_ipa_version":"IPA-6.14.0",  
   "workflow_id":689,  
   "model_group_id":723,  
   "model_id":1324,  
   "component_id":1604,  
   "source_column_id":822,  
   "created_by":4,  
   "created_at":1737746726.994178  
}

Agent Import

Call the AddStaticModelComponent class to import the model pickle file into a workflow:

def __init__(self,
             workflow_id: int,
             after_component_id: int | None = None,
             after_component_link_id: int | None = None,
             static_component_config: dict[str, Any] | None = None,
             auto_process: bool = False,
             export_file: str | None = None) -> None

Add a static model component to a workflow.
Available on 6.14+ only.
Copied from: AddStaticModelComponent

Example Script

This is a sample script to export an agent from one workflow and import it into another. This script uses the Python SDK .

from indico import IndicoClient, IndicoConfig
from indico.queries import AddStaticModelComponent, CreateModelExport, GetWorkflow
from indico.types.model_export import ModelExport
import os
import requests
from pathlib import Path

# Constants for workflow and model IDs
EXPORT_WORKFLOW_ID = 689
IMPORT_WORKFLOW_ID = 690
MODEL_ID = 1324

# Configuration for the Indico client
my_config = IndicoConfig(host="cluster.us-east-1.indico-dev.indico.io",
                         api_token_path="./indico_api_token.txt")

# Instantiate the Indico client
client = IndicoClient(config=my_config)

def download_export(export: ModelExport) -> Path:
   """
   Download the model export file from the provided signed URL.

   Args:
       export (ModelExport): The model export object containing the signed URL and file path.

   Returns:
       Path: The path to the downloaded file.
   """
   file_name = os.path.join(os.getcwd(), Path(export.file_path).name.replace(".indico", ".zip"))
   response = requests.get(export.signed_url, stream=True)
   with open(file_name, "wb") as dl_path:
       for chunk in response.iter_content(chunk_size=8192):
           dl_path.write(chunk)
   return Path(file_name)

def main():
   """
   Main function to add a static model component to an existing workflow.
   """
   # Retrieve the workflow details
   workflow = client.call(GetWorkflow(workflow_id=EXPORT_WORKFLOW_ID))

   # Create a model export from one workflow
   model_export = client.call(CreateModelExport(model_id=MODEL_ID))

   # Download the exported model file
   dled_export = download_export(model_export[0])

   # Add the static model component to another workflow
   client.call(
       AddStaticModelComponent(
           workflow_id=IMPORT_WORKFLOW_ID,           after_component_id=workflow.component_by_type("INPUT_OCR_EXTRACTION").id,
           auto_process=True,
           component_name="imported_model",
           export_file=str(dled_export),
       )
   )

if __name__ == "__main__":
   main()

Common Errors

Export Errors

  • If the agent is not trained: “Only successfully trained models can be exported”.
  • If an agent fails to download: “Model failed to download.”
  • If an agent fails to export: “Model failed to export”
    • If the agent export times out (takes more than 15 minutes): “Model export timed out”.
    • If the agent ID does not exist: “The model ID does not exist or you do not have access to this model”.
    • If the user does not have manager access to the agent: “The model ID does not exist or you do not have access to this model”.

Import Errors

  • Incompatible with valid actions: “Model type must conform to valid actions.”
  • If version incompatibility: “Versions are incompatible.”
  • If dataset incompatibility: “Datasets must match between model types.” Includes dataset settings or dataset provider incompatibility.
  • If file type is incorrect: “File type unsupported.”
  • If a generic failure to upload error: “Model failed to upload.”
  • If the OCR engine is not available: “OCR engine not supported.”