tech-envision commited on
Commit
e393049
·
1 Parent(s): 1085a21

Add Discord bot for LLM chat

Browse files
Files changed (4) hide show
  1. bot/__init__.py +5 -0
  2. bot/config.py +13 -0
  3. bot/discord_bot.py +60 -0
  4. requirements.txt +1 -0
bot/__init__.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ """Discord bot for chatting with the LLM."""
2
+
3
+ from .discord_bot import LLMDiscordBot
4
+
5
+ __all__ = ["LLMDiscordBot"]
bot/config.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Configuration for the Discord bot."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ from typing import Final
7
+
8
+ # Discord bot token
9
+ DISCORD_TOKEN: Final[str | None] = os.getenv("DISCORD_TOKEN")
10
+
11
+ # Default values for chat sessions
12
+ DEFAULT_USER_PREFIX: Final[str] = "discord_"
13
+ DEFAULT_SESSION: Final[str] = "discord"
bot/discord_bot.py ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Implementation of a Discord bot that uses the LLM backend."""
2
+
3
+ from __future__ import annotations
4
+
5
+
6
+ import discord
7
+ from discord.ext import commands
8
+
9
+ from src.chat import ChatSession
10
+ from src.log import get_logger
11
+
12
+ from .config import DEFAULT_SESSION, DEFAULT_USER_PREFIX, DISCORD_TOKEN
13
+
14
+ __all__ = ["LLMDiscordBot", "run_bot"]
15
+
16
+
17
+ class LLMDiscordBot(commands.Bot):
18
+ """Discord bot that interfaces with :class:`ChatSession`."""
19
+
20
+ def __init__(self, *, intents: discord.Intents | None = None) -> None:
21
+ intents = intents or discord.Intents.default()
22
+ intents.message_content = True
23
+ super().__init__(command_prefix=None, intents=intents)
24
+ self._log = get_logger(self.__class__.__name__)
25
+
26
+ async def on_ready(self) -> None: # noqa: D401
27
+ self._log.info("Logged in as %s (%s)", self.user, self.user.id)
28
+
29
+ async def on_message(self, message: discord.Message) -> None: # noqa: D401
30
+ if message.author.bot or not message.content.strip():
31
+ return
32
+
33
+ user_id = f"{DEFAULT_USER_PREFIX}{message.author.id}"
34
+ session_id = f"{DEFAULT_SESSION}_{message.channel.id}"
35
+
36
+ self._log.debug("Received message from %s: %s", user_id, message.content)
37
+
38
+ async with ChatSession(user=user_id, session=session_id) as chat:
39
+ try:
40
+ reply = await chat.chat(message.content)
41
+ except Exception:
42
+ self._log.exception("Failed to generate reply")
43
+ return
44
+
45
+ if reply:
46
+ await message.channel.send(reply)
47
+
48
+
49
+ def run_bot(token: str | None = None) -> None:
50
+ """Run the Discord bot using the provided token."""
51
+ token = token or DISCORD_TOKEN
52
+ if not token:
53
+ raise RuntimeError("Discord token not provided")
54
+
55
+ bot = LLMDiscordBot()
56
+ bot.run(token)
57
+
58
+
59
+ if __name__ == "__main__": # pragma: no cover - manual start
60
+ run_bot()
requirements.txt CHANGED
@@ -1,3 +1,4 @@
1
  colorlog
2
  ollama
3
  peewee
 
 
1
  colorlog
2
  ollama
3
  peewee
4
+ discord.py