discord_svr.py
Overview
discord_svr.py is a Python script designed to create a Discord bot that integrates with the RAGFlow Assistant Chat Bot API. The bot listens for messages in Discord channels where it is mentioned, forwards user queries to the RAGFlow API, and returns the bot’s response back to the Discord channel. It can handle both text responses and images encoded in base64 format, which it decodes and sends as attachments to the Discord channel.
This file primarily serves as a bridge between Discord users and an AI-powered chat service, enabling interactive conversations within Discord servers using external AI completion services.
Detailed Explanation
Constants and Configuration
URL (
str):
The endpoint URL of the RAGFlow Assistant Chat Bot API. This should be replaced with the actual IP address and port of the deployment or use the provided demo URL.JSON_DATA (
dict):
Template JSON payload sent to the RAGFlow API. Contains:conversation_id(str): Unique conversation identifier obtained from the RAGFlow /api/new_conversation endpoint.Authorization(str): API key for authorization with the RAGFlow Assistant Chat Bot.word(str): The user's question, populated dynamically upon message reception.
DISCORD_BOT_KEY (
str):
The Discord bot token obtained from the Discord Developer Portal, used to authenticate the bot.
Imports
logging: For logging bot activity (currently used for startup info).discord: Discord.py library for interacting with the Discord API.requests: To make HTTP POST requests to the RAGFlow API.base64: To decode base64-encoded images returned from the API.asyncio: To run the asynchronous Discord client event loop.
Discord Client Setup
intents = discord.Intents.default()
intents.message_content = True
client = discord.Client(intents=intents)
The bot requests default intents and enables
message_contentintent, which is required to read message contents in Discord channels.Creates a Discord client instance with these intents.
Event Handlers
on_ready()
@client.event
async def on_ready():
logging.info(f'We have logged in as {client.user}')
Triggered when the bot successfully connects to Discord.
Logs the bot’s username to indicate readiness.
on_message(message)
@client.event
async def on_message(message):
if message.author == client.user:
return
if client.user.mentioned_in(message):
if len(message.content.split('> ')) == 1:
await message.channel.send("Hi~ How can I help you? ")
else:
JSON_DATA['word']=message.content.split('> ')[1]
response = requests.post(URL, json=JSON_DATA)
response_data = response.json().get('data', [])
image_bool = False
for i in response_data:
if i['type'] == 1:
res = i['content']
if i['type'] == 3:
image_bool = True
image_data = base64.b64decode(i['url'])
with open('tmp_image.png','wb') as file:
file.write(image_data)
image= discord.File('tmp_image.png')
await message.channel.send(f"{message.author.mention}{res}")
if image_bool:
await message.channel.send(file=image)
Listens for all messages in channels the bot can see.
Ignores messages sent by the bot itself to prevent loops.
Checks if the bot is mentioned in the message.
If the message contains just the mention without a subsequent question, replies with a greeting ("Hi~ How can I help you?").
If a question is present, extracts the text following the mention (
>delimiter), updates thewordfield inJSON_DATA, and sends a POST request to the RAGFlow API.Parses the API response, which is expected to be a list of items with a
typefield:type == 1: Text response stored inres.type == 3: Base64-encoded image data, decoded and saved astmp_image.png.
Sends the textual response mentioning the user.
If an image was received, sends the image as a file attachment.
Main Execution Loop
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(client.start(DISCORD_BOT_KEY))
except KeyboardInterrupt:
loop.run_until_complete(client.close())
finally:
loop.close()
Creates an asyncio event loop to run the Discord client.
Starts the bot using the Discord token.
Gracefully handles shutdown on
KeyboardInterrupt(Ctrl+C).Closes the event loop at the end.
Usage Example
Set the constants
URL,JSON_DATA['conversation_id'],JSON_DATA['Authorization'], andDISCORD_BOT_KEYwith valid values.Run the script:
python discord_svr.pyIn a Discord server where the bot is added, mention the bot with a query:
@BotName> What is the weather today?The bot will respond with the answer from the RAGFlow API, optionally sending an image if included.
Important Implementation Details and Algorithms
Message Parsing:
The bot expects messages to have the format:@BotName> user question hereIt splits on
'> 'to separate the mention from the query.API Communication:
Uses synchronousrequests.postinside an async function, which could be improved by using an asynchronous HTTP client (likeaiohttp) to avoid blocking the event loop.Image Handling:
Base64 image data returned by the API is decoded and saved to a temporary filetmp_image.pngbefore sending to Discord. This is a simple approach but may have concurrency issues if multiple requests happen simultaneously.
Interaction with Other System Components
RAGFlow Assistant Chat Bot API:
The core external dependency. This file acts as a client to the RAGFlow API, sending user queries and receiving responses.Discord Platform:
Acts as a bot client interfacing with Discord servers and channels, enabling real-time user interaction.File System:
Temporarily writes an image file to disk before sending it to Discord.
Mermaid Class Diagram
classDiagram
class DiscordClient {
+intents: discord.Intents
+client: discord.Client
+on_ready()
+on_message(message)
}
class RAGFlowAPI {
+URL: str
+JSON_DATA: dict
+post_query(word: str) dict
}
DiscordClient --> RAGFlowAPI : uses
Note:
DiscordClientrepresents the Discord bot client and its event methods.RAGFlowAPIrepresents the interaction with the external API endpoint.
Summary
discord_svr.py is a focused integration script that connects Discord users with an AI chatbot via the RAGFlow API. It listens for mentions, sends queries, and returns responses including images, enabling natural language interaction inside Discord. The architecture is straightforward, leveraging Discord.py and synchronous HTTP calls, with potential for enhancements in concurrency and error handling.