Designing an OpenAI powered IRC Chat Bot for Fun and Profit
As seen in 2600 The Hacker Quarterly, Autumn 2023!!
A Crash Course in LLM AI
So, for a long time people have thought about what happens when computers become sentient, what defines sentience, and being self aware. People have fantasized about this, writing books and making movies about AI takeovers since a time when computers were only in their infancy, which surprises even me. While this will be a more specific intro to ChatGPT’s type of AI, which is in layman’s terms, a bunch of numerical floating point weights, that to some extent mimics neuroplasticity in the way that they reinforce patterns made by the algorithm and make sure those are used more often, attached to an algorithm that, using it’s initial training, in this case lots, and lots…. AND LOTS, of human language, designed to statistically generate a response that is the most probable considering which pieces of a sentence, seen to the algorithm as being broken up into small pieces of words (tokens) that are generally used with which generalized strings of text that the user entered. So the algorithm is designed to finish the text by using the tokens to pull from the initial training that are statistically found together, to “finish” what was written by the user, by deciding probabilistically bit, by bit, what should come next, in turn adding information from it’s model’s training back in. If you would like to read more about how ChatGPT specifically works, there is a decent article explaining it here.
So, okay, the LLM is basically mapping a user’s input to a probable output. Now in my opinion, this is hardly intelligence. But it provides the illusion of intelligence, and is in my experience just good enough to where for an unwitting user, it may even be Turing complete. ChatGPT actually, instead if learning, completely makes up facts just because they seem probable, rather than that they are actually true on many occasions. Though talking about this seems to be frowned upon by the designers of ChatGPT. But again, by my definition of intelligence, this hardly pushes the envelope, and thus even opens the creators to an ethical issue, considering they are pushing this as intelligence… When that is hardly the case at all. It is a talking probability engine. But for my purposes, it happens to work almost perfectly.
An IRC Bot
I decided one day I was determined to make an IRC bot, superior to the Markov bots we usually see… Something useful, and entertaining enough for people to play with. Enter Franklin. Now there have actually been two major versions of what is known as Franklin, the initial being written in bash shell, had many security implications and was pretty quickly scrapped and rewritten from the ground up to mesh with the IRC client Irssi, as a plugin, written in Perl.
Perl was one of the first languages I learned out of the gates, right after QBASIC, and around the same time I was learning C, so I’ve been around the block a couple times with it and felt confident I could get this done. I first went to choose a model, and researched my options. OpenAI had been making headlines recently, so I headed there, and came across the showcase ChatGPT, which wasn’t exactly what I had in mind, and they didn’t offer an API hook publicly for that model iteration quite yet anyway, so I settled on text-davinci-003, and it seems to have worked well for my purposes, after a little tuning. The main program waits for a message to be received in channel, then hands that off to a subroutine that picks apart the user’s request, sees if Franklin was called specifically, or if a random Franklin message should be called instead. Once it handles finding the user’s message, it hands this off to the subroutine that sets up what I refer to as the contextual prelude, including calling on a second routine that will resolve and strip URLs from HTML to plain text, sets up the request JSON, calls the OpenAI API, and handles returning the message text-davinci-003 generated back to the user via another Irssi hook. Most user definable variables are coded in to be able to be set via Irssi’s /set command, and then pulled into Franklin via Irssi’s memory.
The main called routine looks like:
Then the part of the routine that calls the API and parses the response is:
Running the bot is simple, you can start Irssi, configure the bot using
/franklin_* variables, and set up it’s data directory, then use scriptassist to auto-run the bot on Irssi startup. After much debugging Franklin is mostly stable, however, in the event that the code stalls, you can reload the bot by either reloading the script manually, or you can use a trigger.pl configuration from the setup documentation to be able to reload the bot remotely over IRC.
One of the first features I implemented was a primitive hard coded awareness that Franklin itself is a bot, and some variables about the environment it resides in, such as servers connected to, channels, date, time, if it is an op in any channels. I call this the contextual prelude, which lets Franklin’s response be more direct and relational to where it is at the time. Franklin also has a memory of the last couple lines of the chat, in a rolling array where user’s latest comments are shifted in then popped back out 7 or 8 comments later, which is in turn prepared into a string which is tacked onto the contextual prelude. This gives Franklin a “context”, and allows it to know what the general discussion topic currently is in each channel it is connected to. This helps Franklin’s responses seem more relatable, and also helps improve accuracy.
Our context setup looks like:
It was also pertinent that Franklin have a connection to the internet, and the ability to resolve any URLs that he is asked about, and has the ability to summarize the text from the link’s given website, after stripping off extraneous HTML, and then adds this as well to the contextual prelude. Otherwise Franklin would just guess what the website is about based on the context of the question, and the text that makes up the link alone, and this is obviously not adequate.
Which calls an HTML stripping routine:
At a user’s request, a TXID was implemented so that any text that runs out of IRC bounds is still readable, because Franklin generates a webpage per query that contains the question asked, as well as the bot’s response, as well as some other information about the query itself, such as how many tokens were used in processing it. This turned out to be a great addition, and while it was originally implemented as a link to the page, this turned out to be problematic, mostly because it looked like advertising, in the way that Franklin repeatedly would drop links to it’s own website while it was being used. This was inadvertent and mitigated by using the TXID, and the accompanying search box on Franklin’s website. You can also review all Franklin’s previous responses to queries. Franklin records in both .txt and .html formats.
I also wrote in a thread that runs continuously, pinging a URL every couple seconds, so that if Franklin stalls or the script dies, it will alert me via Email, as well as aggregate downtime.
This is the keepalive routine:
Two more abilities that Franklin has that go hand in hand, are the bot’s ability to keep track of the chat’s topic and respond with relevant information autonomously without directly being called by a user; and Franklin’s ability to gauge how much of a jerk a user is being, and if the bot has at minimum half operator status in the channel, it can kick a misbehaving user with a custom message.
To keep track of the channel context, we take this, and and add it to the contextual prelude, basically:
The entire franklin.pl source at it’s most current version can be found on GitHub at: https://github.com/oxagast/Franklin.
Running the bot itself has turned out to be a task. I get pings and even text messages in the middle of the night sometimes regarding either questions or issues with the bot because it has turned out to be one of my most popular solo projects. When I first started writing the bot I had no idea how novel, and downright entertaining the interactions with it would be. I have overall had minimal issues, and one ethical concern of using the user’s backlog data to better response content, but it was decided that since chat not directed at Franklin is only in memory and not recorded to the drive, the risk is acceptable.
Quite frankly, I’ve had fun, am thrilled to have made something people actually find useful; also I appreciate as well as thank everyone who has asked for features, or found bugs in the project. Finally, if you would like to give it a whirl, join Franklin and I on irc.2600.net, in the #2600 channel, or our test channel, #gpt3!
If you enjoy my work, sponsor or hire me! I work hard keeping oxasploits running!
Thank you so much and happy hacking!