Test a script locally¶
A script runs on the platform in a sandbox started from one public image. You can pull that image and run your script in it on your own machine, without network access as on the platform, before you register a version. What runs there is what the platform runs: the same Python and Node.js, the same libraries at the same versions (What the sandbox image ships).
A local test checks your program. It does not test the argument schema, the limits of your key or the files a turn attaches; call the script directly for that once the version is registered.
What you need¶
- Docker, or another tool that runs OCI images.
- The release your platform runs. Every release publishes its sandbox image as
ghcr.io/artific-ai/artific-core/sandbox:<version>, such assandbox:1.42.0. The version is theinfo.versionyour deployment's/api/openapi.jsonreports (Versions). Pulling the image needs no sign-in.
IMAGE=ghcr.io/artific-ai/artific-core/sandbox:<version>
docker pull "$IMAGE"
When no image is published under that version, your platform runs a build ahead of its release,
as a test environment does. Ask your operator for the exact image,
ghcr.io/artific-ai/artific-core/sandbox@sha256:<digest>, and use that as IMAGE in the same way.
To check that you pulled the image your platform runs, compare its Python libraries with the
pypi entries GET /packages answers with approval: image. The listing also names pip itself,
which is the image's installer and not on that list:
docker run --rm "$IMAGE" python3 -m pip list --format=freeze
The image is built for Linux on x86-64. On a machine with another processor, such as a Mac with
Apple silicon, add --platform linux/amd64 to every docker command on this page.
Run the script¶
Run from the directory that holds your entrypoint. The command mounts that directory as
/workspace and runs the script there. On the platform a script runs in a directory of its own
below /workspace; relative paths to its own files work the same in both. Write only below
/workspace: the platform may make every other path read-only. The command gives the script what
a call gives it
(What the script receives): the arguments on standard
input and in the file ARTIFIC_ARGUMENTS names, and a directory for the files it returns.
echo '{"slides": ["Plan", "Budget"]}' > arguments.json
mkdir -p out
docker run --rm -i --network none \
-v "$PWD:/workspace" \
-e ARTIFIC_ARGUMENTS=/workspace/arguments.json \
-e ARTIFIC_OUTPUTS=/workspace/out \
"$IMAGE" python3 main.py < arguments.json
For a Node.js entrypoint, end the command with node index.js. The files the script wrote are in
out/, and what it printed on standard output and standard error is what the model reads
(What a call does). mkdir -p out keeps the files of an
earlier run; Core empties the directory before every call.
A script that reads a turn's attachments finds them under ARTIFIC_INPUTS, as
<file id>/<file name>. Put test files in inputs/<file id>/<file name> beside your entrypoint and
add -e ARTIFIC_INPUTS=/workspace/inputs to the command.
| Part of the command | Why |
|---|---|
--network none |
the sandbox has no network; a script that needs one fails here as it fails on the platform |
-v "$PWD:/workspace" |
the script runs in its own directory, as an ordinary user, not root, whose home is /workspace |
-i and < arguments.json |
the arguments arrive on standard input |
The image runs as user id 1000. On Linux, when your own user id is another one, the script cannot
write to the mounted directory; add --user "$(id -u):$(id -g)".
With packages you approved¶
A library that is not in the image reaches a script as an
approved package: a wheel or an npm tarball, installed in the sandbox
from the file, offline. Do the same locally with the files you would upload for approval, with every
dependency that is not in the image. Put the wheels in wheels/ and the tarballs in tarballs/
beside your entrypoint.
Python:
docker run --rm --network none -v "$PWD:/workspace" "$IMAGE" sh -c '
python3 -m pip install --no-index --no-deps --no-compile --no-cache-dir \
--disable-pip-version-check --quiet --target .packages/python ./wheels/*.whl &&
PYTHONPATH=.packages/python python3 main.py'
Node.js:
docker run --rm --network none -v "$PWD:/workspace" "$IMAGE" sh -c '
npm install --offline --ignore-scripts --no-bin-links --no-audit --no-fund --no-save \
--no-package-lock --cache /workspace/.packages/.npm-cache \
--prefix .packages/node ./tarballs/*.tgz &&
NODE_PATH=.packages/node/node_modules:/opt/artific/node/node_modules node index.js'
These are the install commands Core runs on a call, with the same options. --no-deps and
--offline mean nothing is resolved or fetched: a dependency you left out fails at the script's own import or require,
here as on the platform. Write ./tarballs/, with the leading ./; npm reads a bare
tarballs/name.tgz as a repository on GitHub. Add the -i, -e and < arguments.json parts of
Run the script when the script reads arguments.
A local test leaves files in your directory that are not the script's: arguments.json, out/,
inputs/, .packages/, and dot-directories libraries write to the home directory, such as
.cache/ and .config/. Register only the script's own files.
When a local test differs¶
| What you see | Cause |
|---|---|
ModuleNotFoundError or Cannot find module for a library on the reference page |
the image you pulled is not the one your platform runs; pull the tag of the release your platform runs |
| the same error for another library | it is not in the image: approve it and install it as above |
No matching distribution found or a wheel that is "not a supported wheel on this platform" |
the wheel is built for another platform or Python than the sandbox's (Runtimes) |
Permission denied writing a file |
your user id is not 1000; add --user "$(id -u):$(id -g)" |