Skip to content

Commit

Permalink
Add more configurable env vars
Browse files Browse the repository at this point in the history
  • Loading branch information
Elehiggle committed Apr 11, 2024
1 parent 72f037c commit 30558dc
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 30 deletions.
42 changes: 26 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,22 +50,32 @@ _or alternatively:_
python3.12 -m pip install anthropic mattermostdriver ssl certifi beautifulsoup4 pillow httpx
```

3. Set the following environment variables with your own values:

| Parameter | Description |
| --- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `AI_API_KEY` | Your Anthropic API key |
| `AI_MODEL` | The Anthropic model to use. Default: "claude-3-opus-20240229" |
| `AI_TIMEOUT` | The timeout for the AI API call in seconds. Default: "120" |
| `MAX_RESPONSE_SIZE_MB` | The maximum size of the website content to extract (in megabytes). Default: "100" |
| `MAX_TOKENS` | The maximum number of tokens to generate in the response. Default: "4096" (max) |
| `TEMPERATURE` | The temperature value for controlling the randomness of the generated responses (0.0 = analytical, 1.0 = fully random). Default: "0.15" |
| `MATTERMOST_URL` | The URL of your Mattermost server |
| `MATTERMOST_TOKEN` | The bot token (alternatively personal access token) with relevant permissions created specifically for the chatbot. Don't forget to add the bot account to the team. |
| `MATTERMOST_USERNAME` | The username of the dedicated Mattermost user account for the chatbot (if using username/password login) |
| `MATTERMOST_PASSWORD` | The password of the dedicated Mattermost user account for the chatbot (if using username/password login) |
| `MATTERMOST_MFA_TOKEN` | The MFA token of the dedicated Mattermost user account for the chatbot (if using MFA) |
| `MATTERMOST_IGNORE_SENDER_ID` | The user ID of a user to ignore (optional, useful if you have multiple chatbots to prevent endless loops) |
3. Set the following environment variables with your own values (most are optional):

| Parameter | Description |
|------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `AI_API_KEY` | Required. Your Anthropic API key |
| `AI_MODEL` | The Anthropic model to use. Default: "claude-3-opus-20240229" |
| `MATTERMOST_URL` | Required. The URL of your Mattermost server |
| `MATTERMOST_TOKEN` | Required if not using user/password. The bot token (alternatively personal access token) with relevant permissions created specifically for the chatbot. Don't forget to add the bot account to the team. |
| `MATTERMOST_USERNAME` | Required if not using token. The username of the dedicated Mattermost user account for the chatbot (if using username/password login) |
| `MATTERMOST_PASSWORD` | Required if not using token. The password of the dedicated Mattermost user account for the chatbot (if using username/password login) |
| `MATTERMOST_MFA_TOKEN` | The MFA token of the dedicated Mattermost user account for the chatbot (if using MFA) |

#### Extended optional configuration variables:

| Parameter | Description |
|-------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `AI_SYSTEM_PROMPT` | The system prompt/instructions. Default: [click](https://github.com/Elehiggle/Claude3MattermostChatbot/blob/a1e1813c40f44f5231d10ee3f25ef6eee13ae58f/chatbot.py#L88) (Subject to change. current_time and chatbot_username variables inside the prompt will be auto-formatted and substituted. |
| `AI_TIMEOUT` | The timeout for the AI API call in seconds. Default: "120" |
| `MAX_TOKENS` | The maximum number of tokens to generate in the response. Default: "4096" (max) |
| `TEMPERATURE` | The temperature value for controlling the randomness of the generated responses (0.0 = analytical, 1.0 = fully random). Default: "0.15" |
| `MAX_RESPONSE_SIZE_MB` | The maximum size of the website content to extract (in megabytes). Default: "100" |
| `MATTERMOST_IGNORE_SENDER_ID` | The user ID of a user to ignore (optional, useful if you have multiple chatbots to prevent endless loops) |
| `MATTERMOST_PORT` | The port of your Mattermost server. Default: "443" |
| `MATTERMOST_SCHEME` | The scheme of the connection. Default: "https" |
| `MATTERMOST_BASEPATH` | The basepath of your Mattermost server. Default: "/api/v4" |
| `MATTERMOST_CERT_VERIFY` | Cert verification. Default: True (also: string path to your certificate file) |

## Usage

Expand Down
45 changes: 31 additions & 14 deletions chatbot.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,18 @@ def cdc(*args, **kwargs):
timeout = int(os.getenv("AI_TIMEOUT", "120"))
max_tokens = int(os.getenv("MAX_TOKENS", "4096"))
temperature = float(os.getenv("TEMPERATURE", "0.15"))
system_prompt_unformatted = os.getenv(
"AI_SYSTEM_PROMPT",
"You are a helpful assistant. The current UTC time is {current_time}. Whenever users asks you for help you will provide them with succinct answers formatted using Markdown; do not unnecessarily greet people with their name. Do not be apologetic. You know the user's name as it is provided within [CONTEXT, from:username] bracket at the beginning of a user-role message. Never add any CONTEXT bracket to your replies (eg. [CONTEXT, from:{chatbot_username}]). The CONTEXT bracket may also include grabbed text from a website if a user adds a link to his question.",
)

# Mattermost server details
mattermost_url = os.environ["MATTERMOST_URL"]
mattermost_personal_access_token = os.getenv("MATTERMOST_TOKEN", "")
mattermost_scheme = os.getenv("MATTERMOST_SCHEME", "https")
mattermost_port = int(os.getenv("MATTERMOST_PORT", "443"))
mattermost_basepath = os.getenv("MATTERMOST_BASEPATH", "/api/v4")
mattermost_cert_verify = os.getenv("MATTERMOST_CERT_VERIFY", True)
mattermost_token = os.getenv("MATTERMOST_TOKEN", "")
mattermost_ignore_sender_id = os.getenv("MATTERMOST_IGNORE_SENDER_ID", "")
mattermost_username = os.getenv("MATTERMOST_USERNAME", "")
mattermost_password = os.getenv("MATTERMOST_PASSWORD", "")
Expand All @@ -59,14 +67,14 @@ def cdc(*args, **kwargs):
driver = Driver(
{
"url": mattermost_url,
"token": mattermost_personal_access_token,
"token": mattermost_token,
"login_id": mattermost_username,
"password": mattermost_password,
"mfa_token": mattermost_mfa_token,
"scheme": "https",
"port": 443,
"basepath": "/api/v4",
"verify": True,
"scheme": mattermost_scheme,
"port": mattermost_port,
"basepath": mattermost_basepath,
"verify": mattermost_cert_verify,
}
)

Expand All @@ -80,13 +88,14 @@ def cdc(*args, **kwargs):
# Create a thread pool with a fixed number of worker threads
thread_pool = concurrent.futures.ThreadPoolExecutor(max_workers=5)


def get_system_instructions():
current_time = datetime.datetime.now(datetime.UTC).strftime("%Y-%m-%d %H:%M:%S.%f")[
:-3
]
return f"You are a helpful assistant. The current UTC time is {current_time}. Whenever users asks you for help you will provide them with succinct answers formatted using Markdown; do not unnecessarily greet people with their name. Do not be apologetic. You know the user's name as it is provided within [CONTEXT, from:username] bracket at the beginning of a user-role message. Never add any CONTEXT bracket to your replies (eg. [CONTEXT, from:{chatbot_username}]). The CONTEXT bracket may also include grabbed text from a website if a user adds a link to his question."

global chatbot_username
return system_prompt_unformatted.format(
current_time=current_time, chatbot_username=chatbot_username
)

def sanitize_username(username):
if not re.match(r"^[a-zA-Z0-9_-]{1,64}$", username):
Expand Down Expand Up @@ -191,7 +200,7 @@ def add_chunk(chunk, in_code, code_lang):
return f"```{code_lang}\n"
return ""

lines = msg.split('\n')
lines = msg.split("\n")
for i, line in enumerate(lines):
# Check if this line starts or ends a code block
if line.startswith("```"):
Expand All @@ -206,19 +215,25 @@ def add_chunk(chunk, in_code, code_lang):
else:
# Starting a new code block, capture the language
in_code_block = True
code_block_lang = line[3:].strip() # Remove the backticks and get the language
code_block_lang = line[
3:
].strip() # Remove the backticks and get the language
current_chunk += line + "\n"
else:
# If adding this line exceeds the max length, we need to split here
if len(current_chunk) + len(line) + 1 > max_length:
# Split here, preserve the code block state and language if necessary
current_chunk = add_chunk(current_chunk, in_code_block, code_block_lang)
current_chunk += line
if i < len(lines) - 1: # Avoid adding a newline at the end of the last line
if (
i < len(lines) - 1
): # Avoid adding a newline at the end of the last line
current_chunk += "\n"
else:
current_chunk += line
if i < len(lines) - 1: # Avoid adding a newline at the end of the last line
if (
i < len(lines) - 1
): # Avoid adding a newline at the end of the last line
current_chunk += "\n"

# Don't forget to add the last chunk
Expand Down Expand Up @@ -308,7 +323,7 @@ async def message_handler(event):
sender_id == driver.client.userid
or sender_id == mattermost_ignore_sender_id
):
logging.info("Ignoring post from a ignored sender ID")
logging.info("Ignoring post from an ignored sender ID")
return

# Check if the post is from a bot
Expand Down Expand Up @@ -566,6 +581,8 @@ def main():
chatbot_username = driver.client.username
chatbot_usernameAt = f"@{chatbot_username}"

logging.info(f"SYSTEM PROMPT: {get_system_instructions()}")

# Initialize the WebSocket connection
while True:
try:
Expand Down

0 comments on commit 30558dc

Please sign in to comment.