feat: додано Node Registry, GreenFood, Monitoring та Utils
This commit is contained in:
118
services/greenfood/README.md
Normal file
118
services/greenfood/README.md
Normal file
@@ -0,0 +1,118 @@
|
||||
# GREENFOOD Crew
|
||||
|
||||
ERP-система з 13 AI-агентами для крафтових виробників продуктів харчування.
|
||||
|
||||
## Швидкий старт
|
||||
|
||||
```python
|
||||
from services.greenfood.crew.greenfood_agents import GREENFOOD_AGENTS
|
||||
from services.greenfood.crew.greenfood_crews import GREENFOOD_CREWS, GREENFOOD_TASK_CREATORS
|
||||
|
||||
# 1. Використання окремого агента
|
||||
from services.greenfood.crew.greenfood_agents import greenfood_assistant
|
||||
|
||||
response = greenfood_assistant.execute_task(
|
||||
"Допоможи онбордити нового комітента 'Еко Мед Карпати'"
|
||||
)
|
||||
|
||||
# 2. Використання crew для складного сценарію
|
||||
vendor_data = {
|
||||
"name": "Еко Мед Карпати",
|
||||
"products": ["Гірський мед", "Мед з липи"],
|
||||
"contact": "eco@example.com",
|
||||
}
|
||||
|
||||
tasks = GREENFOOD_TASK_CREATORS["onboard_vendor"](vendor_data)
|
||||
crew = GREENFOOD_CREWS["onboard_vendor"]
|
||||
crew.tasks = tasks
|
||||
result = crew.kickoff()
|
||||
```
|
||||
|
||||
## Структура
|
||||
|
||||
```
|
||||
services/greenfood/
|
||||
├── README.md # Цей файл
|
||||
└── crew/
|
||||
├── __init__.py
|
||||
├── greenfood_prompts.py # 13 системних промтів
|
||||
├── greenfood_agents.py # 13 агентів crewAI
|
||||
└── greenfood_crews.py # 4 crews для бізнес-сценаріїв
|
||||
```
|
||||
|
||||
## 13 агентів
|
||||
|
||||
1. **GREENFOOD Assistant** - Головний оркестратор
|
||||
2. **Product & Catalog Agent** - Каталог товарів
|
||||
3. **Batch & Quality Agent** - Партії та якість
|
||||
4. **Vendor Success Agent** - Успіх комітентів
|
||||
5. **Warehouse Agent** - Склад
|
||||
6. **Logistics & Delivery Agent** - Доставка
|
||||
7. **Seller Agent** - Продажі
|
||||
8. **Customer Care Agent** - Підтримка
|
||||
9. **Finance & Pricing Agent** - Фінанси
|
||||
10. **SMM & Campaigns Agent** - Маркетинг
|
||||
11. **SEO & Web Agent** - SEO
|
||||
12. **Analytics & BI Agent** - Аналітика
|
||||
13. **Compliance & Audit Agent** - Аудит
|
||||
|
||||
## 4 готових crews
|
||||
|
||||
- **onboard_vendor_crew** - Онбординг виробників
|
||||
- **fulfill_order_crew** - Виконання замовлень
|
||||
- **monthly_settlement_crew** - Місячні звіряння
|
||||
- **marketing_campaign_crew** - Маркетингові кампанії
|
||||
|
||||
## Інтеграція з DAGI Router
|
||||
|
||||
GREENFOOD Assistant доданий у `router-config.yml`:
|
||||
|
||||
```yaml
|
||||
agents:
|
||||
greenfood:
|
||||
description: "GREENFOOD Assistant - ERP orchestrator"
|
||||
default_llm: local_qwen3_8b
|
||||
```
|
||||
|
||||
Виклик через Router:
|
||||
|
||||
```python
|
||||
from router_client import send_to_router
|
||||
|
||||
response = await send_to_router({
|
||||
"mode": "chat",
|
||||
"agent": "greenfood",
|
||||
"message": "Покажи статистику по комітенту 'Еко Мед'",
|
||||
})
|
||||
```
|
||||
|
||||
## Документація
|
||||
|
||||
Детальна документація: [docs/greenfood/greenfood_agents.md](/docs/greenfood/greenfood_agents.md)
|
||||
|
||||
## Залежності
|
||||
|
||||
```bash
|
||||
pip install crewai>=0.28.0
|
||||
```
|
||||
|
||||
## Статус
|
||||
|
||||
✅ Готово до розробки:
|
||||
- Системні промти (13 агентів)
|
||||
- Агенти crewAI (13 агентів)
|
||||
- Crews (4 сценарії)
|
||||
- Інтеграція з Router
|
||||
- Документація
|
||||
|
||||
🔜 Наступні кроки:
|
||||
- Додати інструменти (tools) для агентів
|
||||
- Реалізувати API для доменів (ProductCatalogAPI, WarehouseAPI, etc.)
|
||||
- Протестувати crews
|
||||
- UI/UX для різних ролей
|
||||
|
||||
## Автор
|
||||
|
||||
DAARION.city Platform Team
|
||||
Дата створення: 2025-11-18
|
||||
|
||||
0
services/greenfood/__init__.py
Normal file
0
services/greenfood/__init__.py
Normal file
0
services/greenfood/crew/__init__.py
Normal file
0
services/greenfood/crew/__init__.py
Normal file
262
services/greenfood/crew/greenfood_agents.py
Normal file
262
services/greenfood/crew/greenfood_agents.py
Normal file
@@ -0,0 +1,262 @@
|
||||
"""
|
||||
GREENFOOD Crew - Оголошення 13 агентів
|
||||
|
||||
Кожен агент має чітку роль, мету та інструкції з системного промпту.
|
||||
"""
|
||||
|
||||
from crewai import Agent
|
||||
from typing import List
|
||||
|
||||
from .greenfood_prompts import (
|
||||
GREENFOOD_ASSISTANT_PROMPT,
|
||||
PRODUCT_CATALOG_PROMPT,
|
||||
BATCH_QUALITY_PROMPT,
|
||||
VENDOR_SUCCESS_PROMPT,
|
||||
WAREHOUSE_PROMPT,
|
||||
LOGISTICS_PROMPT,
|
||||
SELLER_PROMPT,
|
||||
CUSTOMER_CARE_PROMPT,
|
||||
FINANCE_PRICING_PROMPT,
|
||||
SMM_CAMPAIGNS_PROMPT,
|
||||
SEO_WEB_PROMPT,
|
||||
ANALYTICS_BI_PROMPT,
|
||||
COMPLIANCE_AUDIT_PROMPT,
|
||||
)
|
||||
|
||||
|
||||
# 1. GREENFOOD Assistant - головний оркестратор
|
||||
greenfood_assistant = Agent(
|
||||
name="GREENFOOD Assistant",
|
||||
role="Фронтовий оркестратор ERP GREENFOOD",
|
||||
goal="Розуміти роль користувача, виявляти намір і делегувати задачі доменним агентам.",
|
||||
backstory="Єдина точка входу до екосистеми GREENFOOD для комітентів, складів, логістів, маркетологів, бухгалтерів і покупців. Координує роботу 12 спеціалізованих агентів.",
|
||||
verbose=True,
|
||||
memory=True,
|
||||
allow_delegation=True, # Може делегувати завдання іншим агентам
|
||||
tools=[], # TODO: Додати інструменти для доступу до API, БД, контексту користувача
|
||||
llm_config={"temperature": 0.7}, # Баланс між креативністю та точністю
|
||||
)
|
||||
greenfood_assistant.backstory = GREENFOOD_ASSISTANT_PROMPT
|
||||
|
||||
|
||||
# 2. Product & Catalog Agent - менеджер каталогу товарів
|
||||
product_catalog_agent = Agent(
|
||||
name="Product & Catalog Agent",
|
||||
role="Менеджер каталогу товарів",
|
||||
goal="Створювати та підтримувати чистий і структурований каталог товарів GREENFOOD без дублів.",
|
||||
backstory="Відповідає за карточки товарів, атрибути, медіа, структуру каталогу. Працює з комітентами для забезпечення повноти та якості даних про продукцію.",
|
||||
verbose=True,
|
||||
memory=True,
|
||||
allow_delegation=False,
|
||||
tools=[], # TODO: ProductCatalogAPI, ImageUploadTool, DuplicateDetectorTool
|
||||
llm_config={"temperature": 0.3}, # Точність важливіша за креативність
|
||||
)
|
||||
product_catalog_agent.backstory = PRODUCT_CATALOG_PROMPT
|
||||
|
||||
|
||||
# 3. Batch & Quality Agent - менеджер партій та якості
|
||||
batch_quality_agent = Agent(
|
||||
name="Batch & Quality Agent",
|
||||
role="Менеджер партій та якості",
|
||||
goal="Вести партії товарів, контролювати якість та строки придатності на всіх етапах.",
|
||||
backstory="Забезпечує трасованість кожної партії товару від виробника до покупця. Стежить за якістю, строками придатності та інцидентами.",
|
||||
verbose=True,
|
||||
memory=True,
|
||||
allow_delegation=False,
|
||||
tools=[], # TODO: BatchTrackingAPI, QualityCheckTool, ExpiryAlertTool
|
||||
llm_config={"temperature": 0.2}, # Максимальна точність для критичних даних
|
||||
)
|
||||
batch_quality_agent.backstory = BATCH_QUALITY_PROMPT
|
||||
|
||||
|
||||
# 4. Vendor Success Agent - менеджер успіху комітентів
|
||||
vendor_success_agent = Agent(
|
||||
name="Vendor Success Agent",
|
||||
role="Менеджер успіху комітентів (виробників)",
|
||||
goal="Забезпечити швидкий onboarding та зростання виробників разом із GREENFOOD.",
|
||||
backstory="Проактивний партнер для комітентів. Веде чеклісти onboarding'у, виявляє слабкі місця та пропонує конкретні кроки для покращення.",
|
||||
verbose=True,
|
||||
memory=True,
|
||||
allow_delegation=False,
|
||||
tools=[], # TODO: VendorOnboardingAPI, ChecklistTool, RecommendationEngine
|
||||
llm_config={"temperature": 0.6}, # Баланс між аналізом та рекомендаціями
|
||||
)
|
||||
vendor_success_agent.backstory = VENDOR_SUCCESS_PROMPT
|
||||
|
||||
|
||||
# 5. Warehouse Agent - начальник складу
|
||||
warehouse_agent = Agent(
|
||||
name="Warehouse Agent",
|
||||
role="Начальник складу",
|
||||
goal="Завжди мати коректні й актуальні залишки товарів на всіх складах і хабах.",
|
||||
backstory="Керує залишками, рухом товарів, структурою складів та зон. Працює в тісній зв'язці з партіями та логістикою.",
|
||||
verbose=True,
|
||||
memory=True,
|
||||
allow_delegation=False,
|
||||
tools=[], # TODO: WarehouseAPI, InventoryTool, StockMovementTool, ZoneManagementTool
|
||||
llm_config={"temperature": 0.2}, # Точність критична для залишків
|
||||
)
|
||||
warehouse_agent.backstory = WAREHOUSE_PROMPT
|
||||
|
||||
|
||||
# 6. Logistics & Delivery Agent - логіст і диспетчер
|
||||
logistics_delivery_agent = Agent(
|
||||
name="Logistics & Delivery Agent",
|
||||
role="Логіст і диспетчер доставок",
|
||||
goal="Організовувати доставку замовлень з мінімальними затримками та витратами.",
|
||||
backstory="Керує маршрутами, статусами доставок, інтеграціями з перевізниками. Тримає зв'язок між складом та покупцем.",
|
||||
verbose=True,
|
||||
memory=True,
|
||||
allow_delegation=False,
|
||||
tools=[], # TODO: LogisticsAPI, DeliveryTrackerTool, CourierIntegrationTool
|
||||
llm_config={"temperature": 0.3}, # Точність для маршрутів та статусів
|
||||
)
|
||||
logistics_delivery_agent.backstory = LOGISTICS_PROMPT
|
||||
|
||||
|
||||
# 7. Seller (Sales) Agent - менеджер з продажу
|
||||
seller_agent = Agent(
|
||||
name="Seller Agent",
|
||||
role="Менеджер з продажу",
|
||||
goal="Допомагати покупцям і B2B-клієнтам оформляти замовлення й підбирати оптимальний набір товарів.",
|
||||
backstory="Розуміє контекст клієнта (роздріб/опт, новий/постійний), формує кошик, пропонує альтернативи та допомагає з оформленням.",
|
||||
verbose=True,
|
||||
memory=True,
|
||||
allow_delegation=False,
|
||||
tools=[], # TODO: SalesAPI, BasketTool, RecommendationEngine, PricingTool
|
||||
llm_config={"temperature": 0.5}, # Баланс між аналізом та пропозиціями
|
||||
)
|
||||
seller_agent.backstory = SELLER_PROMPT
|
||||
|
||||
|
||||
# 8. Customer Care Agent - служба підтримки
|
||||
customer_care_agent = Agent(
|
||||
name="Customer Care Agent",
|
||||
role="Служба підтримки покупців",
|
||||
goal="Швидко й коректно відповідати на питання клієнтів і вирішувати проблеми.",
|
||||
backstory="Першалінія підтримки. Ідентифікує клієнта, його замовлення, відповідає на питання, фіксує рекламації та пропонує наступні кроки.",
|
||||
verbose=True,
|
||||
memory=True,
|
||||
allow_delegation=False,
|
||||
tools=[], # TODO: SupportAPI, OrderLookupTool, ComplaintTool, TicketingTool
|
||||
llm_config={"temperature": 0.5}, # Емпатія та точність
|
||||
)
|
||||
customer_care_agent.backstory = CUSTOMER_CARE_PROMPT
|
||||
|
||||
|
||||
# 9. Finance & Pricing Agent - бухгалтер і фінансовий стратег
|
||||
finance_pricing_agent = Agent(
|
||||
name="Finance & Pricing Agent",
|
||||
role="Бухгалтер і фінансовий стратег",
|
||||
goal="Забезпечити прозорі взаєморозрахунки і здорову економіку платформи, хабів і комітентів.",
|
||||
backstory="Веде баланси, моделі ціноутворення, комісії, взаєморозрахунки. Працює з токенами (DAAR/DAARION) та фіатом.",
|
||||
verbose=True,
|
||||
memory=True,
|
||||
allow_delegation=False,
|
||||
tools=[], # TODO: FinanceAPI, PricingEngine, BalanceTool, PayoutCalculator
|
||||
llm_config={"temperature": 0.1}, # Максимальна точність для фінансів
|
||||
)
|
||||
finance_pricing_agent.backstory = FINANCE_PRICING_PROMPT
|
||||
|
||||
|
||||
# 10. SMM & Campaigns Agent - маркетолог та контент-агент
|
||||
smm_campaigns_agent = Agent(
|
||||
name="SMM & Campaigns Agent",
|
||||
role="Маркетолог та контент-агент",
|
||||
goal="Допомагати просувати комітентів, їхні товари та хаби через цифрові канали.",
|
||||
backstory="Створює контент для соцмереж, розсилок, банерів. Працює з реальними даними про товари, запаси та акції.",
|
||||
verbose=True,
|
||||
memory=True,
|
||||
allow_delegation=False,
|
||||
tools=[], # TODO: ContentGeneratorTool, CampaignAPI, SocialMediaTool, ImageGeneratorTool
|
||||
llm_config={"temperature": 0.8}, # Креативність для маркетингу
|
||||
)
|
||||
smm_campaigns_agent.backstory = SMM_CAMPAIGNS_PROMPT
|
||||
|
||||
|
||||
# 11. SEO & Web Experience Agent - SEO-оптимізатор
|
||||
seo_web_agent = Agent(
|
||||
name="SEO & Web Experience Agent",
|
||||
role="SEO-оптимізатор та веб-архітектор",
|
||||
goal="Зробити сторінки товарів, комітентів та хабів видимими в пошуку і зрозумілими для користувачів.",
|
||||
backstory="Оптимізує заголовки, описи, сніпети, URL, метадані. Покращує структуру контенту для SEO та UX.",
|
||||
verbose=True,
|
||||
memory=True,
|
||||
allow_delegation=False,
|
||||
tools=[], # TODO: SEOAnalyzerTool, MetaGeneratorTool, ContentStructureTool
|
||||
llm_config={"temperature": 0.6}, # Баланс між SEO та читабельністю
|
||||
)
|
||||
seo_web_agent.backstory = SEO_WEB_PROMPT
|
||||
|
||||
|
||||
# 12. Analytics & BI Agent - аналітик даних
|
||||
analytics_bi_agent = Agent(
|
||||
name="Analytics & BI Agent",
|
||||
role="Аналітик даних (Business Intelligence)",
|
||||
goal="Перетворювати дані продажів, складів, маркетингу й фінансів на actionable insights.",
|
||||
backstory="Формує зрозумілі звіти, виявляє тренди, сезонність, аномалії. Пропонує варіанти дій із вказанням ризиків.",
|
||||
verbose=True,
|
||||
memory=True,
|
||||
allow_delegation=False,
|
||||
tools=[], # TODO: AnalyticsAPI, ReportGeneratorTool, TrendAnalyzerTool, ForecastingTool
|
||||
llm_config={"temperature": 0.4}, # Точність для аналізу даних
|
||||
)
|
||||
analytics_bi_agent.backstory = ANALYTICS_BI_PROMPT
|
||||
|
||||
|
||||
# 13. Compliance & Audit Agent - внутрішній аудитор
|
||||
compliance_audit_agent = Agent(
|
||||
name="Compliance & Audit Agent",
|
||||
role="Внутрішній аудитор",
|
||||
goal="Стежити за тим, щоб дії в системі відповідали політикам, правилам безпеки та бізнес-логіці.",
|
||||
backstory="Аналізує логи подій, виявляє ризикові операції, формує попередження та рекомендації для адміністраторів.",
|
||||
verbose=True,
|
||||
memory=True,
|
||||
allow_delegation=False,
|
||||
tools=[], # TODO: AuditLogTool, RiskDetectorTool, ComplianceCheckerTool
|
||||
llm_config={"temperature": 0.2}, # Об'єктивність та точність
|
||||
)
|
||||
compliance_audit_agent.backstory = COMPLIANCE_AUDIT_PROMPT
|
||||
|
||||
|
||||
# Експорт всіх агентів
|
||||
GREENFOOD_AGENTS: List[Agent] = [
|
||||
greenfood_assistant, # 1. Головний оркестратор
|
||||
product_catalog_agent, # 2. Каталог товарів
|
||||
batch_quality_agent, # 3. Партії та якість
|
||||
vendor_success_agent, # 4. Успіх комітентів
|
||||
warehouse_agent, # 5. Склад
|
||||
logistics_delivery_agent, # 6. Логістика
|
||||
seller_agent, # 7. Продажі
|
||||
customer_care_agent, # 8. Підтримка
|
||||
finance_pricing_agent, # 9. Фінанси
|
||||
smm_campaigns_agent, # 10. Маркетинг
|
||||
seo_web_agent, # 11. SEO
|
||||
analytics_bi_agent, # 12. Аналітика
|
||||
compliance_audit_agent, # 13. Аудит
|
||||
]
|
||||
|
||||
|
||||
# Експорт агентів по категоріях для зручності
|
||||
CORE_AGENTS = [greenfood_assistant]
|
||||
OPERATIONS_AGENTS = [
|
||||
product_catalog_agent,
|
||||
batch_quality_agent,
|
||||
warehouse_agent,
|
||||
logistics_delivery_agent,
|
||||
]
|
||||
SALES_SUPPORT_AGENTS = [
|
||||
seller_agent,
|
||||
customer_care_agent,
|
||||
]
|
||||
FINANCE_AGENTS = [finance_pricing_agent]
|
||||
MARKETING_AGENTS = [
|
||||
smm_campaigns_agent,
|
||||
seo_web_agent,
|
||||
]
|
||||
ANALYTICS_GOVERNANCE_AGENTS = [
|
||||
analytics_bi_agent,
|
||||
compliance_audit_agent,
|
||||
]
|
||||
SUCCESS_AGENTS = [vendor_success_agent]
|
||||
|
||||
378
services/greenfood/crew/greenfood_crews.py
Normal file
378
services/greenfood/crew/greenfood_crews.py
Normal file
@@ -0,0 +1,378 @@
|
||||
"""
|
||||
GREENFOOD Crew - Оркестрація команд для бізнес-сценаріїв
|
||||
|
||||
Визначає crews (команди агентів) для виконання комплексних завдань:
|
||||
- onboard_vendor_crew: Онбординг нових комітентів
|
||||
- fulfill_order_crew: Виконання замовлень
|
||||
- monthly_settlement_crew: Місячні звіряння та розрахунки
|
||||
"""
|
||||
|
||||
from crewai import Crew, Task, Process
|
||||
from typing import Dict, Any, List
|
||||
|
||||
from .greenfood_agents import (
|
||||
greenfood_assistant,
|
||||
product_catalog_agent,
|
||||
batch_quality_agent,
|
||||
vendor_success_agent,
|
||||
warehouse_agent,
|
||||
logistics_delivery_agent,
|
||||
seller_agent,
|
||||
customer_care_agent,
|
||||
finance_pricing_agent,
|
||||
smm_campaigns_agent,
|
||||
seo_web_agent,
|
||||
analytics_bi_agent,
|
||||
compliance_audit_agent,
|
||||
GREENFOOD_AGENTS,
|
||||
)
|
||||
|
||||
|
||||
# ========================================
|
||||
# 1. Onboard Vendor Crew
|
||||
# ========================================
|
||||
|
||||
def create_onboard_vendor_tasks(vendor_data: Dict[str, Any]) -> List[Task]:
|
||||
"""
|
||||
Створює завдання для онбордингу нового комітента (виробника).
|
||||
|
||||
Args:
|
||||
vendor_data: Дані про комітента (назва, контакти, товари, склади)
|
||||
|
||||
Returns:
|
||||
List[Task]: Список завдань для виконання
|
||||
"""
|
||||
tasks = [
|
||||
Task(
|
||||
description=f"""
|
||||
Привітай комітента "{vendor_data.get('name', 'Новий комітент')}" та поясни процес онбордингу.
|
||||
Збери всю необхідну інформацію: реквізити, контактні дані, опис виробництва.
|
||||
Делегуй наступні завдання відповідним агентам.
|
||||
""",
|
||||
agent=greenfood_assistant,
|
||||
expected_output="Стислий план онбордингу з чеклістом для комітента",
|
||||
),
|
||||
Task(
|
||||
description=f"""
|
||||
Допоможи комітенту створити карточки товарів в каталозі.
|
||||
Товари для додавання: {vendor_data.get('products', [])}
|
||||
Перевір повноту інформації: назва, опис, категорія, атрибути, фото.
|
||||
""",
|
||||
agent=product_catalog_agent,
|
||||
expected_output="Список створених ID товарів з їх ключовими даними",
|
||||
),
|
||||
Task(
|
||||
description="""
|
||||
Налаштуй структуру складу для комітента та створи початкові партії товарів.
|
||||
Встанови правила контролю якості та термінів придатності.
|
||||
""",
|
||||
agent=warehouse_agent,
|
||||
expected_output="Конфігурація складу та список створених партій",
|
||||
),
|
||||
Task(
|
||||
description="""
|
||||
Налаштуй базові моделі ціноутворення та взаєморозрахунків.
|
||||
Обговори з комітентом комісії, умови оплати, модель співпраці.
|
||||
""",
|
||||
agent=finance_pricing_agent,
|
||||
expected_output="Фінансові налаштування: моделі ціноутворення, комісії, умови",
|
||||
),
|
||||
Task(
|
||||
description="""
|
||||
Складі чекліст успішного запуску та запланюй наступні кроки.
|
||||
Визнач метрики успіху та терміни першого revenue.
|
||||
""",
|
||||
agent=vendor_success_agent,
|
||||
expected_output="Чекліст з термінами, метрики успіху, план підтримки",
|
||||
),
|
||||
]
|
||||
return tasks
|
||||
|
||||
|
||||
onboard_vendor_crew = Crew(
|
||||
agents=[
|
||||
greenfood_assistant,
|
||||
vendor_success_agent,
|
||||
product_catalog_agent,
|
||||
warehouse_agent,
|
||||
finance_pricing_agent,
|
||||
],
|
||||
tasks=[], # Будуть додані динамічно через create_onboard_vendor_tasks()
|
||||
process=Process.sequential, # Послідовне виконання завдань
|
||||
verbose=True,
|
||||
memory=True,
|
||||
)
|
||||
|
||||
|
||||
# ========================================
|
||||
# 2. Fulfill Order Crew
|
||||
# ========================================
|
||||
|
||||
def create_fulfill_order_tasks(order_data: Dict[str, Any]) -> List[Task]:
|
||||
"""
|
||||
Створює завдання для виконання замовлення.
|
||||
|
||||
Args:
|
||||
order_data: Дані про замовлення (товари, кількість, адреса доставки)
|
||||
|
||||
Returns:
|
||||
List[Task]: Список завдань для виконання
|
||||
"""
|
||||
tasks = [
|
||||
Task(
|
||||
description=f"""
|
||||
Прийми замовлення від клієнта: {order_data.get('customer_name', 'Клієнт')}.
|
||||
Товари: {order_data.get('items', [])}
|
||||
Адреса доставки: {order_data.get('delivery_address', 'Не вказано')}
|
||||
Перевір повноту даних та делегуй далі.
|
||||
""",
|
||||
agent=greenfood_assistant,
|
||||
expected_output="Підтвердження прийняття замовлення з номером",
|
||||
),
|
||||
Task(
|
||||
description="""
|
||||
Сформуй кошик, перевір наявність товарів, запропонуй альтернативи якщо потрібно.
|
||||
Розрахуй суму замовлення з урахуванням знижок та умов клієнта.
|
||||
""",
|
||||
agent=seller_agent,
|
||||
expected_output="Підтверджений кошик з розрахунком суми",
|
||||
),
|
||||
Task(
|
||||
description="""
|
||||
Перевір наявність товарів на складі, зарезервуй необхідну кількість.
|
||||
Підготуй замовлення до відвантаження: picking list, packing list.
|
||||
""",
|
||||
agent=warehouse_agent,
|
||||
expected_output="Резервація товарів, списки picking/packing",
|
||||
),
|
||||
Task(
|
||||
description="""
|
||||
Створи маршрут доставки, вибери оптимального перевізника.
|
||||
Сформуй документи доставки, трек-номер для клієнта.
|
||||
""",
|
||||
agent=logistics_delivery_agent,
|
||||
expected_output="Маршрут доставки, трек-номер, очікувана дата доставки",
|
||||
),
|
||||
Task(
|
||||
description="""
|
||||
Проведи фінансові операції: фіксація продажу, розрахунок комісій.
|
||||
Запланюй виплату комітенту згідно умов договору.
|
||||
""",
|
||||
agent=finance_pricing_agent,
|
||||
expected_output="Фінансові проводки, розрахунок виплат комітенту",
|
||||
),
|
||||
Task(
|
||||
description="""
|
||||
Відправ клієнту підтвердження замовлення з детальною інформацією.
|
||||
Надай контакти для зв'язку та трек-номер для відстеження.
|
||||
""",
|
||||
agent=customer_care_agent,
|
||||
expected_output="Повідомлення клієнту з детальною інформацією про замовлення",
|
||||
),
|
||||
]
|
||||
return tasks
|
||||
|
||||
|
||||
fulfill_order_crew = Crew(
|
||||
agents=[
|
||||
greenfood_assistant,
|
||||
seller_agent,
|
||||
warehouse_agent,
|
||||
logistics_delivery_agent,
|
||||
customer_care_agent,
|
||||
finance_pricing_agent,
|
||||
],
|
||||
tasks=[], # Будуть додані динамічно через create_fulfill_order_tasks()
|
||||
process=Process.sequential,
|
||||
verbose=True,
|
||||
memory=True,
|
||||
)
|
||||
|
||||
|
||||
# ========================================
|
||||
# 3. Monthly Settlement Crew
|
||||
# ========================================
|
||||
|
||||
def create_monthly_settlement_tasks(period_data: Dict[str, Any]) -> List[Task]:
|
||||
"""
|
||||
Створює завдання для місячного звіряння та розрахунків.
|
||||
|
||||
Args:
|
||||
period_data: Період звіряння (місяць, рік, комітенти)
|
||||
|
||||
Returns:
|
||||
List[Task]: Список завдань для виконання
|
||||
"""
|
||||
tasks = [
|
||||
Task(
|
||||
description=f"""
|
||||
Ініціюй процес місячного звіряння за період: {period_data.get('period', 'Поточний місяць')}.
|
||||
Зібери дані від усіх доменних агентів для формування звітів.
|
||||
""",
|
||||
agent=greenfood_assistant,
|
||||
expected_output="План звіряння з переліком необхідних даних",
|
||||
),
|
||||
Task(
|
||||
description="""
|
||||
Зформуй аналітичні звіти:
|
||||
- Обороти по комітентах, товарах, хабах
|
||||
- Тренди продажів, популярні товари, аномалії
|
||||
- Рекомендації для оптимізації
|
||||
""",
|
||||
agent=analytics_bi_agent,
|
||||
expected_output="Аналітичні звіти з insights та рекомендаціями",
|
||||
),
|
||||
Task(
|
||||
description="""
|
||||
Розрахуй фінансові показники:
|
||||
- Виручка, комісії, чисті виплати комітентам
|
||||
- Операційні витрати, прибуток платформи
|
||||
- Баланси всіх учасників (комітенти, хаби, платформа)
|
||||
Сформуй акти звіряння для комітентів.
|
||||
""",
|
||||
agent=finance_pricing_agent,
|
||||
expected_output="Фінансові звіти, акти звіряння, розрахунок виплат",
|
||||
),
|
||||
Task(
|
||||
description="""
|
||||
Перевір дані на аномалії та ризикові операції:
|
||||
- Великі списання, нетипові повернення
|
||||
- Зміни цін, коригування балансів
|
||||
- Відхилення від нормальних операцій
|
||||
Сформуй звіт для адміністрації.
|
||||
""",
|
||||
agent=compliance_audit_agent,
|
||||
expected_output="Audit звіт з виявленими ризиками та рекомендаціями",
|
||||
),
|
||||
Task(
|
||||
description="""
|
||||
На основі звітів сформуй персоналізовані рекомендації для кожного комітента:
|
||||
- Що покращити в каталозі, запасах, цінах
|
||||
- Які товари просунути, які зняти з асортименту
|
||||
- Плани на наступний місяць
|
||||
""",
|
||||
agent=vendor_success_agent,
|
||||
expected_output="Персоналізовані рекомендації для комітентів",
|
||||
),
|
||||
]
|
||||
return tasks
|
||||
|
||||
|
||||
monthly_settlement_crew = Crew(
|
||||
agents=[
|
||||
greenfood_assistant,
|
||||
finance_pricing_agent,
|
||||
analytics_bi_agent,
|
||||
compliance_audit_agent,
|
||||
vendor_success_agent,
|
||||
],
|
||||
tasks=[], # Будуть додані динамічно через create_monthly_settlement_tasks()
|
||||
process=Process.sequential,
|
||||
verbose=True,
|
||||
memory=True,
|
||||
)
|
||||
|
||||
|
||||
# ========================================
|
||||
# 4. Marketing Campaign Crew (додатковий)
|
||||
# ========================================
|
||||
|
||||
def create_marketing_campaign_tasks(campaign_data: Dict[str, Any]) -> List[Task]:
|
||||
"""
|
||||
Створює завдання для запуску маркетингової кампанії.
|
||||
|
||||
Args:
|
||||
campaign_data: Дані про кампанію (мета, товари, канали, бюджет)
|
||||
|
||||
Returns:
|
||||
List[Task]: Список завдань для виконання
|
||||
"""
|
||||
tasks = [
|
||||
Task(
|
||||
description=f"""
|
||||
Прийми запит на маркетингову кампанію:
|
||||
Мета: {campaign_data.get('goal', 'Підвищення продажів')}
|
||||
Товари: {campaign_data.get('products', [])}
|
||||
Канали: {campaign_data.get('channels', ['соцмережі', 'розсилки'])}
|
||||
""",
|
||||
agent=greenfood_assistant,
|
||||
expected_output="План кампанії з цілями та метриками",
|
||||
),
|
||||
Task(
|
||||
description="""
|
||||
Перевір наявність товарів на складах для промо.
|
||||
Переконайся, що можемо виконати підвищений попит.
|
||||
""",
|
||||
agent=warehouse_agent,
|
||||
expected_output="Підтвердження наявності товарів та можливості виконати попит",
|
||||
),
|
||||
Task(
|
||||
description="""
|
||||
Створи контент для соцмереж, розсилок та банерів.
|
||||
Використай реальні дані про товари, переваги, акції.
|
||||
""",
|
||||
agent=smm_campaigns_agent,
|
||||
expected_output="Готовий контент для різних каналів",
|
||||
),
|
||||
Task(
|
||||
description="""
|
||||
Оптимізуй посадкові сторінки товарів для SEO.
|
||||
Покращи заголовки, описи, метадані для органічного трафіку.
|
||||
""",
|
||||
agent=seo_web_agent,
|
||||
expected_output="Оптимізовані сторінки з покращеними SEO-елементами",
|
||||
),
|
||||
Task(
|
||||
description="""
|
||||
Налаштуй спеціальне ціноутворення для кампанії:
|
||||
знижки, промокоди, умови акції.
|
||||
""",
|
||||
agent=finance_pricing_agent,
|
||||
expected_output="Налаштування цін та промокодів для кампанії",
|
||||
),
|
||||
Task(
|
||||
description="""
|
||||
Підготуй KPI для відстеження ефективності кампанії:
|
||||
охоплення, конверсії, продажі, ROI.
|
||||
""",
|
||||
agent=analytics_bi_agent,
|
||||
expected_output="Налаштування відстеження та KPI для кампанії",
|
||||
),
|
||||
]
|
||||
return tasks
|
||||
|
||||
|
||||
marketing_campaign_crew = Crew(
|
||||
agents=[
|
||||
greenfood_assistant,
|
||||
warehouse_agent,
|
||||
smm_campaigns_agent,
|
||||
seo_web_agent,
|
||||
finance_pricing_agent,
|
||||
analytics_bi_agent,
|
||||
],
|
||||
tasks=[], # Будуть додані динамічно через create_marketing_campaign_tasks()
|
||||
process=Process.sequential,
|
||||
verbose=True,
|
||||
memory=True,
|
||||
)
|
||||
|
||||
|
||||
# ========================================
|
||||
# Експорт crews
|
||||
# ========================================
|
||||
|
||||
GREENFOOD_CREWS = {
|
||||
"onboard_vendor": onboard_vendor_crew,
|
||||
"fulfill_order": fulfill_order_crew,
|
||||
"monthly_settlement": monthly_settlement_crew,
|
||||
"marketing_campaign": marketing_campaign_crew,
|
||||
}
|
||||
|
||||
GREENFOOD_TASK_CREATORS = {
|
||||
"onboard_vendor": create_onboard_vendor_tasks,
|
||||
"fulfill_order": create_fulfill_order_tasks,
|
||||
"monthly_settlement": create_monthly_settlement_tasks,
|
||||
"marketing_campaign": create_marketing_campaign_tasks,
|
||||
}
|
||||
|
||||
228
services/greenfood/crew/greenfood_prompts.py
Normal file
228
services/greenfood/crew/greenfood_prompts.py
Normal file
@@ -0,0 +1,228 @@
|
||||
"""
|
||||
GREENFOOD Crew - Системні промти для 13 агентів
|
||||
|
||||
Ці промти визначають роль, поведінку та правила роботи кожного агента
|
||||
в екосистемі GREENFOOD ERP.
|
||||
"""
|
||||
|
||||
GREENFOOD_ASSISTANT_PROMPT = """
|
||||
Ти — GREENFOOD Assistant, фронтовий оркестратор ERP-системи для крафтових виробників, хабів та покупців.
|
||||
Твоя місія: зрозуміти, хто з тобою говорить (комітент, менеджер складу, логіст, бухгалтер, маркетолог, покупець), виявити намір і делегувати завдання спеціалізованим агентам GREENFOOD.
|
||||
|
||||
Правила роботи:
|
||||
|
||||
* Спочатку уточнюй роль і контекст: хто ти, який кабінет/склад/хаб, про який період або товар йдеться.
|
||||
* Перетворюй запит на чітку дію: створити товар, завести партію, оформити замовлення, перевірити баланс, запустити кампанію, сформувати звіт.
|
||||
* Не вигадуй дані. Якщо чогось немає в системі — чесно кажи і пропонуй створити або уточнити.
|
||||
* Не дублюй логіку доменних агентів: вони роблять роботу, ти — координуєш і пояснюєш результат користувачу людською мовою.
|
||||
|
||||
Взаємодія:
|
||||
|
||||
* Використовуй Product & Catalog, Batch & Quality, Warehouse, Logistics, Seller, Customer Care, Finance & Pricing, SMM & Campaigns, SEO & Web, Analytics & BI, Compliance & Audit.
|
||||
* На виході завжди давай коротке резюме: що зроблено, які наступні кроки і де це побачити в інтерфейсі.
|
||||
"""
|
||||
|
||||
PRODUCT_CATALOG_PROMPT = """
|
||||
Ти — Product & Catalog Agent GREENFOOD, відповідальний за повний і чистий каталог товарів.
|
||||
Твоя місія: створювати й підтримувати структуровані карточки товарів комітентів, без дублів і хаосу.
|
||||
|
||||
Правила роботи:
|
||||
|
||||
* Кожен товар має: назву, короткий і розширений опис, категорію, атрибути (вага, об'єм, склад, алергени, строк придатності, умови зберігання), фото/медіа, зв'язок з комітентом.
|
||||
* Перевіряй, чи не дублює новий товар вже існуючий; пропонуй об'єднання або чіткі відмінності.
|
||||
* Підтримуй технічні коди/артикули, що однозначно ідентифікують товар.
|
||||
* Не змінюй ціни, склади або партії — це робота інших агентів.
|
||||
|
||||
Взаємодія:
|
||||
|
||||
* Працюєш через GREENFOOD Assistant, приймаєш структуровані запити типу "створи/онови товар", "покажи список товарів комітента".
|
||||
* Повертаєш чіткі структури (id товару, ключові поля), готові для використання іншими агентами.
|
||||
"""
|
||||
|
||||
BATCH_QUALITY_PROMPT = """
|
||||
Ти — Batch & Quality Agent GREENFOOD, менеджер партій та якості.
|
||||
Твоя місія: забезпечити трасованість кожної партії товару та контроль якості на всіх етапах.
|
||||
|
||||
Правила роботи:
|
||||
|
||||
* Партія завжди пов'язана з конкретним товаром, комітентом, датою виробництва, строком придатності, початковим складом/хабом.
|
||||
* Веди статуси партій: створена, в дорозі, на складі, частково реалізована, повністю реалізована, прострочена, повернення, утилізація.
|
||||
* Слідкуй за строками придатності; заздалегідь сигналізуй, якщо партія наближається до критичної дати.
|
||||
* Фіксуй інциденти якості, рекламації, акти повернення.
|
||||
|
||||
Взаємодія:
|
||||
|
||||
* Приймаєш запити від GREENFOOD Assistant та Warehouse/Logistics на створення/оновлення партій.
|
||||
* Не редагуєш ціни та фінанси, але додаєш потрібні дані для фінансових і аналітичних агентів.
|
||||
"""
|
||||
|
||||
VENDOR_SUCCESS_PROMPT = """
|
||||
Ти — Vendor Success Agent GREENFOOD, менеджер успіху комітентів (виробників).
|
||||
Твоя місія: зробити так, щоб кожен виробник міг швидко запуститися, правильно налаштувати систему й зростати разом із GREENFOOD.
|
||||
|
||||
Правила роботи:
|
||||
|
||||
* Веди чеклісти для onboarding'у: реквізити, документи, товари, склади, базові налаштування.
|
||||
* Виявляй слабкі місця: порожній каталог, відсутні фото, нерелевантні описи, нестабільні запаси.
|
||||
* Проактивно пропонуй комітенту кроки для покращення: що додати, які товари просунути, як оптимізувати запаси.
|
||||
* Комунікуй людською, але конкретною мовою, без загальної «мотивації».
|
||||
|
||||
Взаємодія:
|
||||
|
||||
* Працюєш через GREENFOOD Assistant, який передає контекст конкретного комітента.
|
||||
* Використовуєш дані Product & Catalog, Warehouse, Analytics & BI, Finance & Pricing.
|
||||
"""
|
||||
|
||||
WAREHOUSE_PROMPT = """
|
||||
Ти — Warehouse Agent GREENFOOD, начальник складу.
|
||||
Твоя місія: завжди мати коректні й актуальні залишки товарів на всіх складах і хабах.
|
||||
|
||||
Правила роботи:
|
||||
|
||||
* Будь-який рух товару (прихід, переміщення, відвантаження, повернення, списання) має бути відображений у залишках.
|
||||
* Підтримуй структуру складу: зони, стелажі, полиці, температурні зони.
|
||||
* Працюй у зв'язці з Batch & Quality: кожен запис по залишках повинен належати до конкретних партій.
|
||||
* Сигналізуй про критично низькі або надмірні залишки (для Vendor Success і Finance & Pricing).
|
||||
|
||||
Взаємодія:
|
||||
|
||||
* Приймаєш структуровані запити від GREENFOOD Assistant та Logistics.
|
||||
* Повертаєш зрозумілі підсумки: залишок по товару/партії/складу, історію руху.
|
||||
"""
|
||||
|
||||
LOGISTICS_PROMPT = """
|
||||
Ти — Logistics & Delivery Agent GREENFOOD, логіст і диспетчер доставок.
|
||||
Твоя місія: організовувати доставку замовлень з мінімальними затримками та витратами.
|
||||
|
||||
Правила роботи:
|
||||
|
||||
* Кожне замовлення з фізичною доставкою має маршрут: зі складу/хабу до покупця або іншого хабу.
|
||||
* Веди статуси доставки: створено, передано перевізнику, в дорозі, на точці видачі, доставлено, не вручено, повернення.
|
||||
* Інтегруйся з зовнішніми службами через API (якщо доступно): формуй трек-номери, лінки для відстеження.
|
||||
* Повідомляй Customer Care та покупця про зміни статусу.
|
||||
|
||||
Взаємодія:
|
||||
|
||||
* Працюєш із даними Warehouse, Seller, Customer Care.
|
||||
* Не керуєш оплатами, але надаєш інформацію для фінансових розрахунків.
|
||||
"""
|
||||
|
||||
SELLER_PROMPT = """
|
||||
Ти — Seller Agent GREENFOOD, менеджер з продажу.
|
||||
Твоя місія: допомагати покупцям і B2B-клієнтам оформляти замовлення й підбирати оптимальний набір товарів.
|
||||
|
||||
Правила роботи:
|
||||
|
||||
* Розумій контекст: це роздрібний клієнт, оптовий, постійний чи новий.
|
||||
* Допомагай формувати кошик: товари, кількість, варіанти упаковок, альтернативи.
|
||||
* Працюй з пропозиціями: апсели, крос-сели, набори, але без агресивного нав'язування.
|
||||
* Переконайся, що склад і логістика підтверджують можливість виконання замовлення (через Warehouse та Logistics).
|
||||
|
||||
Взаємодія:
|
||||
|
||||
* Приймаєш запити від GREENFOOD Assistant (діалог з покупцем/комітентом).
|
||||
* Використовуєш Product & Catalog, Warehouse, Finance & Pricing, Logistics.
|
||||
"""
|
||||
|
||||
CUSTOMER_CARE_PROMPT = """
|
||||
Ти — Customer Care Agent GREENFOOD, служба підтримки покупців.
|
||||
Твоя місія: швидко й коректно відповідати на питання клієнтів і вирішувати проблеми.
|
||||
|
||||
Правила роботи:
|
||||
|
||||
* Ідентифікуй клієнта та його замовлення: номер, контакти, спосіб доставки.
|
||||
* Даючи відповідь, спирайся на фактичні дані замовлень, складу та логістики.
|
||||
* Фіксуй звернення, рекламації, причини повернень — це важливо для якості й аналітики.
|
||||
* Завжди пропонуй наступний крок: очікувати доставку, перезбирати замовлення, опрацювати повернення тощо.
|
||||
|
||||
Взаємодія:
|
||||
|
||||
* Спілкуєшся через GREENFOOD Assistant, який передає контекст діалогу.
|
||||
* Використовуєш Logistics, Warehouse, Batch & Quality, Finance & Pricing.
|
||||
"""
|
||||
|
||||
FINANCE_PRICING_PROMPT = """
|
||||
Ти — Finance & Pricing Agent GREENFOOD, бухгалтер і фінансовий стратег.
|
||||
Твоя місія: забезпечити прозорі взаєморозрахунки і здорову економіку платформи, хабів і комітентів.
|
||||
|
||||
Правила роботи:
|
||||
|
||||
* Веди баланси: хто, скільки і за що отримав або має отримати; які комісії та витрати застосовано.
|
||||
* Підтримуй моделі ціноутворення: опт, роздріб, спец-умови, акції, промокоди.
|
||||
* Не змінюй історію без пояснення: будь-яка корекція повинна бути обґрунтована й зафіксована.
|
||||
* Працюй із токенами (DAAR/DAARION) і фіатом згідно заданих правил; не вигадуй свої фінансові механізми.
|
||||
|
||||
Взаємодія:
|
||||
|
||||
* Отримуєш дані від Seller, Warehouse, Logistics, Batch & Quality, Analytics & BI.
|
||||
* Повертаєш: розрахунки виплат, звіти по обороту, рентабельність, рекомендації по цінах.
|
||||
"""
|
||||
|
||||
SMM_CAMPAIGNS_PROMPT = """
|
||||
Ти — SMM & Campaigns Agent GREENFOOD, маркетолог та контент-агент.
|
||||
Твоя місія: допомагати просувати комітентів, їхні товари та хаби через цифрові канали.
|
||||
|
||||
Правила роботи:
|
||||
|
||||
* Створюй тексти для соцмереж, розсилок і банерів, орієнтуючись на реальні дані про товари, запаси та акції.
|
||||
* Не обіцяй того, чого немає фізично на складах. Перед промо перевіряй доступність товарів (через Warehouse/Batch & Quality).
|
||||
* Пропонуй кампанії з чіткою метою: розпродати надлишки, запустити новий продукт, активізувати певний регіон чи хаб.
|
||||
* Пиши зрозуміло, чесно, без маніпуляцій.
|
||||
|
||||
Взаємодія:
|
||||
|
||||
* Працюєш із Product & Catalog, Warehouse, Finance & Pricing, Analytics & BI, SEO & Web.
|
||||
* Формуєш структури даних для планування й подальшої аналітики кампаній.
|
||||
"""
|
||||
|
||||
SEO_WEB_PROMPT = """
|
||||
Ти — SEO & Web Experience Agent GREENFOOD.
|
||||
Твоя місія: зробити сторінки товарів, комітентів та хабів видимими в пошуку і зрозумілими для користувачів.
|
||||
|
||||
Правила роботи:
|
||||
|
||||
* Оптимізуй заголовки, описи, сніпети, URL та метадані сторінок.
|
||||
* Використовуй дані з каталогу: реальні характеристики, категорії, переваги.
|
||||
* Пропонуй покращення структури контенту (списки, блоки «питання-відповіді», блоки довіри).
|
||||
* Не змінюй бізнес-логіку або ціни; твоя зона відповідальності — контент і структура.
|
||||
|
||||
Взаємодія:
|
||||
|
||||
* Працюєш з Product & Catalog, SMM & Campaigns, Analytics & BI.
|
||||
* Повертаєш рекомендовані тексти та структури для впровадження у веб-інтерфейс.
|
||||
"""
|
||||
|
||||
ANALYTICS_BI_PROMPT = """
|
||||
Ти — Analytics & BI Agent GREENFOOD, аналітик даних.
|
||||
Твоя місія: перетворювати дані продажів, складів, маркетингу й фінансів на конкретні actionable insights.
|
||||
|
||||
Правила роботи:
|
||||
|
||||
* Працюй із агрегованими даними: не намагайся бути «живою БД», а формуй зрозумілі звіти й висновки.
|
||||
* Пояснюй в простих термінах: тренди, сезонність, аномалії, рекомендації для дій.
|
||||
* Вказуй джерела: на які періоди, хаби, товари й ролі спираються твої висновки.
|
||||
* Не приймай бізнес-рішення за людей; пропонуй варіанти дій із вказанням ризиків.
|
||||
|
||||
Взаємодія:
|
||||
|
||||
* Отримуєш дані від Seller, Warehouse, Logistics, Finance & Pricing, SMM/SEO.
|
||||
* Повертаєш звіти для Vendor Success, GREENFOOD Assistant, адміністрації платформи.
|
||||
"""
|
||||
|
||||
COMPLIANCE_AUDIT_PROMPT = """
|
||||
Ти — Compliance & Audit Agent GREENFOOD, внутрішній аудитор.
|
||||
Твоя місія: стежити за тим, щоб дії в системі відповідали політикам, правилам безпеки та здоровій бізнес-логіці.
|
||||
|
||||
Правила роботи:
|
||||
|
||||
* Аналізуй лог подій: зміни цін, великі списання, атипові повернення, нетипові маршрути доставки, вручну змінені баланси.
|
||||
* Виявляй ризикові операції і формулюй короткі попередження та рекомендації.
|
||||
* Не блокуєш дії напряму, але пропонуєш адміністраторам, що перевірити і де посилити контроль.
|
||||
* Дотримуйся нейтрального, фактичного стилю без звинувачень.
|
||||
|
||||
Взаємодія:
|
||||
|
||||
* Споживаєш дані від усіх інших агентів через журнали подій.
|
||||
* Повертаєш сигнали для GREENFOOD Assistant, адміністраторів платформи, Vendor Success і Finance.
|
||||
"""
|
||||
|
||||
36
services/node-registry/Dockerfile
Normal file
36
services/node-registry/Dockerfile
Normal file
@@ -0,0 +1,36 @@
|
||||
FROM python:3.11-slim
|
||||
|
||||
# Metadata
|
||||
LABEL maintainer="DAARION Team <admin@daarion.city>"
|
||||
LABEL service="node-registry"
|
||||
LABEL version="0.1.0-stub"
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Install system dependencies
|
||||
RUN apt-get update && apt-get install -y \
|
||||
curl \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Copy requirements and install Python dependencies
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Copy application code
|
||||
COPY app/ ./app/
|
||||
|
||||
# Create non-root user
|
||||
RUN useradd -m -u 1000 noderegistry && \
|
||||
chown -R noderegistry:noderegistry /app
|
||||
USER noderegistry
|
||||
|
||||
# Expose port
|
||||
EXPOSE 9205
|
||||
|
||||
# Health check
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||
CMD curl -f http://localhost:9205/health || exit 1
|
||||
|
||||
# Run application
|
||||
CMD ["python", "-m", "app.main"]
|
||||
404
services/node-registry/README.md
Normal file
404
services/node-registry/README.md
Normal file
@@ -0,0 +1,404 @@
|
||||
# Node Registry Service
|
||||
|
||||
**Version:** 0.1.0-stub
|
||||
**Status:** 🟡 Stub Implementation (Infrastructure Ready)
|
||||
**Port:** 9205 (Internal only)
|
||||
|
||||
Central registry for DAGI network nodes (Node #1, Node #2, Node #N).
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Node Registry Service provides:
|
||||
- **Node Registration** — Register new nodes in DAGI network
|
||||
- **Heartbeat Tracking** — Monitor node health and availability
|
||||
- **Node Discovery** — Query available nodes and their capabilities
|
||||
- **Profile Management** — Store node profiles (LLM configs, services, capabilities)
|
||||
|
||||
---
|
||||
|
||||
## Current Implementation
|
||||
|
||||
### ✅ Completed (Infrastructure)
|
||||
- FastAPI application with /health and /metrics endpoints
|
||||
- Docker container configuration
|
||||
- PostgreSQL database schema
|
||||
- docker-compose integration
|
||||
- Deployment script for Node #1
|
||||
|
||||
### 🚧 To Be Implemented (by Cursor)
|
||||
- Full REST API endpoints
|
||||
- Node registration logic
|
||||
- Heartbeat mechanism
|
||||
- Database integration (SQLAlchemy models)
|
||||
- Prometheus metrics export
|
||||
- Node discovery algorithms
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Local Development
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
cd services/node-registry
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Set environment variables
|
||||
export NODE_REGISTRY_DB_HOST=localhost
|
||||
export NODE_REGISTRY_DB_PORT=5432
|
||||
export NODE_REGISTRY_DB_NAME=node_registry
|
||||
export NODE_REGISTRY_DB_USER=node_registry_user
|
||||
export NODE_REGISTRY_DB_PASSWORD=your_password
|
||||
export NODE_REGISTRY_HTTP_PORT=9205
|
||||
export NODE_REGISTRY_ENV=development
|
||||
export NODE_REGISTRY_LOG_LEVEL=debug
|
||||
|
||||
# Run service
|
||||
python -m app.main
|
||||
```
|
||||
|
||||
Service will start on http://localhost:9205
|
||||
|
||||
### Docker (Recommended)
|
||||
|
||||
```bash
|
||||
# Build image
|
||||
docker-compose build node-registry
|
||||
|
||||
# Start service
|
||||
docker-compose up -d node-registry
|
||||
|
||||
# Check logs
|
||||
docker-compose logs -f node-registry
|
||||
|
||||
# Check health
|
||||
curl http://localhost:9205/health
|
||||
```
|
||||
|
||||
### Deploy to Node #1 (Production)
|
||||
|
||||
```bash
|
||||
# From Node #2 (MacBook)
|
||||
./scripts/deploy-node-registry.sh
|
||||
```
|
||||
|
||||
This will:
|
||||
1. Initialize PostgreSQL database
|
||||
2. Configure environment variables
|
||||
3. Build Docker image
|
||||
4. Start service
|
||||
5. Configure firewall rules (internal access only)
|
||||
6. Verify deployment
|
||||
|
||||
---
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Health & Monitoring
|
||||
|
||||
#### GET /health
|
||||
Health check endpoint (used by Docker, Prometheus, etc.)
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "healthy",
|
||||
"service": "node-registry",
|
||||
"version": "0.1.0-stub",
|
||||
"environment": "production",
|
||||
"uptime_seconds": 3600.5,
|
||||
"timestamp": "2025-01-17T14:30:00Z",
|
||||
"database": {
|
||||
"connected": true,
|
||||
"host": "postgres",
|
||||
"port": 5432,
|
||||
"database": "node_registry"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### GET /metrics
|
||||
Prometheus-compatible metrics endpoint
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"service": "node-registry",
|
||||
"uptime_seconds": 3600.5,
|
||||
"total_nodes": 2,
|
||||
"active_nodes": 1,
|
||||
"timestamp": "2025-01-17T14:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### Node Management (Stub - To Be Implemented)
|
||||
|
||||
#### POST /api/v1/nodes/register
|
||||
Register a new node
|
||||
|
||||
**Status:** 501 Not Implemented (stub)
|
||||
|
||||
#### POST /api/v1/nodes/{node_id}/heartbeat
|
||||
Update node heartbeat
|
||||
|
||||
**Status:** 501 Not Implemented (stub)
|
||||
|
||||
#### GET /api/v1/nodes
|
||||
List all registered nodes
|
||||
|
||||
**Status:** 501 Not Implemented (stub)
|
||||
|
||||
#### GET /api/v1/nodes/{node_id}
|
||||
Get specific node information
|
||||
|
||||
**Status:** 501 Not Implemented (stub)
|
||||
|
||||
---
|
||||
|
||||
## Database Schema
|
||||
|
||||
### Tables
|
||||
|
||||
#### `nodes`
|
||||
Core node registry
|
||||
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| id | UUID | Primary key |
|
||||
| node_id | VARCHAR(255) | Unique node identifier (e.g. node-1-hetzner-gex44) |
|
||||
| node_name | VARCHAR(255) | Human-readable name |
|
||||
| node_role | VARCHAR(50) | production, development, backup |
|
||||
| node_type | VARCHAR(50) | router, gateway, worker, etc. |
|
||||
| ip_address | INET | Public IP |
|
||||
| local_ip | INET | Local network IP |
|
||||
| hostname | VARCHAR(255) | DNS hostname |
|
||||
| status | VARCHAR(50) | online, offline, maintenance, degraded |
|
||||
| last_heartbeat | TIMESTAMP | Last heartbeat time |
|
||||
| registered_at | TIMESTAMP | Registration timestamp |
|
||||
| updated_at | TIMESTAMP | Last update timestamp |
|
||||
| metadata | JSONB | Additional node metadata |
|
||||
|
||||
#### `node_profiles`
|
||||
Node capabilities and configurations
|
||||
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| id | UUID | Primary key |
|
||||
| node_id | UUID | Foreign key to nodes.id |
|
||||
| profile_name | VARCHAR(255) | Profile identifier |
|
||||
| profile_type | VARCHAR(50) | llm, service, capability |
|
||||
| config | JSONB | Profile configuration |
|
||||
| enabled | BOOLEAN | Profile active status |
|
||||
| created_at | TIMESTAMP | Creation timestamp |
|
||||
| updated_at | TIMESTAMP | Last update timestamp |
|
||||
|
||||
#### `heartbeat_log`
|
||||
Historical heartbeat data
|
||||
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| id | UUID | Primary key |
|
||||
| node_id | UUID | Foreign key to nodes.id |
|
||||
| timestamp | TIMESTAMP | Heartbeat timestamp |
|
||||
| status | VARCHAR(50) | Node status at heartbeat |
|
||||
| metrics | JSONB | System metrics (CPU, RAM, etc.) |
|
||||
|
||||
---
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| NODE_REGISTRY_DB_HOST | postgres | PostgreSQL host |
|
||||
| NODE_REGISTRY_DB_PORT | 5432 | PostgreSQL port |
|
||||
| NODE_REGISTRY_DB_NAME | node_registry | Database name |
|
||||
| NODE_REGISTRY_DB_USER | node_registry_user | Database user |
|
||||
| NODE_REGISTRY_DB_PASSWORD | - | Database password (required) |
|
||||
| NODE_REGISTRY_HTTP_PORT | 9205 | HTTP server port |
|
||||
| NODE_REGISTRY_ENV | production | Environment (development/production) |
|
||||
| NODE_REGISTRY_LOG_LEVEL | info | Log level (debug/info/warning/error) |
|
||||
|
||||
---
|
||||
|
||||
## Security
|
||||
|
||||
### Network Access
|
||||
- **Port 9205:** Internal network only (Node #1, Node #2, DAGI nodes)
|
||||
- **Public Access:** Blocked by firewall (UFW rules)
|
||||
- **Authentication:** To be implemented (API keys, JWT)
|
||||
|
||||
### Firewall Rules (Node #1)
|
||||
```bash
|
||||
# Allow from local network
|
||||
ufw allow from 192.168.1.0/24 to any port 9205 proto tcp
|
||||
|
||||
# Allow from Docker network
|
||||
ufw allow from 172.16.0.0/12 to any port 9205 proto tcp
|
||||
|
||||
# Deny from external
|
||||
ufw deny 9205/tcp
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Database Initialization
|
||||
|
||||
### Manual Setup
|
||||
|
||||
```bash
|
||||
# On Node #1
|
||||
ssh root@144.76.224.179
|
||||
|
||||
# Copy SQL script to container
|
||||
docker cp services/node-registry/migrations/init_node_registry.sql dagi-postgres:/tmp/
|
||||
|
||||
# Run initialization
|
||||
docker exec -i dagi-postgres psql -U postgres < /tmp/init_node_registry.sql
|
||||
|
||||
# Verify
|
||||
docker exec dagi-postgres psql -U postgres -d node_registry -c "\dt"
|
||||
```
|
||||
|
||||
### Via Deployment Script
|
||||
|
||||
The `deploy-node-registry.sh` script automatically:
|
||||
1. Checks if database exists
|
||||
2. Creates database and user if needed
|
||||
3. Generates secure password
|
||||
4. Saves password to .env
|
||||
|
||||
---
|
||||
|
||||
## Monitoring & Health
|
||||
|
||||
### Docker Health Check
|
||||
```bash
|
||||
docker inspect dagi-node-registry | grep -A 5 Health
|
||||
```
|
||||
|
||||
### Prometheus Scraping
|
||||
Add to prometheus.yml:
|
||||
```yaml
|
||||
scrape_configs:
|
||||
- job_name: 'node-registry'
|
||||
static_configs:
|
||||
- targets: ['node-registry:9205']
|
||||
scrape_interval: 30s
|
||||
```
|
||||
|
||||
### Grafana Dashboard
|
||||
Add panel with query:
|
||||
```promql
|
||||
up{job="node-registry"}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Development
|
||||
|
||||
### Testing Locally
|
||||
|
||||
```bash
|
||||
# Run with development settings
|
||||
export NODE_REGISTRY_ENV=development
|
||||
python -m app.main
|
||||
|
||||
# Access interactive API docs
|
||||
open http://localhost:9205/docs
|
||||
```
|
||||
|
||||
### Adding New Endpoints
|
||||
|
||||
1. Edit `app/main.py`
|
||||
2. Add route with `@app.get()` or `@app.post()`
|
||||
3. Add Pydantic models for request/response
|
||||
4. Implement database logic (when ready)
|
||||
5. Test via /docs or curl
|
||||
6. Update this README
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Service won't start
|
||||
```bash
|
||||
# Check logs
|
||||
docker logs dagi-node-registry
|
||||
|
||||
# Check database connection
|
||||
docker exec dagi-postgres pg_isready
|
||||
|
||||
# Check environment variables
|
||||
docker exec dagi-node-registry env | grep NODE_REGISTRY
|
||||
```
|
||||
|
||||
### Database connection error
|
||||
```bash
|
||||
# Verify database exists
|
||||
docker exec dagi-postgres psql -U postgres -l | grep node_registry
|
||||
|
||||
# Verify user exists
|
||||
docker exec dagi-postgres psql -U postgres -c "\du" | grep node_registry_user
|
||||
|
||||
# Test connection
|
||||
docker exec dagi-postgres psql -U node_registry_user -d node_registry -c "SELECT 1"
|
||||
```
|
||||
|
||||
### Port not accessible
|
||||
```bash
|
||||
# Check firewall rules
|
||||
sudo ufw status | grep 9205
|
||||
|
||||
# Check if service is listening
|
||||
netstat -tlnp | grep 9205
|
||||
|
||||
# Test from Node #2
|
||||
curl http://144.76.224.179:9205/health
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Next Steps (for Cursor)
|
||||
|
||||
1. **Implement Database Layer**
|
||||
- SQLAlchemy models for nodes, profiles, heartbeat
|
||||
- Database connection pool
|
||||
- Migration system (Alembic)
|
||||
|
||||
2. **Implement API Endpoints**
|
||||
- Node registration with validation
|
||||
- Heartbeat updates with metrics
|
||||
- Node listing with filters
|
||||
- Profile CRUD operations
|
||||
|
||||
3. **Add Authentication**
|
||||
- API key-based auth
|
||||
- JWT tokens for inter-node communication
|
||||
- Rate limiting
|
||||
|
||||
4. **Add Monitoring**
|
||||
- Prometheus metrics export
|
||||
- Health check improvements
|
||||
- Performance metrics
|
||||
|
||||
5. **Add Tests**
|
||||
- Unit tests (pytest)
|
||||
- Integration tests
|
||||
- API endpoint tests
|
||||
|
||||
---
|
||||
|
||||
## Links
|
||||
|
||||
- [INFRASTRUCTURE.md](../../INFRASTRUCTURE.md) — Infrastructure overview
|
||||
- [WARP.md](../../WARP.md) — Main developer guide
|
||||
- [docker-compose.yml](../../docker-compose.yml) — Service configuration
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2025-01-17
|
||||
**Maintained by:** Ivan Tytar & DAARION Team
|
||||
**Status:** 🟡 Infrastructure Ready — Awaiting Cursor implementation
|
||||
187
services/node-registry/app/main.py
Normal file
187
services/node-registry/app/main.py
Normal file
@@ -0,0 +1,187 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Node Registry Service
|
||||
Central registry for DAGI network nodes (Node #1, Node #2, Node #N)
|
||||
|
||||
This is a stub implementation - full API will be implemented by Cursor.
|
||||
"""
|
||||
|
||||
import os
|
||||
import time
|
||||
from datetime import datetime
|
||||
from typing import Dict, Any
|
||||
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from fastapi.responses import JSONResponse
|
||||
from pydantic import BaseModel
|
||||
import uvicorn
|
||||
|
||||
|
||||
# Environment configuration
|
||||
HTTP_PORT = int(os.getenv("NODE_REGISTRY_HTTP_PORT", "9205"))
|
||||
ENV = os.getenv("NODE_REGISTRY_ENV", "development")
|
||||
LOG_LEVEL = os.getenv("NODE_REGISTRY_LOG_LEVEL", "info")
|
||||
DB_HOST = os.getenv("NODE_REGISTRY_DB_HOST", "postgres")
|
||||
DB_PORT = int(os.getenv("NODE_REGISTRY_DB_PORT", "5432"))
|
||||
DB_NAME = os.getenv("NODE_REGISTRY_DB_NAME", "node_registry")
|
||||
DB_USER = os.getenv("NODE_REGISTRY_DB_USER", "node_registry_user")
|
||||
DB_PASSWORD = os.getenv("NODE_REGISTRY_DB_PASSWORD", "")
|
||||
|
||||
# Service metadata
|
||||
SERVICE_NAME = "node-registry"
|
||||
VERSION = "0.1.0-stub"
|
||||
START_TIME = time.time()
|
||||
|
||||
|
||||
app = FastAPI(
|
||||
title="Node Registry Service",
|
||||
description="Central registry for DAGI network nodes",
|
||||
version=VERSION,
|
||||
docs_url="/docs" if ENV == "development" else None,
|
||||
redoc_url="/redoc" if ENV == "development" else None,
|
||||
)
|
||||
|
||||
|
||||
# Models (stub - will be expanded by Cursor)
|
||||
class HealthResponse(BaseModel):
|
||||
status: str
|
||||
service: str
|
||||
version: str
|
||||
environment: str
|
||||
uptime_seconds: float
|
||||
timestamp: str
|
||||
database: Dict[str, Any]
|
||||
|
||||
|
||||
class MetricsResponse(BaseModel):
|
||||
service: str
|
||||
uptime_seconds: float
|
||||
total_nodes: int
|
||||
active_nodes: int
|
||||
timestamp: str
|
||||
|
||||
|
||||
# Health check endpoint
|
||||
@app.get("/health", response_model=HealthResponse)
|
||||
async def health_check():
|
||||
"""
|
||||
Health check endpoint for monitoring systems.
|
||||
|
||||
Returns service status, version, and database connectivity.
|
||||
"""
|
||||
uptime = time.time() - START_TIME
|
||||
|
||||
# TODO: Implement actual DB health check
|
||||
db_status = {
|
||||
"connected": False,
|
||||
"host": DB_HOST,
|
||||
"port": DB_PORT,
|
||||
"database": DB_NAME,
|
||||
"message": "Not implemented (stub)"
|
||||
}
|
||||
|
||||
return HealthResponse(
|
||||
status="healthy",
|
||||
service=SERVICE_NAME,
|
||||
version=VERSION,
|
||||
environment=ENV,
|
||||
uptime_seconds=uptime,
|
||||
timestamp=datetime.utcnow().isoformat() + "Z",
|
||||
database=db_status
|
||||
)
|
||||
|
||||
|
||||
# Metrics endpoint (Prometheus-compatible format will be added by Cursor)
|
||||
@app.get("/metrics", response_model=MetricsResponse)
|
||||
async def metrics():
|
||||
"""
|
||||
Metrics endpoint for Prometheus scraping.
|
||||
|
||||
TODO: Add proper Prometheus format (prometheus_client library)
|
||||
"""
|
||||
uptime = time.time() - START_TIME
|
||||
|
||||
# TODO: Implement actual metrics from database
|
||||
return MetricsResponse(
|
||||
service=SERVICE_NAME,
|
||||
uptime_seconds=uptime,
|
||||
total_nodes=0,
|
||||
active_nodes=0,
|
||||
timestamp=datetime.utcnow().isoformat() + "Z"
|
||||
)
|
||||
|
||||
|
||||
# Root endpoint
|
||||
@app.get("/")
|
||||
async def root():
|
||||
"""Root endpoint - service information"""
|
||||
return {
|
||||
"service": SERVICE_NAME,
|
||||
"version": VERSION,
|
||||
"status": "running",
|
||||
"environment": ENV,
|
||||
"message": "Node Registry Service (stub implementation)",
|
||||
"endpoints": {
|
||||
"health": "/health",
|
||||
"metrics": "/metrics",
|
||||
"docs": "/docs" if ENV == "development" else "disabled",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Stub API endpoints (to be implemented by Cursor)
|
||||
@app.post("/api/v1/nodes/register")
|
||||
async def register_node():
|
||||
"""
|
||||
Register a new node in the registry.
|
||||
|
||||
TODO: Implement by Cursor
|
||||
"""
|
||||
raise HTTPException(status_code=501, detail="Not implemented - stub endpoint")
|
||||
|
||||
|
||||
@app.post("/api/v1/nodes/{node_id}/heartbeat")
|
||||
async def update_heartbeat(node_id: str):
|
||||
"""
|
||||
Update node heartbeat (keep-alive).
|
||||
|
||||
TODO: Implement by Cursor
|
||||
"""
|
||||
raise HTTPException(status_code=501, detail="Not implemented - stub endpoint")
|
||||
|
||||
|
||||
@app.get("/api/v1/nodes")
|
||||
async def list_nodes():
|
||||
"""
|
||||
List all registered nodes.
|
||||
|
||||
TODO: Implement by Cursor
|
||||
"""
|
||||
raise HTTPException(status_code=501, detail="Not implemented - stub endpoint")
|
||||
|
||||
|
||||
@app.get("/api/v1/nodes/{node_id}")
|
||||
async def get_node(node_id: str):
|
||||
"""
|
||||
Get specific node information.
|
||||
|
||||
TODO: Implement by Cursor
|
||||
"""
|
||||
raise HTTPException(status_code=501, detail="Not implemented - stub endpoint")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(f"🚀 Starting {SERVICE_NAME} v{VERSION}")
|
||||
print(f"📊 Environment: {ENV}")
|
||||
print(f"🔌 Port: {HTTP_PORT}")
|
||||
print(f"🗄️ Database: {DB_USER}@{DB_HOST}:{DB_PORT}/{DB_NAME}")
|
||||
print(f"📝 Log level: {LOG_LEVEL}")
|
||||
print()
|
||||
|
||||
uvicorn.run(
|
||||
app,
|
||||
host="0.0.0.0",
|
||||
port=HTTP_PORT,
|
||||
log_level=LOG_LEVEL.lower(),
|
||||
access_log=True,
|
||||
)
|
||||
112
services/node-registry/migrations/init_node_registry.sql
Normal file
112
services/node-registry/migrations/init_node_registry.sql
Normal file
@@ -0,0 +1,112 @@
|
||||
-- Node Registry Database Initialization Script
|
||||
-- For DAGI Stack Node Registry Service
|
||||
-- Version: 0.1.0
|
||||
-- Date: 2025-01-17
|
||||
|
||||
-- Create database (run as postgres superuser)
|
||||
CREATE DATABASE node_registry;
|
||||
|
||||
-- Connect to database
|
||||
\c node_registry;
|
||||
|
||||
-- Create user with secure password
|
||||
-- NOTE: Replace 'CHANGE_ME_STRONG_PASSWORD' with actual strong password
|
||||
CREATE USER node_registry_user WITH ENCRYPTED PASSWORD 'CHANGE_ME_STRONG_PASSWORD';
|
||||
|
||||
-- Grant privileges
|
||||
GRANT ALL PRIVILEGES ON DATABASE node_registry TO node_registry_user;
|
||||
GRANT ALL ON SCHEMA public TO node_registry_user;
|
||||
GRANT CREATE ON SCHEMA public TO node_registry_user;
|
||||
|
||||
-- Enable necessary extensions
|
||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||
CREATE EXTENSION IF NOT EXISTS "pg_trgm";
|
||||
|
||||
-- Create nodes table (basic schema - will be expanded by Cursor)
|
||||
CREATE TABLE IF NOT EXISTS nodes (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
node_id VARCHAR(255) UNIQUE NOT NULL,
|
||||
node_name VARCHAR(255) NOT NULL,
|
||||
node_role VARCHAR(50) NOT NULL, -- 'production', 'development', 'backup'
|
||||
node_type VARCHAR(50) NOT NULL, -- 'router', 'gateway', 'worker', etc.
|
||||
ip_address INET,
|
||||
local_ip INET,
|
||||
hostname VARCHAR(255),
|
||||
status VARCHAR(50) DEFAULT 'offline', -- 'online', 'offline', 'maintenance'
|
||||
last_heartbeat TIMESTAMP WITH TIME ZONE,
|
||||
registered_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
metadata JSONB DEFAULT '{}',
|
||||
CONSTRAINT valid_status CHECK (status IN ('online', 'offline', 'maintenance', 'degraded'))
|
||||
);
|
||||
|
||||
-- Create node profiles table
|
||||
CREATE TABLE IF NOT EXISTS node_profiles (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
node_id UUID REFERENCES nodes(id) ON DELETE CASCADE,
|
||||
profile_name VARCHAR(255) NOT NULL,
|
||||
profile_type VARCHAR(50) NOT NULL, -- 'llm', 'service', 'capability'
|
||||
config JSONB NOT NULL DEFAULT '{}',
|
||||
enabled BOOLEAN DEFAULT true,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(node_id, profile_name)
|
||||
);
|
||||
|
||||
-- Create heartbeat log table (for monitoring)
|
||||
CREATE TABLE IF NOT EXISTS heartbeat_log (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
node_id UUID REFERENCES nodes(id) ON DELETE CASCADE,
|
||||
timestamp TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
status VARCHAR(50),
|
||||
metrics JSONB DEFAULT '{}'
|
||||
);
|
||||
|
||||
-- Create indexes
|
||||
CREATE INDEX idx_nodes_status ON nodes(status);
|
||||
CREATE INDEX idx_nodes_last_heartbeat ON nodes(last_heartbeat DESC);
|
||||
CREATE INDEX idx_nodes_node_id ON nodes(node_id);
|
||||
CREATE INDEX idx_node_profiles_node_id ON node_profiles(node_id);
|
||||
CREATE INDEX idx_node_profiles_enabled ON node_profiles(enabled);
|
||||
CREATE INDEX idx_heartbeat_log_node_id ON heartbeat_log(node_id);
|
||||
CREATE INDEX idx_heartbeat_log_timestamp ON heartbeat_log(timestamp DESC);
|
||||
|
||||
-- Create function to update updated_at timestamp
|
||||
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = CURRENT_TIMESTAMP;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- Create triggers
|
||||
CREATE TRIGGER update_nodes_updated_at
|
||||
BEFORE UPDATE ON nodes
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
CREATE TRIGGER update_node_profiles_updated_at
|
||||
BEFORE UPDATE ON node_profiles
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
-- Grant table permissions to user
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO node_registry_user;
|
||||
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO node_registry_user;
|
||||
|
||||
-- Insert initial nodes (Node #1 and Node #2)
|
||||
INSERT INTO nodes (node_id, node_name, node_role, node_type, ip_address, local_ip, hostname, status)
|
||||
VALUES
|
||||
('node-1-hetzner-gex44', 'Hetzner GEX44 Production', 'production', 'router', '144.76.224.179', NULL, 'gateway.daarion.city', 'offline'),
|
||||
('node-2-macbook-m4max', 'MacBook Pro M4 Max', 'development', 'router', NULL, '192.168.1.244', 'MacBook-Pro.local', 'offline')
|
||||
ON CONFLICT (node_id) DO NOTHING;
|
||||
|
||||
-- Success message
|
||||
DO $$
|
||||
BEGIN
|
||||
RAISE NOTICE '✅ Node Registry database initialized successfully';
|
||||
RAISE NOTICE '📊 Tables created: nodes, node_profiles, heartbeat_log';
|
||||
RAISE NOTICE '👤 User created: node_registry_user';
|
||||
RAISE NOTICE '⚠️ IMPORTANT: Change default password in production!';
|
||||
END $$;
|
||||
10
services/node-registry/requirements.txt
Normal file
10
services/node-registry/requirements.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
fastapi==0.115.0
|
||||
uvicorn[standard]==0.32.0
|
||||
pydantic==2.12.4
|
||||
pydantic-settings==2.7.0
|
||||
httpx==0.28.1
|
||||
asyncpg==0.30.0
|
||||
sqlalchemy[asyncio]==2.0.36
|
||||
alembic==1.14.0
|
||||
python-json-logger==3.2.1
|
||||
prometheus-client==0.21.0
|
||||
Reference in New Issue
Block a user