feat: оновлення інфраструктури з Node #2 та нові сервіси
This commit is contained in:
@@ -6,20 +6,36 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📍 Production Servers
|
## 📍 Network Nodes
|
||||||
|
|
||||||
### GEX44 Server #2844465 (Hetzner)
|
### Node #1: Production Server (Hetzner GEX44 #2844465)
|
||||||
|
- **Node ID:** `node-1-hetzner-gex44`
|
||||||
- **IP Address:** `144.76.224.179`
|
- **IP Address:** `144.76.224.179`
|
||||||
- **SSH Access:** `ssh root@144.76.224.179`
|
- **SSH Access:** `ssh root@144.76.224.179`
|
||||||
- **Location:** Hetzner Cloud
|
- **Location:** Hetzner Cloud (Germany)
|
||||||
- **Project Root:** `/opt/microdao-daarion` (or `/opt/dagi-router`)
|
- **Project Root:** `/opt/microdao-daarion`
|
||||||
- **Docker Network:** `dagi-network`
|
- **Docker Network:** `dagi-network`
|
||||||
|
- **Role:** Production Router + Gateway + All Services
|
||||||
|
- **Uptime:** 24/7
|
||||||
|
|
||||||
**Domains:**
|
**Domains:**
|
||||||
- `gateway.daarion.city` → `144.76.224.179` (Gateway + Nginx)
|
- `gateway.daarion.city` → `144.76.224.179` (Gateway + Nginx)
|
||||||
- `api.daarion.city` → TBD (API Gateway)
|
- `api.daarion.city` → TBD (API Gateway)
|
||||||
- `daarion.city` → TBD (Main website)
|
- `daarion.city` → TBD (Main website)
|
||||||
|
|
||||||
|
### Node #2: Development Node (MacBook Pro M4 Max)
|
||||||
|
- **Node ID:** `node-2-macbook-m4max`
|
||||||
|
- **Local IP:** `192.168.1.244`
|
||||||
|
- **SSH Access:** `ssh apple@192.168.1.244` (if enabled)
|
||||||
|
- **Location:** Local Network (Ivan's Office)
|
||||||
|
- **Project Root:** `/Users/apple/github-projects/microdao-daarion`
|
||||||
|
- **Role:** Development + Testing + Backup Router
|
||||||
|
- **Specs:** M4 Max (16 cores), 64GB RAM, 2TB SSD, 40-core GPU
|
||||||
|
- **Uptime:** On-demand (battery-powered)
|
||||||
|
|
||||||
|
**See full specs:** [NODE-2-MACBOOK-SPECS.md](./NODE-2-MACBOOK-SPECS.md)
|
||||||
|
**Current state:** [NODE-2-CURRENT-STATE.md](./NODE-2-CURRENT-STATE.md) — What's running now
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🐙 GitHub Repositories
|
## 🐙 GitHub Repositories
|
||||||
|
|||||||
@@ -6,12 +6,12 @@
|
|||||||
"source": [
|
"source": [
|
||||||
"# 🚀 Infrastructure Quick Reference — DAARION & MicroDAO\n",
|
"# 🚀 Infrastructure Quick Reference — DAARION & MicroDAO\n",
|
||||||
"\n",
|
"\n",
|
||||||
"**Версія:** 1.1.0 \n",
|
"**Версія:** 1.2.0 \n",
|
||||||
"**Останнє оновлення:** 2025-01-17 \n",
|
"**Останнє оновлення:** 2025-01-17 \n",
|
||||||
"\n",
|
"\n",
|
||||||
"Цей notebook містить швидкий довідник по серверах, репозиторіях та endpoints для DAGI Stack.\n",
|
"Цей notebook містить швидкий довідник по серверах, репозиторіях та endpoints для DAGI Stack.\n",
|
||||||
"\n",
|
"\n",
|
||||||
"**NEW:** Vision Encoder + Qdrant vector database (OpenCLIP ViT-L/14)"
|
"**NEW:** Vision Encoder + Qdrant + Node #2 (MacBook Pro M4 Max)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -48,6 +48,75 @@
|
|||||||
" print(f\"{name.upper():<20} {service['port']:<7} {service['container']:<30} {health}{gpu}\")"
|
" print(f\"{name.upper():<20} {service['port']:<7} {service['container']:<30} {health}{gpu}\")"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## 🖥️ Network Nodes\n",
|
||||||
|
"\n",
|
||||||
|
"### Node #1: Production Server (Hetzner)\n",
|
||||||
|
"- **Node ID:** node-1-hetzner-gex44\n",
|
||||||
|
"- **IP:** 144.76.224.179\n",
|
||||||
|
"- **Role:** Production Router + Gateway + All Services (24/7)\n",
|
||||||
|
"- **Location:** Hetzner Cloud (Germany)\n",
|
||||||
|
"\n",
|
||||||
|
"### Node #2: Development Node (MacBook Pro M4 Max)\n",
|
||||||
|
"- **Node ID:** node-2-macbook-m4max\n",
|
||||||
|
"- **Local IP:** 192.168.1.244\n",
|
||||||
|
"- **Role:** Development + Testing + Backup Router\n",
|
||||||
|
"- **Specs:** M4 Max (16 cores), 64GB RAM, 2TB SSD, 40-core GPU\n",
|
||||||
|
"- **Location:** Local Network (Ivan's Office)\n",
|
||||||
|
"- **Docs:** [NODE-2-MACBOOK-SPECS.md](../NODE-2-MACBOOK-SPECS.md)\n",
|
||||||
|
"\n",
|
||||||
|
"---"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Network Nodes Configuration\n",
|
||||||
|
"NODES = {\n",
|
||||||
|
" \"node-1\": {\n",
|
||||||
|
" \"name\": \"Hetzner GEX44\",\n",
|
||||||
|
" \"ip\": \"144.76.224.179\",\n",
|
||||||
|
" \"local_ip\": None,\n",
|
||||||
|
" \"role\": \"production\",\n",
|
||||||
|
" \"uptime\": \"24/7\",\n",
|
||||||
|
" \"ssh\": \"root@144.76.224.179\",\n",
|
||||||
|
" \"domain\": \"gateway.daarion.city\",\n",
|
||||||
|
" \"services\": \"All (17 services)\",\n",
|
||||||
|
" \"specs\": \"See SYSTEM-INVENTORY.md\"\n",
|
||||||
|
" },\n",
|
||||||
|
" \"node-2\": {\n",
|
||||||
|
" \"name\": \"MacBook Pro M4 Max\",\n",
|
||||||
|
" \"ip\": None,\n",
|
||||||
|
" \"local_ip\": \"192.168.1.244\",\n",
|
||||||
|
" \"role\": \"development\",\n",
|
||||||
|
" \"uptime\": \"on-demand\",\n",
|
||||||
|
" \"ssh\": \"apple@192.168.1.244\",\n",
|
||||||
|
" \"domain\": None,\n",
|
||||||
|
" \"services\": \"Core only (Router, DevTools, Memory, Ollama)\",\n",
|
||||||
|
" \"specs\": \"M4 Max, 16 cores, 64GB RAM, 2TB SSD, 40-core GPU\"\n",
|
||||||
|
" }\n",
|
||||||
|
"}\n",
|
||||||
|
"\n",
|
||||||
|
"print(\"DAGI Stack Network Nodes:\")\n",
|
||||||
|
"print(\"=\"*80)\n",
|
||||||
|
"for node_id, node in NODES.items():\n",
|
||||||
|
" print(f\"\\n{node_id.upper()}: {node['name']}\")\n",
|
||||||
|
" print(f\" Role: {node['role']}\")\n",
|
||||||
|
" print(f\" IP: {node['ip'] or node['local_ip']}\")\n",
|
||||||
|
" print(f\" SSH: {node['ssh']}\")\n",
|
||||||
|
" print(f\" Uptime: {node['uptime']}\")\n",
|
||||||
|
" print(f\" Services: {node['services']}\")\n",
|
||||||
|
" if node['domain']:\n",
|
||||||
|
" print(f\" Domain: https://{node['domain']}\")\n",
|
||||||
|
" print(f\" Specs: {node['specs']}\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
@@ -157,7 +226,8 @@
|
|||||||
" \"Deployment\": \"../DEPLOY-NOW.md\",\n",
|
" \"Deployment\": \"../DEPLOY-NOW.md\",\n",
|
||||||
" \"Helion Status\": \"../STATUS-HELION.md\",\n",
|
" \"Helion Status\": \"../STATUS-HELION.md\",\n",
|
||||||
" \"Architecture Index\": \"../docs/cursor/README.md\",\n",
|
" \"Architecture Index\": \"../docs/cursor/README.md\",\n",
|
||||||
" \"API Reference\": \"../docs/api.md\"\n",
|
" \"API Reference\": \"../docs/api.md\",\n",
|
||||||
|
" \"Node #2 Specs\": \"../NODE-2-MACBOOK-SPECS.md\"\n",
|
||||||
"}\n",
|
"}\n",
|
||||||
"\n",
|
"\n",
|
||||||
"print(\"Documentation Quick Links:\")\n",
|
"print(\"Documentation Quick Links:\")\n",
|
||||||
@@ -180,11 +250,14 @@
|
|||||||
"- ✅ **768-dim embeddings** for multimodal RAG\n",
|
"- ✅ **768-dim embeddings** for multimodal RAG\n",
|
||||||
"- ✅ Created VISION-ENCODER-STATUS.md with full implementation details\n",
|
"- ✅ Created VISION-ENCODER-STATUS.md with full implementation details\n",
|
||||||
"- ✅ Added test-vision-encoder.sh smoke tests\n",
|
"- ✅ Added test-vision-encoder.sh smoke tests\n",
|
||||||
|
"- ✅ **Added Node #2** (MacBook Pro M4 Max) as development node\n",
|
||||||
|
"- ✅ Created NODE-2-MACBOOK-SPECS.md with complete specifications\n",
|
||||||
"\n",
|
"\n",
|
||||||
"### Services Count: 17 (from 15)\n",
|
"### Network Architecture\n",
|
||||||
"- Total Services: 17\n",
|
"- **Nodes:** 2 (1 production + 1 development)\n",
|
||||||
"- GPU Services: 1 (Vision Encoder)\n",
|
"- **Total Services:** 17\n",
|
||||||
"- Vector Databases: 1 (Qdrant)\n",
|
"- **GPU Services:** 1 (Vision Encoder) + Node #2 (40-core Apple GPU)\n",
|
||||||
|
"- **Vector Databases:** 1 (Qdrant)\n",
|
||||||
"\n",
|
"\n",
|
||||||
"---\n",
|
"---\n",
|
||||||
"\n",
|
"\n",
|
||||||
|
|||||||
33
http_api.py
33
http_api.py
@@ -5,7 +5,7 @@ Provides HTTP endpoints for routing requests
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from fastapi import APIRouter, HTTPException, status
|
from fastapi import APIRouter, HTTPException, status
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field, ConfigDict
|
||||||
from typing import Optional, Dict, Any
|
from typing import Optional, Dict, Any
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@@ -21,6 +21,8 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class IncomingRequest(BaseModel):
|
class IncomingRequest(BaseModel):
|
||||||
"""HTTP request format"""
|
"""HTTP request format"""
|
||||||
|
model_config = ConfigDict(extra='allow') # Дозволити додаткові поля для сумісності
|
||||||
|
|
||||||
mode: Optional[str] = Field(None, description="Request mode (e.g., 'chat', 'crew')")
|
mode: Optional[str] = Field(None, description="Request mode (e.g., 'chat', 'crew')")
|
||||||
agent: Optional[str] = Field(None, description="Agent ID (e.g., 'devtools')")
|
agent: Optional[str] = Field(None, description="Agent ID (e.g., 'devtools')")
|
||||||
message: Optional[str] = Field(None, description="User message")
|
message: Optional[str] = Field(None, description="User message")
|
||||||
@@ -29,6 +31,7 @@ class IncomingRequest(BaseModel):
|
|||||||
session_id: Optional[str] = Field(None, description="Session identifier")
|
session_id: Optional[str] = Field(None, description="Session identifier")
|
||||||
user_id: Optional[str] = Field(None, description="User identifier")
|
user_id: Optional[str] = Field(None, description="User identifier")
|
||||||
payload: Dict[str, Any] = Field(default_factory=dict, description="Additional payload data")
|
payload: Dict[str, Any] = Field(default_factory=dict, description="Additional payload data")
|
||||||
|
context: Optional[Dict[str, Any]] = Field(None, description="Legacy: context on top level (will be migrated to payload.context)")
|
||||||
|
|
||||||
|
|
||||||
class RouterAPIResponse(BaseModel):
|
class RouterAPIResponse(BaseModel):
|
||||||
@@ -74,6 +77,32 @@ def build_router_http(app_core: RouterApp) -> APIRouter:
|
|||||||
- Other metadata
|
- Other metadata
|
||||||
"""
|
"""
|
||||||
logger.info(f"Incoming request: agent={req.agent}, mode={req.mode}")
|
logger.info(f"Incoming request: agent={req.agent}, mode={req.mode}")
|
||||||
|
logger.info(f"Raw payload type: {type(req.payload)}, keys: {list(req.payload.keys()) if req.payload else []}")
|
||||||
|
logger.info(f"Raw context: {req.context}")
|
||||||
|
|
||||||
|
# Нормалізувати payload: якщо є "context" на верхньому рівні (старий формат),
|
||||||
|
# перемістити його в payload.context для уніфікованої обробки
|
||||||
|
normalized_payload = req.payload.copy() if req.payload else {}
|
||||||
|
|
||||||
|
# Перевірити, чи є context на верхньому рівні (legacy формат від gateway-bot)
|
||||||
|
# Це потрібно для сумісності з DAARWIZZ
|
||||||
|
if req.context:
|
||||||
|
# Якщо context на верхньому рівні, перемістити в payload.context
|
||||||
|
if "context" not in normalized_payload:
|
||||||
|
normalized_payload["context"] = {}
|
||||||
|
# Мержити context з верхнього рівня в payload.context
|
||||||
|
if isinstance(req.context, dict):
|
||||||
|
normalized_payload["context"].update(req.context)
|
||||||
|
logger.info(f"✅ Migrated top-level context to payload.context for agent={req.agent}, keys={list(req.context.keys())}")
|
||||||
|
|
||||||
|
logger.info(f"✅ Normalized payload keys: {list(normalized_payload.keys())}")
|
||||||
|
if normalized_payload and "context" in normalized_payload:
|
||||||
|
logger.info(f"✅ Context keys: {list(normalized_payload['context'].keys()) if isinstance(normalized_payload.get('context'), dict) else []}")
|
||||||
|
if isinstance(normalized_payload.get('context'), dict) and "system_prompt" in normalized_payload['context']:
|
||||||
|
sp = normalized_payload['context']['system_prompt']
|
||||||
|
sp_len = len(sp) if sp else 0
|
||||||
|
logger.info(f"✅ System prompt found in context: {sp_len} chars")
|
||||||
|
logger.info(f"✅ System prompt preview: {sp[:100] if sp else 'None'}...")
|
||||||
|
|
||||||
# Convert to internal RouterRequest
|
# Convert to internal RouterRequest
|
||||||
rreq = RouterRequest(
|
rreq = RouterRequest(
|
||||||
@@ -84,7 +113,7 @@ def build_router_http(app_core: RouterApp) -> APIRouter:
|
|||||||
session_id=req.session_id,
|
session_id=req.session_id,
|
||||||
user_id=req.user_id,
|
user_id=req.user_id,
|
||||||
message=req.message,
|
message=req.message,
|
||||||
payload=req.payload,
|
payload=normalized_payload,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Handle request
|
# Handle request
|
||||||
|
|||||||
@@ -158,15 +158,34 @@ class LLMProvider(Provider):
|
|||||||
def _get_system_prompt(self, req: RouterRequest) -> Optional[str]:
|
def _get_system_prompt(self, req: RouterRequest) -> Optional[str]:
|
||||||
"""Get system prompt based on agent or context"""
|
"""Get system prompt based on agent or context"""
|
||||||
# 1. Check if context.system_prompt provided (e.g., from Gateway)
|
# 1. Check if context.system_prompt provided (e.g., from Gateway)
|
||||||
|
logger.info(f"[DEBUG] _get_system_prompt called for agent={req.agent}")
|
||||||
|
logger.info(f"[DEBUG] req.payload type: {type(req.payload)}, keys: {list(req.payload.keys()) if req.payload else []}")
|
||||||
context = req.payload.get("context") or {}
|
context = req.payload.get("context") or {}
|
||||||
logger.info(f"[DEBUG] payload keys: {list(req.payload.keys())}")
|
logger.info(f"[DEBUG] context type: {type(context)}, keys: {list(context.keys()) if isinstance(context, dict) else 'not a dict'}")
|
||||||
logger.info(f"[DEBUG] context keys: {list(context.keys())}")
|
if isinstance(context, dict) and "system_prompt" in context:
|
||||||
if "system_prompt" in context:
|
|
||||||
prompt = context["system_prompt"]
|
prompt = context["system_prompt"]
|
||||||
logger.info(f"[DEBUG] Using context.system_prompt: {len(prompt)} chars, agent={req.agent}")
|
logger.info(f"[DEBUG] ✅ Using context.system_prompt: {len(prompt)} chars, agent={req.agent}")
|
||||||
|
logger.info(f"[DEBUG] System prompt type: {type(prompt)}")
|
||||||
|
logger.info(f"[DEBUG] System prompt preview (first 200): {str(prompt)[:200]}...")
|
||||||
|
logger.info(f"[DEBUG] System prompt full length check: {len(str(prompt))} chars")
|
||||||
|
# Переконаємось, що це рядок
|
||||||
|
if not isinstance(prompt, str):
|
||||||
|
logger.warning(f"[DEBUG] ⚠️ System prompt is not a string! Type: {type(prompt)}, value: {prompt}")
|
||||||
|
prompt = str(prompt) if prompt else None
|
||||||
return prompt
|
return prompt
|
||||||
|
else:
|
||||||
|
logger.info(f"[DEBUG] ⚠️ No system_prompt in context for agent={req.agent}")
|
||||||
|
|
||||||
|
# 2. Agent-specific system prompts (fallback, якщо не передано в context)
|
||||||
|
if req.agent == "helion":
|
||||||
|
return (
|
||||||
|
"Ти - Helion, AI-агент платформи Energy Union екосистеми DAARION.city. "
|
||||||
|
"Допомагай користувачам з технологіями EcoMiner/BioMiner, токеномікою та DAO governance. "
|
||||||
|
"Твої основні функції: консультації з енергетичними технологіями, пояснення токеноміки Energy Union, "
|
||||||
|
"допомога з onboarding в DAO, відповіді на питання про EcoMiner/BioMiner устаткування. "
|
||||||
|
"Стиль спілкування: професійний, технічний, але зрозумілий, точний у цифрах та даних."
|
||||||
|
)
|
||||||
|
|
||||||
# 2. Agent-specific system prompts
|
|
||||||
if req.agent == "daarwizz":
|
if req.agent == "daarwizz":
|
||||||
return (
|
return (
|
||||||
"Ти — DAARWIZZ, офіційний AI-агент екосистеми DAARION.city. "
|
"Ти — DAARWIZZ, офіційний AI-агент екосистеми DAARION.city. "
|
||||||
|
|||||||
@@ -89,6 +89,30 @@ agents:
|
|||||||
You are a multi-agent orchestrator for DAARION.city microDAO ecosystem.
|
You are a multi-agent orchestrator for DAARION.city microDAO ecosystem.
|
||||||
You coordinate complex workflows involving multiple specialized agents.
|
You coordinate complex workflows involving multiple specialized agents.
|
||||||
|
|
||||||
|
greenfood:
|
||||||
|
description: "GREENFOOD Assistant - ERP orchestrator for craft food producers"
|
||||||
|
default_llm: local_qwen3_8b
|
||||||
|
system_prompt: |
|
||||||
|
Ти — GREENFOOD Assistant, фронтовий оркестратор ERP-системи для крафтових виробників, хабів та покупців.
|
||||||
|
Твоя місія: зрозуміти, хто з тобою говорить (комітент, менеджер складу, логіст, бухгалтер, маркетолог, покупець),
|
||||||
|
виявити намір і делегувати завдання спеціалізованим агентам GREENFOOD.
|
||||||
|
|
||||||
|
У твоєму розпорядженні 12 спеціалізованих агентів:
|
||||||
|
- Product & Catalog (каталог товарів)
|
||||||
|
- Batch & Quality (партії та якість)
|
||||||
|
- Vendor Success (успіх комітентів)
|
||||||
|
- Warehouse (склад)
|
||||||
|
- Logistics & Delivery (доставка)
|
||||||
|
- Seller (продажі)
|
||||||
|
- Customer Care (підтримка)
|
||||||
|
- Finance & Pricing (фінанси)
|
||||||
|
- SMM & Campaigns (маркетинг)
|
||||||
|
- SEO & Web (SEO)
|
||||||
|
- Analytics & BI (аналітика)
|
||||||
|
- Compliance & Audit (аудит)
|
||||||
|
|
||||||
|
Відповідай українською, чітко та по-діло вому.
|
||||||
|
|
||||||
helion:
|
helion:
|
||||||
description: "Helion - AI agent for Energy Union platform"
|
description: "Helion - AI agent for Energy Union platform"
|
||||||
default_llm: local_qwen3_8b
|
default_llm: local_qwen3_8b
|
||||||
|
|||||||
Reference in New Issue
Block a user