ShivaliGupta commited on
Commit
718c2f9
·
1 Parent(s): 9e0cc60

Fix import

Browse files
Files changed (1) hide show
  1. backend/main.py +88 -39
backend/main.py CHANGED
@@ -1,29 +1,28 @@
1
- """
2
- FastAPI backend for the AI Shopping Research Agent.
3
-
4
- Endpoints:
5
- GET /api/health -> quick status check (keys configured? etc)
6
- POST /api/recommend -> runs the full multi-agent pipeline
7
-
8
- Also serves the static frontend (frontend/) directly, so running this one
9
- process gives you the whole working app -- no separate frontend server needed.
10
- """
11
  import logging
12
  import os
13
 
14
  from fastapi import FastAPI, HTTPException
15
  from fastapi.middleware.cors import CORSMiddleware
16
- from fastapi.staticfiles import StaticFiles
17
  from fastapi.responses import FileResponse
 
18
  from pydantic import BaseModel, Field
19
 
20
  from backend.agents.orchestrator import run_pipeline
21
  from backend.config import GEMINI_API_KEY, SERPAPI_KEY
22
 
 
 
 
23
  logging.basicConfig(level=logging.INFO)
24
- logger = logging.getLogger("main")
25
-
26
- app = FastAPI(title="AI Shopping Research Agent", version="1.0.0")
 
 
 
 
 
 
27
 
28
  app.add_middleware(
29
  CORSMiddleware,
@@ -33,14 +32,34 @@ app.add_middleware(
33
  allow_headers=["*"],
34
  )
35
 
36
- FRONTEND_DIR = os.path.join(os.path.dirname(__file__), "..", "frontend")
37
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
 
 
 
 
39
  class RecommendRequest(BaseModel):
40
- query: str = Field(..., min_length=2, description="What the user wants to buy")
41
- budget_max: float | None = Field(None, description="Optional maximum budget")
42
-
43
 
 
 
 
44
  @app.get("/api/health")
45
  def health():
46
  return {
@@ -49,34 +68,64 @@ def health():
49
  "serpapi_configured": bool(SERPAPI_KEY),
50
  }
51
 
52
-
 
 
53
  @app.post("/api/recommend")
54
  def recommend(payload: RecommendRequest):
 
55
  if not GEMINI_API_KEY:
56
  raise HTTPException(
57
  status_code=400,
58
- detail="GEMINI_API_KEY is not configured on the server. "
59
- "Add a free key from https://aistudio.google.com/apikey to your .env file.",
60
  )
61
- try:
62
- result = run_pipeline(payload.query, payload.budget_max)
63
- except Exception as exc: # noqa: BLE001
64
- logger.exception("Pipeline failed")
65
- raise HTTPException(status_code=500, detail=f"Pipeline error: {exc}") from exc
66
-
67
- return {
68
- "query": payload.query,
69
- "used_live_data": result.get("used_live_data", False),
70
- "errors": result.get("errors", []),
71
- "results": result.get("ranked", []),
72
- }
73
 
 
 
 
 
 
74
 
75
- # --- Serve the static frontend ---
76
- FRONTEND_DIR = os.path.join(os.path.dirname(__file__), "..", "frontend")
 
 
 
 
77
 
78
- app.mount("/frontend", StaticFiles(directory=FRONTEND_DIR), name="frontend")
 
 
 
 
 
79
 
 
 
 
80
  @app.get("/")
81
- def home():
82
- return FileResponse(os.path.join(FRONTEND_DIR, "index.html"))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import logging
2
  import os
3
 
4
  from fastapi import FastAPI, HTTPException
5
  from fastapi.middleware.cors import CORSMiddleware
 
6
  from fastapi.responses import FileResponse
7
+ from fastapi.staticfiles import StaticFiles
8
  from pydantic import BaseModel, Field
9
 
10
  from backend.agents.orchestrator import run_pipeline
11
  from backend.config import GEMINI_API_KEY, SERPAPI_KEY
12
 
13
+ # -------------------------------------------------------
14
+ # Logging
15
+ # -------------------------------------------------------
16
  logging.basicConfig(level=logging.INFO)
17
+ logger = logging.getLogger("ShopPilot")
18
+
19
+ # -------------------------------------------------------
20
+ # App
21
+ # -------------------------------------------------------
22
+ app = FastAPI(
23
+ title="ShopPilot AI",
24
+ version="1.0.0"
25
+ )
26
 
27
  app.add_middleware(
28
  CORSMiddleware,
 
32
  allow_headers=["*"],
33
  )
34
 
35
+ # -------------------------------------------------------
36
+ # Paths
37
+ # -------------------------------------------------------
38
+ BASE_DIR = os.path.dirname(os.path.abspath(__file__))
39
+ PROJECT_DIR = os.path.abspath(os.path.join(BASE_DIR, ".."))
40
+ FRONTEND_DIR = os.path.join(PROJECT_DIR, "frontend")
41
+
42
+ logger.info(f"Frontend directory: {FRONTEND_DIR}")
43
+
44
+ # -------------------------------------------------------
45
+ # Static Files
46
+ # -------------------------------------------------------
47
+ app.mount(
48
+ "/frontend",
49
+ StaticFiles(directory=FRONTEND_DIR),
50
+ name="frontend"
51
+ )
52
 
53
+ # -------------------------------------------------------
54
+ # Request Model
55
+ # -------------------------------------------------------
56
  class RecommendRequest(BaseModel):
57
+ query: str = Field(..., min_length=2)
58
+ budget_max: float | None = None
 
59
 
60
+ # -------------------------------------------------------
61
+ # Health API
62
+ # -------------------------------------------------------
63
  @app.get("/api/health")
64
  def health():
65
  return {
 
68
  "serpapi_configured": bool(SERPAPI_KEY),
69
  }
70
 
71
+ # -------------------------------------------------------
72
+ # Recommendation API
73
+ # -------------------------------------------------------
74
  @app.post("/api/recommend")
75
  def recommend(payload: RecommendRequest):
76
+
77
  if not GEMINI_API_KEY:
78
  raise HTTPException(
79
  status_code=400,
80
+ detail="GEMINI_API_KEY not configured."
 
81
  )
 
 
 
 
 
 
 
 
 
 
 
 
82
 
83
+ try:
84
+ result = run_pipeline(
85
+ payload.query,
86
+ payload.budget_max
87
+ )
88
 
89
+ return {
90
+ "query": payload.query,
91
+ "used_live_data": result.get("used_live_data", False),
92
+ "errors": result.get("errors", []),
93
+ "results": result.get("ranked", []),
94
+ }
95
 
96
+ except Exception as e:
97
+ logger.exception("Pipeline failed")
98
+ raise HTTPException(
99
+ status_code=500,
100
+ detail=str(e)
101
+ )
102
 
103
+ # -------------------------------------------------------
104
+ # Frontend
105
+ # -------------------------------------------------------
106
  @app.get("/")
107
+ def index():
108
+ return FileResponse(
109
+ os.path.join(FRONTEND_DIR, "index.html"),
110
+ media_type="text/html",
111
+ headers={
112
+ "Cache-Control": "no-cache"
113
+ },
114
+ )
115
+
116
+ # -------------------------------------------------------
117
+ # Fallback routes (handles cached requests)
118
+ # -------------------------------------------------------
119
+ @app.get("/style.css")
120
+ def style():
121
+ return FileResponse(
122
+ os.path.join(FRONTEND_DIR, "style.css"),
123
+ media_type="text/css"
124
+ )
125
+
126
+ @app.get("/script.js")
127
+ def script():
128
+ return FileResponse(
129
+ os.path.join(FRONTEND_DIR, "script.js"),
130
+ media_type="application/javascript"
131
+ )