diff --git a/langchain/chains/self_ask_with_search/examples.json b/langchain/chains/self_ask_with_search/examples.json new file mode 100644 index 00000000000..69cd1438b46 --- /dev/null +++ b/langchain/chains/self_ask_with_search/examples.json @@ -0,0 +1,18 @@ +[ + { + "question": "Who lived longer, Muhammad Ali or Alan Turing?", + "answer": "Are follow up questions needed here: Yes.\nFollow up: How old was Muhammad Ali when he died?\nIntermediate answer: Muhammad Ali was 74 years old when he died.\nFollow up: How old was Alan Turing when he died?\nIntermediate answer: Alan Turing was 41 years old when he died.\nSo the final answer is: Muhammad Ali" + }, + { + "question": "When was the founder of craigslist born?", + "answer": "Are follow up questions needed here: Yes.\nFollow up: Who was the founder of craigslist?\nIntermediate answer: Craigslist was founded by Craig Newmark.\nFollow up: When was Craig Newmark born?\nIntermediate answer: Craig Newmark was born on December 6, 1952.\nSo the final answer is: December 6, 1952" + }, + { + "question": "Who was the maternal grandfather of George Washington?", + "answer": "Are follow up questions needed here: Yes.\nFollow up: Who was the mother of George Washington?\nIntermediate answer: The mother of George Washington was Mary Ball Washington.\nFollow up: Who was the father of Mary Ball Washington?\nIntermediate answer: The father of Mary Ball Washington was Joseph Ball.\nSo the final answer is: Joseph Ball" + }, + { + "question": "Are both the directors of Jaws and Casino Royale from the same country?", + "answer": "Are follow up questions needed here: Yes.\nFollow up: Who is the director of Jaws?\nIntermediate Answer: The director of Jaws is Steven Spielberg.\nFollow up: Where is Steven Spielberg from?\nIntermediate Answer: The United States.\nFollow up: Who is the director of Casino Royale?\nIntermediate Answer: The director of Casino Royale is Martin Campbell.\nFollow up: Where is Martin Campbell from?\nIntermediate Answer: New Zealand.\nSo the final answer is: No" + } +] \ No newline at end of file diff --git a/langchain/chains/self_ask_with_search/prompt.py b/langchain/chains/self_ask_with_search/prompt.py index 003e68dd7fd..3208a5cbef9 100644 --- a/langchain/chains/self_ask_with_search/prompt.py +++ b/langchain/chains/self_ask_with_search/prompt.py @@ -1,13 +1,25 @@ # flake8: noqa -from langchain.prompts.prompt import Prompt +from langchain.prompts.dynamic import +from langchain.prompts.data import BaseExample +from pathlib import Path + +example_path = Path(__file__).parent / "examples.json" +import json + + +class SelfAskWithSearchExample(BaseExample): + question: str + answer: str + + def formatted(self) -> str: + return f"Question: {self.question}\n{self.answer}" + +with open(example_path) as f: + raw_examples = json.load(f) + examples = [SelfAskWithSearchExample(**example) for example in raw_examples] _DEFAULT_TEMPLATE = """Question: Who lived longer, Muhammad Ali or Alan Turing? -Are follow up questions needed here: Yes. -Follow up: How old was Muhammad Ali when he died? -Intermediate answer: Muhammad Ali was 74 years old when he died. -Follow up: How old was Alan Turing when he died? -Intermediate answer: Alan Turing was 41 years old when he died. -So the final answer is: Muhammad Ali + Question: When was the founder of craigslist born? Are follow up questions needed here: Yes. diff --git a/langchain/prompts/data.py b/langchain/prompts/data.py new file mode 100644 index 00000000000..ddddd8b903c --- /dev/null +++ b/langchain/prompts/data.py @@ -0,0 +1,18 @@ +from pydantic import BaseModel +from abc import abstractmethod, ABC + +class BaseExample(BaseModel, ABC): + """Base class for examples.""" + + @abstractmethod + @property + def formatted(self) -> str: + """Returns a formatted example as a string.""" + + +class SimpleExample(BaseExample): + + text: str + + def formatted(self) -> str: + return self.text \ No newline at end of file diff --git a/langchain/prompts/dynamic.py b/langchain/prompts/dynamic.py index fbf0c351351..af92302a7a1 100644 --- a/langchain/prompts/dynamic.py +++ b/langchain/prompts/dynamic.py @@ -5,7 +5,7 @@ from typing import Any, Callable, Dict, List from pydantic import BaseModel, Extra, root_validator from langchain.prompts.base import DEFAULT_FORMATTER_MAPPING, BasePrompt - +from langchain.prompts.data import BaseExample, SimpleExample class DynamicPrompt(BaseModel, BasePrompt): r"""Schema to represent a dynamic prompt for an LLM. @@ -25,7 +25,7 @@ class DynamicPrompt(BaseModel, BasePrompt): ) """ - examples: List[str] + examples: List[BaseExample] """A list of the examples that the prompt template expects.""" example_separator: str = "\n\n" @@ -76,7 +76,7 @@ class DynamicPrompt(BaseModel, BasePrompt): prompt.format(variable1="foo") """ - curr_examples = self.examples + curr_examples = [example.formatted for example in self.examples] template = self.template(curr_examples, **kwargs) while self.get_text_length(template) > self.max_length and curr_examples: curr_examples = curr_examples[:-1] @@ -96,13 +96,6 @@ class DynamicPrompt(BaseModel, BasePrompt): f"Invalid template format. Got `{template_format}`;" f" should be one of {valid_formats}" ) - try: - result = values["get_text_length"]("foo") - assert isinstance(result, int) - except AssertionError: - raise ValueError( - "Invalid text length callable, must take string & return int;" - ) dummy_inputs = {input_variable: "foo" for input_variable in input_variables} try: formatter_func = DEFAULT_FORMATTER_MAPPING[template_format] @@ -110,3 +103,21 @@ class DynamicPrompt(BaseModel, BasePrompt): except KeyError: raise ValueError("Invalid prompt schema.") return values + + @root_validator() + def get_text_length_is_valid(cls, values: Dict) -> Dict: + try: + result = values["get_text_length"]("foo") + assert isinstance(result, int) + except AssertionError: + raise ValueError( + "Invalid text length callable, must take string & return int;" + ) + return values + + @root_validator() + def convert_examples(cls, values: Dict) -> Dict: + examples = values["examples"] + examples = [example if isinstance(example, BaseExample) else SimpleExample(text=str(example)) for example in examples] + values["examples"] = examples + return values