import logging import asyncio import sys import os sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..")) try: from backend.integrations.isap_client import ISAPClient from backend.integrations.parp_client import PARPClient from backend.rag_pipeline.scraper import scrape_grant_url from backend.rag_pipeline.ingest import process_and_ingest except ImportError: ISAPClient = None PARPClient = None logger = logging.getLogger(__name__) class ScraperAgent: """ Inteligentny Agent, który decyduje w jaki sposób pozyskać dane. Przeznaczony do działania z Celery Beat / APScheduler do cyklicznych aktualizacji. """ def __init__(self): if ISAPClient and PARPClient: self.isap_client = ISAPClient() self.parp_client = PARPClient() else: self.isap_client = None self.parp_client = None # Namespace do ogólnodostępnej przestrzeni aktów i regulaminów self.public_namespace = "public_legal" async def run_sync_job(self): """Uruchamia cykliczny proces synchronizacji dotacji i prawa""" if not self.isap_client or not self.parp_client: logger.error("[AGENT] Brak klientow ISAP/PARP. Synchronizacja anulowana.") return logger.info( "[AGENT] Rozpoczęcie automatycznego zadania synchronizacji bazy wiedzy..." ) # 1. PARP (Regulaminy Naborów) grants = self.parp_client.fetch_grants() for grant in grants: url = grant["url"] logger.info(f"[AGENT] Zlecam scrapowanie dla dotacji: {grant['id']}") try: text, _ = await scrape_grant_url(url) if text: process_and_ingest( text, url, priority="high", namespace=self.public_namespace ) except Exception as e: logger.error(f"[AGENT] Błąd fetchowania {url}: {e}") # 2. ISAP (Ustawa z dn 6 marca 2018 - Prawo przedsiębiorców) logger.info("[AGENT] Pobieranie ram prawnych (ISAP)") act_info = self.isap_client.fetch_act("WDU", 2018, 646) if act_info: url = act_info["text_url"] try: # Firecrawl poradzi sobie z ujednoliconym PDF w HTML wrapperze ISAP text, _ = await scrape_grant_url(url) if text: process_and_ingest( text, url, priority="critical", namespace=self.public_namespace ) except Exception as e: logger.error(f"[AGENT] Błąd parsowania ISAP {url}: {e}") logger.info("[AGENT] Zakończono automatyczny cykl agenta synchronizacyjnego.") if __name__ == "__main__": logging.basicConfig(level=logging.INFO) agent = ScraperAgent() asyncio.run(agent.run_sync_job())