mage-ai 0.9.8__py3-none-any.whl → 0.9.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of mage-ai might be problematic. Click here for more details.
- mage_ai/ai/constants.py +1 -0
- mage_ai/ai/generator.py +6 -0
- mage_ai/ai/{gen_doc_for_pipeline.py → generator_cmds.py} +5 -0
- mage_ai/ai/llm_pipeline_wizard.py +108 -3
- mage_ai/api/policies/BlockPolicy.py +1 -0
- mage_ai/api/policies/BlockTemplatePolicy.py +9 -0
- mage_ai/api/policies/LlmPolicy.py +3 -2
- mage_ai/api/policies/OauthAccessTokenPolicy.py +31 -0
- mage_ai/api/policies/PipelinePolicy.py +1 -0
- mage_ai/api/policies/ProjectPolicy.py +9 -0
- mage_ai/api/policies/SearchResultPolicy.py +32 -0
- mage_ai/api/policies/VariablePolicy.py +8 -0
- mage_ai/api/presenters/BlockTemplatePresenter.py +1 -0
- mage_ai/api/presenters/OauthAccessTokenPresenter.py +9 -0
- mage_ai/api/presenters/ProjectPresenter.py +2 -0
- mage_ai/api/presenters/SearchResultPresenter.py +73 -0
- mage_ai/api/resources/BlockResource.py +43 -4
- mage_ai/api/resources/BlockTemplateResource.py +15 -2
- mage_ai/api/resources/CustomTemplateResource.py +15 -3
- mage_ai/api/resources/FileContentResource.py +8 -1
- mage_ai/api/resources/FileResource.py +22 -2
- mage_ai/api/resources/OauthAccessTokenResource.py +24 -0
- mage_ai/api/resources/PipelineResource.py +70 -2
- mage_ai/api/resources/ProjectResource.py +15 -1
- mage_ai/api/resources/SearchResultResource.py +68 -0
- mage_ai/api/resources/VariableResource.py +25 -14
- mage_ai/cache/base.py +3 -0
- mage_ai/cache/block_action_object/__init__.py +282 -0
- mage_ai/cache/block_action_object/constants.py +4 -0
- mage_ai/cache/constants.py +1 -0
- mage_ai/data_integrations/destinations/constants.py +2 -0
- mage_ai/data_preparation/executors/k8s_pipeline_executor.py +1 -1
- mage_ai/data_preparation/models/block/__init__.py +20 -1
- mage_ai/data_preparation/models/block/dbt/utils/__init__.py +1 -0
- mage_ai/data_preparation/models/custom_templates/custom_block_template.py +8 -3
- mage_ai/data_preparation/models/custom_templates/utils.py +6 -3
- mage_ai/data_preparation/models/file.py +3 -0
- mage_ai/data_preparation/models/pipeline.py +10 -1
- mage_ai/data_preparation/models/{project.py → project/__init__.py} +17 -0
- mage_ai/data_preparation/models/project/constants.py +5 -0
- mage_ai/data_preparation/repo_manager.py +9 -6
- mage_ai/data_preparation/templates/constants.py +478 -1
- mage_ai/data_preparation/templates/template.py +9 -1
- mage_ai/orchestration/db/__init__.py +25 -0
- mage_ai/orchestration/pipeline_scheduler.py +23 -0
- mage_ai/server/constants.py +1 -1
- mage_ai/server/frontend_dist/404.html +2 -2
- mage_ai/server/frontend_dist/404.html.html +2 -2
- mage_ai/server/frontend_dist/_next/static/OwvTROmputQCA1Z9HEGDv/_buildManifest.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/{1005-ce36fe7ed460d006.js → 1005-16c1a6678de5311e.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/1424-e22139f33196c5c1.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/1484-a76b2c31e4808379.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/2485-b569baad92049d6b.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/{2786-d8b593e5d7c42665.js → 2786-acce6ea0d9b4898e.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/3654-573457b62efff6e2.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/3881-0eb04f7f7a244347.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/{4317-b112fe7bb532b998.js → 4317-3fe63fc9401685d6.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/{4822-52d9d661b6bd1ae9.js → 4822-045cc7cdd7c95163.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/{547-14029bdacc0ed267.js → 547-4ad2cdae967055b6.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/6299-cf188c1b7a1bc33c.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/{7815-6dc55b5fd5d1f48a.js → 7815-fbd99c8f259d9e8b.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/{8312-cdc4d6c3b9f53099.js → 8312-c88a3b1012e5448b.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/{8952-492bf0e29d215ddd.js → 8952-e94a7334fcd5c68b.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/9055-d0d25298cb5f4e45.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{_app-c7557dc9e725825e.js → _app-fa38a24707c76411.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/files-b9dac983c75798f2.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/{settings-17bb362b9683079c.js → settings-453aaa7bf78f8101.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/users/{[user]-bfa53c0ee79920a0.js → [user]-3b502aa6d1a04cad.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/users/{new-2f7e6bf8e2a37380.js → new-dd41d718cbb5990c.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/users-ec748f838b7b8fad.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage-bcc24120f5911f76.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{overview-8ffbc4b0e8a43266.js → overview-6f20b9e9cbec91d6.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/backfills/{[...slug]-373f6b8c9161e819.js → [...slug]-55212dfc15881ef2.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/{backfills-226bf0c5c1bfe004.js → backfills-6b4a82cd0516e121.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-0705c99df236ec8a.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/{logs-4ade07836fd577c9.js → logs-c294f5d74bd2d50f.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/{monitors-fd9eb711e89425e9.js → monitors-1b9e4abc54842cdf.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/{runs-027666ed18d3151e.js → runs-17ebe87e94242ae5.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-48b60ca236a26818.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/{syncs-de58e6b91e5e4552.js → syncs-5153f4665aaf8b17.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/triggers/{[...slug]-432843576e1ed09e.js → [...slug]-1306e85191f6b47c.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/{triggers-ae31b1d0d8a4634d.js → triggers-2e731d343a26d46a.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines-0fab737dbc9074fc.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-b2354688508b0755.js +1 -0
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/{users-a4f01b5c429757cc.js → users-6522c963087f18e8.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{sign-in-1140f8ee7e89381a.js → sign-in-7dcd1257ca9660bb.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/templates/{[...slug]-f59b3f04c5a49351.js → [...slug]-78a07e7fe8973811.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/{templates-dbb209ce131390a9.js → templates-19df643f52679d5a.js} +1 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-a1cf445565b68809.js +1 -0
- mage_ai/server/frontend_dist/files.html +2 -2
- mage_ai/server/frontend_dist/index.html +2 -2
- mage_ai/server/frontend_dist/manage/settings.html +2 -2
- mage_ai/server/frontend_dist/manage/users/[user].html +2 -2
- mage_ai/server/frontend_dist/manage/users/new.html +2 -2
- mage_ai/server/frontend_dist/manage/users.html +2 -2
- mage_ai/server/frontend_dist/manage.html +2 -2
- mage_ai/server/frontend_dist/overview.html +2 -2
- mage_ai/server/frontend_dist/pipeline-runs.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills/[...slug].html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/backfills.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/edit.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/logs.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runs.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors/block-runtime.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/monitors.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/runs/[run].html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/runs.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/settings.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/syncs.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers/[...slug].html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline]/triggers.html +2 -2
- mage_ai/server/frontend_dist/pipelines/[pipeline].html +2 -2
- mage_ai/server/frontend_dist/pipelines.html +2 -2
- mage_ai/server/frontend_dist/settings/account/profile.html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/preferences.html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/sync-data.html +2 -2
- mage_ai/server/frontend_dist/settings/workspace/users.html +2 -2
- mage_ai/server/frontend_dist/settings.html +2 -2
- mage_ai/server/frontend_dist/sign-in.html +16 -16
- mage_ai/server/frontend_dist/templates/[...slug].html +2 -2
- mage_ai/server/frontend_dist/templates.html +2 -2
- mage_ai/server/frontend_dist/terminal.html +2 -2
- mage_ai/server/frontend_dist/test.html +2 -2
- mage_ai/server/frontend_dist/triggers.html +2 -2
- mage_ai/server/frontend_dist/version-control.html +2 -2
- mage_ai/server/server.py +5 -0
- mage_ai/services/search/__init__.py +0 -0
- mage_ai/services/search/block_action_objects.py +33 -0
- mage_ai/services/search/constants.py +1 -0
- mage_ai/shared/array.py +7 -0
- mage_ai/shared/parsers.py +11 -2
- mage_ai/tests/shared/test_parsers.py +73 -0
- mage_ai/usage_statistics/constants.py +1 -0
- mage_ai/usage_statistics/logger.py +19 -1
- {mage_ai-0.9.8.dist-info → mage_ai-0.9.9.dist-info}/METADATA +9 -7
- {mage_ai-0.9.8.dist-info → mage_ai-0.9.9.dist-info}/RECORD +142 -129
- mage_ai/server/frontend_dist/_next/static/RcIgkp9pBXE1Rb4tOGR1L/_buildManifest.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/1424-de97c5aa0477894b.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/1484-c9d6bc33227070dd.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/2485-86c97f516c1abb9f.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/3215-c2f5f19b650f9a50.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/3654-bff4740b63cf280c.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/3881-7f121dbbe6e273cd.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/6299-97f283be01adf6a8.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/files-0df5a20d6f1aa606.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage/users-1f6cb7656299cbd1.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/manage-4894eabb442a039c.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/edit-a9bd86bee73b5762.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines/[pipeline]/settings-cf51793c2112915c.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/pipelines-f1131ffe0d2a4a06.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/settings/workspace/preferences-170943ca00445486.js +0 -1
- mage_ai/server/frontend_dist/_next/static/chunks/pages/version-control-2ecda1f1437013f2.js +0 -1
- /mage_ai/server/frontend_dist/_next/static/{RcIgkp9pBXE1Rb4tOGR1L → OwvTROmputQCA1Z9HEGDv}/_middlewareManifest.js +0 -0
- /mage_ai/server/frontend_dist/_next/static/{RcIgkp9pBXE1Rb4tOGR1L → OwvTROmputQCA1Z9HEGDv}/_ssgManifest.js +0 -0
- {mage_ai-0.9.8.dist-info → mage_ai-0.9.9.dist-info}/LICENSE +0 -0
- {mage_ai-0.9.8.dist-info → mage_ai-0.9.9.dist-info}/WHEEL +0 -0
- {mage_ai-0.9.8.dist-info → mage_ai-0.9.9.dist-info}/entry_points.txt +0 -0
- {mage_ai-0.9.8.dist-info → mage_ai-0.9.9.dist-info}/top_level.txt +0 -0
mage_ai/ai/constants.py
CHANGED
mage_ai/ai/generator.py
CHANGED
|
@@ -24,5 +24,11 @@ class Generator:
|
|
|
24
24
|
return await LLMPipelineWizard().async_generate_pipeline_documentation(
|
|
25
25
|
pipeline_uuid,
|
|
26
26
|
)
|
|
27
|
+
elif use_case == LLMUseCase.GENERATE_BLOCK_WITH_DESCRIPTION:
|
|
28
|
+
from mage_ai.ai.llm_pipeline_wizard import LLMPipelineWizard
|
|
29
|
+
|
|
30
|
+
return await LLMPipelineWizard().async_generate_block_with_description(
|
|
31
|
+
request.get('block_description'),
|
|
32
|
+
)
|
|
27
33
|
|
|
28
34
|
raise Exception(f'Use case {use_case} is not supported yet.')
|
|
@@ -42,5 +42,10 @@ def generate_pipeline_documentation(project_path: str = PROJECT_NAME_DEFAULT,
|
|
|
42
42
|
))['pipeline_doc'])
|
|
43
43
|
|
|
44
44
|
|
|
45
|
+
@app.command()
|
|
46
|
+
def generate_block_with_description(block_description: str):
|
|
47
|
+
print(asyncio.run(LLMPipelineWizard().async_generate_block_with_description(block_description)))
|
|
48
|
+
|
|
49
|
+
|
|
45
50
|
if __name__ == '__main__':
|
|
46
51
|
app()
|
|
@@ -1,17 +1,27 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import json
|
|
3
|
+
import os
|
|
2
4
|
|
|
5
|
+
import openai
|
|
3
6
|
from langchain.chains import LLMChain
|
|
4
7
|
from langchain.llms import OpenAI
|
|
5
8
|
from langchain.prompts import PromptTemplate
|
|
6
9
|
|
|
10
|
+
from mage_ai.data_cleaner.transformer_actions.constants import ActionType, Axis
|
|
7
11
|
from mage_ai.data_preparation.models.block import Block
|
|
8
12
|
from mage_ai.data_preparation.models.constants import (
|
|
9
13
|
NON_PIPELINE_EXECUTABLE_BLOCK_TYPES,
|
|
10
14
|
BlockLanguage,
|
|
11
15
|
BlockType,
|
|
16
|
+
PipelineType,
|
|
12
17
|
)
|
|
13
18
|
from mage_ai.data_preparation.models.pipeline import Pipeline
|
|
14
|
-
from mage_ai.data_preparation.repo_manager import get_repo_path
|
|
19
|
+
from mage_ai.data_preparation.repo_manager import get_repo_config, get_repo_path
|
|
20
|
+
from mage_ai.data_preparation.templates.template import fetch_template_source
|
|
21
|
+
from mage_ai.io.base import DataSource
|
|
22
|
+
from mage_ai.server.logger import Logger
|
|
23
|
+
|
|
24
|
+
logger = Logger().new_server_logger(__name__)
|
|
15
25
|
|
|
16
26
|
BLOCK_LANGUAGE_TO_FILE_TYPE_VARIABLE = {
|
|
17
27
|
BlockLanguage.MARKDOWN: 'markdown script',
|
|
@@ -39,11 +49,58 @@ Write a detailed summarization of the data pipeline based on the content provide
|
|
|
39
49
|
```{block_content}```
|
|
40
50
|
"""
|
|
41
51
|
TRANSFORMERS_FOLDER = 'transformers'
|
|
52
|
+
CLASSIFICATION_FUNCTION_NAME = "classify_description"
|
|
53
|
+
TEMPLATE_CLASSIFICATION_FUNCTION = [
|
|
54
|
+
{
|
|
55
|
+
"name": CLASSIFICATION_FUNCTION_NAME,
|
|
56
|
+
"description": "Classify the code description provided into following properties.",
|
|
57
|
+
"parameters": {
|
|
58
|
+
"type": "object",
|
|
59
|
+
"properties": {
|
|
60
|
+
BlockType.__name__: {
|
|
61
|
+
"type": "string",
|
|
62
|
+
"description": "Type of the code block. It either "
|
|
63
|
+
"loads data from a source, export data to a source "
|
|
64
|
+
"or transform data from one format to another.",
|
|
65
|
+
"enum": ["data_exporter", "data_loader", "transformer"]
|
|
66
|
+
},
|
|
67
|
+
BlockLanguage.__name__: {
|
|
68
|
+
"type": "string",
|
|
69
|
+
"description": "Programming language of the code block.",
|
|
70
|
+
"enum": [type.name.lower() for type in BlockLanguage]
|
|
71
|
+
},
|
|
72
|
+
PipelineType.__name__: {
|
|
73
|
+
"type": "string",
|
|
74
|
+
"description": "Type of pipeline description to build.",
|
|
75
|
+
"enum": [type.name.lower() for type in PipelineType]
|
|
76
|
+
},
|
|
77
|
+
ActionType.__name__: {
|
|
78
|
+
"type": "string",
|
|
79
|
+
"description": f"If {BlockType.__name__} is transformer, "
|
|
80
|
+
f"{ActionType.__name__} specifies what kind "
|
|
81
|
+
"of action the code performs.",
|
|
82
|
+
"enum": [type.name.lower() for type in ActionType]
|
|
83
|
+
},
|
|
84
|
+
DataSource.__name__: {
|
|
85
|
+
"type": "string",
|
|
86
|
+
"description": f"If {BlockType.__name__} is data_loader or "
|
|
87
|
+
f"data_exporter, {DataSource.__name__} field specify "
|
|
88
|
+
"where the data loads from or exports to.",
|
|
89
|
+
"enum": [type.name.lower() for type in DataSource]
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
"required": [BlockType.__name__, BlockLanguage.__name__, PipelineType.__name__],
|
|
93
|
+
},
|
|
94
|
+
}
|
|
95
|
+
]
|
|
42
96
|
|
|
43
97
|
|
|
44
98
|
class LLMPipelineWizard:
|
|
45
99
|
def __init__(self):
|
|
46
|
-
|
|
100
|
+
repo_config = get_repo_config()
|
|
101
|
+
openai_api_key = repo_config.openai_api_key or os.getenv('OPENAI_API_KEY')
|
|
102
|
+
openai.api_key = openai_api_key
|
|
103
|
+
self.llm = OpenAI(openai_api_key=openai_api_key, temperature=0)
|
|
47
104
|
|
|
48
105
|
async def __async_llm_generate_documentation(
|
|
49
106
|
self,
|
|
@@ -68,6 +125,54 @@ class LLMPipelineWizard:
|
|
|
68
125
|
purpose=purpose,
|
|
69
126
|
add_on_prompt=add_on_prompt)
|
|
70
127
|
|
|
128
|
+
def __load_template_params(self, function_args: json):
|
|
129
|
+
block_type = BlockType(function_args[BlockType.__name__].lower())
|
|
130
|
+
block_language = BlockLanguage(
|
|
131
|
+
function_args.get(BlockLanguage.__name__, "python").lower())
|
|
132
|
+
pipeline_type = PipelineType(function_args.get(PipelineType.__name__, "python").lower())
|
|
133
|
+
config = {}
|
|
134
|
+
config['action_type'] = function_args.get(ActionType.__name__, None)
|
|
135
|
+
if config['action_type']:
|
|
136
|
+
if config['action_type'] in [
|
|
137
|
+
ActionType.FILTER,
|
|
138
|
+
ActionType.DROP_DUPLICATE,
|
|
139
|
+
ActionType.REMOVE,
|
|
140
|
+
ActionType.SORT
|
|
141
|
+
]:
|
|
142
|
+
config['axis'] = Axis.ROW
|
|
143
|
+
else:
|
|
144
|
+
config['axis'] = Axis.COLUMN
|
|
145
|
+
config['data_source'] = function_args.get(DataSource.__name__, None)
|
|
146
|
+
return block_type, block_language, pipeline_type, config
|
|
147
|
+
|
|
148
|
+
async def async_generate_block_with_description(self, block_description: str) -> dict:
|
|
149
|
+
messages = [{"role": "user", "content": block_description}]
|
|
150
|
+
response = await openai.ChatCompletion.acreate(
|
|
151
|
+
model="gpt-3.5-turbo-0613",
|
|
152
|
+
messages=messages,
|
|
153
|
+
functions=TEMPLATE_CLASSIFICATION_FUNCTION,
|
|
154
|
+
function_call={"name": CLASSIFICATION_FUNCTION_NAME}, # explicitly set function call
|
|
155
|
+
)
|
|
156
|
+
response_message = response["choices"][0]["message"]
|
|
157
|
+
if response_message.get("function_call"):
|
|
158
|
+
function_args = json.loads(response_message["function_call"]["arguments"])
|
|
159
|
+
block_type, block_language, pipeline_type, config = self.__load_template_params(
|
|
160
|
+
function_args)
|
|
161
|
+
return dict(
|
|
162
|
+
block_type=block_type,
|
|
163
|
+
configuration=config,
|
|
164
|
+
content=fetch_template_source(
|
|
165
|
+
block_type=block_type,
|
|
166
|
+
config=config,
|
|
167
|
+
language=block_language,
|
|
168
|
+
pipeline_type=pipeline_type,
|
|
169
|
+
),
|
|
170
|
+
language=block_language,
|
|
171
|
+
)
|
|
172
|
+
else:
|
|
173
|
+
logger.error("Failed to interpret the description as a block template.")
|
|
174
|
+
return None
|
|
175
|
+
|
|
71
176
|
async def async_generate_pipeline_documentation(
|
|
72
177
|
self,
|
|
73
178
|
pipeline_uuid: str,
|
|
@@ -92,7 +197,7 @@ class LLMPipelineWizard:
|
|
|
92
197
|
chain = LLMChain(llm=self.llm, prompt=prompt_template)
|
|
93
198
|
pipeline_doc = chain.run(block_content=block_docs_content)
|
|
94
199
|
return dict(
|
|
95
|
-
|
|
200
|
+
block_docs=block_docs,
|
|
96
201
|
pipeline_doc=pipeline_doc,
|
|
97
202
|
)
|
|
98
203
|
|
|
@@ -25,3 +25,12 @@ BlockTemplatePolicy.allow_read(BlockTemplatePresenter.default_attributes + [], s
|
|
|
25
25
|
constants.DETAIL,
|
|
26
26
|
constants.LIST,
|
|
27
27
|
], condition=lambda policy: policy.has_at_least_viewer_role())
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
BlockTemplatePolicy.allow_query([
|
|
31
|
+
'show_all',
|
|
32
|
+
], scopes=[
|
|
33
|
+
OauthScope.CLIENT_PRIVATE,
|
|
34
|
+
], on_action=[
|
|
35
|
+
constants.LIST,
|
|
36
|
+
], condition=lambda policy: policy.has_at_least_viewer_role())
|
|
@@ -23,9 +23,10 @@ LlmPolicy.allow_actions([
|
|
|
23
23
|
OauthScope.CLIENT_PRIVATE,
|
|
24
24
|
], condition=lambda policy: policy.has_at_least_editor_role())
|
|
25
25
|
|
|
26
|
+
|
|
26
27
|
LlmPolicy.allow_read([
|
|
28
|
+
'response',
|
|
27
29
|
'use_case',
|
|
28
|
-
'request',
|
|
29
30
|
], scopes=[
|
|
30
31
|
OauthScope.CLIENT_PRIVATE,
|
|
31
32
|
], on_action=[
|
|
@@ -34,8 +35,8 @@ LlmPolicy.allow_read([
|
|
|
34
35
|
|
|
35
36
|
|
|
36
37
|
LlmPolicy.allow_write([
|
|
38
|
+
'request',
|
|
37
39
|
'use_case',
|
|
38
|
-
'response',
|
|
39
40
|
], scopes=[
|
|
40
41
|
OauthScope.CLIENT_PRIVATE,
|
|
41
42
|
], on_action=[
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from mage_ai.api.oauth_scope import OauthScope
|
|
2
|
+
from mage_ai.api.operations import constants
|
|
3
|
+
from mage_ai.api.policies.BasePolicy import BasePolicy
|
|
4
|
+
from mage_ai.api.presenters.OauthAccessTokenPresenter import OauthAccessTokenPresenter
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class OauthAccessTokenPolicy(BasePolicy):
|
|
8
|
+
pass
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
OauthAccessTokenPolicy.allow_actions([
|
|
12
|
+
constants.LIST,
|
|
13
|
+
], scopes=[
|
|
14
|
+
OauthScope.CLIENT_PRIVATE,
|
|
15
|
+
], condition=lambda policy: policy.has_at_least_viewer_role())
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
OauthAccessTokenPolicy.allow_read(OauthAccessTokenPresenter.default_attributes, scopes=[
|
|
19
|
+
OauthScope.CLIENT_PRIVATE,
|
|
20
|
+
], on_action=[
|
|
21
|
+
constants.LIST,
|
|
22
|
+
], condition=lambda policy: policy.has_at_least_viewer_role())
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
OauthAccessTokenPolicy.allow_query([
|
|
26
|
+
'show_all',
|
|
27
|
+
], scopes=[
|
|
28
|
+
OauthScope.CLIENT_PRIVATE,
|
|
29
|
+
], on_action=[
|
|
30
|
+
constants.LIST,
|
|
31
|
+
], condition=lambda policy: policy.has_at_least_viewer_role())
|
|
@@ -35,3 +35,12 @@ ProjectPolicy.allow_write([
|
|
|
35
35
|
], on_action=[
|
|
36
36
|
constants.UPDATE,
|
|
37
37
|
], condition=lambda policy: policy.has_at_least_viewer_role())
|
|
38
|
+
|
|
39
|
+
ProjectPolicy.allow_write([
|
|
40
|
+
'features',
|
|
41
|
+
'openai_api_key',
|
|
42
|
+
], scopes=[
|
|
43
|
+
OauthScope.CLIENT_PRIVATE,
|
|
44
|
+
], on_action=[
|
|
45
|
+
constants.UPDATE,
|
|
46
|
+
], condition=lambda policy: policy.has_at_least_editor_role())
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from mage_ai.api.oauth_scope import OauthScope
|
|
2
|
+
from mage_ai.api.operations import constants
|
|
3
|
+
from mage_ai.api.policies.BasePolicy import BasePolicy
|
|
4
|
+
from mage_ai.api.presenters.SearchResultPresenter import SearchResultPresenter
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class SearchResultPolicy(BasePolicy):
|
|
8
|
+
pass
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
SearchResultPolicy.allow_actions([
|
|
12
|
+
constants.CREATE,
|
|
13
|
+
], scopes=[
|
|
14
|
+
OauthScope.CLIENT_PRIVATE,
|
|
15
|
+
], condition=lambda policy: policy.has_at_least_viewer_role())
|
|
16
|
+
|
|
17
|
+
SearchResultPolicy.allow_read(SearchResultPresenter.default_attributes, scopes=[
|
|
18
|
+
OauthScope.CLIENT_PRIVATE,
|
|
19
|
+
], on_action=[
|
|
20
|
+
constants.CREATE,
|
|
21
|
+
], condition=lambda policy: policy.has_at_least_viewer_role())
|
|
22
|
+
|
|
23
|
+
SearchResultPolicy.allow_write([
|
|
24
|
+
'pipeline_type',
|
|
25
|
+
'query',
|
|
26
|
+
'ratio',
|
|
27
|
+
'type',
|
|
28
|
+
], scopes=[
|
|
29
|
+
OauthScope.CLIENT_PRIVATE,
|
|
30
|
+
], on_action=[
|
|
31
|
+
constants.CREATE,
|
|
32
|
+
], condition=lambda policy: policy.has_at_least_viewer_role())
|
|
@@ -55,3 +55,11 @@ VariablePolicy.allow_write([
|
|
|
55
55
|
constants.CREATE,
|
|
56
56
|
constants.UPDATE,
|
|
57
57
|
], condition=lambda policy: policy.has_at_least_editor_role_and_notebook_edit_access())
|
|
58
|
+
|
|
59
|
+
VariablePolicy.allow_query([
|
|
60
|
+
'global_only',
|
|
61
|
+
], scopes=[
|
|
62
|
+
OauthScope.CLIENT_PRIVATE,
|
|
63
|
+
], on_action=[
|
|
64
|
+
constants.LIST,
|
|
65
|
+
], condition=lambda policy: policy.has_at_least_viewer_role())
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
from mage_ai.api.operations import constants
|
|
2
|
+
from mage_ai.api.presenters.BasePresenter import BasePresenter
|
|
3
|
+
from mage_ai.cache.block_action_object.constants import (
|
|
4
|
+
OBJECT_TYPE_BLOCK_FILE,
|
|
5
|
+
OBJECT_TYPE_CUSTOM_BLOCK_TEMPLATE,
|
|
6
|
+
OBJECT_TYPE_MAGE_TEMPLATE,
|
|
7
|
+
)
|
|
8
|
+
from mage_ai.services.search.constants import SEARCH_TYPE_BLOCK_ACTION_OBJECTS
|
|
9
|
+
from mage_ai.shared.hash import merge_dict
|
|
10
|
+
from mage_ai.shared.strings import remove_extension_from_filename
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class SearchResultPresenter(BasePresenter):
|
|
14
|
+
default_attributes = [
|
|
15
|
+
'results',
|
|
16
|
+
'type',
|
|
17
|
+
'uuid',
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
def present(self, **kwargs):
|
|
21
|
+
display_format = kwargs['format']
|
|
22
|
+
|
|
23
|
+
if constants.CREATE != display_format:
|
|
24
|
+
return self.model
|
|
25
|
+
|
|
26
|
+
results = self.model.get('results', [])
|
|
27
|
+
search_type = self.model.get('type')
|
|
28
|
+
results_transformed = []
|
|
29
|
+
|
|
30
|
+
if SEARCH_TYPE_BLOCK_ACTION_OBJECTS == search_type:
|
|
31
|
+
for result in results:
|
|
32
|
+
block_action_object = result.get('block_action_object')
|
|
33
|
+
object_type = result.get('object_type')
|
|
34
|
+
uuid = result.get('uuid')
|
|
35
|
+
|
|
36
|
+
block_type = None
|
|
37
|
+
description = block_action_object.get('description')
|
|
38
|
+
language = block_action_object.get('language')
|
|
39
|
+
title = None
|
|
40
|
+
|
|
41
|
+
if OBJECT_TYPE_BLOCK_FILE == object_type:
|
|
42
|
+
block_type = block_action_object.get('type')
|
|
43
|
+
u = block_action_object.get('uuid')
|
|
44
|
+
title = ' '.join(list(filter(lambda x: x, [
|
|
45
|
+
remove_extension_from_filename(u).replace('_', ' ') if u else u,
|
|
46
|
+
])))
|
|
47
|
+
elif OBJECT_TYPE_CUSTOM_BLOCK_TEMPLATE == object_type:
|
|
48
|
+
block_type = block_action_object.get('block_type')
|
|
49
|
+
template_name = block_action_object.get('name')
|
|
50
|
+
template_uuid = block_action_object.get('template_uuid')
|
|
51
|
+
u = template_name or template_uuid
|
|
52
|
+
title = ' '.join(list(filter(lambda x: x, [
|
|
53
|
+
remove_extension_from_filename(u).replace('_', ' ') if u else u,
|
|
54
|
+
])))
|
|
55
|
+
elif OBJECT_TYPE_MAGE_TEMPLATE == object_type:
|
|
56
|
+
block_type = block_action_object.get('block_type')
|
|
57
|
+
u = block_action_object.get('name')
|
|
58
|
+
title = ' '.join(list(filter(lambda x: x, [
|
|
59
|
+
remove_extension_from_filename(u).replace('_', ' ') if u else u,
|
|
60
|
+
])))
|
|
61
|
+
|
|
62
|
+
results_transformed.append(dict(
|
|
63
|
+
block_type=block_type,
|
|
64
|
+
description=description,
|
|
65
|
+
language=language,
|
|
66
|
+
object_type=object_type,
|
|
67
|
+
title=title,
|
|
68
|
+
uuid=uuid,
|
|
69
|
+
))
|
|
70
|
+
|
|
71
|
+
return merge_dict(self.model, dict(
|
|
72
|
+
results=results_transformed,
|
|
73
|
+
))
|
|
@@ -3,6 +3,12 @@ import urllib.parse
|
|
|
3
3
|
from mage_ai.api.errors import ApiError
|
|
4
4
|
from mage_ai.api.resources.GenericResource import GenericResource
|
|
5
5
|
from mage_ai.cache.block import BlockCache
|
|
6
|
+
from mage_ai.cache.block_action_object import BlockActionObjectCache
|
|
7
|
+
from mage_ai.cache.block_action_object.constants import (
|
|
8
|
+
OBJECT_TYPE_BLOCK_FILE,
|
|
9
|
+
OBJECT_TYPE_CUSTOM_BLOCK_TEMPLATE,
|
|
10
|
+
OBJECT_TYPE_MAGE_TEMPLATE,
|
|
11
|
+
)
|
|
6
12
|
from mage_ai.data_preparation.models.block import Block
|
|
7
13
|
from mage_ai.data_preparation.models.block.dbt import DBTBlock
|
|
8
14
|
from mage_ai.data_preparation.models.block.utils import clean_name
|
|
@@ -29,6 +35,31 @@ class BlockResource(GenericResource):
|
|
|
29
35
|
content = payload.get('content')
|
|
30
36
|
language = payload.get('language')
|
|
31
37
|
name = payload.get('name')
|
|
38
|
+
block_name = name or payload.get('uuid')
|
|
39
|
+
|
|
40
|
+
payload_config = payload.get('config') or {}
|
|
41
|
+
|
|
42
|
+
block_action_object = payload.get('block_action_object')
|
|
43
|
+
if block_action_object:
|
|
44
|
+
object_type = block_action_object.get('object_type')
|
|
45
|
+
|
|
46
|
+
cache_block_action_object = await BlockActionObjectCache.initialize_cache()
|
|
47
|
+
mapping = cache_block_action_object.load_all_data()
|
|
48
|
+
objects_mapping = mapping.get(object_type)
|
|
49
|
+
object_uuid = block_action_object.get('uuid')
|
|
50
|
+
object_from_cache = objects_mapping.get(object_uuid)
|
|
51
|
+
|
|
52
|
+
if OBJECT_TYPE_BLOCK_FILE == object_type:
|
|
53
|
+
block_name = object_from_cache.get('uuid')
|
|
54
|
+
block_type = object_from_cache.get('type')
|
|
55
|
+
language = object_from_cache.get('language')
|
|
56
|
+
elif OBJECT_TYPE_CUSTOM_BLOCK_TEMPLATE == object_type:
|
|
57
|
+
payload_config['custom_template_uuid'] = object_from_cache.get('template_uuid')
|
|
58
|
+
elif OBJECT_TYPE_MAGE_TEMPLATE == object_type:
|
|
59
|
+
block_type = object_from_cache.get('block_type')
|
|
60
|
+
language = object_from_cache.get('language')
|
|
61
|
+
payload_config['template_path'] = object_from_cache.get('path')
|
|
62
|
+
payload_config['template_variables'] = object_from_cache.get('template_variables')
|
|
32
63
|
|
|
33
64
|
"""
|
|
34
65
|
New DBT models include "content" in its block create payload,
|
|
@@ -47,9 +78,6 @@ class BlockResource(GenericResource):
|
|
|
47
78
|
Please choose a different model name, or add a DBT model by \
|
|
48
79
|
selecting single model from file.')
|
|
49
80
|
|
|
50
|
-
payload_config = payload.get('config')
|
|
51
|
-
|
|
52
|
-
block_name = name or payload.get('uuid')
|
|
53
81
|
block_attributes = dict(
|
|
54
82
|
color=payload.get('color'),
|
|
55
83
|
config=payload_config,
|
|
@@ -104,6 +132,9 @@ class BlockResource(GenericResource):
|
|
|
104
132
|
cache = await BlockCache.initialize_cache()
|
|
105
133
|
cache.add_pipeline(block, pipeline)
|
|
106
134
|
|
|
135
|
+
cache_block_action_object = await BlockActionObjectCache.initialize_cache()
|
|
136
|
+
cache_block_action_object.update_block(block)
|
|
137
|
+
|
|
107
138
|
return self(block, user, **kwargs)
|
|
108
139
|
|
|
109
140
|
@classmethod
|
|
@@ -189,10 +220,16 @@ class BlockResource(GenericResource):
|
|
|
189
220
|
if pipeline:
|
|
190
221
|
cache.remove_pipeline(self.model, pipeline.uuid)
|
|
191
222
|
|
|
223
|
+
cache_block_action_object = await BlockActionObjectCache.initialize_cache()
|
|
224
|
+
cache_block_action_object.update_block(self.model, remove=True)
|
|
225
|
+
|
|
192
226
|
return self.model.delete(force=force)
|
|
193
227
|
|
|
194
228
|
@safe_db_query
|
|
195
|
-
def update(self, payload, **kwargs):
|
|
229
|
+
async def update(self, payload, **kwargs):
|
|
230
|
+
cache_block_action_object = await BlockActionObjectCache.initialize_cache()
|
|
231
|
+
cache_block_action_object.update_block(self.model, remove=True)
|
|
232
|
+
|
|
196
233
|
query = kwargs.get('query', {})
|
|
197
234
|
update_state = query.get('update_state', [False])
|
|
198
235
|
if update_state:
|
|
@@ -202,6 +239,8 @@ class BlockResource(GenericResource):
|
|
|
202
239
|
update_state=update_state,
|
|
203
240
|
)
|
|
204
241
|
|
|
242
|
+
cache_block_action_object.update_block(self.model)
|
|
243
|
+
|
|
205
244
|
async def get_pipelines_from_cache(self):
|
|
206
245
|
await BlockCache.initialize_cache()
|
|
207
246
|
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
from mage_ai.api.errors import ApiError
|
|
2
2
|
from mage_ai.api.resources.GenericResource import GenericResource
|
|
3
|
-
from mage_ai.data_preparation.templates.constants import
|
|
3
|
+
from mage_ai.data_preparation.templates.constants import (
|
|
4
|
+
TEMPLATES,
|
|
5
|
+
TEMPLATES_BY_UUID,
|
|
6
|
+
TEMPLATES_ONLY_FOR_V2,
|
|
7
|
+
)
|
|
4
8
|
from mage_ai.orchestration.db import safe_db_query
|
|
5
9
|
|
|
6
10
|
|
|
@@ -8,8 +12,17 @@ class BlockTemplateResource(GenericResource):
|
|
|
8
12
|
@classmethod
|
|
9
13
|
@safe_db_query
|
|
10
14
|
def collection(self, query, meta, user, **kwargs):
|
|
15
|
+
show_all = query.get('show_all', [None])
|
|
16
|
+
if show_all:
|
|
17
|
+
show_all = show_all[0]
|
|
18
|
+
|
|
19
|
+
arr = TEMPLATES.copy()
|
|
20
|
+
|
|
21
|
+
if show_all:
|
|
22
|
+
arr += TEMPLATES_ONLY_FOR_V2.copy()
|
|
23
|
+
|
|
11
24
|
return self.build_result_set(
|
|
12
|
-
|
|
25
|
+
arr,
|
|
13
26
|
user,
|
|
14
27
|
**kwargs,
|
|
15
28
|
)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import urllib.parse
|
|
2
2
|
from mage_ai.api.errors import ApiError
|
|
3
3
|
from mage_ai.api.resources.GenericResource import GenericResource
|
|
4
|
+
from mage_ai.cache.block_action_object import BlockActionObjectCache
|
|
4
5
|
from mage_ai.data_preparation.models.custom_templates.constants import (
|
|
5
6
|
DIRECTORY_FOR_BLOCK_TEMPLATES,
|
|
6
7
|
DIRECTORY_FOR_PIPELINE_TEMPLATES,
|
|
@@ -51,7 +52,7 @@ class CustomTemplateResource(GenericResource):
|
|
|
51
52
|
)
|
|
52
53
|
|
|
53
54
|
@classmethod
|
|
54
|
-
def create(self, payload, user, **kwargs):
|
|
55
|
+
async def create(self, payload, user, **kwargs):
|
|
55
56
|
custom_template = None
|
|
56
57
|
object_type = payload.get(OBJECT_TYPE_KEY)
|
|
57
58
|
template_uuid = payload.get('template_uuid')
|
|
@@ -76,6 +77,9 @@ class CustomTemplateResource(GenericResource):
|
|
|
76
77
|
)
|
|
77
78
|
|
|
78
79
|
custom_template.save()
|
|
80
|
+
|
|
81
|
+
cache = await BlockActionObjectCache.initialize_cache()
|
|
82
|
+
cache.update_custom_block_template(custom_template)
|
|
79
83
|
elif DIRECTORY_FOR_PIPELINE_TEMPLATES == object_type:
|
|
80
84
|
custom_template = CustomPipelineTemplate.load(template_uuid=template_uuid)
|
|
81
85
|
|
|
@@ -120,13 +124,21 @@ class CustomTemplateResource(GenericResource):
|
|
|
120
124
|
print(f'[WARNING] CustomTemplateResource.member: {err}')
|
|
121
125
|
raise ApiError(ApiError.RESOURCE_NOT_FOUND)
|
|
122
126
|
|
|
123
|
-
def delete(self, **kwargs):
|
|
127
|
+
async def delete(self, **kwargs):
|
|
128
|
+
cache = await BlockActionObjectCache.initialize_cache()
|
|
129
|
+
cache.update_custom_block_template(self.model, remove=True)
|
|
124
130
|
self.model.delete
|
|
125
131
|
|
|
126
|
-
def update(self, payload, **kwargs):
|
|
132
|
+
async def update(self, payload, **kwargs):
|
|
133
|
+
cache = await BlockActionObjectCache.initialize_cache()
|
|
134
|
+
|
|
135
|
+
cache.update_custom_block_template(self.model, remove=True)
|
|
136
|
+
|
|
127
137
|
for key, value in ignore_keys(payload, [
|
|
128
138
|
'uuid',
|
|
129
139
|
OBJECT_TYPE_KEY,
|
|
130
140
|
]).items():
|
|
131
141
|
setattr(self.model, key, value)
|
|
132
142
|
self.model.save()
|
|
143
|
+
|
|
144
|
+
cache.update_custom_block_template(self.model)
|
|
@@ -2,6 +2,8 @@ import urllib.parse
|
|
|
2
2
|
|
|
3
3
|
from mage_ai.api.errors import ApiError
|
|
4
4
|
from mage_ai.api.resources.GenericResource import GenericResource
|
|
5
|
+
from mage_ai.cache.block_action_object import BlockActionObjectCache
|
|
6
|
+
from mage_ai.data_preparation.models.block import Block
|
|
5
7
|
from mage_ai.data_preparation.models.file import File
|
|
6
8
|
from mage_ai.orchestration.db import safe_db_query
|
|
7
9
|
from mage_ai.settings.repo import get_repo_path
|
|
@@ -16,7 +18,7 @@ class FileContentResource(GenericResource):
|
|
|
16
18
|
file = File.from_path(file_path, get_repo_path())
|
|
17
19
|
return self(file, user, **kwargs)
|
|
18
20
|
|
|
19
|
-
def update(self, payload, **kwargs):
|
|
21
|
+
async def update(self, payload, **kwargs):
|
|
20
22
|
error = ApiError.RESOURCE_INVALID.copy()
|
|
21
23
|
|
|
22
24
|
content = payload.get('content')
|
|
@@ -31,3 +33,8 @@ class FileContentResource(GenericResource):
|
|
|
31
33
|
content = file_version.content()
|
|
32
34
|
|
|
33
35
|
self.model.update_content(content)
|
|
36
|
+
|
|
37
|
+
block_type = Block.block_type_from_path(self.model.dir_path)
|
|
38
|
+
if block_type:
|
|
39
|
+
cache_block_action_object = await BlockActionObjectCache.initialize_cache()
|
|
40
|
+
cache_block_action_object.update_block(block_file_absolute_path=self.model.file_path)
|