GPTcord/src/toOpenAIMessages.ts

122 lines
4 KiB
TypeScript
Raw Normal View History

2023-03-14 21:16:54 +01:00
import { ChatCompletionRequestMessage as OpenAIMessage } from "openai";
import { Collection, Message as DiscordMessage, InteractionResponse } from "discord.js";
import FoldToAscii from "fold-to-ascii";
2023-03-14 21:16:54 +01:00
import config from "./config";
import countTokens from "./tokenCounter";
import { RequestMessage } from "./execution";
/**
* formats the request to use as a message contend in OpenAI api
* @param request the request to format
* @returns the formatted request
*/
export async function formatRequestOrResponse(request: RequestMessage | InteractionResponse): Promise<string> {
if (request instanceof DiscordMessage) {
return formatMessage(request);
}
if (request instanceof InteractionResponse) {
return formatMessage(await request.fetch());
}
return formatMessage(await request.fetchReply());
}
2023-03-14 21:16:54 +01:00
/**
* Formats the message to use as a message content in OpenAI api
* @param message the message to format
* @returns the formatted message
*/
export function formatMessage(message: DiscordMessage): string {
2023-03-14 21:16:54 +01:00
let rvalue: string = message.cleanContent;
for (const attachment of message.attachments) {
rvalue += ` [Attachment: ${attachment[1].name}`;
rvalue += attachment[1].description ? ` - ${attachment[1].description}` : "";
rvalue += "]";
}
for (const embed of message.embeds) {
rvalue += ` [Embed:`;
rvalue += embed.title ? ` ${embed.title}` : "";
rvalue += embed.author ? ` by ${embed.author.name}` : "";
rvalue += (embed.title || embed.author) && embed.description ? " -": "";
2023-03-14 21:16:54 +01:00
rvalue += embed.description ? ` ${embed.description}` : "";
2023-03-18 03:38:29 +01:00
for (const field of embed.fields) {
rvalue += ` [${field.name} - ${field.value}]`;
}
2023-03-14 21:16:54 +01:00
rvalue += "]";
}
for (const sticker of message.stickers.values()) {
rvalue += ` [Sticker:`;
rvalue += sticker.name;
rvalue += sticker.description ? ` - ${sticker.description}` : "";
rvalue += "]";
}
return rvalue.trim();
2023-03-14 21:16:54 +01:00
}
/**
* Formats name to be accepted in OpenAI api
* @param name the name to format
* @returns formatted name
*/
function formatName(name: string): string {
// replace all characters to ascii equivelant
return FoldToAscii.foldReplacing(name)
// White spaces are not allowed
.replace(" ", "_")
// replace characters that are not accepted by api with '_'
.replace(/[^a-zA-Z0-9_-]/g, "_")
// remove trailing '-_' characters
.replace(/^[-_]+|[-_]+$/g, "")
// remove duplicated '-_' character sequences
.replace(/([-_])([-_])+/g, "$1");
}
/**
* Gets the name of the author of the message, formatted to be used in OpenAI api
* @param message the message to get the author name
* @returns the proper author name of the message
*/
function getAuthorUsername(message: DiscordMessage): string | undefined {
if (message.author.id === message.client.user.id ) return undefined;
if (message.member) {
const name = formatName(message.member.displayName);
if (name.length >= 3) return name;
}
const name = formatName(message.author.username);
return name;
}
/**
* Converts the Iterable of Discord Messages to array of OpenAI Messages to send
* first message in the interable will be the last of the returned array (reverse order)
* @param messages the iterable to convert
* @returns the converted messages
*/
export default function toOpenAIMessages(
messages: Iterable<DiscordMessage>,
): OpenAIMessage[] {
2023-03-14 21:16:54 +01:00
const rvalue: OpenAIMessage[] = [];
let tokenCount = 0;
2023-03-14 21:16:54 +01:00
for (const message of messages) {
const content = formatMessage(message);
// FIXME: tokens are not being counted properly (it's lower than it is) but it's enough for me for now.
tokenCount += countTokens(content);
if (tokenCount > config.limits.tokens) break;
2023-03-14 21:16:54 +01:00
rvalue.push({
role: message.author.id === message.client.user.id ? "assistant" : "user",
content: content,
name: getAuthorUsername(message),
2023-03-14 21:16:54 +01:00
});
}
rvalue.push(...config.systemPrompt().reverse());
2023-03-14 21:16:54 +01:00
return rvalue.reverse();
2023-03-14 21:16:54 +01:00
}