diff --git a/libs/core/langchain_core/prompts/base.py b/libs/core/langchain_core/prompts/base.py index a95d7fee68..b7275f7181 100644 --- a/libs/core/langchain_core/prompts/base.py +++ b/libs/core/langchain_core/prompts/base.py @@ -182,6 +182,23 @@ class BasePromptTemplate( prompt.format(variable1="foo") """ + async def aformat(self, **kwargs: Any) -> FormatOutputType: + """Format the prompt with the inputs. + + Args: + kwargs: Any arguments to be passed to the prompt template. + + Returns: + A formatted string. + + Example: + + .. code-block:: python + + await prompt.aformat(variable1="foo") + """ + return self.format(**kwargs) + @property def _prompt_type(self) -> str: """Return the prompt type key.""" diff --git a/libs/core/langchain_core/prompts/few_shot.py b/libs/core/langchain_core/prompts/few_shot.py index 4c5ee2c5dc..bf0d55f84e 100644 --- a/libs/core/langchain_core/prompts/few_shot.py +++ b/libs/core/langchain_core/prompts/few_shot.py @@ -147,20 +147,6 @@ class FewShotPromptTemplate(_FewShotPromptTemplateMixin, StringPromptTemplate): arbitrary_types_allowed = True def format(self, **kwargs: Any) -> str: - """Format the prompt with the inputs. - - Args: - **kwargs: Any arguments to be passed to the prompt template. - - Returns: - A formatted string. - - Example: - - .. code-block:: python - - prompt.format(variable1="foo") - """ kwargs = self._merge_partial_and_user_variables(**kwargs) # Get the examples to use. examples = self._get_examples(**kwargs) @@ -178,6 +164,24 @@ class FewShotPromptTemplate(_FewShotPromptTemplateMixin, StringPromptTemplate): # Format the template with the input variables. return DEFAULT_FORMATTER_MAPPING[self.template_format](template, **kwargs) + async def aformat(self, **kwargs: Any) -> str: + kwargs = self._merge_partial_and_user_variables(**kwargs) + # Get the examples to use. + examples = await self._aget_examples(**kwargs) + examples = [ + {k: e[k] for k in self.example_prompt.input_variables} for e in examples + ] + # Format the examples. + example_strings = [ + await self.example_prompt.aformat(**example) for example in examples + ] + # Create the overall template. + pieces = [self.prefix, *example_strings, self.suffix] + template = self.example_separator.join([piece for piece in pieces if piece]) + + # Format the template with the input variables. + return DEFAULT_FORMATTER_MAPPING[self.template_format](template, **kwargs) + @property def _prompt_type(self) -> str: """Return the prompt type key.""" @@ -383,5 +387,9 @@ class FewShotChatMessagePromptTemplate( messages = self.format_messages(**kwargs) return get_buffer_string(messages) + async def aformat(self, **kwargs: Any) -> str: + messages = await self.aformat_messages(**kwargs) + return get_buffer_string(messages) + def pretty_repr(self, html: bool = False) -> str: raise NotImplementedError() diff --git a/libs/core/langchain_core/prompts/image.py b/libs/core/langchain_core/prompts/image.py index d320690924..477c30e812 100644 --- a/libs/core/langchain_core/prompts/image.py +++ b/libs/core/langchain_core/prompts/image.py @@ -3,6 +3,7 @@ from typing import Any, List from langchain_core.prompt_values import ImagePromptValue, ImageURL, PromptValue from langchain_core.prompts.base import BasePromptTemplate from langchain_core.pydantic_v1 import Field +from langchain_core.runnables import run_in_executor from langchain_core.utils import image as image_utils @@ -80,5 +81,8 @@ class ImagePromptTemplate(BasePromptTemplate[ImageURL]): output["detail"] = detail # type: ignore[typeddict-item] return output + async def aformat(self, **kwargs: Any) -> ImageURL: + return await run_in_executor(None, self.format, **kwargs) + def pretty_repr(self, html: bool = False) -> str: raise NotImplementedError() diff --git a/libs/core/langchain_core/prompts/prompt.py b/libs/core/langchain_core/prompts/prompt.py index 2a8d69d04b..f3c53a0e95 100644 --- a/libs/core/langchain_core/prompts/prompt.py +++ b/libs/core/langchain_core/prompts/prompt.py @@ -114,20 +114,6 @@ class PromptTemplate(StringPromptTemplate): return "prompt" def format(self, **kwargs: Any) -> str: - """Format the prompt with the inputs. - - Args: - kwargs: Any arguments to be passed to the prompt template. - - Returns: - A formatted string. - - Example: - - .. code-block:: python - - prompt.format(variable1="foo") - """ kwargs = self._merge_partial_and_user_variables(**kwargs) return DEFAULT_FORMATTER_MAPPING[self.template_format](self.template, **kwargs) diff --git a/libs/core/tests/unit_tests/prompts/test_few_shot.py b/libs/core/tests/unit_tests/prompts/test_few_shot.py index 4129c3fe53..c24becd90f 100644 --- a/libs/core/tests/unit_tests/prompts/test_few_shot.py +++ b/libs/core/tests/unit_tests/prompts/test_few_shot.py @@ -96,7 +96,7 @@ def test_prompt_missing_input_variables() -> None: ).input_variables == ["foo"] -def test_few_shot_functionality() -> None: +async def test_few_shot_functionality() -> None: """Test that few shot works with examples.""" prefix = "This is a test about {content}." suffix = "Now you try to talk about {new_content}." @@ -112,13 +112,15 @@ def test_few_shot_functionality() -> None: example_prompt=EXAMPLE_PROMPT, example_separator="\n", ) - output = prompt.format(content="animals", new_content="party") expected_output = ( "This is a test about animals.\n" "foo: bar\n" "baz: foo\n" "Now you try to talk about party." ) + output = prompt.format(content="animals", new_content="party") + assert output == expected_output + output = await prompt.aformat(content="animals", new_content="party") assert output == expected_output @@ -365,6 +367,24 @@ class AsIsSelector(BaseExampleSelector): return list(self.examples) +def test_few_shot_prompt_template_with_selector() -> None: + """Tests for few shot chat message template with an example selector.""" + examples = [ + {"question": "foo", "answer": "bar"}, + {"question": "baz", "answer": "foo"}, + ] + example_selector = AsIsSelector(examples) + + few_shot_prompt = FewShotPromptTemplate( + input_variables=["foo"], + suffix="This is a {foo} test.", + example_prompt=EXAMPLE_PROMPT, + example_selector=example_selector, + ) + messages = few_shot_prompt.format(foo="bar") + assert messages == "foo: bar\n\nbaz: foo\n\nThis is a bar test." + + def test_few_shot_chat_message_prompt_template_with_selector() -> None: """Tests for few shot chat message template with an example selector.""" examples = [ @@ -421,6 +441,24 @@ class AsyncAsIsSelector(BaseExampleSelector): return list(self.examples) +async def test_few_shot_prompt_template_with_selector_async() -> None: + """Tests for few shot chat message template with an example selector.""" + examples = [ + {"question": "foo", "answer": "bar"}, + {"question": "baz", "answer": "foo"}, + ] + example_selector = AsyncAsIsSelector(examples) + + few_shot_prompt = FewShotPromptTemplate( + input_variables=["foo"], + suffix="This is a {foo} test.", + example_prompt=EXAMPLE_PROMPT, + example_selector=example_selector, + ) + messages = await few_shot_prompt.aformat(foo="bar") + assert messages == "foo: bar\n\nbaz: foo\n\nThis is a bar test." + + async def test_few_shot_chat_message_prompt_template_with_selector_async() -> None: """Tests for few shot chat message template with an async example selector.""" examples = [