a1c00l commited on
Commit
5ac66ed
·
verified ·
1 Parent(s): ca26816

Update src/aibom_generator/api.py

Browse files
Files changed (1) hide show
  1. src/aibom_generator/api.py +30 -108
src/aibom_generator/api.py CHANGED
@@ -1,9 +1,4 @@
1
- import os
2
- import json
3
- import logging
4
- from typing import Dict, List, Optional, Any
5
- from fastapi import FastAPI, HTTPException, Request, Form
6
- from fastapi.responses import JSONResponse, FileResponse, HTMLResponse
7
  from fastapi.staticfiles import StaticFiles
8
  from fastapi.templating import Jinja2Templates
9
  from pydantic import BaseModel
@@ -12,61 +7,46 @@ from pydantic import BaseModel
12
  logging.basicConfig(level=logging.INFO)
13
  logger = logging.getLogger(__name__)
14
 
15
- # Define templates directory
16
  templates_dir = "templates"
 
17
 
18
  # Initialize templates
19
  templates = Jinja2Templates(directory=templates_dir)
20
 
21
  # Create app
22
- app = FastAPI(title="AI SBOM Generator API - Simplified Version")
23
-
24
- # Define output directory for generated AIBOMs
25
- OUTPUT_DIR = "/tmp/aibom_output"
26
 
27
- # Create output directory if it doesn't exist
28
  os.makedirs(OUTPUT_DIR, exist_ok=True)
29
 
30
  # Mount output directory as static files
31
  app.mount("/output", StaticFiles(directory=OUTPUT_DIR), name="output")
32
 
33
- # Define models
34
  class StatusResponse(BaseModel):
35
  status: str
36
  version: str
37
  generator_version: str
38
 
39
- # Startup event to ensure directories exist
40
  @app.on_event("startup")
41
  async def startup_event():
42
- """Create necessary directories on startup."""
43
  os.makedirs(OUTPUT_DIR, exist_ok=True)
44
- logger.info(f"Created output directory at {OUTPUT_DIR}")
45
  logger.info(f"Registered routes: {[route.path for route in app.routes]}")
46
 
47
- # Root route serves the UI
48
  @app.get("/", response_class=HTMLResponse)
49
  async def root(request: Request):
50
- """Serve the web UI interface as the default view."""
51
  try:
52
- logger.info("Attempting to render index.html template")
53
  return templates.TemplateResponse("index.html", {"request": request})
54
  except Exception as e:
55
  logger.error(f"Error rendering template: {str(e)}")
56
- raise HTTPException(status_code=500, detail=f"Error in UI endpoint: {str(e)}")
57
 
58
- # Status endpoint
59
  @app.get("/status", response_model=StatusResponse)
60
  async def get_status():
61
- """Get the API status and version information."""
62
- logger.info("Status endpoint called")
63
- return {
64
- "status": "operational",
65
- "version": "1.0.0",
66
- "generator_version": "1.0.0",
67
- }
68
-
69
- # Form-based generate endpoint for web UI
70
  @app.post("/generate", response_class=HTMLResponse)
71
  async def generate_form(
72
  request: Request,
@@ -74,77 +54,46 @@ async def generate_form(
74
  include_inference: bool = Form(False),
75
  use_best_practices: bool = Form(True)
76
  ):
77
- """Generate an AI SBOM from form data and render the result template."""
78
  try:
79
- logger.info(f"Generate form endpoint called with model_id: {model_id}")
80
-
81
- # Import the generator here to avoid circular imports
82
- try:
83
- from src.aibom_generator.generator import AIBOMGenerator
84
- logger.info("Imported AIBOMGenerator from src.aibom_generator.generator")
85
- except ImportError as e:
86
- logger.warning(f"Import from src.aibom_generator.generator failed: {e}")
87
- try:
88
- from aibom_generator.generator import AIBOMGenerator
89
- logger.info("Imported AIBOMGenerator from aibom_generator.generator")
90
- except ImportError as e:
91
- logger.warning(f"Import from aibom_generator.generator failed: {e}")
92
- try:
93
- from generator import AIBOMGenerator
94
- logger.info("Imported AIBOMGenerator from generator")
95
- except ImportError as e:
96
- logger.error(f"All import attempts failed: {e}")
97
- raise ImportError("Could not import AIBOMGenerator. Please check your installation.")
98
-
99
- # Create generator instance
100
- logger.info("Creating AIBOMGenerator instance")
101
  generator = AIBOMGenerator()
102
-
103
- # Generate AIBOM
104
- logger.info(f"Generating AIBOM for model: {model_id}")
105
- aibom, enhancement_report = generator.generate(
106
  model_id=model_id,
107
  include_inference=include_inference,
108
  use_best_practices=use_best_practices
109
  )
110
- logger.info("AIBOM generation successful")
111
-
112
- # Save AIBOM to file
113
  filename = f"{model_id.replace('/', '_')}_aibom.json"
114
  filepath = os.path.join(OUTPUT_DIR, filename)
115
- logger.info(f"Saving AIBOM to: {filepath}")
116
  with open(filepath, "w") as f:
117
  json.dump(aibom, f, indent=2)
118
-
119
- # Create download URL
120
  download_url = f"/output/{filename}"
121
-
122
- # Create download script
123
- download_script = """
124
  <script>
125
- function downloadJSON() {
126
  const a = document.createElement('a');
127
- a.href = '%s';
128
- a.download = '%s';
129
  document.body.appendChild(a);
130
  a.click();
131
  document.body.removeChild(a);
132
- }
133
  </script>
134
- """ % (download_url, filename)
135
-
136
- # Get completeness score
137
  completeness_score = None
138
  if hasattr(generator, 'get_completeness_score'):
139
  try:
140
- logger.info("Getting completeness score")
141
  completeness_score = generator.get_completeness_score(model_id)
142
- logger.info(f"Completeness score: {completeness_score}")
143
  except Exception as e:
144
- logger.error(f"Error getting completeness score: {str(e)}")
145
-
146
- # Render result template
147
- logger.info("Rendering result.html template")
148
  return templates.TemplateResponse(
149
  "result.html",
150
  {
@@ -158,34 +107,7 @@ async def generate_form(
158
  }
159
  )
160
  except Exception as e:
161
- logger.error(f"Error generating AI SBOM: {str(e)}", exc_info=True)
162
  return templates.TemplateResponse(
163
- "error.html",
164
- {
165
- "request": request,
166
- "error_message": f"Error generating AI SBOM: {str(e)}"
167
- }
168
  )
169
-
170
- # Download endpoint
171
- @app.get("/download/{filename}")
172
- async def download_file(filename: str):
173
- """Download a generated AI SBOM file."""
174
- try:
175
- logger.info(f"Download endpoint called for file: {filename}")
176
- filepath = os.path.join(OUTPUT_DIR, filename)
177
- if not os.path.exists(filepath):
178
- logger.error(f"File not found: {filepath}")
179
- raise HTTPException(status_code=404, detail=f"File {filename} not found")
180
-
181
- logger.info(f"Returning file: {filepath}")
182
- return FileResponse(
183
- filepath,
184
- media_type="application/json",
185
- filename=filename
186
- )
187
- except HTTPException:
188
- raise
189
- except Exception as e:
190
- logger.error(f"Error downloading file: {str(e)}", exc_info=True)
191
- raise HTTPException(status_code=500, detail=f"Error downloading file: {str(e)}")
 
1
+ from fastapi.responses import HTMLResponse
 
 
 
 
 
2
  from fastapi.staticfiles import StaticFiles
3
  from fastapi.templating import Jinja2Templates
4
  from pydantic import BaseModel
 
7
  logging.basicConfig(level=logging.INFO)
8
  logger = logging.getLogger(__name__)
9
 
10
+ # Define directories
11
  templates_dir = "templates"
12
+ OUTPUT_DIR = "/tmp/aibom_output"
13
 
14
  # Initialize templates
15
  templates = Jinja2Templates(directory=templates_dir)
16
 
17
  # Create app
18
+ app = FastAPI(title="AI SBOM Generator API")
 
 
 
19
 
20
+ # Ensure output directory exists
21
  os.makedirs(OUTPUT_DIR, exist_ok=True)
22
 
23
  # Mount output directory as static files
24
  app.mount("/output", StaticFiles(directory=OUTPUT_DIR), name="output")
25
 
26
+ # Status response model
27
  class StatusResponse(BaseModel):
28
  status: str
29
  version: str
30
  generator_version: str
31
 
 
32
  @app.on_event("startup")
33
  async def startup_event():
 
34
  os.makedirs(OUTPUT_DIR, exist_ok=True)
35
+ logger.info(f"Output directory ready at {OUTPUT_DIR}")
36
  logger.info(f"Registered routes: {[route.path for route in app.routes]}")
37
 
 
38
  @app.get("/", response_class=HTMLResponse)
39
  async def root(request: Request):
 
40
  try:
 
41
  return templates.TemplateResponse("index.html", {"request": request})
42
  except Exception as e:
43
  logger.error(f"Error rendering template: {str(e)}")
44
+ raise HTTPException(status_code=500, detail=f"Template rendering error: {str(e)}")
45
 
 
46
  @app.get("/status", response_model=StatusResponse)
47
  async def get_status():
48
+ return StatusResponse(status="operational", version="1.0.0", generator_version="1.0.0")
49
+
 
 
 
 
 
 
 
50
  @app.post("/generate", response_class=HTMLResponse)
51
  async def generate_form(
52
  request: Request,
 
54
  include_inference: bool = Form(False),
55
  use_best_practices: bool = Form(True)
56
  ):
 
57
  try:
58
+ from src.aibom_generator.generator import AIBOMGenerator
59
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  generator = AIBOMGenerator()
61
+
62
+ aibom = generator.generate_aibom(
 
 
63
  model_id=model_id,
64
  include_inference=include_inference,
65
  use_best_practices=use_best_practices
66
  )
67
+ enhancement_report = generator.get_enhancement_report()
68
+
 
69
  filename = f"{model_id.replace('/', '_')}_aibom.json"
70
  filepath = os.path.join(OUTPUT_DIR, filename)
71
+
72
  with open(filepath, "w") as f:
73
  json.dump(aibom, f, indent=2)
74
+
 
75
  download_url = f"/output/{filename}"
76
+
77
+ download_script = f"""
 
78
  <script>
79
+ function downloadJSON() {{
80
  const a = document.createElement('a');
81
+ a.href = '{download_url}';
82
+ a.download = '{filename}';
83
  document.body.appendChild(a);
84
  a.click();
85
  document.body.removeChild(a);
86
+ }}
87
  </script>
88
+ """
89
+
 
90
  completeness_score = None
91
  if hasattr(generator, 'get_completeness_score'):
92
  try:
 
93
  completeness_score = generator.get_completeness_score(model_id)
 
94
  except Exception as e:
95
+ logger.error(f"Completeness score error: {str(e)}")
96
+
 
 
97
  return templates.TemplateResponse(
98
  "result.html",
99
  {
 
107
  }
108
  )
109
  except Exception as e:
110
+ logger.error(f"Error generating AI SBOM: {str(e)}")
111
  return templates.TemplateResponse(
112
+ "error.html", {"request": request, "error": str(e)}
 
 
 
 
113
  )