Files
microdao-daarion/docs/cursor/crawl4ai_web_crawler_task.md
Apple 4601c6fca8 feat: add Vision Encoder service + Vision RAG implementation
- Vision Encoder Service (OpenCLIP ViT-L/14, GPU-accelerated)
  - FastAPI app with text/image embedding endpoints (768-dim)
  - Docker support with NVIDIA GPU runtime
  - Port 8001, health checks, model info API

- Qdrant Vector Database integration
  - Port 6333/6334 (HTTP/gRPC)
  - Image embeddings storage (768-dim, Cosine distance)
  - Auto collection creation

- Vision RAG implementation
  - VisionEncoderClient (Python client for API)
  - Image Search module (text-to-image, image-to-image)
  - Vision RAG routing in DAGI Router (mode: image_search)
  - VisionEncoderProvider integration

- Documentation (5000+ lines)
  - SYSTEM-INVENTORY.md - Complete system inventory
  - VISION-ENCODER-STATUS.md - Service status
  - VISION-RAG-IMPLEMENTATION.md - Implementation details
  - vision_encoder_deployment_task.md - Deployment checklist
  - services/vision-encoder/README.md - Deployment guide
  - Updated WARP.md, INFRASTRUCTURE.md, Jupyter Notebook

- Testing
  - test-vision-encoder.sh - Smoke tests (6 tests)
  - Unit tests for client, image search, routing

- Services: 17 total (added Vision Encoder + Qdrant)
- AI Models: 3 (qwen3:8b, OpenCLIP ViT-L/14, BAAI/bge-m3)
- GPU Services: 2 (Vision Encoder, Ollama)
- VRAM Usage: ~10 GB (concurrent)

Status: Production Ready 
2025-11-17 05:24:36 -08:00

15 KiB
Raw Blame History

Task: Web Crawler Service (crawl4ai) & Agent Tool Integration

Goal

Інтегрувати crawl4ai в агентську систему MicroDAO/DAARION як:

  1. Окремий бекенд-сервіс Web Crawler, який:
    • вміє скрапити сторінки з JS (Playwright/Chromium),
    • повертати структурований текст/HTML/метадані,
    • (опційно) генерувати події doc.upserted для RAG-ingestion.
  2. Агентський tool web_crawler, який викликається через Tool Proxy і доступний агентам (Team Assistant, Bridges Agent, тощо) з урахуванням безпеки.

Мета — дати агентам можливість читати зовнішні веб-ресурси (з обмеженнями) і, за потреби, індексувати їх у RAG.


Context

  • Root: microdao-daarion/.
  • Інфраструктура агентів та tools:
    • docs/cursor/12_agent_runtime_core.md
    • docs/cursor/13_agent_memory_system.md
    • docs/cursor/37_agent_tools_and_plugins_specification.md
    • docs/cursor/20_integrations_bridges_agent.md
  • RAG-шар:
    • docs/cursor/rag_gateway_task.md
    • docs/cursor/rag_ingestion_worker_task.md
    • docs/cursor/rag_ingestion_events_wave1_mvp_task.md
  • Event Catalog / NATS:
    • docs/cursor/42_nats_event_streams_and_event_catalog.md
    • docs/cursor/43_database_events_outbox_design.md

На сервері вже встановлено crawl4ai[all] та playwright chromium.


1. Сервіс Web Crawler

1.1. Структура сервісу

Створити новий Python-сервіс (подібно до інших внутрішніх сервісів):

  • Директорія: services/web-crawler/
  • Файли (пропозиція):
    • main.py — entrypoint (FastAPI/uvicorn).
    • api.py — визначення HTTP-ендпоїнтів.
    • crawl_client.py — обгортка над crawl4ai.
    • models.py — Pydantic-схеми (request/response).
    • config.py — налаштування (timeouts, max_depth, allowlist доменів, тощо).

Сервіс не має прямого UI; його викликають Tool Proxy / інші бекенд-сервіси.

1.2. Основний ендпоїнт: POST /api/web/scrape

Пропонований контракт:

Request JSON:

{
  "url": "https://example.com/article",
  "team_id": "dao_greenfood",
  "session_id": "sess_...",        
  "max_depth": 1,                    
  "max_pages": 1,                    
  "js_enabled": true,                
  "timeout_seconds": 30,
  "user_agent": "MicroDAO-Crawler/1.0",
  "mode": "public",                
  "indexed": false,                 
  "tags": ["external", "web", "research"],
  "return_html": false,             
  "max_chars": 20000                
}

Response JSON (скорочено):

{
  "ok": true,
  "url": "https://example.com/article",
  "final_url": "https://example.com/article",
  "status_code": 200,
  "content": {
    "text": "... main extracted text ...",
    "html": "<html>...</html>",
    "title": "Example Article",
    "language": "en",
    "meta": {
      "description": "...",
      "keywords": ["..."]
    }
  },
  "links": [
    { "url": "https://example.com/next", "text": "Next" }
  ],
  "raw_size_bytes": 123456,
  "fetched_at": "2025-11-17T10:45:00Z"
}

Використати API/параметри crawl4ai для:

  • рендеру JS (Playwright),
  • витягання основного контенту (article/reader mode, якщо є),
  • нормалізації тексту (видалення зайвого boilerplate).

1.3. Додаткові ендпоїнти (опційно)

  • POST /api/web/scrape_batch — масовий скрап кількох URL (обмежений top-K).
  • POST /api/web/crawl_site — обхід сайту з max_depth/max_pages (для MVP можна не реалізовувати або залишити TODO).
  • POST /api/web/scrape_and_ingest — варіант, який одразу шле подію doc.upserted (див. розділ 3).

1.4. Обмеження та безпека

У config.py передбачити:

  • MAX_DEPTH (наприклад, 12 для MVP).
  • MAX_PAGES (наприклад, 35).
  • MAX_CHARS/MAX_BYTES (щоб не забивати памʼять).
  • (Опційно) allowlist/denylist доменів для кожної команди/DAO.
  • таймаут HTTP/JS-запиту.

Логувати тільки мінімальний технічний контекст (URL, код статусу, тривалість), не зберігати повний HTML у логах.


2. Обгортка над crawl4ai (crawl_client.py)

Створити модуль, який інкапсулює виклики crawl4ai, щоб API/деталі можна було змінювати централізовано.

Приблизна логіка:

  • функція async def fetch_page(url: str, options: CrawlOptions) -> CrawlResult:
    • налаштувати crawl4ai з Playwright (chromium),
    • виконати рендер/збір контенту,
    • повернути нормалізований результат: text, html (опційно), метадані, посилання.

Обовʼязково:

  • коректно обробляти помилки мережі, редіректи, 4xx/5xx;
  • повертати ok=false + error message у HTTP-відповіді API.

3. Інтеграція з RAG-ingestion (doc.upserted)

3.1. Подія doc.upserted для веб-сторінок

Після успішного скрапу, якщо indexed=true, Web Crawler може (в майбутньому або одразу) створювати подію:

  • event: doc.upserted
  • stream: STREAM_PROJECT або спеціальний STREAM_DOCS

Payload (адаптований під RAG-дизайн):

{
  "doc_id": "web::<hash_of_url>",
  "team_id": "dao_greenfood",
  "project_id": null,
  "path": "web/https_example_com_article",
  "title": "Example Article",
  "text": "... main extracted text ...",
  "url": "https://example.com/article",
  "tags": ["web", "external", "research"],
  "visibility": "public",
  "doc_type": "web",
  "indexed": true,
  "mode": "public",
  "updated_at": "2025-11-17T10:45:00Z"
}

Цю подію можна:

  1. заповнити в таблицю outbox (див. 43_database_events_outbox_design.md),
  2. з неї Outbox Worker відправить у NATS (JetStream),
  3. rag-ingest-worker (згідно rag_ingestion_events_wave1_mvp_task.md) сприйме doc.upserted і проіндексує сторінку в Milvus/Neo4j.

3.2. Підтримка у нормалізаторі

У services/rag-ingest-worker/pipeline/normalization.py уже є/буде normalize_doc_upserted:

  • для веб-сторінок doc_type="web" потрібно лише переконатися, що:
    • source_type = "doc" або "web" (на твій вибір, але консистентний),
    • у tags включено "web"/"external",
    • у metadata є url.

Якщо потрібно, можна додати просту гілку для doc_type == "web".


4. Agent Tool: web_crawler

4.1. Категорія безпеки

Відповідно до 37_agent_tools_and_plugins_specification.md:

  • Зовнішній інтернет — Category D — Critical Tools (browser-full, external_api).
  • Новий інструмент:
    • назва: web_crawler,
    • capability: tool.web_crawler.invoke,
    • категорія: D (Critical),
    • за замовчуванням вимкнений — вмикається Governance/адміністратором для конкретних MicroDAO.

4.2. Tool request/response контракт

Tool Proxy викликає Web Crawler через HTTP.

Request від Agent Runtime до Tool Proxy:

{
  "tool": "web_crawler",
  "args": {
    "url": "https://example.com/article",
    "max_chars": 8000,
    "indexed": false,
    "mode": "public"
  },
  "context": {
    "agent_run_id": "ar_123",
    "team_id": "dao_greenfood",
    "user_id": "u_001",
    "channel_id": "ch_abc"
  }
}

Tool Proxy далі робить HTTP-запит до web-crawler сервісу (POST /api/web/scrape).

Відповідь до агента (спрощена):

{
  "ok": true,
  "output": {
    "title": "Example Article",
    "url": "https://example.com/article",
    "snippet": "Короткий уривок тексту...",
    "full_text": "... обрізаний до max_chars ..."
  }
}

Для безпеки:

  • у відповідь, яку бачить LLM/агент, повертати обмежений full_text (наприклад, 810k символів),
  • якщо full_text занадто довгий — обрізати та явно це позначити.

4.3. PDP та quotas

  • Перед викликом Tool Proxy повинен викликати PDP:
    • action = tool.web_crawler.invoke,
    • subject = agent_id,
    • resource = team_id.
  • Usage Service (див. 44_usage_accounting_and_quota_engine.md) може:
    • рахувати кількість викликів web_crawler/день,
    • обмежувати тривалість/обʼєм даних.

5. Інтеграція з Bridges Agent / іншими агентами

5.1. Bridges Agent

Bridges Agent (20_integrations_bridges_agent.md) може використовувати web_crawler як один зі своїх tools:

  • сценарій: "Підтяни останню версію документації з https://docs.example.com/... і збережи як doc у Co-Memory";
  • Bridges Agent викликає tool web_crawler, отримує текст, створює внутрішній doc (через Projects/Co-Memory API) і генерує doc.upserted.

5.2. Team Assistant / Research-агенти

Для окремих DAO можна дозволити:

  • Team Assistant викликає web_crawler для досліджень (наприклад, "знайди інформацію на сайті Мінекономіки про гранти"),
  • але з жорсткими лімітами (whitelist доменів, rate limits).

6. Confidential mode та privacy

Згідно з 47_messaging_channels_and_privacy_layers.md та 48_teams_access_control_and_confidential_mode.md:

  • Якщо контекст агента mode = confidential:
    • інструмент web_crawler не повинен отримувати confidential plaintext із внутрішніх повідомлень (тобто, у args не має бути фрагментів внутрішнього тексту);
    • зазвичай достатньо лише URL.
  • Якщо indexed=true та mode=confidential для веб-сторінки (рідкісний кейс):
    • можна дозволити зберігати plaintext сторінки в RAG, оскільки це зовнішнє джерело;
    • але варто позначати таку інформацію як source_type="web_external" і у PDP контролювати, хто може її читати.

Для MVP в цій задачі достатньо:

  • заборонити виклик web_crawler із confidential-контексту без явної конфігурації (тобто PDP повертає deny).

7. Логування та моніторинг

Додати базове логування в Web Crawler:

  • при кожному скрапі:
    • team_id,
    • url,
    • status_code,
    • duration_ms,
    • bytes_downloaded.

Без збереження body/HTML у логах.

За бажанням — контрприклад метрик:

  • web_crawler_requests_total,
  • web_crawler_errors_total,
  • web_crawler_avg_duration_ms.

8. Files to create/modify (suggested)

Назви/шляхи можна адаптувати до фактичної структури, важлива ідея.

  • services/web-crawler/main.py

  • services/web-crawler/api.py

  • services/web-crawler/crawl_client.py

  • services/web-crawler/models.py

  • services/web-crawler/config.py

  • Tool Proxy / агентський runtime (Node/TS):

    • додати tool web_crawler у список інструментів (див. 37_agent_tools_and_plugins_specification.md).
    • оновити Tool Proxy, щоб він міг робити HTTP-виклик до Web Crawler.
  • Bridges/Team Assistant агенти:

    • (опційно) додати web_crawler у їхні конфіги як доступний tool.
  • RAG ingestion:

    • (опційно) оновити rag-ingest-worker/docs, щоб описати doc_type="web" у doc.upserted подіях.

9. Acceptance criteria

  1. Існує новий сервіс web-crawler з ендпоїнтом POST /api/web/scrape, який використовує crawl4ai+Playwright для скрапу сторінок.
  2. Ендпоїнт повертає текст/метадані у структурованому JSON, з обмеженнями по розміру.
  3. Заготовлена (або реалізована) інтеграція з Event Catalog через подію doc.upserted для doc_type="web" (indexed=true).
  4. У Tool Proxy зʼявився tool web_crawler (категорія D, capability tool.web_crawler.invoke) з чітким request/response контрактом.
  5. PDP/usage engine враховують новий tool (принаймні у вигляді basic перевірок/квот).
  6. Bridges Agent (або Team Assistant) може використати web_crawler для простого MVP-сценарію (наприклад: скрапнути одну сторінку і показати її summary користувачу).
  7. Конфіденційний режим враховано: у конфігурації за замовчуванням web_crawler недоступний у confidential каналах/командах.

10. Інструкція для Cursor

You are a senior backend engineer (Python + Node/TS) working on the DAARION/MicroDAO stack.

Implement the Web Crawler service and agent tool integration using:
- crawl4ai_web_crawler_task.md
- 37_agent_tools_and_plugins_specification.md
- 20_integrations_bridges_agent.md
- rag_gateway_task.md
- rag_ingestion_worker_task.md
- 42_nats_event_streams_and_event_catalog.md

Tasks:
1) Create the `services/web-crawler` service (FastAPI or equivalent) with /api/web/scrape based on crawl4ai.
2) Implement basic options: js_enabled, max_depth, max_pages, max_chars, timeouts.
3) Add tool `web_crawler` to the Tool Proxy (category D, capability tool.web_crawler.invoke).
4) Wire Tool Proxy → Web Crawler HTTP call with proper request/response mapping.
5) (Optional but preferred) Implement doc.upserted emission for indexed=true pages (doc_type="web") via the existing outbox → NATS flow.
6) Add a simple usage example in Bridges Agent or Team Assistant config (one agent that can use this tool in dev).

Output:
- list of modified files
- diff
- summary