mirror of
https://github.com/hwchase17/langchain.git
synced 2025-07-31 00:29:57 +00:00
[Feat] Accept non-dict if only 1 prompt input variable (#19156)
For prompt templates with only 1 variable (common in e.g., MessageGraph), it's convenient to wrap the incoming object in the variable before formatting. The downside of this, of course, would be that some number of invocations will successfully format when the user may have intended to format it properly before
This commit is contained in:
parent
d9396bdec1
commit
68298cdc82
@ -89,10 +89,15 @@ class BasePromptTemplate(
|
||||
|
||||
def _format_prompt_with_error_handling(self, inner_input: Dict) -> PromptValue:
|
||||
if not isinstance(inner_input, dict):
|
||||
raise TypeError(
|
||||
f"Expected mapping type as input to {self.__class__.__name__}. "
|
||||
f"Received {type(inner_input)}."
|
||||
)
|
||||
if len(self.input_variables) == 1:
|
||||
var_name = self.input_variables[0]
|
||||
inner_input = {var_name: inner_input}
|
||||
|
||||
else:
|
||||
raise TypeError(
|
||||
f"Expected mapping type as input to {self.__class__.__name__}. "
|
||||
f"Received {type(inner_input)}."
|
||||
)
|
||||
missing = set(self.input_variables).difference(inner_input)
|
||||
if missing:
|
||||
raise KeyError(
|
||||
|
@ -574,11 +574,51 @@ class ChatPromptTemplate(BaseChatPromptTemplate):
|
||||
("human", "{user_input}"),
|
||||
])
|
||||
|
||||
messages = template.format_messages(
|
||||
name="Bob",
|
||||
user_input="What is your name?"
|
||||
prompt_value = template.invoke(
|
||||
{
|
||||
"name": "Bob",
|
||||
"user_input": "What is your name?"
|
||||
}
|
||||
)
|
||||
"""
|
||||
# Output:
|
||||
# ChatPromptValue(
|
||||
# messages=[
|
||||
# SystemMessage(content='You are a helpful AI bot. Your name is Bob.'),
|
||||
# HumanMessage(content='Hello, how are you doing?'),
|
||||
# AIMessage(content="I'm doing well, thanks!"),
|
||||
# HumanMessage(content='What is your name?')
|
||||
# ]
|
||||
#)
|
||||
|
||||
Single-variable template:
|
||||
|
||||
If your prompt has only a single input variable (i.e., 1 instance of "{variable_nams}"),
|
||||
and you invoke the template with a non-dict object, the prompt template will
|
||||
inject the provided argument into that variable location.
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from langchain_core.prompts import ChatPromptTemplate
|
||||
|
||||
template = ChatPromptTemplate.from_messages([
|
||||
("system", "You are a helpful AI bot. Your name is Carl."),
|
||||
("human", "{user_input}"),
|
||||
])
|
||||
|
||||
prompt_value = template.invoke("Hello, there!")
|
||||
# Equivalent to
|
||||
# prompt_value = template.invoke({"user_input": "Hello, there!"})
|
||||
|
||||
# Output:
|
||||
# ChatPromptValue(
|
||||
# messages=[
|
||||
# SystemMessage(content='You are a helpful AI bot. Your name is Carl.'),
|
||||
# HumanMessage(content='Hello, there!'),
|
||||
# ]
|
||||
# )
|
||||
|
||||
""" # noqa: E501
|
||||
|
||||
input_variables: List[str]
|
||||
"""List of input variables in template messages. Used for validation."""
|
||||
|
@ -533,3 +533,16 @@ def test_chat_prompt_message_placeholder_partial() -> None:
|
||||
assert prompt.format_messages() == []
|
||||
prompt = prompt.partial(history=[("system", "foo")])
|
||||
assert prompt.format_messages() == [SystemMessage(content="foo")]
|
||||
|
||||
|
||||
def test_messages_prompt_accepts_list() -> None:
|
||||
prompt = ChatPromptTemplate.from_messages([MessagesPlaceholder("history")])
|
||||
value = prompt.invoke([("user", "Hi there")]) # type: ignore
|
||||
assert value.to_messages() == [HumanMessage(content="Hi there")]
|
||||
|
||||
# Assert still raises a nice error
|
||||
prompt = ChatPromptTemplate.from_messages(
|
||||
[("system", "You are a {foo}"), MessagesPlaceholder("history")]
|
||||
)
|
||||
with pytest.raises(TypeError):
|
||||
prompt.invoke([("user", "Hi there")]) # type: ignore
|
||||
|
Loading…
Reference in New Issue
Block a user