naas-abi 1.0.8__py3-none-any.whl → 1.0.10__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.
- naas_abi/__init__.py +16 -1
- naas_abi/agents/AbiAgent.py +27 -18
- naas_abi/agents/EntitytoSPARQLAgent.py +22 -17
- naas_abi/agents/KnowledgeGraphBuilderAgent.py +17 -15
- naas_abi/agents/OntologyEngineerAgent.py +4 -15
- naas_abi/apps/oxigraph_admin/main.py +7 -4
- naas_abi/apps/sparql_terminal/main.py +7 -4
- naas_abi/pipelines/AIAgentOntologyGenerationPipeline_test.py +4 -3
- naas_abi/pipelines/AddIndividualPipeline_test.py +10 -7
- naas_abi/pipelines/InsertDataSPARQLPipeline.py +6 -4
- naas_abi/pipelines/InsertDataSPARQLPipeline_test.py +9 -6
- naas_abi/pipelines/MergeIndividualsPipeline.py +6 -2
- naas_abi/pipelines/MergeIndividualsPipeline_test.py +10 -9
- naas_abi/pipelines/RemoveIndividualPipeline.py +6 -2
- naas_abi/pipelines/RemoveIndividualPipeline_test.py +8 -8
- naas_abi/pipelines/UpdateDataPropertyPipeline.py +6 -2
- naas_abi/workflows/GetObjectPropertiesFromClassWorkflow_test.py +7 -2
- naas_abi/workflows/GetSubjectGraphWorkflow_test.py +8 -3
- naas_abi/workflows/SearchIndividualWorkflow_test.py +6 -6
- {naas_abi-1.0.8.dist-info → naas_abi-1.0.10.dist-info}/METADATA +2 -2
- naas_abi-1.0.10.dist-info/RECORD +49 -0
- naas_abi/apps/terminal_agent/main.py +0 -553
- naas_abi/apps/terminal_agent/terminal_style.py +0 -175
- naas_abi/mappings.py +0 -83
- naas_abi/triggers.py +0 -131
- naas_abi/workflows/ConvertOntologyGraphToYamlWorkflow.py +0 -210
- naas_abi/workflows/ConvertOntologyGraphToYamlWorkflow_test.py +0 -78
- naas_abi/workflows/CreateClassOntologyYamlWorkflow.py +0 -214
- naas_abi/workflows/CreateClassOntologyYamlWorkflow_test.py +0 -65
- naas_abi/workflows/CreateIndividualOntologyYamlWorkflow.py +0 -183
- naas_abi/workflows/CreateIndividualOntologyYamlWorkflow_test.py +0 -86
- naas_abi/workflows/ExportGraphInstancesToExcelWorkflow.py +0 -450
- naas_abi/workflows/ExportGraphInstancesToExcelWorkflow_test.py +0 -33
- naas_abi-1.0.8.dist-info/RECORD +0 -61
- {naas_abi-1.0.8.dist-info → naas_abi-1.0.10.dist-info}/WHEEL +0 -0
- {naas_abi-1.0.8.dist-info → naas_abi-1.0.10.dist-info}/top_level.txt +0 -0
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
from rich.console import Console
|
|
2
|
-
from rich.markdown import Markdown
|
|
3
|
-
from rich.panel import Panel
|
|
4
|
-
from rich.syntax import Syntax
|
|
5
|
-
from rich.text import Text
|
|
6
|
-
from rich.box import ROUNDED
|
|
7
|
-
from PIL import Image
|
|
8
|
-
import os
|
|
9
|
-
import platform
|
|
10
|
-
import subprocess
|
|
11
|
-
|
|
12
|
-
console = Console()
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def set_terminal_title():
|
|
16
|
-
"""Set the terminal title to 'ABI'"""
|
|
17
|
-
if platform.system() == "Windows":
|
|
18
|
-
os.system("title ABI")
|
|
19
|
-
else: # For Unix-like systems (Linux, macOS)
|
|
20
|
-
print("\33]0;ABI\a", end="", flush=True)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def print_agent_response(text, agent_label):
|
|
24
|
-
console.print() # Add a blank line before the assistant's response
|
|
25
|
-
console.print(f"[bold green]{agent_label}:[/bold green] ", end="")
|
|
26
|
-
md = Markdown(text)
|
|
27
|
-
console.print(md)
|
|
28
|
-
console.print() # Add a blank line after the assistant's response
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def print_system_message(text):
|
|
32
|
-
console.print() # Add a blank line before the system message
|
|
33
|
-
system_text = Text(text, style="yellow")
|
|
34
|
-
console.print(
|
|
35
|
-
Panel(
|
|
36
|
-
system_text,
|
|
37
|
-
border_style="yellow",
|
|
38
|
-
box=ROUNDED,
|
|
39
|
-
expand=False,
|
|
40
|
-
title="System",
|
|
41
|
-
title_align="left",
|
|
42
|
-
)
|
|
43
|
-
)
|
|
44
|
-
console.print() # Add a blank line after the system message
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def print_code(code, language="python"):
|
|
48
|
-
syntax = Syntax(code, language, theme="monokai", line_numbers=True)
|
|
49
|
-
console.print(
|
|
50
|
-
Panel(
|
|
51
|
-
syntax,
|
|
52
|
-
border_style="red",
|
|
53
|
-
box=ROUNDED,
|
|
54
|
-
expand=False,
|
|
55
|
-
title=f"Code ({language})",
|
|
56
|
-
title_align="left",
|
|
57
|
-
)
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def dict_to_equal_string(d: dict) -> str:
|
|
62
|
-
return "\n".join([f'-{key}="{value}"' for key, value in d.items()])
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def print_tool_usage(message):
|
|
66
|
-
print_message = ""
|
|
67
|
-
tool_name = message.tool_calls[0]["name"]
|
|
68
|
-
arguments = ""
|
|
69
|
-
if (
|
|
70
|
-
"args" in message.tool_calls[0]
|
|
71
|
-
and len(message.tool_calls[0]["args"].values()) > 0
|
|
72
|
-
):
|
|
73
|
-
arguments += dict_to_equal_string(message.tool_calls[0]["args"])
|
|
74
|
-
|
|
75
|
-
if tool_name.startswith("transfer_to_"):
|
|
76
|
-
tool_label = " ".join(
|
|
77
|
-
word.capitalize()
|
|
78
|
-
for word in tool_name.split("transfer_to_")[1].replace("_", " ").split()
|
|
79
|
-
)
|
|
80
|
-
print_message = f"\n🧞 [bold blue]Delegated to [/bold blue]{tool_label}"
|
|
81
|
-
else:
|
|
82
|
-
tool_label = tool_name.capitalize().replace("_", " ")
|
|
83
|
-
print_message = f"\n[bold blue]Tool Used:[/bold blue] {tool_label}\n{arguments}"
|
|
84
|
-
console.print(print_message)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
def print_tool_response(response):
|
|
88
|
-
console.print(f"\n[bold blue]Response:[/bold blue] {response}")
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
def clear_screen():
|
|
92
|
-
console.clear()
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
def print_welcome_message(agent):
|
|
96
|
-
# Set terminal title
|
|
97
|
-
set_terminal_title()
|
|
98
|
-
|
|
99
|
-
# Skip the welcome - we already said hello in the CLI startup
|
|
100
|
-
# Just quietly start the conversation
|
|
101
|
-
pass
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
def print_divider():
|
|
105
|
-
console.print("─" * console.width, style="dim")
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
def get_user_input(agent_label):
|
|
109
|
-
try:
|
|
110
|
-
user_input = console.input(
|
|
111
|
-
"\n[bold cyan]You:[/bold cyan] "
|
|
112
|
-
) # Add a newline before the prompt
|
|
113
|
-
console.print() # Add a blank line after the user's input
|
|
114
|
-
return user_input
|
|
115
|
-
except EOFError:
|
|
116
|
-
console.print(
|
|
117
|
-
f"\n[bold red]{agent_label}:[/bold red] Conversation ended by user."
|
|
118
|
-
)
|
|
119
|
-
return "exit"
|
|
120
|
-
except KeyboardInterrupt:
|
|
121
|
-
console.print(
|
|
122
|
-
f"\n[bold red]{agent_label}:[/bold red] Conversation ended by user."
|
|
123
|
-
)
|
|
124
|
-
return "exit"
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
def print_image(image_path: str):
|
|
128
|
-
"""Display an image in the terminal."""
|
|
129
|
-
try:
|
|
130
|
-
console.print() # Add some spacing
|
|
131
|
-
|
|
132
|
-
# Display the file path and viewing instructions
|
|
133
|
-
message = (
|
|
134
|
-
f"[yellow]Image saved at: {image_path}[/yellow]\n\n"
|
|
135
|
-
"[dim]To view the image:[/dim]\n"
|
|
136
|
-
f"[cyan]• Local system: Open {image_path} with your image viewer[/cyan]\n"
|
|
137
|
-
"[cyan]• Remote/SSH: Download the file to your local machine to view[/cyan]"
|
|
138
|
-
)
|
|
139
|
-
|
|
140
|
-
console.print(
|
|
141
|
-
Panel(
|
|
142
|
-
message,
|
|
143
|
-
border_style="yellow",
|
|
144
|
-
box=ROUNDED,
|
|
145
|
-
expand=False,
|
|
146
|
-
title="Graph Output",
|
|
147
|
-
title_align="left",
|
|
148
|
-
)
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
# Only try to show the image if we're in a GUI environment
|
|
152
|
-
if os.environ.get("DISPLAY") and platform.system() != "Windows":
|
|
153
|
-
try:
|
|
154
|
-
img = Image.open(image_path)
|
|
155
|
-
img.show()
|
|
156
|
-
except Exception:
|
|
157
|
-
pass # Silently fail if we can't display the image
|
|
158
|
-
elif platform.system() == "Windows":
|
|
159
|
-
try:
|
|
160
|
-
subprocess.run(['start', '', image_path], shell=True) # Windows-specific file opening
|
|
161
|
-
except Exception:
|
|
162
|
-
pass
|
|
163
|
-
|
|
164
|
-
console.print() # Add some spacing after
|
|
165
|
-
except Exception as e:
|
|
166
|
-
console.print(
|
|
167
|
-
Panel(
|
|
168
|
-
f"[yellow]Unable to process image. File saved at: {image_path}[/yellow]\nError: {str(e)}",
|
|
169
|
-
border_style="yellow",
|
|
170
|
-
box=ROUNDED,
|
|
171
|
-
expand=False,
|
|
172
|
-
title="Graph Output",
|
|
173
|
-
title_align="left",
|
|
174
|
-
)
|
|
175
|
-
)
|
naas_abi/mappings.py
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
COLORS_NODES = {
|
|
2
|
-
# Role
|
|
3
|
-
"http://ontology.naas.ai/abi/Offering": "#f61685",
|
|
4
|
-
"http://ontology.naas.ai/abi/Product": "#C4116A",
|
|
5
|
-
"http://ontology.naas.ai/abi/Service": "#F973B5",
|
|
6
|
-
"http://ontology.naas.ai/abi/Positioning": "#FDD0E6",
|
|
7
|
-
# Capability
|
|
8
|
-
"http://ontology.naas.ai/abi/HumanCapabilities": "#D397F8",
|
|
9
|
-
"http://ontology.naas.ai/abi/TechnologicalCapabilities": "#bd87df",
|
|
10
|
-
"https://www.commoncoreontologies.org/ont00000089": "#bd87df", # Skill
|
|
11
|
-
# Temporal Region
|
|
12
|
-
"https://www.commoncoreontologies.org/ont00000832": "#47DD82",
|
|
13
|
-
"http://ontology.naas.ai/abi/ISO8601UTCDateTime": "#47DD82",
|
|
14
|
-
# Agent Ontology
|
|
15
|
-
'https://www.commoncoreontologies.org/ont00001180': 'white', # Organization
|
|
16
|
-
'https://www.commoncoreontologies.org/ont00000443': 'white', # Commercial Organization
|
|
17
|
-
'http://ontology.naas.ai/abi/StockMarket': 'white', # Stock Market Institution
|
|
18
|
-
'https://www.commoncoreontologies.org/ont00001302': 'white', # Civil Organization
|
|
19
|
-
'https://www.commoncoreontologies.org/ont00000564': 'white', # Educational Organization
|
|
20
|
-
'https://www.commoncoreontologies.org/ont00000408': 'white', # Government Organization
|
|
21
|
-
'https://www.commoncoreontologies.org/ont00001239': '#f6f6f6', # Group Organization
|
|
22
|
-
'http://ontology.naas.ai/abi/Industry': '#f6f6f6', # Group of organizations
|
|
23
|
-
'http://ontology.naas.ai/abi/LinkedInIndustry': '#f6f6f6', # Group of organizations
|
|
24
|
-
'https://www.commoncoreontologies.org/ont00001262': '#919191', # Group
|
|
25
|
-
'https://www.commoncoreontologies.org/ont00000647': '#919191', # Member
|
|
26
|
-
'https://www.commoncoreontologies.org/ont00000914': 'white', # Group Member
|
|
27
|
-
'https://www.commoncoreontologies.org/ont00000175': '#3e3e3e', # Member Role
|
|
28
|
-
'http://ontology.naas.ai/abi/leadership#Position': '#905e0e', # Position
|
|
29
|
-
# Event Ontology
|
|
30
|
-
"http://ontology.naas.ai/abi/ActOfPartnership": "black",
|
|
31
|
-
"http://ontology.naas.ai/abi/ActOfJointVenture": "black",
|
|
32
|
-
"http://ontology.naas.ai/abi/ActOfMarketingAlliance": "black",
|
|
33
|
-
"http://ontology.naas.ai/abi/ActOfResearchCollaboration": "black",
|
|
34
|
-
"http://ontology.naas.ai/abi/ActOfTechnologyLicensing": "black",
|
|
35
|
-
"http://ontology.naas.ai/abi/ActOfDistributionAgreement": "black",
|
|
36
|
-
"http://ontology.naas.ai/abi/ActOfOrganizationalMerger": "black",
|
|
37
|
-
"http://ontology.naas.ai/abi/ActOfOrganizationalAcquisition": "black",
|
|
38
|
-
"http://ontology.naas.ai/abi/ActOfSubsidiaryEstablishment": "black",
|
|
39
|
-
# Information Content
|
|
40
|
-
"https://www.commoncoreontologies.org/ont00001331": "#AECCE4", # Legal Name
|
|
41
|
-
"http://ontology.naas.ai/abi/OrganizationSize": "#9ABDDC",
|
|
42
|
-
"http://ontology.naas.ai/abi/Ticker": "#6C849A",
|
|
43
|
-
"http://ontology.naas.ai/abi/Address": "#4D5F6E",
|
|
44
|
-
"http://ontology.naas.ai/abi/Market": "#4169E1",
|
|
45
|
-
"http://ontology.naas.ai/abi/MarketSegment": "#6495ED",
|
|
46
|
-
"http://ontology.naas.ai/abi/LinkedInProfilePage": "#0A66C2",
|
|
47
|
-
"http://ontology.naas.ai/abi/IncomeStatement": "#847c35",
|
|
48
|
-
"http://ontology.naas.ai/abi/BalanceSheet": "#9d965d",
|
|
49
|
-
"http://ontology.naas.ai/abi/CashFlowStatement": "#c1bd9a",
|
|
50
|
-
# Finance Ontology
|
|
51
|
-
"http://ontology.naas.ai/abi/Revenue": "#bf9b30",
|
|
52
|
-
"http://ontology.naas.ai/abi/Expenses": "#bf9b30",
|
|
53
|
-
"http://ontology.naas.ai/abi/Profit": "#bf9b30",
|
|
54
|
-
"http://ontology.naas.ai/abi/EBITDA": "#bf9b30",
|
|
55
|
-
"http://ontology.naas.ai/abi/KPI": "#d4bf79",
|
|
56
|
-
# Facility Ontology
|
|
57
|
-
"http://ontology.naas.ai/abi/GlobalHeadquarters": "#9D7153",
|
|
58
|
-
"http://ontology.naas.ai/abi/RegionalHeadquarters": "#b0917c",
|
|
59
|
-
# Geospatial Ontology
|
|
60
|
-
"http://ontology.naas.ai/abi/Country": "#8e7010",
|
|
61
|
-
"http://ontology.naas.ai/abi/CountryISO3166-1": "#8e7010",
|
|
62
|
-
"http://ontology.naas.ai/abi/State": "#c6a84f",
|
|
63
|
-
"https://www.commoncoreontologies.org/ont00000887": "#aa8b26",
|
|
64
|
-
# Euronext Index
|
|
65
|
-
"http://ontology.naas.ai/abi/DataSource": "#5b1f00",
|
|
66
|
-
"http://ontology.naas.ai/abi/DataSourceComponent": "#713112",
|
|
67
|
-
"http://ontology.naas.ai/abi/TradingLocation": "#09a12d",
|
|
68
|
-
"http://ontology.naas.ai/abi/euronext#Index": "#7fed0e",
|
|
69
|
-
# LinkedIn
|
|
70
|
-
"http://ontology.naas.ai/abi/linkedin#LinkedInProfile": "white",
|
|
71
|
-
"http://ontology.naas.ai/abi/linkedin#PositionGroup": "white",
|
|
72
|
-
"http://ontology.naas.ai/abi/linkedin#Position": "grey",
|
|
73
|
-
"http://ontology.naas.ai/abi/linkedin#Language": "#D397F8",
|
|
74
|
-
"http://ontology.naas.ai/abi/linkedin#Skill": "#bd87df",
|
|
75
|
-
"http://ontology.naas.ai/abi/linkedin#Certification": "#76b3ec",
|
|
76
|
-
"http://ontology.naas.ai/abi/linkedin#Course": "#b9986d",
|
|
77
|
-
|
|
78
|
-
# "http://ontology.naas.ai/abi/linkedin#Skill": "white",
|
|
79
|
-
# "http://ontology.naas.ai/abi/linkedin#Education": "white",
|
|
80
|
-
# "http://ontology.naas.ai/abi/linkedin#Certification": "white",
|
|
81
|
-
# "http://ontology.naas.ai/abi/linkedin#Company": "white",
|
|
82
|
-
# "http://ontology.naas.ai/abi/linkedin#Industry": "white",
|
|
83
|
-
}
|
naas_abi/triggers.py
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
# This file defines triggers for the opendata module
|
|
2
|
-
# Triggers allow the module to react automatically to changes in the ontology store
|
|
3
|
-
# Each trigger consists of:
|
|
4
|
-
# 1. A triple pattern (subject, predicate, object) where None acts as a wildcard
|
|
5
|
-
# 2. An event type (OntologyEvent.INSERT or OntologyEvent.DELETE)
|
|
6
|
-
# 3. A callback function to execute when the event occurs
|
|
7
|
-
#
|
|
8
|
-
# Example:
|
|
9
|
-
# from naas_abi_core.services.triple_store.TripleStorePorts import OntologyEvent
|
|
10
|
-
# from rdflib import URIRef, Namespace
|
|
11
|
-
#
|
|
12
|
-
# ex = Namespace("http://example.org/")
|
|
13
|
-
#
|
|
14
|
-
# def handle_new_dataset(event_type, ontology_name, triple):
|
|
15
|
-
# subject, predicate, obj = triple
|
|
16
|
-
# # Process the new dataset here
|
|
17
|
-
#
|
|
18
|
-
# triggers = [
|
|
19
|
-
# ((None, URIRef(ex + "hasOpenData"), None), OntologyEvent.INSERT, handle_new_dataset),
|
|
20
|
-
# ]
|
|
21
|
-
|
|
22
|
-
import os
|
|
23
|
-
|
|
24
|
-
from naas_abi_core import logger, secret, services
|
|
25
|
-
from naas_abi_core.services.triple_store.TripleStorePorts import OntologyEvent
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
def is_production_mode():
|
|
29
|
-
"""Check if the application is running in production mode"""
|
|
30
|
-
return os.environ.get("ENV") != "dev"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def create_class_ontology_yaml():
|
|
34
|
-
"""Create class ontology YAML trigger - only active in production"""
|
|
35
|
-
if not is_production_mode():
|
|
36
|
-
logger.debug("Skipping class ontology YAML trigger - not in production mode")
|
|
37
|
-
return None
|
|
38
|
-
|
|
39
|
-
from naas_abi_marketplace.applications.naas.integrations.NaasIntegration import (
|
|
40
|
-
NaasIntegrationConfiguration,
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
from naas_abi.workflows.ConvertOntologyGraphToYamlWorkflow import (
|
|
44
|
-
ConvertOntologyGraphToYamlWorkflowConfiguration,
|
|
45
|
-
)
|
|
46
|
-
from naas_abi.workflows.CreateClassOntologyYamlWorkflow import (
|
|
47
|
-
CreateClassOntologyYamlWorkflow,
|
|
48
|
-
CreateClassOntologyYamlWorkflowConfiguration,
|
|
49
|
-
)
|
|
50
|
-
|
|
51
|
-
# Get secrets
|
|
52
|
-
naas_api_key = secret.get("NAAS_API_KEY")
|
|
53
|
-
if naas_api_key is None:
|
|
54
|
-
logger.error("NAAS_API_KEY is not set")
|
|
55
|
-
return None
|
|
56
|
-
|
|
57
|
-
# Configure Naas integration
|
|
58
|
-
naas_integration_config = NaasIntegrationConfiguration(api_key=naas_api_key)
|
|
59
|
-
|
|
60
|
-
# Configure ConvertOntologyGraphToYaml workflow
|
|
61
|
-
convert_ontology_graph_config = ConvertOntologyGraphToYamlWorkflowConfiguration(
|
|
62
|
-
naas_integration_config
|
|
63
|
-
)
|
|
64
|
-
workflow = CreateClassOntologyYamlWorkflow(
|
|
65
|
-
CreateClassOntologyYamlWorkflowConfiguration(
|
|
66
|
-
services.triple_store_service, convert_ontology_graph_config
|
|
67
|
-
)
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
# Subscribe to the trigger
|
|
71
|
-
logger.info("Activating class ontology YAML trigger in production mode")
|
|
72
|
-
return ((None, None, None), OntologyEvent.INSERT, workflow.trigger, True)
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
def create_individual_ontology_yaml():
|
|
76
|
-
"""Create individual ontology YAML trigger - only active in production"""
|
|
77
|
-
if not is_production_mode():
|
|
78
|
-
logger.debug(
|
|
79
|
-
"Skipping individual ontology YAML trigger - not in production mode"
|
|
80
|
-
)
|
|
81
|
-
return None
|
|
82
|
-
|
|
83
|
-
from naas_abi_marketplace.applications.naas.integrations.NaasIntegration import (
|
|
84
|
-
NaasIntegrationConfiguration,
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
from naas_abi.workflows.ConvertOntologyGraphToYamlWorkflow import (
|
|
88
|
-
ConvertOntologyGraphToYamlWorkflowConfiguration,
|
|
89
|
-
)
|
|
90
|
-
from naas_abi.workflows.CreateIndividualOntologyYamlWorkflow import (
|
|
91
|
-
CreateIndividualOntologyYamlWorkflow,
|
|
92
|
-
CreateIndividualOntologyYamlWorkflowConfiguration,
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
# Get secrets
|
|
96
|
-
naas_api_key = secret.get("NAAS_API_KEY")
|
|
97
|
-
if naas_api_key is None:
|
|
98
|
-
logger.error("NAAS_API_KEY is not set")
|
|
99
|
-
return None
|
|
100
|
-
|
|
101
|
-
# Configure Naas integration
|
|
102
|
-
naas_integration_config = NaasIntegrationConfiguration(api_key=naas_api_key)
|
|
103
|
-
|
|
104
|
-
# Configure ConvertOntologyGraphToYaml workflow
|
|
105
|
-
convert_ontology_graph_config = ConvertOntologyGraphToYamlWorkflowConfiguration(
|
|
106
|
-
naas_integration_config
|
|
107
|
-
)
|
|
108
|
-
workflow = CreateIndividualOntologyYamlWorkflow(
|
|
109
|
-
CreateIndividualOntologyYamlWorkflowConfiguration(
|
|
110
|
-
services.triple_store_service, convert_ontology_graph_config
|
|
111
|
-
)
|
|
112
|
-
)
|
|
113
|
-
|
|
114
|
-
# Subscribe to the trigger
|
|
115
|
-
logger.info("Activating individual ontology YAML trigger in production mode")
|
|
116
|
-
return ((None, None, None), OntologyEvent.INSERT, workflow.trigger, True)
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
# Filter out None values from triggers (when not in production mode)
|
|
120
|
-
# Skip triggers in test environment to avoid SSH tunnel initialization
|
|
121
|
-
if os.getenv("PYTEST_CURRENT_TEST") is not None or os.getenv("TESTING") == "true":
|
|
122
|
-
triggers = [] # Skip all triggers during testing
|
|
123
|
-
else:
|
|
124
|
-
triggers = [
|
|
125
|
-
trigger
|
|
126
|
-
for trigger in [
|
|
127
|
-
create_class_ontology_yaml(),
|
|
128
|
-
create_individual_ontology_yaml(),
|
|
129
|
-
]
|
|
130
|
-
if trigger is not None
|
|
131
|
-
]
|
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
from dataclasses import dataclass
|
|
2
|
-
from enum import Enum
|
|
3
|
-
from typing import Annotated, Dict, Optional
|
|
4
|
-
|
|
5
|
-
import pydash as _
|
|
6
|
-
import yaml
|
|
7
|
-
from langchain_core.tools import BaseTool, StructuredTool
|
|
8
|
-
from naas_abi import config, logger
|
|
9
|
-
from naas_abi.mappings import COLORS_NODES
|
|
10
|
-
from naas_abi_core.utils.Expose import APIRouter
|
|
11
|
-
from naas_abi_core.utils.OntologyYaml import OntologyYaml
|
|
12
|
-
from naas_abi_core.workflow import Workflow, WorkflowConfiguration
|
|
13
|
-
from naas_abi_core.workflow.workflow import WorkflowParameters
|
|
14
|
-
from naas_abi_marketplace.applications.naas.integrations.NaasIntegration import (
|
|
15
|
-
NaasIntegration,
|
|
16
|
-
NaasIntegrationConfiguration,
|
|
17
|
-
)
|
|
18
|
-
from pydantic import Field
|
|
19
|
-
from rdflib import Graph
|
|
20
|
-
from yaml import Dumper
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
@dataclass
|
|
24
|
-
class ConvertOntologyGraphToYamlWorkflowConfiguration(WorkflowConfiguration):
|
|
25
|
-
"""Configuration for ConvertOntologyGraphToYaml workflow.
|
|
26
|
-
|
|
27
|
-
Attributes:
|
|
28
|
-
naas_integration_config (NaasIntegrationConfiguration): Configuration for the Naas integration
|
|
29
|
-
"""
|
|
30
|
-
|
|
31
|
-
naas_integration_config: NaasIntegrationConfiguration
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
class ConvertOntologyGraphToYamlWorkflowParameters(WorkflowParameters):
|
|
35
|
-
"""Parameters for ConvertOntologyGraphToYaml workflow execution.
|
|
36
|
-
|
|
37
|
-
Attributes:
|
|
38
|
-
ontology_name (str): The name of the ontology store to use
|
|
39
|
-
label (str): The label of the ontology
|
|
40
|
-
description (str): The description of the ontology
|
|
41
|
-
logo_url (str): The URL of the ontology logo
|
|
42
|
-
level (str): The level of the ontology (e.g., 'TOP_LEVEL', 'MID_LEVEL', 'DOMAIN', 'USE_CASE')
|
|
43
|
-
display_relations_names (bool): Whether to display relation names in the visualization
|
|
44
|
-
"""
|
|
45
|
-
|
|
46
|
-
graph: Annotated[
|
|
47
|
-
str, Field(..., description="The graph serialized as turtle format")
|
|
48
|
-
]
|
|
49
|
-
ontology_id: Annotated[
|
|
50
|
-
Optional[str], Field(..., description="The ID of the ontology")
|
|
51
|
-
] = None
|
|
52
|
-
label: Annotated[str, Field(..., description="The label of the ontology")] = (
|
|
53
|
-
"New Ontology"
|
|
54
|
-
)
|
|
55
|
-
description: Annotated[
|
|
56
|
-
str,
|
|
57
|
-
Field(
|
|
58
|
-
...,
|
|
59
|
-
description="The description of the ontology. Example: 'Represents ABI Ontology with agents, workflows, ontologies, pipelines and integrations.'",
|
|
60
|
-
),
|
|
61
|
-
] = "New Ontology Description"
|
|
62
|
-
logo_url: Annotated[
|
|
63
|
-
Optional[str], Field(..., description="The logo URL of the ontology")
|
|
64
|
-
] = "https://naasai-public.s3.eu-west-3.amazonaws.com/abi-demo/ontology_ULO.png"
|
|
65
|
-
level: Annotated[str, Field(..., description="The level of the ontology")] = (
|
|
66
|
-
"USE_CASE"
|
|
67
|
-
)
|
|
68
|
-
display_relations_names: Annotated[
|
|
69
|
-
bool,
|
|
70
|
-
Field(
|
|
71
|
-
..., description="Whether to display relation names in the visualization"
|
|
72
|
-
),
|
|
73
|
-
] = True
|
|
74
|
-
class_colors_mapping: Annotated[
|
|
75
|
-
Dict, Field(..., description="The mapping of class colors")
|
|
76
|
-
] = COLORS_NODES
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
class ConvertOntologyGraphToYamlWorkflow(Workflow):
|
|
80
|
-
"""Workflow for converting ontology graph to YAML."""
|
|
81
|
-
|
|
82
|
-
__configuration: ConvertOntologyGraphToYamlWorkflowConfiguration
|
|
83
|
-
|
|
84
|
-
def __init__(self, configuration: ConvertOntologyGraphToYamlWorkflowConfiguration):
|
|
85
|
-
self.__configuration = configuration
|
|
86
|
-
self.__naas_integration = NaasIntegration(
|
|
87
|
-
self.__configuration.naas_integration_config
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
def graph_to_yaml(
|
|
91
|
-
self, parameters: ConvertOntologyGraphToYamlWorkflowParameters
|
|
92
|
-
) -> str:
|
|
93
|
-
# Initialize parameters
|
|
94
|
-
logger.debug(f"==> Converting ontology graph to YAML: {parameters.label}")
|
|
95
|
-
yaml_data = None
|
|
96
|
-
ontology_id = parameters.ontology_id
|
|
97
|
-
|
|
98
|
-
# Create Graph from turtle string
|
|
99
|
-
g = Graph()
|
|
100
|
-
g.parse(data=parameters.graph, format="turtle")
|
|
101
|
-
|
|
102
|
-
# Upload asset to Naas
|
|
103
|
-
asset = self.__naas_integration.upload_asset(
|
|
104
|
-
data=parameters.graph.encode("utf-8"), # Use the original turtle string
|
|
105
|
-
workspace_id=config.workspace_id,
|
|
106
|
-
storage_name=config.storage_name,
|
|
107
|
-
prefix="assets",
|
|
108
|
-
object_name=str(parameters.label + ".ttl"),
|
|
109
|
-
visibility="public",
|
|
110
|
-
)
|
|
111
|
-
# Save asset URL to JSON
|
|
112
|
-
if asset is None:
|
|
113
|
-
raise ValueError("Failed to upload asset to Naas")
|
|
114
|
-
|
|
115
|
-
asset_url = asset.get("asset", {}).get("url")
|
|
116
|
-
if not asset_url:
|
|
117
|
-
raise ValueError("Asset URL not found in response")
|
|
118
|
-
|
|
119
|
-
if asset_url.endswith("/"):
|
|
120
|
-
asset_url = asset_url[:-1]
|
|
121
|
-
|
|
122
|
-
# Convert to YAML
|
|
123
|
-
try:
|
|
124
|
-
yaml_data = OntologyYaml.rdf_to_yaml(
|
|
125
|
-
g,
|
|
126
|
-
display_relations_names=parameters.display_relations_names,
|
|
127
|
-
class_colors_mapping=parameters.class_colors_mapping,
|
|
128
|
-
)
|
|
129
|
-
except Exception as e:
|
|
130
|
-
message = f"Error converting ontology to YAML: {e}"
|
|
131
|
-
raise e
|
|
132
|
-
|
|
133
|
-
# Initialize parameters
|
|
134
|
-
if yaml_data is not None:
|
|
135
|
-
workspace_id = config.workspace_id
|
|
136
|
-
onto_label = parameters.label
|
|
137
|
-
onto_description = parameters.description
|
|
138
|
-
onto_logo_url = parameters.logo_url
|
|
139
|
-
onto_level = parameters.level
|
|
140
|
-
|
|
141
|
-
# Get ontology ID if it exists
|
|
142
|
-
ontologies = self.__naas_integration.get_ontologies(workspace_id).get(
|
|
143
|
-
"ontologies", []
|
|
144
|
-
)
|
|
145
|
-
for ontology in ontologies:
|
|
146
|
-
if (
|
|
147
|
-
ontology
|
|
148
|
-
and isinstance(ontology, dict)
|
|
149
|
-
and ontology.get("label") == onto_label
|
|
150
|
-
):
|
|
151
|
-
ontology_id = ontology.get("id")
|
|
152
|
-
break
|
|
153
|
-
|
|
154
|
-
if ontology_id is None:
|
|
155
|
-
# Create new ontology
|
|
156
|
-
res = self.__naas_integration.create_ontology(
|
|
157
|
-
workspace_id=workspace_id,
|
|
158
|
-
label=onto_label,
|
|
159
|
-
source=yaml.dump(yaml_data, Dumper=Dumper),
|
|
160
|
-
level=onto_level,
|
|
161
|
-
description=onto_description,
|
|
162
|
-
download_url=asset_url,
|
|
163
|
-
logo_url=onto_logo_url,
|
|
164
|
-
)
|
|
165
|
-
ontology_id = str(_.get(res, "ontology.id", ""))
|
|
166
|
-
message = (
|
|
167
|
-
f"✅ Ontology '{onto_label}' ({ontology_id}) successfully created."
|
|
168
|
-
)
|
|
169
|
-
else:
|
|
170
|
-
# Update existing ontology
|
|
171
|
-
res = self.__naas_integration.update_ontology(
|
|
172
|
-
workspace_id=workspace_id,
|
|
173
|
-
ontology_id=ontology_id,
|
|
174
|
-
source=yaml.dump(yaml_data, Dumper=Dumper),
|
|
175
|
-
level=onto_level,
|
|
176
|
-
description=onto_description,
|
|
177
|
-
download_url=asset_url,
|
|
178
|
-
logo_url=onto_logo_url,
|
|
179
|
-
)
|
|
180
|
-
message = (
|
|
181
|
-
f"✅ Ontology '{onto_label}' ({ontology_id}) successfully updated."
|
|
182
|
-
)
|
|
183
|
-
logger.info(message)
|
|
184
|
-
if ontology_id is None:
|
|
185
|
-
raise ValueError("Failed to create or update ontology")
|
|
186
|
-
return ontology_id
|
|
187
|
-
|
|
188
|
-
def as_tools(self) -> list[BaseTool]:
|
|
189
|
-
"""Returns a list of LangChain tools for this workflow."""
|
|
190
|
-
return [
|
|
191
|
-
StructuredTool(
|
|
192
|
-
name="convert_graph_to_yaml",
|
|
193
|
-
description="Convert an ontology graph to YAML.",
|
|
194
|
-
func=lambda **kwargs: self.graph_to_yaml(
|
|
195
|
-
ConvertOntologyGraphToYamlWorkflowParameters(**kwargs)
|
|
196
|
-
),
|
|
197
|
-
args_schema=ConvertOntologyGraphToYamlWorkflowParameters,
|
|
198
|
-
)
|
|
199
|
-
]
|
|
200
|
-
|
|
201
|
-
def as_api(
|
|
202
|
-
self,
|
|
203
|
-
router: APIRouter,
|
|
204
|
-
route_name: str = "",
|
|
205
|
-
name: str = "",
|
|
206
|
-
description: str = "",
|
|
207
|
-
description_stream: str = "",
|
|
208
|
-
tags: list[str | Enum] | None = None,
|
|
209
|
-
) -> None:
|
|
210
|
-
pass
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
from naas_abi import secret
|
|
3
|
-
from naas_abi.workflows.ConvertOntologyGraphToYamlWorkflow import (
|
|
4
|
-
ConvertOntologyGraphToYamlWorkflow,
|
|
5
|
-
ConvertOntologyGraphToYamlWorkflowConfiguration,
|
|
6
|
-
ConvertOntologyGraphToYamlWorkflowParameters,
|
|
7
|
-
)
|
|
8
|
-
from naas_abi_marketplace.applications.naas.integrations.NaasIntegration import (
|
|
9
|
-
NaasIntegration,
|
|
10
|
-
NaasIntegrationConfiguration,
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
@pytest.fixture
|
|
15
|
-
def workflow() -> ConvertOntologyGraphToYamlWorkflow:
|
|
16
|
-
return ConvertOntologyGraphToYamlWorkflow(
|
|
17
|
-
ConvertOntologyGraphToYamlWorkflowConfiguration(
|
|
18
|
-
NaasIntegrationConfiguration(api_key=secret.get("NAAS_API_KEY"))
|
|
19
|
-
)
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def test_convert_ontology_graph_to_yaml_workflow(
|
|
24
|
-
workflow: ConvertOntologyGraphToYamlWorkflow,
|
|
25
|
-
):
|
|
26
|
-
import time
|
|
27
|
-
from uuid import uuid4
|
|
28
|
-
|
|
29
|
-
from naas_abi import config, logger, services
|
|
30
|
-
from rdflib import OWL, RDF, RDFS, Graph, Literal, Namespace, URIRef
|
|
31
|
-
|
|
32
|
-
ABI = Namespace("http://ontology.naas.ai/abi/")
|
|
33
|
-
|
|
34
|
-
graph = Graph()
|
|
35
|
-
uri = ABI[str(uuid4())]
|
|
36
|
-
graph.add(
|
|
37
|
-
(uri, RDF.type, URIRef("https://www.commoncoreontologies.org/ont00000443"))
|
|
38
|
-
)
|
|
39
|
-
graph.add((uri, RDF.type, OWL.NamedIndividual))
|
|
40
|
-
graph.add((uri, RDFS.label, Literal("Naas.ai")))
|
|
41
|
-
graph.add(
|
|
42
|
-
(
|
|
43
|
-
uri,
|
|
44
|
-
ABI.logo,
|
|
45
|
-
Literal(
|
|
46
|
-
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9gXMaBLQZ39W6Pk53PRuzFjUvv_6lLRWPoQ&s"
|
|
47
|
-
),
|
|
48
|
-
)
|
|
49
|
-
)
|
|
50
|
-
services.triple_store_service.insert(graph)
|
|
51
|
-
time.sleep(3)
|
|
52
|
-
|
|
53
|
-
# Run workflow
|
|
54
|
-
ontology_id = workflow.graph_to_yaml(
|
|
55
|
-
ConvertOntologyGraphToYamlWorkflowParameters(
|
|
56
|
-
graph=graph.serialize(format="turtle"),
|
|
57
|
-
ontology_id=None,
|
|
58
|
-
label="Naas.ai",
|
|
59
|
-
description="Naas.ai Ontology",
|
|
60
|
-
logo_url="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ9gXMaBLQZ39W6Pk53PRuzFjUvv_6lLRWPoQ&s",
|
|
61
|
-
level="USE_CASE",
|
|
62
|
-
display_relations_names=True,
|
|
63
|
-
class_colors_mapping={},
|
|
64
|
-
)
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
# Remove graph
|
|
68
|
-
services.triple_store_service.remove(graph)
|
|
69
|
-
|
|
70
|
-
# Remove ontology
|
|
71
|
-
naas_integration = NaasIntegration(
|
|
72
|
-
NaasIntegrationConfiguration(api_key=secret.get("NAAS_API_KEY"))
|
|
73
|
-
)
|
|
74
|
-
result = naas_integration.delete_ontology(
|
|
75
|
-
workspace_id=config.workspace_id, ontology_id=ontology_id
|
|
76
|
-
)
|
|
77
|
-
logger.info(f"Removed ontology: {result}")
|
|
78
|
-
assert result is not None, result
|