diff --git a/misskaty/plugins/chatbot_ai.py b/misskaty/plugins/chatbot_ai.py
index 9b7532ba..86ac327c 100644
--- a/misskaty/plugins/chatbot_ai.py
+++ b/misskaty/plugins/chatbot_ai.py
@@ -7,6 +7,7 @@ import html
import json
import random
+from cachetools import TTLCache
from openai import APIConnectionError, APIStatusError, AsyncOpenAI, RateLimitError
from pyrogram import filters, utils
from pyrogram.errors import MessageTooLong
@@ -23,6 +24,57 @@ __HELP__ = """
/ask - Generate text response from AI using OpenAI.
"""
+user_conversations = TTLCache(maxsize=4000, ttl=24*60*60)
+
+async def get_openai_stream_response(messages, bmsg):
+ ai = AsyncOpenAI(api_key=OPENAI_KEY, base_url="https://duckai.yasirapi.eu.org/v1")
+ response = await ai.chat.completions.create(
+ model="gpt-4o-mini",
+ messages=messages,
+ temperature=0.7,
+ stream=True,
+ )
+ answer = ""
+ num = 0
+ try:
+ async for chunk in response:
+ if not chunk.choices or not chunk.choices[0].delta.content:
+ continue
+ num += 1
+ answer += chunk.choices[0].delta.content
+ if num == 30:
+ await bmsg.edit_msg(html.escape(answer))
+ await asyncio.sleep(1.5)
+ num = 0
+ await bmsg.edit_msg(f"{html.escape(answer)}\n\nPowered by: GPT 4o Mini")
+ except MessageTooLong:
+ answerlink = await post_to_telegraph(
+ False, "MissKaty ChatBot ", html.escape(f"{answer}")
+ )
+ await bmsg.edit_msg(
+ strings("answers_too_long").format(answerlink=answerlink),
+ disable_web_page_preview=True,
+ )
+ except APIConnectionError as e:
+ await bmsg.edit_msg(f"The server could not be reached because {e.__cause__}")
+ return None
+ except RateLimitError as e:
+ if "billing details" in str(e):
+ return await bmsg.edit_msg(
+ "This openai key from this bot has expired, please give openai key donation for bot owner."
+ )
+ await bmsg.edit_msg("You're got rate limit, please try again later.")
+ return None
+ except APIStatusError as e:
+ await bmsg.edit_msg(
+ f"Another {e.status_code} status code was received with response {e.response}"
+ )
+ return None
+ except Exception as e:
+ await bmsg.edit_msg(f"ERROR: {e}")
+ return None
+ return answer
+
@app.on_message(filters.command("ai", COMMAND_HANDLER) & pyro_cooldown.wait(10))
@app.on_bot_business_message(
@@ -71,47 +123,15 @@ async def openai_chatbot(self, ctx: Message, strings):
is_in_gap, _ = await check_time_gap(uid)
if is_in_gap and (uid not in SUDO):
return await ctx.reply_msg(strings("dont_spam"), del_in=5)
- ai = AsyncOpenAI(api_key=OPENAI_KEY, base_url="https://duckai.yasirapi.eu.org/v1")
pertanyaan = ctx.input
msg = await ctx.reply_msg(strings("find_answers_str"), quote=True)
- num = 0
- answer = ""
- try:
- response = await ai.chat.completions.create(
- model="gpt-4o-mini",
- messages=[{"role": "user", "content": pertanyaan}],
- temperature=0.7,
- stream=True,
- )
- async for chunk in response:
- if not chunk.choices or not chunk.choices[0].delta.content:
- continue
- num += 1
- answer += chunk.choices[0].delta.content
- if num == 30:
- await msg.edit_msg(html.escape(answer))
- await asyncio.sleep(1.5)
- num = 0
- await msg.edit_msg(f"{html.escape(answer)}\n\nPowered by: GPT 4o Mini")
- except MessageTooLong:
- answerlink = await post_to_telegraph(
- False, "MissKaty ChatBot ", html.escape(f"{answer}")
- )
- await msg.edit_msg(
- strings("answers_too_long").format(answerlink=answerlink),
- disable_web_page_preview=True,
- )
- except APIConnectionError as e:
- await msg.edit_msg(f"The server could not be reached because {e.__cause__}")
- except RateLimitError as e:
- if "billing details" in str(e):
- return await msg.edit_msg(
- "This openai key from this bot has expired, please give openai key donation for bot owner."
- )
- await msg.edit_msg("You're got rate limit, please try again later.")
- except APIStatusError as e:
- await msg.edit_msg(
- f"Another {e.status_code} status code was received with response {e.response}"
- )
- except Exception as e:
- await msg.edit_msg(f"ERROR: {e}")
+ if uid not in user_conversations:
+ user_conversations[uid] = [{"role": "user", "content": pertanyaan}]
+ else:
+ user_conversations[uid].append({"role": "user", "content": pertanyaan})
+ ai_response = await get_openai_stream_response(user_conversations[uid], bmsg)
+ if not ai_response:
+ user_conversations[user_id].pop()
+ if len(user_conversations[user_id]) == 1:
+ user_conversations.pop(user_id)
+ user_conversations[uid].append({"role": "assistant", "content": ai_response})