{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# How to create custom callback handlers\n",
    "\n",
    ":::info Prerequisites\n",
    "\n",
    "This guide assumes familiarity with the following concepts:\n",
    "\n",
    "- [Callbacks](/docs/concepts/#callbacks)\n",
    "\n",
    ":::\n",
    "\n",
    "LangChain has some built-in callback handlers, but you will often want to create your own handlers with custom logic.\n",
    "\n",
    "To create a custom callback handler, we need to determine the [event(s)](https://api.python.langchain.com/en/latest/callbacks/langchain_core.callbacks.base.BaseCallbackHandler.html#langchain-core-callbacks-base-basecallbackhandler) we want our callback handler to handle as well as what we want our callback handler to do when the event is triggered. Then all we need to do is attach the callback handler to the object, for example via [the constructor](/docs/how_to/callbacks_constructor) or [at runtime](/docs/how_to/callbacks_runtime).\n",
    "\n",
    "In the example below, we'll implement streaming with a custom handler.\n",
    "\n",
    "In our custom callback handler `MyCustomHandler`, we implement the `on_llm_new_token` handler to print the token we have just received. We then attach our custom handler to the model object as a constructor callback."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# | output: false\n",
    "# | echo: false\n",
    "\n",
    "%pip install -qU langchain langchain_anthropic\n",
    "\n",
    "import getpass\n",
    "import os\n",
    "\n",
    "os.environ[\"ANTHROPIC_API_KEY\"] = getpass.getpass()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "My custom handler, token: Here\n",
      "My custom handler, token: 's\n",
      "My custom handler, token:  a\n",
      "My custom handler, token:  bear\n",
      "My custom handler, token:  joke\n",
      "My custom handler, token:  for\n",
      "My custom handler, token:  you\n",
      "My custom handler, token: :\n",
      "My custom handler, token: \n",
      "\n",
      "Why\n",
      "My custom handler, token:  di\n",
      "My custom handler, token: d the\n",
      "My custom handler, token:  bear\n",
      "My custom handler, token:  dissol\n",
      "My custom handler, token: ve\n",
      "My custom handler, token:  in\n",
      "My custom handler, token:  water\n",
      "My custom handler, token: ?\n",
      "My custom handler, token: \n",
      "Because\n",
      "My custom handler, token:  it\n",
      "My custom handler, token:  was\n",
      "My custom handler, token:  a\n",
      "My custom handler, token:  polar\n",
      "My custom handler, token:  bear\n",
      "My custom handler, token: !\n"
     ]
    }
   ],
   "source": [
    "from langchain_anthropic import ChatAnthropic\n",
    "from langchain_core.callbacks import BaseCallbackHandler\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "\n",
    "\n",
    "class MyCustomHandler(BaseCallbackHandler):\n",
    "    def on_llm_new_token(self, token: str, **kwargs) -> None:\n",
    "        print(f\"My custom handler, token: {token}\")\n",
    "\n",
    "\n",
    "prompt = ChatPromptTemplate.from_messages([\"Tell me a joke about {animal}\"])\n",
    "\n",
    "# To enable streaming, we pass in `streaming=True` to the ChatModel constructor\n",
    "# Additionally, we pass in our custom handler as a list to the callbacks parameter\n",
    "model = ChatAnthropic(\n",
    "    model=\"claude-3-sonnet-20240229\", streaming=True, callbacks=[MyCustomHandler()]\n",
    ")\n",
    "\n",
    "chain = prompt | model\n",
    "\n",
    "response = chain.invoke({\"animal\": \"bears\"})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can see [this reference page](https://api.python.langchain.com/en/latest/callbacks/langchain_core.callbacks.base.BaseCallbackHandler.html#langchain-core-callbacks-base-basecallbackhandler) for a list of events you can handle. Note that the `handle_chain_*` events run for most LCEL runnables.\n",
    "\n",
    "## Next steps\n",
    "\n",
    "You've now learned how to create your own custom callback handlers.\n",
    "\n",
    "Next, check out the other how-to guides in this section, such as [how to attach callbacks to a runnable](/docs/how_to/callbacks_attach)."
   ]
  }
 ],
 "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.10.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
