|
7 | 7 | "source": [ |
8 | 8 | "# Creating Python Code Files for SAS Intelligent Decisioning\n", |
9 | 9 | "\n", |
10 | | - "This notebook demonstrates how to use the `CodeFile` class to upload Python code files formatted for SAS Intelligent Decisioning.\n", |
| 10 | + "This notebook demonstrates how to use the `CodeFile` class to upload Python code\n", |
| 11 | + "files that are properly formatted for use with SAS Intelligent Decisioning.\n", |
11 | 12 | "\n", |
12 | 13 | "## Overview\n", |
13 | 14 | "\n", |
| 15 | + "SAS Intelligent Decisioning requires Python code files to follow a specific format.\n", |
14 | 16 | "\n", |
15 | | - "SAS Intelligent Decisioning (ID) requires Python code files to follow a specific format for detailed specifications on Python code file format requirements for SAS Intelligent Decisioning, see the [Rules For Developing Python Code Files](https://go.documentation.sas.com/doc/en/edmcdc/v_063/edmug/n04vfc1flrz8jsn1o5jblnbgx6i3.htm#n0jrohir6wzvd0n11omfautducm3) documentation.\n", |
| 17 | + "Here is a high-level summary of the formatting requirements:\n", |
16 | 18 | "\n", |
17 | | - "A basic overview:\n", |
18 | 19 | "- An `execute` function is required\n", |
19 | | - "- An `Output:` docstring listing output variables as first line in the execute function\n", |
20 | | - "- A `DependentPackages:` docstring listing required packages at the top of the file including all non built-in packages needed\n", |
| 20 | + "- An `Output:` docstring listing output variables as the first line in the execute function\n", |
| 21 | + "- A `DependentPackages:` docstring listing required packages at the top of the file including packages that are needed but are not built-in\n", |
21 | 22 | "- Must return standard Python data types\n", |
22 | 23 | "\n", |
23 | 24 | "\n", |
24 | 25 | "The `CodeFile` class validates and uploads properly formatted Python code to SAS Viya.\n", |
25 | 26 | "\n", |
| 27 | + "For more information about formating requirements for Python code files, see the [Rules\n", |
| 28 | + "For Developing Python Code\n", |
| 29 | + "Files](https://documentation.sas.com/?cdcId=edmcdc&cdcVersion=default&docsetId=edmug&docsetTarget=n04vfc1flrz8jsn1o5jblnbgx6i3.htm#n0jrohir6wzvd0n11omfautducm3)\n", |
| 30 | + "in _SAS Intelligent Decisioning: User's Guide_.\n", |
| 31 | + "\n", |
26 | 32 | "## Prerequisites\n", |
27 | 33 | "\n", |
28 | | - "- A SAS Viya environment with Intelligent Decisioning\n", |
| 34 | + "- SAS Viya environment with SAS Intelligent Decisioning\n", |
29 | 35 | "- Appropriate permissions to create files in the target folder\n", |
30 | 36 | "- sasctl package installed\n", |
31 | | - "- Python code already formatted according to ID requirements" |
| 37 | + "- Python code already formatted according to SAS Intelligent Decisioning requirements" |
32 | 38 | ] |
33 | 39 | }, |
34 | 40 | { |
|
44 | 50 | "execution_count": null, |
45 | 51 | "id": "e27dcadc", |
46 | 52 | "metadata": {}, |
47 | | - "outputs": [ |
48 | | - { |
49 | | - "name": "stderr", |
50 | | - "output_type": "stream", |
51 | | - "text": [ |
52 | | - "/Users/sababa/Desktop/repos/python-sasctl/venv3.11/lib/python3.11/site-packages/urllib3/connectionpool.py:1097: InsecureRequestWarning: Unverified HTTPS request is being made to host 'base.ingress-nginx.sababa-dq1-m1.modelmanager.sashq-d.openstack.sas.com'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings\n", |
53 | | - " warnings.warn(\n" |
54 | | - ] |
55 | | - }, |
56 | | - { |
57 | | - "name": "stdout", |
58 | | - "output_type": "stream", |
59 | | - "text": [ |
60 | | - "Connected to https://base.ingress-nginx.sababa-dq1-m1.modelmanager.sashq-d.openstack.sas.com/\n", |
61 | | - "Folder already exists. HTTP Error 409: {\"version\":2,\"httpStatusCode\":409,\"errorCode\":11552,\"message\":\"An item named \\\"ID_python_files\\\" of type \\\"Folder\\\" already exists in the folder \\\"Public\\\".\",\"details\":[\"Existing member: \",\"/folders/folders/3789dfcd-a5a6-4836-85d9-beb5f812baf8\",\"Suggestion: ID_python_files (1)\",\"path: /folders/folders\",\"correlator: 58004f45-b0cb-4737-adb1-1edbfba2040c\"]}\n" |
62 | | - ] |
63 | | - } |
64 | | - ], |
| 53 | + "outputs": [], |
65 | 54 | "source": [ |
66 | 55 | "from sasctl import Session\n", |
67 | 56 | "from sasctl.pzmm import CodeFile\n", |
68 | 57 | "from sasctl.services import folders as folder_service\n", |
69 | 58 | "\n", |
70 | 59 | "\n", |
71 | | - "# Replace with your SAS Viya connection details\n", |
| 60 | + "# Replace with your SAS Viya connection information\n", |
72 | 61 | "HOST = 'your-viya-host.com'\n", |
73 | 62 | "USERNAME = 'your-username'\n", |
74 | 63 | "PASSWORD = 'your-password'\n", |
|
90 | 79 | "source": [ |
91 | 80 | "## Example 1: Simple Code File\n", |
92 | 81 | "\n", |
93 | | - "Let's start with a simple example that performs a basic calculation." |
| 82 | + "Here is a simple example that performs a basic calculation." |
94 | 83 | ] |
95 | 84 | }, |
96 | 85 | { |
97 | 86 | "cell_type": "code", |
98 | 87 | "execution_count": null, |
99 | 88 | "id": "fa33286d", |
100 | 89 | "metadata": {}, |
101 | | - "outputs": [ |
102 | | - { |
103 | | - "name": "stdout", |
104 | | - "output_type": "stream", |
105 | | - "text": [ |
106 | | - "File uploaded successfully!\n", |
107 | | - "File ID: 5169bfbe-4ba4-4998-b9c3-24228add86a7\n", |
108 | | - "File Name: simple_calculator\n" |
109 | | - ] |
110 | | - } |
111 | | - ], |
| 90 | + "outputs": [], |
112 | 91 | "source": [ |
113 | | - "# Define properly formatted ID Python code\n", |
| 92 | + "# Define properly formatted Python code\n", |
114 | 93 | "simple_code = \"\"\"\n", |
115 | 94 | "def execute(input_value):\n", |
116 | 95 | " '''Output: score, category'''\n", |
|
120 | 99 | " return score, category\n", |
121 | 100 | "\"\"\"\n", |
122 | 101 | "\n", |
123 | | - "# Upload the code file to Viya\n", |
| 102 | + "# Upload the code file to SAS Viya\n", |
124 | 103 | "file_obj = CodeFile.write_id_code_file(\n", |
125 | 104 | " code=simple_code,\n", |
126 | 105 | " file_name='simple_calculator.py',\n", |
127 | 106 | " folder='/Public/ID_python_files'\n", |
128 | 107 | ")\n", |
129 | 108 | "\n", |
130 | | - "print(f\"File uploaded successfully!\")\n", |
| 109 | + "print(f\"The file was uploaded successfully.\")\n", |
131 | 110 | "print(f\"File ID: {file_obj.id}\")\n", |
132 | 111 | "print(f\"File Name: {file_obj.name}\")" |
133 | 112 | ] |
|
139 | 118 | "source": [ |
140 | 119 | "## Example 2: Code File with API Call\n", |
141 | 120 | "\n", |
142 | | - "This example shows how to create a code file that makes an API call to retrieve data." |
| 121 | + "Here is an example of how to create a code file that makes an API call to retrieve data." |
143 | 122 | ] |
144 | 123 | }, |
145 | 124 | { |
146 | 125 | "cell_type": "code", |
147 | | - "execution_count": 11, |
| 126 | + "execution_count": null, |
148 | 127 | "id": "6608730a", |
149 | 128 | "metadata": {}, |
150 | | - "outputs": [ |
151 | | - { |
152 | | - "name": "stdout", |
153 | | - "output_type": "stream", |
154 | | - "text": [ |
155 | | - "File uploaded successfully!\n", |
156 | | - "File ID: 7484adcd-3121-4e13-b208-c7b1ef51e444\n", |
157 | | - "File Name: risk_score_api\n" |
158 | | - ] |
159 | | - } |
160 | | - ], |
| 129 | + "outputs": [], |
161 | 130 | "source": [ |
162 | 131 | "api_code = \"\"\"\n", |
163 | 132 | "'''DependentPackages: requests'''\n", |
|
188 | 157 | " folder='/Public/ID_python_files'\n", |
189 | 158 | ")\n", |
190 | 159 | "\n", |
191 | | - "print(f\"File uploaded successfully!\")\n", |
| 160 | + "print(f\"The file was uploaded successfully.\")\n", |
192 | 161 | "print(f\"File ID: {file_obj.id}\")\n", |
193 | | - "print(f\"File Name: {file_obj.name}\")" |
| 162 | + "print(f\"File name: {file_obj.name}\")" |
194 | 163 | ] |
195 | 164 | }, |
196 | 165 | { |
|
200 | 169 | "source": [ |
201 | 170 | "## Example 3: Code with Multiple Dependencies\n", |
202 | 171 | "\n", |
203 | | - "Specify multiple packages in the DependentPackages docstring." |
| 172 | + "Here is an example of specifying multiple packages in the `DependentPackages` docstring." |
204 | 173 | ] |
205 | 174 | }, |
206 | 175 | { |
207 | 176 | "cell_type": "code", |
208 | | - "execution_count": 12, |
| 177 | + "execution_count": null, |
209 | 178 | "id": "48f441ff", |
210 | 179 | "metadata": {}, |
211 | | - "outputs": [ |
212 | | - { |
213 | | - "name": "stdout", |
214 | | - "output_type": "stream", |
215 | | - "text": [ |
216 | | - "File uploaded successfully: data_processor\n" |
217 | | - ] |
218 | | - } |
219 | | - ], |
| 180 | + "outputs": [], |
220 | 181 | "source": [ |
221 | 182 | "data_processing_code = \"\"\"\n", |
222 | 183 | "'''DependentPackages: pandas, numpy'''\n", |
|
234 | 195 | " mean_value = float(np.mean(data['values']))\n", |
235 | 196 | " std_value = float(np.std(data['values']))\n", |
236 | 197 | " result = 'Pass' if mean_value > threshold else 'Fail'\n", |
237 | | - " \n", |
| 198 | + "\n", |
238 | 199 | " return mean_value, std_value, result\n", |
239 | 200 | "\"\"\"\n", |
240 | 201 | "\n", |
|
245 | 206 | " folder='/Public/ID_python_files'\n", |
246 | 207 | ")\n", |
247 | 208 | "\n", |
248 | | - "print(f\"File uploaded successfully: {file_obj.name}\")" |
| 209 | + "print(f\"This file was uploaded successfully: {file_obj.name}\")" |
249 | 210 | ] |
250 | 211 | }, |
251 | 212 | { |
|
255 | 216 | "source": [ |
256 | 217 | "## Example 4: Reading Code from a File\n", |
257 | 218 | "\n", |
258 | | - "You can also read Python code from an existing file." |
| 219 | + "Here is an example of reading Python code from an existing file." |
259 | 220 | ] |
260 | 221 | }, |
261 | 222 | { |
262 | 223 | "cell_type": "code", |
263 | 224 | "execution_count": null, |
264 | 225 | "id": "eb8ad79d", |
265 | 226 | "metadata": {}, |
266 | | - "outputs": [ |
267 | | - { |
268 | | - "name": "stdout", |
269 | | - "output_type": "stream", |
270 | | - "text": [ |
271 | | - "Uploaded code from file: credit_decision\n" |
272 | | - ] |
273 | | - } |
274 | | - ], |
| 227 | + "outputs": [], |
275 | 228 | "source": [ |
276 | 229 | "from pathlib import Path\n", |
277 | 230 | "\n", |
|
298 | 251 | "# Clean up\n", |
299 | 252 | "temp_code_file.unlink()\n", |
300 | 253 | "\n", |
301 | | - "print(f\"Uploaded code from file: {file_obj.name}\")" |
| 254 | + "print(f\"Code uploaded from file: {file_obj.name}\")" |
302 | 255 | ] |
303 | 256 | }, |
304 | 257 | { |
|
308 | 261 | "source": [ |
309 | 262 | "## Example 5: Code File with No Parameters\n", |
310 | 263 | "\n", |
311 | | - "You can also create code files that don't require input parameters." |
| 264 | + "Here is an example of creating code files that do not require input parameters." |
312 | 265 | ] |
313 | 266 | }, |
314 | 267 | { |
315 | 268 | "cell_type": "code", |
316 | 269 | "execution_count": null, |
317 | 270 | "id": "460f264f", |
318 | 271 | "metadata": {}, |
319 | | - "outputs": [ |
320 | | - { |
321 | | - "name": "stdout", |
322 | | - "output_type": "stream", |
323 | | - "text": [ |
324 | | - "WARNING: About to delete existing file: config_info.py\n", |
325 | | - "This may result in loss of sensitive data or configurations.\n", |
326 | | - "Deleted existing file: config_info.py\n", |
327 | | - "Configuration code file created: config_info\n" |
328 | | - ] |
329 | | - } |
330 | | - ], |
| 272 | + "outputs": [], |
331 | 273 | "source": [ |
332 | 274 | "from sasctl.services import files as file_service\n", |
333 | 275 | "from sasctl.services import folders as folder_service\n", |
|
341 | 283 | " current_date = datetime.datetime.now().strftime('%Y-%m-%d')\n", |
342 | 284 | " environment = 'production'\n", |
343 | 285 | " version = '1.0.0'\n", |
344 | | - " \n", |
| 286 | + "\n", |
345 | 287 | " return current_date, environment, version\n", |
346 | 288 | "\"\"\"\n", |
347 | 289 | "\n", |
348 | | - "# Check if file already exists and delete it\n", |
349 | | - "# WARNING: Deleting files may result in loss of important data or configurations.\n", |
| 290 | + "# Check if file already exists and delete it.\n", |
| 291 | + "# Warning: Deleting files might result in loss of important data or configurations.\n", |
350 | 292 | "# Ensure you have backups or that the file can be safely removed before proceeding.\n", |
351 | 293 | "\n", |
352 | 294 | "file_name = 'config_info.py'\n", |
|
361 | 303 | " params={\"filter\": file_filter}\n", |
362 | 304 | " )\n", |
363 | 305 | " if len(existing_file) > 0:\n", |
364 | | - " print(f\"WARNING: About to delete existing file: {file_name}\")\n", |
365 | | - " print(\"This may result in loss of sensitive data or configurations.\")\n", |
| 306 | + " print(f\"Warning: You are about to delete this file: {file_name}\")\n", |
| 307 | + " print(\"This action might result in loss of sensitive data or configurations.\")\n", |
366 | 308 | "\n", |
367 | 309 | " file_service.delete_file({\"id\": existing_file['uri'].split('/')[-1]})\n", |
368 | | - " print(f\"Deleted existing file: {file_name}\")\n", |
| 310 | + " print(f\"Deleted file: {file_name}\")\n", |
369 | 311 | "except Exception as e:\n", |
370 | | - " print(f\"No existing file found: {file_name} {e}\")\n", |
| 312 | + " print(f\"This file was not found: {file_name} {e}\")\n", |
371 | 313 | "\n", |
372 | 314 | "\n", |
373 | 315 | "file_obj = CodeFile.write_id_code_file(\n", |
|
386 | 328 | "source": [ |
387 | 329 | "## Example 6: Disable Validation\n", |
388 | 330 | "\n", |
389 | | - "You can skip pre-upload validation **Note:** The file will still be uploaded even if it has formatting errors - those errors will appear later when you try to use the file in a decision. You can view the codeFile in Intelligent Decisioning and validate it to check." |
| 331 | + "Here is an example of skipping pre-upload validation.\n", |
| 332 | + "\n", |
| 333 | + "**Note:** The file will still be uploaded even if it contains formatting errors.\n", |
| 334 | + "The errors appear later when you try to use the file in a decision. You can\n", |
| 335 | + "view the code file in SAS Intelligent Decisioning and validate it to check for errors." |
390 | 336 | ] |
391 | 337 | }, |
392 | 338 | { |
393 | 339 | "cell_type": "code", |
394 | 340 | "execution_count": null, |
395 | 341 | "id": "95855524", |
396 | 342 | "metadata": {}, |
397 | | - "outputs": [ |
398 | | - { |
399 | | - "name": "stdout", |
400 | | - "output_type": "stream", |
401 | | - "text": [ |
402 | | - "File uploaded without pre-validation: fast_calculator\n", |
403 | | - "Warning: If there are formatting errors, they will appear when you use the file in a decision.\n" |
404 | | - ] |
405 | | - } |
406 | | - ], |
| 343 | + "outputs": [], |
407 | 344 | "source": [ |
408 | 345 | "fast_code = \"\"\"\n", |
409 | 346 | "def execute(input_a, input_b):\n", |
|
413 | 350 | "\"\"\"\n", |
414 | 351 | "\n", |
415 | 352 | "# Skip pre-upload validation for faster upload\n", |
416 | | - "# File will still be created even if there are formatting errors\n", |
| 353 | + "# File is still created when there are formatting errors\n", |
417 | 354 | "file_obj = CodeFile.write_id_code_file(\n", |
418 | 355 | " code=fast_code,\n", |
419 | 356 | " file_name='fast_calculator.py',\n", |
|
437 | 374 | }, |
438 | 375 | { |
439 | 376 | "cell_type": "code", |
440 | | - "execution_count": 16, |
| 377 | + "execution_count": null, |
441 | 378 | "id": "4a1f6b08", |
442 | 379 | "metadata": {}, |
443 | | - "outputs": [ |
444 | | - { |
445 | | - "name": "stdout", |
446 | | - "output_type": "stream", |
447 | | - "text": [ |
448 | | - "Session closed\n" |
449 | | - ] |
450 | | - } |
451 | | - ], |
| 380 | + "outputs": [], |
452 | 381 | "source": [ |
453 | 382 | "# Close the session\n", |
454 | 383 | "sess.close()\n", |
|
462 | 391 | "source": [ |
463 | 392 | "## Additional Resources\n", |
464 | 393 | "\n", |
465 | | - "- [SAS Intelligent Decisioning Documentation](https://go.documentation.sas.com/doc/en/edmcdc/v_063/edmug/n04vfc1flrz8jsn1o5jblnbgx6i3.htm)\n", |
466 | | - "- [Rules For Developing Python Code Files](https://go.documentation.sas.com/doc/en/edmcdc/v_063/edmug/n04vfc1flrz8jsn1o5jblnbgx6i3.htm#n0jrohir6wzvd0n11omfautducm3)\n", |
| 394 | + "- [SAS Intelligent Decisioning Documentation](https://documentation.sas.com/?cdcId=edmcdc&cdcVersion=default&docsetId=edmug&docsetTarget=n04vfc1flrz8jsn1o5jblnbgx6i3.htm)\n", |
| 395 | + "- [Rules For Developing Python Code Files](https://documentation.sas.com/?cdcId=edmcdc&cdcVersion=default&docsetId=edmug&docsetTarget=n04vfc1flrz8jsn1o5jblnbgx6i3.htm#n0jrohir6wzvd0n11omfautducm3)\n", |
467 | 396 | "- [python-sasctl Documentation](https://sassoftware.github.io/python-sasctl/)" |
468 | 397 | ] |
469 | 398 | } |
|
0 commit comments