| .gitignore | Initial commit | |
| LICENSE | Added a license to the project. Nothing more, nothing less. | |
| ponder.lua | so i started to work on a simple ELIZA implementation that is not quite as cringey as the original. the goal would be to have a relatively simple chat that mirrors what I'm saying in order to spur being able to express things. | |
| README.md | so i started to work on a simple ELIZA implementation that is not quite as cringey as the original. the goal would be to have a relatively simple chat that mirrors what I'm saying in order to spur being able to express things. | |
ponder.lua
small utility that helps pondering
I do some journaling every day and sometimes I reflect on things. nano is my go-to editor for linear writing. Every now and then I find myself doing the same reflective exercises, like asking "What? So What? Now What?" 1 , and in other moments I just wish to save an ELIZA 2 discussion as a plaintext file.
So let's try to do this as a little utility! And, besides, I also want to learn Lua and this seems like a good oportunity.
-- the reflection needs to be saved somewhere
<<save>>
-- question helper function
<<question>>
-- questions for every type of reflection
<<header>>
-- let's start with a simple exercise
<<what>>
-- an attempt to implement a simple ELIZA
<<eliza>>
-- entry point to the script
<<cmd>>
Saving Reflections
This function will write a given reflection to a markdown file with a little bit of frontmatter. That's all there is to it.
function save(topic, tags, reflection)
-- we need a timestamp for our reflection
local timestamp = os.time()
-- and a file to write to
local file = io.open(os.date('%Y-%m-%d', timestamp) .. ' ' .. topic .. '.md', 'w')
file:write('---\n')
file:write('title: "' .. topic .. '"\n')
file:write('timestamp: ' .. timestamp .. '\n')
if tags ~= '' then
file:write('tags:\n')
for tag in string.gmatch(tags, '([^,]+)') do
file:write(' - ' .. tag .. '\n')
end
end
file:write('---\n')
file:write(reflection)
file:close()
print('\nOkay bye!')
end
Question
Small helper function for asking a question and returning question and answer.
function question(q)
-- asking
print('\n~ ' .. q)
io.write('~ ')
-- answering
return io.read()
end
Header
This questions are asked before every reflection. They help me organize the reflections later.
function header()
-- let's use four variables to safe topic and reflections
local topic = question('Topic of your reflection?')
-- I like tags as transversal connectors
local tags = question('Any tags for this reflection?')
return topic, tags
end
What?
This reflection follows the classical What? So What? Now What? pattern. First you describe what you did, in pratical terms. Then you try to explress why that is important or meaningful. And lastly you state how you plan to continue.
function what()
local topic, tags = header()
local reflection = '# ' .. topic
local questions = {'What?', 'So What?', 'Now What?'}
for i = 1, #questions do
local answer = question(questions[i])
reflection = reflection .. '\n\n## ' .. questions[i] .. '\n' .. answer
end
reflection = reflection .. '\n'
-- goodbye
save(topic, tags, reflection)
end
ELIZA
I was wondering if chatting would be a nice way of reflecting. ELIZA seemed to work for some people so I will try to create a simple implementation of that and see where it goes. The idea would be to start with something of concern and have ELIZA bounce back questions that keep cognitive engagement going. After I would just save the entire chat.
function eliza()
local topic, tags = header()
local reflection = '# ' .. topic
local chatting = true
-- exit values
local exits = {'quit', 'goodbye', 'bye'}
local q = ''
local a = ''
-- questions
local welcome_qs = {'What brought you here today?', 'Hi, how are you feeling today?', 'What\'s up?'}
local generic_qs = {}
local want_ts = {'want', 'need', 'long', 'crave'}
local want_qs = {'You mentioned you #1ed #2?', 'Why is it you #1 #2?'}
-- keep on chatting
while chatting do
-- create a local copy with lower characters only; easier to search thing
local _a = a:lower()
-- introduction question
if _a == '' or _a:find('h%allo') or _a:find('hi[ ,.!?]*$') then
q = welcome_qs[math.random(1, #welcome_qs)]
else
q = 'generic question'
end
-- last answer contained one of the want trigger-words
for i = 1, #want_ts do
local trigger = want_ts[i]
if _a:find(trigger) then
local x = _a:match(trigger .. 's? ([^,]*)')
x = x:gsub('[.,!?]', '')
q = string.gsub(want_qs[math.random(1, #want_qs)], '#1', trigger)
q = q:gsub('#2', x)
end
end
a = question(q)
reflection = reflection .. '\n\n## ' .. q .. '\n' .. a
-- check if the answer contained an exit key word
for i = 1, #exits do
if a == exits[i] then
chatting = false
end
end
end
reflection = reflection .. '\n'
-- goodbye
save(topic, tags, reflection)
end
CMD
Let's let ponder know which reflection we want, and I just default to "What?" for now.
-- set default to what
local type = 'what'
-- check what was passed
if arg[1] then
type = arg[1]
end
-- execute the correct reflection
if type == 'what' then
what()
end
if type == 'eliza' then
eliza()
end
Ideas
- Markov Chain?