Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optional command prefix #2

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# chatGPT
# chatGPT

maubot plugin to allow your maubot instance to return queries from openAI GPT API endpoints.
maubot plugin to allow your maubot instance to return queries from openAI GPT API endpoints.

add your openAI API key to the config, and modify as you see fit. if you don't know what the options are, you
probably shouldn't be using this. please refer to the openai documentation.
Expand All @@ -10,3 +10,8 @@ recently sent in the current room to provide additional context to the conversat
have reasonable success with contextual follow-up questions, but may be seen as a significant security leak for
private rooms, and you may be using significantly more tokens than you think with each request. use this bot responsibly.

## Getting Started
Clone the repo and build the plugin with
```bash
zip -9r org.jobmachine.chatgpt.mbp *
```
11 changes: 8 additions & 3 deletions base-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ gpt_api_key: somestring
model: gpt-3.5-turbo
max_tokens: 2500

# The command to talk to chatgpt. Set to empty string '' to disable command
# prefix. When disabled, the bot will repond to all messages (except those
# it sent and other commands that start with !)
command_prefix: gpt

# allowed users who can make calls to the openAI APIs. an empty list
# means everyone is allowed.
allowed_users: []
Expand All @@ -25,8 +30,8 @@ enable_multi_user: true
# how to minimally train your bot. use this to adjust your bot's behavior.
# you can use the {name} variable in this text.
system_prompt: |
You are a friendly assistant named {name}.
The currend datetime is {timestamp}, and this can be used reliably to
You are a friendly assistant named {name}.
The currend datetime is {timestamp}, and this can be used reliably to
answer questions related to dates and times.
Answer concisely.

Expand All @@ -35,7 +40,7 @@ system_prompt: |
# so leave room here to include previous questions and context.
# refer to documentation about zero-shot, one-shot, and few-shot prompts.
# leave this an empty list to skip it altogether.
addl_context:
addl_context:
- role: user
content: What does TLA stand for?
- role: assistant
Expand Down
24 changes: 15 additions & 9 deletions gpt.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ def do_update(self, helper: ConfigUpdateHelper) -> None:
helper.copy("name")
helper.copy("allowed_users")
helper.copy("addl_context")
helper.copy("command_prefix")


class GPTPlugin(Plugin):

Expand All @@ -45,6 +47,7 @@ async def on_message(self, event: MessageEvent) -> None:
user = ''
content = ''
timestamp = datetime.today().strftime('%Y-%m-%d %H:%M:%S')
command_prefix = self.config['command_prefix']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be interesting to strip the config value to avoid "strange" behavior.


if event.sender == self.client.mxid:
role = 'assistant'
Expand All @@ -54,13 +57,18 @@ async def on_message(self, event: MessageEvent) -> None:
user = self.client.parse_user_id(event.sender)[0] + ': ' # only use the localpart

# keep track of all messages, even if the bot sent them
self.prev_room_events[event.room_id].append({"role": role , "content":
self.prev_room_events[event.room_id].append({"role": role , "content":
user + event['content']['body']})

# if the bot sent the message or another command was issued, just pass
if event.sender == self.client.mxid or event.content.body.startswith('!'):
# if the bot sent the message just pass
if event.sender == self.client.mxid:
return

if len(command_prefix) > 0 and not event.content.body.startswith(f"!{command_prefix}"):
return # ignore a comand does not match the required prefix
if len(command_prefix) == 0 and event.content.body.startswith(f'!'):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of this could be replaced by

if not command_prefix or not event.content.body.startswith(f'!{command_prefix}'):
    return

return # ignore all commands when prefix is disabled

joined_members = await self.client.get_joined_members(event.room_id)

try:
Expand All @@ -78,7 +86,7 @@ async def on_message(self, event: MessageEvent) -> None:
system_prompt = {"role": "system", "content": prompt}

await event.mark_read()

context = self.prev_room_events.get(event.room_id, [])
# if our short history is already at max capacity, drop the oldest messages
# to make room for our more important system prompt(s)
Expand Down Expand Up @@ -108,7 +116,7 @@ async def on_message(self, event: MessageEvent) -> None:
# Call the chatGPT API to get a response
await self.client.set_typing(event.room_id, timeout=99999)
response = await self._call_gpt(context)

# Send the response back to the chat room
await self.client.set_typing(event.room_id, timeout=0)
await event.respond(f"{response}")
Expand Down Expand Up @@ -140,7 +148,7 @@ async def _call_gpt(self, prompt):
"messages": full_context,
"max_tokens": self.config['max_tokens']
}

async with self.http.post(
GPT_API_URL, headers=headers, data=json.dumps(data)
) as response:
Expand All @@ -154,7 +162,7 @@ async def _call_gpt(self, prompt):
#self.log.debug(content)
return content

@command.new(name='gpt', help='control chatGPT functionality', require_subcommand=True)
@command.new(name=f"self.config['command_prefix']", help='control chatGPT functionality', require_subcommand=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The f-string here is wrong and unecessary. It should just be self.config['command_prefix']

async def gpt(self, evt: MessageEvent) -> None:
pass

Expand All @@ -163,9 +171,7 @@ async def clear_cache(self, evt: MessageEvent) -> None:
self.prev_room_events.pop(evt.room_id)
await evt.react('✅')


@classmethod
def get_config_class(cls) -> Type[BaseProxyConfig]:
return Config


2 changes: 1 addition & 1 deletion maubot.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ main_class: GPTPlugin
config: true
extra_files:
- base-config.yaml
database: false
database: false