naas-abi 1.0.0__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.
Files changed (62) hide show
  1. naas_abi/__init__.py +35 -0
  2. naas_abi/agents/AbiAgent.py +442 -0
  3. naas_abi/agents/AbiAgent_test.py +157 -0
  4. naas_abi/agents/EntitytoSPARQLAgent.py +952 -0
  5. naas_abi/agents/EntitytoSPARQLAgent_test.py +66 -0
  6. naas_abi/agents/KnowledgeGraphBuilderAgent.py +321 -0
  7. naas_abi/agents/KnowledgeGraphBuilderAgent_test.py +86 -0
  8. naas_abi/agents/OntologyEngineerAgent.py +115 -0
  9. naas_abi/agents/OntologyEngineerAgent_test.py +42 -0
  10. naas_abi/apps/oxigraph_admin/main.py +392 -0
  11. naas_abi/apps/oxigraph_admin/terminal_style.py +151 -0
  12. naas_abi/apps/sparql_terminal/main.py +68 -0
  13. naas_abi/apps/sparql_terminal/terminal_style.py +236 -0
  14. naas_abi/apps/terminal_agent/main.py +553 -0
  15. naas_abi/apps/terminal_agent/terminal_style.py +175 -0
  16. naas_abi/cli.py +714 -0
  17. naas_abi/mappings.py +83 -0
  18. naas_abi/models/airgap_gemma.py +220 -0
  19. naas_abi/models/airgap_qwen.py +24 -0
  20. naas_abi/models/default.py +23 -0
  21. naas_abi/models/gpt_4_1.py +25 -0
  22. naas_abi/pipelines/AIAgentOntologyGenerationPipeline.py +635 -0
  23. naas_abi/pipelines/AIAgentOntologyGenerationPipeline_test.py +133 -0
  24. naas_abi/pipelines/AddIndividualPipeline.py +215 -0
  25. naas_abi/pipelines/AddIndividualPipeline_test.py +66 -0
  26. naas_abi/pipelines/InsertDataSPARQLPipeline.py +197 -0
  27. naas_abi/pipelines/InsertDataSPARQLPipeline_test.py +96 -0
  28. naas_abi/pipelines/MergeIndividualsPipeline.py +245 -0
  29. naas_abi/pipelines/MergeIndividualsPipeline_test.py +98 -0
  30. naas_abi/pipelines/RemoveIndividualPipeline.py +166 -0
  31. naas_abi/pipelines/RemoveIndividualPipeline_test.py +58 -0
  32. naas_abi/pipelines/UpdateCommercialOrganizationPipeline.py +198 -0
  33. naas_abi/pipelines/UpdateDataPropertyPipeline.py +175 -0
  34. naas_abi/pipelines/UpdateLegalNamePipeline.py +107 -0
  35. naas_abi/pipelines/UpdateLinkedInPagePipeline.py +179 -0
  36. naas_abi/pipelines/UpdatePersonPipeline.py +184 -0
  37. naas_abi/pipelines/UpdateSkillPipeline.py +118 -0
  38. naas_abi/pipelines/UpdateTickerPipeline.py +104 -0
  39. naas_abi/pipelines/UpdateWebsitePipeline.py +106 -0
  40. naas_abi/triggers.py +131 -0
  41. naas_abi/workflows/AgentRecommendationWorkflow.py +321 -0
  42. naas_abi/workflows/AgentRecommendationWorkflow_test.py +160 -0
  43. naas_abi/workflows/ArtificialAnalysisWorkflow.py +337 -0
  44. naas_abi/workflows/ArtificialAnalysisWorkflow_test.py +57 -0
  45. naas_abi/workflows/ConvertOntologyGraphToYamlWorkflow.py +210 -0
  46. naas_abi/workflows/ConvertOntologyGraphToYamlWorkflow_test.py +78 -0
  47. naas_abi/workflows/CreateClassOntologyYamlWorkflow.py +208 -0
  48. naas_abi/workflows/CreateClassOntologyYamlWorkflow_test.py +65 -0
  49. naas_abi/workflows/CreateIndividualOntologyYamlWorkflow.py +183 -0
  50. naas_abi/workflows/CreateIndividualOntologyYamlWorkflow_test.py +86 -0
  51. naas_abi/workflows/ExportGraphInstancesToExcelWorkflow.py +450 -0
  52. naas_abi/workflows/ExportGraphInstancesToExcelWorkflow_test.py +33 -0
  53. naas_abi/workflows/GetObjectPropertiesFromClassWorkflow.py +385 -0
  54. naas_abi/workflows/GetObjectPropertiesFromClassWorkflow_test.py +57 -0
  55. naas_abi/workflows/GetSubjectGraphWorkflow.py +84 -0
  56. naas_abi/workflows/GetSubjectGraphWorkflow_test.py +71 -0
  57. naas_abi/workflows/SearchIndividualWorkflow.py +190 -0
  58. naas_abi/workflows/SearchIndividualWorkflow_test.py +98 -0
  59. naas_abi-1.0.0.dist-info/METADATA +9 -0
  60. naas_abi-1.0.0.dist-info/RECORD +62 -0
  61. naas_abi-1.0.0.dist-info/WHEEL +5 -0
  62. naas_abi-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,952 @@
1
+ from datetime import datetime
2
+ from queue import Queue
3
+ from typing import Any, Callable, Optional, Union
4
+
5
+ from langchain_core.language_models import BaseChatModel
6
+ from langchain_core.messages import AIMessage, BaseMessage, SystemMessage
7
+ from langchain_core.tools import BaseTool, Tool
8
+ from langchain_openai import ChatOpenAI # noqa: F401
9
+ from langgraph.checkpoint.base import BaseCheckpointSaver
10
+ from langgraph.checkpoint.memory import MemorySaver
11
+ from langgraph.graph import START, StateGraph
12
+ from langgraph.graph.message import MessagesState
13
+ from langgraph.types import Command
14
+ from naas_abi import ABIModule
15
+
16
+ # from naas_abi import secret
17
+ from naas_abi_core.engine.EngineProxy import ServicesProxy
18
+ from naas_abi_core.models.Model import ChatModel
19
+ from naas_abi_core.services.agent.Agent import (
20
+ Agent,
21
+ AgentConfiguration,
22
+ AgentSharedState,
23
+ )
24
+
25
+ MODULE: ABIModule = ABIModule.get_instance()
26
+ SERVICES: ServicesProxy = MODULE.engine.services
27
+
28
+ NAME = "Entity_to_SPARQL"
29
+ DESCRIPTION = "A agent that extracts entities from text and transform them into SPARQL INSERT DATA statements."
30
+ SYSTEM_PROMPT = """
31
+ # ROLE:
32
+ You are an expert Ontology Engineer specialized in extracting entities from text and transforming them into SPARQL INSERT DATA statements using the BFO (Basic Formal Ontology) framework.
33
+
34
+ # OBJECTIVE:
35
+ Transform extracted entities and their relationships into well-structured, semantically accurate SPARQL INSERT DATA statements with clear explanations for non-technical users.
36
+
37
+ # CONTEXT:
38
+ You will receive prompts from different agents containing:
39
+ - Initial text for entity extraction
40
+ - List of entities mapped to BFO Ontology classes
41
+ - List of object properties defining relationships between entity classes
42
+
43
+ # TASK:
44
+ Present a comprehensive analysis that includes:
45
+ 1. Original text acknowledgment
46
+ 2. Detailed entity extraction explanation with BFO reasoning
47
+ 3. Relationship analysis and justification
48
+ 4. Complete SPARQL INSERT DATA statement with annotations
49
+
50
+ # OPERATING GUIDELINES:
51
+
52
+ ## 1. ORIGINAL TEXT PRESENTATION
53
+ Start your response by acknowledging the source material:
54
+ ```
55
+ ## Entity Extraction Analysis
56
+
57
+ I am analyzing the following original text to extract ontological entities:
58
+
59
+ ```text
60
+ {original_text}
61
+ ```
62
+ ```
63
+
64
+ ## 2. ENTITY EXTRACTION EXPLANATION
65
+ Provide a detailed explanation of extracted entities:
66
+ ```
67
+ ## Extracted Entities
68
+
69
+ Based on the BFO ontological framework, I have identified the following entities:
70
+
71
+ ### Continuants (Entities that persist through time)
72
+ - **[Entity Name]** → `[BFO Class Label]` (`[BFO URI]`)
73
+ - **Reasoning**: [Clear explanation of why this entity belongs to this BFO class]
74
+ - **Ontological Significance**: [What this classification means in the context]
75
+
76
+ ### Occurrents (Processes, events, or temporal regions)
77
+ - **[Entity Name]** → `[BFO Class Label]` (`[BFO URI]`)
78
+ - **Reasoning**: [Clear explanation of why this entity belongs to this BFO class]
79
+ - **Temporal Characteristics**: [How this entity unfolds in time]
80
+
81
+ ### Relationships Identified
82
+ - **[Relationship Type]**: [Entity A] → [Entity B]
83
+ - **Justification**: [Why this relationship exists based on the text and BFO principles]
84
+ ```
85
+
86
+ ## 3. SPARQL STATEMENT PRESENTATION
87
+ Present the SPARQL statement with comprehensive annotations:
88
+ ```
89
+ ## SPARQL INSERT DATA Statement
90
+
91
+ The following SPARQL statement creates the ontological representation of the extracted entities:
92
+
93
+ ```sparql
94
+ # Namespace Prefixes
95
+ PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
96
+ PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
97
+ PREFIX bfo: <http://purl.obolibrary.org/obo/>
98
+ PREFIX abi: <http://ontology.naas.ai/abi/>
99
+
100
+ INSERT DATA {
101
+ # [Entity Type]: [Entity Description]
102
+ abi:[entity-uuid] rdf:type bfo:[BFO_CLASS] ;
103
+ rdfs:label "[Entity Label]" ;
104
+ rdfs:comment "[Detailed description of the entity]" .
105
+
106
+ # Relationships between entities
107
+ abi:[entity1-uuid] bfo:[relationship-property] abi:[entity2-uuid] .
108
+ }
109
+ ```
110
+
111
+ ### Statement Explanation:
112
+ - **Entity Types**: Each entity is classified using appropriate BFO classes
113
+ - **Labels**: Human-readable names for each entity
114
+ - **Comments**: Detailed descriptions providing context and meaning
115
+ - **Relationships**: Semantic connections between entities based on BFO object properties
116
+ ```
117
+
118
+ ## 4. FORMATTING REQUIREMENTS
119
+ - Use clear markdown headers (##, ###) for section organization
120
+ - Employ consistent bullet points and numbering
121
+ - Include code blocks with appropriate syntax highlighting
122
+ - Use **bold** for entity names and important concepts
123
+ - Use `backticks` for technical terms and URIs
124
+ - Provide line breaks between sections for readability
125
+
126
+ ## 5. LANGUAGE AND TONE
127
+ - Use clear, accessible language suitable for non-ontologists
128
+ - Explain technical concepts in plain English
129
+ - Provide context for BFO classifications
130
+ - Be precise but not overly technical
131
+ - Include reasoning for each classification decision
132
+
133
+ # CONSTRAINTS:
134
+ - NEVER create new entities not present in the provided list
135
+ - ALWAYS use the exact URIs provided for each entity
136
+ - MUST provide clear reasoning for each BFO classification
137
+ - MUST include comprehensive comments in the SPARQL statement
138
+ - MUST explain relationships between entities when they exist
139
+ - MUST maintain consistency between explanations and SPARQL code
140
+ - MUST use proper SPARQL syntax with all required prefixes
141
+ - MUST ensure all statements are semantically valid according to BFO principles
142
+ """
143
+
144
+
145
+ def create_agent(
146
+ agent_shared_state: Optional[AgentSharedState] = None,
147
+ agent_configuration: Optional[AgentConfiguration] = None,
148
+ ) -> Optional[Agent]:
149
+ # Set model based on AI_MODE
150
+ ai_mode = MODULE.configuration.global_config.ai_mode
151
+
152
+ if ai_mode == "airgap":
153
+ from naas_abi.models.default import get_model
154
+
155
+ model = get_model()
156
+ else:
157
+ from naas_abi_marketplace.ai.chatgpt.models.o3_mini import model
158
+
159
+ if agent_configuration is None:
160
+ agent_configuration = AgentConfiguration(system_prompt=SYSTEM_PROMPT)
161
+
162
+ # Use provided shared state or create new one
163
+ if agent_shared_state is None:
164
+ agent_shared_state = AgentSharedState()
165
+
166
+ return EntitytoSPARQLAgent(
167
+ name=NAME,
168
+ description=DESCRIPTION,
169
+ chat_model=model,
170
+ tools=[],
171
+ agents=[],
172
+ memory=MemorySaver(),
173
+ state=agent_shared_state,
174
+ configuration=agent_configuration,
175
+ )
176
+
177
+
178
+ class EntityExtractionState(MessagesState):
179
+ """State class for entity extraction conversations.
180
+
181
+ Extends MessagesState to include entity extraction information that tracks
182
+ the extracted entities and their relationships throughout the conversation flow.
183
+
184
+ Attributes:
185
+ entities (list[dict[str, Any]]): List of extracted entities with their BFO mappings
186
+ object_properties (list[dict[str, Any]]): List of object properties for entity relationships
187
+ """
188
+
189
+ entities: list[dict[str, Any]]
190
+ object_properties: list[dict[str, Any]]
191
+
192
+
193
+ class EntitytoSPARQLAgent(Agent):
194
+ def __init__(
195
+ self,
196
+ name: str,
197
+ description: str,
198
+ chat_model: BaseChatModel | ChatModel,
199
+ tools: list[Union[Tool, BaseTool, "Agent"]] = [],
200
+ agents: list["Agent"] = [],
201
+ memory: BaseCheckpointSaver = MemorySaver(),
202
+ state: AgentSharedState = AgentSharedState(),
203
+ configuration: AgentConfiguration = AgentConfiguration(),
204
+ event_queue: Queue | None = None,
205
+ ):
206
+ super().__init__(
207
+ name,
208
+ description,
209
+ chat_model,
210
+ tools,
211
+ agents,
212
+ memory,
213
+ state,
214
+ configuration,
215
+ event_queue,
216
+ )
217
+
218
+ self.datastore_path = f"datastore/ontology/entities_to_sparql/{datetime.now().strftime('%Y%m%d%H%M%S')}"
219
+
220
+ def entity_extract(self, state: EntityExtractionState) -> Command:
221
+ """
222
+ This node is used to extract the entities from the last message.
223
+ """
224
+
225
+ system_prompt = """
226
+ # ROLE:
227
+ You are a BFO Ontology Expert in entity extraction.
228
+
229
+ # OBJECTIVE:
230
+ Extract entities from the message and return a structured JSON representing the BFO representation of the entities.
231
+
232
+ # CONTEXT:
233
+ You will receive message from user or from Ontology Engineer Agent.
234
+ You must use BFO Ontology as your knowledge base for the mapping.
235
+ The current date is {{current_date}}.
236
+
237
+ # TASK:
238
+ - Extract entities from the message.
239
+ - Map entities to the BFO Ontology
240
+ - Return the entities in a JSON format.
241
+
242
+ # OPERATING GUIDELINES:
243
+ 1. Extract all entities from the message using BFO ontology.
244
+ Use the following BFO definition of class 'entity' and its 2 main subclasses:
245
+ ```turtle
246
+ <http://purl.obolibrary.org/obo/BFO_0000001> rdf:type owl:Class ;
247
+ dc11:identifier "001-BFO" ;
248
+ rdfs:label "entity"@en ;
249
+ skos:definition "(Elucidation) An entity is anything that exists or has existed or will exist"@en ;
250
+ skos:example "Julius Caesar; the Second World War; your body mass index; Verdi's Requiem"@en .
251
+
252
+ <http://purl.obolibrary.org/obo/BFO_0000002> rdf:type owl:Class ;
253
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000001> ,
254
+ [ rdf:type owl:Restriction ;
255
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000176> ;
256
+ owl:allValuesFrom <http://purl.obolibrary.org/obo/BFO_0000002>
257
+ ] ;
258
+ owl:disjointWith <http://purl.obolibrary.org/obo/BFO_0000003> ;
259
+ dc11:identifier "008-BFO" ;
260
+ rdfs:label "continuant"@en ;
261
+ skos:definition "(Elucidation) A continuant is an entity that persists, endures, or continues to exist through time while maintaining its identity"@en ;
262
+ skos:example "A human being; a tennis ball; a cave; a region of space; someone's temperature"@en .
263
+
264
+ <http://purl.obolibrary.org/obo/BFO_0000003> rdf:type owl:Class ;
265
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000001> ;
266
+ dc11:identifier "077-BFO" ;
267
+ rdfs:label "occurrent"@en ;
268
+ skos:definition "(Elucidation) An occurrent is an entity that unfolds itself in time or it is the start or end of such an entity or it is a temporal or spatiotemporal region"@en ;
269
+ skos:example "As for process, history, process boundary, spatiotemporal region, zero-dimensional temporal region, one-dimensional temporal region, temporal interval, temporal instant."@en .
270
+ ```
271
+
272
+ 2. Map entities to the BFO Ontology subclasses of 'Continuants' and 'Occurrents' classes.
273
+ Try to be as precise as possible finding the right BFO class for the entity.
274
+ If you find you missed entities, you can add it again in the message.
275
+ "Continuants":
276
+ ```turtle
277
+ <http://purl.obolibrary.org/obo/BFO_0000020> rdf:type owl:Class ;
278
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000002> ;
279
+ dc11:identifier "050-BFO" ;
280
+ rdfs:label "specifically dependent continuant"@en ;
281
+ skos:definition "b is a specifically dependent continuant =Def b is a continuant & there is some independent continuant c which is not a spatial region & which is such that b specifically depends on c"@en ;
282
+ skos:example "(with multiple bearers) John's love for Mary; the ownership relation between John and this statue; the relation of authority between John and his subordinates"@en ,
283
+ "(with one bearer) The mass of this tomato; the pink colour of a medium rare piece of grilled filet mignon at its centre; the smell of this portion of mozzarella; the disposition of this fish to decay; the role of being a doctor; the function of this heart to pump blood; the shape of this hole"@en .
284
+
285
+ <http://purl.obolibrary.org/obo/BFO_0000017> rdf:type owl:Class ;
286
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000020> ;
287
+ owl:disjointWith <http://purl.obolibrary.org/obo/BFO_0000019> ;
288
+ dc11:identifier "058-BFO" ;
289
+ rdfs:label "realizable entity"@en ;
290
+ skos:definition "(Elucidation) A realizable entity is a specifically dependent continuant that inheres in some independent continuant which is not a spatial region & which is of a type some instances of which are realized in processes of a correlated type"@en ;
291
+ skos:example "The role of being a doctor; the role of this boundary to delineate where Utah and Colorado meet; the function of your reproductive organs; the disposition of your blood to coagulate; the disposition of this piece of metal to conduct electricity"@en .
292
+
293
+ <http://purl.obolibrary.org/obo/BFO_0000023> rdf:type owl:Class ;
294
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000017> ;
295
+ dc11:identifier "061-BFO" ;
296
+ rdfs:label "role"@en ;
297
+ skos:altLabel "externally-grounded realizable entity"@en ;
298
+ skos:definition "(Elucidation) A role b is a realizable entity such that b exists because there is some single bearer that is in some special physical, social, or institutional set of circumstances in which this bearer does not have to be & b is not such that, if it ceases to exist, then the physical make-up of the bearer is thereby changed"@en ;
299
+ skos:example "The priest role; the student role; the role of subject in a clinical trial; the role of a stone in marking a property boundary; the role of a boundary to demarcate two neighbouring administrative territories; the role of a building in serving as a military target"@en .
300
+
301
+ <http://purl.obolibrary.org/obo/BFO_0000016> rdf:type owl:Class ;
302
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000017> ;
303
+ owl:disjointWith <http://purl.obolibrary.org/obo/BFO_0000023> ;
304
+ dc11:identifier "062-BFO" ;
305
+ rdfs:label "disposition"@en ;
306
+ skos:altLabel "internally-grounded realizable entity"@en ;
307
+ skos:definition "(Elucidation) A disposition b is a realizable entity such that if b ceases to exist then its bearer is physically changed & b's realization occurs when and because this bearer is in some special physical circumstances & this realization occurs in virtue of the bearer's physical make-up"@en ;
308
+ skos:example "An atom of element X has the disposition to decay to an atom of element Y; the cell wall is disposed to transport cellular material through endocytosis and exocytosis; certain people have a predisposition to colon cancer; children are innately disposed to categorize objects in certain ways"@en .
309
+
310
+ <http://purl.obolibrary.org/obo/BFO_0000034> rdf:type owl:Class ;
311
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000016> ;
312
+ dc11:identifier "064-BFO" ;
313
+ rdfs:label "function"@en ;
314
+ skos:definition "(Elucidation) A function is a disposition that exists in virtue of its bearer's physical make-up & this physical make-up is something the bearer possesses because it came into being either through evolution (in the case of natural biological entities) or through intentional design (in the case of artefacts) in order to realize processes of a certain sort"@en ;
315
+ skos:example "The function of a hammer to drive in nails; the function of a heart pacemaker to regulate the beating of a heart through electricity"@en .
316
+
317
+ <http://purl.obolibrary.org/obo/BFO_0000019> rdf:type owl:Class ;
318
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000020> ;
319
+ dc11:identifier "055-BFO" ;
320
+ rdfs:label "quality"@en ;
321
+ skos:definition "(Elucidation) A quality is a specifically dependent continuant that, in contrast to roles and dispositions, does not require any further process in order to be realized"@en ;
322
+ skos:example "The colour of a tomato; the ambient temperature of this portion of air; the length of the circumference of your waist; the shape of your nose; the shape of your nostril; the mass of this piece of gold"@en .
323
+
324
+ <http://purl.obolibrary.org/obo/BFO_0000145> rdf:type owl:Class ;
325
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000019> ;
326
+ dc11:identifier "057-BFO" ;
327
+ rdfs:label "relational quality"@en ;
328
+ skos:definition "b is a relational quality =Def b is a quality & there exists c and d such that c and d are not identical & b specifically depends on c & b specifically depends on d"@en ;
329
+ skos:example "A marriage bond; an instance of love; an obligation between one person and another"@en .
330
+
331
+ <http://purl.obolibrary.org/obo/BFO_0000024> rdf:type owl:Class ;
332
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000040> ;
333
+ dc11:identifier "027-BFO" ;
334
+ rdfs:label "fiat object part"@en ;
335
+ skos:definition "(Elucidation) A fiat object part b is a material entity & such that if b exists then it is continuant part of some object c & demarcated from the remainder of c by one or more fiat surfaces"@en ;
336
+ skos:example "The upper and lower lobes of the left lung; the dorsal and ventral surfaces of the body; the Western hemisphere of the Earth; the FMA:regional parts of an intact human body"@en .
337
+
338
+ <http://purl.obolibrary.org/obo/BFO_0000031> rdf:type owl:Class ;
339
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000002> ;
340
+ dc11:identifier "074-BFO" ;
341
+ rdfs:label "generically dependent continuant"@en ;
342
+ skos:altLabel "g-dependent continuant"@en ;
343
+ skos:definition "(Elucidation) A generically dependent continuant is an entity that exists in virtue of the fact that there is at least one of what may be multiple copies which is the content or the pattern that multiple copies would share"@en ;
344
+ skos:example "The pdf file on your laptop; the pdf file that is a copy thereof on my laptop; the sequence of this protein molecule; the sequence that is a copy thereof in that protein molecule; the content that is shared by a string of dots and dashes written on a page and the transmitted Morse code signal; the content of a sentence; an engineering blueprint"@en .
345
+
346
+ <http://purl.obolibrary.org/obo/BFO_0000004> rdf:type owl:Class ;
347
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000002> ,
348
+ [ rdf:type owl:Restriction ;
349
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000176> ;
350
+ owl:allValuesFrom <http://purl.obolibrary.org/obo/BFO_0000004>
351
+ ] ;
352
+ dc11:identifier "017-BFO" ;
353
+ rdfs:label "independent continuant"@en ;
354
+ skos:definition "b is an independent continuant =Def b is a continuant & there is no c such that b specifically depends on c or b generically depends on c"@en ;
355
+ skos:example "An atom; a molecule; an organism; a heart; a chair; the bottom right portion of a human torso; a leg; the interior of your mouth; a spatial region; an orchestra"@en .
356
+
357
+ <http://purl.obolibrary.org/obo/BFO_0000040> rdf:type owl:Class ;
358
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000004> ,
359
+ [ rdf:type owl:Restriction ;
360
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000176> ;
361
+ owl:allValuesFrom <http://purl.obolibrary.org/obo/BFO_0000040>
362
+ ] ,
363
+ [ rdf:type owl:Restriction ;
364
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000178> ;
365
+ owl:allValuesFrom [ rdf:type owl:Class ;
366
+ owl:unionOf ( <http://purl.obolibrary.org/obo/BFO_0000029>
367
+ <http://purl.obolibrary.org/obo/BFO_0000040>
368
+ <http://purl.obolibrary.org/obo/BFO_0000140>
369
+ )
370
+ ]
371
+ ] ;
372
+ owl:disjointWith <http://purl.obolibrary.org/obo/BFO_0000141> ;
373
+ dc11:identifier "019-BFO" ;
374
+ rdfs:label "material entity"@en ;
375
+ skos:definition "(Elucidation) A material entity is an independent continuant has some portion of matter as continuant part"@en ;
376
+ skos:example "A human being; the undetached arm of a human being; an aggregate of human beings"@en .
377
+
378
+ <http://purl.obolibrary.org/obo/BFO_0000030> rdf:type owl:Class ;
379
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000040> ;
380
+ dc11:identifier "024-BFO" ;
381
+ rdfs:label "object"@en ;
382
+ skos:definition "(Elucidation) An object is a material entity which manifests causal unity & is of a type instances of which are maximal relative to the sort of causal unity manifested"@en ;
383
+ skos:example "An organism; a fish tank; a planet; a laptop; a valve; a block of marble; an ice cube"@en ;
384
+ skos:scopeNote "A description of three primary sorts of causal unity is provided in Basic Formal Ontology 2.0. Specification and User Guide"@en .
385
+
386
+ <http://purl.obolibrary.org/obo/BFO_0000027> rdf:type owl:Class ;
387
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000040> ;
388
+ dc11:identifier "025-BFO" ;
389
+ rdfs:label "object aggregate"@en ;
390
+ skos:definition "(Elucidation) An object aggregate is a material entity consisting exactly of a plurality (≥1) of objects as member parts which together form a unit"@en ;
391
+ skos:example "The aggregate of the musicians in a symphony orchestra and their instruments; the aggregate of bearings in a constant velocity axle joint; the nitrogen atoms in the atmosphere; a collection of cells in a blood biobank"@en ;
392
+ skos:scopeNote "'Exactly' means that there are no parts of the object aggregate other than its member parts." ,
393
+ "The unit can, at certain times, consist of exactly one object, for example, when a wolf litter loses all but one of its pups, but it must at some time have a plurality of member parts." .
394
+
395
+ <http://purl.obolibrary.org/obo/BFO_0000141> rdf:type owl:Class ;
396
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000004> ;
397
+ dc11:identifier "028-BFO" ;
398
+ rdfs:label "immaterial entity"@en ;
399
+ skos:definition "b is an immaterial entity =Def b is an independent continuant which is such that there is no time t when it has a material entity as continuant part"@en ;
400
+ skos:example "As for fiat point, fiat line, fiat surface, site"@en .
401
+
402
+ <http://purl.obolibrary.org/obo/BFO_0000140> rdf:type owl:Class ;
403
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000141> ,
404
+ [ rdf:type owl:Restriction ;
405
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000124> ;
406
+ owl:allValuesFrom <http://purl.obolibrary.org/obo/BFO_0000140>
407
+ ] ,
408
+ [ rdf:type owl:Restriction ;
409
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000178> ;
410
+ owl:allValuesFrom <http://purl.obolibrary.org/obo/BFO_0000140>
411
+ ] ;
412
+ dc11:identifier "029-BFO" ;
413
+ rdfs:label "continuant fiat boundary"@en ;
414
+ skos:definition "(Elucidation) A continuant fiat boundary b is an immaterial entity that is of zero, one or two dimensions & such that there is no time t when b has a spatial region as continuant part & whose location is determined in relation to some material entity"@en ;
415
+ skos:example "As for fiat point, fiat line, fiat surface"@en .
416
+
417
+ <http://purl.obolibrary.org/obo/BFO_0000142> rdf:type owl:Class ;
418
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000140> ,
419
+ [ rdf:type owl:Restriction ;
420
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000178> ;
421
+ owl:allValuesFrom [ rdf:type owl:Class ;
422
+ owl:unionOf ( <http://purl.obolibrary.org/obo/BFO_0000142>
423
+ <http://purl.obolibrary.org/obo/BFO_0000147>
424
+ )
425
+ ]
426
+ ] ;
427
+ dc11:identifier "032-BFO" ;
428
+ rdfs:label "fiat line"@en ;
429
+ skos:definition "(Elucidation) A fiat line is a one-dimensional continuant fiat boundary that is continuous"@en ;
430
+ skos:example "The Equator; all geopolitical boundaries; all lines of latitude and longitude; the median sulcus of your tongue; the line separating the outer surface of the mucosa of the lower lip from the outer surface of the skin of the chin"@en .
431
+
432
+ <http://purl.obolibrary.org/obo/BFO_0000146> rdf:type owl:Class ;
433
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000140> ,
434
+ [ rdf:type owl:Restriction ;
435
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000178> ;
436
+ owl:allValuesFrom <http://purl.obolibrary.org/obo/BFO_0000140>
437
+ ] ;
438
+ dc11:identifier "033-BFO" ;
439
+ rdfs:label "fiat surface"@en ;
440
+ skos:definition "(Elucidation) A fiat surface is a two-dimensional continuant fiat boundary that is self-connected"@en ;
441
+ skos:example "The surface of the Earth; the plane separating the smoking from the non-smoking zone in a restaurant"@en .
442
+
443
+ <http://purl.obolibrary.org/obo/BFO_0000147> rdf:type owl:Class ;
444
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000140> ,
445
+ [ rdf:type owl:Restriction ;
446
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000178> ;
447
+ owl:allValuesFrom <http://purl.obolibrary.org/obo/BFO_0000147>
448
+ ] ;
449
+ dc11:identifier "031-BFO" ;
450
+ rdfs:label "fiat point"@en ;
451
+ skos:definition "(Elucidation) A fiat point is a zero-dimensional continuant fiat boundary that consists of a single point"@en ;
452
+ skos:example "The geographic North Pole; the quadripoint where the boundaries of Colorado, Utah, New Mexico and Arizona meet; the point of origin of some spatial coordinate system"@en .
453
+
454
+ <http://purl.obolibrary.org/obo/BFO_0000029> rdf:type owl:Class ;
455
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000141> ,
456
+ [ rdf:type owl:Restriction ;
457
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000176> ;
458
+ owl:allValuesFrom [ rdf:type owl:Class ;
459
+ owl:unionOf ( <http://purl.obolibrary.org/obo/BFO_0000029>
460
+ <http://purl.obolibrary.org/obo/BFO_0000040>
461
+ )
462
+ ]
463
+ ] ,
464
+ [ rdf:type owl:Restriction ;
465
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000178> ;
466
+ owl:allValuesFrom [ rdf:type owl:Class ;
467
+ owl:unionOf ( <http://purl.obolibrary.org/obo/BFO_0000029>
468
+ <http://purl.obolibrary.org/obo/BFO_0000140>
469
+ )
470
+ ]
471
+ ] ,
472
+ [ rdf:type owl:Restriction ;
473
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000210> ;
474
+ owl:allValuesFrom <http://purl.obolibrary.org/obo/BFO_0000028>
475
+ ] ;
476
+ dc11:identifier "034-BFO" ;
477
+ rdfs:label "site"@en ;
478
+ skos:definition "(Elucidation) A site is a three-dimensional immaterial entity whose boundaries either (partially or wholly) coincide with the boundaries of one or more material entities or have locations determined in relation to some material entity"@en ;
479
+ skos:example "A hole in a portion of cheese; a rabbit hole; the Grand Canyon; the Piazza San Marco; the kangaroo-joey-containing hole of a kangaroo pouch; your left nostril (a fiat part - the opening - of your left nasal cavity); the lumen of your gut; the hold of a ship; the interior of the trunk of your car; hole in an engineered floor joist"@en .
480
+
481
+ <http://purl.obolibrary.org/obo/BFO_0000006> rdf:type owl:Class ;
482
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000141> ,
483
+ [ rdf:type owl:Restriction ;
484
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000176> ;
485
+ owl:allValuesFrom <http://purl.obolibrary.org/obo/BFO_0000006>
486
+ ] ;
487
+ dc11:identifier "035-BFO" ;
488
+ rdfs:label "spatial region"@en ;
489
+ skos:definition "(Elucidation) A spatial region is a continuant entity that is a continuant part of the spatial projection of a portion of spacetime at a given time"@en ;
490
+ skos:example "As for zero-dimensional spatial region, one-dimensional spatial region, two-dimensional spatial region, three-dimensional spatial region"@en .
491
+
492
+ <http://purl.obolibrary.org/obo/BFO_0000018> rdf:type owl:Class ;
493
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000006> ,
494
+ [ rdf:type owl:Restriction ;
495
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000178> ;
496
+ owl:allValuesFrom <http://purl.obolibrary.org/obo/BFO_0000018>
497
+ ] ;
498
+ dc11:identifier "037-BFO" ;
499
+ rdfs:label "zero-dimensional spatial region"@en ;
500
+ skos:definition "(Elucidation) A zero-dimensional spatial region is one or a collection of more than one spatially disjoint points in space"@en ;
501
+ skos:example "The spatial region occupied at some time instant by the North Pole"@en .
502
+
503
+ <http://purl.obolibrary.org/obo/BFO_0000026> rdf:type owl:Class ;
504
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000006> ,
505
+ [ rdf:type owl:Restriction ;
506
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000178> ;
507
+ owl:allValuesFrom [ rdf:type owl:Class ;
508
+ owl:unionOf ( <http://purl.obolibrary.org/obo/BFO_0000018>
509
+ <http://purl.obolibrary.org/obo/BFO_0000026>
510
+ )
511
+ ]
512
+ ] ;
513
+ dc11:identifier "038-BFO" ;
514
+ rdfs:label "one-dimensional spatial region"@en ;
515
+ skos:definition "(Elucidation) A one-dimensional spatial region is a whole consisting of a line together with zero or more lines which may have points as parts"@en ;
516
+ skos:example "An edge of a cube-shaped portion of space; a line connecting two points; two parallel lines extended in space"@en .
517
+
518
+ <http://purl.obolibrary.org/obo/BFO_0000009> rdf:type owl:Class ;
519
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000006> ,
520
+ [ rdf:type owl:Restriction ;
521
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000178> ;
522
+ owl:allValuesFrom [ rdf:type owl:Class ;
523
+ owl:unionOf ( <http://purl.obolibrary.org/obo/BFO_0000009>
524
+ <http://purl.obolibrary.org/obo/BFO_0000018>
525
+ <http://purl.obolibrary.org/obo/BFO_0000026>
526
+ )
527
+ ]
528
+ ] ;
529
+ dc11:identifier "039-BFO" ;
530
+ rdfs:label "two-dimensional spatial region"@en ;
531
+ skos:definition "(Elucidation) A two-dimensional spatial region is a spatial region that is a whole consisting of a surface together with zero or more surfaces which may have spatial regions of lower dimension as parts"@en ;
532
+ skos:example "The surface of a sphere-shaped part of space; an infinitely thin plane in space"@en .
533
+
534
+ <http://purl.obolibrary.org/obo/BFO_0000028> rdf:type owl:Class ;
535
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000006> ,
536
+ [ rdf:type owl:Restriction ;
537
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000178> ;
538
+ owl:allValuesFrom <http://purl.obolibrary.org/obo/BFO_0000006>
539
+ ] ;
540
+ dc11:identifier "040-BFO" ;
541
+ rdfs:label "three-dimensional spatial region"@en ;
542
+ skos:definition "(Elucidation) A three-dimensional spatial region is a whole consisting of a spatial volume together with zero or more spatial volumes which may have spatial regions of lower dimension as parts"@en ;
543
+ skos:example "A cube-shaped region of space; a sphere-shaped region of space; the region of space occupied by all and only the planets in the solar system at some point in time"@en .
544
+ ```
545
+
546
+ "Occurrents":
547
+ ```turtle
548
+ <http://purl.obolibrary.org/obo/BFO_0000015> rdf:type owl:Class ;
549
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000003> ,
550
+ [ rdf:type owl:Restriction ;
551
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000117> ;
552
+ owl:allValuesFrom [ rdf:type owl:Class ;
553
+ owl:unionOf ( <http://purl.obolibrary.org/obo/BFO_0000015>
554
+ <http://purl.obolibrary.org/obo/BFO_0000035>
555
+ )
556
+ ]
557
+ ] ,
558
+ [ rdf:type owl:Restriction ;
559
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000132> ;
560
+ owl:allValuesFrom <http://purl.obolibrary.org/obo/BFO_0000015>
561
+ ] ,
562
+ [ rdf:type owl:Restriction ;
563
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000139> ;
564
+ owl:allValuesFrom <http://purl.obolibrary.org/obo/BFO_0000015>
565
+ ] ;
566
+ dc11:identifier "083-BFO" ;
567
+ rdfs:label "process"@en ;
568
+ skos:altLabel "event"@en ;
569
+ skos:definition "(Elucidation) p is a process means p is an occurrent that has some temporal proper part and for some time t, p has some material entity as participant"@en ;
570
+ skos:example "An act of selling; the life of an organism; a process of sleeping; a process of cell-division; a beating of the heart; a process of meiosis; the taxiing of an aircraft; the programming of a computer"@en .
571
+
572
+ <http://purl.obolibrary.org/obo/BFO_0000182> rdf:type owl:Class ;
573
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000015> ;
574
+ dc11:identifier "138-BFO" ;
575
+ rdfs:label "history"@en ;
576
+ skos:definition "(Elucidation) A history is a process that is the sum of the totality of processes taking place in the spatiotemporal region occupied by the material part of a material entity"@en ;
577
+ skos:example "The life of an organism from the beginning to the end of its existence"@en .
578
+
579
+ <http://purl.obolibrary.org/obo/BFO_0000035> rdf:type owl:Class ;
580
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000003> ,
581
+ [ rdf:type owl:Restriction ;
582
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000117> ;
583
+ owl:allValuesFrom <http://purl.obolibrary.org/obo/BFO_0000035>
584
+ ] ,
585
+ [ rdf:type owl:Restriction ;
586
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000121> ;
587
+ owl:allValuesFrom <http://purl.obolibrary.org/obo/BFO_0000035>
588
+ ] ,
589
+ [ rdf:type owl:Restriction ;
590
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000132> ;
591
+ owl:allValuesFrom [ rdf:type owl:Class ;
592
+ owl:unionOf ( <http://purl.obolibrary.org/obo/BFO_0000015>
593
+ <http://purl.obolibrary.org/obo/BFO_0000035>
594
+ )
595
+ ]
596
+ ] ,
597
+ [ rdf:type owl:Restriction ;
598
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000139> ;
599
+ owl:allValuesFrom [ rdf:type owl:Class ;
600
+ owl:unionOf ( <http://purl.obolibrary.org/obo/BFO_0000015>
601
+ <http://purl.obolibrary.org/obo/BFO_0000035>
602
+ )
603
+ ]
604
+ ] ;
605
+ dc11:identifier "084-BFO" ;
606
+ rdfs:label "process boundary"@en ;
607
+ skos:definition "p is a process boundary =Def p is a temporal part of a process & p has no proper temporal parts"@en ;
608
+ skos:example "The boundary between the 2nd and 3rd year of your life"@en .
609
+
610
+ <http://purl.obolibrary.org/obo/BFO_0000008> rdf:type owl:Class ;
611
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000003> ,
612
+ [ rdf:type owl:Restriction ;
613
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000132> ;
614
+ owl:allValuesFrom <http://purl.obolibrary.org/obo/BFO_0000008>
615
+ ] ,
616
+ [ rdf:type owl:Restriction ;
617
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000139> ;
618
+ owl:allValuesFrom <http://purl.obolibrary.org/obo/BFO_0000008>
619
+ ] ;
620
+ dc11:identifier "100-BFO" ;
621
+ rdfs:label "temporal region"@en ;
622
+ skos:definition "(Elucidation) A temporal region is an occurrent over which processes can unfold"@en ;
623
+ skos:example "As for zero-dimensional temporal region and one-dimensional temporal region"@en .
624
+
625
+ <http://purl.obolibrary.org/obo/BFO_0000038> rdf:type owl:Class ;
626
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000008> ,
627
+ [ rdf:type owl:Restriction ;
628
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000121> ;
629
+ owl:allValuesFrom [ rdf:type owl:Class ;
630
+ owl:unionOf ( <http://purl.obolibrary.org/obo/BFO_0000038>
631
+ <http://purl.obolibrary.org/obo/BFO_0000148>
632
+ )
633
+ ]
634
+ ] ,
635
+ [ rdf:type owl:Restriction ;
636
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000139> ;
637
+ owl:allValuesFrom <http://purl.obolibrary.org/obo/BFO_0000038>
638
+ ] ;
639
+ owl:disjointWith <http://purl.obolibrary.org/obo/BFO_0000148> ;
640
+ dc11:identifier "103-BFO" ;
641
+ rdfs:label "one-dimensional temporal region"@en ;
642
+ skos:definition "(Elucidation) A one-dimensional temporal region is a temporal region that is a whole that has a temporal interval and zero or more temporal intervals and temporal instants as parts"@en ;
643
+ skos:example "The temporal region during which a process occurs"@en .
644
+
645
+ <http://purl.obolibrary.org/obo/BFO_0000148> rdf:type owl:Class ;
646
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000008> ,
647
+ [ rdf:type owl:Restriction ;
648
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000121> ;
649
+ owl:allValuesFrom <http://purl.obolibrary.org/obo/BFO_0000148>
650
+ ] ;
651
+ dc11:identifier "102-BFO" ;
652
+ rdfs:label "zero-dimensional temporal region"@en ;
653
+ skos:definition "(Elucidation) A zero-dimensional temporal region is a temporal region that is a whole consisting of one or more separated temporal instants as parts"@en ;
654
+ skos:example "A temporal region that is occupied by a process boundary; the moment at which a finger is detached in an industrial accident"@en .
655
+
656
+ <http://purl.obolibrary.org/obo/BFO_0000202> rdf:type owl:Class ;
657
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000038> ;
658
+ dc11:identifier "155-BFO" ;
659
+ rdfs:label "temporal interval"@en ;
660
+ skos:definition "(Elucidation) A temporal interval is a one-dimensional temporal region that is continuous, thus without gaps or breaks"@en ;
661
+ skos:example "The year 2018."@en ;
662
+ skos:scopeNote "A one-dimensional temporal region can include as parts not only temporal intervals but also temporal instants separated from other parts by gaps."@en .
663
+
664
+ <http://purl.obolibrary.org/obo/BFO_0000203> rdf:type owl:Class ;
665
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000148> ;
666
+ dc11:identifier "209-BFO" ;
667
+ rdfs:label "temporal instant"@en ;
668
+ skos:definition "(Elucidation) A temporal instant is a zero-dimensional temporal region that has no proper temporal part"@en ;
669
+ skos:example "The millennium"@en .
670
+
671
+ <http://purl.obolibrary.org/obo/BFO_0000011> rdf:type owl:Class ;
672
+ rdfs:subClassOf <http://purl.obolibrary.org/obo/BFO_0000003> ,
673
+ [ rdf:type owl:Restriction ;
674
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000132> ;
675
+ owl:allValuesFrom <http://purl.obolibrary.org/obo/BFO_0000011>
676
+ ] ,
677
+ [ rdf:type owl:Restriction ;
678
+ owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000139> ;
679
+ owl:allValuesFrom <http://purl.obolibrary.org/obo/BFO_0000011>
680
+ ] ;
681
+ dc11:identifier "095-BFO" ;
682
+ rdfs:label "spatiotemporal region"@en ;
683
+ skos:definition "(Elucidation) A spatiotemporal region is an occurrent that is an occurrent part of spacetime"@en ;
684
+ skos:example "The spatiotemporal region occupied by the development of a cancer tumour; the spatiotemporal region occupied by an orbiting satellite"@en ;
685
+ skos:scopeNote "'Spacetime' here refers to the maximal instance of the universal spatiotemporal region."@en .
686
+ ```
687
+
688
+ 3. For temporal regions instances, replace label by the following format based on the current date:
689
+ 'today', 'yesterday', 'tomorrow' -> 'YYYY-MM-DD'
690
+ 'this week' -> 'YYYY-WW'
691
+ 'this month' -> 'YYYY-MM'
692
+ 'this year' -> 'YYYY'
693
+
694
+ 4. Return the entities in the following JSON format:
695
+ ```json
696
+ [
697
+ {
698
+ "type": "Continuant" | "Occurrent",
699
+ "class_uri": "", # URI of the subclass of the "Continuants" or "Occurrents" class
700
+ "class_label": "", # Label of the subclass of the "Continuants" or "Occurrents" class
701
+ "label": "", # Label of the instance
702
+ "comment": "" # Comment of the instance
703
+ },
704
+ ]
705
+ ```
706
+
707
+ # CONSTRAINTS:
708
+ - You must return a JSON without any other text or comment.
709
+ - You must be exhaustive in your search for entities.
710
+ - You must use BFO Ontology as your knowledge base for the mapping.
711
+ - You must try to find the most specific class for each entity.
712
+ - You must transform all dates to temporal instants type date or datetime.
713
+
714
+ - Remember to identify entities not explicitly defined like:
715
+ - 'i' representing a person
716
+ - 'today', 'yesterday', 'tomorrow', 'this week', 'this month', 'this year' representing a temporal region.
717
+
718
+ - Process Entities (BFO_0000015) MUST be carefully identified and analyzed:
719
+ 1. A process MUST be recognized as an occurrent with ALL of these critical relationships:
720
+ - MUST realize one or more realizable entities (e.g. functions, roles, dispositions)
721
+ - MUST have at least one participant that is either:
722
+ - a specifically dependent continuant (e.g. qualities, realizable entities)
723
+ - a generically dependent continuant (e.g. information entities)
724
+ - an independent continuant that is not a spatial region (e.g. material entities)
725
+ - MUST concretize at least one generically dependent continuant
726
+ - MUST occur in either:
727
+ - a specific site (e.g. anatomical location)
728
+ - a material entity (e.g. physical object)
729
+ - MUST occupy a defined temporal region
730
+ - MUST occupy a defined spatiotemporal region
731
+
732
+ 2. For each process identified:
733
+ - You MUST create a descriptive label that captures the complete event
734
+ - You MUST identify and link ALL continuants and occurrents involved
735
+ - You MUST establish and document ALL relationships between entities
736
+ - You MUST validate that all required relationships are present
737
+ - You MUST ensure temporal and spatial aspects are properly captured
738
+ """
739
+ from datetime import datetime
740
+
741
+ system_prompt = system_prompt.replace(
742
+ "{{current_date}}", datetime.now().strftime("%Y-%m-%d")
743
+ )
744
+ messages = [SystemMessage(content=system_prompt)] + [
745
+ message
746
+ for message in state["messages"]
747
+ if not isinstance(message, SystemMessage)
748
+ ]
749
+ response: BaseMessage = self._chat_model.invoke(messages)
750
+ return Command(update={"messages": [response]})
751
+
752
+ def prep_data(self, state: EntityExtractionState) -> Command:
753
+ """
754
+ This node is used to prepare the data for the SPARQL generation.
755
+ It extracts the entities from the last message and transform them into SPARQL INSERT DATA statements.
756
+ """
757
+ import uuid
758
+
759
+ from naas_abi.utils.Storage import save_json, save_text
760
+ from naas_abi.workflows.GetObjectPropertiesFromClassWorkflow import (
761
+ GetObjectPropertiesFromClassWorkflow,
762
+ GetObjectPropertiesFromClassWorkflowConfiguration,
763
+ GetObjectPropertiesFromClassWorkflowParameters,
764
+ )
765
+ from naas_abi_core.utils.JSON import extract_json_from_completion
766
+
767
+ workflow = GetObjectPropertiesFromClassWorkflow(
768
+ GetObjectPropertiesFromClassWorkflowConfiguration(
769
+ triple_store=SERVICES.triple_store
770
+ )
771
+ )
772
+
773
+ last_message_content = state["messages"][-1].content
774
+ assert isinstance(last_message_content, str), (
775
+ "Last message content must be a string"
776
+ )
777
+
778
+ # Get JSON response from model
779
+ object_properties = {}
780
+ entities = extract_json_from_completion(last_message_content)
781
+ for e in entities:
782
+ # Create a unique URI for the entity
783
+ e["uri"] = "http://ontology.naas.ai/abi/" + str(uuid.uuid4())
784
+ class_uri = e.get("class_uri")
785
+
786
+ # Only fetch object properties if we haven't seen this class/subclass before
787
+ if class_uri:
788
+ if class_uri not in object_properties:
789
+ oprop = workflow.get_object_properties_from_class(
790
+ GetObjectPropertiesFromClassWorkflowParameters(
791
+ class_uri=class_uri
792
+ )
793
+ )
794
+ if len(oprop.get("object_properties", [])) > 0:
795
+ object_properties[class_uri] = oprop
796
+
797
+ # Save data to storage
798
+ last_last_message_content_str = str(state["messages"][-2].content)
799
+ save_text(
800
+ last_last_message_content_str,
801
+ self.datastore_path,
802
+ "init_text.txt",
803
+ copy=False,
804
+ )
805
+ save_json(entities, self.datastore_path, "entities.json", copy=False)
806
+ save_json(
807
+ object_properties, self.datastore_path, "object_properties.json", copy=False
808
+ )
809
+
810
+ # Store entities and object_properties in state instead of AI message
811
+ return Command(
812
+ update={
813
+ "entities": entities,
814
+ "object_properties": list(object_properties.values()),
815
+ }
816
+ )
817
+
818
+ def create_sparql(self, state: EntityExtractionState) -> Command:
819
+ """
820
+ This node is used to generate SPARQL INSERT DATA statements from extracted entities and their relationships.
821
+
822
+ Uses a language model to transform the extracted entities and object properties
823
+ into proper SPARQL INSERT DATA statements that can be executed against a triple store.
824
+
825
+ Args:
826
+ state (EntityExtractionState): Current state containing entities and object_properties
827
+
828
+ Returns:
829
+ Command: Command to end the workflow with the generated SPARQL statement
830
+ """
831
+ from naas_abi.utils.Storage import save_text
832
+
833
+ # Create system message for SPARQL generation
834
+ system_prompt = """# ROLE:
835
+ You are a Ontology Engineer expert specializing in generating SPARQL INSERT DATA statements from entity extraction results.
836
+
837
+ # OBJECTIVE:
838
+ Transform the provided entities and their object properties into a valid SPARQL INSERT DATA statement that creates RDF triples representing the entities and their relationships.
839
+
840
+ # CONTEXT:
841
+ You will receive:
842
+ 1. A list of entities with their BFO ontology mappings (class_uri, class_label, label, comment, uri)
843
+ 2. Object properties that define possible relationships between entity classes
844
+ 3. The original message that was used for entity extraction
845
+
846
+ # TASK:
847
+ Generate a SPARQL INSERT DATA statement that:
848
+ 1. Creates instances of each entity with their appropriate RDF type
849
+ 2. Adds rdfs:label properties for each entity
850
+ 3. Adds rdfs:comment properties where comments exist
851
+ 4. Creates relationships between entities using the provided object properties
852
+ 5. Uses appropriate prefixes for readability
853
+
854
+ # OPERATING GUIDELINES:
855
+ 1. Always start with appropriate PREFIX declarations
856
+ 2. Use the INSERT DATA clause
857
+ 3. Create rdf:type triples for each entity using their class_uri
858
+ 4. Add rdfs:label and rdfs:comment properties
859
+ 5. Analyze the original message and entity relationships to determine which object properties to apply
860
+ 6. Only create relationships that are logically supported by the entities and the original message
861
+ 7. Use proper RDF syntax with angle brackets for URIs and quotes for literals
862
+ 8. When referencing ABI entities, use the prefix notation 'abi:' followed by the UUID, not 'abi/'
863
+
864
+ # EXAMPLE FORMAT:
865
+ ```sparql
866
+ PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
867
+ PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
868
+ PREFIX bfo: <http://purl.obolibrary.org/obo/>
869
+ PREFIX abi: <http://ontology.naas.ai/abi/>
870
+
871
+ INSERT DATA {
872
+ abi:entity1 rdf:type bfo:BFO_0000030 ;
873
+ rdfs:label "Entity Label" .
874
+
875
+ abi:entity2 rdf:type bfo:BFO_0000015 ;
876
+ rdfs:label "Process Label" .
877
+
878
+ # Relationships
879
+ abi:entity2 bfo:has_participant abi:entity1 .
880
+ }
881
+ ```
882
+
883
+ # CONSTRAINTS:
884
+ - You must return only the SPARQL statement without any other text or explanations
885
+ - Use proper SPARQL syntax
886
+ - Ensure all URIs are properly formatted
887
+ - Only create relationships that are semantically meaningful based on the entities and original message
888
+ - You MUST not return "comment" in the SPARQL statement.
889
+ """
890
+
891
+ # Prepare the input data for the model
892
+ entities_data = {
893
+ "entities": state.get("entities", []),
894
+ "object_properties": state.get("object_properties", []),
895
+ "original_message": state["messages"][0].content
896
+ if state["messages"]
897
+ else "",
898
+ }
899
+
900
+ # Create messages for the model
901
+ messages = [
902
+ SystemMessage(content=system_prompt),
903
+ AIMessage(
904
+ content=f"Here is the data to transform into SPARQL:\n\n{entities_data}"
905
+ ),
906
+ ]
907
+
908
+ # Generate SPARQL using the model
909
+ response: BaseMessage = self._chat_model.invoke(messages)
910
+
911
+ # Save SPARQL statement to storage
912
+ response_content_str = str(response.content) if response.content else ""
913
+ save_text(
914
+ response_content_str, self.datastore_path, "insert_data.sparql", copy=False
915
+ )
916
+
917
+ # Return the generated SPARQL statement
918
+ return Command(update={"messages": [AIMessage(content=response.content)]})
919
+
920
+ def call_model(
921
+ self,
922
+ state: EntityExtractionState, # type: ignore[override]
923
+ ) -> Command:
924
+ """
925
+ This node is used to call the model to extract the entities from the last message.
926
+ """
927
+ messages = state["messages"]
928
+ if self._system_prompt:
929
+ messages = [
930
+ SystemMessage(content=self._system_prompt),
931
+ ] + messages
932
+
933
+ response: BaseMessage = self._chat_model_with_tools.invoke(messages)
934
+
935
+ return Command(goto="__end__", update={"messages": [response]})
936
+
937
+ def build_graph(self, patcher: Optional[Callable] = None):
938
+ graph = StateGraph(EntityExtractionState)
939
+
940
+ graph.add_node(self.entity_extract)
941
+ graph.add_edge(START, "entity_extract")
942
+
943
+ graph.add_node(self.prep_data)
944
+ graph.add_edge("entity_extract", "prep_data")
945
+
946
+ graph.add_node(self.create_sparql)
947
+ graph.add_edge("prep_data", "create_sparql")
948
+
949
+ graph.add_node(self.call_model)
950
+ graph.add_edge("create_sparql", "call_model")
951
+
952
+ self.graph = graph.compile(checkpointer=self._checkpointer)