{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "27962df3",
   "metadata": {},
   "source": [
    "Notebook to generate and run a bash command.\n",
    "Adapted from LangChain\n",
    "[BashChain](https://langchain.readthedocs.io/en/latest/modules/chains/examples/llm_bash.html)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "e01d45bc",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-02-27T14:12:17.548344Z",
     "iopub.status.busy": "2023-02-27T14:12:17.547695Z",
     "iopub.status.idle": "2023-02-27T14:12:17.767947Z",
     "shell.execute_reply": "2023-02-27T14:12:17.767208Z"
    }
   },
   "outputs": [],
   "source": [
    "import minichain"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b2caf597",
   "metadata": {
    "lines_to_next_cell": 2
   },
   "source": [
    "Prompt that asks LLM to produce a bash command."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "8669ca4e",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-02-27T14:12:17.773257Z",
     "iopub.status.busy": "2023-02-27T14:12:17.771880Z",
     "iopub.status.idle": "2023-02-27T14:12:17.778057Z",
     "shell.execute_reply": "2023-02-27T14:12:17.777432Z"
    },
    "lines_to_next_cell": 2
   },
   "outputs": [],
   "source": [
    "class CLIPrompt(minichain.TemplatePrompt):\n",
    "    template_file = \"bash.pmpt.tpl\"\n",
    "\n",
    "    def parse(self, out: str, inp):\n",
    "        out = out.strip()\n",
    "        assert out.startswith(\"```bash\")\n",
    "        return out.split(\"\\n\")[1:-1]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "79cc544e",
   "metadata": {
    "lines_to_next_cell": 2
   },
   "source": [
    "Prompt that runs the bash command."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "db1e09b6",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-02-27T14:12:17.782732Z",
     "iopub.status.busy": "2023-02-27T14:12:17.781591Z",
     "iopub.status.idle": "2023-02-27T14:12:17.787303Z",
     "shell.execute_reply": "2023-02-27T14:12:17.786651Z"
    }
   },
   "outputs": [],
   "source": [
    "class BashPrompt(minichain.Prompt):\n",
    "    def prompt(self, inp) -> str:\n",
    "        return \";\".join(inp).replace(\"\\n\", \"\")\n",
    "\n",
    "    def parse(self, out: str, inp) -> str:\n",
    "        return out"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5b993ae8",
   "metadata": {},
   "source": [
    "Generate and run bash command."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "17572fff",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-02-27T14:12:17.792430Z",
     "iopub.status.busy": "2023-02-27T14:12:17.791251Z",
     "iopub.status.idle": "2023-02-27T14:12:19.652953Z",
     "shell.execute_reply": "2023-02-27T14:12:19.650586Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "#backend.py#\n",
      "backend.py\n",
      "base.py\n",
      "__init__.py\n",
      "lang.py\n",
      "prompts.py\n",
      "__pycache__\n",
      "templates\n",
      "\n"
     ]
    }
   ],
   "source": [
    "with minichain.start_chain(\"bash\") as backend:\n",
    "    question = (\n",
    "        '\"go up one directory, and then into the minichain directory,'\n",
    "        'and list the files in the directory\"'\n",
    "    )\n",
    "    prompt = CLIPrompt(backend.OpenAI()).chain(BashPrompt(backend.BashProcess()))\n",
    "    result = prompt({\"question\": question})\n",
    "    print(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aadedf29",
   "metadata": {},
   "source": [
    "View the prompts."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "0e1c2f1a",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-02-27T14:12:19.662941Z",
     "iopub.status.busy": "2023-02-27T14:12:19.661254Z",
     "iopub.status.idle": "2023-02-27T14:12:19.738758Z",
     "shell.execute_reply": "2023-02-27T14:12:19.738197Z"
    },
    "lines_to_next_cell": 2,
    "tags": [
     "hide_inp"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "<!-- <link rel=\"stylesheet\" href=\"https://cdn.rawgit.com/Chalarangelo/mini.css/v3.0.1/dist/mini-default.min.css\"> -->\n",
       " <main class=\"container\">\n",
       "\n",
       "<h3>CLIPrompt</h3>\n",
       "\n",
       "<dl>\n",
       "  <dt>Input:</dt>\n",
       "  <dd>\n",
       "<div class=\"highlight\"><pre><span></span><span class=\"p\">{</span><span class=\"s1\">&#39;question&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;list the files in the directory&#39;</span><span class=\"p\">}</span>\n",
       "</pre></div>\n",
       "\n",
       "\n",
       "  </dd>\n",
       "\n",
       "  <dt> Full Prompt: </dt>\n",
       "  <dd>\n",
       "    <details>\n",
       "      <summary>Prompt</summary>\n",
       "      <p>If someone asks you to perform a task, your job is to come up with a series of bash commands that will perform the task. There is no need to put \"#!/bin/bash\" in your answer. Make sure to reason step by step, using this format:<br><br>Question: \"copy the files in the directory named 'target' into a new directory at the same level as target called 'myNewDirectory'\"<br><br>I need to take the following actions:<br>- List all files in the directory<br>- Create a new directory<br>- Copy the files from the first directory into the second directory<br>```bash<br>ls<br>mkdir myNewDirectory<br>cp -r target/* myNewDirectory<br>```<br><br>That is the format. Begin!<br><br>Question: <div style='color:red'>list the files in the directory</div></p>\n",
       "    </details>\n",
       "  </dd>\n",
       "\n",
       "  <dt> Response: </dt>\n",
       "  <dd>\n",
       "    ```bash<br>ls<br>```\n",
       "  </dd>\n",
       "\n",
       "  <dt>Value:</dt>\n",
       "  <dd>\n",
       "<div class=\"highlight\"><pre><span></span><span class=\"p\">[</span><span class=\"s1\">&#39;ls&#39;</span><span class=\"p\">]</span>\n",
       "</pre></div>\n",
       "\n",
       "  </dd>\n",
       "</main>\n"
      ],
      "text/plain": [
       "HTML(html='\\n<!-- <link rel=\"stylesheet\" href=\"https://cdn.rawgit.com/Chalarangelo/mini.css/v3.0.1/dist/mini-default.min.css\"> -->\\n <main class=\"container\">\\n\\n<h3>CLIPrompt</h3>\\n\\n<dl>\\n  <dt>Input:</dt>\\n  <dd>\\n<div class=\"highlight\"><pre><span></span><span class=\"p\">{</span><span class=\"s1\">&#39;question&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;list the files in the directory&#39;</span><span class=\"p\">}</span>\\n</pre></div>\\n\\n\\n  </dd>\\n\\n  <dt> Full Prompt: </dt>\\n  <dd>\\n    <details>\\n      <summary>Prompt</summary>\\n      <p>If someone asks you to perform a task, your job is to come up with a series of bash commands that will perform the task. There is no need to put \"#!/bin/bash\" in your answer. Make sure to reason step by step, using this format:<br><br>Question: \"copy the files in the directory named \\'target\\' into a new directory at the same level as target called \\'myNewDirectory\\'\"<br><br>I need to take the following actions:<br>- List all files in the directory<br>- Create a new directory<br>- Copy the files from the first directory into the second directory<br>```bash<br>ls<br>mkdir myNewDirectory<br>cp -r target/* myNewDirectory<br>```<br><br>That is the format. Begin!<br><br>Question: <div style=\\'color:red\\'>list the files in the directory</div></p>\\n    </details>\\n  </dd>\\n\\n  <dt> Response: </dt>\\n  <dd>\\n    ```bash<br>ls<br>```\\n  </dd>\\n\\n  <dt>Value:</dt>\\n  <dd>\\n<div class=\"highlight\"><pre><span></span><span class=\"p\">[</span><span class=\"s1\">&#39;ls&#39;</span><span class=\"p\">]</span>\\n</pre></div>\\n\\n  </dd>\\n</main>\\n')"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "CLIPrompt().show(\n",
    "    {\"question\": \"list the files in the directory\"}, \"\"\"```bash\\nls\\n```\"\"\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "79cf9c84",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-02-27T14:12:19.740976Z",
     "iopub.status.busy": "2023-02-27T14:12:19.740788Z",
     "iopub.status.idle": "2023-02-27T14:12:19.745592Z",
     "shell.execute_reply": "2023-02-27T14:12:19.745136Z"
    },
    "tags": [
     "hide_inp"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "<!-- <link rel=\"stylesheet\" href=\"https://cdn.rawgit.com/Chalarangelo/mini.css/v3.0.1/dist/mini-default.min.css\"> -->\n",
       " <main class=\"container\">\n",
       "\n",
       "<h3>BashPrompt</h3>\n",
       "\n",
       "<dl>\n",
       "  <dt>Input:</dt>\n",
       "  <dd>\n",
       "<div class=\"highlight\"><pre><span></span><span class=\"p\">[</span><span class=\"s1\">&#39;ls&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;cat file.txt&#39;</span><span class=\"p\">]</span>\n",
       "</pre></div>\n",
       "\n",
       "\n",
       "  </dd>\n",
       "\n",
       "  <dt> Full Prompt: </dt>\n",
       "  <dd>\n",
       "    <details>\n",
       "      <summary>Prompt</summary>\n",
       "      <p>ls;cat file.txt</p>\n",
       "    </details>\n",
       "  </dd>\n",
       "\n",
       "  <dt> Response: </dt>\n",
       "  <dd>\n",
       "    hello\n",
       "  </dd>\n",
       "\n",
       "  <dt>Value:</dt>\n",
       "  <dd>\n",
       "<div class=\"highlight\"><pre><span></span><span class=\"n\">hello</span>\n",
       "</pre></div>\n",
       "\n",
       "  </dd>\n",
       "</main>\n"
      ],
      "text/plain": [
       "HTML(html='\\n<!-- <link rel=\"stylesheet\" href=\"https://cdn.rawgit.com/Chalarangelo/mini.css/v3.0.1/dist/mini-default.min.css\"> -->\\n <main class=\"container\">\\n\\n<h3>BashPrompt</h3>\\n\\n<dl>\\n  <dt>Input:</dt>\\n  <dd>\\n<div class=\"highlight\"><pre><span></span><span class=\"p\">[</span><span class=\"s1\">&#39;ls&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;cat file.txt&#39;</span><span class=\"p\">]</span>\\n</pre></div>\\n\\n\\n  </dd>\\n\\n  <dt> Full Prompt: </dt>\\n  <dd>\\n    <details>\\n      <summary>Prompt</summary>\\n      <p>ls;cat file.txt</p>\\n    </details>\\n  </dd>\\n\\n  <dt> Response: </dt>\\n  <dd>\\n    hello\\n  </dd>\\n\\n  <dt>Value:</dt>\\n  <dd>\\n<div class=\"highlight\"><pre><span></span><span class=\"n\">hello</span>\\n</pre></div>\\n\\n  </dd>\\n</main>\\n')"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "BashPrompt().show([\"ls\", \"cat file.txt\"], \"hello\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "89c7bc6c",
   "metadata": {},
   "source": [
    "View the run log."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "7dbcec08",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2023-02-27T14:12:19.748151Z",
     "iopub.status.busy": "2023-02-27T14:12:19.747899Z",
     "iopub.status.idle": "2023-02-27T14:12:19.768720Z",
     "shell.execute_reply": "2023-02-27T14:12:19.768248Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[38;5;15mfc682a98-f50a-4837-8b6d-87e843c19732\u001b[1m\u001b[0m\n",
      "└── \u001b[38;5;5m<class '__main__.CLIPrompt'>\u001b[0m/1\u001b[0m ⇒ \u001b[38;5;2mstarted\u001b[0m \u001b[38;5;15m2023-02-27 14:12:18Z\u001b[2m\u001b[0m ⧖ \u001b[38;5;4m1.531s\u001b[2m\u001b[0m\n",
      "    ├── \u001b[38;5;5mInput Function\u001b[0m/2/1\u001b[0m ⇒ \u001b[38;5;2mstarted\u001b[0m \u001b[38;5;15m2023-02-27 14:12:18Z\u001b[2m\u001b[0m ⧖ \u001b[38;5;4m0.003s\u001b[2m\u001b[0m\n",
      "    │   ├── \u001b[38;5;4minput\u001b[0m: \u001b[0m\n",
      "    │   │   └── \u001b[38;5;4mquestion\u001b[0m: \"go up one directory, and then into the minichain directory,and list the files in the directory\"\u001b[0m\n",
      "    │   └── \u001b[38;5;5mInput Function\u001b[0m/2/2\u001b[0m ⇒ \u001b[38;5;2msucceeded\u001b[0m \u001b[38;5;15m2023-02-27 14:12:18Z\u001b[2m\u001b[0m\n",
      "    ├── \u001b[38;5;5mPrompted\u001b[0m/3/1\u001b[0m ⇒ \u001b[38;5;2mstarted\u001b[0m \u001b[38;5;15m2023-02-27 14:12:18Z\u001b[2m\u001b[0m ⧖ \u001b[38;5;4m1.528s\u001b[2m\u001b[0m\n",
      "    │   ├── \u001b[38;5;4mprompt\u001b[0m: If someone asks you to perform a task, your job is to come up with a series of bash commands that will perform the task. There is no need to put \"#!/bin/bash\" in your answer. Make sure to reason step by step, using this format:⏎\n",
      "    │   │   ⏎\n",
      "    │   │   Question: \"copy the files in the directory named 'target' into a new directory at the same level as target called 'myNewDirectory'\"⏎\n",
      "    │   │   ⏎\n",
      "    │   │   I need to take the following actions:⏎\n",
      "    │   │   - List all files in the directory⏎\n",
      "    │   │   - Create a new directory⏎\n",
      "    │   │   - Copy the files from the first directory into the second directory⏎\n",
      "    │   │   ```bash⏎\n",
      "    │   │   ls⏎\n",
      "    │   │   mkdir myNewDirectory⏎\n",
      "    │   │   cp -r target/* myNewDirectory⏎\n",
      "    │   │   ```⏎\n",
      "    │   │   ⏎\n",
      "    │   │   That is the format. Begin!⏎\n",
      "    │   │   ⏎\n",
      "    │   │   Question: \"go up one directory, and then into the minichain directory,and list the files in the directory\"\u001b[0m\n",
      "    │   └── \u001b[38;5;5mPrompted\u001b[0m/3/2\u001b[0m ⇒ \u001b[38;5;2msucceeded\u001b[0m \u001b[38;5;15m2023-02-27 14:12:19Z\u001b[2m\u001b[0m\n",
      "    ├── \u001b[38;5;5mResult\u001b[0m/4/1\u001b[0m ⇒ \u001b[38;5;2mstarted\u001b[0m \u001b[38;5;15m2023-02-27 14:12:19Z\u001b[2m\u001b[0m ⧖ \u001b[38;5;4m0.000s\u001b[2m\u001b[0m\n",
      "    │   ├── \u001b[38;5;4mresult\u001b[0m: ⏎\n",
      "    │   │   ⏎\n",
      "    │   │   ```bash⏎\n",
      "    │   │   cd ..⏎\n",
      "    │   │   cd minichain⏎\n",
      "    │   │   ls⏎\n",
      "    │   │   ```\u001b[0m\n",
      "    │   └── \u001b[38;5;5mResult\u001b[0m/4/2\u001b[0m ⇒ \u001b[38;5;2msucceeded\u001b[0m \u001b[38;5;15m2023-02-27 14:12:19Z\u001b[2m\u001b[0m\n",
      "    └── \u001b[38;5;5m<class '__main__.CLIPrompt'>\u001b[0m/5\u001b[0m ⇒ \u001b[38;5;2msucceeded\u001b[0m \u001b[38;5;15m2023-02-27 14:12:19Z\u001b[2m\u001b[0m\n",
      "\n",
      "\u001b[38;5;15m328e2368-6c0f-4a03-ae78-26aa43a517e3\u001b[1m\u001b[0m\n",
      "└── \u001b[38;5;5m<class '__main__.BashPrompt'>\u001b[0m/1\u001b[0m ⇒ \u001b[38;5;2mstarted\u001b[0m \u001b[38;5;15m2023-02-27 14:12:19Z\u001b[2m\u001b[0m ⧖ \u001b[38;5;4m0.006s\u001b[2m\u001b[0m\n",
      "    ├── \u001b[38;5;5mInput Function\u001b[0m/2/1\u001b[0m ⇒ \u001b[38;5;2mstarted\u001b[0m \u001b[38;5;15m2023-02-27 14:12:19Z\u001b[2m\u001b[0m ⧖ \u001b[38;5;4m0.000s\u001b[2m\u001b[0m\n",
      "    │   ├── \u001b[38;5;4minput\u001b[0m: \u001b[0m\n",
      "    │   │   ├── \u001b[38;5;4m0\u001b[0m: cd ..\u001b[0m\n",
      "    │   │   ├── \u001b[38;5;4m1\u001b[0m: cd minichain\u001b[0m\n",
      "    │   │   └── \u001b[38;5;4m2\u001b[0m: ls\u001b[0m\n",
      "    │   └── \u001b[38;5;5mInput Function\u001b[0m/2/2\u001b[0m ⇒ \u001b[38;5;2msucceeded\u001b[0m \u001b[38;5;15m2023-02-27 14:12:19Z\u001b[2m\u001b[0m\n",
      "    ├── \u001b[38;5;5mPrompted\u001b[0m/3/1\u001b[0m ⇒ \u001b[38;5;2mstarted\u001b[0m \u001b[38;5;15m2023-02-27 14:12:19Z\u001b[2m\u001b[0m ⧖ \u001b[38;5;4m0.005s\u001b[2m\u001b[0m\n",
      "    │   ├── \u001b[38;5;4mprompt\u001b[0m: cd ..;cd minichain;ls\u001b[0m\n",
      "    │   └── \u001b[38;5;5mPrompted\u001b[0m/3/2\u001b[0m ⇒ \u001b[38;5;2msucceeded\u001b[0m \u001b[38;5;15m2023-02-27 14:12:19Z\u001b[2m\u001b[0m\n",
      "    ├── \u001b[38;5;5mResult\u001b[0m/4/1\u001b[0m ⇒ \u001b[38;5;2mstarted\u001b[0m \u001b[38;5;15m2023-02-27 14:12:19Z\u001b[2m\u001b[0m ⧖ \u001b[38;5;4m0.000s\u001b[2m\u001b[0m\n",
      "    │   ├── \u001b[38;5;4mresult\u001b[0m: #backend.py#⏎\n",
      "    │   │   backend.py⏎\n",
      "    │   │   base.py⏎\n",
      "    │   │   __init__.py⏎\n",
      "    │   │   lang.py⏎\n",
      "    │   │   prompts.py⏎\n",
      "    │   │   __pycache__⏎\n",
      "    │   │   templates⏎\n",
      "    │   │   \u001b[0m\n",
      "    │   └── \u001b[38;5;5mResult\u001b[0m/4/2\u001b[0m ⇒ \u001b[38;5;2msucceeded\u001b[0m \u001b[38;5;15m2023-02-27 14:12:19Z\u001b[2m\u001b[0m\n",
      "    └── \u001b[38;5;5m<class '__main__.BashPrompt'>\u001b[0m/5\u001b[0m ⇒ \u001b[38;5;2msucceeded\u001b[0m \u001b[38;5;15m2023-02-27 14:12:19Z\u001b[2m\u001b[0m\n",
      "\n",
      "\u001b[38;5;15mca5f4b25-55ca-441d-a0d2-f39ad0bca2d0\u001b[1m\u001b[0m\n",
      "└── \u001b[38;5;5mbash\u001b[0m/1\u001b[0m ⇒ \u001b[38;5;2mstarted\u001b[0m \u001b[38;5;15m2023-02-27 14:12:17Z\u001b[2m\u001b[0m ⧖ \u001b[38;5;4m1.850s\u001b[2m\u001b[0m\n",
      "    └── \u001b[38;5;5mbash\u001b[0m/2\u001b[0m ⇒ \u001b[38;5;2msucceeded\u001b[0m \u001b[38;5;15m2023-02-27 14:12:19Z\u001b[2m\u001b[0m\n",
      "\n"
     ]
    }
   ],
   "source": [
    "minichain.show_log(\"bash.log\")"
   ]
  }
 ],
 "metadata": {
  "jupytext": {
   "cell_metadata_filter": "tags,-all"
  },
  "kernelspec": {
   "display_name": "minichain",
   "language": "python",
   "name": "minichain"
  },
  "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.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}