fix: make sure queue is always properly managed

This commit is contained in:
Udit Karode 2023-04-09 22:27:33 +05:30
parent bdfb91a604
commit 0fff450e38

122
src/ai.ts
View File

@ -2,7 +2,7 @@ import { done, firstPos, queue } from "./queue.js";
import { transformBingResponse } from "./transformers.js";
import { ChatMessage } from "bing-chat";
import { Context } from "telegraf";
import { bold, fmt } from "telegraf/format";
import { FmtString, bold, fmt } from "telegraf/format";
import { Update } from "typegram";
import { bingChat } from "./config.js";
import pTimeout from "p-timeout";
@ -14,7 +14,6 @@ const chats: Record<
> = {};
export const variants = ["creative", "balanced", "precise"];
const defaultTimeoutMs = 50 * 1000;
const defaultVariant = "Balanced";
@ -22,71 +21,86 @@ export async function ai(
ctx: Context<Update>,
prompt: string,
): Promise<void | Message> {
if (!prompt)
return await ctx.reply(
"No prompt provided! Please read /help for more information.",
);
// set up the chat object in `chats`
const chatId = ctx.chat!.id;
chats[chatId] ||= { index: 1 };
const { pos, turn } = queue();
let message_id: number;
async function edit(msg: string | FmtString) {
await ctx.telegram.editMessageText(chatId, message_id, undefined, msg, {
disable_web_page_preview: true,
});
}
try {
if (!prompt) {
return await ctx.reply(
"No prompt provided! Please read /help for more information.",
);
}
const chatId = ctx.chat!.id;
chats[chatId] ||= { index: 1 };
const { pos, turn } = queue();
// wait for our turn if we are not the first client in the queue
if (pos > firstPos) {
await ctx.reply(fmt`Queued at position: ${bold`${pos}`}`);
await turn;
}
const { message_id } = await ctx.reply(
fmt`${bold`[${chats[chatId].index++}]`} Running prompt...`,
message_id = (
await ctx.reply(
fmt`${bold`[${chats[chatId].index++}]`} Running prompt...`,
)
).message_id;
const bingRes = await pTimeout(
bingChat.sendMessage(
prompt,
Object.assign({}, chats[chatId].res, {
variant: chats[chatId].variant ?? defaultVariant,
}),
),
{
milliseconds: defaultTimeoutMs,
fallback() {
return new Error(
`No response from Bing, waited ${defaultTimeoutMs / 1000} seconds`,
);
},
},
);
let bingRes: ChatMessage;
try {
bingRes = await pTimeout(
bingChat.sendMessage(
prompt,
Object.assign({}, chats[chatId].res, {
variant: chats[chatId].variant ?? defaultVariant,
}),
),
{
milliseconds: defaultTimeoutMs,
message: `No response from Bing, waited ${
defaultTimeoutMs / 1000
} seconds`,
},
);
} catch (e) {
return await ctx.reply((e as Error).message || "Something went wrong");
// set the res to the chat object so the next message
// can continue the same conversation
if (!(bingRes instanceof Error)) {
chats[chatId].res = bingRes;
}
chats[chatId].res = bingRes;
const tgRes = (() => {
if (bingRes.text === prompt) {
// Bing Chat often replies with the exact prompt
// in case it's unable to continue the conversation.
return "Bing replied with the exact text as your prompt. This usually happens when the AI is unable to continue the conversation. Starting a new chat with /newchat is recommended.";
}
if (!bingRes.text) {
return "Received an empty response. Make sure the bot is set up properly and that you haven't crossed the daily message limit.";
}
return transformBingResponse(bingRes);
})();
await ctx.telegram.editMessageText(chatId, message_id, undefined, tgRes, {
disable_web_page_preview: true,
});
await edit(getTgResponse(bingRes, prompt));
} catch (e) {
console.log(e);
await ctx.reply("Something went wrong!");
} finally {
done();
await edit("Something went wrong!");
}
// signal completion, let the next client proceed
done();
}
function getTgResponse(bingRes: ChatMessage | Error, prompt: string) {
if (bingRes instanceof Error) {
return bingRes.message;
}
if (bingRes.text === prompt) {
// Bing Chat often replies with the exact prompt
// in case it's unable to continue the conversation.
return "Bing replied with the exact text as your prompt. This usually happens when the AI is unable to continue the conversation. Starting a new chat with /newchat is recommended.";
}
if (!bingRes.text) {
return "Received an empty response. Make sure the bot is set up properly and that you haven't crossed the daily message limit.";
}
return transformBingResponse(bingRes);
}
export function newChat(chatId: number) {