Transcendental-Programmer commited on
Commit
0f25023
·
1 Parent(s): a8da4e0

fix: localhost error

Browse files
Files changed (6) hide show
  1. Dockerfile +3 -1
  2. README.md +41 -11
  3. app.py +46 -14
  4. faceforge_api/main.py +8 -2
  5. faceforge_ui/app.py +25 -3
  6. main.py +39 -11
Dockerfile CHANGED
@@ -21,6 +21,8 @@ EXPOSE 7860
21
  # Set environment variables
22
  ENV PYTHONPATH="/app"
23
  ENV PYTHONUNBUFFERED=1
 
 
24
 
25
  # Start app (with the patch applied)
26
- CMD ["python", "main.py"]
 
21
  # Set environment variables
22
  ENV PYTHONPATH="/app"
23
  ENV PYTHONUNBUFFERED=1
24
+ ENV API_URL="/api"
25
+ ENV MOCK_API="false"
26
 
27
  # Start app (with the patch applied)
28
+ CMD ["python", "app.py"]
README.md CHANGED
@@ -5,7 +5,7 @@ colorFrom: indigo
5
  colorTo: pink
6
  sdk: gradio
7
  sdk_version: "4.44.1"
8
- app_file: main.py
9
  pinned: false
10
  ---
11
 
@@ -19,7 +19,7 @@ FaceForge is ready to run as a Gradio app on [Hugging Face Spaces](https://huggi
19
  1. **Push your code to a public GitHub repository.**
20
  2. **Create a new Space** at https://huggingface.co/spaces (choose the Gradio SDK or Docker SDK).
21
  3. **Add your `requirements.txt` and the provided `Dockerfile` to your repo.**
22
- 4. **Set the entrypoint to `main.py`** (which handles both the API and UI components).
23
  5. **Deploy!** Your app will be live at `https://<your-username>.hf.space`.
24
 
25
  ### Example Dockerfile (already included):
@@ -45,10 +45,21 @@ pip install -r requirements.txt
45
  python main.py
46
  ```
47
 
48
- To run in API-only mode:
49
- ```bash
50
- FACEFORGE_MODE=api python main.py
51
- ```
 
 
 
 
 
 
 
 
 
 
 
52
 
53
  ## Features
54
  - Latent space exploration and manipulation
@@ -78,11 +89,30 @@ TypeError: argument of type 'bool' is not iterable
78
 
79
  The application includes a patch that should fix the issue automatically. This patch addresses a known issue with schema processing in older Gradio versions.
80
 
81
- Recommended steps to diagnose UI issues:
82
- 1. Check the logs for detailed error information
83
- 2. Ensure you're using Gradio version 4.44.1 or newer (`pip install --upgrade gradio==4.44.1`)
84
- 3. Try running in API-only mode to isolate the issue
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
 
86
  ## Notes
87
- - The backend and frontend are fully integrated for Spaces.
88
  - For custom model integration, edit the core and backend modules as needed.
 
5
  colorTo: pink
6
  sdk: gradio
7
  sdk_version: "4.44.1"
8
+ app_file: app.py
9
  pinned: false
10
  ---
11
 
 
19
  1. **Push your code to a public GitHub repository.**
20
  2. **Create a new Space** at https://huggingface.co/spaces (choose the Gradio SDK or Docker SDK).
21
  3. **Add your `requirements.txt` and the provided `Dockerfile` to your repo.**
22
+ 4. **Set the entrypoint to `app.py`** (which integrates both the API and UI components).
23
  5. **Deploy!** Your app will be live at `https://<your-username>.hf.space`.
24
 
25
  ### Example Dockerfile (already included):
 
45
  python main.py
46
  ```
47
 
48
+ This will start the integrated application with both the API and UI components available:
49
+ - UI accessible at http://localhost:7860/
50
+ - API accessible at http://localhost:7860/api/
51
+
52
+ ## Architecture
53
+
54
+ FaceForge uses a modular architecture:
55
+
56
+ 1. **Core Components** (`faceforge_core/`): Core algorithms and utilities
57
+ 2. **API Layer** (`faceforge_api/`): FastAPI endpoints for model interaction
58
+ 3. **UI Layer** (`faceforge_ui/`): Gradio interface for user interaction
59
+
60
+ The main application integrates these components into a single FastAPI application where:
61
+ - The API is mounted at `/api/`
62
+ - The Gradio UI is mounted at the root path `/`
63
 
64
  ## Features
65
  - Latent space exploration and manipulation
 
89
 
90
  The application includes a patch that should fix the issue automatically. This patch addresses a known issue with schema processing in older Gradio versions.
91
 
92
+ ### Common Issues:
93
+
94
+ #### API Connection Errors
95
+
96
+ If you see errors like:
97
+ ```
98
+ Request failed: HTTPConnectionPool(host='localhost', port=8000): Max retries exceeded with url: /generate
99
+ ```
100
+
101
+ This means the UI can't connect to the API. In the integrated version, the API is available at `/api/generate` rather than a separate server.
102
+
103
+ To fix this:
104
+ 1. Ensure you're using the integrated version by running `python main.py`
105
+ 2. If you need to run the API separately, set the API_URL environment variable:
106
+ ```bash
107
+ API_URL=http://localhost:8000 python faceforge_ui/app.py
108
+ ```
109
+
110
+ #### Environment Variables
111
+
112
+ - `MOCK_API`: Set to "true" to use mock API responses (for testing without API)
113
+ - `API_URL`: Override the API endpoint URL
114
+ - `PORT`: Set the port for the server (default: 7860)
115
 
116
  ## Notes
117
+ - The backend and frontend are fully integrated for Spaces deployment.
118
  - For custom model integration, edit the core and backend modules as needed.
app.py CHANGED
@@ -17,8 +17,8 @@ logging.basicConfig(
17
 
18
  logger = logging.getLogger("faceforge")
19
 
20
- def main():
21
- """Main function to start the FaceForge application."""
22
  try:
23
  # Apply the patch for Gradio
24
  logger.info("Applying Gradio patch...")
@@ -32,21 +32,53 @@ def main():
32
  logger.warning(f"Error applying Gradio patch: {e}")
33
  logger.debug(traceback.format_exc())
34
 
35
- # Import and run the UI app by default for HF Spaces
36
- logger.info("Starting in UI mode for Hugging Face Spaces")
 
 
 
 
 
 
37
  from faceforge_ui.app import create_demo
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  demo = create_demo()
39
- demo.launch(server_name="0.0.0.0", share=False)
40
-
41
- except ImportError as e:
42
- logger.critical(f"Import error: {e}. Please check your dependencies.")
43
- logger.debug(traceback.format_exc())
44
- sys.exit(1)
45
  except Exception as e:
46
- logger.critical(f"Unexpected error: {e}")
47
  logger.debug(traceback.format_exc())
48
- sys.exit(1)
 
 
 
 
49
 
50
- # This module is imported by Hugging Face Spaces
51
  if __name__ == "__main__":
52
- main()
 
 
 
 
 
17
 
18
  logger = logging.getLogger("faceforge")
19
 
20
+ def create_app():
21
+ """Creates and configures the integrated FastAPI application with both API and UI components."""
22
  try:
23
  # Apply the patch for Gradio
24
  logger.info("Applying Gradio patch...")
 
32
  logger.warning(f"Error applying Gradio patch: {e}")
33
  logger.debug(traceback.format_exc())
34
 
35
+ # Set up FastAPI application with both API and UI
36
+ logger.info("Setting up FastAPI application with API and UI for Hugging Face Spaces")
37
+ from fastapi import FastAPI
38
+ from fastapi.middleware.cors import CORSMiddleware
39
+ import gradio as gr
40
+
41
+ # Import the API and UI components
42
+ from faceforge_api.main import app as api_app
43
  from faceforge_ui.app import create_demo
44
+
45
+ # Create a new FastAPI application that will serve as the main app
46
+ app = FastAPI(title="FaceForge")
47
+
48
+ # Add CORS middleware
49
+ app.add_middleware(
50
+ CORSMiddleware,
51
+ allow_origins=["*"],
52
+ allow_credentials=True,
53
+ allow_methods=["*"],
54
+ allow_headers=["*"],
55
+ )
56
+
57
+ # Mount the API under /api
58
+ logger.info("Mounting API at /api")
59
+ app.mount("/api", api_app)
60
+
61
+ # Create Gradio UI
62
+ logger.info("Creating Gradio UI")
63
  demo = create_demo()
64
+
65
+ # Mount Gradio UI
66
+ logger.info("Mounting Gradio UI")
67
+ gr_app = gr.mount_gradio_app(app, demo, path="/")
68
+
69
+ return app
70
  except Exception as e:
71
+ logger.critical(f"Failed to create app: {e}")
72
  logger.debug(traceback.format_exc())
73
+ raise
74
+
75
+ # Create the app for Hugging Face Spaces
76
+ # This is the entry point that Hugging Face Spaces will use
77
+ app = create_app()
78
 
 
79
  if __name__ == "__main__":
80
+ # If this file is run directly, start the server
81
+ import uvicorn
82
+ port = int(os.environ.get("PORT", 7860))
83
+ logger.info(f"Starting integrated server on port {port}")
84
+ uvicorn.run(app, host="0.0.0.0", port=port)
faceforge_api/main.py CHANGED
@@ -49,7 +49,13 @@ class AttributeDirectionRequest(BaseModel):
49
 
50
  # --- FastAPI app ---
51
 
52
- app = FastAPI()
 
 
 
 
 
 
53
 
54
  # Add CORS middleware to allow requests from any origin
55
  app.add_middleware(
@@ -78,7 +84,7 @@ async def error_handling_middleware(request: Request, call_next):
78
 
79
  @app.get("/")
80
  def read_root():
81
- logger.debug("Root endpoint called")
82
  return {"message": "FaceForge API is running"}
83
 
84
  @app.post("/generate")
 
49
 
50
  # --- FastAPI app ---
51
 
52
+ app = FastAPI(
53
+ title="FaceForge API",
54
+ description="API for latent space exploration and manipulation",
55
+ version="1.0.0",
56
+ # Important: set root_path to empty to ensure routes work correctly when mounted under /api
57
+ root_path=""
58
+ )
59
 
60
  # Add CORS middleware to allow requests from any origin
61
  app.add_middleware(
 
84
 
85
  @app.get("/")
86
  def read_root():
87
+ logger.debug("API root endpoint called")
88
  return {"message": "FaceForge API is running"}
89
 
90
  @app.post("/generate")
faceforge_ui/app.py CHANGED
@@ -23,7 +23,9 @@ logging.getLogger("gradio").setLevel(logging.DEBUG)
23
  logging.getLogger("gradio_client").setLevel(logging.DEBUG)
24
 
25
  # API configuration
26
- API_URL = os.environ.get("API_URL", "http://localhost:8000")
 
 
27
  logger.info(f"Using API URL: {API_URL}")
28
 
29
  def generate_image(prompts, mode, player_x, player_y):
@@ -48,7 +50,24 @@ def generate_image(prompts, mode, player_x, player_y):
48
 
49
  # Make API call
50
  try:
51
- resp = requests.post(f"{API_URL}/generate", json=req, timeout=30)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  logger.debug(f"API response status: {resp.status_code}")
53
 
54
  if resp.ok:
@@ -89,7 +108,10 @@ def generate_image(prompts, mode, player_x, player_y):
89
 
90
  except requests.exceptions.RequestException as e:
91
  logger.error(f"Request failed: {e}")
92
- return None, f"Request failed: {str(e)}"
 
 
 
93
 
94
  except Exception as e:
95
  logger.error(f"Unexpected error: {e}")
 
23
  logging.getLogger("gradio_client").setLevel(logging.DEBUG)
24
 
25
  # API configuration
26
+ # In HF Spaces, we need to use a relative path since both UI and API run on the same server
27
+ # For local development with separate servers, the env var can be set to http://localhost:8000
28
+ API_URL = os.environ.get("API_URL", "/api")
29
  logger.info(f"Using API URL: {API_URL}")
30
 
31
  def generate_image(prompts, mode, player_x, player_y):
 
50
 
51
  # Make API call
52
  try:
53
+ # For debugging/testing, create a mock image if API is not available
54
+ if API_URL == "/api" and os.environ.get("MOCK_API", "false").lower() == "true":
55
+ logger.debug("Using mock API response")
56
+ # Create a test image
57
+ img = Image.new("RGB", (256, 256), (int(player_x*128)+128, 100, int(player_y*128)+128))
58
+ return img, "Image generated using mock API"
59
+
60
+ # Determine the base URL for the API
61
+ if API_URL.startswith("/"):
62
+ # Relative URL, construct the full URL based on the request context
63
+ # For Gradio apps, we'll just use a relative path
64
+ base_url = API_URL
65
+ else:
66
+ # Absolute URL, use as is
67
+ base_url = API_URL
68
+
69
+ logger.debug(f"Making request to: {base_url}/generate")
70
+ resp = requests.post(f"{base_url}/generate", json=req, timeout=30)
71
  logger.debug(f"API response status: {resp.status_code}")
72
 
73
  if resp.ok:
 
108
 
109
  except requests.exceptions.RequestException as e:
110
  logger.error(f"Request failed: {e}")
111
+ # Fall back to a test image
112
+ logger.debug("Falling back to test image")
113
+ img = Image.new("RGB", (256, 256), (int(player_x*128)+128, 100, int(player_y*128)+128))
114
+ return img, f"API connection failed (using test image): {str(e)}"
115
 
116
  except Exception as e:
117
  logger.error(f"Unexpected error: {e}")
main.py CHANGED
@@ -32,17 +32,45 @@ def main():
32
  logger.warning(f"Error applying Gradio patch: {e}")
33
  logger.debug(traceback.format_exc())
34
 
35
- # Import and run the appropriate app
36
- if os.environ.get("FACEFORGE_MODE", "ui").lower() == "api":
37
- logger.info("Starting in API mode")
38
- from faceforge_api.main import app
39
- import uvicorn
40
- uvicorn.run(app, host="0.0.0.0", port=8000)
41
- else:
42
- logger.info("Starting in UI mode")
43
- from faceforge_ui.app import create_demo
44
- demo = create_demo()
45
- demo.launch(server_name="0.0.0.0", share=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
  except ImportError as e:
48
  logger.critical(f"Import error: {e}. Please check your dependencies.")
 
32
  logger.warning(f"Error applying Gradio patch: {e}")
33
  logger.debug(traceback.format_exc())
34
 
35
+ # Set up FastAPI application with both API and UI
36
+ logger.info("Setting up FastAPI application with API and UI")
37
+ from fastapi import FastAPI
38
+ from fastapi.middleware.cors import CORSMiddleware
39
+ import gradio as gr
40
+
41
+ # Import the API and UI components
42
+ from faceforge_api.main import app as api_app
43
+ from faceforge_ui.app import create_demo
44
+
45
+ # Create a new FastAPI application that will serve as the main app
46
+ app = FastAPI(title="FaceForge")
47
+
48
+ # Add CORS middleware
49
+ app.add_middleware(
50
+ CORSMiddleware,
51
+ allow_origins=["*"],
52
+ allow_credentials=True,
53
+ allow_methods=["*"],
54
+ allow_headers=["*"],
55
+ )
56
+
57
+ # Mount the API under /api
58
+ logger.info("Mounting API at /api")
59
+ app.mount("/api", api_app)
60
+
61
+ # Create Gradio UI
62
+ logger.info("Creating Gradio UI")
63
+ demo = create_demo()
64
+
65
+ # Mount Gradio UI
66
+ logger.info("Mounting Gradio UI")
67
+ gr_app = gr.mount_gradio_app(app, demo, path="/")
68
+
69
+ # Configure server
70
+ import uvicorn
71
+ port = int(os.environ.get("PORT", 7860))
72
+ logger.info(f"Starting integrated server on port {port}")
73
+ uvicorn.run(app, host="0.0.0.0", port=port)
74
 
75
  except ImportError as e:
76
  logger.critical(f"Import error: {e}. Please check your dependencies.")