Skip to content

Commit 21de536

Browse files
authored
Merge pull request #1044 from jupyter-naas/fix-ontology
fix(ontology): resolve local vs external name collisions and add Agent class
2 parents 20a50ae + 4d2d8da commit 21de536

5 files changed

Lines changed: 190 additions & 12 deletions

File tree

libs/naas-abi-core/naas_abi_core/utils/onto2py/onto2py.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ def _run_ontology_check(ttl_file_path: str) -> None:
7676
_CACHE_MARKER_PREFIX = "# onto2py-source-sha256: "
7777
# Bump this when the generator output format changes so previously cached
7878
# .py files are invalidated even when the source TTL hash matches.
79-
_CACHE_KEY_VERSION = "3-annotation-locator"
79+
_CACHE_KEY_VERSION = "4-local-external-name-collision"
8080

8181
# Annotation properties that let an ontology declare *where* it lives in the
8282
# Python package tree, so cross-package `owl:imports <https://canonical-iri>`
@@ -1240,6 +1240,33 @@ def _path_to_python_module(ttl_path: Path) -> str:
12401240
return ".".join(safe_parts)
12411241

12421242

1243+
def _resolve_local_external_name_collisions(
1244+
classes: Dict[str, ClassInfo],
1245+
) -> None:
1246+
"""Drop imported externals whose Python name collides with a local class.
1247+
1248+
A module can only bind one object to a given name. When the importer
1249+
defines a class whose ``rdfs:label`` matches an imported (external) class
1250+
of a different URI, the local definition is authoritative: it carries the
1251+
importer's intended properties and is what its own code references. The
1252+
external entry must be removed so it neither shadows the local class via an
1253+
``import`` nor pre-empts it in the name-keyed topological sort (which would
1254+
otherwise silently drop the local body entirely).
1255+
"""
1256+
local_names = {
1257+
cinfo.name
1258+
for cinfo in classes.values()
1259+
if cinfo.external_module is None
1260+
}
1261+
colliding_external_uris = [
1262+
uri
1263+
for uri, cinfo in classes.items()
1264+
if cinfo.external_module is not None and cinfo.name in local_names
1265+
]
1266+
for uri in colliding_external_uris:
1267+
del classes[uri]
1268+
1269+
12431270
def _extract_into(
12441271
g: rdflib.Graph,
12451272
classes: Dict[str, ClassInfo],
@@ -1477,6 +1504,14 @@ def onto2py(ttl_file: str | io.TextIOBase, overwrite: bool = False) -> str:
14771504
# because they were ingested with full property chains.
14781505
inherit_parent_properties(classes)
14791506

1507+
# Resolve Python-name collisions between a local class and an imported
1508+
# external class. Two ontology classes with different URIs but the same
1509+
# rdfs:label (e.g. abi:Agent and nexus:Agent) both map to one Python name.
1510+
# The importer's own definition is authoritative for that name, so drop
1511+
# the external entry — otherwise it both blocks the local class during
1512+
# the name-keyed topological sort and emits a shadowing `import`.
1513+
_resolve_local_external_name_collisions(classes)
1514+
14801515
# Add required metadata properties (rdfs:label, dcterms:created,
14811516
# dcterms:creator) to all *local* classes. External classes already had
14821517
# this applied during ingestion.

libs/naas-abi/naas_abi/ontologies/modules/ABIOntology.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# onto2py-source-sha256: 31ca4ad3740b72d15e69c04ae238bf9f75a48103d3cd9263289290152dffa6b9
1+
# onto2py-source-sha256: 40c058c224cb477120f279371db2578f8d88f01e4076bfe07a5481d26cbd368e
22
from __future__ import annotations
33

44
import datetime

libs/naas-abi/naas_abi/ontologies/modules/BFO7BucketsProcessOntology.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# onto2py-source-sha256: 94fdc4646e56c01df4a868e535cff24832099df4680bb3f752c5e4d86f8e97fc
1+
# onto2py-source-sha256: cea61faf003f8394fa31bbd9e55cc422888f069c09795ec10db93aa7539d5f37
22
from __future__ import annotations
33

44
import datetime

libs/naas-abi/naas_abi/ontologies/modules/NexusPlatformOntology.py

Lines changed: 148 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# onto2py-source-sha256: 6a584cb5560f23483ede25d5dc1ce9be7e153a5b5d8cb849a48ad3852ea808a0
1+
# onto2py-source-sha256: 7c2423bfe3ffb71cbffda5de998aec7b7f199516b5672181bc359890d3bd5c3d
22
from __future__ import annotations
33

44
import datetime
@@ -16,8 +16,11 @@
1616
get_origin,
1717
)
1818

19+
from pydantic import BaseModel, Field, ValidationError
20+
from rdflib import Graph, Literal, Namespace, URIRef
21+
from rdflib.namespace import OWL, RDF, RDFS, XSD
22+
1923
from naas_abi.ontologies.modules.ABIOntology import (
20-
Agent,
2124
Disposition,
2225
GenericallyDependentContinuant,
2326
MaterialEntity,
@@ -30,9 +33,6 @@
3033
TemporalInstant,
3134
TemporalRegion,
3235
)
33-
from pydantic import BaseModel, Field, ValidationError
34-
from rdflib import Graph, Literal, Namespace, URIRef
35-
from rdflib.namespace import OWL, RDF, RDFS, XSD
3636

3737
BFO = Namespace("http://purl.obolibrary.org/obo/")
3838
ABI = Namespace("http://ontology.naas.ai/abi/")
@@ -1007,6 +1007,148 @@ class Message(GenericallyDependentContinuant, RDFEntity):
10071007
] = None
10081008

10091009

1010+
class Agent(GenericallyDependentContinuant, RDFEntity):
1011+
"""
1012+
Agent
1013+
"""
1014+
1015+
_class_uri: ClassVar[str] = "http://ontology.naas.ai/nexus/Agent"
1016+
_name: ClassVar[str] = "Agent"
1017+
_property_uris: ClassVar[dict] = {
1018+
"class_name": "http://ontology.naas.ai/nexus/class_name",
1019+
"class_path": "http://ontology.naas.ai/nexus/class_path",
1020+
"created": "http://purl.org/dc/terms/created",
1021+
"creator": "http://purl.org/dc/terms/creator",
1022+
"description": "http://ontology.naas.ai/nexus/description",
1023+
"generically_depends_on": "http://ontology.naas.ai/abi/genericallyDependsOn",
1024+
"has_agent_role": "http://ontology.naas.ai/nexus/hasAgentRole",
1025+
"has_intent": "http://ontology.naas.ai/nexus/hasAgentIntent",
1026+
"has_subagent": "http://ontology.naas.ai/nexus/hasSubAgent",
1027+
"has_tool": "http://ontology.naas.ai/nexus/hasAgentTool",
1028+
"is_concretized_by": "http://ontology.naas.ai/abi/isConcretizedBy",
1029+
"is_subagent_of": "http://ontology.naas.ai/nexus/isSubAgentOf",
1030+
"label": "http://www.w3.org/2000/01/rdf-schema#label",
1031+
"logo_url": "http://ontology.naas.ai/nexus/logo_url",
1032+
"module_path": "http://ontology.naas.ai/nexus/module_path",
1033+
"system_prompt": "http://ontology.naas.ai/nexus/system_prompt",
1034+
"uses_model": "http://ontology.naas.ai/nexus/usesModel",
1035+
}
1036+
_object_properties: ClassVar[set[str]] = {
1037+
"generically_depends_on",
1038+
"has_agent_role",
1039+
"has_intent",
1040+
"has_subagent",
1041+
"has_tool",
1042+
"is_concretized_by",
1043+
"is_subagent_of",
1044+
"uses_model",
1045+
}
1046+
1047+
# Data properties
1048+
description: Optional[
1049+
Annotated[
1050+
str,
1051+
Field(
1052+
description="A description used in Nexus platform to identify a generically dependent continuant instance."
1053+
),
1054+
]
1055+
] = None
1056+
logo_url: Optional[
1057+
Annotated[
1058+
str,
1059+
Field(
1060+
description="A URL to a logo image used in Nexus platform to identify a generically dependent continuant instance."
1061+
),
1062+
]
1063+
] = None
1064+
class_name: Optional[Annotated[str, Field(description="Agent class name.")]] = None
1065+
module_path: Optional[
1066+
Annotated[str, Field(description="Agent module path in naas-abi.")]
1067+
] = None
1068+
class_path: Optional[
1069+
Annotated[str, Field(description="Agent module path and class name.")]
1070+
] = None
1071+
system_prompt: Optional[
1072+
Annotated[
1073+
str,
1074+
Field(
1075+
description="A system prompt used in Nexus platform to configure a software agent."
1076+
),
1077+
]
1078+
] = None
1079+
label: Optional[Annotated[str, Field(description="Label of the resource.")]] = None
1080+
created: Optional[
1081+
Annotated[
1082+
datetime.datetime,
1083+
Field(description="Date of creation of the resource."),
1084+
]
1085+
] = None
1086+
creator: Optional[
1087+
Annotated[
1088+
Any,
1089+
Field(description="An entity responsible for making the resource."),
1090+
]
1091+
] = None
1092+
1093+
# Object properties
1094+
generically_depends_on: Optional[
1095+
Annotated[
1096+
List[Union[MaterialEntity, URIRef, str]],
1097+
Field(
1098+
description="b generically depends on c =Def b is a generically dependent continuant & c is an independent continuant that is not a spatial region & at some time t there inheres in c a specifically dependent continuant which concretizes b at t"
1099+
),
1100+
]
1101+
] = None
1102+
has_agent_role: Optional[
1103+
Annotated[
1104+
List[Union[AgentRole, URIRef, str]],
1105+
Field(
1106+
description="Relates an agent to an agent role that concretizes it in platform use."
1107+
),
1108+
]
1109+
] = None
1110+
has_intent: Optional[
1111+
Annotated[
1112+
List[Union[AgentIntent, URIRef, str]],
1113+
Field(description="Relates an agent to an intent available to it."),
1114+
]
1115+
] = None
1116+
has_subagent: Optional[
1117+
Annotated[
1118+
List[Union[Agent, URIRef, str]],
1119+
Field(
1120+
description="Relates a supervisor agent to a sub-agent it orchestrates within the Nexus platform."
1121+
),
1122+
]
1123+
] = None
1124+
has_tool: Optional[
1125+
Annotated[
1126+
List[Union[AgentTool, URIRef, str]],
1127+
Field(description="Relates an agent to a tool available to it."),
1128+
]
1129+
] = None
1130+
is_concretized_by: Optional[
1131+
Annotated[
1132+
List[Union[Disposition, Process, Quality, Role, URIRef, str]],
1133+
Field(description="c is concretized by b =Def b concretizes c"),
1134+
]
1135+
] = None
1136+
is_subagent_of: Optional[
1137+
Annotated[
1138+
List[Union[Agent, URIRef, str]],
1139+
Field(
1140+
description="Relates a sub-agent to the supervisor agent that orchestrates it within the Nexus platform."
1141+
),
1142+
]
1143+
] = None
1144+
uses_model: Optional[
1145+
Annotated[
1146+
List[Union[AIModel, URIRef, str]],
1147+
Field(description="Relates an agent to the AI model it uses."),
1148+
]
1149+
] = None
1150+
1151+
10101152
class AgentTool(GenericallyDependentContinuant, RDFEntity):
10111153
"""
10121154
Agent Tool
@@ -4680,6 +4822,7 @@ class Logout(Process, RDFEntity):
46804822
Search.model_rebuild()
46814823
Conversation.model_rebuild()
46824824
Message.model_rebuild()
4825+
Agent.model_rebuild()
46834826
AgentTool.model_rebuild()
46844827
AgentIntent.model_rebuild()
46854828
Ontology.model_rebuild()

uv.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)