{"repo": "berry2012/prompt-based-moderation-with-llm", "files": {"notebooks/Universal_llm_harmfull-detection-v1.ipynb": {"74fd764bb663c5032842e7ebdaad62af9424e30b": {"t": 1786068259.7549412, "n": 160615, "h": "575f6ed756e57b53", "c": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"id\": \"05ab8959-d5f1-4abb-bf99-760c9a2d7fae\",\n \"metadata\": {},\n \"source\": [\n \"# Prompt Based Harmful Message detection using MCP and LLM\"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"id\": \"3d306d00-e469-49fc-a076-8973c28c1591\",\n \"metadata\": {},\n \"source\": [\n \"https://docs.gpt4all.io/gpt4all_desktop/models.html#explore-models\\n\",\n \"\\n\",\n \"https://github.com/deepseek-ai/DeepSeek-R1\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": 1,\n \"id\": \"c2c4ceaa-2f72-475d-bd97-fed66f86f124\",\n \"metadata\": {},\n \"outputs\": [\n {\n \"name\": \"stdout\",\n \"output_type\": \"stream\",\n \"text\": [\n \"Requirement already satisfied: datasets in /opt/conda/lib/python3.12/site-packages (4.0.0)\\n\",\n \"Requirement already satisfied: pandas in /opt/conda/lib/python3.12/site-packages (2.2.3)\\n\",\n \"Requirement already satisfied: scikit-learn in /opt/conda/lib/python3.12/site-packages (1.5.2)\\n\",\n \"Requirement already satisfied: matplotlib in /opt/conda/lib/python3.12/site-packages (3.10.3)\\n\",\n \"Requirement already satisfied: seaborn in /opt/conda/lib/python3.12/site-packages (0.13.2)\\n\",\n \"Requirement already satisfied: openai in /opt/conda/lib/python3.12/site-packages (1.99.7)\\n\",\n \"Requirement already satisfied: tqdm in /opt/conda/lib/python3.12/site-packages (4.67.1)\\n\",\n \"Requirement already satisfied: filelock in /opt/conda/lib/python3.12/site-packages (from datasets) (3.18.0)\\n\",\n \"Requirement already satisfied: numpy>=1.17 in /opt/conda/lib/python3.12/site-packages (from datasets) (1.26.4)\\n\",\n \"Requirement already satisfied: pyarrow>=15.0.0 in /opt/conda/lib/python3.12/site-packages (from datasets) (19.0.1)\\n\",\n \"Requirement already satisfied: dill<0.3.9,>=0.3.0 in /opt/conda/lib/python3.12/site-packages (from datasets) (0.3.8)\\n\",\n \"Requirement already satisfied: requests>=2.32.2 in /opt/conda/lib/python3.12/site-packages (from datasets) (2.32.3)\\n\",\n \"Requirement already satisfied: xxhash in /opt/conda/lib/python3.12/site-packages (from datasets) (3.5.0)\\n\",\n \"Requirement already satisfied: multiprocess<0.70.17 in /opt/conda/lib/python3.12/site-packages (from datasets) (0.70.16)\\n\",\n \"Requirement already satisfied: fsspec<=2025.3.0,>=2023.1.0 in /opt/conda/lib/python3.12/site-packages (from fsspec[http]<=2025.3.0,>=2023.1.0->datasets) (2024.10.0)\\n\",\n \"Requirement already satisfied: huggingface-hub>=0.24.0 in /opt/conda/lib/python3.12/site-packages (from datasets) (0.31.4)\\n\",\n \"Requirement already satisfied: packaging in /opt/conda/lib/python3.12/site-packages (from datasets) (24.2)\\n\",\n \"Requirement already satisfied: pyyaml>=5.1 in /opt/conda/lib/python3.12/site-packages (from datasets) (6.0.2)\\n\",\n \"Requirement already satisfied: python-dateutil>=2.8.2 in /opt/conda/lib/python3.12/site-packages (from pandas) (2.9.0.post0)\\n\",\n \"Requirement already satisfied: pytz>=2020.1 in /opt/conda/lib/python3.12/site-packages (from pandas) (2024.2)\\n\",\n \"Requirement already satisfied: tzdata>=2022.7 in /opt/conda/lib/python3.12/site-packages (from pandas) (2025.2)\\n\",\n \"Requirement already satisfied: scipy>=1.6.0 in /opt/conda/lib/python3.12/site-packages (from scikit-learn) (1.15.2)\\n\",\n \"Requirement already satisfied: joblib>=1.2.0 in /opt/conda/lib/python3.12/site-packages (from scikit-learn) (1.5.0)\\n\",\n \"Requirement already satisfied: threadpoolctl>=3.1.0 in /opt/conda/lib/python3.12/site-packages (from scikit-learn) (3.6.0)\\n\",\n \"Requirement already satisfied: contourpy>=1.0.1 in /opt/conda/lib/python3.12/site-packages (from matplotlib) (1.3.2)\\n\",\n \"Requirement already satisfied: cycler>=0.10 in /opt/conda/lib/python3.12/site-packages (from matplotlib) (0.12.1)\\n\",\n \"Requirement already satisfied: fonttools>=4.22.0 in /opt/conda/lib/python3.12/site-packages (from matplotlib) (4.58.0)\\n\",\n \"Requirement already satisfied: kiwisolver>=1.3.1 in /opt/conda/lib/python3.12/site-packages (from matplotlib) (1.4.8)\\n\",\n \"Requirement already satisfied: pillow>=8 in /opt/conda/lib/python3.12/site-packages (from matplotlib) (11.2.1)\\n\",\n \"Requirement already satisfied: pyparsing>=2.3.1 in /opt/conda/lib/python3.12/site-packages (from matplotlib) (3.2.3)\\n\",\n \"Requirement already satisfied: anyio<5,>=3.5.0 in /opt/conda/lib/python3.12/site-packages (from openai) (4.9.0)\\n\",\n \"Requirement already satisfied: distro<2,>=1.7.0 in /opt/conda/lib/python3.12/site-packages (from openai) (1.9.0)\\n\",\n \"Requirement already satisfied: httpx<1,>=0.23.0 in /opt/conda/lib/python3.12/site-packages (from openai) (0.28.1)\\n\",\n \"Requirement already satisfied: jiter<1,>=0.4.0 in /opt/conda/lib/python3.12/site-packages (from openai) (0.10.0)\\n\",\n \"Requirement already satisfied: pydantic<3,>=1.9.0 in /opt/conda/lib/python3.12/site-packages (from openai) (2.11.4)\\n\",\n \"Requirement already satisfied: sniffio in /opt/conda/lib/python3.12/site-packages (from openai) (1.3.1)\\n\",\n \"Requirement already satisfied: typing-extensions<5,>=4.11 in /opt/conda/lib/python3.12/site-packages (from openai) (4.13.2)\\n\",\n \"Requirement already satisfied: idna>=2.8 in /opt/conda/lib/python3.12/site-packages (from anyio<5,>=3.5.0->openai) (3.10)\\n\",\n \"Requirement already satisfied: aiohttp!=4.0.0a0,!=4.0.0a1 in /opt/conda/lib/python3.12/site-packages (from fsspec[http]<=2025.3.0,>=2023.1.0->datasets) (3.9.5)\\n\",\n \"Requirement already satisfied: certifi in /opt/conda/lib/python3.12/site-packages (from httpx<1,>=0.23.0->openai) (2025.4.26)\\n\",\n \"Requirement already satisfied: httpcore==1.* in /opt/conda/lib/python3.12/site-packages (from httpx<1,>=0.23.0->openai) (1.0.9)\\n\",\n \"Requirement already satisfied: h11>=0.16 in /opt/conda/lib/python3.12/site-packages (from httpcore==1.*->httpx<1,>=0.23.0->openai) (0.16.0)\\n\",\n \"Requirement already satisfied: annotated-types>=0.6.0 in /opt/conda/lib/python3.12/site-packages (from pydantic<3,>=1.9.0->openai) (0.7.0)\\n\",\n \"Requirement already satisfied: pydantic-core==2.33.2 in /opt/conda/lib/python3.12/site-packages (from pydantic<3,>=1.9.0->openai) (2.33.2)\\n\",\n \"Requirement already satisfied: typing-inspection>=0.4.0 in /opt/conda/lib/python3.12/site-packages (from pydantic<3,>=1.9.0->openai) (0.4.0)\\n\",\n \"Requirement already satisfied: six>=1.5 in /opt/conda/lib/python3.12/site-packages (from python-dateutil>=2.8.2->pandas) (1.17.0)\\n\",\n \"Requirement already satisfied: charset_normalizer<4,>=2 in /opt/conda/lib/python3.12/site-packages (from requests>=2.32.2->datasets) (3.4.2)\\n\",\n \"Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/conda/lib/python3.12/site-packages (from requests>=2.32.2->datasets) (2.4.0)\\n\",\n \"Requirement already satisfied: aiosignal>=1.1.2 in /opt/conda/lib/python3.12/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets) (1.3.2)\\n\",\n \"Requirement already satisfied: attrs>=17.3.0 in /opt/conda/lib/python3.12/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets) (23.2.0)\\n\",\n \"Requirement already satisfied: frozenlist>=1.1.1 in /opt/conda/lib/python3.12/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets) (1.6.0)\\n\",\n \"Requirement already satisfied: multidict<7.0,>=4.5 in /opt/conda/lib/python3.12/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets) (6.4.4)\\n\",\n \"Requirement already satisfied: yarl<2.0,>=1.0 in /opt/conda/lib/python3.12/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets) (1.20.0)\\n\",\n \"Requirement already satisfied: propcache>=0.2.1 in /opt/conda/lib/python3.12/site-packages (from yarl<2.0,>=1.0->aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets) (0.3.1)\\n\"\n ]\n }\n ],\n \"source\": [\n \"!pip install datasets pandas scikit-learn matplotlib seaborn openai tqdm\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": 2,\n \"id\": \"a207b785-62c5-4902-8590-227bb412c6aa\",\n \"metadata\": {},\n \"outputs\": [\n {\n \"name\": \"stdout\",\n \"output_type\": \"stream\",\n \"text\": [\n \"Requirement already satisfied: datasets in /opt/conda/lib/python3.12/site-packages (4.0.0)\\n\",\n \"Requirement already satisfied: filelock in /opt/conda/lib/python3.12/site-packages (from datasets) (3.18.0)\\n\",\n \"Requirement already satisfied: numpy>=1.17 in /opt/conda/lib/python3.12/site-packages (from datasets) (1.26.4)\\n\",\n \"Requirement already satisfied: pyarrow>=15.0.0 in /opt/conda/lib/python3.12/site-packages (from datasets) (19.0.1)\\n\",\n \"Requirement already satisfied: dill<0.3.9,>=0.3.0 in /opt/conda/lib/python3.12/site-packages (from datasets) (0.3.8)\\n\",\n \"Requirement already satisfied: pandas in /opt/conda/lib/python3.12/site-packages (from datasets) (2.2.3)\\n\",\n \"Requirement already satisfied: requests>=2.32.2 in /opt/conda/lib/python3.12/site-packages (from datasets) (2.32.3)\\n\",\n \"Requirement already satisfied: tqdm>=4.66.3 in /opt/conda/lib/python3.12/site-packages (from datasets) (4.67.1)\\n\",\n \"Requirement already satisfied: xxhash in /opt/conda/lib/python3.12/site-packages (from datasets) (3.5.0)\\n\",\n \"Requirement already satisfied: multiprocess<0.70.17 in /opt/conda/lib/python3.12/site-packages (from datasets) (0.70.16)\\n\",\n \"Requirement already satisfied: fsspec<=2025.3.0,>=2023.1.0 in /opt/conda/lib/python3.12/site-packages (from fsspec[http]<=2025.3.0,>=2023.1.0->datasets) (2024.10.0)\\n\",\n \"Requirement already satisfied: huggingface-hub>=0.24.0 in /opt/conda/lib/python3.12/site-packages (from datasets) (0.31.4)\\n\",\n \"Requirement already satisfied: packaging in /opt/conda/lib/python3.12/site-packages (from datasets) (24.2)\\n\",\n \"Requirement already satisfied: pyyaml>=5.1 in /opt/conda/lib/python3.12/site-packages (from datasets) (6.0.2)\\n\",\n \"Requirement already satisfied: aiohttp!=4.0.0a0,!=4.0.0a1 in /opt/conda/lib/python3.12/site-packages (from fsspec[http]<=2025.3.0,>=2023.1.0->datasets) (3.9.5)\\n\",\n \"Requirement already satisfied: typing-extensions>=3.7.4.3 in /opt/conda/lib/python3.12/site-packages (from huggingface-hub>=0.24.0->datasets) (4.13.2)\\n\",\n \"Requirement already satisfied: charset_normalizer<4,>=2 in /opt/conda/lib/python3.12/site-packages (from requests>=2.32.2->datasets) (3.4.2)\\n\",\n \"Requirement already satisfied: idna<4,>=2.5 in /opt/conda/lib/python3.12/site-packages (from requests>=2.32.2->datasets) (3.10)\\n\",\n \"Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/conda/lib/python3.12/site-packages (from requests>=2.32.2->datasets) (2.4.0)\\n\",\n \"Requirement already satisfied: certifi>=2017.4.17 in /opt/conda/lib/python3.12/site-packages (from requests>=2.32.2->datasets) (2025.4.26)\\n\",\n \"Requirement already satisfied: python-dateutil>=2.8.2 in /opt/conda/lib/python3.12/site-packages (from pandas->datasets) (2.9.0.post0)\\n\",\n \"Requirement already satisfied: pytz>=2020.1 in /opt/conda/lib/python3.12/site-packages (from pandas->datasets) (2024.2)\\n\",\n \"Requirement already satisfied: tzdata>=2022.7 in /opt/conda/lib/python3.12/site-packages (from pandas->datasets) (2025.2)\\n\",\n \"Requirement already satisfied: aiosignal>=1.1.2 in /opt/conda/lib/python3.12/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets) (1.3.2)\\n\",\n \"Requirement already satisfied: attrs>=17.3.0 in /opt/conda/lib/python3.12/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets) (23.2.0)\\n\",\n \"Requirement already satisfied: frozenlist>=1.1.1 in /opt/conda/lib/python3.12/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets) (1.6.0)\\n\",\n \"Requirement already satisfied: multidict<7.0,>=4.5 in /opt/conda/lib/python3.12/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets) (6.4.4)\\n\",\n \"Requirement already satisfied: yarl<2.0,>=1.0 in /opt/conda/lib/python3.12/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets) (1.20.0)\\n\",\n \"Requirement already satisfied: six>=1.5 in /opt/conda/lib/python3.12/site-packages (from python-dateutil>=2.8.2->pandas->datasets) (1.17.0)\\n\",\n \"Requirement already satisfied: propcache>=0.2.1 in /opt/conda/lib/python3.12/site-packages (from yarl<2.0,>=1.0->aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2025.3.0,>=2023.1.0->datasets) (0.3.1)\\n\"\n ]\n }\n ],\n \"source\": [\n \"!pip install --upgrade datasets\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": 3,\n \"id\": \"1694eb50-3f0f-4fb4-88a2-48ff4f9fd5ee\",\n \"metadata\": {},\n \"outputs\": [\n {\n \"name\": \"stdout\",\n \"output_type\": \"stream\",\n \"text\": [\n \"Requirement already satisfied: gpt4all in /opt/conda/lib/python3.12/site-packages (2.8.2)\\n\",\n \"Requirement already satisfied: requests in /opt/conda/lib/python3.12/site-packages (from gpt4all) (2.32.3)\\n\",\n \"Requirement already satisfied: tqdm in /opt/conda/lib/python3.12/site-packages (from gpt4all) (4.67.1)\\n\",\n \"Requirement already satisfied: charset_normalizer<4,>=2 in /opt/conda/lib/python3.12/site-packages (from requests->gpt4all) (3.4.2)\\n\",\n \"Requirement already satisfied: idna<4,>=2.5 in /opt/conda/lib/python3.12/site-packages (from requests->gpt4all) (3.10)\\n\",\n \"Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/conda/lib/python3.12/site-packages (from requests->gpt4all) (2.4.0)\\n\",\n \"Requirement already satisfied: certifi>=2017.4.17 in /opt/conda/lib/python3.12/site-packages (from requests->gpt4all) (2025.4.26)\\n\"\n ]\n }\n ],\n \"source\": [\n \"!pip install gpt4all\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": 4,\n \"id\": \"93192d2c-1531-4882-ae39-474b76a28f2d\",\n \"metadata\": {},\n \"outputs\": [\n {\n \"data\": {\n \"text/plain\": [\n \"True\"\n ]\n },\n \"execution_count\": 4,\n \"metadata\": {},\n \"output_type\": \"execute_result\"\n }\n ],\n \"source\": [\n \"import os\\n\",\n \"import pandas as pd\\n\",\n \"import numpy as np\\n\",\n \"import matplotlib.pyplot as plt\\n\",\n \"import seaborn as sns\\n\",\n \"import json\\n\",\n \"import re\\n\",\n \"import time\\n\",\n \"from datetime import datetime\\n\",\n \"from tqdm import tqdm\\n\",\n \"from openai import OpenAI\\n\",\n \"from dotenv import load_dotenv\\n\",\n \"try:\\n\",\n \" from gpt4all import GPT4All\\n\",\n \"except ImportError:\\n\",\n \" GPT4All = None\\n\",\n \"from sklearn.metrics import (\\n\",\n \" accuracy_score, precision_score, recall_score, f1_score, roc_auc_score,\\n\",\n \" confusion_matrix, ConfusionMatrixDisplay, classification_report\\n\",\n \")\\n\",\n \"\\n\",\n \"tqdm.pandas()\\n\",\n \"load_dotenv()\"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"id\": \"c7852aa1-d3d2-4b47-a65c-07816e68a31f\",\n \"metadata\": {},\n \"source\": [\n \"# Test - Debugging\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": 5,\n \"id\": \"9930b6e3-a986-433b-9799-1f1c2e5a0b60\",\n \"metadata\": {},\n \"outputs\": [\n {\n \"name\": \"stdout\",\n \"output_type\": \"stream\",\n \"text\": [\n \"Model configuration completed\\n\"\n ]\n }\n ],\n \"source\": [\n \"# Model configuration\\n\",\n \"MODEL_TYPE = \\\"deepseek\\\" # Options: \\\"deepseek\\\", \\\"gpt4all\\\", \\\"mistral\\\"\\n\",\n \"DEEPSEEK_MODEL = \\\"deepseek-ai/DeepSeek-R1-Distill-Llama-8B\\\"\\n\",\n \"GPT4ALL_MODEL = \\\"Meta-Llama-3-8B-Instruct.Q4_0.gguf\\\"\\n\",\n \"GPT4ALL_MODEL_PATH = \\\"/home/sagemaker-user/harmfull-detection/models/\\\"\\n\",\n \"MISTRAL_MODEL = \\\"/tmp/models/mistral-7b-v0-2\\\"\\n\",\n \"# Initialize clients\\n\",\n \"if MODEL_TYPE == \\\"deepseek\\\":\\n\",\n \" client = OpenAI(\\n\",\n \" api_key=os.getenv(\\\"DEEPSEEK_API_KEY\\\"),\\n\",\n \" base_url=\\\"http://k8s-deepseek-deepseek-e92cca8149-b20547a64509f06f.elb.eu-west-1.amazonaws.com/v1\\\"\\n\",\n \" )\\n\",\n \"elif MODEL_TYPE == \\\"mistral\\\":\\n\",\n \" client = OpenAI(\\n\",\n \" api_key=os.getenv(\\\"MISTRAL_API_KEY\\\"),\\n\",\n \" base_url=\\\"http://vllm-serve-svc-pub-288545519.us-west-2.elb.amazonaws.com/v1\\\"\\n\",\n \" ) \\n\",\n \"elif MODEL_TYPE == \\\"gpt4all\\\":\\n\",\n \" if GPT4All is None:\\n\",\n \" raise ImportError(\\\"Install gpt4all: pip install gpt4all\\\")\\n\",\n \" \\n\",\n \" model_file = os.path.join(GPT4ALL_MODEL_PATH, GPT4ALL_MODEL)\\n\",\n \" if os.path.exists(model_file):\\n\",\n \" print(f\\\"Loading cached model from {model_file}\\\")\\n\",\n \" client = GPT4All(model_name=GPT4ALL_MODEL, model_path=GPT4ALL_MODEL_PATH, allow_download=False)\\n\",\n \" else:\\n\",\n \" print(f\\\"Downloading model to {GPT4ALL_MODEL_PATH}\\\")\\n\",\n \" os.makedirs(GPT4ALL_MODEL_PATH, exist_ok=True)\\n\",\n \" client = GPT4All(model_name=GPT4ALL_MODEL, model_path=GPT4ALL_MODEL_PATH)\\n\",\n \"\\n\",\n \"def predict_with_model(text):\\n\",\n \" prompt = f'Analyze this message and respond ONLY with JSON: {{\\\"action\\\": \\\"allow|warn|block|timeout\\\", \\\"confidence\\\": 0.0-1.0, \\\"categories\\\": [\\\"list of violation types]}}: \\\"{text}\\\"'\\n\",\n \" \\n\",\n \" try:\\n\",\n \" if MODEL_TYPE == \\\"deepseek\\\":\\n\",\n \" response = client.chat.completions.create(\\n\",\n \" model=DEEPSEEK_MODEL,\\n\",\n \" messages=[\\n\",\n \" {\\\"role\\\": \\\"system\\\", \\\"content\\\": \\\"You are a content moderation assistant. Respond only with JSON.\\\"},\\n\",\n \" {\\\"role\\\": \\\"user\\\", \\\"content\\\": prompt}\\n\",\n \" ],\\n\",\n \" temperature=0\\n\",\n \" )\\n\",\n \" reply = response.choices[0].message.content.strip()\\n\",\n \" \\n\",\n \" elif MODEL_TYPE == \\\"gpt4all\\\":\\n\",\n \" with client.chat_session():\\n\",\n \" reply = client.generate(prompt, max_tokens=1024)\\n\",\n \" \\n\",\n \" print(\\\"Model output:\\\", reply) # Add before json_match\\n\",\n \" \\n\",\n \" json_match = re.search(r'\\\\{.*\\\\}', reply, re.DOTALL)\\n\",\n \" if json_match:\\n\",\n \" result = json.loads(json_match.group())\\n\",\n \" return 1 if result.get(\\\"action\\\", \\\"\\\").upper() == \\\"BLOCK\\\" else 0\\n\",\n \" return 0\\n\",\n \" except:\\n\",\n \" return 0\\n\",\n \"\\n\",\n \"def measure_inference_times(texts, predict_fn):\\n\",\n \" times, predictions = [], []\\n\",\n \" for text in tqdm(texts, desc=\\\"Processing texts\\\"):\\n\",\n \" start = time.time()\\n\",\n \" pred = predict_fn(text)\\n\",\n \" times.append(time.time() - start)\\n\",\n \" predictions.append(pred)\\n\",\n \" return predictions, times\\n\",\n \"\\n\",\n \"def generate_performance_report(y_true, y_pred, inference_times=None):\\n\",\n \" print(\\\"\\\\nšŸ“Š Classification Report:\\\")\\n\",\n \" print(classification_report(y_true, y_pred))\\n\",\n \" \\n\",\n \" if inference_times:\\n\",\n \" times_ms = np.array(inference_times) * 1000\\n\",\n \" print(f\\\"\\\\nā±ļø Mean inference time: {np.mean(times_ms):.2f}ms\\\")\\n\",\n \"\\n\",\n \"print(\\\"Model configuration completed\\\")\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": 6,\n \"id\": \"80e51a7c-6a73-4598-a8db-1366c368c6fd\",\n \"metadata\": {},\n \"outputs\": [\n {\n \"name\": \"stdout\",\n \"output_type\": \"stream\",\n \"text\": [\n \"Model output: Okay, so I need to analyze this message: \\\"You are a terrible person!\\\" and decide whether to allow, warn, block, or timeout the user, along with the confidence level and the category of violation. \\n\",\n \"\\n\",\n \"First, I should consider what the message is saying. The user is calling someone a terrible person. That's a strong, derogatory term. It's clearly offensive and intended to insult the recipient. Such language can be hurtful and violate community guidelines that promote respect and kindness.\\n\",\n \"\\n\",\n \"Next, I should think about the context. Without knowing the specific situation, I can assume that using such harsh language is not appropriate. It's likely intended to attack or demean someone, which is against most content policies.\\n\",\n \"\\n\",\n \"Now, considering the categories, this definitely falls under \\\"abusive or harassing\\\" behavior. It's a personal attack that can harm others. The confidence level should be high because the message is clearly offensive and not ambiguous.\\n\",\n \"\\n\",\n \"So, the action should be to block the user to prevent further abuse. The confidence is 1.0 because there's no doubt about the violation. The category is \\\"abusive or harassing.\\\"\\n\",\n \"\\n\",\n \"\\n\",\n \"```json\\n\",\n \"{\\n\",\n \" \\\"action\\\": \\\"block\\\",\\n\",\n \" \\\"confidence\\\": 1.0,\\n\",\n \" \\\"categories\\\": [\\\"abusive or harassing\\\"]\\n\",\n \"}\\n\",\n \"```\\n\",\n \"Moderation result (1=toxic, 0=non-toxic): 1\\n\"\n ]\n }\n ],\n \"source\": [\n \"# Test the function\\n\",\n \"test_text = \\\"You are a terrible person!\\\"\\n\",\n \"result = predict_with_model(test_text)\\n\",\n \"print(f\\\"Moderation result (1=toxic, 0=non-toxic): {result}\\\")\\n\"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"id\": \"51190abd-81c1-4706-b05d-d01340c205f8\",\n \"metadata\": {},\n \"source\": [\n \"# Model configuration - DeepSeek R1-Distill-Llama-8B\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": 7,\n \"id\": \"498b0309-5b4e-4d53-bf5c-ad7e6682ec10\",\n \"metadata\": {},\n \"outputs\": [\n {\n \"name\": \"stdout\",\n \"output_type\": \"stream\",\n \"text\": [\n \"Model configuration completed\\n\"\n ]\n }\n ],\n \"source\": [\n \"# Model configuration\\n\",\n \"MODEL_TYPE = \\\"deepseek\\\" # Options: \\\"deepseek\\\", \\\"gpt4all\\\", \\\"mistral\\\"\\n\",\n \"DEEPSEEK_MODEL = \\\"deepseek-ai/DeepSeek-R1-Distill-Llama-8B\\\"\\n\",\n \"GPT4ALL_MODEL = \\\"Meta-Llama-3-8B-Instruct.Q4_0.gguf\\\"\\n\",\n \"GPT4ALL_MODEL_PATH = \\\"/home/sagemaker-user/harmfull-detection/models/\\\"\\n\",\n \"MISTRAL_MODEL = \\\"/tmp/models/mistral-7b-v0-2\\\"\\n\",\n \"# Initialize clients\\n\",\n \"if MODEL_TYPE == \\\"deepseek\\\":\\n\",\n \" client = OpenAI(\\n\",\n \" api_key=os.getenv(\\\"DEEPSEEK_API_KEY\\\"),\\n\",\n \" base_url=\\\"http://k8s-deepseek-deepseek-e92cca8149-b20547a64509f06f.elb.eu-west-1.amazonaws.com/v1\\\"\\n\",\n \" )\\n\",\n \"elif MODEL_TYPE == \\\"mistral\\\":\\n\",\n \" client = OpenAI(\\n\",\n \" api_key=os.getenv(\\\"MISTRAL_API_KEY\\\"),\\n\",\n \" base_url=\\\"http://vllm-serve-svc-pub-288545519.us-west-2.elb.amazonaws.com/v1\\\"\\n\",\n \" ) \\n\",\n \"elif MODEL_TYPE == \\\"gpt4all\\\":\\n\",\n \" if GPT4All is None:\\n\",\n \" raise ImportError(\\\"Install gpt4all: pip install gpt4all\\\")\\n\",\n \" \\n\",\n \" model_file = os.path.join(GPT4ALL_MODEL_PATH, GPT4ALL_MODEL)\\n\",\n \" if os.path.exists(model_file):\\n\",\n \" print(f\\\"Loading cached model from {model_file}\\\")\\n\",\n \" client = GPT4All(model_name=GPT4ALL_MODEL, model_path=GPT4ALL_MODEL_PATH, allow_download=False)\\n\",\n \" else:\\n\",\n \" print(f\\\"Downloading model to {GPT4ALL_MODEL_PATH}\\\")\\n\",\n \" os.makedirs(GPT4ALL_MODEL_PATH, exist_ok=True)\\n\",\n \" client = GPT4All(model_name=GPT4ALL_MODEL, model_path=GPT4ALL_MODEL_PATH)\\n\",\n \"\\n\",\n \"def predict_with_model(text):\\n\",\n \" prompt = f'Analyze this message and respond ONLY with JSON: {{\\\"action\\\": \\\"allow|warn|block|timeout\\\", \\\"confidence\\\": 0.0-1.0, \\\"categories\\\": [\\\"list of violation types\\\"]}}: \\\"{text}\\\"'\\n\",\n \" \\n\",\n \" try:\\n\",\n \" if MODEL_TYPE == \\\"deepseek\\\":\\n\",\n \" response = client.chat.completions.create(\\n\",\n \" model=DEEPSEEK_MODEL,\\n\",\n \" messages=[\\n\",\n \" {\\\"role\\\": \\\"system\\\", \\\"content\\\": \\\"You are a content moderation assistant. Respond only with JSON.\\\"},\\n\",\n \" {\\\"role\\\": \\\"user\\\", \\\"content\\\": prompt}\\n\",\n \" ],\\n\",\n \" temperature=0\\n\",\n \" )\\n\",\n \" reply = response.choices[0].message.content.strip()\\n\",\n \" \\n\",\n \" elif MODEL_TYPE == \\\"gpt4all\\\":\\n\",\n \" with client.chat_session():\\n\",\n \" reply = client.generate(prompt, max_tokens=1024)\\n\",\n \" \\n\",\n \" json_match = re.search(r'\\\\{.*\\\\}', reply, re.DOTALL)\\n\",\n \" if json_match:\\n\",\n \" result = json.loads(json_match.group())\\n\",\n \" return 1 if result.get(\\\"action\\\", \\\"\\\").upper() == \\\"BLOCK\\\" else 0\\n\",\n \" return 0\\n\",\n \" except:\\n\",\n \" return 0\\n\",\n \"\\n\",\n \"def measure_inference_times(texts, predict_fn):\\n\",\n \" times, predictions = [], []\\n\",\n \" for text in tqdm(texts, desc=\\\"Processing texts\\\"):\\n\",\n \" start = time.time()\\n\",\n \" pred = predict_fn(text)\\n\",\n \" times.append(time.time() - start)\\n\",\n \" predictions.append(pred)\\n\",\n \" return predictions, times\\n\",\n \"\\n\",\n \"def generate_performance_report(y_true, y_pred, inference_times=None):\\n\",\n \" print(\\\"\\\\nšŸ“Š Classification Report:\\\")\\n\",\n \" print(classification_report(y_true, y_pred))\\n\",\n \" \\n\",\n \" if inference_times:\\n\",\n \" times_ms = np.array(inference_times) * 1000\\n\",\n \" print(f\\\"\\\\nā±ļø Mean inference time: {np.mean(times_ms):.2f}ms\\\")\\n\",\n \"\\n\",\n \"print(\\\"Model configuration completed\\\")\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": 8,\n \"id\": \"5da3f791-3f7e-4fff-b29c-b71cb7e397f9\",\n \"metadata\": {},\n \"outputs\": [\n {\n \"name\": \"stdout\",\n \"output_type\": \"stream\",\n \"text\": [\n \"Dataset balanced: [20, 20]\\n\"\n ]\n }\n ],\n \"source\": [\n \"# Load and sample data\\n\",\n \"df_test = pd.read_csv(\\\"/home/sagemaker-user/test.csv\\\")\\n\",\n \"n_samples = 20\\n\",\n \"sample_df = pd.concat([\\n\",\n \" df_test[df_test[\\\"label\\\"] == 1].sample(n=n_samples, random_state=42),\\n\",\n \" df_test[df_test[\\\"label\\\"] == 0].sample(n=n_samples, random_state=42)\\n\",\n \"]).sample(frac=1, random_state=42).reset_index(drop=True)\\n\",\n \"\\n\",\n \"print(f\\\"Dataset balanced: {sample_df['label'].value_counts().tolist()}\\\")\\n\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": null,\n \"id\": \"845e26b6-6d9e-41a0-a888-a8bad76ee4bb\",\n \"metadata\": {},\n \"outputs\": [],\n \"source\": []\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": 9,\n \"id\": \"428f7e4d-1013-4a5b-9018-2635b58c993c\",\n \"metadata\": {},\n \"outputs\": [\n {\n \"name\": \"stdout\",\n \"output_type\": \"stream\",\n \"text\": [\n \"\\n\",\n \"šŸš€ Running inference with deepseek...\\n\"\n ]\n },\n {\n \"name\": \"stderr\",\n \"output_type\": \"stream\",\n \"text\": [\n \"Processing texts: 100%|ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆ| 40/40 [07:13<00:00, 10.84s/it]\\n\"\n ]\n }\n ],\n \"source\": [\n \"# Run predictions with timing\\n\",\n \"print(f\\\"\\\\nšŸš€ Running inference with {MODEL_TYPE}...\\\")\\n\",\n \"predictions, inference_times = measure_inference_times(sample_df[\\\"text\\\"], predict_with_model)\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": 10,\n \"id\": \"d02ed8ea-e7a5-4d4b-a3db-9b3843700429\",\n \"metadata\": {},\n \"outputs\": [\n {\n \"name\": \"stdout\",\n \"output_type\": \"stream\",\n \"text\": [\n \"\\n\",\n \"šŸ“Š Metrics:\\n\",\n \"Accuracy: 0.8000\\n\",\n \"Precision: 0.8750\\n\",\n \"Recall: 0.7000\\n\",\n \"F1: 0.7778\\n\",\n \"AUC: 0.8000\\n\",\n \"\\n\",\n \"šŸ“Š Classification Report:\\n\",\n \" precision recall f1-score support\\n\",\n \"\\n\",\n \" 0 0.75 0.90 0.82 20\\n\",\n \" 1 0.88 0.70 0.78 20\\n\",\n \"\\n\",\n \" accuracy 0.80 40\\n\",\n \" macro avg 0.81 0.80 0.80 40\\n\",\n \"weighted avg 0.81 0.80 0.80 40\\n\",\n \"\\n\",\n \"\\n\",\n \"ā±ļø Mean inference time: 10834.75ms\\n\"\n ]\n },\n {\n \"data\": {\n \"image/png\": \"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jBihatWqqVq1anr99dfv+L7ffvstx/vIPH6r2+8lc76TLfdiMpk0cOBAffDBB1q6dKlq1Kihtm3bZnvut99+qwceeEBSxiq6r7/+Wnv37tXkyZNtvm5293mnGMPCwnT9+nUFBgYydwdwABIewMnc3d3VsWNH7du3L8uk4+xkfuifPXs2y7FffvlFZcuWdVhsXl5ekqQbN25Y7b99npAktW3bVhs2bNClS5e0Z88etWzZUs8995xWrlyZ4/hlypTJ8T4kOfRebhUWFqYLFy5o6dKlGjhwYI7nrVy5Uh4eHvr000/Vu3dvtWrVSk2bNs3TNbOb/J2Ts2fPasSIEWrYsKF+++03Pf/883m6JoD/IeEBCoFJkybJMAwNGTIk20m+KSkp2rBhgyTpb3/7myRZJh1n2rt3rxISEtSxY0eHxZW50ujgwYNW+zNjyY67u7tatGihN954Q5K0f//+HM/t2LGjtmzZYklwMr333nsqXrx4vi3ZvvfeexUeHq4ePXpowIABOZ5nMplUrFgxubu7W/Zdu3ZN77//fpZzHVU1S0tL0+OPPy6TyaSNGzcqMjJSCxcu1Jo1a+weG7ib8RweoBBo2bKllixZouHDh6tJkyZ69tlnVadOHaWkpOjAgQN66623VLduXfXo0UM1a9bU0KFDtXDhQrm5ualr1646deqUIiIiFBwcrLFjxzosrm7dusnf31+DBw/WjBkzVKxYMcXExCgxMdHqvKVLl2rLli3q3r27KlasqOvXr1tWQnXq1CnH8adOnapPP/1UHTp00JQpU+Tv76/ly5frs88+09y5c+Xn5+ewe7ndnDlz/vKc7t27a968eerXr5+GDh2q3377Ta+88kq2jw6oV6+eVq5cqY8++khVq1aVl5dXnubdTJ06VV999ZW++OILBQYGavz48dq+fbsGDx6sRo0aqUqVKjaPCYCEByg0hgwZoubNm+u1115TVFSUzp07Jw8PD9WoUUP9+vXTyJEjLecuWbJE1apV0zvvvKM33nhDfn5+evDBBxUZGZntnJ288vX11aZNm/Tcc8/piSeeUKlSpfT000+ra9euevrppy3nNWzYUF988YWmTp2qc+fOqWTJkqpbt67Wr19vmQOTnZo1a2rXrl168cUXNWLECF27dk21a9dWdHS0TU8szi9/+9vf9O677yoqKko9evTQvffeqyFDhigg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\",\n \"text/plain\": [\n \"
\"\n ]\n },\n \"metadata\": {},\n \"output_type\": \"display_data\"\n },\n {\n \"name\": \"stderr\",\n \"output_type\": \"stream\",\n \"text\": [\n \"/tmp/ipykernel_24223/3815011085.py:28: FutureWarning: \\n\",\n \"\\n\",\n \"Passing `palette` without assigning `hue` is deprecated and will be removed in v0.14.0. Assign the `x` variable to `hue` and set `legend=False` for the same effect.\\n\",\n \"\\n\",\n \" sns.barplot(x=list(metrics.keys()), y=list(metrics.values()), palette=\\\"mako\\\")\\n\"\n ]\n },\n {\n \"data\": {\n \"image/png\": \"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xhhjihcvbl588UX7cuPGjTOSzIwZMxweb/DgwUaSWbp0qTHGmMWLFxtJZsSIEQ79Pv30UyPJ9O3b195Ws2ZNkydPHnPp0iWHvp06dTJeXl7m4sWLxhhjDh8+bCSZSZMm3XbdkvoNHjzYxMXFmRs3bpioqCgTGBhoJJmffvrJXL161WTJksXUq1fPYdmEhARTunRpU758eXtb3759jSTTp0+f276OSf7880/j7e1tateu7dD32LFjxtPT0zRv3tze1rJlSyPJTJw4MdljSzI5cuQwV65csbfNnTvXSDJlypQxiYmJ9vaIiAgjyezatSvF1yQxMdHExcWZo0ePGklm3rx5ydZvyJAhDst07NjReHl52Z9n7dq1RpLp1atXis+RtI5ubm6mc+fODu0xMTEmR44c5vXXX091WWOMfVucOXOmOXTokLHZbGbhwoXGGGOaNGliqlataowxpk6dOiZ//vz25TZt2mQkmc8//9zh8Y4fP268vb3NRx99ZG/757JJkrabQoUKmZs3b6Z4363b3ksvvWQyZcpkzp07l+r6lChRwrz22mu3XeeUTJ8+3UgymzdvTnZf/vz5jaRkP+XLlzenT5++7ePGx8ebK1eumPTp0zu8N5Ne91WrVt31sknvgY4dOzr0HzJkiJFkr+nQoUPG1dXVvPHGG6k+x928LytUqGBy5cplrl+/bm+7fPmyyZIli7mT3Y1ffvnF5MuXz/76ZcyY0dStW9dMmTLF4b31TwkJCSYuLs4MGDDAZM2a1aFv/vz5jbe3tzlx4oS9bceOHUaSyZkzp7l69aq9Pem9PH/+fHtb0udBap+b69evd3iuli1b2m+Hh4cbFxcXh88iY4z58ccfjSSzaNEih/b9+/cbSWbs2LH/8koBjy5GLIBH0IsvvqhChQpp4sSJ+u233/Trr7+mOg1q5cqVSp8+vRo3buzQnjQFKOkbxVWrVkmS3njjDYd+zZs3d7h948YNrVixQg0aNFC6dOns38LGx8erdu3aunHjhjZv3nxP69WtWze5u7vLy8tLAQEBOnbsmMaPH6/atWtr48aNunjxolq2bOnwnImJiXrllVf066+/Jps+0KhRozt63k2bNun69evJztiSN29evfTSSymOhqT22NWqVVP69Ontt4sVKyZJqlWrlsOZb5Lab/3m99y5c+rQoYPy5s0rNzc3ubu7K3/+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atCgQfe1QAAAAACPvnsKFj169NDOnTu1evVqeXl52durV6+u6dOn37fiAAAAAKQNbvey0Ny5czV9+nQ9//zzstls9vZnn31WBw8evG/FAQAAAEgb7mnE4vz588qePXuy9qtXrzoEDQAAAABPhnsKFoGBgfrpp5/st5PCxNdff62goKD7UxkAAACANOOepkKFh4frlVde0d69exUfH68RI0Zoz5492rRpk9asWXO/awQAAADwiLunEYuKFStq48aNunbtmgoVKqSlS5fKz89PmzZtUkBAwP2uEQAAAMAj7q5HLOLi4tSuXTv17t1b33zzzYOoCQAAAEAac9cjFu7u7pozZ86DqAUAAABAGnVPU6EaNGiguXPn3udSAAAAAKRV93TwduHChfXJJ59o48aNCggIUPr06R3uDw0NvS/FAQAAAEgb7ilYTJgwQZkyZVJUVJSioqIc7rPZbAQLAAAA4AlzT8Hi8OHD97sOAAAAAGnYPR1jcStjjIwx96MWAAAAAGnUPQeLKVOmqGTJkvL29pa3t7dKlSqlb7/99n7WBgAAACCNuKepUMOHD1fv3r3VqVMnVapUScYYbdiwQR06dNCFCxfUtWvX+10nAAAAgEfYPQWLUaNGaezYsQoJCbG3vfrqqypevLj69etHsAAAAACeMPc0Fer06dOqWLFisvaKFSvq9OnTlosCAAAAkLbcU7AoXLiwZsyYkax9+vTpKlKkiOWiAAAAAKQt9zQVqn///mratKnWrl2rSpUqyWazaf369VqxYkWKgQMAAADA4+2eRiwaNWqkLVu2KFu2bJo7d65mz56tbNmy6ZdfflGDBg3ud40AAAAAHnH3NGIhSQEBAfruu+/uZy0AAAAA0qh7GrFYtGiRlixZkqx9yZIlWrx4seWiAAAAAKQt9xQsunfvroSEhGTtxhh1797dclEAAAAA0pZ7Chb79+/Xs88+m6z9mWee0YEDBywXBQAAACBtuadg4evrq0OHDiVrP3DggNKnT2+5KAAAAABpyz0Fi/r166tLly46ePCgve3AgQN6//33Vb9+/ftWHAAAAIC04Z6CxdChQ5U+fXo988wz8vf3l7+/v5555hllzZpVw4YNu981AgAAAHjE3dPpZn19fbVx40YtW7ZMO3fulLe3t0qXLq3KlSvf7/oAAAAApAF3NWKxZcsW++lkbTabgoODlT17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Awd05coVLV682H4wZUJCgvbv3y93d3f7H/g//vhDw4YN04YNG+xnVsCT5/Llyw63t2/fro4dO2r48OHq16+fPVScOnVKWbJk0YIFC+Tt7a2PPvpIK1eudEbJcIKksLBp0yYNGzZM/fr108yZM+Xl5aUuXbro+PHjat26tQ4cOKBffvlFPXv21I8//qg33niDUAHgnlStWlVvv/22IiIidOPGDeXMmVP79u2Tv7+/ihcvrh9++EE5cuTQF198IQ8PD0LFfcLXhbCbNm2a+vbtK19fXxUrVsw+iuHq6qratWurc+fOunjxoo4cOaKEhAQFBARISvmbSDz++vXrJ09PT3344YdydXWVzWbTnj17lD9/fr399tu6cuWK5s+fr++++047d+5U27Zt1b9/f82cOVMhISEqWrSos1cBD4nNZtOsWbPUpk0b1a5dW1evXtX333+v5cuXa/z48ZKkyMhIFStWTP7+/vLw8NDy5cuZkgDAkgoVKmj48OFyd3dX27ZttXr1aq1YsULFixfXwYMHtWTJkmQXWIQ1BIsnWFJwSPr3+vXr8vPz0+7du5WQkCAXFxfFxcXJ3d1d7777rtzc3LR582YVLFjQPncxISFBrq6uzl4VOIGvr6+Cg4Pl5uamGzduyMvLS3nz5tXhw4fVuXNn7dixQ1myZFHu3LlVp04dde7cWdWrV1flypW1cOFCzjP/BDlw4IA++OADhYeH65133tG+ffsUFBRkH40ICQlRy5YttX79emXPnl2ZM2fWU0895eSqAaR1jRs31qhRo+Th4aEcOXJoyZIl9i8sChUqpI4dOzq5wscPx1hAUVFRCggIUGJioubMmaO+ffsqc+bM+vHHH+Xn5+dwQOWtx2Lc2o4nxz9HqFatWqXVq1erQ4cO8vHx0YQJEzRjxgyVK1dOLVu21HPPPacrV64oODhYERERqlChAqNcj6lbPx9utXr1aoWFhWnbtm06evSoKleurNq1a2vcuHGSpE2bNikoKOhhlwvgMZb0d2bRokXq2rWrBg8erNdee42/Pw8YXxk+4davX6/AwECNGjVKLi4uatiwoXr37i2bzaaQkBCdPXtWbm5uiouLk+R4NVNCxZPpnx/IGzdu1BdffKEJEyYoNjZW7733nlauXKkRI0aobNmystlsGjJkiM6fP698+fKl+BhI+5JCxZEjRxQREaFPP/1U8+bNkyS5urrKx8dHUVFRqly5smrVqqXRo0dLkrZt26Zp06Zp//79ziwfwGMm6e9M0henUVFRDu14MNgzfMIVL15cffr0UVhYmFxcXPTuu+/q9ddflzFGY8eOVatWrTRx4kSuQgm7pG97jh07pnz58qlXr17y8PDQiBEjlJiYqDZt2ihPnjySpOXLl2vatGmaP3++li5dynb0mEoKFbt27VLdunWVP39+nTp1SmfOnNHIkSPVsGFD7d27V4GBgXr77bftx1VI0rfffqu9e/cqa9asTlwDAI8rPz8/9e3bVx06dFC9evVUvnx5Z5f0WGPE4gmS0qy3zJkzq0uXLurdu7c6d+6sMWPGyGazqWnTpurYsaOOHj2qIUOGOKFaPIqSQsX8+fNVt25dffnll5KkDz/8UKGhofr6668VGRmpkydP6vr169q3b59u3rypNWvW6LnnnnNy9XgQbg0VQUFBeuONN7RixQrNnj1b/v7+Gj58uDJnzqxx48bJZrPJ09NTW7Zs0c6dO/X+++9r0qRJioiI4DomAB6YatWqKTAwULly5XJ2KY89jrF4An3++efKkyePmjZtam/766+/NHLkSPXr109ff/212rRpo8TERK1cuVLVqlXjAG3YLVy4UE2aNNGwYcMUFBSksmXL2u8bMmSIRo4cqfbt26tjx47y9fVVbGys0qdP78SK8aAdP35cZcuWVbVq1TRjxgx7+8svv6x9+/Zp69atypUrl5YuXaq33npLbm5u8vLyUvr06RUZGakyZco4r3gAT4Skk4zgwWIq1BPg1gOVrly5oh07dqh3797y8vLSq6++KknKlCmT3nnnHa1du1Zvv/22YmJi1KVLF1WvXl2SOPsTJEkxMTGKiIhQt27d9O6779rbk84e9tFHH8lms6lPnz7y8PDQhx9+SKh4AiQkJMjf31+xsbHasGGDKlWqpPDwcK1atUqlSpVSq1atlJCQYD9DS9asWZU3b175+voyUgHgoSBUPByMWDzmbj1Ly4EDB1SgQAFduHBBn332mb755htNnjxZDRo0sPfv3LmzNm3aJG9vb61du1YSBzrhf86dO6eyZctq8ODBeuONNxxC663/Hz58uOrVq6ciRYo4s1w8RPv371doaKg8PDyUPXt2zZs3T+PGjdMLL7yg33//Xfv27dPnn3+u69evq0CBAlqzZg2nHAaAxwwj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\",\n \"text/plain\": [\n \"
\"\n ]\n },\n \"metadata\": {},\n \"output_type\": \"display_data\"\n },\n {\n \"name\": \"stdout\",\n \"output_type\": \"stream\",\n \"text\": [\n \"\\n\",\n \"šŸ’¾ Results saved to moderation_results_deepseek_20250812_072840.csv\\n\"\n ]\n }\n ],\n \"source\": [\n \"# Evaluate\\n\",\n \"y_true, y_pred = sample_df[\\\"label\\\"], predictions\\n\",\n \"metrics = {\\n\",\n \" \\\"Accuracy\\\": accuracy_score(y_true, y_pred),\\n\",\n \" \\\"Precision\\\": precision_score(y_true, y_pred),\\n\",\n \" \\\"Recall\\\": recall_score(y_true, y_pred),\\n\",\n \" \\\"F1\\\": f1_score(y_true, y_pred),\\n\",\n \" \\\"AUC\\\": roc_auc_score(y_true, y_pred)\\n\",\n \"}\\n\",\n \"\\n\",\n \"print(\\\"\\\\nšŸ“Š Metrics:\\\")\\n\",\n \"for k, v in metrics.items():\\n\",\n \" print(f\\\"{k}: {v:.4f}\\\")\\n\",\n \"\\n\",\n \"generate_performance_report(y_true, y_pred, inference_times)\\n\",\n \"\\n\",\n \"\\n\",\n \"# Confusion Matrix\\n\",\n \"cm = confusion_matrix(y_true, y_pred)\\n\",\n \"disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=[\\\"Not Toxic\\\", \\\"Toxic\\\"])\\n\",\n \"disp.plot(cmap=plt.cm.Blues)\\n\",\n \"plt.title(\\\"Confusion Matrix\\\")\\n\",\n \"plt.tight_layout()\\n\",\n \"plt.show()\\n\",\n \"\\n\",\n \"# Bar Plot of Metrics\\n\",\n \"plt.figure(figsize=(8, 5))\\n\",\n \"sns.barplot(x=list(metrics.keys()), y=list(metrics.values()), palette=\\\"mako\\\")\\n\",\n \"plt.title(\\\"Model Performance Metrics (Balanced Sample)\\\")\\n\",\n \"plt.ylabel(\\\"Score\\\")\\n\",\n \"plt.ylim(0, 1)\\n\",\n \"plt.xticks(rotation=45)\\n\",\n \"plt.tight_layout()\\n\",\n \"plt.show()\\n\",\n \"\\n\",\n \"# Save results\\n\",\n \"results_df = pd.DataFrame({\\n\",\n \" 'text': sample_df[\\\"text\\\"],\\n\",\n \" 'true_label': y_true,\\n\",\n \" 'predicted_label': y_pred,\\n\",\n \" 'inference_time_ms': np.array(inference_times) * 1000\\n\",\n \"})\\n\",\n \"timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')\\n\",\n \"results_df.to_csv(f'moderation_results_deepseek_{timestamp}.csv', index=False)\\n\",\n \"print(f\\\"\\\\nšŸ’¾ Results saved to moderation_results_deepseek_{timestamp}.csv\\\") \"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"id\": \"ea92019d-8aaa-4c8f-a9bd-437a61c30478\",\n \"metadata\": {},\n \"source\": [\n \"# Model configuration - gpt4all Llama 3 \"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": 11,\n \"id\": \"83c84b17-caa4-4f47-8f6d-854b582523c9\",\n \"metadata\": {},\n \"outputs\": [\n {\n \"name\": \"stdout\",\n \"output_type\": \"stream\",\n \"text\": [\n \"Loading cached model from /home/sagemaker-user/harmfull-detection/models/Meta-Llama-3-8B-Instruct.Q4_0.gguf\\n\"\n ]\n },\n {\n \"name\": \"stderr\",\n \"output_type\": \"stream\",\n \"text\": [\n \"Failed to load libllamamodel-mainline-cuda-avxonly.so: dlopen: libcudart.so.11.0: cannot open shared object file: No such file or directory\\n\",\n \"Failed to load libllamamodel-mainline-cuda.so: dlopen: libcudart.so.11.0: cannot open shared object file: No such file or directory\\n\"\n ]\n },\n {\n \"name\": \"stdout\",\n \"output_type\": \"stream\",\n \"text\": [\n \"Model configuration completed\\n\"\n ]\n }\n ],\n \"source\": [\n \"# Model configuration\\n\",\n \"MODEL_TYPE = \\\"gpt4all\\\" # Options: \\\"deepseek\\\", \\\"gpt4all\\\", \\\"mistral\\\"\\n\",\n \"DEEPSEEK_MODEL = \\\"deepseek-ai/DeepSeek-R1-Distill-Llama-8B\\\"\\n\",\n \"GPT4ALL_MODEL = \\\"Meta-Llama-3-8B-Instruct.Q4_0.gguf\\\"\\n\",\n \"GPT4ALL_MODEL_PATH = \\\"/home/sagemaker-user/harmfull-detection/models/\\\"\\n\",\n \"MISTRAL_MODEL = \\\"/tmp/models/mistral-7b-v0-2\\\"\\n\",\n \"# Initialize clients\\n\",\n \"if MODEL_TYPE == \\\"deepseek\\\":\\n\",\n \" client = OpenAI(\\n\",\n \" api_key=os.getenv(\\\"DEEPSEEK_API_KEY\\\"),\\n\",\n \" base_url=\\\"http://k8s-deepseek-deepseek-e92cca8149-b20547a64509f06f.elb.eu-west-1.amazonaws.com/v1\\\"\\n\",\n \" )\\n\",\n \"elif MODEL_TYPE == \\\"mistral\\\":\\n\",\n \" client = OpenAI(\\n\",\n \" api_key=os.getenv(\\\"MISTRAL_API_KEY\\\"),\\n\",\n \" base_url=\\\"http://vllm-serve-svc-pub-288545519.us-west-2.elb.amazonaws.com/v1\\\"\\n\",\n \" ) \\n\",\n \"elif MODEL_TYPE == \\\"gpt4all\\\":\\n\",\n \" if GPT4All is None:\\n\",\n \" raise ImportError(\\\"Install gpt4all: pip install gpt4all\\\")\\n\",\n \" \\n\",\n \" model_file = os.path.join(GPT4ALL_MODEL_PATH, GPT4ALL_MODEL)\\n\",\n \" if os.path.exists(model_file):\\n\",\n \" print(f\\\"Loading cached model from {model_file}\\\")\\n\",\n \" client = GPT4All(model_name=GPT4ALL_MODEL, model_path=GPT4ALL_MODEL_PATH, allow_download=False)\\n\",\n \" else:\\n\",\n \" print(f\\\"Downloading model to {GPT4ALL_MODEL_PATH}\\\")\\n\",\n \" os.makedirs(GPT4ALL_MODEL_PATH, exist_ok=True)\\n\",\n \" client = GPT4All(model_name=GPT4ALL_MODEL, model_path=GPT4ALL_MODEL_PATH)\\n\",\n \"\\n\",\n \"def predict_with_model(text):\\n\",\n \" prompt = f'Analyze this message and respond ONLY with JSON: {{\\\"action\\\": \\\"allow|warn|block|timeout\\\", \\\"confidence\\\": 0.0-1.0, \\\"categories\\\": [\\\"list of violation types\\\"]}}: \\\"{text}\\\"'\\n\",\n \" \\n\",\n \" try:\\n\",\n \" if MODEL_TYPE == \\\"deepseek\\\":\\n\",\n \" response = client.chat.completions.create(\\n\",\n \" model=DEEPSEEK_MODEL,\\n\",\n \" messages=[\\n\",\n \" {\\\"role\\\": \\\"system\\\", \\\"content\\\": \\\"You are a content moderation assistant. Respond only with JSON.\\\"},\\n\",\n \" {\\\"role\\\": \\\"user\\\", \\\"content\\\": prompt}\\n\",\n \" ],\\n\",\n \" temperature=0\\n\",\n \" )\\n\",\n \" reply = response.choices[0].message.content.strip()\\n\",\n \" \\n\",\n \" elif MODEL_TYPE == \\\"gpt4all\\\":\\n\",\n \" with client.chat_session():\\n\",\n \" reply = client.generate(prompt, max_tokens=1024)\\n\",\n \" \\n\",\n \" json_match = re.search(r'\\\\{.*\\\\}', reply, re.DOTALL)\\n\",\n \" if json_match:\\n\",\n \" result = json.loads(json_match.group())\\n\",\n \" return 1 if result.get(\\\"action\\\", \\\"\\\").upper() == \\\"BLOCK\\\" else 0\\n\",\n \" return 0\\n\",\n \" except:\\n\",\n \" return 0\\n\",\n \"\\n\",\n \"def measure_inference_times(texts, predict_fn):\\n\",\n \" times, predictions = [], []\\n\",\n \" for text in tqdm(texts, desc=\\\"Processing texts\\\"):\\n\",\n \" start = time.time()\\n\",\n \" pred = predict_fn(text)\\n\",\n \" times.append(time.time() - start)\\n\",\n \" predictions.append(pred)\\n\",\n \" return predictions, times\\n\",\n \"\\n\",\n \"def generate_performance_report(y_true, y_pred, inference_times=None):\\n\",\n \" print(\\\"\\\\nšŸ“Š Classification Report:\\\")\\n\",\n \" print(classification_report(y_true, y_pred))\\n\",\n \" \\n\",\n \" if inference_times:\\n\",\n \" times_ms = np.array(inference_times) * 1000\\n\",\n \" print(f\\\"\\\\nā±ļø Mean inference time: {np.mean(times_ms):.2f}ms\\\")\\n\",\n \"\\n\",\n \"print(\\\"Model configuration completed\\\")\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": 12,\n \"id\": \"3d0618bb-59b0-429f-9d55-0012a3549d3f\",\n \"metadata\": {},\n \"outputs\": [\n {\n \"name\": \"stdout\",\n \"output_type\": \"stream\",\n \"text\": [\n \"\\n\",\n \"šŸš€ Running inference with gpt4all...\\n\"\n ]\n },\n {\n \"name\": \"stderr\",\n \"output_type\": \"stream\",\n \"text\": [\n \"Processing texts: 100%|ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆ| 40/40 [35:50<00:00, 53.76s/it]\\n\"\n ]\n }\n ],\n \"source\": [\n \"# Run predictions with timing\\n\",\n \"print(f\\\"\\\\nšŸš€ Running inference with {MODEL_TYPE}...\\\")\\n\",\n \"predictions, inference_times = measure_inference_times(sample_df[\\\"text\\\"], predict_with_model)\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": 13,\n \"id\": \"7e278805-a03c-47fd-acfc-8bae863930db\",\n \"metadata\": {},\n \"outputs\": [\n {\n \"name\": \"stdout\",\n \"output_type\": \"stream\",\n \"text\": [\n \"\\n\",\n \"šŸ“Š Metrics:\\n\",\n \"Accuracy: 0.6250\\n\",\n \"Precision: 0.6923\\n\",\n \"Recall: 0.4500\\n\",\n \"F1: 0.5455\\n\",\n \"AUC: 0.6250\\n\",\n \"\\n\",\n \"šŸ“Š Classification Report:\\n\",\n \" precision recall f1-score support\\n\",\n \"\\n\",\n \" 0 0.59 0.80 0.68 20\\n\",\n \" 1 0.69 0.45 0.55 20\\n\",\n \"\\n\",\n \" accuracy 0.62 40\\n\",\n \" macro avg 0.64 0.62 0.61 40\\n\",\n \"weighted avg 0.64 0.62 0.61 40\\n\",\n \"\\n\",\n \"\\n\",\n \"ā±ļø Mean inference time: 53756.16ms\\n\"\n ]\n },\n {\n \"data\": {\n \"image/png\": \"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Q77iARxRvXr1XP+8XP+z/OqrryoxMVFbtmzRZ599ZrNa8a/q1Kmjr7/+Wunp6QUWM+AwlzbUgL9x/Tyaa3r16mX6+fnZzOHZvXu36eXlZU6cONE8fPiwGRcXZ/r7+5uLFi2yntO+fXvzwQcfNH/88UebuTV5vffQoUPN8PBwc926debBgwfN3r17m6VLlzZ/++030zRNc86cOWapUqXMU6dOmaZpmk888YRZr14988qVK6Zp5pxHsWnTJtPLy8scN26ceejQIfO7774zY2Nj7fyEgL/315+9VatWmT4+Pua8efPMI0eOmK+//rrp7e1tbtq0yTRN09y7d6/p6+trrlmzxjRN03znnXfMgIAA8/jx46Zp5pzDc+7cObNMmTJm165dzV27dplHjhwx33vvPfO///1vYb5N4KZIeODWckt4Tpw4YVosFvOv+fpHH31k1qhRw/Tx8THLlStnvvrqqzbHd+zYYdapUyfXa/Ny78uXL5vPPfecGRISYlosFrNFixbmt99+a5qmaSYmJpr+/v7m0qVLreefP3/erFChgjlq1CjTNHP+0jFN01yxYoVZr14909fX1wwJCTG7du36t3EB9srtZ2/u3LlmpUqVTB8fH7Nq1arme++9Z5pm9s95jRo1zAEDBtic//DDD5vNmzc3MzIyciQ8pmma+/fvN++9916zePHiZkBAgNmyZUtrggS4A74tHQAAeDzm8AAAAI9HwgMAADweCQ8AAPB4JDwAAMDjkfAAAACPR8IDAAA8HgkPAADweCQ8AADA45HwAMi3CRMmqF69etbX0dHReuihhwo9jhMnTsgwDO3bt++G51SoUEEzZszI85hxcXEqVaqUw7EZhqHVq1c7PA4Ax5DwAB4mOjpahmHIMAz5+PioUqVKeuGFF5Samlrg9545c6bi4uLydG5ekhQAcJZirg4AgPPdd999WrRokdLT0/X111/rqaeeUmpqqubNm5fj3PT0dPn4+DjlvkFBQU4ZBwCcjQoP4IEsFovCwsIUERGhHj16qGfPnta2yrU21LvvvqtKlSrJYrHINE2dP39eAwYMUGhoqAIDA/WPf/xD+/fvtxl36tSpKlu2rAICAtSvXz+lpaXZHP9rSysrK0uxsbGqUqWKLBaLypUrp8mTJ0uSKlasKEmqX7++DMNQVFSU9bpFixapevXq8vPzU7Vq1TR37lyb+3z77beqX7++/Pz81KhRI+3du9fuz2j69OmqXbu2SpQooYiICA0aNEgXL17Mcd7q1atVtWpV+fn5qX379kpOTrY5vnbtWjVs2FB+fn6qVKmSXnnlFWVkZNgdD4CCRcID3AL8/f2Vnp5ufX3s2DEtX75cK1assLaUOnXqpDNnzujTTz/V7t271aBBA7Vt21a//fabJGn58uUaP368Jk+erISEBN1+++05EpG/GjNmjGJjYzV27FgdOnRIS5cuVdmyZSVlJy2S9OWXX+r06dNauXKlJGnBggV6+eWXNXnyZCUmJmrKlCkaO3as4uPjJUmpqal64IEHFBkZqd27d2vChAl64YUX7P5MvLy8NGvWLB04cEDx8fHauHGjRo0aZXPOpUuXNHnyZMXHx2vbtm1KSUlR9+7drcc/++wzPfHEExoyZIgOHTqkt956S3FxcdakDoAbcfG3tQNwst69e5tdunSxvv7mm2/MMmXKmI899phpmqY5fvx408fHxzx79qz1nA0bNpiBgYFmWlqazViVK1c233rrLdM0TbNZs2bm008/bXP87rvvNuvWrZvrvVNSUkyLxWIuWLAg1ziTkpJMSebevXtt9kdERJhLly612Tdp0iSzWbNmpmma5ltvvWUGBwebqamp1uPz5s3LdazrlS9f3nzjjTdueHz58uVmmTJlrK8XLVpkSjJ37txp3ZeYmGhKMr/55hvTNE2zZcuW5pQpU2zGWbx4sXn77bdbX0syV61adcP7AigczOEBPNDHH3+skiVLKiMjQ+np6erSpYtmz55tPV6+fHnddttt1te7d+/WxYsXVaZMGZtxLl++rOPHj0uSEhMT9fTTT9scb9asmTZt2pRrDImJibpy5Yratm2b57h/+eUXJScnq1+/furfv791f0ZGhnV+UGJiourWravixYvbxGGvTZs2acqUKTp06JBSUlKUkZGhtLQ0paamqkSJEpKkYsWKqVGjRtZrqlWrplKlSikxMVFNmjTR7t27tWvXLpuKTmZmptLS0nTp0iWbGAG4FgkP4IHatGmjefPmycfHR+Hh4TkmJV/7hX5NVlaWbr/9dm3evDnHWPldmu3v72/3NVlZWZKy21p33323zTFvb29Jkmma+YrneidPntT999+vp59+WpMmTVJwcLC2bt2qfv362bT+pOxl5X91bV9WVpZeeeUVde3aNcc5fn5+DscJwHlIeAAPVKJECVWpUiXP5zdo0EBnzpxRsWLFVKFChVzPqV69unbu3Kknn3zSum/nzp03HPOuu+6Sv7+/NmzYoKeeeirHcV9fX0nZFZFrypYtqzvuuEM//PCDevbsmeu4NWrU0OLFi3X58mVrUnWzOHKTkJCgjIwMvf766/Lyyp7KuHz58hznZWRkKCEhQU2aNJEkHT58WH/88YeqVasmKftzO3z4sF2fNQDXIOEBoHbt2qlZs2Z66KGHFBsbq8jISP3888/69NNP9dBDD6lRo0YaOnSoevfurUaNGumee+7RkiVLdPDgQVWqVCnXMf38/DR69GiNGjVKvr6+atGihX755RcdPHhQ/fr1U2hoqPz9/bV+/Xrdeeed8vPzU1BQkCZMmKAhQ4YoMDBQHTt21JUrV5SQkKDff/9dw4cPV48ePfTyyy+rX79++te//qUTJ07otddes+v9Vq5cWRkZGZo9e7Y6d+6sbdu2af78+TnO8/Hx0XPPPadZs2bJx8dHzz77rJo2bWpNgMaNG6cHHnhAERERevTRR+Xl5aXvvvtO33//vf7973/b/38EgALDKi0AMgxDn376qVq1aqW+ffuqatWq6t69u06cOGFdVdWtWzeNGzdOo0ePVsOGDXXy5Ek988wzNx137NixGjFihMaNG6fq1aurW7duOnv2rKTs+TGzZs3SW2+9pfDwcHXp0kWS9NRTT+mdd95RXFycateurdatWysuLs66jL1kyZJau3atDh06pPr16+vll19WbGysXe+3Xr16mj59umJjY1WrVi0tWbJEMTExOc4rXry4Ro8erR49eqhZs2by9/fXsmXLrMc7dOigjz/+WF988YUaN26spk2bavr06Spfvrxd8QAoeIbpjIY4AACAG6PCAwAAPB4JDwAA8HgkPAAAwOOR8AAAAI9HwgMAADweCQ8AAPB4JDwAAMDjkfAAAACPR8IDAAA8HgkPAADweCQ8AADA45HwAAAAj/f/AXmuWGzsU/EpAAAAAElFTkSuQmCC\",\n \"text/plain\": [\n \"
\"\n ]\n },\n \"metadata\": {},\n \"output_type\": \"display_data\"\n },\n {\n \"name\": \"stderr\",\n \"output_type\": \"stream\",\n \"text\": [\n \"/tmp/ipykernel_24223/3542555518.py:28: FutureWarning: \\n\",\n \"\\n\",\n \"Passing `palette` without assigning `hue` is deprecated and will be removed in v0.14.0. Assign the `x` variable to `hue` and set `legend=False` for the same effect.\\n\",\n \"\\n\",\n \" sns.barplot(x=list(metrics.keys()), y=list(metrics.values()), palette=\\\"mako\\\")\\n\"\n ]\n },\n {\n \"data\": {\n \"image/png\": \"iVBORw0KGgoAAAANSUhEUgAAAxYAAAHqCAYAAACZcdjsAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAAVVpJREFUeJzt3Xd4FFXfxvF700NJaBI6hKZIlRAwIAgKQarS5AElgCAgQoRYaFJFQxMDSFMCiCIC0hGk96aEJsVHeq9BIbSQct4/fLMPaxIEBlgC38915YI9e2b3N5vZzdx7zszYjDFGAAAAAGCBi7MLAAAAAJD2ESwAAAAAWEawAAAAAGAZwQIAAACAZQQLAAAAAJYRLAAAAABYRrAAAAAAYBnBAgAAAIBlBAsAAAAAlhEsgEfE5MmTZbPZZLPZtHr16mT3G2NUuHBh2Ww2Va1a9b4+t81mU79+/e56uSNHjshms2ny5Ml31C/px8XFRVmzZlXt2rW1adOmeyv6NkaNGqXChQvLw8NDNptNf/31131/jifF6tWr7b+31H7PL730kmw2mwoUKHBPz/H9998rIiLirpa5023vfpsyZYqeeuopxcTE2NsKFCjgsH17eXmpcOHCCgsL04ULF+7peZJe95Q+C9Kafv36yWaz/Ws/Y4x++OEHVa5cWdmzZ5eXl5fy5MmjmjVrasKECQ+hUmsKFCigVq1a3fVycXFxKlSo0F2/B4BHEcECeMRkzJhRkZGRydrXrFmjgwcPKmPGjE6o6v7o3LmzNm3apHXr1ik8PFw7d+5UtWrVtH379vv2HDt27FBoaKiqVaumlStXatOmTWn6NXtUpLZdHj58WKtXr5aPj889P/a9BIucOXNq06ZNqlOnzj0/7926du2aevbsqW7duiXbpipVqqRNmzZp06ZNWrx4sdq3b6/x48frlVdeeWj1pXU9evRQs2bNVKxYMU2YMEGLFy/WwIED5efnp3nz5jm7vAfG3d1dffr00YABAxQdHe3scgBL3JxdAABHTZs21dSpUzV69GiHnbXIyEgFBQXp8uXLTqzOmnz58un555+X9PeOWOHChfXyyy9rzJgx+vrrry099rVr15QuXTrt2bNHkvT222+rfPnylmu+9bGfZE2bNtWECRO0f/9+FSlSxN4+ceJE5c6dWyVLltTevXsfeB0JCQmKj4+Xp6enfVt6WL755htFR0erbdu2ye7LlCmTQz3VqlVTTEyMPvnkE/3xxx8qWrTowyw1zbl+/boiIiIUEhKir776yuG+Vq1aKTEx0UmVPRzNmjVTWFiYxo8fr549ezq7HOCeMWIBPGKaNWsmSZo2bZq97dKlS5o1a5beeuutFJe5ePGiOnbsqNy5c8vDw0MFCxZUr169FBsb69Dv8uXLevvtt5U1a1ZlyJBBr7zyiv74448UH3P//v1q3ry5smfPLk9PTxUrVkyjR4++T2v5t6QdsaNHj9rbli9frpdfflk+Pj5Kly6dKlWqpBUrVjgslzS1Ytu2bWrcuLEyZ86sQoUKqWrVqnrzzTclSRUqVJDNZnOYmjBx4kSVLl1aXl5eypIlixo0aKB9+/Y5PHarVq2UIUMG/fbbbwoODlbGjBn18ssvS/p7ylinTp00adIkPf300/L29la5cuW0efNmGWM0dOhQ+fv7K0OGDHrppZd04MABh8detmyZXn31VeXJk8c+XaZ9+/bJpsskrd+ePXvUrFkz+fr6ys/PT2+99ZYuXbrk0DcxMVGjRo1SmTJl5O3tbd/BnT9/vkO/6dOnKygoSOnTp1eGDBlUs2bNuxopqlGjhvLmzauJEyc6PPc333yjli1bysUl+Z8TY4zGjBljry1z5sxq3LixDh06ZO9TtWpV/fTTTzp69KjDdCLpf9OdhgwZooEDB8rf31+enp5atWpVqlOhfv/9dzVr1kx+fn7y9PRUvnz5FBISYn8vXLt2TR988IH8/f3t20G5cuUc3m+pGTt2rOrVq6dMmTLd0Wvm6+sr6e9vpJNs3bpV//nPf1SgQAF5e3urQIECatasmcN7IDV3umzStMpVq1bpnXfeUbZs2ZQ1a1Y1bNhQp06dSva433//vYKCgpQhQwZlyJBBZcqUSTY6dSfvS0n66aefVKZMGXl6esrf31/Dhg27o9fq6tWrio2NVc6cOVO8/5/bV//+/VWhQgVlyZJFPj4+Klu2rCIjI2WMcehXoEAB1a1bVwsXLtRzzz0nb29vFStWTAsXLrS/VsWKFVP69OlVvnx5bd261WH5pM+DPXv26OWXX1b69On11FNPqVOnTrp27dq/rtfly5ft25uHh4dy586tLl266OrVqw79PDw81LRpU3311VfJ1gFISwgWwCPGx8dHjRs3dtiBmzZtmlxcXNS0adNk/W/cuKFq1appypQpCgsL008//aQ333xTQ4YMUcOGDe39jDF67bXX9O233+r999/XnDlz9Pzzz6tWrVrJHnPv3r0KDAzU7t279fnnn2vhwoWqU6eOQkND1b9///u2rkk73k899ZQk6bvvvlNwcLB8fHz0zTffaMaMGcqSJYtq1qyZ4k5Mw4YNVbhwYc2cOVPjxo3TmDFj9PHHH0uSJk2apE2bNql3796SpPDwcLVp00bFixfX7NmzNWLECO3atUtBQUHav3+/w+PevHlT9evX10svvaR58+Y5rPPChQs1YcIEDRo0SNOmTVNMTIzq1Kmj999/Xxs2bNCXX36pr776Snv37lWjRo0cdhIOHjyooKAgjR07VkuXLlWfPn20ZcsWvfDCC4qLi0u2fo0aNVLRokU1a9Ysde/eXd9//726du3q0KdVq1Z67733FBgYqOnTp+uHH35Q/fr1deTIEXufzz77TM2aNdOzzz6rGTNm6Ntvv1VMTIwqV658x6MMLi4uatWqlaZMmaKEhARJ0tKlS3XixAm1bt06xWXat2+vLl26qHr16po7d67GjBmjPXv2qGLFijp79qwkacyYMapUqZJy5Mhhn0r0z+NuRo4cqZUrV2rYsGFavHixnnnmmRSfb+fOnQoMDNTmzZs1YMAALV68WOHh4YqNjdXNmzclSWFhYRo7dqxCQ0P1888/69tvv1WTJk3+dQrKiRMn9Ntvv6latWop3m+MUXx8vOLj43XlyhWtWrVKERERqlSpkvz9/e39jhw5oqeffloRERFasmSJBg8erNOnTyswMPBfj8e422Xbtm0rd3d3ff/99xoyZIhWr15tD95J+vTpozfeeEO5cuXS5MmTNWfOHLVs2dIhrNzp+3LFihV69dVXlTFjRv3www8aOnSoZsyYoUmTJt12vSQpW7ZsKly4sMaMGaPhw4fr999/v+0O9pEjR9S+fXvNmDFDs2fPVsOGDdW5c2d98sknyfru3LlTPXr0ULdu3TR79mz5+vqqYcOG6tu3ryZMmKDPPvtMU6dO1aVLl1S3bl1dv37dYfm4uDjVrl1bL7/8subOnatOnTpp/PjxKX4e3+ratWt68cUX9c033yg0NFSLFy9Wt27dNHnyZNWvXz/Z+lWtWlVHjx7V7t27//X1Ah5ZBsAjYdKkSUaS+fXXX82qVauMJLN7925jjDGBgYGmVatWxhhjihcvbl588UX7cuPGjTOSzIwZMxweb/DgwUaSWbp0qTHGmMWLFxtJZsSIEQ79Pv30UyPJ9O3b195Ws2ZNkydPHnPp0iWHvp06dTJeXl7m4sWLxhhjDh8+bCSZSZMm3XbdkvoNHjzYxMXFmRs3bpioqCgTGBhoJJmffvrJXL161WTJksXUq1fPYdmEhARTunRpU758eXtb3759jSTTp0+f276OSf7880/j7e1tateu7dD32LFjxtPT0zRv3tze1rJlSyPJTJw4MdljSzI5cuQwV65csbfNnTvXSDJlypQxiYmJ9vaIiAgjyezatSvF1yQxMdHExcWZo0ePGklm3rx5ydZvyJAhDst07NjReHl52Z9n7dq1RpLp1atXis+RtI5ubm6mc+fODu0xMTEmR44c5vXXX091WWOMfVucOXOmOXTokLHZbGbhwoXGGGOaNGliqlataowxpk6dOiZ//vz25TZt2mQkmc8//9zh8Y4fP268vb3NRx99ZG/757JJkrabQoUKmZs3b6Z4363b3ksvvWQyZcpkzp07l+r6lChRwrz22mu3XeeUTJ8+3UgymzdvTnZf/vz5jaRkP+XLlzenT5++7ePGx8ebK1eumPTp0zu8N5Ne91WrVt31sknvgY4dOzr0HzJkiJFkr+nQoUPG1dXVvPHGG6k+x928LytUqGBy5cplrl+/bm+7fPmyyZIli7mT3Y1ffvnF5MuXz/76ZcyY0dStW9dMmTLF4b31TwkJCSYuLs4MGDDAZM2a1aFv/vz5jbe3tzlx4oS9bceOHUaSyZkzp7l69aq9Pem9PH/+fHtb0udBap+b69evd3iuli1b2m+Hh4cbFxcXh88iY4z58ccfjSSzaNEih/b9+/cbSWbs2LH/8koBjy5GLIBH0IsvvqhChQpp4sSJ+u233/Trr7+mOg1q5cqVSp8+vRo3buzQnjQFKOkbxVWrVkmS3njjDYd+zZs3d7h948YNrVixQg0aNFC6dOns38LGx8erdu3aunHjhjZv3nxP69WtWze5u7vLy8tLAQEBOnbsmMaPH6/atWtr48aNunjxolq2bOnwnImJiXrllVf066+/Jps+0KhRozt63k2bNun69evJztiSN29evfTSSymOhqT22NWqVVP69Ontt4sVKyZJqlWrlsOZb5Lab/3m99y5c+rQoYPy5s0rNzc3ubu7K3/+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GTJkcHZJaYpTr7yNx1e6dOmUOXNmnTx5Unny5FFiYqJ9JANIiTFGNptNMTEx8vHxUUJCglxdXdl2nnCRkZFyc3NTkyZNVKtWLc2bN0916tSRJPXr1085c+Z0coVwtgMHDmjFihVq3LixsmbN6uxykIb997//VdWqVdW+fXt1795dPj4+zi4pzeHK27AstR2/2rVr68qVK1q7dq0TqkJatHDhQg0aNEheXl4qW7asevXqJV9fX8LFE8oYoypVquivv/5S7969VbduXaVLl05LlixRnTp11KZNG/Xv3185cuRwdqlwkv379yswMFCXL1/W4MGD1a5dO/n6+jq7LKRBsbGxatmypdzd3TVlyhT79KekL71wZ/hLDcuSdviuXbvm0N6nTx9du3ZNy5cvl8S0FtxeVFSUGjdurGrVqil37tzasGGDXn31Vf35559ycXFhqsMTJumP+apVq1SwYEGFh4drwYIFunbtmmrWrKmffvpJkZGRTIt6gl25ckX9+/dXw4YN1a9fP3Xr1k1jxozRpUuXnF0a0qC4uDjt3r1blSpVcggStwaMlP6FI4IF7ovx48erSJEiGjBggP773/9KkooXLy53d3fNmTNHkkj8SNWuXbu0e/du9e/fX5988okmTZqkHj16KC4uTvXr17eHi4SEBGeXiofEZrMpISFBbm5umjVrlnLnzq1BgwYRLiDp7y+y4uLi9Nxzz6lWrVrq06ePRowYoV69ehEucE+io6N14sQJZc6cWVLy4GCz2ZSYmKh+/frp/Pnz7NOkgmCBe3Lrt8c3btxQo0aN1KJFC23ZskUBAQHq1q2b/vjjDw0ZMkSzZs3Sli1bnFgtHmUnTpxQ+/btFRoaav8gd3FxUa1atdSjRw8lJiaqYcOGio6Olqurq5OrxcPk6upqDxdz585Vrly5UgwXU6ZMUVhYmM6ePevskvEQREVFqXTp0rp+/breeOMNNWnSRJLUuXNnRURE2MPF5cuXJUkJCQk6deqUM0vGI+ry5cu6efOmJMnDw0Ourq7asGFDqv03bNigPXv28LfoNggWuGu3zncfOnSoBg4cqCtXrmjQoEGaPn26xo8fr3379qlRo0Z6//335ebmps2bN0sS3zgjmWzZsunNN99Unjx5NH/+fPs24urqqtq1a6tXr146d+6cWrRowXSoJ8St3xQmfda4ublp3rx5ypkzZ7JwMWPGDC1dupTt4wmwc+dOVatWTbVr11auXLnsx9fExcVJkkJDQ/XFF1+oV69eGj16tM6fP6/u3burW7duunHjhjNLxyPm9OnTatSokb7++mvduHFDOXPm1DvvvKMxY8Zo1qxZ9lFT6X9fpv7888+SJHd3d6fV/cgzwD366KOPTPbs2U1kZKQ5efKkw33R0dHmt99+M6+//rrJnz+/yZs3r7l48aKTKsWjJDExMVnb9evXzaRJk0yJEiVM06ZNzY0bN+z3JSQkmCVLlpjDhw8/xCrhLEnbx/Lly837779v6tSpY+bMmWMOHjxojDEmLi7O1KpVy5QpU8ZMnz7dXLlyxRhj7P/i8bVz506TLl0607NnT4f22NhYY4wx8fHx9rYRI0YYd3d3U6ZMGePq6mq2b9/+MEtFGnDjxg1Ts2ZNExQUZCZMmGBu3rxpjhw5YoKDg42rq6uZPHmyuXDhgjHGmIMHD5pu3bqZLFmymD179ji58kcbZ4XCPVm8eLHatWun2bNnKzAw0N7+z7P3JCYmatu2berSpYv+85//qFOnTpxh4QmW9Ltft26dVq5cqYsXL6pKlSpq2LChEhMTNWXKFH355ZcqUqSIpkyZIg8PD2eXDCeYO3euQkJC1KhRI8XFxenXX39V9erV1a5dO5UuXVrx8fFq2LChdu3apeHDh6thw4Z8rjzmjh8/rrJly+qll17S9OnT7e0RERE6efKkBg0aJFdXV4ft4Pnnn9eBAwe0atUqlSxZ0lml4xGUdDrz2NhYtWjRQocOHVLnzp0VEhKiPXv2aMCAAfrxxx9VpEgRSZKvr6/++usvzZgxQ2XKlHFu8Y84pkLhnpw9e1Y5cuTQM888Yx8qNMbIxcVF8fHx9n4uLi4qW7ascuTIoW3btkniIO4nmc1m0+zZs/XKK69ow4YN2rVrl5o0aaJ27drp1KlTatGihTp27KijR4/qtddes899xZMjKipKXbt21fDhwzVp0iRNnDhRJ0+e1MKFCzVy5Ejt3r3bfkB3+fLl7X/k+Vx5vCUkJMjf3183btywz4EfNGiQ+vbtqzp16tjnvNtsNsXFxalz58765ZdfCBVIxhhjP37L09NTU6ZMUcGCBTVy5EhNmTJFzz77rKZOnap58+apSZMmqlmzpj788EOtWLGCUHEHuEAe7snJkyd1/PhxZcyYUZIUHx8vNzc3JSYmav369fbQkRQ2fH19deLECcXGxsrDw4OdgCfEP79FPnLkiD788EMNHz5c7du3lyQtWbJEISEhcnV11bhx49S8eXNdu3ZNc+bM0fnz55U7d25nlQ8n+Ouvv9SwYUO1bdtWR44cUbVq1dSqVSuVLFlSXbp0kaurq9q1a6dy5cppxowZzi4XD0mBAgU0depUhYaGasiQIfLz89O8efM0c+ZMVa1a1aFvfHy8ChYsqKioKEIF7Pbv368///xT5cuXdwgXXl5emjJlilq2bKlRo0YpW7ZsqlWrlurVq6d69eo5u+y0x0lTsJBGJCQkpNi+e/duU7BgQdO1a1eHOfN//fWXqVGjhpk4caK9bceOHaZs2bLMcX3CREREmMWLFzu07d+/3xQsWNBs2bLFJCYm2revRYsWGZvNZn766SdjzN9zX//666+HXjMevqTPj2vXrpnExEQTExNj9u/fb+Li4kyDBg1M69atTVxcnDHGmNKlS5unnnrKvPfee+bGjRspHq+Dx9t///tfU6NGDePt7W2GDRuWar/U/nbhyZSQkGDeeecdY7PZzMaNG40x//vsSTo259q1a6ZKlSomKCjIaXU+DpgKhVTderxEVFSUNm/erD/++EOSVLBgQb355ptav3693nrrLe3fv18rVqzQG2+8oQsXLqhFixb2xyldurSWLl3KEOITwhij69eva9GiRSpUqJDDfTdv3tSpU6f0559/ymazKT4+XomJiapVq5bKli1rny7n6enJ1XOfAOb/R7R+/vln9ezZU9u2bVOGDBlUuHBhXb58WYcOHVK1atXk5uamS5cuqWTJkgoNDVXXrl3l6enJyOcTqGjRoho7dqwqV66sFStWaP369fb7TApnEwOkv7eHfv36qWXLlqpRo4Y2btwom81mH7mIj4+Xt7e3vvnmG23fvl1r1651dslpFu88pMj8/xQmSfr444/VuHFjhYSEqFSpUvriiy/k4uKiDz74QK1bt9a2bdtUqlQpde7cWbGxsdqyZYvc3NyUkJBgP0Vb1qxZnbk6eMi8vb21ePFiFSlSRJs2bdKCBQsUHx+vZ599Vs2aNVPHjh21Y8cOeXh4yMXFRcYYubu7y8fHx9ml4yGy2WyaM2eOGjdurAwZMihDhgz2+2JiYuTi4qI//vhDW7du1RdffKHffvtNnTp1Uv78+Z1YNZytUKFC+vLLL2WM0cCBA+3HXBA0cTvZs2fX4MGD1aBBAwUHB9vDRWJion0q94ULF1S0aFHlzJnT2eWmXU4cLUEa8Mknn5gcOXKYlStXGmOM6dixo/H09DS9evUy165ds/fbsmWLOXz4sH34OWnqAp5c8fHxJi4uzgQFBZlSpUqZhQsXGmOM+e2338yrr75qChQoYGbNmmWWLFlievToYbJkyWL279/v5KrxMCVNjRs3blyK93/22WemQIECJl++fCZ37twmKirqIVeIR9kff/xh6tata55//nmzadMmZ5eDR8y+fftM9+7dzcGDB83Nmzft7WfPnjXNmzc36dOnN6tXr3ZYpk+fPiYoKMicO3fuYZf72CBYwMGt81L/+9//mlq1apm5c+caY4yZM2eOyZw5s3njjTeMzWYzH3/8sTl16tRtHwNPnqR5q1evXjXGGHP+/HlTtWpV8/zzz9uPudizZ49p166dyZgxo3nmmWdM6dKlzbZt25xWM5wjKirKFClSxOzbt8/+ufHP4ya2b99uNm/ebI4fP+6MEvGI27dvn2ncuLE5evSos0vBIyQ2NtYEBgYam81mChcubLp06WKmTZtmv//KlSumRYsWxtXV1Xz22WcmIiLChIWFmcyZM5udO3c6sfK0j+tYwM7ccgafP/74Q0WLFtWUKVP0+uuvKyoqSk2bNlW3bt3UuXNntW3bVtOmTVO7du3Ur18/5sND0v+2oeXLl2vOnDnq1KmTihUrpj///FP169dXXFyc+vXrp5o1a8pms+nQoUNKnz693N3dlSVLFmeXj4fg1s+ZhQsX6tVXX9WJEyeUM2dO+9nlpL+P67LZbHruueeY4oLbunnzJte8QTJDhw6Vm5ubSpYsqfXr1ysiIkK1atVS5cqV1aFDB7m4uGjEiBGKjIyUt7e3ChYsqI8//ljFixd3dulpGsECkhwP1H7vvfc0YcIEnT17VsYYZcyYUV26dNGFCxcUGRkpT09PffTRR9q0aZP99LL84UeSWbNmqVWrVnr//fdVt25dlStXTpJ08eJF1a9fX/Hx8erdu7dq1qxp34nE48+kcAG7GzduKCgoSEWKFNH48eOVOXNme7/27dsra9as6t+/v9zd3Z1UNYC0avXq1Xrttde0fPlylStXTqdPn9ZXX32l8PBwlS5dWq1atVLjxo3tX4wmJCTI29vbyVWnfRy8DUn/O4PGgQMHdOXKFS1evNh+MGVCQoL2798vd3d3+x/4P/74Q8OGDdOGDRvsZ1bAk+fy5csOt7dv366OHTtq+PDh6tevnz1UnDp1SlmyZNGCBQvk7e2tjz76SCtXrnRGyXCCpLCwadMmDRs2TP369dPMmTPl5eWlLl266Pjx42rdurUOHDigX375RT179tSPP/6oN954g1AB4J5UrVpVb7/9tiIiInTjxg3lzJlT+/btk7+/v4oXL64ffvhBOXLk0BdffCEPDw9CxX3C14WwmzZtmvr27StfX18VK1bMPorh6uqq2rVrq3Pnzrp48aKOHDmihIQEBQQESEr5m0g8/vr16ydPT099+OGHcnV1lc1m0549e5Q/f369/fbbunLliubPn6/vvvtOO3fuVNu2bdW/f3/NnDlTISEhKlq0qLNXAQ+JzWbTrFmz1KZNG9WuXVtXr17V999/r+XLl2v8+PGSpMjISBUrVkz+/v7y8PDQ8uXLmZIAwJIKFSpo+PDhcnd3V9u2bbV69WqtWLFCxYsX18GDB7VkyZJkF1iENQSLJ1hScEj69/r16/Lz89Pu3buVkJAgFxcXxcXFyd3dXe+++67c3Ny0efNmFSxY0D53MSEhQa6urs5eFTiBr6+vgoOD5ebmphs3bsjLy0t58+bV4cOH1blzZ+3YsUNZsmRR7ty5VadOHXXu3FnVq1dX5cqVtXDhQs4z/wQ5cOCAPvjgA4WHh+udd97Rvn37FBQUZB+NCAkJUcuWLbV+/Xplz55dmTNn1lNPPeXkqgGkdY0bN9aoUaPk4eGhHDlyaMmSJfYvLAoVKqSOHTs6ucLHD8dYQFFRUQoICFBiYqLmzJmjvn37KnPmzPrxxx/l5+fncEDlrcdi3NqOJ8c/R6hWrVql1atXq0OHDvLx8dGECRM0Y8YMlStXTi1bttRzzz2nK1euKDg4WBEREapQoQKjXI+pWz8fbrV69WqFhYVp27ZtOnr0qCpXrqzatWtr3LhxkqRNmzYpKCjoYZcL4DGW9Hdm0aJF6tq1qwYPHqzXXnuNvz8PGF8ZPuHWr1+vwMBAjRo1Si4uLmrYsKF69+4tm82mkJAQnT17Vm5uboqLi5PkeDVTQsWT6Z8fyBs3btQXX3yhCRMmKDY2Vu+9955WrlypESNGqGzZsrLZbBoyZIjOnz+vfPnypfgYSPuSQsWRI0cUERGhTz/9VPPmzZMkubq6ysfHR1FRUapcubJq1aql0aNHS5K2bdumadOmaf/+/c4sH8BjJunvTNIXp1FRUQ7teDDYM3zCFS9eXH369FFYWJhcXFz07rvv6vXXX5cxRmPHjlWrVq00ceJErkIJu6Rve44dO6Z8+fKpV69e8vDw0IgRI5SYmKg2bdooT548kqTly5dr2rRpmj9/vpYuXcp29JhKChW7du1S3bp1lT9/fp06dUpnzpzRyJEj1bBhQ+3du1eBgYF6++237cdVSNK3336rvXv3KmvWrE5cAwCPKz8/P/Xt21cdOnRQvXr1VL58eWeX9FhjxOIJktKst8yZM6tLly7q3bu3OnfurDFjxshms6lp06bq2LGjjh49qiFDhjihWjyKkkLF/PnzVbduXX355ZeSpA8//FChoaH6+uuvFRkZqZMnT+r69evat2+fbt68qTVr1ui5555zcvV4EG4NFUFBQXrjjTe0YsUKzZ49W/7+/ho+fLgyZ86scePGyWazydPTU1u2bNHOnTv1/vvva9KkSYqIiOA6JgAemGrVqikwMFC5cuVydimPPY6xeAJ9/vnnypMnj5o2bWpv++uvvzRy5Ej169dPX3/9tdq0aaPExEStXLlS1apV4wBt2C1cuFBNmjTRsGHDFBQUpLJly9rvGzJkiEaOHKn27durY8eO8vX1VWxsrNKnT+/EivGgHT9+XGXLllW1atU0Y8YMe/vLL7+sffv2aevWrcqVK5eWLl2qt956S25ubvLy8lL69OkVGRmpMmXKOK94AE+EpJOM4MFiKtQT4NYDla5cuaIdO3aod+/e8vLy0quvvipJypQpk9555x2tXbtWb7/9tmJiYtSlSxdVr15dkjj7EyRJMTExioiIULdu3fTuu+/a25POHvbRRx/JZrOpT58+8vDw0IcffkioeAIkJCTI399fsbGx2rBhgypVqqTw8HCtWrVKpUqVUqtWrZSQkGA/Q0vWrFmVN29e+fr6MlIB4KEgVDwcjFg85m49S8uBAwdUoEABXbhwQZ999pm++eYbTZ48WQ0aNLD379y5szZt2iRvb2+tXbtWEgc64X/OnTunsmXLavDgwXrjjTccQuut/x8+fLjq1aunIkWKOLNcPET79+9XaGioPDw8lD17ds2bN0/jxo3TCy+8oN9//1379u3T559/ruvXr6tAgQJas2YNpxwGgMcMIxaPsVtDRd++fbVt2za1bt1aDRs2VNeuXZWYmKjWrVvL1dVV9evX1/Xr13XhwgX17t3bPpJB7sStPDw8lDt3bh06dCjZdVDWr1+vqKgodenSRWFhYc4uFQ9ZkSJFNGLECHXq1ElTp07VgAED1LBhQ0lS9uzZVaVKFTVv3ly7d+9W9uzZCRUA8BhixOIJ0Lt3b40dO1bffvutypYtKz8/P0nS0aNHFRERoREjRqhq1ao6d+6c3N3dtXXrVrm6unKu5ydc0u8/ISFB8fHx8vT0lCS1b99ey5YtU2RkpKpWrWrfRnr27Kk1a9Zo4cKFypw5szNLhxMdPHhQHTt2lKurq3r27KkXXnhBEte9AYAnAcHiMbd792795z//0eeff66aNWsmu//69etatGiRli9frmzZsqlv375cURv2ULF48WJ988032r9/vypVqqSQkBCVK1dOVatW1fnz51WnTh3lzZtXO3fu1MyZM7Vu3TqVKlXK2eXDyZKmRRlj1Lt3b1WqVMnZJQEAHgKCxWNu+/btqlWrlhYsWKDAwECH+27evKm4uDilT5/eIUjwzSIkacGCBWrWrJneffddBQQEaMCAAZKkRYsWKV++fOrSpYv27NmjkydPqmjRohowYAChAnb79+9XWFiYLly4oC+++ELPP/+8s0sCADxg7D0+Rm49piJJTEyMrl27pvj4eEl/hwkPDw9J0oYNG3T8+HH95z//sbdJXFH7SZeYmKg///xTQ4cO1YABAxQWFqa4uDiFhoaqWbNmyp07tyQpIiJCknTp0iV5enpyxg04KFKkiIYOHarevXtz7ngAeEIwYvGYuDVUfPnll7p69aq6desmSXrttde0bds2/frrr/bjK65fv64GDRqoRIkSGjZsmNPqxqPj1mNqbty4oUqVKmnevHmKj49XpUqVVKdOHX311VeSpBUrVqh48eLKkSOHM0tGGnDrlxkAgMcbp+V4TCSFig8//FCDBw/W9evXdfToUUlSv3795O/vr2LFiumLL75QeHi4Xn31VZ08eVKDBg1yZtl4hNhsNn3zzTcKDw9XYmKizp8/r7lz56pGjRqqU6eOxowZI+nvg/5Hjx6tnTt3OrlipAWECgB4chAsHiPTp0/XlClTNHv2bPXr10/58+eXJJUpU0YzZsxQSEiIpk6dqkWLFil37tzatm2b3Nzc7NOk8OQxxthPKXzkyBGFhYXJGKN06dKpXbt2ev/991WgQAF99dVX9ilyX3/9tQ4cOKBnn33WmaUDAIBHDFOhHiP9+/fXb7/9ph9//NF+MPY/D8S+ePGifH19OVD7CZbSsThbtmzRsmXLdPHiRQ0fPlyStGfPHg0ZMkSLFy/WRx99JC8vL+3du1ffffed1q5dqzJlyjihegAA8KhijzKNSto5vHVe/MWLF3XkyBElJibar0Ph5uam2NhYrVixQrVr11aWLFnsj5F0P54cSdvN8ePHtWTJEl29elU5cuTQxo0bFRkZqZdeesnet3jx4urRo4eefvppjR49Wn5+fsqbN682btyoEiVKOHEtAADAo4gRizRo2rRp+vnnn9WtWzflzZtXGTNmlCRNmDBBn3zyiUaPHq3q1avbz9Lz559/ql69eurSpYsaN27szNLhREmhYteuXXr11VeVOXNmHTx4UJ6enqpSpYqyZ8+uyZMn6+eff1aVKlUclo2JiVHGjBl148YNzv4EAABSRLBIYy5duqSAgABdvnxZfn5+CggIUJUqVfTWW29JkurVq6fff/9dH3/8sSpVqqS4uDh98MEHio6O1oYNG7jo3RPq1lARFBSkzp07q1u3bvr999/19ddfa9myZerevbuWLVumw4cPa8yYMapUqZKMMfZlbTYbV2MHAACpIlikMQkJCerdu7fy58+vwMBArVy5UgMHDlT16tVVrVo1tW/fXv/5z3906tQpbd68WaVLl5aXl5fWrl0rd3d3rqj9BDt+/LjKli2ratWqacaMGfb2OXPm6K233tKqVat08+ZNDR06VPv379eYMWNUsWJFwgQAALgjnBUqjXF1dVWVKlX00Ucfyc3NTR988IHOnDmj4sWLq3PnzqpRo4YCAgL03nvvafny5Ro/frw2bNggd3d3xcfHEyqeYAkJCfL391dsbKzWr19vb/fz81NCQoISExNVvnx5hYaG6plnnlHz5s21ZcsWQgUAALgjjFikUZ06dZIxRqNHj5b094G2RYsWVaFChfT7779r0aJFmjx5skJCQiSlfCYgPHn279+v0NBQJSYmKiIiQnny5FHhwoUVEhKioUOH2vutXLlSU6ZMUZ8+fVSwYEEnVgwAANIKgkUaFRkZqUmTJmn+/PmqXr260qVLp0WLFsnHx0dnzpzRunXr1KBBA876hGT279+v9957T9euXdOuXbvUsmVLffHFF5IcTz98/fp1eXt7O7NUAACQhvAVdhrVpk0b3bx5U9myZZOPj4/mz58vHx8fSVKOHDnUpEkTLn6HFBUpUkQjRoyQq6urfHx81KBBA/t9SacplkSoAAAAd4VgkQYl7fiFhoaqePHi+vzzz5UlSxalNPjEiAVSUqRIEY0fP17FihXTZ599pg0bNkiSbDYbx1QAAIB7QrBIg5J2/KpVq6bo6GgtW7bMoR24E4ULF9bIkSPl7u6uDz74QJs3b3Z2SQAAIA0jWKRhuXPnVo8ePTRs2DDt3bvX2eUgDSpSpIiGDh2qPHnyKFeuXM4uBwAApGEcvJ3GHTx4UAMGDNCkSZM46xPu2c2bN+Xh4eHsMgAAQBpGsHgMJF3AjIvfAQAAwFkIFgAAAAAsY+4MAAAAAMsIFgAAAAAsI1gAAAAAsIxgAQAAAMAyggUAAAAAywgWAAAAACwjWAAAAACwjGABAAAAwDKCBQAAAADLCBYAAAAALPs/JoKeqMjfLXMAAAAASUVORK5CYII=\",\n \"text/plain\": [\n \"
\"\n ]\n },\n \"metadata\": {},\n \"output_type\": \"display_data\"\n },\n {\n \"name\": \"stdout\",\n \"output_type\": \"stream\",\n \"text\": [\n \"\\n\",\n \"šŸ’¾ Results saved to moderation_results_gpt4all_20250812_085149.csv\\n\"\n ]\n }\n ],\n \"source\": [\n \"# Evaluate\\n\",\n \"y_true, y_pred = sample_df[\\\"label\\\"], predictions\\n\",\n \"metrics = {\\n\",\n \" \\\"Accuracy\\\": accuracy_score(y_true, y_pred),\\n\",\n \" \\\"Precision\\\": precision_score(y_true, y_pred),\\n\",\n \" \\\"Recall\\\": recall_score(y_true, y_pred),\\n\",\n \" \\\"F1\\\": f1_score(y_true, y_pred),\\n\",\n \" \\\"AUC\\\": roc_auc_score(y_true, y_pred)\\n\",\n \"}\\n\",\n \"\\n\",\n \"print(\\\"\\\\nšŸ“Š Metrics:\\\")\\n\",\n \"for k, v in metrics.items():\\n\",\n \" print(f\\\"{k}: {v:.4f}\\\")\\n\",\n \"\\n\",\n \"generate_performance_report(y_true, y_pred, inference_times)\\n\",\n \"\\n\",\n \"\\n\",\n \"# Confusion Matrix\\n\",\n \"cm = confusion_matrix(y_true, y_pred)\\n\",\n \"disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=[\\\"Not Toxic\\\", \\\"Toxic\\\"])\\n\",\n \"disp.plot(cmap=plt.cm.Blues)\\n\",\n \"plt.title(\\\"Confusion Matrix\\\")\\n\",\n \"plt.tight_layout()\\n\",\n \"plt.show()\\n\",\n \"\\n\",\n \"# Bar Plot of Metrics\\n\",\n \"plt.figure(figsize=(8, 5))\\n\",\n \"sns.barplot(x=list(metrics.keys()), y=list(metrics.values()), palette=\\\"mako\\\")\\n\",\n \"plt.title(\\\"Model Performance Metrics (Balanced Sample)\\\")\\n\",\n \"plt.ylabel(\\\"Score\\\")\\n\",\n \"plt.ylim(0, 1)\\n\",\n \"plt.xticks(rotation=45)\\n\",\n \"plt.tight_layout()\\n\",\n \"plt.show()\\n\",\n \"\\n\",\n \"# Save results\\n\",\n \"results_df = pd.DataFrame({\\n\",\n \" 'text': sample_df[\\\"text\\\"],\\n\",\n \" 'true_label': y_true,\\n\",\n \" 'predicted_label': y_pred,\\n\",\n \" 'inference_time_ms': np.array(inference_times) * 1000\\n\",\n \"})\\n\",\n \"timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')\\n\",\n \"results_df.to_csv(f'moderation_results_gpt4all_{timestamp}.csv', index=False)\\n\",\n \"print(f\\\"\\\\nšŸ’¾ Results saved to moderation_results_gpt4all_{timestamp}.csv\\\") \"\n ]\n },\n {\n \"cell_type\": \"markdown\",\n \"id\": \"c0667bc6-9ccd-4cc6-9567-501cdaae88ff\",\n \"metadata\": {},\n \"source\": [\n \"# Debugging\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": 14,\n \"id\": \"f6fb62d9-2649-47ef-b959-5c9ea5b81e34\",\n \"metadata\": {},\n \"outputs\": [\n {\n \"name\": \"stdout\",\n \"output_type\": \"stream\",\n \"text\": [\n \"Model configuration completed\\n\"\n ]\n }\n ],\n \"source\": [\n \"# Model configuration\\n\",\n \"MODEL_TYPE = \\\"deepseek\\\" # Options: \\\"deepseek\\\", \\\"gpt4all\\\", \\\"mistral\\\"\\n\",\n \"DEEPSEEK_MODEL = \\\"deepseek-ai/DeepSeek-R1-Distill-Llama-8B\\\"\\n\",\n \"GPT4ALL_MODEL = \\\"Meta-Llama-3-8B-Instruct.Q4_0.gguf\\\"\\n\",\n \"GPT4ALL_MODEL_PATH = \\\"/home/sagemaker-user/harmfull-detection/models/\\\"\\n\",\n \"MISTRAL_MODEL = \\\"/tmp/models/mistral-7b-v0-2\\\"\\n\",\n \"# Initialize clients\\n\",\n \"if MODEL_TYPE == \\\"deepseek\\\":\\n\",\n \" client = OpenAI(\\n\",\n \" api_key=os.getenv(\\\"DEEPSEEK_API_KEY\\\"),\\n\",\n \" base_url=\\\"http://k8s-deepseek-deepseek-e92cca8149-b20547a64509f06f.elb.eu-west-1.amazonaws.com/v1\\\"\\n\",\n \" )\\n\",\n \"elif MODEL_TYPE == \\\"mistral\\\":\\n\",\n \" client = OpenAI(\\n\",\n \" api_key=os.getenv(\\\"MISTRAL_API_KEY\\\"),\\n\",\n \" base_url=\\\"http://vllm-serve-svc-pub-288545519.us-west-2.elb.amazonaws.com/v1\\\"\\n\",\n \" ) \\n\",\n \"elif MODEL_TYPE == \\\"gpt4all\\\":\\n\",\n \" if GPT4All is None:\\n\",\n \" raise ImportError(\\\"Install gpt4all: pip install gpt4all\\\")\\n\",\n \" \\n\",\n \" model_file = os.path.join(GPT4ALL_MODEL_PATH, GPT4ALL_MODEL)\\n\",\n \" if os.path.exists(model_file):\\n\",\n \" print(f\\\"Loading cached model from {model_file}\\\")\\n\",\n \" client = GPT4All(model_name=GPT4ALL_MODEL, model_path=GPT4ALL_MODEL_PATH, allow_download=False)\\n\",\n \" else:\\n\",\n \" print(f\\\"Downloading model to {GPT4ALL_MODEL_PATH}\\\")\\n\",\n \" os.makedirs(GPT4ALL_MODEL_PATH, exist_ok=True)\\n\",\n \" client = GPT4All(model_name=GPT4ALL_MODEL, model_path=GPT4ALL_MODEL_PATH)\\n\",\n \"\\n\",\n \"def predict_with_model(text):\\n\",\n \" prompt = f'Analyze this message and respond ONLY with JSON: {{\\\"action\\\": \\\"allow|warn|block|timeout\\\", \\\"confidence\\\": 0.0-1.0, \\\"categories\\\": [\\\"list of violation types]}}: \\\"{text}\\\"'\\n\",\n \" \\n\",\n \" try:\\n\",\n \" if MODEL_TYPE == \\\"deepseek\\\":\\n\",\n \" response = client.chat.completions.create(\\n\",\n \" model=DEEPSEEK_MODEL,\\n\",\n \" messages=[\\n\",\n \" {\\\"role\\\": \\\"system\\\", \\\"content\\\": \\\"You are a content moderation assistant. Respond only with JSON.\\\"},\\n\",\n \" {\\\"role\\\": \\\"user\\\", \\\"content\\\": prompt}\\n\",\n \" ],\\n\",\n \" temperature=0\\n\",\n \" )\\n\",\n \" reply = response.choices[0].message.content.strip()\\n\",\n \" \\n\",\n \" elif MODEL_TYPE == \\\"gpt4all\\\":\\n\",\n \" with client.chat_session():\\n\",\n \" reply = client.generate(prompt, max_tokens=1024)\\n\",\n \" \\n\",\n \" print(\\\"Model output:\\\", reply) # Add before json_match\\n\",\n \" \\n\",\n \" json_match = re.search(r'\\\\{.*\\\\}', reply, re.DOTALL)\\n\",\n \" if json_match:\\n\",\n \" result = json.loads(json_match.group())\\n\",\n \" return 1 if result.get(\\\"action\\\", \\\"\\\").upper() == \\\"BLOCK\\\" else 0\\n\",\n \" return 0\\n\",\n \" except:\\n\",\n \" return 0\\n\",\n \"\\n\",\n \"def measure_inference_times(texts, predict_fn):\\n\",\n \" times, predictions = [], []\\n\",\n \" for text in tqdm(texts, desc=\\\"Processing texts\\\"):\\n\",\n \" start = time.time()\\n\",\n \" pred = predict_fn(text)\\n\",\n \" times.append(time.time() - start)\\n\",\n \" predictions.append(pred)\\n\",\n \" return predictions, times\\n\",\n \"\\n\",\n \"def generate_performance_report(y_true, y_pred, inference_times=None):\\n\",\n \" print(\\\"\\\\nšŸ“Š Classification Report:\\\")\\n\",\n \" print(classification_report(y_true, y_pred))\\n\",\n \" \\n\",\n \" if inference_times:\\n\",\n \" times_ms = np.array(inference_times) * 1000\\n\",\n \" print(f\\\"\\\\nā±ļø Mean inference time: {np.mean(times_ms):.2f}ms\\\")\\n\",\n \"\\n\",\n \"print(\\\"Model configuration completed\\\")\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": 15,\n \"id\": \"b0bba8bd-8a96-469c-bb22-9d31ed543389\",\n \"metadata\": {},\n \"outputs\": [\n {\n \"name\": \"stdout\",\n \"output_type\": \"stream\",\n \"text\": [\n \"Model output: Okay, so I need to analyze this message: \\\"You are a terrible person!\\\" and decide whether to allow, warn, block, or timeout the user, along with the confidence level and the category of violation. \\n\",\n \"\\n\",\n \"First, I should consider what the message is saying. The user is calling someone a \\\"terrible person.\\\" That's a strong, derogatory term. It's clearly offensive and intended to insult the recipient. Such language can be hurtful and is likely to create a negative environment.\\n\",\n \"\\n\",\n \"Next, I should think about the context. Without knowing the specific situation, I can assume that using such harsh language is inappropriate. It's a personal attack that goes beyond just expressing strong opinions. The term \\\"terrible person\\\" is a direct insult and can be considered hate speech or at least a form of abuse.\\n\",\n \"\\n\",\n \"Now, considering the categories, this definitely falls under \\\"abusive language\\\" because it's meant to demean someone. It's not just a casual insult; it's more severe. The confidence level should be high because the message is clearly violating guidelines against hate speech and abuse.\\n\",\n \"\\n\",\n \"So, the action should be to block the user to prevent further abuse. The confidence is 1.0 because the violation is clear and severe. The category is \\\"abusive language.\\\"\\n\",\n \"\\n\",\n \"\\n\",\n \"```json\\n\",\n \"{\\n\",\n \" \\\"action\\\": \\\"block\\\",\\n\",\n \" \\\"confidence\\\": 1.0,\\n\",\n \" \\\"categories\\\": [\\\"abusive language\\\"]\\n\",\n \"}\\n\",\n \"```\\n\",\n \"Moderation result (1=toxic, 0=non-toxic): 1\\n\"\n ]\n }\n ],\n \"source\": [\n \"# Test the function\\n\",\n \"test_text = \\\"You are a terrible person!\\\"\\n\",\n \"result = predict_with_model(test_text)\\n\",\n \"print(f\\\"Moderation result (1=toxic, 0=non-toxic): {result}\\\")\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": 16,\n \"id\": \"129fc559-cfcc-4bc4-80b1-e308703ff974\",\n \"metadata\": {},\n \"outputs\": [\n {\n \"name\": \"stdout\",\n \"output_type\": \"stream\",\n \"text\": [\n \"Model output: Okay, so I need to analyze this message and decide whether to allow, warn, block, or timeout the user. The message is pretty harsh, calling the user an idiot and accusing them of spreading hate. The user is questioning the number of German civilians killed after WWII and links it to Jews, which is a sensitive and offensive topic. They also mention Stanford, implying the user is educated but is using that knowledge to spread harmful information. The tone is confrontational and uses derogatory language, which could escalate tensions. I should consider the categories like hate speech, anti-Semitism, and harassment. The confidence is high because the content is clearly offensive and harmful. So, the action should be block, confidence 1.0, and categories as hate speech, anti-Semitism, and harassment.\\n\",\n \"\\n\",\n \"\\n\",\n \"```json\\n\",\n \"{\\n\",\n \" \\\"action\\\": \\\"block\\\",\\n\",\n \" \\\"confidence\\\": 1.0,\\n\",\n \" \\\"categories\\\": [\\\"hate speech\\\", \\\"anti-Semitism\\\", \\\"harassment\\\"]\\n\",\n \"}\\n\",\n \"```\\n\",\n \"Moderation result (1=toxic, 0=non-toxic): 1\\n\"\n ]\n }\n ],\n \"source\": [\n \"# Test the function\\n\",\n \"test_text = \\\"\\\"\\\"\\n\",\n \"\\\"The German government, apparently, puts the number of German citizens killed in the terrible disruption after WWII at 2 to 2.5 million. Other estimates are lower . . . as much as 2/3's lower. Is it really your contention that they were all massacred by Jews? \\n\",\n \"\\n\",\n \"Did they teach you this pestiferous crap at Stanford? You should ask for your money back. !\\\"\\n\",\n \"\\\"\\\"\\\"\\n\",\n \"\\n\",\n \"result = predict_with_model(test_text)\\n\",\n \"# print(f\\\"Ground Truth: 1 - toxic in original downloaded dataset. This will be corrected\\\")\\n\",\n \"print(f\\\"Moderation result (1=toxic, 0=non-toxic): {result}\\\")\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": 17,\n \"id\": \"28a6d36c-69db-4954-a536-d65585dba0a1\",\n \"metadata\": {},\n \"outputs\": [\n {\n \"name\": \"stdout\",\n \"output_type\": \"stream\",\n \"text\": [\n \"Model output: Alright, so I need to analyze this message and decide whether to allow, warn, block, or timeout the user. The message is about political motivations, infrastructure like high-speed rail and Maglev, and some economic aspects. \\n\",\n \"\\n\",\n \"First, I'll read through the message carefully. The user is discussing both political and infrastructure topics. They mention political motivations but then quickly clarify they want to know people's actual thoughts, not just party lines. That seems neutral.\\n\",\n \"\\n\",\n \"Next, they talk about a high-speed transit project from Windsor to Toronto and possibly Toronto to Montreal. They note that infrastructure can foster growth but also mention the cost factor, which could be a concern for people. They compare HSR and Maglev, noting that Maglev is more expensive but has lower maintenance costs and is quieter, which might reduce NIMBY issues. They end with a positive note about future infrastructure.\\n\",\n \"\\n\",\n \"I need to categorize this. The user is sharing their thoughts on infrastructure and policy, which could be related to public discussion. They're not promoting hate speech, spam, or anything harmful. They're expressing opinions and comparing different transit options.\\n\",\n \"\\n\",\n \"So, the categories here would be \\\"Public Discussion\\\" and \\\"Infrastructure.\\\" The action should be \\\"allow\\\" because the content is constructive and doesn't violate any policies. Confidence is high because there's no indication of issues.\\n\",\n \"\\n\",\n \"\\n\",\n \"```json\\n\",\n \"{\\n\",\n \" \\\"action\\\": \\\"allow\\\",\\n\",\n \" \\\"confidence\\\": 0.9,\\n\",\n \" \\\"categories\\\": [\\\"Public Discussion\\\", \\\"Infrastructure\\\"]\\n\",\n \"}\\n\",\n \"```\\n\",\n \"Moderation result (1=toxic, 0=non-toxic): 0\\n\"\n ]\n }\n ],\n \"source\": [\n \"# Test the function\\n\",\n \"test_text = \\\"\\\"\\\"\\n\",\n \"\\\"Political motivations, and parties aside. I would love to know peoples actual thoughts on this. Good. Bad? Could we actually get bipartisan support or is it a pipe dream. \\n\",\n \"\\n\",\n \"Additionally, the idea of a high speed transit in the windsor to toronto, and maybe in the future toronto to montreal corridors (which is like half of Canada's population) is one that may be interesting. There isn't much debate that infrastructure like this can massively foster growth along the route, but there is also the price factor. People don't like it in their backyard. \\n\",\n \"\\n\",\n \"Also, since this will be costly regardless, I would be curious price comparisons between HSR and Maglev. Mostly because the latter is more expensive but will require reduced maintenance costs whilst also having the advantage of being far quieter, likely reducing \\\"\\\"NIMBY\\\"\\\" BS. Not to mention it would be a great selling point of \\\"\\\"hey, look at our futuresque shit that travels at speeds that rival planes\\\"\\\".\\\"\\n\",\n \"\\\"\\\"\\\"\\n\",\n \"result = predict_with_model(test_text)\\n\",\n \"# print(f\\\"Ground Truth: 1 - toxic in original downloaded dataset. This will be corrected\\\")\\n\",\n \"print(f\\\"Moderation result (1=toxic, 0=non-toxic): {result}\\\")\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": 18,\n \"id\": \"87f4dc26-5036-4b99-ab21-bc1e2f7a44b7\",\n \"metadata\": {},\n \"outputs\": [\n {\n \"name\": \"stdout\",\n \"output_type\": \"stream\",\n \"text\": [\n \"Model output: Okay, so I need to analyze this message and decide whether to allow, warn, block, or timeout the user. The message says, \\\"Merkel smart and progressive. Trump not in the least bit smart and utterly regressive. The US will be the unconditional loser as the world turns away, in everything from trade and tourism to science and collaboration. What an utter and avoidable waste. aMErica.\\\"\\n\",\n \"\\n\",\n \"First, I'll read through the message carefully. It's comparing Angela Merkel positively as smart and progressive, while describing Donald Trump as not smart and regressive. The user then goes on to predict that the US will lose in various areas because of this, calling it a waste.\\n\",\n \"\\n\",\n \"I need to check if this violates any content policies. The categories I can use are things like hate speech, violence, harassment, adult content, spam, etc. The message is political, expressing opinions about political figures. While strong opinions can be polarizing, I don't see any direct threats, hate speech, or other prohibited content.\\n\",\n \"\\n\",\n \"However, the user is making a statement that could be seen as disrespectful towards Trump. But without any incitement to violence or other harmful actions, it might fall under free speech. Unless the policy strictly prohibits political opinions, which I don't think it does.\\n\",\n \"\\n\",\n \"So, considering the content, it's more of an opinionated statement rather than a violation. Therefore, the appropriate action would be to allow the message.\\n\",\n \"\\n\",\n \"\\n\",\n \"```json\\n\",\n \"{\\n\",\n \" \\\"action\\\": \\\"allow\\\",\\n\",\n \" \\\"confidence\\\": 0.9,\\n\",\n \" \\\"categories\\\": []\\n\",\n \"}\\n\",\n \"```\\n\",\n \"Moderation result (1=toxic, 0=non-toxic): 0\\n\"\n ]\n }\n ],\n \"source\": [\n \"# Test the function\\n\",\n \"test_text = \\\"\\\"\\\"\\n\",\n \"Merkel smart and progressive. Trump not in the least bit smart and utterly regressive. The US will be the unconditional loser as the world turns away, in everything from trade and tourism to science and collaboration. What an utter and avoidable waste. aMErica.\\n\",\n \"\\\"\\\"\\\"\\n\",\n \"result = predict_with_model(test_text)\\n\",\n \"# print(f\\\"Ground Truth: 1 - toxic in original downloaded dataset. This will be corrected\\\")\\n\",\n \"print(f\\\"Moderation result (1=toxic, 0=non-toxic): {result}\\\")\"\n ]\n },\n {\n \"cell_type\": \"code\",\n \"execution_count\": null,\n \"id\": \"17885ec8-8082-4e4d-b973-9cbc7f0265a7\",\n \"metadata\": {},\n \"outputs\": [],\n \"source\": []\n }\n ],\n \"metadata\": {\n \"kernelspec\": {\n \"display_name\": \"Python 3 (ipykernel)\",\n \"language\": \"python\",\n \"name\": \"python3\"\n },\n \"language_info\": {\n \"codemirror_mode\": {\n \"name\": \"ipython\",\n \"version\": 3\n },\n \"file_extension\": \".py\",\n \"mimetype\": \"text/x-python\",\n \"name\": \"python\",\n \"nbconvert_exporter\": \"python\",\n \"pygments_lexer\": \"ipython3\",\n \"version\": \"3.12.9\"\n }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 5\n}\n"}}}}