Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.ca.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ La plataforma està dissenyada per a desenvolupadors, científics de dades i equ

- [**simplified-stack**](simplified-stack/README.ca.md): Versió lleugera optimitzada per al desenvolupament local que integra Drupal, Obsidian i Forgejo per a fluxos de treball d'IA aïllats.
- [**very-simplified-stack**](very-simplified-stack/README.ca.md): Versió minimalista que elimina l'orquestració de n8n i es centra en serveis de veu i l'API d'agent Cognito, dissenyada per connectar amb una instància d'Ollama externa.
- [**AGI Agents & NOOA Framework**](agents/README.md): Mòdul d'agents cognitius que implementa el Roadmap de 5 fases (Chain-of-Thought, Autovalidació i iteració, Memòria a llarg termini amb SQLite + Vectorial, Multi-agent, i Autonomia) integrat de manera nativa amb suport per al paradigma NOOA (NVIDIA-labs Object Oriented Agents).

---

Expand Down
1 change: 1 addition & 0 deletions README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ The platform is designed for developers, data scientists, and AI teams that need

- [**simplified-stack**](simplified-stack/README.en.md): Lightweight version optimized for local development that integrates Drupal, Obsidian, and Forgejo for isolated AI workflows.
- [**very-simplified-stack**](very-simplified-stack/README.en.md): Minimalist version that removes n8n orchestration and focuses on voice services and the Cognito agent API, designed to connect to an external Ollama instance.
- [**AGI Agents & NOOA Framework**](agents/README.md): Cognitive agents module implementing the 5-phase Roadmap (Chain-of-Thought, Self-Evaluation & iteration, Long-Term SQLite + Vectorial Memory, Multi-Agent, and Autonomy) natively integrated with full support for the NOOA (NVIDIA-labs Object Oriented Agents) paradigm.

---

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ La plataforma está diseñada para desarrolladores, científicos de datos y equi

- [**simplified-stack**](simplified-stack/README.md): Versión ligera optimizada para desarrollo local que integra Drupal, Obsidian y Forgejo para flujos de trabajo de IA aislados.
- [**very-simplified-stack**](very-simplified-stack/README.md): Versión minimalista que elimina la orquestación de n8n y se centra en servicios de voz y el API de agente Cognito, diseñada para conectar con una instancia de Ollama externa.
- [**AGI Agents & NOOA Framework**](agents/README.md): Módulo de agentes cognitivos que implementa el Roadmap de 5 fases (Chain-of-Thought, Autovalidación e iteración, Memoria a largo plazo con SQLite + Vectorial, Multi-agente, y Autonomía) integrado de forma nativa con soporte para el paradigma NOOA (NVIDIA-labs Object Oriented Agents).

---

Expand Down
3 changes: 2 additions & 1 deletion README.zh-cn.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@
## 🔄 变体版本

- [**simplified-stack**](simplified-stack/README.zh-cn.md): 为本地开发优化的轻量级版本,集成了 Drupal、Obsidian 和 Forgejo,用于隔离的 AI 工作流。
- [**very-simplified-stack**](very-simplified-stack/README.zh-cn.md): 删除了 n8n 编排的极简版本,专注于语音服务和 Cognito 代理 API,旨在连接到外部 Ollama 实例。
- [**very-simplified-stack**](very-simplified-stack/README.zh-cn.md): 删除了 n8n 编排的极简版本,专注于语音服务 and Cognito 代理 API,旨在连接 to 外部 Ollama 实例。
- [**AGI Agents & NOOA Framework**](agents/README.md): 认知代理模块,实现5阶段路线图(思维链、自我评估与迭代、基于SQLite + 向量的长期记忆、多智能体协作、以及完全自主),原生集成并全面支持 NOOA (NVIDIA-labs Object Oriented Agents) 框架规范。

---

Expand Down
4 changes: 2 additions & 2 deletions agents/README.ca.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ Welcome to the AGI agents module. This directory contains the implementation of
| 1 | **Chain-of-Thought** | ✅ IMPLEMENTED | Reasoning + Multi-LLM routing |
| 2 | **Self-Evaluation** | ✅ IMPLEMENTED | Output validation + iteration |
| 3 | **Memory & Learning** | ✅ IMPLEMENTED | Experience storage + few-shot |
| 4 | Multi-Agent Collab | 🔄 Planned | Team coordination |
| 5 | Autonomous Op | 🔄 Planned | Fully autonomous loops |
| 4 | **Multi-Agent Collab** | ✅ IMPLEMENTED | Team coordination & Orchestrator |
| 5 | **Autonomous Op** | ✅ IMPLEMENTED | Fully autonomous loops & Optimization |

## 🚀 Quick Start

Expand Down
4 changes: 2 additions & 2 deletions agents/README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ Welcome to the AGI agents module. This directory contains the implementation of
| 1 | **Chain-of-Thought** | ✅ IMPLEMENTED | Reasoning + Multi-LLM routing |
| 2 | **Self-Evaluation** | ✅ IMPLEMENTED | Output validation + iteration |
| 3 | **Memory & Learning** | ✅ IMPLEMENTED | Experience storage + few-shot |
| 4 | Multi-Agent Collab | 🔄 Planned | Team coordination |
| 5 | Autonomous Op | 🔄 Planned | Fully autonomous loops |
| 4 | **Multi-Agent Collab** | ✅ IMPLEMENTED | Team coordination & Orchestrator |
| 5 | **Autonomous Op** | ✅ IMPLEMENTED | Fully autonomous loops & Optimization |

## 🚀 Quick Start

Expand Down
4 changes: 2 additions & 2 deletions agents/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ Welcome to the AGI agents module. This directory contains the implementation of
| 1 | **Chain-of-Thought** | ✅ IMPLEMENTED | Reasoning + Multi-LLM routing |
| 2 | **Self-Evaluation** | ✅ IMPLEMENTED | Output validation + iteration |
| 3 | **Memory & Learning** | ✅ IMPLEMENTED | Experience storage + few-shot |
| 4 | Multi-Agent Collab | 🔄 Planned | Team coordination |
| 5 | Autonomous Op | 🔄 Planned | Fully autonomous loops |
| 4 | **Multi-Agent Collab** | ✅ IMPLEMENTED | Team coordination & Orchestrator |
| 5 | **Autonomous Op** | ✅ IMPLEMENTED | Fully autonomous loops & Optimization |

## 🚀 Quick Start

Expand Down
4 changes: 2 additions & 2 deletions agents/README.zh-cn.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ Welcome to the AGI agents module. This directory contains the implementation of
| 1 | **Chain-of-Thought** | ✅ IMPLEMENTED | Reasoning + Multi-LLM routing |
| 2 | **Self-Evaluation** | ✅ IMPLEMENTED | Output validation + iteration |
| 3 | **Memory & Learning** | ✅ IMPLEMENTED | Experience storage + few-shot |
| 4 | Multi-Agent Collab | 🔄 Planned | Team coordination |
| 5 | Autonomous Op | 🔄 Planned | Fully autonomous loops |
| 4 | **Multi-Agent Collab** | ✅ IMPLEMENTED | Team coordination & Orchestrator |
| 5 | **Autonomous Op** | ✅ IMPLEMENTED | Fully autonomous loops & Optimization |

## 🚀 Quick Start

Expand Down
101 changes: 78 additions & 23 deletions agents/agent_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,35 +30,74 @@ class AgentCapability(Enum):
SYNTHESIS = "synthesis"
EVALUATION = "evaluation"

class TaskCategory(Enum):
"""Task category for compatibility"""
ANALYSIS = "analysis"
RESEARCH = "research"
CODE = "code"
CREATIVE = "creative"
SYNTHESIS = "synthesis"
EVALUATION = "evaluation"


@dataclass
class Agent:
"""Represents an AI agent with specific capabilities"""
name: str
agent_type: str
capabilities: List[AgentCapability]
max_complexity: int # Maximum complexity it can handle (1-10)
capabilities: List[Any] = field(default_factory=list)
agent_type: str = "general"
max_complexity: int = 10
current_load: int = 0
success_rate: float = 0.95 # Historical success rate

def can_handle(self, task_type: TaskType, complexity: int) -> bool:
type: str = ""
available: bool = True

def __post_init__(self):
if self.type:
self.agent_type = self.type
elif self.agent_type:
self.type = self.agent_type

def can_handle(self, task_type: Any, complexity: Any) -> bool:
"""Check if agent can handle the task"""
# Check complexity
if isinstance(complexity, float):
complexity = int(complexity * 10)
else:
complexity = int(complexity)

if complexity > self.max_complexity:
return False

# Check capability match
capability_map = {
TaskType.ANALYSIS: AgentCapability.ANALYSIS,
TaskType.RESEARCH: AgentCapability.RESEARCH,
TaskType.CODE: AgentCapability.CODE_GENERATION,
TaskType.CREATIVE: AgentCapability.CREATIVE,
TaskType.SYNTHESIS: AgentCapability.SYNTHESIS,
TaskType.EVALUATION: AgentCapability.EVALUATION,
}

required_capability = capability_map.get(task_type, AgentCapability.ANALYSIS)
return required_capability in self.capabilities

# Support both string and Enum for task_type
task_str = task_type.value if hasattr(task_type, "value") else str(task_type)

# Support both string and Enum for capabilities
agent_caps = []
for cap in self.capabilities:
if hasattr(cap, "value"):
agent_caps.append(cap.value)
if cap == AgentCapability.CODE_GENERATION:
agent_caps.append("code")
else:
agent_caps.append(str(cap))
if str(cap) == "code":
agent_caps.append("code_generation")

# Map task type to capability
required_caps = [task_str]
if task_str == "code":
required_caps.append("code_generation")
elif task_str == "code_generation":
required_caps.append("code")
elif task_str == "analytical":
required_caps.append("analysis")
elif task_str == "analysis":
required_caps.append("analytical")
elif task_str == "creative":
required_caps.append("brainstorm")
required_caps.append("ideate")

return any(rc in agent_caps for rc in required_caps)

def get_load_score(self) -> float:
"""Get current load score (0-1, higher = busier)"""
Expand Down Expand Up @@ -177,13 +216,24 @@ def __init__(self, registry: Optional[AgentRegistry] = None):
"""
self.registry = registry or AgentRegistry()
logger.info("AgentRouter initialized")

def register_agent(self, agent: Agent):
self.registry.add_agent(agent)

@property
def agent_registry(self) -> Dict[str, Agent]:
return self.registry.agents

def select_best_agent(
self,
task_type: TaskType,
complexity: int,
task_type: Any,
complexity: Any,
preferences: Optional[List[str]] = None
) -> Optional[Agent]:
if isinstance(complexity, float):
complexity = int(complexity * 10)
else:
complexity = int(complexity)
"""
Select the best agent for a task.

Expand All @@ -200,8 +250,9 @@ def select_best_agent(
Returns:
Selected Agent, or None if no suitable agent found
"""
task_str = task_type.value if hasattr(task_type, "value") else str(task_type)
logger.debug(
f"Selecting agent for {task_type.value} task "
f"Selecting agent for {task_str} task "
f"(complexity={complexity})"
)

Expand All @@ -218,18 +269,22 @@ def select_best_agent(

# Then, find all capable agents
for agent in self.registry.list_agents():
if not getattr(agent, "available", True):
continue
if agent.can_handle(task_type, complexity):
# Calculate score: lower is better
# Lower load is better, higher success rate is better
score = (
agent.get_load_score() * 0.7 + # 70% weight on load
(1 - agent.success_rate) * 0.3 # 30% weight on success rate
)
if agent.agent_type == task_str or agent.type == task_str:
score -= 1.0 # Significant bonus for exact type matching!
candidates.append((agent, score))

if not candidates:
logger.warning(
f"No suitable agent found for {task_type.value} "
f"No suitable agent found for {task_str} "
f"(complexity={complexity})"
)
return None
Expand Down
8 changes: 6 additions & 2 deletions agents/iterative_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@
from typing import Dict, Any, Optional
import logging

from .chain_of_thought_agent import ChainOfThoughtAgent
from .output_validator import OutputValidator
try:
from .chain_of_thought_agent import ChainOfThoughtAgent
from .output_validator import OutputValidator
except (ImportError, ValueError):
from chain_of_thought_agent import ChainOfThoughtAgent
from output_validator import OutputValidator

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
Expand Down
2 changes: 1 addition & 1 deletion agents/meta_learner.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,9 @@ def _classify_task(self, task: str) -> str:
task_lower = task.lower()

keywords = {
'coding': ['code', 'algorithm', 'program', 'function', 'class'],
'analytical': ['analyze', 'compare', 'evaluate', 'explain cause'],
'creative': ['create', 'generate', 'imagine', 'write', 'design'],
'coding': ['code', 'algorithm', 'program', 'function', 'class'],
'explanation': ['what', 'how', 'why', 'explain', 'describe'],
'evidence': ['prove', 'support', 'evidence', 'data']
}
Expand Down
9 changes: 3 additions & 6 deletions agents/model_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ def select_model(self, category: str) -> str:
In simple version, returns first available model.
"""
if category not in MODEL_PROFILES:
logger.warning(f"Unknown category {category}, using general")
category = "general"
logger.warning(f"Unknown category {category}, using default model")
return DEFAULT_MODEL

models = MODEL_PROFILES[category]["models"]
selected = models[0] if models else DEFAULT_MODEL
Expand Down Expand Up @@ -194,9 +194,6 @@ def route_and_execute(

def get_routing_stats(self) -> Dict[str, Any]:
"""Get statistics on routing decisions."""
if not self.routing_history:
return {"total_tasks": 0}

categories_used = {}
models_used = {}

Expand All @@ -215,7 +212,7 @@ def get_routing_stats(self) -> Dict[str, Any]:
sum(c["confidence"] for c in self.classification_history)
/ max(len(self.classification_history), 1),
2,
),
) if self.classification_history else 0.0,
}


Expand Down
14 changes: 12 additions & 2 deletions agents/performance_optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,16 @@ def profile_task(
def get_performance_summary(self) -> Dict[str, Any]:
"""Get performance summary"""
if not self.metrics:
return {'metrics_count': 0}
return {
'total_executions': 0,
'cache_hits': 0,
'cache_hit_rate': 0,
'avg_execution_time': 0,
'min_execution_time': 0,
'max_execution_time': 0,
'cache_size': len(self.query_cache),
'metrics_count': 0
}

execution_times = [m.execution_time for m in self.metrics]
cache_hits = sum(1 for m in self.metrics if m.cache_hit)
Expand All @@ -218,7 +227,8 @@ def get_performance_summary(self) -> Dict[str, Any]:
'avg_execution_time': sum(execution_times) / len(execution_times) if execution_times else 0,
'min_execution_time': min(execution_times) if execution_times else 0,
'max_execution_time': max(execution_times) if execution_times else 0,
'cache_size': len(self.query_cache)
'cache_size': len(self.query_cache),
'metrics_count': len(self.metrics)
}

def optimize_allocation(self) -> Dict[str, Any]:
Expand Down
31 changes: 27 additions & 4 deletions agents/result_synthesizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ def __init__(self, cot_agent=None, validator=None):
def synthesize(
self,
main_task: str,
subtask_results: Dict[str, TaskResult],
subtask_descriptions: Dict[str, str]
subtask_results: Optional[Dict[str, Any]] = None,
subtask_descriptions: Optional[Dict[str, str]] = None,
results: Optional[Dict[str, Any]] = None,
task_descriptions: Optional[Dict[str, str]] = None
) -> str:
"""
Synthesize multiple sub-task results into final answer.
Expand All @@ -67,15 +69,36 @@ def synthesize(
Returns:
Final synthesized answer
"""
if subtask_results is None:
subtask_results = results or {}
if subtask_descriptions is None:
subtask_descriptions = task_descriptions or {}

# Normalize subtask_results to always have TaskResult objects
normalized_results = {}
for k, v in subtask_results.items():
if isinstance(v, dict):
ans = v.get("answer") or v.get("analysis") or v.get("result") or v.get("feedback") or ""
confidence = v.get("confidence", 0.9)
quality = v.get("quality") or (confidence * 5.0)
normalized_results[k] = TaskResult(
task_id=k,
status=TaskStatus.COMPLETED,
result=ans,
quality_score=quality
)
else:
normalized_results[k] = v

logger.info(
f"Synthesizing {len(subtask_results)} subtask results "
f"Synthesizing {len(normalized_results)} subtask results "
f"for main task: {main_task[:80]}..."
)

# Step 1: Filter successful results
successful_results = {
task_id: result
for task_id, result in subtask_results.items()
for task_id, result in normalized_results.items()
if result.status == TaskStatus.COMPLETED and result.result
}

Expand Down
8 changes: 5 additions & 3 deletions agents/task_decomposer.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class TaskDecomposition:
"""Result of task decomposition"""
main_task: str
main_task_type: TaskType
complexity: int
complexity: float
subtasks: List[SubTask]
execution_layers: List[List[str]] # Groups of tasks that can run in parallel
estimated_total_time: float # minutes
Expand Down Expand Up @@ -209,7 +209,7 @@ def decompose(
result = TaskDecomposition(
main_task=task,
main_task_type=main_task_type,
complexity=main_complexity,
complexity=main_complexity / 10.0,
subtasks=subtasks,
execution_layers=execution_layers,
estimated_total_time=total_time,
Expand Down Expand Up @@ -242,7 +242,9 @@ def _estimate_complexity(self, task: str) -> int:

Uses keyword matching, length, and task type indicators.
"""
complexity = 1
if len(task.split()) < 5:
return 1
complexity = 3
task_lower = task.lower()

# Base complexity from indicators
Expand Down
Loading
Loading