0.0
No commit activity in last 3 years
No release in over 3 years
Ruby generative grammer for conversational text
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

>= 0

Runtime

 Project Readme

Confabulator

A recursive syntax for the procedural generation of random sentences in Ruby.

Why do I care?

Perhaps you want to generate emails, text messages, or webpages that are all readable, but have different wordings. Perhaps you're writing a game and want to vary character dialog. Perhaps you're writing a testing language and need a concise way to express linguistic possibilities. Perhaps you don't need a reason.

Install

gem install confabulator

Use

require 'confabulator'

Choice blocks

Choice blocks let the parser make a random choice.

> 5.times { puts Confabulator::Parser.new("{Choice one|Choice two} and stuff").confabulate }
Choice two and stuff
Choice one and stuff
Choice two and stuff
...

Choices inside of choices (ad infinitum) are fine:

> 5.times { puts Confabulator::Parser.new("This is {an example|a {good|great|mediocre} demonstration}").confabulate }
This is a great demonstration
This is a mediocre demonstration
This is an example
This is a good demonstration
This is an example
This is an example
This is a good demonstration
...

You can differentially weight the options: {5:This is 5 times more likely|than this}

Substitutions

Substitutions let you re-use common templates.

> knowledge = Confabulator::Knowledge.new
> knowledge.add "friend", "{friend|world|there}" # a hash is also acceptable
> Confabulator::Parser.new("Hello, [friend]!", :knowledge => knowledge).confabulate
=> "Hello, there!"
> Confabulator::Parser.new("Hello, [friend]!", :knowledge => knowledge).confabulate
=> "Hello, world!"
...

Equivalently, as a helper on the Knowledge object:

> knowledge.confabulate("Hello, [friend]!")
=> "Hello, there!"

You can ask a substitution to be capitalized:

> knowledge.confabulate("Hello, [friend:c]!")
=> "Hello, World!"

Or pluralized:

> knowledge.add "dude" => "friend"
> knowledge.confabulate("Hello, [dude:p]!")
=> "Hello, friends!"

Substitutions can contain other substitutions inside of choice nodes inside of other substitutions, etc., ad infinitum. Just try to avoid infinite loops!

Escaping

You must escape the special characters {, [, `, and | with backslashes:

> knowledge.add "dude" => "friend"
> knowledge.confabulate("Hello, \\{friend\\|something\\} \\`\\`stuff\\`\\` \\[dude:p]!")
=> "Hello, {friend|something}  ``stuff`` [dude:p]!!"

Protected regions

Sometimes you want to insert user generated content without having to escape every {, [, `, and |. For this you use protected regions.

> knowledge.add "dude" => "friend"
> user_content = "protect regions [and stuff] with double backticks (`)!"
> knowledge.confabulate("Hello, ``#{user_content}``")
=> "Hello, protect regions [and stuff] with double backticks (`)!"

At the moment, sequences of more than one backtick are never allowed inside of a protected region.

Enumerating possible confabulations

You can output an array of all possible confabulations using all_confabulations, like so:

> Confabulator::Parser.new("{Hello|Hi} {world|there}").all_confabulations
=> [
     "Hello world", 
     "Hello there", 
     "Hi world", 
     "Hi there"
   ]

Internally, this calls tree, which outputs a simplified confabulation parse tree.

Next Steps

Here are some things that could be added to this library:

  • Depth limits / recursion detection
  • Learning through back propagation of a reward signal and optimization of the choice nodes to make the rewarded or penalized outcome more or less likely.
  • Whatever you want!

Helping out

Fork, write specs, add a feature, write documentation, send me a pull request!