Tutorials

Text-to-CAD Tutorial

This tutorial will walk you through how to use our Text-to-CAD API endpoint from your own Python script. Text-to-CAD is a powerful tool that allows you to generate CAD models from text prompts. We recommend trying out our Text-to-CAD UI before starting this tutorial.

Objectives

Our objective is to use the API to:

  • Give a text prompt
  • Receive a CAD file in response
  • Save the CAD file to our local machine

Let's get started

Before you can use our API, you must have an API key. When you send an API command, you will pass this API key along with your command, so that we can verify it's you.

You will see your API token below if you are signed in and have already generated one. If all you see is "Generate your first API token," then you currently do not have a token. Follow the steps below to generate an API key:

  • Create an account. If you haven't already, you can create an account here
  • Sign in. Once you've signed up for an account, make sure you are signed in.
  • Generate an API key. You can either go into your account settings to generate an API key, or you can press the button below and we will take care of it for you!

Python setup

We will be using Zoo's KittyCAD Python package for this tutorial. If you don't have Python installed, you can download it here.

In your terminal, use the command pip install kittycad to install the kittycad package in your Python environment.

Imports

Let's start building the script. Create a new file with the .py extension and open it in your preferred editor.

First, we need to import the necessary libraries. You can reference our AI API documentation here.

There are two API calls that we are going to make.

  1. Generate a CAD model from text
  2. List Text-to-CAD models you've generated

Import the libraries necessary to create and retrieve models with Text-to-CAD:

import time

from kittycad.api.ml import create_text_to_cad, get_text_to_cad_model_for_user
from kittycad.client import ClientFromEnv
from kittycad.models import (
    ApiCallStatus,
    Error,
    FileExportFormat,
    TextToCad,
    TextToCadCreateBody,
)

Initialize the client

To use the API, we need to instantiate a client with your API key. We do this by calling ClientFromEnv(). This will look for the ZOO_API_TOKEN environment variable and use that as the API key. Make sure that you have set this environment variable before running the script.

# Create our client.
client = ClientFromEnv()

Submit the prompt

We will use the create_text_to_cad.sync() function to submit our prompt. This function takes in the client, the output format, and the body of the request. Text-to-CAD will always return a GLTF and STEP file by default, but you can specify any other supported file format here. The body of the request is a TextToCadCreateBody object. This object takes in the prompt that you want to use to generate the CAD model. In the example below, we wrote "Design a gear with 40 teeth" as the prompt, but you can replace this with whatever you would like.

# Prompt the API to generate a 3D model from text.
response = create_text_to_cad.sync(
    client=client,
    output_format=FileExportFormat.STEP,
    body=TextToCadCreateBody(
        prompt="Design a gear with 40 teeth",
    ),
)

if isinstance(response, Error) or response is None:
    print(f"Error: {response}")
    exit(1)

Checking the status

Now that we have made the API call, we need to check the status of the model. We can do this by using the get_text_to_cad_model_for_user.sync() function. This function takes in the client and the ID of the request that we want to check the status. keep in mind that more complex prompts will take more time to process. In this example, we check the status every 5 seconds until the original request is complete.

result: TextToCad = response

# Polling to check if the task is complete
while result.completed_at is None:
    # Wait for 5 seconds before checking again
    time.sleep(5)

    # Check the status of the task
    response = get_text_to_cad_model_for_user.sync(
        client=client,
        id=result.id,
    )

    if isinstance(response, Error) or response is None:
        print(f"Error: {response}")
        exit(1)

    result = response

Save the final result

Once our request is complete, we can check the status one more time to see if it was successful. Then, we can save the generated CAD model to our local machine.

Sometimes, Text-to-CAD will fail to generate a model. In this case, we recommend adjusting your prompt and trying again. For example, you may recieve the error message 400 / Bad Request / The prompt must clearly describe a CAD model. If you receive this error, try to be more specific with your prompt.

In our script, if Text-to-CAD returns an error, we want to print the error message. If it succeeds, then we print the available file formats of the generated CAD model.

In this example, we will save the STEP file to our file system. The API returns a base64 encoded string, so we decode it to plain text and save it as a .step file.

if result.status == ApiCallStatus.FAILED:
    # Print out the error message
    print(f"Text-to-CAD failed: {result.error}")

elif result.status == ApiCallStatus.COMPLETED:
    if result.outputs is None:
        print("Text-to-CAD completed but returned no files.")
        exit(0)

    # Print out the names of the generated files
    print(f"Text-to-CAD completed and returned {len(result.outputs)} files:")
    for name in result.outputs:
        print(f"  * {name}")

    # Save the STEP data as text-to-cad-output.step
    final_result = result.outputs["source.step"]
    with open("text-to-cad-output.step", "w", encoding="utf-8") as output_file:
        output_file.write(final_result.decode("utf-8"))
        print(f"Saved output to {output_file.name}")

Feel free to reference or copy the full script below:

import time

from kittycad.api.ml import create_text_to_cad, get_text_to_cad_model_for_user
from kittycad.client import ClientFromEnv
from kittycad.models import (
    ApiCallStatus,
    Error,
    FileExportFormat,
    TextToCad,
    TextToCadCreateBody,
)

# Create our client.
client = ClientFromEnv()

# Prompt the API to generate a 3D model from text.
response = create_text_to_cad.sync(
    client=client,
    output_format=FileExportFormat.STEP,
    body=TextToCadCreateBody(
        prompt="Design a gear with 40 teeth",
    ),
)

if isinstance(response, Error) or response is None:
    print(f"Error: {response}")
    exit(1)

result: TextToCad = response

# Polling to check if the task is complete
while result.completed_at is None:
    # Wait for 5 seconds before checking again
    time.sleep(5)

    # Check the status of the task
    response = get_text_to_cad_model_for_user.sync(
        client=client,
        id=result.id,
    )

    if isinstance(response, Error) or response is None:
        print(f"Error: {response}")
        exit(1)

    result = response

if result.status == ApiCallStatus.FAILED:
    # Print out the error message
    print(f"Text-to-CAD failed: {result.error}")

elif result.status == ApiCallStatus.COMPLETED:
    if result.outputs is None:
        print("Text-to-CAD completed but returned no files.")
        exit(0)

    # Print out the names of the generated files
    print(f"Text-to-CAD completed and returned {len(result.outputs)} files:")
    for name in result.outputs:
        print(f"  * {name}")

    # Save the STEP data as text-to-cad-output.step
    final_result = result.outputs["source.step"]
    with open("text-to-cad-output.step", "w", encoding="utf-8") as output_file:
        output_file.write(final_result.decode("utf-8"))
        print(f"Saved output to {output_file.name}")
Found a typo?