A PHP package that transforms class properties into XML-formatted prompts, ready for Large Language Model (LLM) API calls. It recursively handles arrays, collections, nested arrays, and nested Prompt instances, converting them into XML with appropriate tags.
Structured prompts are essential when interacting with Large Language Models (LLMs) to ensure consistency, clarity, and optimal performance. XML provides a standardized way to structure data, making it an excellent choice for formatting prompts:
- Consistency Across Models: XML's hierarchical structure allows for consistent formatting of prompts, which can be beneficial when working with different models or APIs.
- Improved Parsing: XML is a widely accepted format that can be easily parsed and validated, reducing the likelihood of errors in prompt interpretation.
- Flexibility: XML's ability to represent complex nested data makes it suitable for constructing detailed and intricate prompts.
- Readability: Structured XML prompts are more readable and maintainable, aiding in debugging and prompt optimization.
By using XML-formatted prompts, developers can provide clear and unambiguous instructions to LLMs, potentially enhancing the models' understanding and response accuracy.
- Installation
- Features
- Usage
- Testing
- Contributing
- License
- Additional Notes
Install the package via Composer:
composer require ogi/prompt- Automatic XML Conversion: Transforms public class properties into XML elements.
- Array and Collection Handling: Supports arrays, collections, and nested arrays, using
<entry>and<list>tags where appropriate. - Nested Prompt Instances: Allows properties to be instances of
Prompt, rendering them recursively within<prompt>tags. - Custom Object Support: Handles objects implementing
toArray()or__toString(). - Edge Case Handling: Manages special cases like private/protected properties, null values, booleans, numerics, special characters, and circular references.
- Recursive Processing: Recursively processes nested arrays and collections to any depth.
- Easy Integration: Extend the
Promptclass and define your data; therender()method handles the rest. - Templates: Extend the
GeneralPromptTemplateclass and leverage its setters to populate a versatile, general-use template prompt for your data.
Create a PHP class that extends the Prompt class provided by the package. Define your data using public properties.
<?php
require 'vendor/autoload.php';
use Ogi\Prompt\Prompt;
class MyPrompt extends Prompt
{
public $purpose = 'Who are the leaders of England, France and Russia when World War 2 started';
public $instructions = [
'For definition of leader consider titles - king, prime-minister, president',
'Present the output in a markdown table with columns leader title,name, country'
];
}
$prompt = new MyPrompt();
echo $prompt->render();Output:
<prompt>
<purpose>Who are the leaders of England, France and Russia when World War 2 started</purpose>
<instructions>
<entry>For definition of leader consider titles - king, prime-minister, president</entry>
<entry>Present the output in a markdown table with columns leader title,name, country</entry>
</instructions>
</prompt>The package automatically handles arrays and converts them into XML using <entry> and <list> tags.
<?php
class MyPrompt extends Prompt
{
public $questions = [
'What is your name?',
'How old are you?',
'What is your favorite color?',
];
}
$prompt = new MyPrompt();
echo $prompt->render();Output:
<prompt>
<questions>
<entry>What is your name?</entry>
<entry>How old are you?</entry>
<entry>What is your favorite color?</entry>
</questions>
</prompt>The package supports any object that implements the Traversable interface, such as PHP's ArrayObject or collections from frameworks like Laravel's Illuminate\Support\Collection.
<?php
use Illuminate\Support\Collection;
class MyPrompt extends Prompt
{
public $items;
public function __construct()
{
$this->items = new Collection([
'First Item',
'Second Item',
new Collection(['Nested Item 1', 'Nested Item 2']),
'Third Item',
]);
}
}
$prompt = new MyPrompt();
echo $prompt->render();Output:
<prompt>
<items>
<entry>First Item</entry>
<entry>Second Item</entry>
<list>
<entry>Nested Item 1</entry>
<entry>Nested Item 2</entry>
</list>
<entry>Third Item</entry>
</items>
</prompt>You can have properties that are instances of the Prompt class. These will be rendered recursively within <prompt> tags.
<?php
class SubPrompt extends Prompt
{
public $message = 'This is a sub-prompt.';
public $details = [
'detail1' => 'Detail One',
'detail2' => 'Detail Two',
];
}
class MyPrompt extends Prompt
{
public $title = 'Main Prompt';
public $subPrompt;
public function __construct()
{
$this->subPrompt = new SubPrompt();
}
}
$prompt = new MyPrompt();
echo $prompt->render();Output:
<prompt>
<title>Main Prompt</title>
<subPrompt>
<prompt>
<message>This is a sub-prompt.</message>
<details>
<detail1>Detail One</detail1>
<detail2>Detail Two</detail2>
</details>
</prompt>
</subPrompt>
</prompt>The GeneralPromptTemplate is an abstract class that allows you to define more structured prompts with context, purpose, goals, and instructions for input and output. You can extend this class and set properties to generate XML prompts.
<?php
require 'vendor/autoload.php';
use Ogi\Prompt\Templates\GeneralPromptTemplate;
class MyPrompt extends GeneralPromptTemplate
{
public function setInput($data): void
{
$this->input = $data;
}
}
$prompt = new MyPrompt();
$prompt->addContext('Provide recommendations based on user input.');
$prompt->addPurpose('To give tailored advice for improving coding practices.');
$prompt->addGoal('Ensure the recommendations are practical and concise.');
$prompt->addInputDefinition('A brief description of the code the user wants feedback on.');
$prompt->addOutputDefinition('A list of suggestions to improve the user’s code.');
$prompt->addHowtoSteps([
'Analyze the provided code.',
'Identify areas of improvement.',
'Provide actionable feedback with examples.',
]);
echo $prompt->render();Output:
<prompt>
<context>Provide recommendations based on user input.</context>
<purpose>To give tailored advice for improving coding practices.</purpose>
<goal>Ensure the recommendations are practical and concise.</goal>
<instructions>
<input>
<definition>A brief description of the code the user wants feedback on.</definition>
<structure></structure>
<value-meaning></value-meaning>
<possible-values></possible-values>
<if-instructions-per-type>
</if-instructions-per-type>
</input>
<output>
<definition>A list of suggestions to improve the user’s code.</definition>
<structure></structure>
<value-meaning></value-meaning>
<possible-values></possible-values>
<if-instructions-per-type>
</if-instructions-per-type>
<example-valid-output></example-valid-output>
<example-invalid-output></example-invalid-output>
</output>
<howto>
<definition></definition>
<steps>
<entry>Analyze the provided code.</entry>
<entry>Identify areas of improvement.</entry>
<entry>Provide actionable feedback with examples.</entry>
</steps>
<corner-cases>
</corner-cases>
</howto>
</instructions>
<considerations>
</considerations>
<struggles>
</struggles>
<input></input>
</prompt>The package can handle custom objects that implement toArray() or __toString().
<?php
class CustomObject
{
public function toArray()
{
return [
'keyA' => 'Value A',
'keyB' => 'Value B',
];
}
}
class MyPrompt extends Prompt
{
public $customData;
public function __construct()
{
$this->customData = new CustomObject();
$this->customArray = [1,2, new CustomObject()];
}
}
$prompt = new MyPrompt();
echo $prompt->render();Output:
<prompt>
<customData>
<keyA>Value A</keyA>
<keyB>Value B</keyB>
</customData>
<customArray>
<entry>1</entry>
<entry>2</entry>
<entry>
<keyA>Value A</keyA>
<keyB>Value B</keyB>
</keyB>
</customArray>
</prompt><?php
class StringableObject
{
public function __toString()
{
return 'I can be converted to a string!';
}
}
class MyPrompt extends Prompt
{
public $stringable;
public function __construct()
{
$this->stringable = new StringableObject();
}
}
$prompt = new MyPrompt();
echo $prompt->render();Output:
<prompt>
<stringable>I can be converted to a string!</stringable>
</prompt>Only public properties are included in the XML output. Private and protected properties are excluded.
<?php
class MyPrompt extends Prompt
{
public $publicProperty = 'Public Value';
protected $protectedProperty = 'Protected Value';
private $privateProperty = 'Private Value';
}
$prompt = new MyPrompt();
echo $prompt->render();Output:
<prompt>
<publicProperty>Public Value</publicProperty>
</prompt>Properties with null values or empty arrays are handled gracefully.
<?php
class MyPrompt extends Prompt
{
public $nullProperty = null;
public $emptyArray = [];
}
$prompt = new MyPrompt();
echo $prompt->render();Output:
<prompt>
<nullProperty></nullProperty>
<emptyArray>
</emptyArray>
</prompt>Boolean values are converted as follows:
truebecomes1falsebecomes an empty string
<?php
class MyPrompt extends Prompt
{
public $trueProperty = true;
public $falseProperty = false;
}
$prompt = new MyPrompt();
echo $prompt->render();Output:
<prompt>
<trueProperty>true</trueProperty>
<falseProperty>false</falseProperty>
</prompt>Numeric values are converted to strings and included in the output.
<?php
class MyPrompt extends Prompt
{
public $integerProperty = 42;
public $floatProperty = 3.14;
}
$prompt = new MyPrompt();
echo $prompt->render();Output:
<prompt>
<integerProperty>42</integerProperty>
<floatProperty>3.14</floatProperty>
</prompt>Special characters are properly escaped to produce valid XML.
<?php
class MyPrompt extends Prompt
{
public $specialChars = 'Special < & > " \' Characters';
}
$prompt = new MyPrompt();
echo $prompt->render();Output:
<prompt>
<specialChars>Special < & > " ' Characters</specialChars>
</prompt>Objects that cannot be converted to a string or array are represented as empty tags.
<?php
class NonStringableObject
{
public $data = 'Some Data';
}
class MyPrompt extends Prompt
{
public $nonStringableObject;
public function __construct()
{
$this->nonStringableObject = new NonStringableObject();
}
}
$prompt = new MyPrompt();
echo $prompt->render();Output:
<prompt>
<nonStringableObject></nonStringableObject>
</prompt>The package handles circular references gracefully to prevent infinite recursion.
<?php
class MyPrompt extends Prompt
{
public $me;
public function __construct()
{
$this->me = $this;
}
}
$prompt = new MyPrompt();
echo $prompt->render();Output:
<prompt>
<me>
<self></self>
</me>
</prompt>The package includes a comprehensive test suite using PHPUnit to ensure reliability and correctness. Tests cover:
- Inclusion of public properties and exclusion of private/protected ones.
- Handling of null values, empty arrays, booleans, numerics, and special characters.
- Processing of objects with and without
toArray()or__toString__. - Recursive rendering of nested
Promptinstances. - Edge cases like circular references and mixed-type arrays.
To run the tests, execute:
./vendor/bin/phpunitOr if you have added a Composer script:
composer testContributions are welcome! Please follow these steps:
- Fork the repository on GitHub.
- Create a new branch for your feature or bugfix.
- Write tests for your changes.
- Ensure all tests pass.
- Submit a pull request with a detailed description of your changes.
This project is licensed under the MIT License.
- PHP Version: Ensure your PHP version is 7.4 or higher.
- Dependencies: If you use collections from frameworks like Laravel, make sure to include the necessary packages (e.g.,
illuminate/support). - Circular References: Circular references are detected to prevent infinite loops during rendering.
Need Help?
If you have any questions or need assistance, please open an issue on the GitHub repository.
Happy Coding!