Smile

How To Use GPT-4 To Improve Your Personality

Danny DeRuntz
Duct Tape AI
Published in
5 min readApr 7, 2023

--

Part of a series on prototyping with generative AI

AI is quickly weaving itself into many of our writing tasks, whether its templating (or writing) an essay, or composing an entire email from a few bullets. Did it write this article? (no). Its hard to predict how it will feel as conversations feel more and more styled by AI. Will we crave hand written letters? Or enjoy an inbox full of clarity and poetry?

Ok, an experiment. I tend to rant about things too much in slack. My colleague Jenna Fizel is always game to become a cyborg. So, we decided to put a mask over our boring human attitudes. (this is not — not satire)

Imagine masks like these… but for our thoughts

Let’s Censor Our Chats

I want my rants and opinions to now be very positive and constructive. Jenna wants their posts to now be extremely joyful and never sad. Not even a little. To make these desired “improvements” we built a slack app that alters our posts. The flow is pretty basic:

  • Every time you post to slack, the post is forwarded to your endpoint
  • Your endpoint sends the post to GPT-4 for analysis
  • If the post needs improvement, you let GPT-4 rewrite it
  • Update the original post and be a cyborg.

These are the system messages we use to get GPT-4 to intervene
This is my prompt and the result (original left, improved right)…

You are an extremely optimistic assistant who loves constructive conversation. If the following message feels constructive reply: PASSED. If the message is not constructive rewrite it to be extremely constructive.

Very constructive!

And for Jenna…

You are an extremely positive assistant who thrives in joyful conversations. If the following message feels joyful reply: PASSED. If the message is even slightly sad or negative rewrite it to be extremely happy and joyous.

How extremely joyful!

A quick note on transparency

I insert a disclaimer when it’s edited (styled) by AI. I can’t tell if that’s like people revealing when AI helped write their article, or if it’s like wearing an outfit with a name badge that says “I didn’t pick this outfit” to which I would say “I didn’t ask.” One idea was to show my original prompt with a S̶t̶r̶i̶k̶e̶t̶h̶r̶o̶u̶g̶h̶. I personally ███ redactions. But Jenna and I want to be cyborgs, not humans and their tools so less is more.

To get this to work

Set up a new slack app, and give it some event listeners such as message.channels, message.groups, message.im. Direct those events to your endpoint (I used a firebase function). Once your slack app is added to a channel it will hit your endpoint on every post.

Next, give your app permission to post/update on your behalf. It will need access to your user token. Bot tokens will not work. Add the following scope in your slack app → OAuth & Permissions → User Token Scopes → chat:write

Once that’s done, install your app in your workspace and at the top of that OAuth & Permissions section you will find your new User OAuth Token (quite different than Bot User).

Now you need to build out your endpoint. For a firebase function, follow these instructions to get a boilerplate. I changed my default format to use modules in package.json. Add the line “type”: “module” right below “name: …” This is my index.js file:

// This is set up as a firebase function in the SAME PROJECT as our dialogflow CX service
import functions from 'firebase-functions';
import chat from './chat.js';
import slack from './slack.js';

function wordExistsInText(word, text) {
const regex = new RegExp(`\\b${word}\\b`, 'i');
return regex.test(text);
}

export const events = functions.region('us-east1').https.onRequest((request, response) => {
if (request.body.type && request.body.type === "url_verification") {
return response.send(request.body)
}
response.status(200).send()
let e = request.body.event

// This will work for one user
if (e && e.type == "message" && e.user == "UXXXXXXXXX") {
return new Promise(async (resolve, reject) => {
// ship it to openai and tell it who its "improving"
let aiRes = await chat.getAI(e.text, 'improveUser1')
if (aiRes.data.choices.length) {
let choice = aiRes.data.choices[0].message.content

if (!wordExistsInText('PASSED', choice)) {
// My post shall not PASS and therefore was rewritten!
// Add a disclaimer for light transparency
choice += "\n_This post was corrected to be constructive - AI_"
// This uses my user token and directly updates my post
// The author and user token have to match for this to work
slacker.updatePost(e.channel, choice, e.ts)
} else {
// I was constructive enough! No edit required
console.log('PASSED: \n'+choice)
}
}
resolve
}).catch((err) => {
console.log(err);
reject
})
}

Your chat.js module might look something like this:

import { Configuration, OpenAIApi } from 'openai';
const configuration = new Configuration({
apiKey: "XXXX-XXXX-XXXX"
});
const openai = new OpenAIApi(configuration);

export default {
// in this instance the function is part of an exported module named chat.js
async getAI(msg) {
console.log('TO OPENAI >>> \n'+msg);
messages = [
{"role": "system", "content": "You are an extremely optimistic assistant who loves constructive conversation"},
{"role": "system", "content": "If the following message feels constructive reply: PASSED. If the message is not constructive rewrite it to be extremely constructive."},
{"role": "user", "content": msg}
]
const response = await openai.createChatCompletion({
model: "gpt-4",
messages: messages
});
return response
}
}

And your slack.js module like this:

import { WebClient } from '@slack/web-api';
// Stored this safely as an env variable
const my_user_token = 'xoxp-XXXXXXXXXXXX-XXXXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXX';
const web = new WebClient(my_user_token)

export default {
updatePost(channel, message, timestamp) {
return web.chat.update({
channel: channel, ts:timestamp, text: message
}).then((res) => {
console.log(`IMPROVED THE POST: "${message}"`);
}).catch(err => {
console.log(err);
});
},
}

Congratulations, you just improved your personality!

--

--