PyRel is RelationalAI’s Python package for building semantic models.
In this guide you’ll create and configure a project, then learn PyRel’s core concepts through a simple model.
Finally, you’ll query the model to answer a business question.
Estimated time
20–30 minutes
Prerequisites
A Bash, zsh, or PowerShell terminal.
Python 3.10–3.14 to run the project. If Python is not installed, the uv setup in this guide can download it automatically.
Network access to install Python packages and connect to your Snowflake account.
Start by downloading the starter project and installing the Python packages it needs.
The project includes a simple model, a query, and CSV data that you’ll work through in this guide.
You can install the required Python packages with uv or pip.
If you don’t have a preference, choose uv for fewer setup commands.
Your selection applies to commands throughout this guide:
Installs pandas to read the starter project’s CSV files.
Stores the project’s packages in .venv, separate from other Python projects.
Run the remaining commands in this guide from the supplier-disruption folder.
You’ll configure the Snowflake connection in the next section.
What if uv can’t find or download a supported Python version?
uv normally downloads a compatible Python version when you run uv sync. If it does not, install Python 3.13 through uv, then try again:
Terminal window
uvpythoninstall3.13
uvsync
If Python cannot be downloaded, check your network connection. Your organization may also disable Python downloads through uv. In that case, install Python 3.10 through 3.14 using your organization’s standard method.
What if the terminal can’t find uv after installation?
Close and reopen your terminal, then run:
Terminal window
uv--version
If the terminal still cannot find uv, repeat the uv installation instructions for your operating system. Follow any message from the installer about updating your PATH, then open another terminal.
Run these commands to check that PyRel and the rai command were installed:
Open a terminal and run these commands to extract the starter project, enter its folder, create a virtual environment, and install the required packages.
If you saved the ZIP file outside Downloads, update its path in the first command:
These results verify the installation only.
You’ll test the Snowflake connection in the next section.
What if one of these commands fails?
Make sure your terminal is in the supplier-disruption folder. Activate the virtual environment again using the command from the previous step, then reinstall the packages:
RelationalAI Agent Skills give coding agents guided workflows for PyRel modeling, reasoning, deployment, and operations. You can complete this guide without a coding agent, but if you want agent assistance in later steps, execute this prompt with your agent to get started:
Read https://docs.relational.ai/agent-setup/prompt.md and follow the instructions to set up RelationalAI Agent Skills.
After installation, start a new agent session so the skills are available. For client-specific installation and update instructions, see Install skill files.
PyRel reads your connection settings from raiconfig.yaml in your project folder.
If your administrator sent you an invitation link with all required settings, the configuration below is ready to save.
Otherwise, the builder expands the fields you need to complete.
You can always expand Review or edit configuration details to inspect or change settings.
Then save the file, set any required credentials, and verify the connection.
Configure with a coding agent
If you installed RelationalAI Agent Skills, paste this prompt into the new agent session. The prompt updates when you change validated, non-secret settings in the form.
Prompt
/rai-setup Configure this starter project. Ask me one question at a time for my account, warehouse, username, and the authentication method my administrator told me to use. Ask for additional non-secret settings only when that authentication method requires them. Ask about deployment settings only if I say my administrator supplied them. If I do not know which authentication method to use, explain the supported methods and tell me what to confirm with my administrator instead of guessing.
Do not ask me to paste credentials into chat, and do not print, write, or commit credentials. If authentication requires a credential or browser action, tell me how to complete that step locally. Create or update `raiconfig.yaml` in the project root, but do not change other project files. Run `rai connect` from this project to validate the connection. If it fails, explain the error and help me fix it; do not report success unless the command succeeds.
Whether you use the prompt or the form, review the generated configuration and confirm that rai connect succeeds before continuing.
The starter project models a manufacturer that buys parts from several suppliers. Its completed semantic model connects suppliers to the parts they provide and the products that require those parts. You’ll use the included CSV data to answer a hypothetical question: If Northstar Components can’t deliver, which products depend on parts it supplies?
You’ve installed PyRel and verified that the project can connect to Snowflake. Next, you’ll use PyRel to query the semantic model and find which products depend on parts supplied by Northstar Components.
Run and explain with a coding agent
If you installed RelationalAI Agent Skills, paste this prompt into the new agent session. The agent will not edit the starter files. If deployment is configured, it must ask before creating or removing Snowflake objects.
Without deployment
Prompt
/rai-pyrel Read these sections of the Start building with PyRel guide before acting:
Follow the guide’s **Without deployment** path for this supplied starter project. Do not edit files or install or upgrade packages. Use the project’s existing Python environment, run the documented query, and compare its output with the guide’s expected output.
Stop if the command fails or the output does not match. Use the guide’s troubleshooting steps, explain the problem, and help me fix it; do not continue or report success as though the check succeeded. After it succeeds, use the project files and the guide’s model walkthrough to briefly explain how the model, source mappings, relationships, and query produce the result. Preserve the guide’s limits on what the result establishes.
With deployment
Prompt
/rai-pyrel Read these sections of the Start building with PyRel guide before acting:
Follow the guide’s **With deployment** path for this supplied starter project. Do not edit files, install or upgrade packages, or display configuration or credential values. Use the project’s existing Python environment.
Before deployment, use the guide to explain which Snowflake objects and refresh tasks the command creates, then ask for my explicit confirmation. If I confirm, run the documented deployment command. Continue only if deployment succeeds.
Run the documented query and compare its output with the guide’s expected output. Stop if the command fails or the output does not match. Use the guide’s troubleshooting steps, explain the problem, and help me fix it; do not continue or report success as though the check succeeded.
After a successful query, run the guide’s cleanup preview without `--force` and tell me which deployment and metadata schemas it names. Ask for my explicit confirmation before forced teardown. If I do not confirm, leave the deployment in place and tell me that it remains. Afterward, use the project files and the guide’s model walkthrough to briefly explain how the model, source mappings, relationships, and query produce the result. Preserve the guide’s limits on what the result establishes.
Compare the command output with the expected output below before continuing.
Use the same terminal where you ran rai connect in Verify the connection, make sure you're in the supplier-disruption folder, and then run:
Without deployment
uv
Terminal window
uvrunpythonfind_affected_products.py
pip
Terminal window
pythonfind_affected_products.py
Output
product part
0 Cold-chain tracker Control board
1 Cold-chain tracker Temperature sensor
2 Factory gateway Control board
3 Smart thermostat Temperature sensor
The rows may appear in a different order.
If you see this output, PyRel successfully connected to Snowflake, loaded the semantic model, ran the query, and returned results. You can pause here, or read on to learn how the starter project's semantic model works.
What if Python can’t find the model module?
If you see ModuleNotFoundError: No module named 'model', run the query command from your project folder. This is the folder containing pyproject.toml and the model folder.
What if authentication fails when I run the query?
Follow the troubleshooting guidance in Verify the connection. Once the connection check succeeds, retry the command.
What if my results don’t match the example output?
If you see different combinations of products and parts, compare your project files with the code in Understand the code, or download a fresh starter project.
With deployment
Your raiconfig.yaml includes deployment settings, so deploy the model, run the query, and clean up the deployment.
Deploy the model
First, deploy the model from your project folder using the rai models deploy CLI command:
uv
Terminal window
uvrunraimodelsdeploy--pathmodel--wait
pip
Terminal window
raimodelsdeploy--pathmodel--wait
What this command does
--path model loads the model from the model folder.
PyRel deploys the model to the schema set by deployment.schema in raiconfig.yaml.
PyRel creates output objects in Snowflake and fills them with the model's initial results.
Snowflake tasks refresh those outputs on configurable schedules to incorporate changes in your source data.
--wait keeps the command running until the initial data load finishes.
What if deployment fails with a schema or permissions error?
Run uv run rai config explain (pip: rai config explain) to check the names of the deployment and metadata schemas. Ask your administrator to confirm that your role has the required permissions on both schemas.
What if authentication fails when I deploy the model?
Follow the troubleshooting guidance in Verify the connection. Once the connection check succeeds, retry the command.
Run the query
After deployment succeeds, run the query:
uv
Terminal window
uvrunpythonfind_affected_products.py
pip
Terminal window
pythonfind_affected_products.py
Output
product part
0 Cold-chain tracker Control board
1 Cold-chain tracker Temperature sensor
2 Factory gateway Control board
3 Smart thermostat Temperature sensor
The rows may appear in a different order.
If you see this output, PyRel successfully connected to Snowflake, loaded the semantic model, ran the query, and returned results. You can pause here, or read on to learn how the starter project's semantic model works.
What if Python can’t find the model module?
If you see ModuleNotFoundError: No module named 'model', run the query command from your project folder. This is the folder containing pyproject.toml and the model folder.
What if authentication fails when I run the query?
Follow the troubleshooting guidance in Verify the connection. Once the connection check succeeds, retry the command.
What if my results don’t match the example output?
If you see different combinations of products and parts, compare your project files with the code in Understand the code, or download a fresh starter project.
Clean up the deployment
When you’re done with the example, remove the deployed model from Snowflake. This deletes the objects RelationalAI created in your deployment and metadata schemas, but keeps both schemas.
Preview the cleanup:
uv
Terminal window
uvrunraimodelsteardown
pip
Terminal window
raimodelsteardown
Review the preview and confirm that it names the deployment and metadata schemas you used for this example.
Then run the following command to remove the model:
Now that you’ve run the starter project, you can explore how PyRel builds the semantic model used to answer its question: Which products depend on parts supplied by Northstar Components?
With PyRel, you create a semantic model in Python. A semantic model adds business meaning to your source data by representing the things your business cares about and how they relate.
Three fundamental building blocks define the model’s structure:
Concepts represent kinds of things, such as suppliers, parts, and products.
Properties describe those things, such as a supplier’s name.
Relationships connect them. In this model, suppliers supply parts and products require parts.
Source mappings connect source rows to that structure, turning the CSV rows into entity and relationship facts. Together, the declarations and source mappings create a semantic model that PyRel can query.
The model explorer below shows concepts as labeled blocks and relationships as labeled paths. Select a block or path to see its properties, connections, or fields. Expand Preview source data when you want to inspect the supporting CSV rows.
Select a concept or relationship to see what it means and where its facts come from.
Supplier disruption
Three concepts describe the business objects. Two relationships connect them: a Supplier supplies a Part, and a Product requires a Part.
This eight-step walkthrough connects the semantic model you just explored to the code that makes it all work. See how the project defines the model, turns CSV rows into facts, and builds the query. Hover over dotted-underlined text to highlight the corresponding code. You can also focus or tap it.
1
Explore the project structure
Each part of the project has one job:
data/ holds CSV facts about suppliers, parts, products, and their connections.
model/schema.py declares the model; model/source.py maps CSV rows to facts; model/__init__.py exposes the assembled model.
find_affected_products.py finds products that depend on parts supplied by Northstar Components.
pyproject.toml declares which Python version and packages the project requires.
raiconfig.yaml holds your local connection settings. You created it earlier; it is not included in the download.
Directorysupplier-disruption/
Directorymodel/
schema.py
source.py
__init__.py
Directorydata/
suppliers.csv
parts.csv
products.csv
supplier_parts.csv
product_parts.csv
find_affected_products.py
pyproject.toml
raiconfig.yaml local only, not included in the download
2
Create the model
Model("SupplierDisruption") creates a Model object named SupplierDisruption and stores it in model for the rest of the project to build and query.
Supplier, Part, and Product each represent one kind of thing. identify_by names the property that identifies each entity, so rows with the same supplier_id, for example, refer to the same supplier.
Each concept gets a name property so queries can return readable labels. model.Property() defines it from a reading, where f-string placeholders become typed PyRel fields: {Supplier} infers the field name supplier, while {String:name} explicitly names the string field name.
Supplier.name = model.Property(f"{Supplier} has {String:name}")
model/schema.py (lines 9)
Part.name = model.Property(f"{Part} has {String:name}")
model/schema.py (lines 12)
Product.name = model.Property(f"{Product} has {String:name}")
5
Connect concepts with relationships
Supplier.supplies relates suppliers to parts, and Product.requires relates products to parts. Each relationship can connect one entity to many others, and its reading expresses the connection in natural language.
read_csv() loads each entity file into a pandas DataFrame, and model.data() exposes its rows to PyRel. For each row, Supplier.new(), Part.new(), or Product.new() finds or creates the entity by ID; .name() assigns its readable name, and model.define() adds both facts to the model.
Use Snowflake data
For Snowflake tables, use Model.Table() instead. This starter uses model.data() so it can run from local CSV files.
model/source.py
8 collapsed lines
from pathlib import Path
from pandas import read_csv
from .schema import Part, Product, Supplier, model
supplier_parts.csv and product_parts.csv store pairs of entity IDs. For each row, Supplier.lookup() or Product.lookup() finds one entity, Part.lookup() finds the other, and Supplier.supplies or Product.requires connects them. model.define() adds the relationship as a fact.
model/source.py
26 collapsed lines
from pathlib import Path
from pandas import read_csv
from .schema import Part, Product, Supplier, model
The query starts with Northstar Components, follows Supplier.supplies to each part, then Product.requires to each product that uses it.
Each .ref() creates a variable that can match an entity.
model.where() specifies how the supplier, parts, and products must be related.
.select() chooses the names to return, and .inspect() runs the query and prints the matches.
Each product that depends on a part supplied by Northstar Components.
The part supplied by Northstar that each product depends on.
What this result does not show
Whether production will stop.
Which supplier should replace Northstar.
Answers to those questions, which RelationalAI can provide with a richer model that includes current inventory, lead times, and alternative suppliers, together with the appropriate reasoning.
Nice work!
You set up a PyRel project and used a semantic model to answer a business question. You're ready to start building with your own data.