File size: 5,512 Bytes
a9dc537
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
"""
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"
    )