Having a Discord bot for your server that interacts with users and resolves their queries on your behalf is incredibly useful. However, building such a bot can be extremely challenging and may take months due to the complexities involved in data preprocessing, model training, hyperparameter training, and deployment. This is where Julep comes in to save the day.
Julep is a platform that helps to build stateful and functional LLM-powered applications. Using Julep, you can create a fully operational AI application with minimal code.
While platforms such as OpenAI's GPT-3, Microsoft's Azure Bot Service, and Google's Dialogflow enable the development of AI applications, Julep distinguishes itself with unique benefits. Julep offers unique features like composio tools integration, adaptive context, multiple AI Agents support, and in-built RAG.
In this blog, we will create an AI Discord Bot using Julep and add it to a live Discord Server to try it. We will walk through each step and understand how you can use Julep in your projects.
Prerequisites
Make sure you have Node.js installed on your device. Download and install Node.js from their official website.
If you like the posts on the Julep blog so far, please consider please consider giving Julep a star on GitHub, it helps us to reach and help more developers.
🌟 Contributors and DevFest.AI Participants (Click to expand)
🌟 Call for Contributors!
We're excited to welcome new contributors to the Julep project! We've created several "good first issues" to help you get started. Here's how you can contribute:
Check out our CONTRIBUTING.md file for guidelines on how to contribute.
Create a new Julep Client using julep.Client() method. This client interfaces with the Julep API and sets up the managers for agents, users, sessions, documents, memories, and tools.
Add a log to display a message when the Discord client is ready. This will confirm that the Discord client has been successfully created.
client.once("ready",()=>{console.log(`Logged in as ${client.user.tag}!`);});
Now, we want to capture the message content each time the user enters a new message. For that, we will use the messageCreate action.
client.on("messageCreate",async (message)=>{
When a user sends a message in the channel, a message object is created. This message object contains every detail about the sent message. We will use this message object to capture some of those details.
Next step is to make sure that the user is not a bot and a human. For that we will check if bot property is present in message object or not:
if (message.author.bot){return;}
We want to show the Bot is typing…. animation to let the users know that the bot is replying to their query. For this we will use the sendTyping() function.
awaitmessage.channel.sendTyping();
Now, let’s create users, agents, and sessions to perform the interaction with Julep API.
Creating User
A User object represents an entity, either a person or a system, that interacts with the application. Every AI application built with Julep supports multiple users, each able to interact with the Agent. Each user is unique, with their own identity and role.
It is not a necessary thing to define a User. Applications can function properly even in the absence of a User. However, it's a good idea to create a user profile for each person or system interacting with the Agent for better organization and tracking. Adding basic details about the user helps the application understand their behavior, allowing it to provide personalized results that match the user's preferences and needs.
Julep comes with a users.create() method which we can be used on the client to create a user. Creating a user demands 4 attributes:
Name - Name of the user
About - Small description of the user
Documents - Essential documents formatted as text tailored to the user's needs (Optional)
Metadata - Additional data beyond the ID that pertains to the user within the application (Optional)
Here’s an example:
constuser=awaitclient.users.create({name:"Sam",about:"Machine Learning Developer and AI Enthusiast",docs:[{"title":"AI Efficiency Report","content":"...","metadata":{"page":1}}],// Optionalmetadata:{"db_uuid":"1234"},// Optional});
Now, let’s create a user for our Discord bot. We will keep the name of the user dynamic to capture the name of each user interacting with the Discord bot.
constuser=awaitjulepClient.users.create({name:message.author.globalName,about:"A test user",});
Here, we have created a user with the name assigned to globalName property and A test user as description.
Creating Agent
An Agent is a smart interface that connects the user and the application, managing interactions to improve the user experience. Agents are designed to handle user queries and provide customized results or suggestions.
Agents store all the settings and configurations for the LLM models you want to use in your AI application. This allows the application to perform specific tasks and meet individual user preferences.
Agents can be simple, like a chatbot, or more complex, like advanced AI assistants that understand natural language and perform complex tasks.
In Julep, you can create an agent using the agents.create() method. Creating an agent requires a set of attributes:
Name - Name of the agent
About - Small description of the agent (Optional)
Instructions - List of instructions for the agent to follow (Optional)
Tools - List of functions for agent to execute tasks (Optional)
Model Name - LLM Model that agent will use (Optional)
Settings - Configurations on LLM model (Optional)
Documents - Important documents in text format to be used by agent to improve the persona (Optional)
Metadata - Additional information apart from ID to identify the user or agent (Optional)
Here’s an example:
constagent=client.agents.create((name="Cody"),(about="Cody is an AI powered code reviewer. It can review code, provide feedback, suggest improvements, and answer questions about code."),(instructions=["On every new issue, Review the issue made in the code. Summarize the issue made in the code and add a comment","Scrutinize the changes very deeply for potential bugs, errors, security vulnerabilities. Assume the worst case scenario and explain your reasoning for the same.",]),(tools=[{type:"function",function:{name:"github_comment",description:"Posts a comment made on a GitHub Pull Request after every new commit. The tool will return a boolean value to indicate if the comment was successfully posted or not.",parameters:{type:"object",properties:{comment:{type:"string",description:"The comment to be posted on the issue. It should be a summary of the changes made in the PR and the feedback on the same.",},pr_number:{type:"number",description:"The issue number on which the comment is to be posted.",},},required:["comment","pr_number"],},},},]),(model="gpt-4"),(default_settings={temperature:0.7,top_p:1,min_p:0.01,presence_penalty:0,frequency_penalty:0,length_penalty:1.0,}),(docs=[{title:"API Reference",content:"...",metadata:{page:1}}]),(metadata={db_uuid:"1234"}));
Now, let’s create the agent for our Discord bot:
constagent=awaitjulepClient.agents.create({name:"Jarvis an AI Assistant",model:"gpt-4-turbo",});
Here, we've used the gpt-4-turbo LLM model in this agent, but Julep supports various LLM models for creating AI applications. Check out the documentation for more information.
Creating Session
A Session is a period where users interact with the agent. It includes all the back-and-forth messaging and relevant details.
Sessions store all messages exchanged between the user and agent. This helps the AI understand the conversation better and provide more personalized answers.
To create a session, use the sessions.create() method. Here are the attributes it requires:
Agent ID - ID of the created agent
User ID - ID of the created user (Optional)
Situation - A prompt to describe the background of the interaction
Metadata - Additional information apart from IDs to identify the session (Optional)
Situation attribute is important in the session because it provides context for the interaction. This helps the agent understand the user's query better and give more personalized responses.
Here’s an example:
// Assuming 'client' is an object with a 'sessions' property containing a 'create' methodletsession=client.sessions.create({agent_id:agent.id,user_id:user.id,situation:`
You are James a Software Developer, public speaker & renowned educator.
You are an educator who is qualified to train students, developers & entrepreneurs.
About you:
...
Important guidelines:
...
`,metadata:{db_uuid:"1234"},});
Let’s create a session for our Discord bot:
constsituationPrompt="Your name is Jarvis and you are a Senior Software Engineer that has decades of experience in coding. You have worked with almost every programming language present there like C, C++, C#, JavaScript, TypeScript, Python, Swift, Ruby, Go, Rust, Blockchain, Solidity, etc. People comes to you and ask their questions related to coding. Users ask their doubts, queries, project ideas, questions, solutions and everything about related to coding. You help users with their coding related problems. But you are savage and sarcastic in nature. Therefore, you answer each question in a very sarcastic and savage manner. Sometimes you also roast users based upon the query they have asked. But no matter how sarcastic and savage you are, you do provide the answer user is looking for.";constsession=awaitjulepClient.sessions.create({agentId:agent.id,userId:user.id,situation:situationPrompt,});
Here, we have created the situationPrompt that has the whole situation/context for our Discord bot to perform the interaction. Then used this situationPrompt for situation attribute and specified other mandatory attributes to create a session.
Getting Message Response
After creating the user, agent, and session, we need to manage the interaction. We'll use the sessions.chat() method to handle the chat and get the response message.
This method requires two attributes to work: session.id and an object containing a messages array.
constchatParams={messages:[{role:"user",name:message.author.globalName,content:message.content,},],max_tokens:1000,};constchatResponse=awaitjulepClient.sessions.chat(session.id,chatParams);constresponseMessage=chatResponse.response[0][0].content;constchunks=responseMessage.match(/[\s\S]{1,2000}/g);// Send each chunk as a separate messagefor (constchunkofchunks){awaitmessage.channel.send(chunk);}
Here, we have created the chatParams object that has a messages array. This array includes:
role - role of the message sender, “user”
name - name of the message sender, message.author.globalName
content - content of the message, message.content
Along with this, the chatParams also holds a max_tokens property with the value 1000, which represents the maximum number of tokens to generate in the chat completion.
Following that, the sessions.chat() method is called on the client with session.id and chatParams as arguments. The resultant object is stored in chatResponse.
The value of the content property is extracted from chatResponse and stored in responseMessage.
Then, the message stored in responseMessage is split into smaller groups of 2000 characters and stored in the chunks variable.
After this, a for-of loop is used on the chunks array to send each chunk as a message to the user using the channel.send() method.
Lastly, the client.login(token) is used to authenticate and connect a client (like a Discord bot) to a server using a specified token.
Here’s the full index.js code:
require("dotenv").config();const{Client,GatewayIntentBits,Collection}=require("discord.js");constclient=newClient({intents:[GatewayIntentBits.Guilds,GatewayIntentBits.GuildMessages,GatewayIntentBits.MessageContent,],});constjulep=require("@julep/sdk");constapiKey=process.env.JULEP_API_KEY;constjulepClient=newjulep.Client({apiKey});client.commands=newCollection();consttoken=process.env.BOT_KEY;client.once("ready",()=>{console.log(`Logged in as ${client.user.tag}!`);});client.on("messageCreate",async (message)=>{if (message.author.bot){return;}awaitmessage.channel.sendTyping();constuser=awaitjulepClient.users.create({name:message.author.globalName,about:"A test user",});constagent=awaitjulepClient.agents.create({name:"July an AI Assistant",model:"gpt-4-turbo",});constsituationPrompt="Your name is Jarvis and you are a Senior Software Engineer that has decades of experience in coding. You have worked with almost every programming language present there like C, C++, C#, JavaScript, TypeScript, Python, Swift, Ruby, Go, Rust, Blockchain, Solidity, etc. People comes to you and ask their questions related to coding. Users ask their doubts, queries, project ideas, questions, solutions and everything about related to coding. You help users with their coding related problems. But you are savage and sarcastic in nature. Therefore, you answer each question in a very sarcastic and savage manner. Sometimes you also roast users based upon the query they have asked. But no matter how sarcastic and savage you are, you do provide the answer user is looking for.";constsession=awaitjulepClient.sessions.create({agentId:agent.id,userId:user.id,situation:situationPrompt,});constchatParams={messages:[{role:"user",name:message.author.globalName,content:message.content,},],max_tokens:1000,};constchatResponse=awaitjulepClient.sessions.chat(session.id,chatParams);constresponseMessage=chatResponse.response[0][0].content;constchunks=responseMessage.match(/[\s\S]{1,2000}/g);// Send each chunk as a separate messagefor (constchunkofchunks){awaitmessage.channel.send(chunk);}});client.login(token);
Congratulations your Discord Bot is successfully created.
Deploy the bot
The bot is completed, we will run it and try it.
To deploy the bot, run the command in the terminal:
node index.js
If your bot starts running successfully, you should see this message in log window:
Logged in as botName#botTag
with your Bot name and Bot tag in-place of botName and botTag.
Now, to try out the Discord bot, we need to add it in a Discord server.
Adding Bot to a Server
Go to the Discord Developer Portal and open your created Discord bot.
Navigate to the OAuth2 section on the left-hand side. Scroll down to the OAuth2 URL Generator and check the bot box.
Further down, under Bot Permissions, select the necessary permissions for your Discord bot, such as Send Messages, Read Message History, and Manage Messages.
A URL will be generated in the Generated URL section. Copy this URL and paste it into your web browser.
Select the desired server from the dropdown menu and click Authorize.
Your bot will now be added to the server.
Now you can try out your Discord bot, message him, and get his responses.
🌟 Contributors and DevFest.AI Participants (Click to expand)
🌟 Call for Contributors!
We're excited to welcome new contributors to the Julep project! We've created several "good first issues" to help you get started. Here's how you can contribute:
Check out our CONTRIBUTING.md file for guidelines on how to contribute.