#!/bin/bash

set -e

sudo -u ec2-user -i <<'EOF'
mkdir -p /home/ec2-user/SageMaker/scripts
cd /home/ec2-user/SageMaker/scripts

# Create notebook code
cat <<EOT > train_and_deploy_model.ipynb
{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install scikit-learn\\n",
    "import pandas as pd\\n",
    "from sklearn.decomposition import TruncatedSVD\\n",
    "from sklearn.metrics.pairwise import cosine_similarity\\n",
    "import boto3\\n",
    "from io import StringIO\\n",
    "import pickle\\n",
    "import tarfile\\n",
    "\\n",
    "# Inference script\\n",
    "inference_script = \"\"\"\\n",
    "import pickle\\n",
    "import pandas as pd\\n",
    "import numpy as np\\n",
    "import logging\\n",
    "import subprocess\\n",
    "import sys\\n",
    "\\n",
    "logger = logging.getLogger()\\n",
    "logger.setLevel(logging.INFO)\\n",
    "\\n",
    "subprocess.check_call([sys.executable, \"-m\", \"pip\", \"install\", \"--upgrade\", \"pip\"])\\n",
    "\\n",
    "subprocess.check_call([sys.executable, \"-m\", \"pip\", \"install\", \"pandas==2.0.3\"])\\n",
    "\\n",
    "# Log versions of libraries\\n",
    "logger.info(f\"Pandas version: {pd.__version__}\")\\n",
    "\\n",
    "\\n",
    "# Define the inference functions\\n",
    "def model_fn(model_dir):\\n",
    "    \\n",
    "    # Load all required components for prediction\\n",
    "    with open(f\"{model_dir}/model.pkl\", 'rb') as f:\\n",
    "        svd = pd.read_pickle(f)\\n",
    "        \\n",
    "    with open(f\"{model_dir}/cosine_sim.pkl\", 'rb') as f:\\n",
    "        cosine_sim = pd.read_pickle(f)\\n",
    "        \\n",
    "    with open(f\"{model_dir}/ui_matrix.pkl\", 'rb') as f:\\n",
    "        ui_matrix = pd.read_pickle(f)\\n",
    "        \\n",
    "    return svd, cosine_sim, ui_matrix\\n",
    "\\n",
    "def input_fn(request_body, request_content_type):\\n",
    "    return int(request_body)\\n",
    "\\n",
    "def predict_fn(input_data, model):\\n",
    "    svd, cosine_sim, ui_matrix = model\\n",
    "    user_id = input_data\\n",
    "    user_idx = user_id - 1\\n",
    "    sim_scores = list(enumerate(cosine_sim[user_idx]))\\n",
    "    sim_scores = sorted(sim_scores, key=lambda x: x[1], reverse=True)\\n",
    "    top_users_indices = [i for i, score in sim_scores[1:6]]\\n",
    "    top_users_ratings = ui_matrix.iloc[top_users_indices].sum(axis=0).sort_values(ascending=False)\\n",
    "    recommended_items = top_users_ratings.index[:5].tolist()\\n",
    "    return recommended_items\\n",
    "\\n",
    "def output_fn(prediction, content_type):\\n",
    "    return str(prediction)\\n",
    "\"\"\"\\n",
    "\\n",
    "# Save the inference script to a file\\n",
    "with open('inference.py', 'w') as f:\\n",
    "    f.write(inference_script)\\n",
    "\\n",
    "# Initialize a session using Amazon S3\\n",
    "s3 = boto3.client('s3')\\n",
    "bucket_name = '${s3_bucket_name}'\\n",
    "\\n",
    "obj = s3.get_object(Bucket=bucket_name, Key='product_ratings.csv') \\n",
    "\\n",
    "# Load the dataset\\n",
    "file_content = obj['Body'].read().decode('utf-8')\\n",
    "df = pd.read_csv(StringIO(file_content))\\n",
    "\\n",
    "# Creating a user-item matrix\\n",
    "ui_matrix = df.pivot_table(index='userId', columns='productId', values='rating', fill_value=0)\\n",
    "\\n",
    "# Apply Truncated SVD\\n",
    "svd = TruncatedSVD(n_components=5, random_state=42)\\n",
    "matrix_reduced = svd.fit_transform(ui_matrix)\\n",
    "\\n",
    "# Calculate the cosine similarity\\n",
    "cosine_sim = cosine_similarity(matrix_reduced)\\n",
    "\\n",
    "# Assuming `svd` and `cosine_sim` have been defined and trained as in your notebook\\n",
    "# Save the models and matrices\\n",
    "with open('model.pkl', 'wb') as f:\\n",
    "    pickle.dump(svd, f)\\n",
    "\\n",
    "with open('cosine_sim.pkl', 'wb') as f:\\n",
    "    pickle.dump(cosine_sim, f)\\n",
    "\\n",
    "with open('ui_matrix.pkl', 'wb') as f:\\n",
    "    pickle.dump(ui_matrix, f)\\n",
    "\\n",
    "# Create a tar.gz file\\n",
    "with tarfile.open('model.tar.gz', 'w:gz') as tar:\\n",
    "    tar.add('ui_matrix.pkl')\\n",
    "    tar.add('cosine_sim.pkl')\\n",
    "    tar.add('model.pkl')\\n",
    "\\n",
    "# Upload the model file to S3\\n",
    "s3.upload_file('model.tar.gz', bucket_name, 'model.tar.gz')\\n",
    "\\n",
    "import sagemaker\\n",
    "from sagemaker.sklearn.model import SKLearnModel\\n",
    "\\n",
    "# Load the SageMaker session and role\\n",
    "sagemaker_session = sagemaker.Session()\\n",
    "role = sagemaker.get_execution_role()\\n",
    "\\n",
    "# Create a SKLearn model\\n",
    "sklearn_model = SKLearnModel(model_data=f's3://{bucket_name}/model.tar.gz',\\n",
    "                             role=role,\\n",
    "                             entry_point='inference.py',\\n",
    "                             framework_version='1.2-1')\\n",
    "\\n",
    "# Deploy the model to an endpoint\\n",
    "endpoint_name = 'reccomendation-system-endpoint'\\n",
    "predictor = sklearn_model.deploy(instance_type='ml.m4.xlarge', initial_instance_count=1, endpoint_name=endpoint_name)\\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
EOT

# Run the notebook to train and deploy the model
nohup jupyter nbconvert --to notebook --execute train_and_deploy_model.ipynb &
EOF
