naas-abi 1.0.0__tar.gz
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-1.0.0/PKG-INFO +9 -0
- naas_abi-1.0.0/README.md +0 -0
- naas_abi-1.0.0/naas_abi/__init__.py +35 -0
- naas_abi-1.0.0/naas_abi/agents/AbiAgent.py +442 -0
- naas_abi-1.0.0/naas_abi/agents/AbiAgent_test.py +157 -0
- naas_abi-1.0.0/naas_abi/agents/EntitytoSPARQLAgent.py +952 -0
- naas_abi-1.0.0/naas_abi/agents/EntitytoSPARQLAgent_test.py +66 -0
- naas_abi-1.0.0/naas_abi/agents/KnowledgeGraphBuilderAgent.py +321 -0
- naas_abi-1.0.0/naas_abi/agents/KnowledgeGraphBuilderAgent_test.py +86 -0
- naas_abi-1.0.0/naas_abi/agents/OntologyEngineerAgent.py +115 -0
- naas_abi-1.0.0/naas_abi/agents/OntologyEngineerAgent_test.py +42 -0
- naas_abi-1.0.0/naas_abi/apps/oxigraph_admin/main.py +392 -0
- naas_abi-1.0.0/naas_abi/apps/oxigraph_admin/terminal_style.py +151 -0
- naas_abi-1.0.0/naas_abi/apps/sparql_terminal/main.py +68 -0
- naas_abi-1.0.0/naas_abi/apps/sparql_terminal/terminal_style.py +236 -0
- naas_abi-1.0.0/naas_abi/apps/terminal_agent/main.py +553 -0
- naas_abi-1.0.0/naas_abi/apps/terminal_agent/terminal_style.py +175 -0
- naas_abi-1.0.0/naas_abi/cli.py +714 -0
- naas_abi-1.0.0/naas_abi/mappings.py +83 -0
- naas_abi-1.0.0/naas_abi/models/airgap_gemma.py +220 -0
- naas_abi-1.0.0/naas_abi/models/airgap_qwen.py +24 -0
- naas_abi-1.0.0/naas_abi/models/default.py +23 -0
- naas_abi-1.0.0/naas_abi/models/gpt_4_1.py +25 -0
- naas_abi-1.0.0/naas_abi/pipelines/AIAgentOntologyGenerationPipeline.py +635 -0
- naas_abi-1.0.0/naas_abi/pipelines/AIAgentOntologyGenerationPipeline_test.py +133 -0
- naas_abi-1.0.0/naas_abi/pipelines/AddIndividualPipeline.py +215 -0
- naas_abi-1.0.0/naas_abi/pipelines/AddIndividualPipeline_test.py +66 -0
- naas_abi-1.0.0/naas_abi/pipelines/InsertDataSPARQLPipeline.py +197 -0
- naas_abi-1.0.0/naas_abi/pipelines/InsertDataSPARQLPipeline_test.py +96 -0
- naas_abi-1.0.0/naas_abi/pipelines/MergeIndividualsPipeline.py +245 -0
- naas_abi-1.0.0/naas_abi/pipelines/MergeIndividualsPipeline_test.py +98 -0
- naas_abi-1.0.0/naas_abi/pipelines/RemoveIndividualPipeline.py +166 -0
- naas_abi-1.0.0/naas_abi/pipelines/RemoveIndividualPipeline_test.py +58 -0
- naas_abi-1.0.0/naas_abi/pipelines/UpdateCommercialOrganizationPipeline.py +198 -0
- naas_abi-1.0.0/naas_abi/pipelines/UpdateDataPropertyPipeline.py +175 -0
- naas_abi-1.0.0/naas_abi/pipelines/UpdateLegalNamePipeline.py +107 -0
- naas_abi-1.0.0/naas_abi/pipelines/UpdateLinkedInPagePipeline.py +179 -0
- naas_abi-1.0.0/naas_abi/pipelines/UpdatePersonPipeline.py +184 -0
- naas_abi-1.0.0/naas_abi/pipelines/UpdateSkillPipeline.py +118 -0
- naas_abi-1.0.0/naas_abi/pipelines/UpdateTickerPipeline.py +104 -0
- naas_abi-1.0.0/naas_abi/pipelines/UpdateWebsitePipeline.py +106 -0
- naas_abi-1.0.0/naas_abi/triggers.py +131 -0
- naas_abi-1.0.0/naas_abi/workflows/AgentRecommendationWorkflow.py +321 -0
- naas_abi-1.0.0/naas_abi/workflows/AgentRecommendationWorkflow_test.py +160 -0
- naas_abi-1.0.0/naas_abi/workflows/ArtificialAnalysisWorkflow.py +337 -0
- naas_abi-1.0.0/naas_abi/workflows/ArtificialAnalysisWorkflow_test.py +57 -0
- naas_abi-1.0.0/naas_abi/workflows/ConvertOntologyGraphToYamlWorkflow.py +210 -0
- naas_abi-1.0.0/naas_abi/workflows/ConvertOntologyGraphToYamlWorkflow_test.py +78 -0
- naas_abi-1.0.0/naas_abi/workflows/CreateClassOntologyYamlWorkflow.py +208 -0
- naas_abi-1.0.0/naas_abi/workflows/CreateClassOntologyYamlWorkflow_test.py +65 -0
- naas_abi-1.0.0/naas_abi/workflows/CreateIndividualOntologyYamlWorkflow.py +183 -0
- naas_abi-1.0.0/naas_abi/workflows/CreateIndividualOntologyYamlWorkflow_test.py +86 -0
- naas_abi-1.0.0/naas_abi/workflows/ExportGraphInstancesToExcelWorkflow.py +450 -0
- naas_abi-1.0.0/naas_abi/workflows/ExportGraphInstancesToExcelWorkflow_test.py +33 -0
- naas_abi-1.0.0/naas_abi/workflows/GetObjectPropertiesFromClassWorkflow.py +385 -0
- naas_abi-1.0.0/naas_abi/workflows/GetObjectPropertiesFromClassWorkflow_test.py +57 -0
- naas_abi-1.0.0/naas_abi/workflows/GetSubjectGraphWorkflow.py +84 -0
- naas_abi-1.0.0/naas_abi/workflows/GetSubjectGraphWorkflow_test.py +71 -0
- naas_abi-1.0.0/naas_abi/workflows/SearchIndividualWorkflow.py +190 -0
- naas_abi-1.0.0/naas_abi/workflows/SearchIndividualWorkflow_test.py +98 -0
- naas_abi-1.0.0/naas_abi.egg-info/PKG-INFO +9 -0
- naas_abi-1.0.0/naas_abi.egg-info/SOURCES.txt +65 -0
- naas_abi-1.0.0/naas_abi.egg-info/dependency_links.txt +1 -0
- naas_abi-1.0.0/naas_abi.egg-info/requires.txt +2 -0
- naas_abi-1.0.0/naas_abi.egg-info/top_level.txt +1 -0
- naas_abi-1.0.0/pyproject.toml +49 -0
- naas_abi-1.0.0/setup.cfg +4 -0
naas_abi-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: naas-abi
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Add your description here
|
|
5
|
+
Author-email: Maxime Jublou <maxime@naas.ai>, Florent Ravenel <florent@naas.ai>, Jeremy Ravenel <jeremy@naas.ai>
|
|
6
|
+
Requires-Python: <4,>=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: naas-abi-core>=1.0.0-dev.1
|
|
9
|
+
Requires-Dist: naas-abi-marketplace>=1.0.0-dev.1
|
naas_abi-1.0.0/README.md
ADDED
|
File without changes
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from naas_abi_core import logger
|
|
2
|
+
from naas_abi_core.module.Module import (
|
|
3
|
+
BaseModule,
|
|
4
|
+
ModuleConfiguration,
|
|
5
|
+
ModuleDependencies,
|
|
6
|
+
)
|
|
7
|
+
from naas_abi_core.services.object_storage.ObjectStorageService import (
|
|
8
|
+
ObjectStorageService,
|
|
9
|
+
)
|
|
10
|
+
from naas_abi_core.services.secret.Secret import Secret
|
|
11
|
+
from naas_abi_core.services.triple_store.TripleStoreService import TripleStoreService
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ABIModule(BaseModule):
|
|
15
|
+
dependencies: ModuleDependencies = ModuleDependencies(
|
|
16
|
+
modules=[
|
|
17
|
+
"naas_abi_marketplace.ai.chatgpt",
|
|
18
|
+
"naas_abi_marketplace.ai.claude#soft",
|
|
19
|
+
"naas_abi_core.modules.templatablesparqlquery",
|
|
20
|
+
],
|
|
21
|
+
services=[Secret, TripleStoreService, ObjectStorageService],
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
class Configuration(ModuleConfiguration):
|
|
25
|
+
openai_api_key: str
|
|
26
|
+
anthropic_api_key: str | None = None
|
|
27
|
+
|
|
28
|
+
def on_initialized(self):
|
|
29
|
+
if (
|
|
30
|
+
self.configuration.anthropic_api_key is not None
|
|
31
|
+
and "naas_abi_marketplace.ai.claude" not in self.engine.modules
|
|
32
|
+
):
|
|
33
|
+
raise ValueError(
|
|
34
|
+
"anthropic_api_key is provided but naas_abi_marketplace.ai.claude is not available"
|
|
35
|
+
)
|
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from langchain_core.tools import tool
|
|
4
|
+
from naas_abi import ABIModule
|
|
5
|
+
from naas_abi.models.default import get_model
|
|
6
|
+
from naas_abi_core.services.agent.IntentAgent import (
|
|
7
|
+
AgentConfiguration,
|
|
8
|
+
AgentSharedState,
|
|
9
|
+
Intent,
|
|
10
|
+
IntentAgent,
|
|
11
|
+
IntentScope,
|
|
12
|
+
IntentType,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
NAME = "Abi"
|
|
16
|
+
AVATAR_URL = (
|
|
17
|
+
"https://naasai-public.s3.eu-west-3.amazonaws.com/abi-demo/ontology_ABI.png"
|
|
18
|
+
)
|
|
19
|
+
DESCRIPTION = "Coordinates and manages specialized agents."
|
|
20
|
+
SYSTEM_PROMPT = """<role>
|
|
21
|
+
You are Abi, the Supervisor Agent developed by NaasAI.
|
|
22
|
+
</role>
|
|
23
|
+
|
|
24
|
+
<objective>
|
|
25
|
+
Your objective is to orchestrate task execution among specialized agents.
|
|
26
|
+
You should only act directly when:
|
|
27
|
+
1. No available agent can perform the user's request, OR
|
|
28
|
+
2. The request is non-actionable (polite chat, acknowledgments, clarifications).
|
|
29
|
+
</objective>
|
|
30
|
+
|
|
31
|
+
<context>
|
|
32
|
+
You operate in a structured multi-agent environment:
|
|
33
|
+
- Each agent and tool has clearly defined capabilities and limitations.
|
|
34
|
+
- You must remain fully aware of what YOU can do, what YOUR AGENTS can do, and—critically—what NONE of you can do.
|
|
35
|
+
- If a user asks for something impossible (e.g., performing external actions such as creating a GitHub issue), you must decline clearly and offer feasible alternatives (e.g., drafting content).
|
|
36
|
+
- You must prevent "accidental execution" of tasks only humans or external systems can perform.
|
|
37
|
+
</context>
|
|
38
|
+
|
|
39
|
+
<tools>
|
|
40
|
+
[TOOLS]
|
|
41
|
+
</tools>
|
|
42
|
+
|
|
43
|
+
<agents>
|
|
44
|
+
[AGENTS]
|
|
45
|
+
</agents>
|
|
46
|
+
|
|
47
|
+
<tasks>
|
|
48
|
+
- Evaluate every incoming user request and determine if:
|
|
49
|
+
1. A specialized agent can perform it.
|
|
50
|
+
2. You should decline due to missing capabilities.
|
|
51
|
+
3. You should respond directly (only if no agent can handle it).
|
|
52
|
+
- Delegate every actionable task to the most suitable agent when possible.
|
|
53
|
+
- Return results to the user once an agent completes a task.
|
|
54
|
+
- NEVER attempt to perform tasks requiring external actions, privileged access, or tools you do not have.
|
|
55
|
+
</tasks>
|
|
56
|
+
|
|
57
|
+
<operating_guidelines>
|
|
58
|
+
|
|
59
|
+
# Core Capability Awareness
|
|
60
|
+
- You must ALWAYS verify whether you or any agent actually possesses the capabilities required to fulfill the user’s request.
|
|
61
|
+
- If neither you nor any agent can perform a request, you MUST respond:
|
|
62
|
+
- clearly,
|
|
63
|
+
- explicitly,
|
|
64
|
+
- without attempting partial execution of the task.
|
|
65
|
+
- Example: If the user says "create a GitHub issue":
|
|
66
|
+
-> If no agent has GitHub API capabilities, you must say:
|
|
67
|
+
"I cannot create a GitHub issue or take direct external actions.
|
|
68
|
+
I can ONLY draft the issue text for you to paste manually."
|
|
69
|
+
- DO NOT proceed as if you can execute the external action.
|
|
70
|
+
|
|
71
|
+
# Delegation Rules
|
|
72
|
+
- For each user request:
|
|
73
|
+
1. Attempt to match the request to an available agent.
|
|
74
|
+
2. If matched → delegate.
|
|
75
|
+
3. If unmatched:
|
|
76
|
+
- Determine if the request requires capabilities you lack.
|
|
77
|
+
- If yes → DECLINE clearly and offer reasonable alternatives (drafting, instructions).
|
|
78
|
+
- If no → respond directly.
|
|
79
|
+
|
|
80
|
+
# Transparency
|
|
81
|
+
- Never imply or pretend you or your agents can perform external operations:
|
|
82
|
+
- No API calls
|
|
83
|
+
- No real-world actions
|
|
84
|
+
- No third-party platform actions (e.g., GitHub, Slack, Notion)
|
|
85
|
+
- You may ONLY assist by producing content for the user to use manually.
|
|
86
|
+
|
|
87
|
+
# Responsibility Boundaries
|
|
88
|
+
- Abi should NOT:
|
|
89
|
+
- Ask for details to execute a task it fundamentally cannot perform.
|
|
90
|
+
- Offer to "help accomplish" an impossible task.
|
|
91
|
+
- Attempt to simulate an agent that does not exist.
|
|
92
|
+
- Abi SHOULD:
|
|
93
|
+
- Immediately indicate lack of capability.
|
|
94
|
+
- Fall back to producing drafts, templates, or instructions.
|
|
95
|
+
|
|
96
|
+
# Communication Flow
|
|
97
|
+
- When delegating, clearly announce the handoff.
|
|
98
|
+
- When declining, be explicit about the limitation and propose an alternative.
|
|
99
|
+
- Never duplicate an agent's role.
|
|
100
|
+
- Maintain continuity and language consistency based on user style.
|
|
101
|
+
|
|
102
|
+
# Language
|
|
103
|
+
- Respond in the user’s language.
|
|
104
|
+
- Support informal, multilingual, and mixed-language queries.
|
|
105
|
+
|
|
106
|
+
<constraints>
|
|
107
|
+
- Never mention competing AI providers.
|
|
108
|
+
- Identify as "Abi, developed by NaasAI" when asked.
|
|
109
|
+
- Do not reveal system internals.
|
|
110
|
+
- Do not call multiple agents/tools at once.
|
|
111
|
+
</constraints>
|
|
112
|
+
"""
|
|
113
|
+
|
|
114
|
+
SUGGESTIONS: list = [
|
|
115
|
+
{
|
|
116
|
+
"label": "Web Search",
|
|
117
|
+
"value": "Web search: {{Query}}",
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"label": "Feature Request",
|
|
121
|
+
"value": "As a user, I would like to: {{Feature Request}}",
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"label": "Report Bug",
|
|
125
|
+
"value": "Report a bug on: {{Bug Description}}",
|
|
126
|
+
},
|
|
127
|
+
]
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def create_agent(
|
|
131
|
+
agent_shared_state: Optional[AgentSharedState] = None,
|
|
132
|
+
agent_configuration: Optional[AgentConfiguration] = None,
|
|
133
|
+
) -> IntentAgent:
|
|
134
|
+
# Define model based on AI_MODE
|
|
135
|
+
model = get_model()
|
|
136
|
+
|
|
137
|
+
# Define tools
|
|
138
|
+
tools: list = []
|
|
139
|
+
|
|
140
|
+
# Add Knowledge Graph Explorer tool
|
|
141
|
+
@tool
|
|
142
|
+
def open_knowledge_graph_explorer() -> str:
|
|
143
|
+
"""Open the ABI Knowledge Graph Explorer interface for semantic data exploration."""
|
|
144
|
+
return """Here's our knowledge graph explorer:
|
|
145
|
+
|
|
146
|
+
[Open Explorer](http://localhost:7878/explorer/)
|
|
147
|
+
|
|
148
|
+
You can browse the data and run queries there."""
|
|
149
|
+
|
|
150
|
+
tools.append(open_knowledge_graph_explorer)
|
|
151
|
+
|
|
152
|
+
templatable_sparql_query_module = ABIModule.get_instance().engine.modules[
|
|
153
|
+
"naas_abi_core.modules.templatablesparqlquery"
|
|
154
|
+
]
|
|
155
|
+
|
|
156
|
+
agent_recommendation_tools = [
|
|
157
|
+
"find_business_proposal_agents",
|
|
158
|
+
"find_coding_agents",
|
|
159
|
+
"find_math_agents",
|
|
160
|
+
"find_best_value_agents",
|
|
161
|
+
"find_fastest_agents",
|
|
162
|
+
"find_cheapest_agents",
|
|
163
|
+
]
|
|
164
|
+
tools.extend(templatable_sparql_query_module.get_tools(agent_recommendation_tools))
|
|
165
|
+
|
|
166
|
+
shared_state = agent_shared_state or AgentSharedState(
|
|
167
|
+
thread_id="0", supervisor_agent=NAME
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
from queue import Queue
|
|
171
|
+
|
|
172
|
+
agent_queue: Queue = Queue()
|
|
173
|
+
|
|
174
|
+
# Define agents - all agents are now loaded automatically during module loading
|
|
175
|
+
agents: list = []
|
|
176
|
+
|
|
177
|
+
modules = ABIModule.get_instance().engine.modules.values()
|
|
178
|
+
for module in modules:
|
|
179
|
+
if hasattr(module, "agents"):
|
|
180
|
+
for agent in module.agents:
|
|
181
|
+
if (
|
|
182
|
+
agent is not None
|
|
183
|
+
and agent != AbiAgent
|
|
184
|
+
and (hasattr(agent, "NAME") and not agent.NAME.endswith("Research"))
|
|
185
|
+
): # exclude ChatGPT and Perplexity Research Agents NOT working properly with supervisor
|
|
186
|
+
new_agent = agent.New().duplicate(
|
|
187
|
+
agent_queue, agent_shared_state=shared_state
|
|
188
|
+
)
|
|
189
|
+
agents.append(new_agent)
|
|
190
|
+
|
|
191
|
+
# Define intents
|
|
192
|
+
intents: list = [
|
|
193
|
+
# Service opening intents - simple RAW responses
|
|
194
|
+
Intent(
|
|
195
|
+
intent_type=IntentType.RAW,
|
|
196
|
+
intent_value="open oxigraph",
|
|
197
|
+
intent_target="🚀 **Oxigraph Knowledge Graph Explorer**\n\n[Open Explorer](http://localhost:7878/explorer/)\n\nFeatures: Dashboard, SPARQL editor, query templates",
|
|
198
|
+
),
|
|
199
|
+
Intent(
|
|
200
|
+
intent_type=IntentType.RAW,
|
|
201
|
+
intent_value="open oxigraph server",
|
|
202
|
+
intent_target="🚀 **Oxigraph Knowledge Graph Explorer**\n\n[Open Explorer](http://localhost:7878/explorer/)\n\nFeatures: Dashboard, SPARQL editor, query templates",
|
|
203
|
+
),
|
|
204
|
+
Intent(
|
|
205
|
+
intent_type=IntentType.RAW,
|
|
206
|
+
intent_value="open knowledge graph",
|
|
207
|
+
intent_target="🚀 **Oxigraph Knowledge Graph Explorer**\n\n[Open Explorer](http://localhost:7878/explorer/)\n\nFeatures: Dashboard, SPARQL editor, query templates",
|
|
208
|
+
),
|
|
209
|
+
Intent(
|
|
210
|
+
intent_type=IntentType.RAW,
|
|
211
|
+
intent_value="open yasgui",
|
|
212
|
+
intent_target="🚀 **YasGUI SPARQL Editor**\n\n[Open YasGUI](http://localhost:3000)\n\nFull-featured SPARQL editor with syntax highlighting",
|
|
213
|
+
),
|
|
214
|
+
Intent(
|
|
215
|
+
intent_type=IntentType.RAW,
|
|
216
|
+
intent_value="open sparql editor",
|
|
217
|
+
intent_target="🚀 **YasGUI SPARQL Editor**\n\n[Open YasGUI](http://localhost:3000)\n\nFull-featured SPARQL editor with syntax highlighting",
|
|
218
|
+
),
|
|
219
|
+
Intent(
|
|
220
|
+
intent_type=IntentType.RAW,
|
|
221
|
+
intent_value="open dagster",
|
|
222
|
+
intent_target="🚀 **Dagster Orchestration UI**\n\n[Open Dagster](http://localhost:3001)\n\nData pipeline orchestration and monitoring",
|
|
223
|
+
),
|
|
224
|
+
Intent(
|
|
225
|
+
intent_type=IntentType.RAW,
|
|
226
|
+
intent_value="open dagster ui",
|
|
227
|
+
intent_target="🚀 **Dagster Orchestration UI**\n\n[Open Dagster](http://localhost:3001)\n\nData pipeline orchestration and monitoring",
|
|
228
|
+
),
|
|
229
|
+
Intent(
|
|
230
|
+
intent_type=IntentType.RAW,
|
|
231
|
+
intent_value="open orchestration",
|
|
232
|
+
intent_target="🚀 **Dagster Orchestration UI**\n\n[Open Dagster](http://localhost:3001)\n\nData pipeline orchestration and monitoring",
|
|
233
|
+
),
|
|
234
|
+
Intent(
|
|
235
|
+
intent_type=IntentType.RAW,
|
|
236
|
+
intent_value="show services",
|
|
237
|
+
intent_target="✅ **ABI Services Available:**\n\n**Core Services:**\n• **Oxigraph**: http://localhost:7878\n• **YasGUI**: http://localhost:3000\n• **PostgreSQL**: localhost:5432\n• **Dagster**: http://localhost:3001\n\n**Admin Tools:**\n• `make oxigraph-admin` - Terminal KG management\n• `make sparql-terminal` - Interactive SPARQL console",
|
|
238
|
+
),
|
|
239
|
+
Intent(
|
|
240
|
+
intent_type=IntentType.RAW,
|
|
241
|
+
intent_value="list services",
|
|
242
|
+
intent_target="✅ **ABI Services Available:**\n\n**Core Services:**\n• **Oxigraph**: http://localhost:7878\n• **YasGUI**: http://localhost:3000\n• **PostgreSQL**: localhost:5432\n• **Dagster**: http://localhost:3001\n\n**Admin Tools:**\n• `make oxigraph-admin` - Terminal KG management\n• `make sparql-terminal` - Interactive SPARQL console",
|
|
243
|
+
),
|
|
244
|
+
# Additional service opening variations
|
|
245
|
+
Intent(
|
|
246
|
+
intent_type=IntentType.RAW,
|
|
247
|
+
intent_value="launch oxigraph",
|
|
248
|
+
intent_target="🚀 Opening Oxigraph Knowledge Graph Explorer at http://localhost:7878/explorer/",
|
|
249
|
+
),
|
|
250
|
+
Intent(
|
|
251
|
+
intent_type=IntentType.RAW,
|
|
252
|
+
intent_value="start oxigraph",
|
|
253
|
+
intent_target="🚀 Opening Oxigraph Knowledge Graph Explorer at http://localhost:7878/explorer/",
|
|
254
|
+
),
|
|
255
|
+
Intent(
|
|
256
|
+
intent_type=IntentType.RAW,
|
|
257
|
+
intent_value="launch yasgui",
|
|
258
|
+
intent_target="🚀 Opening YasGUI SPARQL Editor at http://localhost:3000",
|
|
259
|
+
),
|
|
260
|
+
Intent(
|
|
261
|
+
intent_type=IntentType.RAW,
|
|
262
|
+
intent_value="start yasgui",
|
|
263
|
+
intent_target="🚀 Opening YasGUI SPARQL Editor at http://localhost:3000",
|
|
264
|
+
),
|
|
265
|
+
Intent(
|
|
266
|
+
intent_type=IntentType.RAW,
|
|
267
|
+
intent_value="launch dagster",
|
|
268
|
+
intent_target="🚀 Opening Dagster Orchestration UI at http://localhost:3001",
|
|
269
|
+
),
|
|
270
|
+
Intent(
|
|
271
|
+
intent_type=IntentType.RAW,
|
|
272
|
+
intent_value="start dagster",
|
|
273
|
+
intent_target="🚀 Opening Dagster Orchestration UI at http://localhost:3001",
|
|
274
|
+
),
|
|
275
|
+
Intent(
|
|
276
|
+
intent_type=IntentType.RAW,
|
|
277
|
+
intent_value="what services are running",
|
|
278
|
+
intent_target="✅ **ABI Services Available:**\n\n**Core Services:**\n• **Oxigraph**: http://localhost:7878\n• **YasGUI**: http://localhost:3000\n• **PostgreSQL**: localhost:5432\n• **Dagster**: http://localhost:3001\n\n**Admin Tools:**\n• `make oxigraph-admin` - Terminal KG management\n• `make sparql-terminal` - Interactive SPARQL console",
|
|
279
|
+
),
|
|
280
|
+
Intent(
|
|
281
|
+
intent_type=IntentType.RAW,
|
|
282
|
+
intent_value="what services are available",
|
|
283
|
+
intent_target="✅ **ABI Services Available:**\n\n**Core Services:**\n• **Oxigraph**: http://localhost:7878\n• **YasGUI**: http://localhost:3000\n• **PostgreSQL**: localhost:5432\n• **Dagster**: http://localhost:3001\n\n**Admin Tools:**\n• `make oxigraph-admin` - Terminal KG management\n• `make sparql-terminal` - Interactive SPARQL console",
|
|
284
|
+
),
|
|
285
|
+
# Oxigraph Admin specific intents - simple RAW responses
|
|
286
|
+
Intent(
|
|
287
|
+
intent_type=IntentType.RAW,
|
|
288
|
+
intent_value="open oxigraph admin",
|
|
289
|
+
intent_target="🔧 **Oxigraph Admin**\n\nTo launch the terminal admin interface:\n```\nmake oxigraph-admin\n```\n\nFeatures: KG statistics, query templates, service control",
|
|
290
|
+
),
|
|
291
|
+
Intent(
|
|
292
|
+
intent_type=IntentType.RAW,
|
|
293
|
+
intent_value="open sparql terminal",
|
|
294
|
+
intent_target="💻 **SPARQL Terminal**\n\nTo launch the interactive SPARQL console:\n```\nmake sparql-terminal\n```\n\nDirect command-line SPARQL queries",
|
|
295
|
+
),
|
|
296
|
+
Intent(
|
|
297
|
+
intent_type=IntentType.RAW,
|
|
298
|
+
intent_value="oxigraph admin",
|
|
299
|
+
intent_target="🔧 **Oxigraph Admin**\n\nTo launch the terminal admin interface:\n```\nmake oxigraph-admin\n```\n\nFeatures: KG statistics, query templates, service control",
|
|
300
|
+
),
|
|
301
|
+
Intent(
|
|
302
|
+
intent_type=IntentType.RAW,
|
|
303
|
+
intent_value="sparql terminal",
|
|
304
|
+
intent_target="💻 **SPARQL Terminal**\n\nTo launch the interactive SPARQL console:\n```\nmake sparql-terminal\n```\n\nDirect command-line SPARQL queries",
|
|
305
|
+
),
|
|
306
|
+
Intent(
|
|
307
|
+
intent_type=IntentType.RAW,
|
|
308
|
+
intent_value="knowledge graph admin",
|
|
309
|
+
intent_target="🔧 **Oxigraph Admin**\n\nTo launch the terminal admin interface:\n```\nmake oxigraph-admin\n```\n\nFeatures: KG statistics, query templates, service control",
|
|
310
|
+
),
|
|
311
|
+
Intent(
|
|
312
|
+
intent_type=IntentType.RAW,
|
|
313
|
+
intent_value="kg admin",
|
|
314
|
+
intent_target="🔧 **Oxigraph Admin**\n\nTo launch the terminal admin interface:\n```\nmake oxigraph-admin\n```\n\nFeatures: KG statistics, query templates, service control",
|
|
315
|
+
),
|
|
316
|
+
# Knowledge Graph Explorer intents
|
|
317
|
+
Intent(
|
|
318
|
+
intent_type=IntentType.TOOL,
|
|
319
|
+
intent_value="show knowledge graph explorer",
|
|
320
|
+
intent_target="open_knowledge_graph_explorer",
|
|
321
|
+
),
|
|
322
|
+
Intent(
|
|
323
|
+
intent_type=IntentType.TOOL,
|
|
324
|
+
intent_value="semantic knowledge graph",
|
|
325
|
+
intent_target="open_knowledge_graph_explorer",
|
|
326
|
+
),
|
|
327
|
+
Intent(
|
|
328
|
+
intent_type=IntentType.TOOL,
|
|
329
|
+
intent_value="show the data",
|
|
330
|
+
intent_target="open_knowledge_graph_explorer",
|
|
331
|
+
),
|
|
332
|
+
Intent(
|
|
333
|
+
intent_type=IntentType.TOOL,
|
|
334
|
+
intent_value="make a sparql query",
|
|
335
|
+
intent_target="open_knowledge_graph_explorer",
|
|
336
|
+
),
|
|
337
|
+
Intent(
|
|
338
|
+
intent_type=IntentType.TOOL,
|
|
339
|
+
intent_value="explore the database",
|
|
340
|
+
intent_target="open_knowledge_graph_explorer",
|
|
341
|
+
),
|
|
342
|
+
Intent(
|
|
343
|
+
intent_type=IntentType.TOOL,
|
|
344
|
+
intent_value="knowledge graph",
|
|
345
|
+
intent_target="open_knowledge_graph_explorer",
|
|
346
|
+
),
|
|
347
|
+
Intent(
|
|
348
|
+
intent_type=IntentType.TOOL,
|
|
349
|
+
intent_value="sparql",
|
|
350
|
+
intent_target="open_knowledge_graph_explorer",
|
|
351
|
+
),
|
|
352
|
+
Intent(
|
|
353
|
+
intent_type=IntentType.TOOL,
|
|
354
|
+
intent_value="explore ontology",
|
|
355
|
+
intent_target="open_knowledge_graph_explorer",
|
|
356
|
+
),
|
|
357
|
+
Intent(
|
|
358
|
+
intent_type=IntentType.TOOL,
|
|
359
|
+
intent_value="browse entities",
|
|
360
|
+
intent_target="open_knowledge_graph_explorer",
|
|
361
|
+
),
|
|
362
|
+
Intent(
|
|
363
|
+
intent_type=IntentType.TOOL,
|
|
364
|
+
intent_value="voir ton kg",
|
|
365
|
+
intent_target="open_knowledge_graph_explorer",
|
|
366
|
+
),
|
|
367
|
+
Intent(
|
|
368
|
+
intent_type=IntentType.TOOL,
|
|
369
|
+
intent_value="voir le graphe",
|
|
370
|
+
intent_target="open_knowledge_graph_explorer",
|
|
371
|
+
),
|
|
372
|
+
Intent(
|
|
373
|
+
intent_type=IntentType.TOOL,
|
|
374
|
+
intent_value="explorer les données",
|
|
375
|
+
intent_target="open_knowledge_graph_explorer",
|
|
376
|
+
),
|
|
377
|
+
Intent(
|
|
378
|
+
intent_type=IntentType.TOOL,
|
|
379
|
+
intent_value="base de données sémantique",
|
|
380
|
+
intent_target="open_knowledge_graph_explorer",
|
|
381
|
+
),
|
|
382
|
+
# Time tool
|
|
383
|
+
Intent(
|
|
384
|
+
intent_type=IntentType.TOOL,
|
|
385
|
+
intent_value="what time is it",
|
|
386
|
+
intent_target="get_time",
|
|
387
|
+
),
|
|
388
|
+
]
|
|
389
|
+
|
|
390
|
+
# Set configuration
|
|
391
|
+
agents_string = "\n".join(
|
|
392
|
+
[f"- {agent.name}: {agent.description}" for agent in agents]
|
|
393
|
+
)
|
|
394
|
+
tools_string = "\n".join([f"- {tool.name}: {tool.description}" for tool in tools])
|
|
395
|
+
if agent_configuration is None:
|
|
396
|
+
agent_configuration = AgentConfiguration(
|
|
397
|
+
system_prompt=SYSTEM_PROMPT.replace("[AGENTS]", agents_string).replace(
|
|
398
|
+
"[TOOLS]", tools_string
|
|
399
|
+
),
|
|
400
|
+
)
|
|
401
|
+
|
|
402
|
+
# Add intents for each agent (using agent names directly to avoid recursion)
|
|
403
|
+
for agent in agents:
|
|
404
|
+
# Add default intents to chat with any agent
|
|
405
|
+
intents.append(
|
|
406
|
+
Intent(
|
|
407
|
+
intent_type=IntentType.AGENT,
|
|
408
|
+
intent_value=f"Chat with {agent.name} Agent",
|
|
409
|
+
intent_target=agent.name,
|
|
410
|
+
intent_scope=IntentScope.DIRECT,
|
|
411
|
+
)
|
|
412
|
+
)
|
|
413
|
+
|
|
414
|
+
if hasattr(agent, "intents"):
|
|
415
|
+
for intent in agent.intents:
|
|
416
|
+
if (
|
|
417
|
+
intent.intent_scope is not None
|
|
418
|
+
and intent.intent_scope == IntentScope.DIRECT
|
|
419
|
+
):
|
|
420
|
+
continue
|
|
421
|
+
# Create new intent with target set to agent name
|
|
422
|
+
new_intent = Intent(
|
|
423
|
+
intent_type=IntentType.AGENT,
|
|
424
|
+
intent_value=intent.intent_value,
|
|
425
|
+
intent_target=agent.name,
|
|
426
|
+
)
|
|
427
|
+
intents.append(new_intent)
|
|
428
|
+
|
|
429
|
+
return AbiAgent(
|
|
430
|
+
name=NAME,
|
|
431
|
+
description=DESCRIPTION,
|
|
432
|
+
chat_model=model,
|
|
433
|
+
tools=tools,
|
|
434
|
+
agents=agents,
|
|
435
|
+
intents=intents,
|
|
436
|
+
state=shared_state,
|
|
437
|
+
configuration=agent_configuration,
|
|
438
|
+
)
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
class AbiAgent(IntentAgent):
|
|
442
|
+
pass
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from naas_abi.agents.AbiAgent import create_agent as create_abi_agent
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@pytest.fixture
|
|
6
|
+
def agent():
|
|
7
|
+
return create_abi_agent()
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# ------------------------------------------------------------
|
|
11
|
+
# DIRECT INTENTS
|
|
12
|
+
# ------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_hello(agent):
|
|
16
|
+
"""Test RAW intent mapping for name question -> RAW intent"""
|
|
17
|
+
result = agent.invoke("hello")
|
|
18
|
+
|
|
19
|
+
# Abi: Hello, what can I do for you?
|
|
20
|
+
|
|
21
|
+
assert result is not None, result
|
|
22
|
+
assert "Hello, what can I do for you?" in result, result
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_capabilities(agent):
|
|
26
|
+
"""Test capabilities of the agent"""
|
|
27
|
+
result = agent.invoke("what can you do")
|
|
28
|
+
|
|
29
|
+
# Abi: I’m Abi, developed by NaasAI. Here’s what I can do for you:
|
|
30
|
+
|
|
31
|
+
# 1. Agent Orchestration: I route your requests to the best specialized AI agents for the task—whether it’s coding, research, business strategy, creative work, or data
|
|
32
|
+
# analysis. 2. Strategic Advisory: I provide high-level consulting on business, technical, and strategic matters, synthesizing insights from multiple sources. 3. Knowledge
|
|
33
|
+
# Integration: I combine information from various agents and data sources to deliver clear, actionable answers. 4. Context Preservation: I keep track of our conversation, so
|
|
34
|
+
# you don’t have to repeat yourself, even when switching between different agents or topics. 5. Task Automation: I can help automate workflows, manage resources, and interact
|
|
35
|
+
# with platforms like GitHub or Naas. 6. Custom Recommendations: I suggest the best AI agent or tool for your specific needs—whether you want speed, cost-efficiency,
|
|
36
|
+
# intelligence, or a particular capability. 7. Multimodal Support: I handle text, images, PDFs, and more, and can generate or analyze content in multiple formats.
|
|
37
|
+
|
|
38
|
+
# If you have a specific task or question, just let me know!
|
|
39
|
+
|
|
40
|
+
assert result is not None, result
|
|
41
|
+
# Check that at least 80% (4 out of 5) of the key capabilities are present
|
|
42
|
+
key_capabilities: list[str] = [
|
|
43
|
+
"orchestration",
|
|
44
|
+
"strategic",
|
|
45
|
+
"advisory",
|
|
46
|
+
"knowledge",
|
|
47
|
+
"integration",
|
|
48
|
+
"coordination",
|
|
49
|
+
"multi-agent",
|
|
50
|
+
"routing",
|
|
51
|
+
"naasai",
|
|
52
|
+
]
|
|
53
|
+
found_capabilities = sum(1 for cap in key_capabilities if cap in result.lower())
|
|
54
|
+
min_required = int(len(key_capabilities) * 0.7)
|
|
55
|
+
assert found_capabilities >= min_required, (
|
|
56
|
+
f"Only found {found_capabilities} capabilities in response: {result}"
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# def test_search_web(agent):
|
|
61
|
+
# """Test search web capability"""
|
|
62
|
+
# from datetime import datetime
|
|
63
|
+
# result = agent.invoke("Ask ChatGPT Agent, what are the news about France today? Start by: 'As of today the date is YYYY-MM-DD.")
|
|
64
|
+
|
|
65
|
+
# assert result is not None, result
|
|
66
|
+
# assert datetime.now().strftime("%Y-%m-%d") in result, result
|
|
67
|
+
# assert "sources" in result.lower(), result
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_thank_you(agent):
|
|
71
|
+
"""Test thank you intent -> RAW intent"""
|
|
72
|
+
result = agent.invoke("thank you")
|
|
73
|
+
|
|
74
|
+
# Abi: You're welcome, can I help you with anything else?
|
|
75
|
+
|
|
76
|
+
assert result is not None, result
|
|
77
|
+
assert "You're welcome, can I help you with anything else?" in result, result
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
# ------------------------------------------------------------
|
|
81
|
+
# AGENTS CAPABILITIES
|
|
82
|
+
# ------------------------------------------------------------
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def test_search_web_intent(agent):
|
|
86
|
+
"""Test search web intent -> AGENT intent"""
|
|
87
|
+
result = agent.invoke("search news about ai")
|
|
88
|
+
|
|
89
|
+
# Abi: I found multiple intents that could handle your request:
|
|
90
|
+
|
|
91
|
+
# 1 ChatGPT (confidence: 89.7%) Intent: search news about
|
|
92
|
+
# 2 Grok (confidence: 89.7%) Intent: search news about
|
|
93
|
+
|
|
94
|
+
# Please choose an intent by number (e.g., '1' or '2')
|
|
95
|
+
|
|
96
|
+
assert result is not None, result
|
|
97
|
+
assert "I found multiple intents that could handle your request" in result, result
|
|
98
|
+
assert "chatgpt" in result.lower() or "grok" in result.lower(), result
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def test_image_generation_intent(agent):
|
|
102
|
+
"""Test AGENT intent mapping for image generation"""
|
|
103
|
+
result = agent.invoke("generate image")
|
|
104
|
+
|
|
105
|
+
# Gemini: What kind of image would you like to generate? Please describe it in detail.
|
|
106
|
+
|
|
107
|
+
assert result is not None, result
|
|
108
|
+
# The agent should route to Gemini for image generation
|
|
109
|
+
assert (
|
|
110
|
+
"describe" in result.lower()
|
|
111
|
+
or "image" in result.lower()
|
|
112
|
+
or "generate" in result.lower()
|
|
113
|
+
), result
|
|
114
|
+
|
|
115
|
+
result = agent.invoke("a cat in a box")
|
|
116
|
+
assert "generate" in result.lower(), result
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def test_multimodal_analysis_intent(agent):
|
|
120
|
+
"""Test AGENT intent mapping for multimodal analysis"""
|
|
121
|
+
result = agent.invoke("analyze image")
|
|
122
|
+
|
|
123
|
+
assert result is not None, result
|
|
124
|
+
# The agent should route to Gemini for image analysis
|
|
125
|
+
assert (
|
|
126
|
+
"gemini" in result.lower()
|
|
127
|
+
or "analyze" in result.lower()
|
|
128
|
+
or "image" in result.lower()
|
|
129
|
+
), result
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
# ------------------------------------------------------------
|
|
133
|
+
# AGENTS ROUTING
|
|
134
|
+
# ------------------------------------------------------------
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def test_chatgpt_intent(agent):
|
|
138
|
+
"""Test AGENT intent mapping for chatgpt"""
|
|
139
|
+
result = agent.invoke("@Knowledge_Graph_Builder hello")
|
|
140
|
+
|
|
141
|
+
# Knowledge_Graph_Builder: Hello, what can I do for you?
|
|
142
|
+
|
|
143
|
+
assert result is not None, result
|
|
144
|
+
assert "Hello, what can I do for you?" in result, result
|
|
145
|
+
|
|
146
|
+
result = agent.invoke("search news about ai") # testing routing to other agents
|
|
147
|
+
|
|
148
|
+
# Knowledge_Graph_Builder: I found multiple intents that could handle your request:
|
|
149
|
+
|
|
150
|
+
# 1 ChatGPT (confidence: 89.7%) Intent: search news about
|
|
151
|
+
# 2 Grok (confidence: 89.7%) Intent: search news about
|
|
152
|
+
|
|
153
|
+
# Please choose an intent by number (e.g., '1' or '2')
|
|
154
|
+
|
|
155
|
+
assert result is not None, result
|
|
156
|
+
assert "I found multiple intents that could handle your request" in result, result
|
|
157
|
+
assert "chatgpt" in result.lower() or "grok" in result.lower(), result
|