{ "cells": [ { "cell_type": "markdown", "metadata": { "jukit_cell_id": "2XVP2VXIL1" }, "source": [ "# Chains\n", "\n", "Chaining LLMs with each other or with other experts.\n", "\n", "## Getting Started\n", "\n", "- Using the simple LLM chain\n", "- Creating sequential chains\n", "- Creating a custom chain\n", "\n", "### Why Use Chains ?\n", "\n", "- combine multiple components together\n", "- ex: take user input, format with PromptTemplate, pass formatted text to LLM.\n", "\n", "## Query an LLM with LLMChain" ] }, { "cell_type": "code", "metadata": { "jukit_cell_id": "DPRWRo3fl7" }, "source": [ "from langchain.prompts import PromptTemplate\n", "from langchain.llms import OpenAI\n", "import pprint as pp\n", "\n", "llm = OpenAI(temperature=0.9)\n", "prompt = PromptTemplate(\n", " input_variables=[\"product\"],\n", " template=\"What is a good name for a company that makes {product}\"\n", " )" ], "outputs": [], "execution_count": null }, { "cell_type": "markdown", "metadata": { "jukit_cell_id": "tOpTb9idHh" }, "source": [ "We can now create a simple chain that takes user input format it and pass to LLM" ] }, { "cell_type": "code", "metadata": { "jukit_cell_id": "QXu2N1dEEC" }, "source": [ "from langchain.chains import LLMChain\n", "chain = LLMChain(llm=llm, prompt=prompt, output_key='company_name')\n", "\n", "# run the chain only specifying input variables\n", "print(chain.run(\"hand crafted handbags\"))\n", "\n", "# NOTE: we pass data to the run of the entry chain (see sequence under)" ], "outputs": [ { "output_type": "stream", "name": "stdout", "text": "\n\nUrban Crafts Co.\n" } ], "execution_count": 1 }, { "cell_type": "markdown", "metadata": { "jukit_cell_id": "Kv6bj1l9I3" }, "source": [ "## Combining chains with SequentialChain\n", "\n", "Chains that execute their links in predefined order.\n", "\n", "- SimpleSequentialChain: simplest form, each step has a single input/output. \n", "Output of one step is input to next.\n", "- SequentialChain: More advanced, multiple inputs/outputs.\n", "\n", "\n", "Following tutorial uses SimpleSequentialChain and SequentialChain, each chains output is input to the next one.\n", "This sequential chain will:\n", " 1. create company name for a product. We just use LLMChain for that\n", " 2. Create a catchphrase for the product. We will use a new LLMChain for the catchphrase, as show below." ] }, { "cell_type": "code", "metadata": { "jukit_cell_id": "BMZLsdY9VP" }, "source": [ "second_prompt = PromptTemplate(\n", " input_variables=[\"company_name\"],\n", " template=\"Write a catchphrase for the following company: {company_name}\",\n", " )\n", "chain_two = LLMChain(llm=llm, prompt=second_prompt, output_key='catchphrase')" ], "outputs": [], "execution_count": null }, { "cell_type": "markdown", "metadata": { "jukit_cell_id": "epQHxmeWCP" }, "source": [ "We now combine the two chains to create company name and catch phrase." ] }, { "cell_type": "code", "metadata": { "jukit_cell_id": "SHwDHjVCxb" }, "source": [ "from langchain.chains import SimpleSequentialChain, SequentialChain" ], "outputs": [], "execution_count": null }, { "cell_type": "code", "metadata": { "jukit_cell_id": "lKgp9HR0VX" }, "source": [ "full_chain = SimpleSequentialChain(\n", " chains=[chain, chain_two], verbose=True,\n", " )\n", "\n", "print(full_chain.run(\"hand crafted handbags\"))" ], "outputs": [], "execution_count": null }, { "cell_type": "markdown", "metadata": { "jukit_cell_id": "RiYcYwJhdC" }, "source": [ "---\n", "\n", "In the third prompt we create an small advertisement with the title and the product description" ] }, { "cell_type": "code", "metadata": { "jukit_cell_id": "RhnqOumOtX" }, "source": [ "ad_template = \"\"\"Create a small advertisement destined for reddit. \n", "The advertisement is for a company with the following details:\n", "\n", "name: {company_name}\n", "product: {product}\n", "catchphrase: {catchphrase}\n", "\n", "advertisement:\n", "\"\"\"\n", "ad_prompt = PromptTemplate(\n", " input_variables=[\"product\", \"company_name\", \"catchphrase\"],\n", " template=ad_template,\n", " )" ], "outputs": [], "execution_count": null }, { "cell_type": "code", "metadata": { "jukit_cell_id": "MsQnieyxgL" }, "source": [ "#Connet the three chains together\n", "\n", "ad_chain = LLMChain(llm=llm, prompt=ad_prompt, output_key='advertisement')" ], "outputs": [], "execution_count": null }, { "cell_type": "code", "metadata": { "jukit_cell_id": "4PYfwOxTlq" }, "source": [ "final_chain = SequentialChain(\n", " chains=[chain, chain_two, ad_chain],\n", " input_variables=['product'],\n", " output_variables=['advertisement'],\n", " verbose=True\n", " )\n", "\n", "ad = final_chain.run('Professional Cat Cuddler')" ], "outputs": [ { "output_type": "stream", "name": "stdout", "text": "\n\n\u001b[1m> Entering new SequentialChain chain...\u001b[0m\n\n\u001b[1m> Finished chain.\u001b[0m\n" } ], "execution_count": 2 }, { "cell_type": "code", "metadata": { "jukit_cell_id": "2akm8eB1EV" }, "source": [ "print(ad)" ], "outputs": [ { "output_type": "stream", "name": "stdout", "text": "Are you in need of a little indulgence? Then come to Purr-fect Pampering! Our professional cat cuddler will provide you with the ultimate relaxation experience. We guarantee that after a session with us, you'll be feeling more purr-fect than ever! Treat yourself to the luxurious indulgence of Purr-fect Pampering!\n" } ], "execution_count": 3 }, { "cell_type": "markdown", "metadata": { "jukit_cell_id": "1iT7gBMABZ" }, "source": [ "## Creating a custom chain\n", "\n", "Example: create a custom chain that concats output of 2 LLMChain\n", "\n", "Steps:\n", " 1. Subclass Chain class\n", " 2. Fill out `input_keys` and `output_keys`\n", " 3. add the `_call` method that shows how to execute chain" ] }, { "cell_type": "code", "metadata": { "jukit_cell_id": "OUXv7kGtDH" }, "source": [ "from langchain.chains import LLMChain\n", "from langchain.chains.base import Chain\n", "\n", "from typing import Dict, List\n", "\n", "class ConcatenateChain(Chain):\n", " chain_1: LLMChain\n", " chain_2: LLMChain\n", "\n", " @property\n", " def input_keys(self) -> List[str]:\n", " # Union of the input keys of the two chains\n", " all_inputs_vars = set(self.chain_1.input_keys).union(\n", " set(self.chain_2.input_keys))\n", " return list(all_inputs_vars)\n", "\n", " @property\n", " def output_keys(self) -> List[str]:\n", " return ['concat_output']\n", "\n", " def _call(self, inputs: Dict[str, str]) -> Dict[str,str]:\n", " output_1 = self.chain_1.run(inputs)\n", " output_2 = self.chain_2.run(inputs)\n", " return {'concat_output': output_1 + output_2}" ], "outputs": [], "execution_count": null }, { "cell_type": "markdown", "metadata": { "jukit_cell_id": "MUOMbKovF6" }, "source": [ "Running the custom chain" ] }, { "cell_type": "code", "metadata": { "jukit_cell_id": "kBfPU3rB6L" }, "source": [ "prompt_1 = PromptTemplate(\n", " input_variables=['product'],\n", " template='what is a good name for a company that makes {product}?'\n", " )\n", "chain_1 = LLMChain(llm=llm, prompt=prompt_1)\n", "\n", "prompt_2 = PromptTemplate(\n", " input_variables=['product'],\n", " template='what is a good slogan for a company that makes {product} ?'\n", " )\n", "chain_2 = LLMChain(llm=llm, prompt=prompt_2)\n", "\n", "concat_chain = ConcatenateChain(chain_1=chain_1, chain_2=chain_2)\n", "\n", "concat_output = concat_chain.run('leather handbags')\n", "print(f'Concatenated output:\\n{concat_output}')" ], "outputs": [ { "output_type": "stream", "name": "stdout", "text": "Concatenated output:\n\n\nLeather Luxury Boutique.\n\n\"Handcrafted Leather: The Perfect Accent for Any Look.\"\n" } ], "execution_count": 4 }, { "cell_type": "code", "metadata": { "jukit_cell_id": "9CdH3GtsmW" }, "source": [], "outputs": [], "execution_count": null } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "python", "language": "python", "name": "python3" } }, "nbformat": 4, "nbformat_minor": 4 }