PromptManager
Manage the parameterized prompts (text) used in generative AI (aka chatGPT, OpenAI, et.al.) using storage adapters such as FileSystemAdapter, SqliteAdapter and ActiveRecordAdapter.
Breaking Change in version 0.3.0 - The value of the parameters Hash for a keyword is now an Array instead of a single value. The last value in the Array is always the most recent value used for the given keyword. This was done to support the use of a Readline::History object editing in the aia CLI tool
Table of Contents
- Installation
- Usage
- Overview
- Generative AI (gen-AI)
- What does a keyword look like?
- Generative AI (gen-AI)
- Storage Adapters
- FileSystemAdapter
- Configuration
- prompts_dir
- search_proc
- File Extensions
- Example Prompt Text File
- Example Prompt Parameters JSON File
- Extra Functionality
- Configuration
- ActiveRecordAdapter
- Configuration
- model
- id_column
- text_column
- parameters_column
- Configuration
- Other Potential Storage Adapters
- FileSystemAdapter
- Development
- Contributing
- License
Installation
Install the gem and add to the application's Gemfile by executing:
bundle add prompt_manager
If bundler is not being used to manage dependencies, install the gem by executing:
gem install prompt_manager
Usage
See also examples/using_search_proc.rb
Overview
Generative AI (gen-AI)
Gen-AI deals with the conversion (some would say execution) of a human natural language text (the "prompt") into somthing else using what are known as large language models (LLM) such as those available from OpenAI. A parameterized prompt is one in which there are embedded keywords (parameters) which are place holders for other text to be inserted into the prompt.
The prompt_manager uses a regular expression to identify these keywords within the prompt. It uses the keywords as keys in a parameters
Hash which is stored with the prompt text in a serialized form - for example as JSON.
What does a keyword look like?
The current hard-coded REGEX for a [KEYWORD] identifies any all [UPPERCASE_TEXT] enclosed in square brackets as a keyword. [KEYWORDS CAN ALSO HAVE SPACES] as well as the underscore character.
This is just the initial convention adopted by prompt_manager. It is intended that this REGEX be configurable so that the prompt_manager can be used with other conventions.
Storage Adapters
A storage adapter is a class instance that ties the PromptManager::Prompt
class to a storage facility that holds the actual prompts. Currently there are 3 storage adapters planned for implementation.
The PromptManager::Prompt
to support a small set of methods. A storage adapter can provide "extra" class or instance methods that can be used through the Prompt class. See the test/prompt_manager/prompt_test.rb
for guidance on creating a new storage adapter.
FileSystemAdapter
This is the first storage adapter developed. It saves prompts as text files within the file system inside a designated prompts_dir
(directory) such as ~/.prompts
or where it makes the most sense to you. Another example would be to have your directory on a shared file system so that others can use the same prompts.
The prompt ID
is the basename of the text file. For example todo.txt
is the file for the prompt ID todo
(see the examples directory.)
The parameters for the todo
prompt ID are saved in the same directory as todo.txt
in a JSON file named todo.json
(also in the examples directory.)
Configuration
Use a config
block to establish the configuration for the class.
PromptManager::Storage::FileSystemAdapter.config do |o|
o.prompts_dir = "path/to/prompts_directory"
o.search_proc = nil # default
o.prompt_extension = '.txt' # default
o.params_extension = '.json' # default
end
The config
block returns self
so that means you can do this to setup the storage adapter with the Prompt class:
PromptManager::Prompt
.storage_adapter =
PromptManager::Storage::FileSystemAdapter
.config do |config|
config.prompts_dir = 'path/to/prompts_dir'
end.new
prompts_dir
This is either a String
or a Pathname
object. All file paths are maintained in the class as Pathname
objects. If you provide a String
it will be converted. Relative paths will be converted to absolute paths.
An ArgumentError
will be raised when prompts_dir
does not exist or if it is not a directory.
search_proc
The default for search_proc
is nil which means that the search will be preformed by a default search
method which is basically reading all the prompt files to see which ones contain the search term. It will return an Array of prompt IDs for each prompt file found that contains the search term. Its up to the application to select which returned prompt ID to use.
There are faster ways to search and select files. For example there are specialized search and selection utilities that are available for the command line. The examples
directory contains a bash
script named rgfzf
that uses rg
(aka ripgrep
) to do the searching and fzf
to do the selecting.
See examples/using_search_proc.rb
File Extensions
These two configuration options are String
objects that must start with a period "." utherwise an ArgumentError
will be raised.
- prompt_extension - default: '.txt'
- params_extension - default: '.json'
Currently the FileSystemAdapter
only supports a JSON serializer for its parameters Hash. Using any other values for these extensions will cause problems.
They exist so that there is a platform on to which other storage adapters can be built or serializers added. This is not currently on the roadmap.
Example Prompt Text File
# ~/.prompts/joke.txt
# Desc: Tell some jokes
Tell me a few [KIND] jokes about [SUBJECT]
Note the command lines at the top. This is a convention I use. It is not part of the software. I find it helpful in documenting the prompt.
Example Prompt Parameters JSON File
{
"[KIND]": [
"pun",
"family friendly"
],
"[SUBJECT]": [
"parrot",
"garbage man",
"snowman",
"weather girl"
]
}
The last value in the keyword's Array is the most recent value used for that keyword. This is a functionality established since v0.3.0. Its purpose is to provide a history of values from which a user can select to repeat a previous value or to select ta previous value and edit it into something new.
Extra Functionality
The FileSystemAdapter
adds two new methods for use by the Prompt
class:
- list - returns an Array of prompt IDs
- path and path(prompt_id) - returns a
Pathname
object to the prompt file
Use the path(prompt_id)
form against the Prompt
class
Use prompt.path
when you have an instance of a Prompt
ActiveRecordAdapter
The ActiveRecordAdapter
assumes that there is a database already configured by the application program that is requiring prompt_manager
which has a model that contains prompt content. This model must have at least three columns which contain content for:
- a prompt ID
- prompt text
- prompt parameters
The model and the columns for these three elements can have any name. Those names are provided to the ActiveRecordAdapter
in its config block.
Configuration
Use a config
block to establish the configuration for the class.
The PromptManager::Prompt
class expects an instance of a storage adapter class. By convention storage adapter class config methods will return self
so that a simple new
after the config will establish the instance.
PromptManager::Prompt
.storage_adapter =
PromptManager::Storage::ActiveRecordAdapter.config do |config|
config.model = DbPromptModel # any ActiveRecord::Base model
config.id_column = :prompt_name
config.text_column = :prompt_text
config.parameters_column = :prompt_params
end.new # adapters an instances of the adapter class
model
The model
configuration parameter is the actual class name of the ActiveRecord::Base
or ApplicationRecord
(if you are using a rails application) that contains the content used for prompts.
id_column
The id_column
contains the name of the column that contains the "prompt ID" content. It can be either a String
or Symbol
value.
text_column
The text_column
contains name of the column that contains the actual raw text of the prompt. This raw text can include the keywords which will be replaced by values from the parameters Hash. The column name value can be either a String
or a Symbol
.
parameters_column
The parameters_column
contains the name of the column that contains the parameters used to replace keywords in the prompt text. This column in the database model is expected to be serialized. The ActiveRecordAdapter
currently has a kludge bit of code that assumes that the serialization is done with JSON. The value of the parameters_column can be either a String
or a Symbol
.
TODO: fix the kludge so that any serialization can be used.
Other Potential Storage Adapters
There are many possibilities to example this plugin concept of the storage adapter. Here are some for consideration:
- RedisAdapter - Not sure; isn't redis more temporary oriented?
- ApiAdapter - use some end-point to CRUD a prompt
Development
Looking for feedback and contributors to enhance the capability of prompt_manager.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/MadBomber/prompt_manager.
License
The gem is available as open source under the terms of the MIT License.