Compare commits

..

No commits in common. "0b8391a7e0fe5bcc5ea6a0af2ad5cbd3341d4838" and "902076cd286d53b61ffab7ef6bbbbfecfe2cfe80" have entirely different histories.

4 changed files with 33 additions and 165 deletions

View file

@ -34,4 +34,3 @@ ALLOWED_CHAT=
SAFE_WORD=
# When this character/string is detected anywhere in a message, the bot won't respond to it. Defaults to "\".

View file

@ -1,7 +1,7 @@
import { TailchatWsClient } from "tailchat-client-sdk";
import { TailchatWsClient, stripMentionTag } from "tailchat-client-sdk";
import { OpenAI } from "openai";
import * as fs from "fs";
import { GuildData, ImageRequestData, ImageSize } from "./types";
import { ImageRequestData, ImageSize, Messages } from "./types";
import {
checkFile,
getUsername,
@ -20,6 +20,7 @@ import {
createImageModel,
temperature,
key,
system,
} from "./assistant";
import { ImagesResponse } from "openai/resources";
import chalk from "chalk";
@ -27,9 +28,9 @@ import dotenv from "dotenv";
dotenv.config();
// Specific to Tailchat. The endpoint of my Tailchat server, the bot ID and Secret.
export const HOST = process.env.HOST;
export const APPID = process.env.ID;
export const APPSECRET = process.env.SECRET;
const HOST = process.env.HOST;
const APPID = process.env.ID;
const APPSECRET = process.env.SECRET;
const allVarsFilled = HOST && APPID && APPSECRET;
if (!allVarsFilled) {
@ -38,13 +39,8 @@ if (!allVarsFilled) {
}
// Define the initial system message for the LLM.
const session = new GuildData(checkFile("./messages.json", "utf-8"));
session.data.toString()
? console.log("Our conversation is:", session.data)
: console.log(
"Looks like we're starting fresh, no previous chat history was found.",
);
const session: Messages = checkFile("./messages.json", "utf-8", system.normal);
console.log("Our conversation is:", session);
const THINKING = "[md]`Thinking...`[/md]";
@ -121,13 +117,10 @@ client.connect().then(async () => {
content: "[md]`Analyzing image...`[/md]",
});
session.appendMessage(
formatImageMessage(username, imageData),
message.converseId,
);
session.push(formatImageMessage(username, imageData));
const response = await assistant.chat.completions.create({
messages: session.getHistory(message.converseId),
messages: session,
model: imageModel,
temperature: temperature,
});
@ -136,7 +129,7 @@ client.connect().then(async () => {
"",
);
session.appendMessage(messageOf(response), message.converseId);
session.push(messageOf(response));
await client.sendMessage({
converseId: message.converseId,
@ -145,11 +138,7 @@ client.connect().then(async () => {
content: `[md]${contentOf(response)}[/md]`,
});
fs.writeFileSync(
"./messages.json",
JSON.stringify(session.data),
"utf8",
);
fs.writeFileSync("./messages.json", JSON.stringify(session), "utf8");
console.log("Now our conversation is", session);
} else {
const username = await getUsername(HOST, message.author!);
@ -160,18 +149,15 @@ client.connect().then(async () => {
content: THINKING,
});
session.appendMessage(
formatUserMessage(username, message.content),
message.converseId,
);
session.push(formatUserMessage(username, message.content));
const response = await assistant.chat.completions.create({
messages: session.getHistory(message.converseId),
messages: session,
model: textModel,
temperature: temperature,
});
session.appendMessage(messageOf(response), message.converseId);
session.push(messageOf(response));
await client.sendMessage({
converseId: message.converseId,
@ -180,11 +166,7 @@ client.connect().then(async () => {
content: `[md]${contentOf(response)}[/md]`,
});
fs.writeFileSync(
"./messages.json",
JSON.stringify(session.data),
"utf8",
);
fs.writeFileSync("./messages.json", JSON.stringify(session), "utf8");
}
} catch (err) {
console.log("Failed", err);
@ -205,29 +187,22 @@ client.connect().then(async () => {
content: THINKING,
});
session.appendMessage(
formatUserMessage(username, message.content),
message.converseId,
);
session.push(formatUserMessage(username, message.content));
const response = await assistant.chat.completions.create({
messages: session.getHistory(message.converseId),
messages: session,
model: textModel,
temperature: temperature,
});
session.appendMessage(messageOf(response), message.converseId);
session.push(messageOf(response));
await client.sendMessage({
converseId: message.converseId,
content: `[md]${contentOf(response)}[/md]`,
});
fs.writeFileSync(
"./messages.json",
JSON.stringify(session.data),
"utf8",
);
fs.writeFileSync("./messages.json", JSON.stringify(session), "utf8");
} catch (err) {
console.log("Failed", err);

View file

@ -5,10 +5,6 @@ import {
ChatCompletionSystemMessageParam,
} from "openai/resources";
import { TailchatWsClient } from "tailchat-client-sdk";
import { ChatMessage } from "tailchat-types";
import { formatNewHistory, formatUserMessage, getUsername } from "./utils";
import { HOST } from "./bot";
import chalk from "chalk";
export interface ImageMessage {
role: "user";
@ -31,8 +27,6 @@ export type AnyChatCompletion =
| ChatCompletionUserMessageParam
| ChatCompletionSystemMessageParam;
export type AnyChatCompletionRole = "user" | "system" | "assistant";
export enum ImageSize {
Small = "256x256",
Medium = "512x512",
@ -88,45 +82,4 @@ export type Temperature =
| 1.9
| 2.0;
export type Messages = (AnyChatCompletion | ImageMessage)[];
export interface ChatHistoryData {
id: string;
history: Messages;
}
export type ChatHistory = ChatHistoryData[];
export class GuildData {
data: ChatHistory;
constructor(existingData?: ChatHistory) {
this.data = existingData || [];
}
appendMessage(
message: AnyChatCompletion | ImageMessage,
converseId: string,
): void {
for (const converse of this.data) {
if (converseId === converse.id) {
converse.history.push(message);
return;
}
}
this.data.push(formatNewHistory(message, converseId));
}
getHistory(converseId: string): Messages {
for (const converse of this.data) {
if (converseId === converse.id) {
return converse.history;
}
}
throw new Error(
`No history was found with the given converse id: ${chalk.green(converseId)}. Something isn't right.`,
);
}
}
export type Messages = Array<AnyChatCompletion | ImageMessage>;

View file

@ -1,70 +1,28 @@
import * as fs from "fs";
import {
AnyChatCompletion,
AnyChatCompletionRole,
ChatHistory,
ChatHistoryData,
ImageMessage,
} from "./types";
import { system } from "./assistant";
import { AnyChatCompletion, ImageMessage, Messages } from "./types";
import { ChatCompletion, ChatCompletionMessage } from "openai/resources";
import { stripMentionTag } from "tailchat-client-sdk";
import { ChatMessage } from "tailchat-types";
import { HOST } from "./bot";
import chalk from "chalk";
//export function checkFile(
// file: string,
// encoding: fs.EncodingOption,
// defaultContent: string,
//): Messages {
// let final: Messages;
// const generic: Messages = [
// {
// role: "system",
// content: defaultContent,
// },
// ];
//
// if (fs.existsSync(file)) {
// const data = fs.readFileSync(file, encoding);
//
// final = !data.toString().trim() ? generic : JSON.parse(data.toString());
// } else {
// fs.createWriteStream(file);
// final = generic;
// }
//
// return final;
//}
export function checkFile(
file: string,
encoding: fs.EncodingOption,
): ChatHistory {
let final: ChatHistory;
defaultContent: string,
): Messages {
let final: Messages;
const generic: Messages = [
{
role: "system",
content: defaultContent,
},
];
if (fs.existsSync(file)) {
const data = fs.readFileSync(file, encoding);
final = !data.toString().trim() ? [] : JSON.parse(data.toString());
try {
// @ts-ignore
if (final.at(0).role) {
console.warn(
chalk.yellow(
"Your persistent storage uses the old data structure for persistent messages. These messages will be moved to a backup file and the existing file will be overwritten.",
),
);
fs.writeFileSync(`${file}.bak`, data);
final = [];
}
} catch {}
final = !data.toString().trim() ? generic : JSON.parse(data.toString());
} else {
fs.createWriteStream(file);
final = [];
final = generic;
}
return final;
@ -101,23 +59,6 @@ export function formatImageMessage(
};
}
export function formatNewHistory(
message: AnyChatCompletion | ImageMessage,
converseId: string,
customSystemMessage?: string,
): ChatHistoryData {
return {
id: converseId,
history: [
{
role: "system",
content: customSystemMessage || system.normal,
},
message,
],
};
}
export function messageOf(response: ChatCompletion): ChatCompletionMessage {
return response.choices.at(0)!.message;
}