{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "0",
   "metadata": {},
   "source": [
    "# PyRIT Initializers\n",
    "\n",
    "You can configure PyRIT using:\n",
    "1. **Built-in initializers** - TargetInitializer, ScorerInitializer, TechniqueInitializer, LoadDefaultDatasets\n",
    "2. **External scripts** - Custom PyRITInitializer classes for project-specific needs\n",
    "\n",
    "## Execution Order\n",
    "\n",
    "When `initialize_pyrit_async` is called:\n",
    "1. Environment files are loaded (`.env`, `.env.local`)\n",
    "2. Memory database is configured\n",
    "3. Initializers execute in the order they are passed\n",
    "\n",
    "## Creating an Initializer"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1",
   "metadata": {},
   "source": [
    "The following is a minimal `PyRITInitializer` class. It doesn't need much! In this case, it sets the default value for temperature for all OpenAIChatTargets to .9."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<__main__.CustomInitializer at 0x1d5a2fdb440>"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from pyrit.common.apply_defaults import set_default_value\n",
    "from pyrit.prompt_target import OpenAIChatTarget\n",
    "from pyrit.setup.pyrit_initializer import PyRITInitializer\n",
    "\n",
    "\n",
    "class CustomInitializer(PyRITInitializer):\n",
    "    \"\"\"Sets custom temperature for OpenAI targets.\"\"\"\n",
    "\n",
    "    async def initialize_async(self) -> None:\n",
    "        set_default_value(class_type=OpenAIChatTarget, parameter_name=\"temperature\", value=0.9)\n",
    "\n",
    "\n",
    "CustomInitializer()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3",
   "metadata": {},
   "source": [
    "## Built-in Initializers\n",
    "\n",
    "PyRIT includes a few built-in initializers that set more intelligent defaults!\n",
    "\n",
    "- **TargetInitializer**: Registers targets from environment variables. With only OPENAI_CHAT_ENDPOINT, OPENAI_CHAT_MODEL, and OPENAI_CHAT_KEY set, it registers a sensible default objective/converter target.\n",
    "- **ScorerInitializer**: Registers default scorers (run it after TargetInitializer, since scorers use those targets).\n",
    "- **TechniqueInitializer**: Registers the attack techniques used by scenarios.\n",
    "- **LoadDefaultDatasets**: Loads the datasets required by registered scenarios into memory.\n",
    "\n",
    "These are easy to include."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Found default environment files: ['./.pyrit/.env', './.pyrit/.env.local']\n",
      "Loaded environment file: ./.pyrit/.env\n",
      "Loaded environment file: ./.pyrit/.env.local\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "No new upgrade operations detected.\n"
     ]
    }
   ],
   "source": [
    "from pyrit.setup import initialize_pyrit_async\n",
    "from pyrit.setup.initializers import ScorerInitializer, TargetInitializer\n",
    "\n",
    "# Using built-in initializers\n",
    "await initialize_pyrit_async(  # type: ignore\n",
    "    memory_db_type=\"InMemory\", initializers=[TargetInitializer(), ScorerInitializer()]\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5",
   "metadata": {},
   "source": [
    "## External Scripts\n",
    "\n",
    "External scripts allow custom configurations without modifying PyRIT. For example, you can write your own library, include them, and never have to check out pyrit in editable mode. Here are some use cases:\n",
    "- Custom targets for security assessments\n",
    "- Project-specific defaults\n",
    "- Organization-specific defaults\n",
    "\n",
    "As an example, say you are building a product, and want to set all your `adversarial_chat` in one place. You can using this!\n",
    "\n",
    "Like the built-in initializers, external scripts have the same format and must contain PyRITInitializer classes. In fact, using something like TargetInitializer() as a template for your own is not a bad place to start."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Created: ./AppData/Local/Temp/tmprs016r1e/custom_init.py\n",
      "Found default environment files: ['./.pyrit/.env', './.pyrit/.env.local']\n",
      "Loaded environment file: ./.pyrit/.env\n",
      "Loaded environment file: ./.pyrit/.env.local\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import shutil\n",
    "import tempfile\n",
    "\n",
    "from pyrit.setup import initialize_pyrit_async\n",
    "\n",
    "temp_dir = tempfile.mkdtemp()\n",
    "script_path = os.path.join(temp_dir, \"custom_init.py\")\n",
    "\n",
    "# This is the simple custom initializer from the \"Creating an Initializer\" section of this notebook\n",
    "script_content = \"\"\"\n",
    "from pyrit.setup.pyrit_initializer import PyRITInitializer\n",
    "from pyrit.common.apply_defaults import set_default_value\n",
    "from pyrit.prompt_target import OpenAIChatTarget\n",
    "\n",
    "class CustomInitializer(PyRITInitializer):\n",
    "    \\\"\\\"\\\"Sets custom temperature for OpenAI targets.\\\"\\\"\\\"\n",
    "\n",
    "    async def initialize_async(self) -> None:\n",
    "        set_default_value(class_type=OpenAIChatTarget, parameter_name=\"temperature\", value=0.9)\n",
    "\n",
    "\"\"\"\n",
    "\n",
    "with open(script_path, \"w\") as f:\n",
    "    f.write(script_content)\n",
    "\n",
    "print(f\"Created: {script_path}\")\n",
    "\n",
    "await initialize_pyrit_async(  # type: ignore\n",
    "    memory_db_type=\"InMemory\", initialization_scripts=[temp_dir + \"/custom_init.py\"]\n",
    ")\n",
    "\n",
    "if os.path.exists(temp_dir):\n",
    "    shutil.rmtree(temp_dir)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7",
   "metadata": {},
   "source": [
    "The initialization_scripts argument ultimately uses `pathlib.Path`, so the scripts are loaded relative to the current working directory (where you're executing the script from, not where PyRIT library is). To avoid ambiguity, it is usually better to use full paths if possible."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8",
   "metadata": {},
   "source": [
    "## More information:\n",
    "- [Configuration notebook](1_configuration.ipynb) shows practical examples with custom targets\n",
    "- [Default Values notebook](default_values.md) explains how defaults work\n"
   ]
  }
 ],
 "metadata": {
  "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.12.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
