Configure deployment
Choose where your model deploys, how its outputs refresh, and which reasoners PyRel uses. Use configuration profiles to keep environment-specific settings in one file.
- Prerequisites
- You have a PyRel project with a
raiconfig.yamlfile to configure. For setup, see Install and run PyRel.
- You have a PyRel project with a
Dev, Staging, and Production environments
Section titled “Dev, Staging, and Production environments”Deploy the same model to different Snowflake schemas to keep its development, staging, and production outputs separate. You can also deploy one model to multiple target schemas simultaneously, for example to support tenants with isolated data sources. Each public schema holds that environment’s outputs, and its internal schema holds the deployment’s own objects, state, and refresh metadata. Name both: a deployment must say where each goes. Deploying to another schema does not move or copy the model’s source tables.
Configuration profiles are named overrides on your base configuration.
Give each environment a profile that sets its deployment target.
Add these settings to your existing raiconfig.yaml, keeping your connection configuration:
profile: dev: deployment: public_schema: MY_DATABASE.MY_MODEL_DEV identity: internal_schema: MY_DATABASE.MY_MODEL_DEV_META staging: deployment: public_schema: MY_DATABASE.MY_MODEL_STAGING identity: internal_schema: MY_DATABASE.MY_MODEL_STAGING_META prod: deployment: public_schema: MY_DATABASE.MY_MODEL_PROD identity: internal_schema: MY_DATABASE.MY_MODEL_PROD_META
active_profile: dev- The
dev,staging, andprodprofiles select different output schemas for the same model. - Each one also names its own internal schema, by convention the public schema with a
_METAsuffix. active_profileselects the profile to load. Change it tostagingorprodwhen you want that environment’s settings.- These profile names are conventions. Selecting a profile does not promote a model or copy data between environments.
Inspect the loaded configuration before deploying:
from relationalai.config import create_config
cfg = create_config()print(cfg.active_profile)print(cfg.deployment.public_schema)devMY_DATABASE.MY_MODEL_DEVThese values confirm that the dev profile selects the development target, not that the model has been deployed.
If they differ, check the active profile and any overrides using Use profiles to manage multiple configurations.
Then follow Deploy a model to deploy and verify the outputs.
Deployment settings
Section titled “Deployment settings”Set the deployment target
Section titled “Set the deployment target”The deployment section controls where and how a model deploys its outputs to Snowflake.
For most models, you only need to set deployment.public_schema, deployment.identity.internal_schema, and deployment.role:
deployment: public_schema: MY_DATABASE.MY_MODEL # Where the model's output views are created identity: internal_schema: MY_DATABASE.MY_MODEL_META # Where PyRel stores deployment metadata role: MY_DEPLOYMENT_ROLE # Snowflake role used to deploy and refresh the model # auto_deploy: true # Deploy automatically before running queries (defaults to false)The auto_deploy setting is optional.
Here is what each setting does:
public_schema: The fully-qualified Snowflake schema (<DATABASE>.<SCHEMA>) that holds the model’s outputs. Each output is a view here, and these views are the model’s SQL interface: query them, grant on them, and attach policies to them. The objects that hold the data behind them live in the internal schema. Models can use dedicated schemas or share a schema with object name prefixes or suffixes. PyRel will not overwrite objects that do not belong to this model. So if an object belonging to you or another model has the same name as a model output, the deploy fails until you resolve the name conflict.role: The Snowflake role PyRel uses to deploy and refresh the model. If you omit it, PyRel uses the connection or current session role. Refresh tasks run with this role alone, excluding Snowflake secondary roles. This role must have every privilege that deployment and refresh need, for exampleUSAGEon the warehouse. Privileges it inherits through Snowflake’s role hierarchy count, but privileges gained via secondary roles do not.identity.internal_schema: The schema where PyRel keeps the deployment’s own internal objects and the metadata that manages them, such as stored procedures, the refresh plan table, and the refresh log. It also holds the objects that store the data behind the public views, named with an_INTERNAL_STORE_prefix. Keeping it separate frompublic_schemaprevents PyRel’s bookkeeping from mixing with your model’s outputs. Treat everything here as PyRel’s own: it can change between releases, so do not query it or depend on its shape. It is required, so the schema PyRel creates these objects in is always one you chose. By convention it is the public schema with a_METAsuffix, for exampleMY_DATABASE.MY_MODEL_META.auto_deploy: Whentrue, PyRel deploys the model automatically before it runs queries against it, so you do not have to runrai models deployyourself. It defaults tofalse, which means you must deploy explicitly.
Configure object name prefixes and suffixes
Section titled “Configure object name prefixes and suffixes”Set deployment.identity.object_name_prefix or deployment.identity.object_name_suffix to customize the names of objects that PyRel creates for your model.
Both settings default to an empty string.
You can set either value or both.
For example, add these fields to your existing deployment configuration:
deployment: public_schema: MY_DATABASE.SHARED_MODELS identity: internal_schema: MY_DATABASE.SHARED_MODELS_META object_name_prefix: PRJ123_ object_name_suffix: _DEVAn output named TRANSACTION becomes PRJ123_TRANSACTION_DEV.
PyRel also applies prefixes and suffixes to internal objects.
For example, the refresh status procedure REFRESH_STATUS() becomes PRJ123_REFRESH_STATUS_DEV().
Source tables and the ownership tag’s name do not change.
The naming rules are:
- Values are converted to uppercase. PyRel adds no separator, so include underscores where you want them.
- Values can contain ASCII letters, digits, underscores, and dollar signs. A nonempty prefix must start with a letter or underscore. A suffix can start with a digit.
- Values cannot contain
$$or the reserved names_INTERNAL_MODEL_IDENTITYand_INTERNAL_DEPLOY_STATE. - Each complete object name, including its prefix and suffix, must fit within Snowflake’s 255-character limit.
Continue to use the original output names in deployment.overrides, without the configured prefix or suffix.
For example, an override for TRANSACTION still names TRANSACTION, not PRJ123_TRANSACTION_DEV.
Choose the schemas, prefix, and suffix before the first deployment. PyRel uses these settings to identify your model. As long as your model remains the same, the generated schema stays stable so others in your organization can depend on it. If you change them, the next deployment targets a different location and leaves the previous deployment in place. To remove a deployment, run teardown with that deployment’s settings.
Configure op log recording
Section titled “Configure op log recording”The oplog section controls whether rai models deploy records your model’s change history to its op log.
In PyRel 1.28 and later, oplog.enabled defaults to true, so deploys record history without any additional configuration.
Set it to false only when you want deploys to install your model without recording history.
The shared-model synchronization workflow is unavailable while recording is disabled because it relies on the op log.
-
Set
oplog.enabledtofalseinraiconfig.yamloplogis a top-level section, alongsideconnections,model, anddeployment.connections:# ...oplog:enabled: false -
Inspect the parsed config
from relationalai.semantics import Modelm = Model("MyModel")print(m.config.oplog.enabled)Output FalseThis confirms that PyRel loaded the explicit
oplog.enabled: falseoverride from your config.
The rai models commands (deploy and pull) read oplog.enabled from the raiconfig.yaml they discover when the command runs.
Set it in the config file for those command-line workflows.
Set oplog.enabled with a plain Python dict passed to create_config.
This example assumes file discovery already provides a valid connection configuration.
from relationalai.config import create_configfrom relationalai.semantics import Model
cfg = create_config(oplog={"enabled": False})m = Model("MyModel", config=cfg)
print(m.config.oplog.enabled)FalseThis confirms that PyRel loaded the explicit oplog.enabled: false override for this Python process.
Programmatic configuration controls what Model.deploy() records when you call it in the same script.
Standalone CLI commands such as rai models pull do not see this in-process config.
They load raiconfig.yaml independently.
To restore the default recording behavior, remove the enabled: false override or set oplog.enabled to true.
If you enable recording programmatically, Model.deploy() needs a source file to record, so set model.path in the same config.
Use a standard op log table for a transient deployment target
Section titled “Use a standard op log table for a transient deployment target”Snowflake can’t create the default Hybrid op log table inside a transient database or schema.
If the deployment target is a transient database or schema, set oplog.table_type to standard before deploying:
deployment: public_schema: MY_DATABASE.MY_TRANSIENT_SCHEMA identity: internal_schema: MY_DATABASE.MY_TRANSIENT_SCHEMA_META
oplog: table_type: standardFor a permanent deployment target, leave out this override to keep the default Hybrid op log table. The override doesn’t change which source tables PyRel supports.
Schedule output refreshes
Section titled “Schedule output refreshes”A deployed model keeps its outputs up to date by refreshing them on a schedule. A schedule is a named refresh cadence: for each schedule you define, PyRel creates a Snowflake task that refreshes the outputs assigned to it. Every output must be assigned to a schedule.
Use this table to find the part of scheduling you want to configure:
| What to do | When to do it |
|---|---|
| Define a schedule | Setting up any deployed model; every model needs at least one schedule. |
| Assign outputs to schedules | Some outputs need to refresh more or less often than others. |
| Skip the deploy-time refresh | An external pipeline or manual trigger drives the first refresh. |
| Auto-suspend test schedules | Developing a model, to keep test deployments from refreshing indefinitely. |
Define a schedule
Section titled “Define a schedule”Define one or more named schedules under deployment.schedules, then set a default schedule for all outputs with deployment.schedule:
deployment: public_schema: MY_DATABASE.MY_MODEL identity: internal_schema: MY_DATABASE.MY_MODEL_META role: MY_DEPLOYMENT_ROLE
schedules: standard: interval_s: 30 # refresh outputs every 30s
schedule: standard # default schedule for all outputsinterval_s is how often the schedule’s task refreshes its outputs, in seconds.
It must be 0 or at least 10.
Use 0 for a schedule whose refresh you trigger manually or from an external pipeline instead of on a fixed interval.
Schedule names must start with a letter and contain only letters, numbers, and underscores.
Assign outputs to schedules
Section titled “Assign outputs to schedules”Every output refreshes on exactly one schedule.
Set the default schedule for all outputs with deployment.schedule, then assign individual outputs to a different schedule with deployment.overrides.
Each override lists the objects it applies to and the schedule they refresh on:
deployment: public_schema: MY_DATABASE.MY_MODEL identity: internal_schema: MY_DATABASE.MY_MODEL_META role: MY_DEPLOYMENT_ROLE
schedules: standard: interval_s: 300 # most outputs refresh every 5 minutes fast_path: interval_s: 30 # these outputs refresh every 30s
schedule: standard # default schedule for all outputs overrides: - objects: - ACCOUNT_SCORE - RISK_FLAG schedule: fast_path # refresh these two outputs on fast_path insteadOutputs you do not name in an override use the default deployment.schedule.
Assign outputs to different schedules to refresh different parts of the model at different rates.
Skip the deploy-time refresh
Section titled “Skip the deploy-time refresh”By default, deploying a model triggers each refresh task once.
rai models deploy waits for the initial refresh by default.
Use --no-wait to return as soon as deployment completes, without waiting for the initial refresh to finish.
In PyRel versions before 1.37.0, add --wait to wait for the initial refresh.
This initial refresh runs even for a manual schedule with interval_s: 0.
Set run_on_deploy: false on a schedule to skip that initial refresh.
Use this when something other than the deploy drives the first refresh, such as an external pipeline that triggers the schedule’s task on its own timing:
schedules: external_pipeline: interval_s: 0 run_on_deploy: false # do not refresh at deploy time; the pipeline triggers it
schedule: external_pipelineTo trigger the refresh yourself, run the schedule’s Snowflake task.
PyRel creates one task per schedule, named REFRESH_<SCHEDULE> (with the schedule name in upper case) in the model’s internal schema.
For the external_pipeline schedule above, deployed to MY_DATABASE.MY_MODEL, you would run:
EXECUTE TASK MY_DATABASE.MY_MODEL_META.REFRESH_EXTERNAL_PIPELINE;Running the task requires the account-level EXECUTE TASK privilege.
Auto-suspend test schedules
Section titled “Auto-suspend test schedules”During development, set suspend_after_mins to auto-suspend a model’s refresh tasks after a period, so lingering tasks from test deployments do not keep running:
deployment: public_schema: MY_DATABASE.MY_MODEL identity: internal_schema: MY_DATABASE.MY_MODEL_META role: MY_DEPLOYMENT_ROLE suspend_after_mins: 15 # suspend refresh tasks 15 minutes after the deploy finishes
schedules: standard: interval_s: 30
schedule: standardLeave suspend_after_mins unset in production, where you want outputs to keep refreshing.
Configure deployed outputs
Section titled “Configure deployed outputs”Configure how PyRel creates and manages deployed outputs in the deployment section.
Set shared materialization and schedule defaults directly under deployment, and use deployment.overrides for named outputs that need different settings or direct row access, projection, or masking policies.
Choose how outputs are materialized
Section titled “Choose how outputs are materialized”Every output is a view in the public schema, whatever you set here.
These two settings, deployment.materialized and deployment.incremental, decide how PyRel stores the data that view reads from, in the internal schema.
Both accept auto (the default), true, or false, and you can override either one for individual outputs with deployment.overrides.
materialized: whether the data behind the output is stored.truestores it in a table,falseleaves the view to compute it on read, andautolets the compiler decide.incremental: whether PyRel maintains that stored data incrementally.trueuses a Snowflake dynamic table.autocurrently behaves likefalse, so PyRel refreshes the data itself.
Setting incremental: true together with materialized: false is a configuration error, because there is no stored data to maintain.
Because the public object is always a view, these settings change query performance and refresh behavior, not the shape of your SQL interface. A query against an output keeps working whichever way you set them.
For example, this configuration lets PyRel choose for most outputs and maintains ACCOUNT_SCORE incrementally:
deployment: public_schema: MY_DATABASE.MY_MODEL identity: internal_schema: MY_DATABASE.MY_MODEL_META role: MY_DEPLOYMENT_ROLE
schedules: standard: interval_s: 30
schedule: standard materialized: auto # let PyRel choose for each output overrides: - objects: - ACCOUNT_SCORE incremental: true # back this one with a dynamic tableName outputs the way you query them, without any configured prefix or suffix, which PyRel adds for you.
You can also name a single column as OUTPUT.COLUMN, which applies the setting only to the objects behind that column and wins over a setting on the whole output.
Internal object names match nothing: if an override matches no output, PyRel warns and ignores it.
Configure access policies
Section titled “Configure access policies”Configure row access, projection, or masking policies to control access to deployed outputs. PyRel attaches existing Snowflake policies to the managed outputs without creating or changing their definitions. Policies attach to the public views only, never to the objects storing their data, so readers go through the view and the policy applies.
Before you configure the outputs:
- Your Snowflake account must use Enterprise Edition or higher.
- Each policy must already exist. Creating a projection or masking policy requires the corresponding
CREATE PROJECTION POLICYorCREATE MASKING POLICYprivilege on its schema; attaching an existing policy does not require either creation privilege. - The role set by
deployment.roleneedsUSAGEor another sufficient privilege on the policy’s database and schema. - The role set by
deployment.rolemust have its usual deployment privileges and eitherAPPLYon each policy or the corresponding account-level privilege:APPLY ROW ACCESS POLICY,APPLY PROJECTION POLICY, orAPPLY MASKING POLICY. - When using policy-level
APPLYfor a projection or masking policy, the role must also own the target output. See Snowflake’s projection-policy privileges and masking-policy privileges.
PyRel uses the deployment role for deployment and refresh queries. The deployment role must be able to read all rows and original column values, including projecting protected columns. Policies that restrict this role can affect deployment and refresh results.
Configure policies under deployment.overrides[].policies in your existing raiconfig.yaml.
Use an override for every output that needs a direct policy.
The policy applies to every output of the override group.
Each of those outputs must contain all columns referenced by those policies in the configuration.
You cannot set a default direct access policy applying to all possible outputs.
To manage default policies, use Snowflake tag-based policies.
Assign the policies to tags in Snowflake, then apply those tags to the deployed objects with deployment.tags.
After deployment, check policy bindings and results as consumer roles.
Apply a row access policy to deployed outputs
Section titled “Apply a row access policy to deployed outputs”Use a Snowflake row access policy to control which rows different users or roles can see in a deployed output.
Add row_access_policy under the output override’s policies in your existing raiconfig.yaml.
This example assumes your model emits an ORDERS output with a TENANT_ID column:
deployment: public_schema: MY_DATABASE.MY_MODEL identity: internal_schema: MY_DATABASE.MY_MODEL_META role: MY_DEPLOYMENT_ROLE
schedules: standard: interval_s: 30
schedule: standard overrides: - objects: - ORDERS policies: row_access_policy: fqn: GOVERNANCE.POLICIES.TENANT_ACCESS columns: - TENANT_IDThe columns field is a non-empty, ordered list of output columns.
Its order and the corresponding output data types must match the arguments in the policy signature.
Apply a projection policy to output columns
Section titled “Apply a projection policy to output columns”Use a Snowflake projection policy to restrict whether a column’s values appear in query results while still allowing users to filter and join on that column. The policy controls whether the column can appear in those results based on the query’s context, such as the active role.
Add projection_policies under the output override’s policies in your existing raiconfig.yaml.
This example assumes your model emits a CUSTOMERS output with EMAIL and PHONE columns:
deployment: public_schema: MY_DATABASE.MY_MODEL identity: internal_schema: MY_DATABASE.MY_MODEL_META role: MY_DEPLOYMENT_ROLE
schedules: standard: interval_s: 30
schedule: standard overrides: - objects: - CUSTOMERS policies: projection_policies: - fqn: GOVERNANCE.POLICIES.HIDE_IDENTIFIERS columns: - EMAIL - PHONEEach entry binds the existing policy identified by its fully qualified name fqn independently to each column in the non-empty columns list.
These columns are policy targets, not arguments passed to the policy.
Apply a masking policy to output columns
Section titled “Apply a masking policy to output columns”Use a Snowflake masking policy to replace sensitive column values at query time according to the policy’s conditions.
Add masking_policies under the output override’s policies in your existing raiconfig.yaml.
This example assumes your model emits a CUSTOMERS output with an EMAIL column whose data type matches the policy’s input and return type:
deployment: public_schema: MY_DATABASE.MY_MODEL identity: internal_schema: MY_DATABASE.MY_MODEL_META role: MY_DEPLOYMENT_ROLE
schedules: standard: interval_s: 30
schedule: standard overrides: - objects: - CUSTOMERS policies: masking_policies: - fqn: GOVERNANCE.POLICIES.EMAIL_MASK columns: - EMAILEach entry binds the existing policy identified by its fully qualified name fqn independently to every column in its non-empty columns list.
For a conditional masking policy, which also uses other columns to decide what to return, add conditional_columns to the masking policy entry.
For example, replace the entry above with this binding when the existing policy accepts an email value followed by visibility and region values:
- fqn: GOVERNANCE.POLICIES.CONDITIONAL_EMAIL_MASK columns: - EMAIL conditional_columns: - VISIBILITY - REGIONIf you list multiple targets in columns, each gets a separate binding with that target as the first argument, followed by the same ordered conditional_columns.
Use separate entries when targets need different policies or conditional columns.
All columns must exist in the output, and each binding’s argument order and data types must match the policy signature.
Do not include any target from columns in conditional_columns.
Omit conditional_columns for a policy that takes only the protected value.
Combine output policies
Section titled “Combine output policies”You can put row_access_policy, projection_policies, and masking_policies in the same override’s policies block.
PyRel checks these restrictions before deployment:
- A column can have at most one direct projection policy and one direct masking policy. Both can protect the same column.
- A projection policy’s target column cannot also be a row access policy argument or a masking policy’s conditional column.
- A row access policy argument cannot also be a masking policy’s conditional column.
Some combinations require checks by Snowflake.
For example, using a masked column as a row access policy argument or another masking policy’s conditional argument requires EXEMPT_OTHER_POLICIES = TRUE on the masking policy protecting that column and compatible policy-owner roles.
PyRel does not configure that setting or fully validate external policy definitions.
If Snowflake rejects an assignment, have the policy owner correct its signature, privileges, or compatibility, then redeploy.
Check the result with consumer roles
Section titled “Check the result with consumer roles”Save the configuration and deploy the model:
rai models deployAfter deployment and a refresh finish, check representative rows and confirm that the policy allows the deployment role to read the full row set and original values.
If your schedule has run_on_deploy: false, trigger a refresh before checking the data.
Use a Snowflake user who can switch to the deployment role, a role your policy should allow, and a role it should restrict.
Each role needs SELECT on the output and USAGE on its database, schema, and query warehouse.
For the CUSTOMERS examples above, compare what each role can select:
USE ROLE MY_DEPLOYMENT_ROLE;SELECT EMAIL FROM MY_DATABASE.MY_MODEL.CUSTOMERS LIMIT 10;
USE ROLE MY_ALLOWED_CONSUMER;SELECT EMAIL FROM MY_DATABASE.MY_MODEL.CUSTOMERS LIMIT 10;
USE ROLE MY_RESTRICTED_CONSUMER;SELECT EMAIL FROM MY_DATABASE.MY_MODEL.CUSTOMERS LIMIT 10;For projection, the restricted query may fail or return NULL, depending on the policy’s enforcement.
For masking, compare the returned value with what the policy should return for that role.
To compare the same rows, filter by an unprotected stable key in your output; LIMIT alone does not guarantee the same rows.
Switching roles alone does not guarantee different results.
If a policy restricts the deployment role, have the policy owner allow it to read all rows and original values, then redeploy before relying on refreshes.
An appropriately privileged administrator can also inspect Snowflake policy references to check the bindings; ordinary SELECT on the output does not grant that permission.
Recover from unavailable policies
Section titled “Recover from unavailable policies”When PyRel proceeds with a deployment, it checks the visibility and kind of each configured row access, projection, and masking policy before creating or updating deployed outputs.
If a policy is missing or unavailable to the deploying role, deployment stops with Invalid Access Policies and lists each unavailable policy with its kind, fully qualified name, and Snowflake error.
Check the configured fqn and policy kind, then have your Snowflake administrator confirm that the existing policy is accessible to deployment.role and that the role has the applicable privileges above.
Correct the configuration or permissions and retry rai models deploy; after it finishes, check the bindings and query again as the intended reader roles.
This preflight checks that Snowflake can describe the policies. It does not prove that their signatures match the output columns or that every reader sees the intended results. Dry runs skip remote policy validation. If the deployed model already matches the current model and configuration and is ready, PyRel can return without redeploying or rechecking the policies.
Tag deployed Snowflake objects
Section titled “Tag deployed Snowflake objects”Use deployment.tags to put your own Snowflake object tags on every object a deploy creates.
That covers the model’s output views, along with the internal objects PyRel manages for the deployment, such as the objects storing the outputs’ data, refresh tasks, procedures, and the metadata tables in the internal schema.
Use it for cost attribution, data classification, or tag-based policies that Snowflake applies to any object carrying a given tag.
Before you configure tags:
- Each tag must already exist in Snowflake.
- The role set by
deployment.rolemust hold theAPPLYprivilege on each tag, andUSAGEon the database and schema that contain it.
Add your tags under deployment.tags in your existing raiconfig.yaml.
Each key is a fully qualified tag name in the form <DATABASE>.<SCHEMA>.<TAG>, and each value is the string assigned to that tag:
deployment: public_schema: MY_DATABASE.MY_MODEL identity: internal_schema: MY_DATABASE.MY_MODEL_META role: MY_DEPLOYMENT_ROLE
tags: GOVERNANCE.TAGS.COST_CENTER: engineering GOVERNANCE.TAGS.DATA_CLASSIFICATION: internalA value must be at most 256 characters, and it must be one of the tag’s ALLOWED_VALUES when the tag defines them.
The tags are applied to all deployed objects in the public and internal schemas. They are not applied to the schemas themselves, as Snowflake propagates a schema’s tags to every object it contains, including objects the model does not own.
After the deploy finishes, confirm the tags landed on an object by querying Snowflake’s TAG_REFERENCES.
Preserve output column case
Section titled “Preserve output column case”Set deployment.preserve_column_case: true to keep the capitalization of model field names in Snowflake columns.
The default is false, so column names follow Snowflake’s case-insensitive rules for unquoted identifiers.
For example, a preserved EntityId column must be written as "EntityId" in SQL.
This setting does not affect table names.
Reasoner settings
Section titled “Reasoner settings”Use reasoner settings to control which logic, prescriptive, and predictive reasoners PyRel uses for your workloads, and how it waits for results. This guide covers reasoner selection, reasoner-specific settings, and polling behavior.
Understand what reasoner configuration covers
Section titled “Understand what reasoner configuration covers”These settings apply after PyRel submits work and a reasoner runs your job:
Use the sections in this guide to tune five parts of that step:
- Reasoner selection controls which logic, prescriptive, and predictive reasoners PyRel uses for a workload.
- Logic reasoner settings control constraint reporting and incremental maintenance.
- Prescriptive reasoner settings control how PyRel identifies prescriptive reasoners and applies prescriptive query time limits.
- Predictive reasoner settings control how PyRel identifies predictive reasoners and applies predictive query time limits.
- Polling behavior controls how PyRel waits for long-running operations.
Each section shows the raiconfig.yaml form, the programmatic form, and a quick way to verify the setting.
If your model runs graph algorithms, also read Deploy a model that uses graph reasoning.
Select which reasoners to use
Section titled “Select which reasoners to use”Use reasoner name and size settings to configure specific reasoners for PyRel to use.
There are a couple of common patterns for using these settings. Use the following table to choose the workflow that matches your use case:
| Workflow | Use it when |
|---|---|
| Create a new reasoner and use it | You have no existing reasoners and need to fully manage them from config. |
| Use a reasoner that already exists | You already have a named reasoner and want PyRel to use it as-is. |
The following examples show both the raiconfig.yaml and programmatic config patterns for each workflow.
Create a new reasoner and use it
Section titled “Create a new reasoner and use it”Use this workflow when you have no existing reasoners and want to manage them from your config.
If you want to create the logic reasoner yourself first, use the CLI:
rai reasoners create --type logic --name team_logic --size HIGHMEM_X64_S --waitThen configure PyRel to use that reasoner name and size:
connections: # ...
reasoners: logic: name: team_logic size: HIGHMEM_X64_Sfrom relationalai.config import create_config
cfg = create_config( reasoners={ "logic": { "name": "team_logic", "size": "HIGHMEM_X64_S", } })
print(cfg.reasoners.logic.name)print(cfg.reasoners.logic.size)If you want to create the prescriptive reasoner yourself first, use the CLI:
rai reasoners create --type prescriptive --name team_prescriptive --size HIGHMEM_X64_S --waitThen configure PyRel to use that reasoner name and size:
connections: # ...
reasoners: prescriptive: name: team_prescriptive size: HIGHMEM_X64_Sfrom relationalai.config import create_config
cfg = create_config( reasoners={ "prescriptive": { "name": "team_prescriptive", "size": "HIGHMEM_X64_S", } })
print(cfg.reasoners.prescriptive.name)print(cfg.reasoners.prescriptive.size)Predictive reasoners are created from config the first time PyRel needs one for a predictive workflow. Set a name and size when you want PyRel to create a specific predictive reasoner instead of relying on the defaults:
connections: # ...
reasoners: predictive: name: team_predictive size: HIGHMEM_X64_Sfrom relationalai.config import create_config
cfg = create_config( reasoners={ "predictive": { "name": "team_predictive", "size": "HIGHMEM_X64_S", } })
print(cfg.reasoners.predictive.name)print(cfg.reasoners.predictive.size)- If
nameandsizeare configured and the named reasoner does not exist, PyRel creates it using the configured size. - Predictive reasoners are created from config the first time PyRel needs them.
- If the named reasoner already exists, PyRel uses it as-is and does not resize it from config.
Use a reasoner that already exists
Section titled “Use a reasoner that already exists”Use this workflow when the named reasoner already exists and you want PyRel to use it.
Set reasoners.logic.name to the existing logic reasoner name:
connections: # ...
reasoners: logic: name: team_logicfrom relationalai.config import create_config
cfg = create_config( reasoners={ "logic": { "name": "team_logic", } })
print(cfg.reasoners.logic.name)reasoners.logic.nametells PyRel which existing logic reasoner to use for model work.- The example omits
sizebecause the reasoner already exists. - PyRel uses the named reasoner as-is and does not change its size from config.
Set reasoners.prescriptive.name to the existing prescriptive reasoner name:
connections: # ...
reasoners: prescriptive: name: team_prescriptivefrom relationalai.config import create_config
cfg = create_config( reasoners={ "prescriptive": { "name": "team_prescriptive", } })
print(cfg.reasoners.prescriptive.name)reasoners.prescriptive.nameis the public config field for solver workloads.- The example omits
sizebecause the prescriptive reasoner already exists. - PyRel uses the existing reasoner as-is and does not resize it from config.
Set reasoners.predictive.name to the existing predictive reasoner name:
connections: # ...
reasoners: predictive: name: team_predictivefrom relationalai.config import create_config
cfg = create_config( reasoners={ "predictive": { "name": "team_predictive", } })
print(cfg.reasoners.predictive.name)reasoners.predictive.nametells PyRel which predictive reasoner to use for predictive workflows.- The example omits
sizebecause the predictive reasoner already exists. - PyRel uses the existing predictive reasoner as-is and does not resize it from config.
- If the reasoner is ever deleted, PyRel will create a new one with the same name if necessary, but it will use the default size for that reasoner type instead of the old size.
- For logic, prescriptive, and predictive reasoners, the default
sizeisHIGHMEM_X64_S. - If you omit
reasoners.predictive.name, PyRel defaults the predictive reasoner name to your Snowflake username with dots replaced by underscores.
Configure logic reasoner settings
Section titled “Configure logic reasoner settings”Which compute pools host logic reasoners
Section titled “Which compute pools host logic reasoners”Logic reasoners run in app-managed compute pools. You do not create or manage these pools directly, but you do choose logic reasoner sizes that map to them.
| Compute pool | Size | Supported cloud platforms | Used for |
|---|---|---|---|
RELATIONAL_AI_HIGHMEM_X64_S | HIGHMEM_X64_S | AWS, Azure | Small logic workloads and the default logic reasoner size. |
RELATIONAL_AI_HIGHMEM_X64_M | HIGHMEM_X64_M | AWS, Azure | Medium logic workloads. |
RELATIONAL_AI_HIGHMEM_X64_L | HIGHMEM_X64_L | AWS only | Large logic workloads on AWS. |
RELATIONAL_AI_HIGHMEM_X64_SL | HIGHMEM_X64_SL | Azure only | Large logic workloads on Azure. |
How logic reasoners are created
Section titled “How logic reasoners are created”PyRel creates logic reasoners automatically. Users can configure the name and size of the logic reasoner that PyRel creates for them.
When a user runs a query that needs a logic reasoner:
- PyRel checks whether the configured reasoner exists and is
READY. - If it is
READY, PyRel sends the query to that reasoner. - If it is not
READY, PyRel resumes it and waits for it to becomeREADY. - If it does not exist, PyRel creates it using the configured size, or
HIGHMEM_X64_Sif no size is configured.
The default logic reasoner settings are:
| Setting | Behavior |
|---|---|
| Name | Defaults to the Snowflake username with dots replaced by underscores. |
| Size | Defaults to HIGHMEM_X64_S. |
| Auto-suspend | Defaults to 60 minutes of inactivity for newly created reasoners when you do not set a different value. |
The logic reasoner runs the rules-based parts of your semantic model. PyRel uses it when it evaluates definitions, requirements, and queries. It also runs the graph algorithms listed in Which graph algorithms use the logic reasoner.
The settings in this section live under reasoners.logic.*.
Most users can leave them at their defaults.
If you do need to change a setting, use this table to find the right subsection:
| Subsection | Use it when |
|---|---|
| Constraint emission | You want more detail about requirement failures for debugging. |
| Incremental maintenance | You want to tune repeated runs that process small data changes. |
Enable or disable constraint emission
Section titled “Enable or disable constraint emission”Use emit_constraints when you need more detail while debugging a failed require() check.
This setting controls whether PyRel asks the logic reasoner for additional diagnostics when a requirement fails.
Requirements still pass or fail the same way whether this setting is on or off.
It defaults to false, so PyRel returns its usual failure information unless you enable it.
When extra diagnostics are available, they may include backend-dependent details such as the violated requirement text or the entities involved in the failing case.
Select the tab for your preferred configuration method and follow the steps to set emit_constraints and verify it.
-
Set
reasoners.logic.emit_constraintsinraiconfig.yaml:connections:# ...reasoners:logic:emit_constraints: true -
Verify the configured value:
from relationalai.config import create_configfrom relationalai.semantics import Modelcfg = create_config()# Use the config.m = Model("MyModel", config=cfg)# Verify the configured value.print(m.config.reasoners.logic.emit_constraints)
Set reasoners.logic.emit_constraints with LogicReasonerConfig or a plain Python dict.
-
Set the value with a typed config class:
from relationalai.config import LogicReasonerConfig, ReasonersConfig, create_configfrom relationalai.semantics import Modelcfg = create_config(reasoners=ReasonersConfig(logic=LogicReasonerConfig(emit_constraints=True,)))# Use the config.m = Model("MyModel", config=cfg)# Verify the configured value.print(m.config.reasoners.logic.emit_constraints) -
Alternatively, set the value with a dict:
from relationalai.config import create_configfrom relationalai.semantics import Modelcfg = create_config(reasoners={"logic": {"emit_constraints": True,}})# Use the config.m = Model("MyModel", config=cfg)# Verify the configured value.print(m.config.reasoners.logic.emit_constraints)
Enable or disable incremental maintenance
Section titled “Enable or disable incremental maintenance”Use reasoners.logic.incremental_maintenance to control whether the logic reasoner reuses work from an earlier run when you rerun the same query after your source data changes.
This matters most when you regularly rerun the same query or regenerate the same report on refreshed data, such as rerunning the same weekly report after the underlying source tables update.
Leave this setting at "off" unless that repeated-query pattern is important for your workload.
"off" is the default and the safest place to start.
Choose one of these modes:
"off"(default): Do not use incremental updates."auto": Use incremental updates where they are supported."all": Try incremental updates more broadly than"auto".
Select the tab for your preferred configuration method and follow the steps to set incremental_maintenance and verify it.
-
Set
reasoners.logic.incremental_maintenanceinraiconfig.yaml:connections:# ...reasoners:logic:incremental_maintenance: "auto" -
Verify the configured value:
from relationalai.config import create_configfrom relationalai.semantics import Modelcfg = create_config()# Use the config.m = Model("MyModel", config=cfg)# Verify the configured value.print(m.config.reasoners.logic.incremental_maintenance)
Set reasoners.logic.incremental_maintenance with LogicReasonerConfig or a plain Python dict.
-
Set the value with a typed config class:
from relationalai.config import LogicReasonerConfig, ReasonersConfig, create_configfrom relationalai.semantics import Modelcfg = create_config(reasoners=ReasonersConfig(logic=LogicReasonerConfig(incremental_maintenance="auto",)))# Use the config.m = Model("MyModel", config=cfg)# Verify the configured value.print(m.config.reasoners.logic.incremental_maintenance) -
Alternatively, set the value with a dict:
from relationalai.config import create_configfrom relationalai.semantics import Modelcfg = create_config(reasoners={"logic": {"incremental_maintenance": "auto",}})# Use the config.m = Model("MyModel", config=cfg)# Verify the configured value.print(m.config.reasoners.logic.incremental_maintenance)
Deploy a model that uses graph reasoning
Section titled “Deploy a model that uses graph reasoning”A model that builds a graph and runs graph algorithms deploys with the same configuration and the same rai models deploy command as any other model.
Three things are specific to graphs:
- The graph’s node and edge concepts each become a view in the public schema, like any other concept. See Understand the deployed representation.
- An algorithm result is computed on every refresh, but it stays in the internal schema unless your model exposes it. See Expose algorithm results as outputs.
- Some algorithms run on the logic reasoner rather than in SQL, so the refresh creates or resumes that reasoner when it needs it. No reasoner setting is required.
Which graph algorithms use the logic reasoner
Section titled “Which graph algorithms use the logic reasoner”A deployed model that runs graph algorithms needs no reasoner setting. When a refresh needs the logic reasoner, it resumes or creates the configured one, as described in How logic reasoners are created.
The following algorithms run on the logic reasoner:
Every other algorithm runs in SQL.
- This list describes current behavior, not a contract. Later releases may compute more algorithms in SQL.
- The first refresh after you add one of these algorithms can take longer while the reasoner starts. Later refreshes queue a job on it.
Expose algorithm results as outputs
Section titled “Expose algorithm results as outputs”A graph result stays in your internal schema until it becomes a part of your ontology. It becomes part of your ontology in one of two ways: you attach it to the node concept, or you use it in a definition. This example does both for a payment graph:
from relationalai.semantics import Integer, Modelfrom relationalai.semantics.reasoners.graph import Graph
m = Model("AccountInfluence")
Account = m.Concept("Account", identify_by={"id": Integer})Payment = m.Concept("Payment", identify_by={"id": Integer})Payment.payer = m.Property(f"{Payment} sent from {Account:payer}")Payment.payee = m.Property(f"{Payment} sent to {Account:payee}")Account.counterparties = m.Property(f"{Account} has {Integer:counterparties} counterparties")
16 collapsed lines
account_data = m.data([{"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}])m.define(Account.new(account_data.to_schema()))
payment_data = m.data([ {"id": 100, "payer_id": 1, "payee_id": 2}, {"id": 101, "payer_id": 2, "payee_id": 3}, {"id": 102, "payer_id": 3, "payee_id": 1}, {"id": 103, "payer_id": 1, "payee_id": 4},])m.define( Payment.new( id=payment_data.id, payer=Account.lookup(id=payment_data.payer_id), payee=Account.lookup(id=payment_data.payee_id), ))
graph = Graph(m, directed=True, weighted=False, aggregator="sum", node_concept=Account)m.define(graph.Edge.new(id=Payment.id, src=Payment.payer, dst=Payment.payee))
# Attach the result to the node concept.Account.pagerank = graph.pagerank()
# Use the result in a definition.degree = graph.degree()m.where(degree(Account, Integer)).define(Account.counterparties(Integer))node_concept=Accountmakes every account a node, so the graph reuses theACCOUNTview instead of creating one.Account.pagerank = graph.pagerank()attaches the PageRank result to the node concept. After deployment it’s thePAGERANKcolumn ofACCOUNT.- The definition at the end fills the
counterpartiesproperty fromgraph.degree(). After deployment it’s theCOUNTERPARTIEScolumn ofACCOUNT. - A result that you call but never attach or use, such as
graph.indegree()on its own line, is still computed and stored, but only in the internal schema.
- Only a per-node result, whose first field is the node concept, can be an attached property.
- A pair result, such as a similarity score, needs a definition into a standalone relationship with a
short_name, which names its view. - Attaching a result that runs on the logic reasoner moves the whole concept onto that reasoner. See A refresh that runs graph algorithms is slow.
Find the results in Snowflake
Section titled “Find the results in Snowflake”Use this table to see where each kind of result lands after rai models deploy and the first refresh:
| What you write | What appears | Where |
|---|---|---|
Account.pagerank = graph.pagerank() | A PAGERANK column | The ACCOUNT view in the public schema |
A definition that fills a property, such as Account.counterparties | A COUNTERPARTIES column | The ACCOUNT view in the public schema |
A definition that fills a standalone relationship with a short_name | A view named after the short_name | The public schema |
| A result you never attach or use | An object with the _INTERNAL_STORE_ prefix | The internal schema only |
After the refresh finishes, query the concept view to confirm both columns are populated:
SELECT ID, PAGERANK, COUNTERPARTIESFROM MY_DATABASE.MY_MODEL.ACCOUNTORDER BY ID;You should see one row per account.
PAGERANK holds a score for every account.
COUNTERPARTIES holds the number of other accounts each account exchanges payments with: 3, 2, 2, and 1 for accounts 1 through 4.
If a column is missing, see A graph algorithm result does not appear in the public schema.
If the columns exist but are empty, the refresh hasn’t finished yet.
See Monitor a deployed model.
Configure prescriptive reasoner settings
Section titled “Configure prescriptive reasoner settings”Which compute pools host prescriptive reasoners
Section titled “Which compute pools host prescriptive reasoners”Prescriptive reasoners run in app-managed compute pools. You do not create or manage these pools directly, but you do choose prescriptive reasoner sizes that map to them.
| Compute pool | Size | Supported cloud platforms | Used for |
|---|---|---|---|
RELATIONAL_AI_HIGHMEM_X64_S | HIGHMEM_X64_S | AWS, Azure | Small prescriptive workloads and the default prescriptive reasoner size. |
RELATIONAL_AI_HIGHMEM_X64_M | HIGHMEM_X64_M | AWS, Azure | Medium prescriptive workloads. |
How prescriptive reasoners are created
Section titled “How prescriptive reasoners are created”PyRel creates prescriptive reasoners automatically. Users can configure the name and size of the prescriptive reasoner that PyRel creates for them.
When a user runs a prescriptive workflow that needs a prescriptive reasoner:
- PyRel checks whether the configured reasoner exists and is
READY. - If it is
READY, PyRel sends the solve workload to that reasoner. - If it exists but is not
READY, PyRel resumes it and waits for it to becomeREADY. - If it does not exist, PyRel creates it using the configured size, or
HIGHMEM_X64_Sif no size is configured.
The default prescriptive reasoner settings are:
| Setting | Behavior |
|---|---|
| Size | Defaults to HIGHMEM_X64_S when PyRel creates a prescriptive reasoner and you do not set a different value. |
| Auto-suspend | Defaults to 60 minutes of inactivity for newly created reasoners when you do not set a different value. |
Prescriptive reasoners run decision-problem and optimization workloads.
Use reasoners.prescriptive.* when you want PyRel to select a specific prescriptive reasoner or apply a prescriptive query timeout.
Older docs may still call the same workload family solver reasoners, but the public config key is prescriptive.
Most users only need to choose the reasoner identity or set a timeout. Use this table to choose the right subsection:
| Subsection | Use it when |
|---|---|
| Name and size | You want PyRel to create or reuse a specific prescriptive reasoner. |
| Query timeout | You want prescriptive queries to stop after an explicit time limit. |
Set the prescriptive reasoner name and size
Section titled “Set the prescriptive reasoner name and size”Use reasoners.prescriptive.name and reasoners.prescriptive.size when you want PyRel to create a specific prescriptive reasoner or bind to one that already exists.
Set both fields when you want PyRel to create the reasoner if it is missing.
Select the tab for your preferred configuration method and follow the steps to set the name, size, and verify the configured values.
-
Set
reasoners.prescriptive.nameandreasoners.prescriptive.sizeinraiconfig.yaml:connections:# ...reasoners:prescriptive:name: team_prescriptivesize: HIGHMEM_X64_S -
Verify the configured values:
from relationalai.config import create_configfrom relationalai.semantics import Modelcfg = create_config()# Use the config.m = Model("MyModel", config=cfg)# Verify the configured values.print(m.config.reasoners.prescriptive.name)print(m.config.reasoners.prescriptive.size)
Set the values with ReasonersConfig and PrescriptiveReasonerConfig, or use a plain Python dict.
-
Set the values with typed config classes:
from relationalai.config import ReasonersConfig, create_configfrom relationalai.config.config_reasoners_fields import PrescriptiveReasonerConfigfrom relationalai.semantics import Modelcfg = create_config(reasoners=ReasonersConfig(prescriptive=PrescriptiveReasonerConfig(name="team_prescriptive",size="HIGHMEM_X64_S",)))# Use the config.m = Model("MyModel", config=cfg)# Verify the configured values.print(m.config.reasoners.prescriptive.name)print(m.config.reasoners.prescriptive.size) -
Alternatively, set the values with a dict:
from relationalai.config import create_configfrom relationalai.semantics import Modelcfg = create_config(reasoners={"prescriptive": {"name": "team_prescriptive","size": "HIGHMEM_X64_S",}})# Use the config.m = Model("MyModel", config=cfg)# Verify the configured values.print(m.config.reasoners.prescriptive.name)print(m.config.reasoners.prescriptive.size)
prescriptiveis the public config term, even if older docs say solver.HIGHMEM_X64_Sis the default prescriptive size.HIGHMEM_X64_Mis also supported for prescriptive workloads.- If the named prescriptive reasoner already exists, PyRel uses it as-is and does not resize it from config.
Set a query timeout for prescriptive workloads
Section titled “Set a query timeout for prescriptive workloads”Use reasoners.prescriptive.query_timeout_mins when you want an explicit limit for prescriptive queries.
Set it when you want PyRel to stop waiting for a long-running prescriptive workload after a fixed number of minutes.
Select the tab for your preferred configuration method and follow the steps to set query_timeout_mins and verify it.
-
Set
reasoners.prescriptive.query_timeout_minsinraiconfig.yaml:connections:# ...reasoners:prescriptive:query_timeout_mins: 30 -
Verify the configured value:
from relationalai.config import create_configfrom relationalai.semantics import Modelcfg = create_config()# Use the config.m = Model("MyModel", config=cfg)# Verify the configured value.print(m.config.reasoners.prescriptive.query_timeout_mins)
Set the value with ReasonersConfig and PrescriptiveReasonerConfig, or use a plain Python dict.
-
Set the value with typed config classes:
from relationalai.config import ReasonersConfig, create_configfrom relationalai.config.config_reasoners_fields import PrescriptiveReasonerConfigfrom relationalai.semantics import Modelcfg = create_config(reasoners=ReasonersConfig(prescriptive=PrescriptiveReasonerConfig(query_timeout_mins=30,)))# Use the config.m = Model("MyModel", config=cfg)# Verify the configured value.print(m.config.reasoners.prescriptive.query_timeout_mins) -
Alternatively, set the value with a dict:
from relationalai.config import create_configfrom relationalai.semantics import Modelcfg = create_config(reasoners={"prescriptive": {"query_timeout_mins": 30,}})# Use the config.m = Model("MyModel", config=cfg)# Verify the configured value.print(m.config.reasoners.prescriptive.query_timeout_mins)
Configure predictive reasoner settings
Section titled “Configure predictive reasoner settings”Which compute pools host predictive reasoners
Section titled “Which compute pools host predictive reasoners”Predictive reasoners run in app-managed compute pools. You do not create or manage these pools directly, but you do choose predictive reasoner sizes that map to them.
| Compute pool | Size | Supported cloud platforms | Used for |
|---|---|---|---|
RELATIONAL_AI_HIGHMEM_X64_S | HIGHMEM_X64_S | AWS, Azure | Small predictive workloads and the default predictive reasoner size. |
RELATIONAL_AI_HIGHMEM_X64_M | HIGHMEM_X64_M | AWS, Azure | Medium predictive workloads. |
RELATIONAL_AI_HIGHMEM_X64_L | HIGHMEM_X64_L | AWS only | Large CPU-based predictive workloads on AWS. |
RELATIONAL_AI_GPU_NV_S | GPU_NV_S | AWS only | GPU-backed predictive workloads on AWS. |
RELATIONAL_AI_GPU_NV_SM | GPU_NV_SM | Azure only | GPU-backed predictive workloads on Azure. |
The Native App also manages internal-only pools such as RELATIONAL_AI_ERP_COMPUTE_POOL and RELATIONAL_AI_COMPILE_CACHE_SPCS.
Those pools support app internals, not user-managed predictive reasoners.
How predictive reasoners are created
Section titled “How predictive reasoners are created”PyRel creates predictive reasoners automatically. Users can configure the name and size of the predictive reasoner that PyRel creates for them.
When a user runs a predictive workflow that needs a predictive reasoner:
- PyRel checks whether the configured reasoner exists and is
READY. - If it is
READY, PyRel sends the predictive workload to that reasoner. - If it exists but is not
READY, PyRel resumes it and waits for it to becomeREADY. - If it does not exist, PyRel creates it using the configured size, or
HIGHMEM_X64_Sif no size is configured.
The default predictive reasoner settings are:
| Setting | Behavior |
|---|---|
| Name | Defaults to the Snowflake username with dots replaced by underscores. |
| Size | Defaults to HIGHMEM_X64_S. |
| Auto-suspend | Defaults to 60 minutes of inactivity for newly created reasoners when you do not set a different value. |
Predictive reasoners run the compute behind PyRel predictive reasoning workflows.
Use reasoners.predictive.* when you want PyRel to select a specific predictive reasoner or apply a predictive query timeout.
This section covers reasoner-instance configuration only, not GNN feature, training, or model-architecture settings.
Most users only need to choose the reasoner identity or set a timeout. Use this table to choose the right subsection:
| Subsection | Use it when |
|---|---|
| Name and size | You want PyRel to create or reuse a specific predictive reasoner. |
| Query timeout | You want predictive queries to stop after an explicit time limit. |
Set the predictive reasoner name and size
Section titled “Set the predictive reasoner name and size”Use reasoners.predictive.name and reasoners.predictive.size when you want PyRel to create a specific predictive reasoner or bind to one that already exists.
Set both fields when you want PyRel to create the reasoner if it is missing.
Select the tab for your preferred configuration method and follow the steps to set the name, size, and verify the configured values.
-
Set
reasoners.predictive.nameandreasoners.predictive.sizeinraiconfig.yaml:connections:# ...reasoners:predictive:name: team_predictivesize: HIGHMEM_X64_M -
Verify the configured values:
from relationalai.config import create_configfrom relationalai.semantics import Modelcfg = create_config()# Use the config.m = Model("MyModel", config=cfg)# Verify the configured values.print(m.config.reasoners.predictive.name)print(m.config.reasoners.predictive.size)
Set the values with ReasonersConfig and ReasonerConfig, or use a plain Python dict.
-
Set the values with typed config classes:
from relationalai.config import ReasonerConfig, ReasonersConfig, create_configfrom relationalai.semantics import Modelcfg = create_config(reasoners=ReasonersConfig(predictive=ReasonerConfig(name="team_predictive",size="HIGHMEM_X64_M",)))# Use the config.m = Model("MyModel", config=cfg)# Verify the configured values.print(m.config.reasoners.predictive.name)print(m.config.reasoners.predictive.size) -
Alternatively, set the values with a dict:
from relationalai.config import create_configfrom relationalai.semantics import Modelcfg = create_config(reasoners={"predictive": {"name": "team_predictive","size": "HIGHMEM_X64_M",}})# Use the config.m = Model("MyModel", config=cfg)# Verify the configured values.print(m.config.reasoners.predictive.name)print(m.config.reasoners.predictive.size)
- If you omit
reasoners.predictive.name, PyRel defaults the predictive reasoner name to your Snowflake username with dots replaced by underscores. HIGHMEM_X64_Sis the default predictive size.HIGHMEM_X64_Mis supported on AWS and Azure.HIGHMEM_X64_LandGPU_NV_Sare AWS-only.GPU_NV_SMis Azure-only.- Predictive reasoners are created from config the first time a predictive workflow needs them.
Set a query timeout for predictive workloads
Section titled “Set a query timeout for predictive workloads”Use reasoners.predictive.query_timeout_mins when you want an explicit limit for predictive queries.
Set it when you want PyRel to stop waiting for a long-running predictive workload after a fixed number of minutes.
Select the tab for your preferred configuration method and follow the steps to set query_timeout_mins and verify it.
-
Set
reasoners.predictive.query_timeout_minsinraiconfig.yaml:connections:# ...reasoners:predictive:query_timeout_mins: 45 -
Verify the configured value:
from relationalai.config import create_configfrom relationalai.semantics import Modelcfg = create_config()# Use the config.m = Model("MyModel", config=cfg)# Verify the configured value.print(m.config.reasoners.predictive.query_timeout_mins)
Set the value with ReasonersConfig and ReasonerConfig, or use a plain Python dict.
-
Set the value with typed config classes:
from relationalai.config import ReasonerConfig, ReasonersConfig, create_configfrom relationalai.semantics import Modelcfg = create_config(reasoners=ReasonersConfig(predictive=ReasonerConfig(query_timeout_mins=45,)))# Use the config.m = Model("MyModel", config=cfg)# Verify the configured value.print(m.config.reasoners.predictive.query_timeout_mins) -
Alternatively, set the value with a dict:
from relationalai.config import create_configfrom relationalai.semantics import Modelcfg = create_config(reasoners={"predictive": {"query_timeout_mins": 45,}})# Use the config.m = Model("MyModel", config=cfg)# Verify the configured value.print(m.config.reasoners.predictive.query_timeout_mins)
Configure reasoner polling behavior
Section titled “Configure reasoner polling behavior”Polling settings control how often PyRel checks the status of a long-running reasoner operation. Most users should keep the defaults. Change them only if the default wait behavior is already a problem, for example if status updates feel too slow or you need to reduce polling noise.
Select the tab for your preferred configuration method and follow the steps to set the polling settings and verify them.
-
Set polling settings under
reasonersinraiconfig.yaml:connections:# ...reasoners:poll_initial_delay_s: 0.5poll_overhead_rate: 0.2poll_max_delay_s: 2.0 -
Verify the configured values:
from relationalai.config import create_configfrom relationalai.semantics import Modelcfg = create_config()# Use the config.m = Model("MyModel", config=cfg)# Verify the polling settings.print(m.config.reasoners.poll_initial_delay_s)print(m.config.reasoners.poll_overhead_rate)print(m.config.reasoners.poll_max_delay_s)
Set polling settings with ReasonersConfig or a plain Python dict.
-
Set the values with a typed config class:
from relationalai.config import ReasonersConfig, create_configfrom relationalai.semantics import Modelcfg = create_config(reasoners=ReasonersConfig(poll_initial_delay_s=0.1,poll_overhead_rate=0.25,poll_max_delay_s=5.0,))# Use the config.m = Model("MyModel", config=cfg)# Verify the configured values.print(m.config.reasoners.poll_initial_delay_s)print(m.config.reasoners.poll_overhead_rate)print(m.config.reasoners.poll_max_delay_s) -
Alternatively, set the values with a dict:
from relationalai.config import create_configfrom relationalai.semantics import Modelcfg = create_config(reasoners={"poll_initial_delay_s": 0.1,"poll_overhead_rate": 0.25,"poll_max_delay_s": 5.0,})# Use the config.m = Model("MyModel", config=cfg)# Verify the configured values.print(m.config.reasoners.poll_initial_delay_s)print(m.config.reasoners.poll_overhead_rate)print(m.config.reasoners.poll_max_delay_s)