Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
souvik03-136 committed Nov 8, 2024
1 parent 008078d commit 2e8b610
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 100,098 deletions.
7 changes: 5 additions & 2 deletions demand_forecast/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ WORKDIR /app
# Copy the current directory contents into the container at /app
COPY . /app

# Install any necessary dependencies
# Upgrade pip to the latest version before installing dependencies
RUN pip install --upgrade pip

# Install necessary dependencies
RUN pip install --no-cache-dir -r requirements.txt

# Expose port 5000 for Flask to run on
EXPOSE 5000

# Run the application
# Set the default command to run the application
CMD ["python", "app.py"]
Binary file modified demand_forecast/__pycache__/bokeh_forecast.cpython-310.pyc
Binary file not shown.
97 changes: 66 additions & 31 deletions demand_forecast/app.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,63 @@
from flask import Flask, request, jsonify, send_file
from flask_cors import CORS
from pathlib import Path
from forecasting import predict_demand, check_stock_and_alert
from bokeh_forecast import create_bokeh_plots
from utils import load_data
import os
import logging

app = Flask(__name__)

# Directory to store uploaded files and plots
UPLOAD_FOLDER = 'uploads'
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
# Enable CORS
CORS(app, resources={r"/*": {"origins": "*"}})

# Configure upload folder and file size limit
UPLOAD_FOLDER = Path(os.getenv('UPLOAD_FOLDER', 'uploads'))
UPLOAD_FOLDER.mkdir(parents=True, exist_ok=True)
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16 MB

# Logging setup
app.logger.setLevel(logging.INFO)

# Allowed file extensions
ALLOWED_EXTENSIONS = {'csv', 'xlsx'}
data_file_path = None


def allowed_file(filename):
"""Check if the uploaded file has an allowed extension."""
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS


@app.route('/upload', methods=['POST'])
def upload_file():
global data_file_path

if 'file' not in request.files:
return jsonify({"error": "No file part in the request"}), 400

file = request.files['file']
if file.filename == '':
return jsonify({"error": "No file selected"}), 400

# Save the uploaded file
data_file_path = os.path.join(UPLOAD_FOLDER, file.filename)
file.save(data_file_path)
return jsonify({"message": "File uploaded successfully", "file_path": data_file_path})
if not allowed_file(file.filename):
return jsonify({"error": "Only .csv and .xlsx files are allowed"}), 400

try:
# Save the new file and overwrite the existing one
data_file_path = UPLOAD_FOLDER / file.filename
file.save(data_file_path)

# Cleanup old plots
for plot in UPLOAD_FOLDER.glob("*.html"):
plot.unlink()

app.logger.info(f"File uploaded successfully: {data_file_path}")
return jsonify({"message": "File uploaded successfully", "file_path": str(data_file_path)})
except Exception as e:
app.logger.error(f"File upload error: {e}")
return jsonify({"error": "Failed to upload file"}), 500


@app.route('/forecast', methods=['POST'])
Expand All @@ -37,50 +69,53 @@ def forecast():
data = request.get_json()
item_id = data.get('item_id')

# Validate item_id
if item_id is None:
return jsonify({"error": "Item ID is required."}), 400

# Load data
df = load_data(data_file_path)
try:
# Load data
df = load_data(data_file_path)

# Check if item_id exists in the dataset
if item_id not in df['item_id'].values:
print(f"Item ID {item_id} not found in the dataset")
return jsonify({"error": f"Item ID {item_id} not found in the dataset."}), 404
# Validate item ID
if item_id not in df['item_id'].values:
app.logger.error(f"Item ID {item_id} not found in the dataset")
return jsonify({"error": f"Item ID {item_id} not found in the dataset."}), 404

# Make predictions
future_months, predicted_demand = predict_demand(df, item_id)
# Generate predictions
future_months, predicted_demand = predict_demand(df, item_id)

if predicted_demand is not None:
alerts = check_stock_and_alert(df, item_id, predicted_demand, future_months)
if predicted_demand is None:
return jsonify({"error": f"Could not generate forecasts for item ID {item_id}."}), 500

# Create and save Bokeh plots
# Generate alerts and plots
alerts = check_stock_and_alert(df, item_id, predicted_demand, future_months)
plot_path = create_bokeh_plots(df, item_id, future_months, predicted_demand)

# Convert arrays to lists for JSON serialization
# Safely convert variables for JSON serialization
response = {
"future_months": future_months.tolist() if hasattr(future_months, 'tolist') else future_months,
"predicted_demand": predicted_demand.tolist() if hasattr(predicted_demand, 'tolist') else predicted_demand,
"future_months": future_months if isinstance(future_months, list) else future_months.tolist(),
"predicted_demand": predicted_demand if isinstance(predicted_demand, list) else predicted_demand.tolist(),
"alerts": alerts,
"plot_url": f"/plot/{item_id}" # URL to view the plot
}
else:
response = {
"error": f"Could not generate forecasts for item ID {item_id}."
"plot_url": f"/plot/{item_id}"
}

return jsonify(response)
app.logger.info(f"Forecast successfully generated for item ID {item_id}")
return jsonify(response)

except Exception as e:
app.logger.error(f"Error during forecasting: {e}")
return jsonify({"error": "An error occurred during forecasting. Please try again."}), 500



@app.route('/plot/<item_id>')
def plot(item_id):
plot_path = f"uploads/demand_forecast_{item_id}.html"
if os.path.exists(plot_path):
plot_path = UPLOAD_FOLDER / f"demand_forecast_{item_id}.html"
if plot_path.exists():
return send_file(plot_path)
else:
return jsonify({"error": "Plot not found"}), 404


if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000, debug=True)
app.run(host='0.0.0.0', port=5000, debug=True)
Binary file modified demand_forecast/best_model.keras
Binary file not shown.
8 changes: 4 additions & 4 deletions demand_forecast/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
flask==2.3.2
Werkzeug==2.3.3
pandas==2.1.3
numpy>=2.1.0
pandas>=2.1,<2.2
numpy>=1.21,<2.1
statsmodels==0.14.0
tensorflow>=2.14.0,<2.18.0
scikit-learn==1.2.2
bokeh==3.1.1

flask-cors==3.0.10
scikit-learn>=0.24.0,<1.3.0
Loading

0 comments on commit 2e8b610

Please sign in to comment.