{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Log, Trace, and Monitor Langchain LLM Calls\n",
    "\n",
    "When building apps or agents using Langchain, you end up making multiple API calls to fulfill a single user request. However, these requests are not chained when you want to analyse them. With [**Portkey**](/docs/ecosystem/integrations/portkey), all the embeddings, completion, and other requests from a single user request will get logged and traced to a common ID, enabling you to gain full visibility of user interactions.\n",
    "\n",
    "This notebook serves as a step-by-step guide on how to integrate and use Portkey in your Langchain app."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First, let's import Portkey, OpenAI, and Agent tools"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "from langchain.agents import AgentType, initialize_agent, load_tools\n",
    "from langchain.llms import OpenAI\n",
    "from langchain.utilities import Portkey"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Paste your OpenAI API key below. [(You can find it here)](https://platform.openai.com/account/api-keys)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "os.environ[\"OPENAI_API_KEY\"] = \"<OPENAI_API_KEY>\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Get Portkey API Key\n",
    "1. Sign up for [Portkey here](https://app.portkey.ai/login)\n",
    "2. On your [dashboard](https://app.portkey.ai/), click on the profile icon on the top left, then click on \"Copy API Key\"\n",
    "3. Paste it below"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "PORTKEY_API_KEY = \"<PORTKEY_API_KEY>\"  # Paste your Portkey API Key here"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Set Trace ID\n",
    "1. Set the trace id for your request below\n",
    "2. The Trace ID can be common for all API calls originating from a single request"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "TRACE_ID = \"portkey_langchain_demo\"  # Set trace id here"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Generate Portkey Headers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "headers = Portkey.Config(\n",
    "    api_key=PORTKEY_API_KEY,\n",
    "    trace_id=TRACE_ID,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Run your agent as usual. The **only** change is that we will **include the above headers** in the request now."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "llm = OpenAI(temperature=0, headers=headers)\n",
    "tools = load_tools([\"serpapi\", \"llm-math\"], llm=llm)\n",
    "agent = initialize_agent(\n",
    "    tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True\n",
    ")\n",
    "\n",
    "# Let's test it out!\n",
    "agent.run(\n",
    "    \"What was the high temperature in SF yesterday in Fahrenheit? What is that number raised to the .023 power?\"\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## How Logging & Tracing Works on Portkey\n",
    "\n",
    "**Logging**\n",
    "- Sending your request through Portkey ensures that all of the requests are logged by default\n",
    "- Each request log contains `timestamp`, `model name`, `total cost`, `request time`, `request json`, `response json`, and additional Portkey features\n",
    "\n",
    "**Tracing**\n",
    "- Trace id is passed along with each request and is visibe on the logs on Portkey dashboard\n",
    "- You can also set a **distinct trace id** for each request if you want\n",
    "- You can append user feedback to a trace id as well. [More info on this here](https://docs.portkey.ai/key-features/feedback-api)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Advanced LLMOps Features - Caching, Tagging, Retries\n",
    "\n",
    "In addition to logging and tracing, Portkey provides more features that add production capabilities to your existing workflows:\n",
    "\n",
    "**Caching**\n",
    "\n",
    "Respond to previously served customers queries from cache instead of sending them again to OpenAI. Match exact strings OR semantically similar strings. Cache can save costs and reduce latencies by 20x.\n",
    "\n",
    "**Retries**\n",
    "\n",
    "Automatically reprocess any unsuccessful API requests **`upto 5`** times. Uses an **`exponential backoff`** strategy, which spaces out retry attempts to prevent network overload.\n",
    "\n",
    "| Feature | Config Key | Value (Type) |\n",
    "| -- | -- | -- |\n",
    "| [🔁 Automatic Retries](https://docs.portkey.ai/key-features/automatic-retries) | `retry_count` | `integer` [1,2,3,4,5] |\n",
    "| [🧠 Enabling Cache](https://docs.portkey.ai/key-features/request-caching) | `cache` | `simple` OR `semantic` |\n",
    "\n",
    "**Tagging**\n",
    "\n",
    "Track and audit ach user interaction in high detail with predefined tags.\n",
    "\n",
    "| Tag | Config Key | Value (Type) |\n",
    "| -- | -- | -- |\n",
    "| User Tag | `user` | `string` |\n",
    "| Organisation Tag | `organisation` | `string` |\n",
    "| Environment Tag | `environment` | `string` |\n",
    "| Prompt Tag (version/id/string) | `prompt` | `string` |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Code Example With All Features"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "headers = Portkey.Config(\n",
    "    # Mandatory\n",
    "    api_key=\"<PORTKEY_API_KEY>\",\n",
    "    # Cache Options\n",
    "    cache=\"semantic\",\n",
    "    cache_force_refresh=\"True\",\n",
    "    cache_age=1729,\n",
    "    # Advanced\n",
    "    retry_count=5,\n",
    "    trace_id=\"langchain_agent\",\n",
    "    # Metadata\n",
    "    environment=\"production\",\n",
    "    user=\"john\",\n",
    "    organisation=\"acme\",\n",
    "    prompt=\"Frost\",\n",
    ")\n",
    "\n",
    "llm = OpenAI(temperature=0.9, headers=headers)\n",
    "\n",
    "print(llm(\"Two roads diverged in the yellow woods\"))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.11.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
