Skip to content

Commit

Permalink
feat: random using code instead of depend on openai
Browse files Browse the repository at this point in the history
  • Loading branch information
dyaskur committed Nov 10, 2024
1 parent 16592c0 commit 98d272d
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 33 deletions.
74 changes: 49 additions & 25 deletions helpers/gpt.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,49 +3,73 @@ import Redis from 'ioredis';
import crypto from 'crypto';

/**
* @param {string} something - thing that will get a random of it
* @param {string} lastAnswers - last answers to generate new thing
* @returns {string} the prompt for gpt
* Get random list from GPT based on user input context.
*
* @param {string} something - user input context
*
* @returns {object|null} - object with keys: context, expectedCount, items
*
* @example
* getRandomFromGpt('animals')
* // => {context: 'animals', expectedCount: 100, items: ["pig", "panda", "monkey", ...]}
*
* @example
* getRandomFromGpt('give me 3 random big animals')
* // => {context: "big animals", expectedCount: 3, items: ["pig", "panda", "monkey"]}
*
* @example
* getRandomFromGpt('give me random number between 5 and 10')
* // => {context: "random_number", expectedCount: 1, items: ["5-10"]}
*/
function getSomethingToAsk(something, lastAnswers) {
if (lastAnswers) {
return `${something} (last answer: ${lastAnswers})`;
}
return `${something}`;
}

// eslint-disable-next-line require-jsdoc
export async function getRandomFromGpt(something) {
const somethingMd5 = crypto.createHash('md5').update(something).digest('hex');
const client = new Redis(process.env.REDIS_URL);
const lastAnswers = await client.get(somethingMd5);

Check failure on line 27 in helpers/gpt.js

View workflow job for this annotation

GitHub Actions / build (22.x)

'lastAnswers' is assigned a value but never used

Check failure on line 27 in helpers/gpt.js

View workflow job for this annotation

GitHub Actions / build (20.x)

'lastAnswers' is assigned a value but never used
const openai = new OpenAI({
apiKey: process.env?.OPENAI_API_KEY,
});
console.log('lastAnswers', lastAnswers);

const command = 'Generate a list based on user input context.' +
'if user says animals, you list 100 animals. ' +
'if user give list to random just give me back the list without addition' +
'if user ask random number, just give me the range' +
'Even if a number is requested, always output 100 items.' +
'Format: first item as the input context, second item as the requested number. ' +
'e.g "give me 2 random big animals", answer: big animals;;2;;pig;;panda;;monkey;;aardvark;;...' +
'e.g "give me random number between 5 and 10", answer: random_number;;1;;5-10' +
'Respond directly, no extra phrases or numbering.';
const completion = await openai.chat.completions.create({
model: 'gpt-4o-mini',
messages: [
{
role: 'system', content: 'You are a system that generate randomly thing from user input. ' +
'If user dont ask how many thing to generate, just give 1 result' +
'don\'t use common answer.' +
'if user says animals, you list 1000 animals from the database and pick at random,' +
'to the point, no say \'sure\'' +
'',
role: 'system',
content: command,
},
{role: 'user', content: getSomethingToAsk(something, lastAnswers)},
{role: 'user', content: something},
],
temperature: 1,
max_tokens: 75,
frequency_penalty: 0.1,
max_completion_tokens: 300,
});

let answer = 'Sorry I don\'t know what you mean';

if (completion?.choices.length > 0) {
answer = completion.choices.map((a) => a.message.content.replace(/(\r\n|\n|\r)/gm, '')).join('\n');
const completionAnswer = completion.choices.map((a) => a.message.content.replace(/(\r\n|\n|\r)/gm, '')).join('\n');
console.log(completionAnswer);
const options = completionAnswer.replace(/(;;;|;;&)+/g, ';;').split(';;');
if (options.length < 3) {
return null;
}
const context = options[0];
const expectedCount = parseInt(options[1]);
const items = options.slice(2);
return {
context,
expectedCount,
items,
};
}
await client.set(somethingMd5, lastAnswers ? lastAnswers + ', ' + answer : answer);
return answer;
// await client.set(somethingMd5, lastAnswers ? lastAnswers + ', ' + answer : answer);
return null;
}


26 changes: 26 additions & 0 deletions helpers/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,29 @@ export function extractConfig(argumentText, messages) {
const extractedTextCommands = extractMessageAndConfig(argumentText);
return extractedTextCommands.filter((val) => !messages.includes(val));
}

/**
* Randomly shuffles an array in place using the Fisher-Yates algorithm.
*
* @param {array} array - The array to be shuffled.
* @returns {array} - The shuffled array.
*/
export function shuffle(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}


/**
* helper function to generate random numbers
*
* @param {number} start - the start of the range
* @param {number} end - the end of the range
* @returns {number[]} - an array of random numbers
*/
export function generateRandomNumbers(start, end) {
return Array.from({length: end - start + 1}, (_, i) => i + start);
}
34 changes: 26 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
helpCommandHandler,
updateWinnerCardHandler,
} from './handlers.js';
import {extractConfig, extractMessageByDoubleQuote} from './helpers/utils.js';
import {extractConfig, extractMessageByDoubleQuote, generateRandomNumbers, shuffle} from './helpers/utils.js';
import {buildInputForm} from './helpers/components.js';
import {getRandomFromGpt} from './helpers/gpt.js';

Expand Down Expand Up @@ -84,13 +84,31 @@ export async function app(req, res) {
await createMessageFromNameListHandler(extractedText, event.space.name, event.threadKey, winnerCount);
} else {
const answer = await getRandomFromGpt(argumentText ?? 'whatever');
reply = {
thread: event.message.thread,
actionResponse: {
type: 'NEW_MESSAGE',
},
text: answer,
};
// console.log(answer);
if (answer) {
let {context, expectedCount, items} = answer;
if (context === 'random_number') {
const range = items[0].split('-');
items = generateRandomNumbers(parseInt(range[0]), parseInt(range[1]));
}
let take = expectedCount * 3 > items.length ? items.length : expectedCount * 3;
if (take > 20) {
take = 20;
}
console.log('context', context, 'expectedCount', expectedCount, 'items', items);
items = shuffle(items).slice().slice(0, take);
if (expectedCount === 100 || expectedCount > items.length) {
expectedCount = 1;
}
await createMessageFromNameListHandler(items, event.space.name, event.threadKey, expectedCount);
reply = {
thread: event.message.thread,
actionResponse: {
type: 'NEW_MESSAGE',
},
text: answer,
};
}
}
}
} else if (event.type === 'CARD_CLICKED') {
Expand Down

0 comments on commit 98d272d

Please sign in to comment.