ZBasePromptTemplate#

The ZBasePromptTemplate extends BasePromptTemplate in multiple ways:

  • Partial variables now support arbitrary types (used by ChoicePromptTemplate to accept arrays as partials)

  • Partial variables now support using defaults from other keys

  • Only _prompt_type and format_prompt need to be overridden during subclassing, as format is rather redundant now.

  • ZChatPromptTemplate supports partials, unlike ChatPromptTemplate (as of langchain v0.0.125)

There also exists ZStringPromptTemplate, ZPromptTemplate, and ZChatPromptTemplate, which should be plug-and-play replacements for their regular Langchain counterparts.

Usage#

It can be used directly:

[1]:
from langchain_contrib.prompts import ZPromptTemplate

template = ZPromptTemplate.from_template("a={a} b={b} c={c}").partial(a="one")
template.format(b=2, c=[3])
[1]:
'a=one b=2 c=[3]'

Or wrapped around an existing BasePromptTemplate:

[2]:
from langchain_contrib.prompts import ZBasePromptTemplate
from langchain.prompts.prompt import PromptTemplate

base = PromptTemplate.from_template("a={a} b={b} c={c}").partial(a="one")
z_base = ZBasePromptTemplate.from_base_template(base).permissive_partial(b=2)
z_base.format(c=[3])
[2]:
'a=one b=2 c=[3]'

Or it can be subclassed. Note that you no longer need to also override format here.

[3]:
from typing import List, Any
from langchain.prompts.base import StringPromptValue
from langchain.schema import PromptValue


class DemoPromptTemplate(ZBasePromptTemplate):
    """Demonstration of subclassing a ZBasePromptTemplate."""

    input_variables: List[str] = ["a", "b", "c"]

    @property
    def _prompt_type(self) -> str:
        return "demo"

    def _format_prompt(self, **kwargs: Any) -> PromptValue:
        """Return a demonstration of a partial prompt."""
        return StringPromptValue(text="a={a} b={b} c={c}".format(**kwargs))


z_base = DemoPromptTemplate().permissive_partial(a="one", b=2)
z_base.format(c=[3])
[3]:
'a=one b=2 c=[3]'

Partials support#

Arbitrary types can be passed into the permissive_partial function. (After all, the BasePromptTemplate.format_prompt function supports arbitrary types, so why shouldn’t partials?)

[4]:
class MyCustomClass:
    def __str__(self):
        return "a car"

template = ZPromptTemplate.from_template(
    "This is {thing}"
).permissive_partial(thing=MyCustomClass())
template.format()
[4]:
'This is a car'

The permissive partials also call any functions you pass in, just as the regular kinds do. To reproduce an example from the Langchain docs:

[5]:
from datetime import datetime
from langchain_contrib.prompts import ZPromptTemplate

def _get_datetime():
    now = datetime.now()
    return now.strftime("%m/%d/%Y, %H:%M:%S")

prompt = ZPromptTemplate.from_template(
    "Tell me a {adjective} joke about the day {date}"
)
partial_prompt = prompt.permissive_partial(date=_get_datetime)
print(partial_prompt.format(adjective="funny"))
Tell me a funny joke about the day 03/31/2023, 14:16:24

Defaulting to other keys#

Partials can also refer to other keys, which can be useful when chaining together formerly unrelated prompts:

[6]:
from langchain_contrib.prompts import ChainedPromptTemplate, DefaultsTo

product = ZPromptTemplate.from_template("I went to buy a {product}.")
fruit = ZPromptTemplate.from_template("I ate the {fruit}.")
chained = ChainedPromptTemplate(subprompts=[product, fruit], joiner=" ")
partial = chained.permissive_partial(product=DefaultsTo("fruit"))

partial.format(fruit="apple")
[6]:
'I went to buy a apple. I ate the apple.'

You can of course still override the partial at prompt formatting time:

[7]:
partial.format(product="banana", fruit="apple")
[7]:
'I went to buy a banana. I ate the apple.'

Chat Prompt Template partials#

ZChatPromptTemplate in also supports partials now, unlike the regular ChatPromptTemplate:

[8]:
from langchain_contrib.prompts import ZChatPromptTemplate
from langchain.prompts.chat import SystemMessagePromptTemplate

template = ZChatPromptTemplate.from_messages(
    [SystemMessagePromptTemplate.from_template("a={a} b={b} c={c}")]
)
partial = template.partial(a="one").permissive_partial(b=2)
partial.format_prompt(c=[3])
[8]:
ChatPromptValue(messages=[SystemMessage(content='a=one b=2 c=[3]', additional_kwargs={})])