Enter the main heading, usually the same as the title.
');
+ });
});
diff --git a/pyproject.toml b/pyproject.toml
index 41be260e..1f9892ed 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -3,7 +3,7 @@ name = "poml"
version = "0.0.5"
description = "Prompt Orchestration Markup Language"
readme = "README.md"
-requires-python = ">=3.8"
+requires-python = ">=3.9"
license = {file = "LICENSE"}
dependencies = [
"nodejs-wheel"
diff --git a/python/poml/__init__.py b/python/poml/__init__.py
index a718fec0..1de2e4f2 100644
--- a/python/poml/__init__.py
+++ b/python/poml/__init__.py
@@ -2,3 +2,4 @@
from .api import poml
from .cli import entrypoint, run
+from .prompt import Prompt
diff --git a/python/poml/_tags.py b/python/poml/_tags.py
new file mode 100644
index 00000000..88e697ef
--- /dev/null
+++ b/python/poml/_tags.py
@@ -0,0 +1,1277 @@
+# This file is auto-generated from component documentation.
+# Do not edit manually. Run `npm run build-comment` to regenerate.
+
+from typing import Optional, Any, Union, List, Dict
+# from numbers import Number # For more specific number types if needed
+
+class _TagLib:
+
+ def tag(self, tag_name: str, **kwargs: Any) -> Any:
+ """Helper method to create a tag with the given name and attributes.
+ Implemented by subclasses.
+ """
+ raise NotImplementedError("This method should be implemented by subclasses.")
+
+ def document(
+ self,
+ src: Optional[str] = None,
+ buffer: Optional[bytes] = None,
+ base64: Optional[str] = None,
+ parser: Optional[str] = None,
+ multimedia: Optional[bool] = None,
+ selectedPages: Optional[str] = None,
+ **kwargs: Any,
+ ):
+ """Displaying an external document like PDF, TXT or DOCX.
+
+ Args:
+ src (Optional[str]): The source file to read the data from. This must be provided if records is not provided.
+ buffer (Optional[bytes]): Document data buffer. Recommended to use `src` instead unless you want to use a string.
+ base64 (Optional[str]): Base64 encoded string of the document data. Mutually exclusive with `src` and `buffer`.
+ parser (Optional[str]): The parser to use for reading the data. If not provided, it will be inferred from the file extension. Choices: `"auto"`, `"pdf"`, `"docx"`, `"txt"`.
+ multimedia (Optional[bool]): If true, the multimedias will be displayed. If false, the alt strings will be displayed at best effort. Default is `true`. Default is `"true"`.
+ selectedPages (Optional[str]): The pages to be selected. This is only available **for PDF documents**. If not provided, all pages will be selected.
+ You can use a string like `2` to specify a single page, or slice like `2:4` to specify a range of pages (2 inclusive, 4 exclusive).
+ The pages selected are **0-indexed**. Negative indexes like `-1` is not supported here.
+
+ Example:
+ To display a Word document without including the real multimedia:
+ ```xml
+
+ ```
+ """
+ return self.tag(
+ tag_name="Document",
+ src=src,
+ buffer=buffer,
+ base64=base64,
+ parser=parser,
+ multimedia=multimedia,
+ selectedPages=selectedPages,
+ **kwargs,
+ )
+
+ def role(
+ self,
+ caption: Optional[str] = None,
+ captionSerialized: Optional[str] = None,
+ captionStyle: Optional[str] = None,
+ captionTextTransform: Optional[str] = None,
+ captionEnding: Optional[str] = None,
+ **kwargs: Any,
+ ):
+ """Specifies the role you want the language model to assume when responding.
+ Defining a role provides the model with a perspective or context,
+ such as a scientist, poet, child, or any other persona you choose.
+
+ Args:
+ caption (Optional[str]): The title or label for the role paragraph. Default is `Role`. Default is `"Role"`.
+ captionSerialized (Optional[str]): The serialized version of the caption when using "serializer" syntaxes. Default is `role`. Default is `"role"`.
+ captionStyle (Optional[str]): Determines the style of the caption,
+ applicable only for "markup" syntaxes. Default is `header`. Default is `"header"`. Choices: `"header"`, `"bold"`, `"plain"`, `"hidden"`.
+ captionTextTransform (Optional[str]): Specifies text transformation for the caption, applicable only for "markup" syntaxes. Default is `none`. Default is `"none"`. Choices: `"upper"`, `"level"`, `"capitalize"`, `"none"`.
+ captionEnding (Optional[str]): A caption can ends with a colon, a newline or simply nothing.
+ If not specified, it defaults to `colon` for `bold` or `plain` captionStyle, and `none` otherwise. Choices: `"colon"`, `"newline"`, `"colon-newline"`, `"none"`.
+
+ Example:
+ ```xml
+ You are a data scientist.
+ ```
+ """
+ return self.tag(
+ tag_name="Role",
+ caption=caption,
+ captionSerialized=captionSerialized,
+ captionStyle=captionStyle,
+ captionTextTransform=captionTextTransform,
+ captionEnding=captionEnding,
+ **kwargs,
+ )
+
+ def task(
+ self,
+ caption: Optional[str] = None,
+ captionSerialized: Optional[str] = None,
+ captionStyle: Optional[str] = None,
+ captionTextTransform: Optional[str] = None,
+ captionEnding: Optional[str] = None,
+ **kwargs: Any,
+ ):
+ """Task represents the action you want the language model to perform.
+ It is a directive or instruction that you want the model to follow.
+ Task is usually not long, but rather a concise and clear statement.
+ Users can also include a list of steps or instructions to complete the task.
+
+ Args:
+ caption (Optional[str]): The title or label for the task paragraph. Default is `Task`. Default is `"Task"`.
+ captionSerialized (Optional[str]): The serialized version of the caption when using "serializer" syntaxes. Default is `task`. Default is `"task"`.
+ captionStyle (Optional[str]): Determines the style of the caption,
+ applicable only for "markup" syntaxes. Default is `header`. Default is `"header"`. Choices: `"header"`, `"bold"`, `"plain"`, `"hidden"`.
+ captionTextTransform (Optional[str]): Specifies text transformation for the caption, applicable only for "markup" syntaxes. Default is `none`. Default is `"none"`. Choices: `"upper"`, `"level"`, `"capitalize"`, `"none"`.
+ captionEnding (Optional[str]): A caption can ends with a colon, a newline or simply nothing.
+ If not specified, it defaults to `colon` for `bold` or `plain` captionStyle, and `none` otherwise. Choices: `"colon"`, `"newline"`, `"colon-newline"`, `"none"`.
+
+ Example:
+ ```xml
+ Cook a recipe on how to prepare a beef dish.
+ ```
+
+ When including a list of steps:
+ ```xml
+
+ Planning a schedule for a travel.
+
+ Decide on the destination and plan the duration.
+ Find useful information about the destination.
+ Write down the schedule for each day.
+
+
+ ```
+ """
+ return self.tag(
+ tag_name="Task",
+ caption=caption,
+ captionSerialized=captionSerialized,
+ captionStyle=captionStyle,
+ captionTextTransform=captionTextTransform,
+ captionEnding=captionEnding,
+ **kwargs,
+ )
+
+ def output_format(
+ self,
+ caption: Optional[str] = None,
+ captionSerialized: Optional[str] = None,
+ captionStyle: Optional[str] = None,
+ captionTextTransform: Optional[str] = None,
+ captionEnding: Optional[str] = None,
+ **kwargs: Any,
+ ):
+ """Output format deals with the format in which the model should provide the output.
+ It can be a specific format such as JSON, XML, or CSV, or a general format such as a story,
+ a diagram or steps of instructions.
+ Please refrain from specifying too complex formats that the model may not be able to generate,
+ such as a PDF file or a video.
+
+ Args:
+ caption (Optional[str]): The title or label for the output format paragraph. Default is `Output Format`.
+ captionSerialized (Optional[str]): The serialized version of the caption when using "serializer" syntaxes. Default is `outputFormat`. Default is `"outputFormat"`.
+ captionStyle (Optional[str]): Determines the style of the caption,
+ applicable only for "markup" syntaxes. Default is `header`. Default is `"header"`. Choices: `"header"`, `"bold"`, `"plain"`, `"hidden"`.
+ captionTextTransform (Optional[str]): Specifies text transformation for the caption, applicable only for "markup" syntaxes. Default is `none`. Default is `"none"`. Choices: `"upper"`, `"level"`, `"capitalize"`, `"none"`.
+ captionEnding (Optional[str]): A caption can ends with a colon, a newline or simply nothing.
+ If not specified, it defaults to `colon` for `bold` or `plain` captionStyle, and `none` otherwise. Choices: `"colon"`, `"newline"`, `"colon-newline"`, `"none"`.
+
+ Example:
+ ```xml
+ Respond with a JSON without additional characters or punctuations.
+ ```
+ """
+ return self.tag(
+ tag_name="OutputFormat",
+ caption=caption,
+ captionSerialized=captionSerialized,
+ captionStyle=captionStyle,
+ captionTextTransform=captionTextTransform,
+ captionEnding=captionEnding,
+ **kwargs,
+ )
+
+ def stepwise_instructions(
+ self,
+ caption: Optional[str] = None,
+ captionSerialized: Optional[str] = None,
+ captionStyle: Optional[str] = None,
+ captionTextTransform: Optional[str] = None,
+ captionEnding: Optional[str] = None,
+ **kwargs: Any,
+ ):
+ """StepwiseInstructions that elaborates the task by providing a list of steps or instructions.
+ Each step should be concise and clear, and the list should be easy to follow.
+
+ Args:
+ caption (Optional[str]): The title or label for the stepwise instructions paragraph. Default is `Stepwise Instructions`.
+ captionSerialized (Optional[str]): The serialized version of the caption when using "serializer" syntaxes. Default is `stepwiseInstructions`. Default is `"stepwiseInstructions"`.
+ captionStyle (Optional[str]): Determines the style of the caption,
+ applicable only for "markup" syntaxes. Default is `header`. Default is `"header"`. Choices: `"header"`, `"bold"`, `"plain"`, `"hidden"`.
+ captionTextTransform (Optional[str]): Specifies text transformation for the caption, applicable only for "markup" syntaxes. Default is `none`. Default is `"none"`. Choices: `"upper"`, `"level"`, `"capitalize"`, `"none"`.
+ captionEnding (Optional[str]): A caption can ends with a colon, a newline or simply nothing.
+ If not specified, it defaults to `colon` for `bold` or `plain` captionStyle, and `none` otherwise. Choices: `"colon"`, `"newline"`, `"colon-newline"`, `"none"`.
+
+ Example:
+ ```xml
+
+
+ Interpret and rewrite user's query.
+ Think of a plan to solve the query.
+ Generate a response based on the plan.
+
+
+ ```
+ """
+ return self.tag(
+ tag_name="StepwiseInstructions",
+ caption=caption,
+ captionSerialized=captionSerialized,
+ captionStyle=captionStyle,
+ captionTextTransform=captionTextTransform,
+ captionEnding=captionEnding,
+ **kwargs,
+ )
+
+ def hint(
+ self,
+ caption: Optional[str] = None,
+ captionSerialized: Optional[str] = None,
+ captionStyle: Optional[str] = None,
+ captionTextTransform: Optional[str] = None,
+ captionColon: Optional[bool] = None,
+ **kwargs: Any,
+ ):
+ """Hint can be used anywhere in the prompt where you want to provide a helpful tip or explanation.
+ It is usually a short and concise statement that guides the LLM in the right direction.
+
+ Args:
+ caption (Optional[str]): The title or label for the hint paragraph. Default is `Hint`. Default is `"Hint"`.
+ captionSerialized (Optional[str]): The serialized version of the caption when using "serializer" syntaxes. Default is `hint`. Default is `"hint"`.
+ captionStyle (Optional[str]): Determines the style of the caption,
+ applicable only for "markup" syntaxes. Default is `bold`. Default is `"bold"`. Choices: `"header"`, `"bold"`, `"plain"`, `"hidden"`.
+ captionTextTransform (Optional[str]): Specifies text transformation for the caption, applicable only for "markup" syntaxes. Default is `none`. Default is `"none"`. Choices: `"upper"`, `"level"`, `"capitalize"`, `"none"`.
+ captionColon (Optional[bool]): Indicates whether to append a colon after the caption.
+ By default, this is true for `bold` or `plain` captionStyle, and false otherwise.
+
+ Example:
+ ```xml
+ Alice first purchased 4 apples and then 3 more, so she has 7 apples in total.
+ ```
+ """
+ return self.tag(
+ tag_name="Hint",
+ caption=caption,
+ captionSerialized=captionSerialized,
+ captionStyle=captionStyle,
+ captionTextTransform=captionTextTransform,
+ captionColon=captionColon,
+ **kwargs,
+ )
+
+ def introducer(
+ self,
+ caption: Optional[str] = None,
+ captionSerialized: Optional[str] = None,
+ captionStyle: Optional[str] = None,
+ captionTextTransform: Optional[str] = None,
+ captionEnding: Optional[str] = None,
+ **kwargs: Any,
+ ):
+ """Introducer is a paragraph before a long paragraph (usually a list of examples, steps, or instructions).
+ It serves as a context introducing what is expected to follow.
+
+ Args:
+ caption (Optional[str]): The title or label for the introducer paragraph. Default is `Introducer`. Default is `"Introducer"`.
+ captionSerialized (Optional[str]): The serialized version of the caption when using "serializer" syntaxes. Default is `introducer`. Default is `"introducer"`.
+ captionStyle (Optional[str]): Determines the style of the caption,
+ applicable only for "markup" syntaxes. Default is `hidden`. Default is `"hidden"`. Choices: `"header"`, `"bold"`, `"plain"`, `"hidden"`.
+ captionTextTransform (Optional[str]): Specifies text transformation for the caption, applicable only for "markup" syntaxes. Default is `none`. Default is `"none"`. Choices: `"upper"`, `"level"`, `"capitalize"`, `"none"`.
+ captionEnding (Optional[str]): A caption can ends with a colon, a newline or simply nothing.
+ If not specified, it defaults to `colon` for `bold` or `plain` captionStyle, and `none` otherwise. Choices: `"colon"`, `"newline"`, `"colon-newline"`, `"none"`.
+
+ Example:
+ ```xml
+ Here are some examples.
+ ```
+ """
+ return self.tag(
+ tag_name="Introducer",
+ caption=caption,
+ captionSerialized=captionSerialized,
+ captionStyle=captionStyle,
+ captionTextTransform=captionTextTransform,
+ captionEnding=captionEnding,
+ **kwargs,
+ )
+
+ def example_set(
+ self,
+ caption: Optional[str] = None,
+ captionSerialized: Optional[str] = None,
+ chat: Optional[bool] = None,
+ introducer: Optional[str] = None,
+ captionStyle: Optional[str] = None,
+ captionTextTransform: Optional[str] = None,
+ captionEnding: Optional[str] = None,
+ **kwargs: Any,
+ ):
+ """Example set (``) is a collection of examples that are usually presented in a list.
+ With the example set, you can manage multiple examples under a single title and optionally an introducer,
+ as well as the same `chat` format.
+ You can also choose to use `` purely without example set.
+
+ Args:
+ caption (Optional[str]): The title or label for the example set paragraph. Default is `Examples`. Default is `"Examples"`.
+ captionSerialized (Optional[str]): The serialized version of the caption when using "serializer" syntaxes. Default is `examples`. Default is `"examples"`.
+ chat (Optional[bool]): Indicates whether the examples should be rendered in chat format.
+ By default, it's `true` for "markup" syntaxes and `false` for "serializer" syntaxes.
+ introducer (Optional[str]): An optional introducer text to be displayed before the examples.
+ For example, `Here are some examples:`.
+ captionStyle (Optional[str]): Determines the style of the caption,
+ applicable only for "markup" syntaxes. Default is `header`. Default is `"header"`. Choices: `"header"`, `"bold"`, `"plain"`, `"hidden"`.
+ captionTextTransform (Optional[str]): Specifies text transformation for the caption, applicable only for "markup" syntaxes. Default is `none`. Default is `"none"`. Choices: `"upper"`, `"level"`, `"capitalize"`, `"none"`.
+ captionEnding (Optional[str]): A caption can ends with a colon, a newline or simply nothing.
+ If not specified, it defaults to `colon` for `bold` or `plain` captionStyle, and `none` otherwise. Choices: `"colon"`, `"newline"`, `"colon-newline"`, `"none"`.
+
+ Example:
+ ```xml
+
+
+ What is the capital of France?
+
+
+
+ What is the capital of Germany?
+
+
+
+ ```
+ """
+ return self.tag(
+ tag_name="ExampleSet",
+ caption=caption,
+ captionSerialized=captionSerialized,
+ chat=chat,
+ introducer=introducer,
+ captionStyle=captionStyle,
+ captionTextTransform=captionTextTransform,
+ captionEnding=captionEnding,
+ **kwargs,
+ )
+
+ def example(
+ self,
+ caption: Optional[str] = None,
+ captionSerialized: Optional[str] = None,
+ captionStyle: Optional[str] = None,
+ chat: Optional[bool] = None,
+ captionTextTransform: Optional[str] = None,
+ captionColon: Optional[bool] = None,
+ **kwargs: Any,
+ ):
+ """Example is useful for providing a context, helping the model to understand what kind of inputs and outputs are expected.
+ It can also be used to demonstrate the desired output style, clarifying the structure, tone, or level of detail in the response.
+
+ Args:
+ caption (Optional[str]): The title or label for the example paragraph. Default is `Example`. Default is `"Example"`.
+ captionSerialized (Optional[str]): The serialized version of the caption when using "serializer" syntaxes. Default is `example`. Default is `"example"`.
+ captionStyle (Optional[str]): Determines the style of the caption, applicable only for "markup" syntaxes. Default is `hidden`.
+ Options include `header`, `bold`, `plain`, or `hidden`. Default is `"hidden"`.
+ chat (Optional[bool]): Indicates whether the example should be rendered in chat format.
+ When used in a example set (``), this is inherited from the example set.
+ Otherwise, it defaults to `false` for "serializer" syntaxes and `true` for "markup" syntaxes.
+ captionTextTransform (Optional[str]): Specifies text transformation for the caption, applicable only for "markup" syntaxes.
+ Options are `upper`, `lower`, `capitalize`, or `none`. Default is `none`. Default is `"none"`.
+ captionColon (Optional[bool]): Indicates whether to append a colon after the caption.
+ By default, this is true for `bold` or `plain` captionStyle, and false otherwise.
+
+ Example:
+ ```xml
+
+ What is the capital of France?
+
+
+ ```
+
+ ```xml
+ Summarize the following passage in a single sentence.
+
+ The sun provides energy for life on Earth through processes like photosynthesis.
+
+
+ ```
+ """
+ return self.tag(
+ tag_name="Example",
+ caption=caption,
+ captionSerialized=captionSerialized,
+ captionStyle=captionStyle,
+ chat=chat,
+ captionTextTransform=captionTextTransform,
+ captionColon=captionColon,
+ **kwargs,
+ )
+
+ def example_input(
+ self,
+ caption: Optional[str] = None,
+ captionSerialized: Optional[str] = None,
+ speaker: Optional[str] = None,
+ captionStyle: Optional[str] = None,
+ captionTextTransform: Optional[str] = None,
+ captionColon: Optional[bool] = None,
+ **kwargs: Any,
+ ):
+ """ExampleInput (``) is a paragraph that represents an example input.
+ By default, it's spoken by a human speaker in a chat context, but you can manually specify the speaker.
+
+ Args:
+ caption (Optional[str]): The title or label for the example input paragraph. Default is `Input`. Default is `"Input"`.
+ captionSerialized (Optional[str]): The serialized version of the caption when using "serializer" syntaxes. Default is `input`. Default is `"input"`.
+ speaker (Optional[str]): The speaker for the example input. Default is `human` if chat context is enabled (see ``). Default is `"human"`.
+ captionStyle (Optional[str]): Determines the style of the caption,
+ applicable only for "markup" syntaxes. Default is `hidden` if chat context is enabled. Otherwise, it's `bold`. Default is `"hidden"`. Choices: `"header"`, `"bold"`, `"plain"`, `"hidden"`.
+ captionTextTransform (Optional[str]): Specifies text transformation for the caption, applicable only for "markup" syntaxes. Default is `none`. Default is `"none"`. Choices: `"upper"`, `"level"`, `"capitalize"`, `"none"`.
+ captionColon (Optional[bool]): Indicates whether to append a colon after the caption.
+ By default, this is true for `bold` or `plain` captionStyle, and false otherwise.
+
+ Example:
+ ```xml
+ What is the capital of France?
+ ```
+
+ When used with a template:
+
+ ```xml
+ What is the capital of {{country}}?
+ ```
+ """
+ return self.tag(
+ tag_name="ExampleInput",
+ caption=caption,
+ captionSerialized=captionSerialized,
+ speaker=speaker,
+ captionStyle=captionStyle,
+ captionTextTransform=captionTextTransform,
+ captionColon=captionColon,
+ **kwargs,
+ )
+
+ def example_output(
+ self,
+ caption: Optional[str] = None,
+ captionSerialized: Optional[str] = None,
+ speaker: Optional[str] = None,
+ captionStyle: Optional[str] = None,
+ captionTextTransform: Optional[str] = None,
+ captionColon: Optional[bool] = None,
+ **kwargs: Any,
+ ):
+ """ExampleOutput (`
+ # [{'speaker': 'human', 'content': '# Task\n\nThis is a task description.\n\nThis is a paragraph in the document.'}]
diff --git a/python/tests/test_basic.py b/python/tests/test_basic.py
index f14f28c4..1aa33a71 100644
--- a/python/tests/test_basic.py
+++ b/python/tests/test_basic.py
@@ -1,5 +1,30 @@
-from poml import poml
+from poml import poml, Prompt
def test_basic():
assert poml("
Hello, World!
") == [{"speaker": "human", "content": "Hello, World!"}]
+
+
+def test_prompt():
+ with Prompt() as p:
+ with p.task(caption="My Task"):
+ p.text("This is a task description.")
+ with p.paragraph():
+ with p.header():
+ p.text("Subheading")
+ p.text("This is a paragraph in the document.")
+
+ xml_output = p.dump_xml()
+ print(xml_output)
+ assert xml_output == (
+ """This is a task description.
+ SubheadingThis is a paragraph in the document.
+"""
+ )
+ prompt_output = p.render()
+ assert prompt_output == [
+ {
+ "speaker": "human",
+ "content": "# My Task\n\nThis is a task description.\n\n## Subheading\n\nThis is a paragraph in the document.",
+ }
+ ]