SPARKNET / api /main.py
MHamdan's picture
Initial commit: SPARKNET framework
a9dc537
"""
SPARKNET FastAPI Backend
Provides RESTful API for Patent Wake-Up workflows.
"""
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from contextlib import asynccontextmanager
from pathlib import Path
from loguru import logger
# Global state for application lifecycle
app_state = {}
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Initialize SPARKNET components on startup"""
logger.info("🚀 Starting SPARKNET API...")
try:
# Import here to avoid circular dependencies
from src.llm.langchain_ollama_client import get_langchain_client
from src.workflow.langgraph_workflow import create_workflow
from src.agents.planner_agent import PlannerAgent
from src.agents.critic_agent import CriticAgent
from src.agents.memory_agent import create_memory_agent
from src.agents.vision_ocr_agent import VisionOCRAgent
# Initialize LangChain client
logger.info("Initializing LangChain Ollama client...")
app_state["llm_client"] = get_langchain_client(
default_complexity='standard',
enable_monitoring=False
)
# Initialize agents
logger.info("Initializing agents...")
app_state["planner"] = PlannerAgent(llm_client=app_state["llm_client"])
app_state["critic"] = CriticAgent(llm_client=app_state["llm_client"])
app_state["memory"] = create_memory_agent(
llm_client=app_state["llm_client"]
)
# Initialize VisionOCR agent if llava model is available
try:
logger.info("Initializing VisionOCR agent...")
vision_ocr = VisionOCRAgent(model_name="llava:7b")
if vision_ocr.is_available():
app_state["vision_ocr"] = vision_ocr
logger.success("✅ VisionOCR agent initialized with llava:7b")
else:
app_state["vision_ocr"] = None
logger.warning("⚠️ llava:7b model not available, OCR features disabled")
except Exception as e:
logger.warning(f"⚠️ Failed to initialize VisionOCR: {e}, OCR features disabled")
app_state["vision_ocr"] = None
# Initialize workflow
logger.info("Creating LangGraph workflow...")
app_state["workflow"] = create_workflow(
llm_client=app_state["llm_client"],
planner_agent=app_state["planner"],
critic_agent=app_state["critic"],
memory_agent=app_state["memory"],
vision_ocr_agent=app_state.get("vision_ocr"),
quality_threshold=0.80,
max_iterations=3
)
# Storage for active workflows and patents
app_state["workflows"] = {}
app_state["patents"] = {}
# Ensure directories exist
Path("uploads/patents").mkdir(parents=True, exist_ok=True)
Path("outputs").mkdir(parents=True, exist_ok=True)
Path("data/vector_store").mkdir(parents=True, exist_ok=True)
logger.success("✅ SPARKNET API initialized successfully!")
except Exception as e:
logger.error(f"❌ Failed to initialize SPARKNET: {e}")
raise
yield
# Cleanup on shutdown
logger.info("Shutting down SPARKNET API...")
app_state.clear()
# Create FastAPI application
app = FastAPI(
title="SPARKNET API",
description="AI-Powered Research Valorization Platform",
version="1.0.0",
lifespan=lifespan,
docs_url="/api/docs",
redoc_url="/api/redoc"
)
# CORS middleware for frontend
app.add_middleware(
CORSMiddleware,
allow_origins=[
"http://localhost:3000", # Next.js dev server
"http://localhost:3001",
"http://localhost:3002",
"http://127.0.0.1:3000",
"http://127.0.0.1:3001",
"http://127.0.0.1:3002",
"http://172.24.50.21:3000", # Server IP
"http://172.24.50.21:3001",
"http://172.24.50.21:3002"
],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Import and include routers
from api.routes import patents, workflows
app.include_router(patents.router, prefix="/api/patents", tags=["Patents"])
app.include_router(workflows.router, prefix="/api/workflows", tags=["Workflows"])
@app.get("/")
async def root():
"""Root endpoint - health check"""
return {
"status": "operational",
"service": "SPARKNET API",
"version": "1.0.0",
"message": "Welcome to SPARKNET - AI-Powered Research Valorization",
"docs": "/api/docs"
}
@app.get("/api/health")
async def health():
"""Detailed health check endpoint"""
components_healthy = {
"llm_client": app_state.get("llm_client") is not None,
"workflow": app_state.get("workflow") is not None,
"planner": app_state.get("planner") is not None,
"critic": app_state.get("critic") is not None,
"memory": app_state.get("memory") is not None
}
all_healthy = all(components_healthy.values())
return {
"status": "healthy" if all_healthy else "degraded",
"components": components_healthy,
"statistics": {
"active_workflows": len(app_state.get("workflows", {})),
"processed_patents": len(app_state.get("patents", {}))
}
}
if __name__ == "__main__":
import uvicorn
uvicorn.run(
"api.main:app",
host="0.0.0.0",
port=8000,
reload=True,
log_level="info"
)