Customer Service Discord Bot with Agentic RAG#
You can also check this cookbook in colab here
⭐ Star the Repo
If you find CAMEL useful or interesting, please consider giving it a star on our CAMEL GitHub Repo! Your stars help others find this project and motivate us to continue improving it.
Installation and Setup#
First, install the CAMEL package with all its dependencies
[ ]:
!pip install "camel-ai[all]==0.2.14"
!pip install starlette
!pip install nest_asyncio
Next, set up your API keys for Firecrawl and the model (Qwen or Mistral)
If you don’t have a FireCrawl API key, you can obtain one by following these steps:
Visit the FireCrawl API Key page https://www.firecrawl.dev/app/api-keys
Log in or sign up for a FireCrawl account.
Navigate to the ‘API Keys’ section.
Click on ‘Create API Key’ button to generate a new API key.
For more details, you can also check the Firecrawl documentation: https://docs.firecrawl.dev/api-reference/introduction
[ ]:
import os
from getpass import getpass
firecrawl_api_key = getpass('Enter your API key: ')
os.environ["FIRECRAWL_API_KEY"] = firecrawl_api_key
Enter your API key: ··········
If you want to choose Mistral as the model, skip below part for Qwen.
If you don’t have a Qwen API key, you can obtain one by following these steps:
Visit the Alibaba Cloud Model Studio Console (https://www.alibabacloud.com/en?_p_lc=1) and follow the on-screen instructions to activate the model services.
In the upper-right corner of the console, click on your account name and select API-KEY.
On the API Key management page, click on the Create API Key button to generate a new key.
For more details, you can also check the Qwen documentation: https://www.alibabacloud.com/help/en/model-studio/developer-reference/use-qwen-by-calling-api
[ ]:
import os
from getpass import getpass
qwen_api_key = getpass('Enter your API key: ')
os.environ["QWEN_API_KEY"] = qwen_api_key
Enter your API key: ··········
Alternatively, use Mistral.
If you don’t have a Mistral API key, you can obtain one by following these steps:
Visit the Mistral Console (https://console.mistral.ai/)
In the left panel, click on API keys under API section
Choose your plan
For more details, you can also check the Mistral documentation: https://docs.mistral.ai/getting-started/quickstart/
[ ]:
mistral_api_key = getpass('Enter your API key')
os.environ["MISTRAL_API_KEY"] = mistral_api_key
Enter your API key··········
Knowledge Crawling and Storage#
Use Firecrawl to crawl a website and store the content in a markdown file:
[ ]:
import os
from camel.loaders import Firecrawl
os.makedirs('local_data', exist_ok=True)
firecrawl = Firecrawl()
knowledge = firecrawl.crawl(
url="https://qdrant.tech/documentation/overview/"
)["data"][0]["markdown"]
with open('local_data/qdrant_overview.md', 'w') as file:
file.write(knowledge)
/usr/local/lib/python3.10/dist-packages/pydantic/_internal/_fields.py:172: UserWarning: Field name "schema" in "FirecrawlApp.ExtractParams" shadows an attribute in parent "BaseModel"
warnings.warn(
Basic Agent Setup#
Qwen is a large language model developed by Alibaba Cloud. It is trained on a massive dataset of text and code and can generate text, translate languages, write different kinds of creative content, and answer your questions in an informative way.
Use QWen model:
[ ]:
from camel.configs import QwenConfig, MistralConfig
from camel.models import ModelFactory
from camel.types import ModelPlatformType, ModelType
qwen_model = ModelFactory.create(
model_platform=ModelPlatformType.QWEN,
model_type=ModelType.QWEN_TURBO,
model_config_dict=QwenConfig(temperature=0.2).as_dict(),
)
mistral_model = ModelFactory.create(
model_platform=ModelPlatformType.MISTRAL,
model_type=ModelType.MISTRAL_LARGE,
model_config_dict=MistralConfig(temperature=0.0).as_dict(),
)
# Use Qwen model
model = qwen_model
# Replace with mistral_model if you want to choose mistral mode instead
# model = mistral_model
[ ]:
from camel.agents import ChatAgent
from camel.messages import BaseMessage
agent = ChatAgent(
system_message="You're a helpful assistant",
message_window_size=10,
model=model
)
knowledge_message = BaseMessage.make_user_message(
role_name="User", content=f"Based on the following knowledge: {knowledge}"
)
agent.update_memory(knowledge_message, "user")
Basic Chatbot Setup#
[ ]:
print("Start chatting! Type 'exit' to end the conversation.")
while True:
user_input = input("User: ")
if user_input.lower() == "exit":
print("Ending conversation.")
break
assistant_response = agent.step(user_input)
print(f"Assistant: {assistant_response.msgs[0].content}")
Start chatting! Type 'exit' to end the conversation.
User: Hey, what is Qdrant?
Assistant: Qdrant is an open-source vector database and vector search engine written in Rust. It provides fast and scalable vector similarity search services with a convenient API.
Key features of Qdrant include:
1. Storage and querying of high-dimensional vectors efficiently.
2. Use of specialized data structures and indexing techniques like Hierarchical Navigable Small World (HNSW) graphs.
3. Support for various distance metrics such as Cosine Similarity, Dot Product, and Euclidean Distance.
4. Ability to handle large-scale datasets with billions of data points.
5. Real-time analytics and query capabilities.
6. Support for vectors derived from complex data types like images, videos, and natural language text.
Qdrant is particularly useful for applications requiring similarity search, such as recommendation systems, content-based image retrieval, and personalized search.
User: Exit
Ending conversation.
Basic Discord Bot Integration#
To build a discord bot, a discord bot token is necessary.
If you don’t have a bot token, you can obtain one by following these steps:
Go to the Discord Developer Portal:https://discord.com/developers/applications
Log in with your Discord account, or create an account if you don’t have one
Click on ‘New Application’ to create a new bot.
Give your application a name and click ‘Create’.
Navigate to the ‘Bot’ tab on the left sidebar and click ‘Add Bot’.
Once the bot is created, you will find a ‘Token’ section. Click ‘Reset Token’ to generate a new token.
Copy the generated token securely.
To invite the bot:
Navigate to the ‘OAuth2’ tab, then to ‘URL Generator’.
Under ‘Scopes’, select ‘bot’.
Under ‘Bot Permissions’, select the permissions your bot will need (e.g., ‘Send Messages’, ‘Read Messages’ for our bot use)
Copy the generated URL and paste it into your browser to invite the bot to your server.
To grant the bot permissions:
Navigate to the ‘Bot’ tab
Under ‘Privileged Gateway Intents’, check ‘Server Members Intent’ and ‘Message Content Intent’.
For more details, you can also check the official Discord bot documentation: https://discord.com/developers/docs/intro
[ ]:
import os
from getpass import getpass
discord_bot_token = getpass('Enter your Discord bot token: ')
os.environ["DISCORD_BOT_TOKEN"] = discord_bot_token
Enter your Discord bot token: ··········
This code cell sets up a simple Discord bot using the DiscordApp class from the camel.bots library. The bot listens for messages in any channel it has access to and provides a response based on the input message.
[ ]:
from camel.bots import DiscordApp
import nest_asyncio
import discord
nest_asyncio.apply()
discord_bot = DiscordApp(token=discord_bot_token)
@discord_bot.client.event
async def on_message(message: discord.Message):
if message.author == discord_bot.client.user:
return
if message.type != discord.MessageType.default:
return
if message.author.bot:
return
user_input = message.content
agent.reset()
agent.update_memory(knowledge_message, "user")
assistant_response = agent.step(user_input)
response_content = assistant_response.msgs[0].content
if len(response_content) > 2000: # discord message length limit
for chunk in [response_content[i:i+2000] for i in range(0, len(response_content), 2000)]:
await message.channel.send(chunk)
else:
await message.channel.send(response_content)
discord_bot.run()
2024-12-05 18:11:30 INFO discord.client logging in using static token
INFO:discord.client:logging in using static token
2024-12-05 18:11:31 INFO discord.gateway Shard ID None has connected to Gateway (Session ID: 18b507aabdd91f2cdcbf70d7f010191d).
INFO:discord.gateway:Shard ID None has connected to Gateway (Session ID: 18b507aabdd91f2cdcbf70d7f010191d).
Integrating Qdrant for Large Files to build a more powerful Discord bot#
Qdrant is a vector similarity search engine and vector database. It is designed to perform fast and efficient similarity searches on large datasets of vectors. This enables the chatbot to access and utilize external information to provide more comprehensive and accurate responses. By storing knowledge as vectors, Qdrant enables efficient semantic search, allowing the chatbot to find relevant information based on the meaning of the user’s query.
Set up an embedding model and retriever for Qdrant:
[ ]:
from camel.embeddings import SentenceTransformerEncoder
sentence_encoder = SentenceTransformerEncoder(model_name='intfloat/e5-large-v2')
/usr/local/lib/python3.10/dist-packages/sentence_transformers/cross_encoder/CrossEncoder.py:13: TqdmExperimentalWarning: Using `tqdm.autonotebook.tqdm` in notebook mode. Use `tqdm.tqdm` instead to force console mode (e.g. in jupyter console)
from tqdm.autonotebook import tqdm, trange
2024-12-05 18:12:54.845321: E external/local_xla/xla/stream_executor/cuda/cuda_fft.cc:485] Unable to register cuFFT factory: Attempting to register factory for plugin cuFFT when one has already been registered
2024-12-05 18:12:54.864069: E external/local_xla/xla/stream_executor/cuda/cuda_dnn.cc:8454] Unable to register cuDNN factory: Attempting to register factory for plugin cuDNN when one has already been registered
2024-12-05 18:12:54.869936: E external/local_xla/xla/stream_executor/cuda/cuda_blas.cc:1452] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered
2024-12-05 18:12:54.884872: I tensorflow/core/platform/cpu_feature_guard.cc:210] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.
To enable the following instructions: AVX2 AVX512F FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.
2024-12-05 18:12:56.139323: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Could not find TensorRT
/usr/local/lib/python3.10/dist-packages/huggingface_hub/utils/_auth.py:94: UserWarning:
The secret `HF_TOKEN` does not exist in your Colab secrets.
To authenticate with the Hugging Face Hub, create a token in your settings tab (https://huggingface.co/settings/tokens), set it as secret in your Google Colab and restart your session.
You will be able to reuse this secret in all of your notebooks.
Please note that authentication is recommended but still optional to access public models or datasets.
warnings.warn(
Set up the AutoRetriever for automatically retrieving relevant information from a storage system.
[ ]:
from camel.retrievers import AutoRetriever
from camel.types import StorageType
assistant_sys_msg = """You are a helpful assistant to answer question,
I will give you the Original Query and Retrieved Context,
answer the Original Query based on the Retrieved Context,
if you can't answer the question just say I don't know."""
auto_retriever = AutoRetriever(
vector_storage_local_path="local_data2/",
storage_type=StorageType.QDRANT,
embedding_model=sentence_encoder
)
qdrant_agent = ChatAgent(system_message=assistant_sys_msg, model=model)
Use Auto RAG to retrieve first and then answer the user’s query using CAMEL ChatAgent
based on the retrieved info:
[ ]:
from camel.bots import DiscordApp
import nest_asyncio
import discord
nest_asyncio.apply()
discord_q_bot = DiscordApp(token=discord_bot_token)
@discord_q_bot.client.event # triggers when a message is sent in the channel
async def on_message(message: discord.Message):
if message.author == discord_q_bot.client.user:
return
if message.type != discord.MessageType.default:
return
if message.author.bot:
return
user_input = message.content
retrieved_info = auto_retriever.run_vector_retriever(
query=user_input,
contents=[
"local_data/qdrant_overview.md",
],
top_k=3,
return_detailed_info=False,
similarity_threshold=0.5
)
user_msg = str(retrieved_info)
assistant_response = qdrant_agent.step(user_msg)
response_content = assistant_response.msgs[0].content
if len(response_content) > 2000: # discord message length limit
for chunk in [response_content[i:i+2000] for i in range(0, len(response_content), 2000)]:
await message.channel.send(chunk)
else:
await message.channel.send(response_content)
discord_q_bot.run()
2024-12-05 18:13:16 INFO discord.client logging in using static token
2024-12-05 18:13:16 INFO discord.client logging in using static token
INFO:discord.client:logging in using static token
2024-12-05 18:13:17 INFO discord.gateway Shard ID None has connected to Gateway (Session ID: 05c4332a395af2dfb6c69abf8779a92a).
2024-12-05 18:13:17 INFO discord.gateway Shard ID None has connected to Gateway (Session ID: 05c4332a395af2dfb6c69abf8779a92a).
INFO:discord.gateway:Shard ID None has connected to Gateway (Session ID: 05c4332a395af2dfb6c69abf8779a92a).
That’s everything: Got questions about 🐫 CAMEL-AI? Join us on Discord! Whether you want to share feedback, explore the latest in multi-agent systems, get support, or connect with others on exciting projects, we’d love to have you in the community! 🤝
Check out some of our other work:
🐫 Creating Your First CAMEL Agent free Colab
Graph RAG Cookbook free Colab
🧑⚖️ Create A Hackathon Judge Committee with Workforce free Colab
🔥 3 ways to ingest data from websites with Firecrawl & CAMEL free Colab
🦥 Agentic SFT Data Generation with CAMEL and Mistral Models, Fine-Tuned with Unsloth free Colab
Thanks from everyone at 🐫 CAMEL-AI
⭐ Star the Repo
If you find CAMEL useful or interesting, please consider giving it a star on our CAMEL GitHub Repo! Your stars help others find this project and motivate us to continue improving it.