add custom prompt notebooks (#198)

This commit is contained in:
Harrison Chase 2022-11-26 06:07:02 -08:00 committed by GitHub
parent fcb9b2ffe5
commit 05c5d0b8ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 450 additions and 2 deletions

View File

@ -45,6 +45,9 @@ However, there are still some challenges going from that to an application runni
- LLM: A large language model, in particular a text-to-text model. - LLM: A large language model, in particular a text-to-text model.
- Prompt: The input to a language model. Typically this is not simply a hardcoded string but rather a combination of a template, some examples, and user input. - Prompt: The input to a language model. Typically this is not simply a hardcoded string but rather a combination of a template, some examples, and user input.
- Prompt Template: An object responsible for constructing the final prompt to pass to a LLM. - Prompt Template: An object responsible for constructing the final prompt to pass to a LLM.
- Examples: Datapoints that can be included in the prompt in order to give the model more context what to do.
- Few Shot Prompt Template: A subclass of the PromptTemplate class that uses examples.
- Example Selector: A class responsible to selecting examples to use dynamically (depending on user input) in a few shot prompt.
**Problems Solved** **Problems Solved**
- Switching costs: by exposing a standard interface for all the top LLM providers, LangChain makes it easy to switch from one provider to another, whether it be for production use cases or just for testing stuff out. - Switching costs: by exposing a standard interface for all the top LLM providers, LangChain makes it easy to switch from one provider to another, whether it be for production use cases or just for testing stuff out.

View File

@ -0,0 +1,176 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "f897c784",
"metadata": {},
"source": [
"# Custom ExampleSelector\n",
"\n",
"This notebook goes over how to implement a custom ExampleSelector. ExampleSelectors are used to select examples to use in few shot prompts.\n",
"\n",
"An ExampleSelector must implement two methods:\n",
"\n",
"1. An `add_example` method which takes in an example and adds it into the ExampleSelector\n",
"2. A `select_examples` method which takes in input variables (which are meant to be user input) and returns a list of examples to use in the few shot prompt.\n",
"\n",
"\n",
"Let's implement a custom ExampleSelector that just selects two examples at random."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "1a945da1",
"metadata": {},
"outputs": [],
"source": [
"from langchain.prompts.example_selector.base import BaseExampleSelector\n",
"from typing import Dict, List\n",
"import numpy as np"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "62cf0ad7",
"metadata": {},
"outputs": [],
"source": [
"class CustomExampleSelector(BaseExampleSelector):\n",
" \n",
" def __init__(self, examples: List[Dict[str, str]]):\n",
" self.examples = examples\n",
" \n",
" def add_example(self, example: Dict[str, str]) -> None:\n",
" \"\"\"Add new example to store for a key.\"\"\"\n",
" self.examples.append(example)\n",
"\n",
" def select_examples(self, input_variables: Dict[str, str]) -> List[dict]:\n",
" \"\"\"Select which examples to use based on the inputs.\"\"\"\n",
" return np.random.choice(self.examples, size=2, replace=False)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "242d3213",
"metadata": {},
"outputs": [],
"source": [
"examples = [{\"foo\": \"1\"}, {\"foo\": \"2\"}, {\"foo\": \"3\"}]\n",
"example_selector = CustomExampleSelector(examples)"
]
},
{
"cell_type": "markdown",
"id": "2a038065",
"metadata": {},
"source": [
"Let's now try it out! We can select some examples and try adding examples."
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "74fbbef5",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([{'foo': '2'}, {'foo': '3'}], dtype=object)"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"example_selector.select_examples({\"foo\": \"foo\"})"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "9bbb5421",
"metadata": {},
"outputs": [],
"source": [
"example_selector.add_example({\"foo\": \"4\"})"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "c0eb9f22",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'foo': '1'}, {'foo': '2'}, {'foo': '3'}, {'foo': '4'}]"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"example_selector.examples"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "cc39b1e3",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([{'foo': '1'}, {'foo': '4'}], dtype=object)"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"example_selector.select_examples({\"foo\": \"foo\"})"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1739dd96",
"metadata": {},
"outputs": [],
"source": []
}
],
"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.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@ -0,0 +1,153 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "9e9b7651",
"metadata": {},
"source": [
"# Custom LLM\n",
"\n",
"This notebook goes over how to create a custom LLM wrapper, in case you want to use your own LLM or a different wrapper than one that is supported in LangChain.\n",
"\n",
"There is only one required thing that a custom LLM needs to implement:\n",
"\n",
"1. A `__call__` method that takes in a string, some optional stop words, and returns a string\n",
"\n",
"There is a second optional thing it can implement:\n",
"\n",
"1. An `_identifying_params` property that is used to help with printing of this class. Should return a dictionary.\n",
"\n",
"Let's implement a very simple custom LLM that just returns the first N characters of the input."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "a65696a0",
"metadata": {},
"outputs": [],
"source": [
"from langchain.llms.base import LLM\n",
"from typing import Optional, List, Mapping, Any"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "d5ceff02",
"metadata": {},
"outputs": [],
"source": [
"class CustomLLM(LLM):\n",
" \n",
" def __init__(self, n: int):\n",
" self.n = n\n",
" \n",
" def __call__(self, prompt: str, stop: Optional[List[str]] = None) -> str:\n",
" if stop is not None:\n",
" raise ValueError(\"stop kwargs are not permitted.\")\n",
" return prompt[:self.n]\n",
" \n",
" @property\n",
" def _identifying_params(self) -> Mapping[str, Any]:\n",
" \"\"\"Get the identifying parameters.\"\"\"\n",
" return {\"n\": self.n}"
]
},
{
"cell_type": "markdown",
"id": "714dede0",
"metadata": {},
"source": [
"We can now use this as an any other LLM."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "10e5ece6",
"metadata": {},
"outputs": [],
"source": [
"llm = CustomLLM(n=10)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "8cd49199",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'This is a '"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"llm(\"This is a foobar thing\")"
]
},
{
"cell_type": "markdown",
"id": "bbfebea1",
"metadata": {},
"source": [
"We can also print the LLM and see its custom print."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "9c33fa19",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1mCustomLLM\u001b[0m\n",
"Params: {'n': 10}\n"
]
}
],
"source": [
"print(llm)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6dac3f47",
"metadata": {},
"outputs": [],
"source": []
}
],
"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.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@ -0,0 +1,116 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "a37d9694",
"metadata": {},
"source": [
"# Custom Prompt Template\n",
"\n",
"This notebook goes over how to create a custom prompt template, in case you want to create your own methodology for creating prompts.\n",
"\n",
"The only two requirements for all prompt templates are:\n",
"\n",
"1. They have a `input_variables` attribute that exposes what input variables this prompt template expects.\n",
"2. They expose a `format` method which takes in keyword arguments corresponding to the expected `input_variables` and returns the formatted prompt.\n",
"\n",
"Let's imagine that we want to create a prompt template that takes in input variables and formats them into the template AFTER capitalizing them. "
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "26f796e5",
"metadata": {},
"outputs": [],
"source": [
"from langchain.prompts import BasePromptTemplate\n",
"from pydantic import BaseModel"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "27919e96",
"metadata": {},
"outputs": [],
"source": [
"class CustomPromptTemplate(BasePromptTemplate, BaseModel):\n",
" template: str\n",
" \n",
" def format(self, **kwargs) -> str:\n",
" capitalized_kwargs = {k: v.upper() for k, v in kwargs.items()}\n",
" return self.template.format(**capitalized_kwargs)\n",
" "
]
},
{
"cell_type": "markdown",
"id": "76d1d84d",
"metadata": {},
"source": [
"We can now see that when we use this, the input variables get formatted."
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "eed1ff28",
"metadata": {},
"outputs": [],
"source": [
"prompt = CustomPromptTemplate(input_variables=[\"foo\"], template=\"Capitalized: {foo}\")"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "94892a3c",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'Capitalized: LOWERCASE'"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"prompt.format(foo=\"lowercase\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d3d9a7c7",
"metadata": {},
"outputs": [],
"source": []
}
],
"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.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@ -602,7 +602,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.10.4" "version": "3.7.6"
} }
}, },
"nbformat": 4, "nbformat": 4,

View File

@ -11,9 +11,9 @@ class LLM(ABC):
"""Run the LLM on the given prompt and input.""" """Run the LLM on the given prompt and input."""
@property @property
@abstractmethod
def _identifying_params(self) -> Mapping[str, Any]: def _identifying_params(self) -> Mapping[str, Any]:
"""Get the identifying parameters.""" """Get the identifying parameters."""
return {}
def __str__(self) -> str: def __str__(self) -> str:
"""Get a string representation of the object for printing.""" """Get a string representation of the object for printing."""