From f5ccc6725879ea75be224d6e59b10f15cd98b263 Mon Sep 17 00:00:00 2001 From: hibobmaster Date: Tue, 11 Apr 2023 13:41:26 +0800 Subject: [PATCH] Support markdown message for better display code --- .env.example | 1 + .gitignore | 1 + README.md | 2 +- askgpt.py | 3 ++- bot.py | 39 +++++++++++++++++++++++++++++---------- config.json.sample | 3 ++- main.py | 2 ++ send_message.py | 30 ++++++++++++++++++++++++------ 8 files changed, 62 insertions(+), 19 deletions(-) diff --git a/.env.example b/.env.example index 9776077..864fe92 100644 --- a/.env.example +++ b/.env.example @@ -9,3 +9,4 @@ BING_API_ENDPOINT="xxxxxxxxxxxxxxx" # Optional, for !bing command ACCESS_TOKEN="xxxxxxxxxxxxxxxxxxxxx" # Optional, use user_id and password is recommended JAILBREAKENABLED="true" # Optional BING_AUTH_COOKIE="xxxxxxxxxxxxxxxxxxx" # _U cookie, Optional, for Bing Image Creator +MARKDOWN_FORMATTED="true" # Optional \ No newline at end of file diff --git a/.gitignore b/.gitignore index b87d56d..67b91f9 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,7 @@ share/python-wheels/ MANIFEST db bot.log +Dockerfile_dev # image generation folder images/ diff --git a/README.md b/README.md index fb39c65..4e25a82 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ python main.py To interact with the bot, simply send a message to the bot in the Matrix room with one of the two prompts:
-- `!gpt` To generate a response using free_endpoint API: +- `!gpt` To generate a one time response: ``` !gpt What is the meaning of life? diff --git a/askgpt.py b/askgpt.py index 9cca2d3..c840284 100644 --- a/askgpt.py +++ b/askgpt.py @@ -4,6 +4,7 @@ import json from log import getlogger logger = getlogger() + class askGPT: def __init__(self): self.session = aiohttp.ClientSession() @@ -22,7 +23,7 @@ class askGPT: while max_try > 0: try: async with self.session.post(url=api_endpoint, - json=jsons, headers=headers, timeout=60) as response: + json=jsons, headers=headers, timeout=60) as response: status_code = response.status if not status_code == 200: # print failed reason diff --git a/bot.py b/bot.py index e52b5d4..0390169 100644 --- a/bot.py +++ b/bot.py @@ -44,11 +44,12 @@ class Bot: "CHATGPT_API_ENDPOINT") or "https://api.openai.com/v1/chat/completions", api_key: Optional[str] = os.environ.get("OPENAI_API_KEY") or "", room_id: Union[str, None] = None, - bing_api_endpoint: Optional[str] = '', + bing_api_endpoint: Union[str, None] = None, password: Union[str, None] = None, access_token: Union[str, None] = None, - jailbreakEnabled: Optional[bool] = True, - bing_auth_cookie: Optional[str] = '', + jailbreakEnabled: Union[bool, None] = True, + bing_auth_cookie: Union[str, None] = '', + markdown_formatted: Union[bool, None] = False, ): if (homeserver is None or user_id is None or device_id is None): @@ -56,7 +57,7 @@ class Bot: sys.exit(1) if (password is None and access_token is None): - logger.warning("password and access_toekn is required") + logger.warning("password or access_toekn is required") sys.exit(1) self.homeserver = homeserver @@ -67,9 +68,27 @@ class Bot: self.room_id = room_id self.api_key = api_key self.chatgpt_api_endpoint = chatgpt_api_endpoint - self.bing_api_endpoint = bing_api_endpoint - self.jailbreakEnabled = jailbreakEnabled - self.bing_auth_cookie = bing_auth_cookie + + if bing_api_endpoint is None: + self.bing_api_endpoint = '' + else: + self.bing_api_endpoint = bing_api_endpoint + + if jailbreakEnabled is None: + self.jailbreakEnabled = True + else: + self.jailbreakEnabled = jailbreakEnabled + + if bing_auth_cookie is None: + self.bing_auth_cookie = '' + else: + self.bing_auth_cookie = bing_auth_cookie + + if markdown_formatted is None: + self.markdown_formatted = False + else: + self.markdown_formatted = markdown_formatted + # initialize AsyncClient object self.store_path = os.getcwd() self.config = AsyncClientConfig(store=SqliteStore, @@ -485,7 +504,7 @@ class Bot: text = text.strip() try: await send_room_message(self.client, room_id, reply_message=text, - reply_to_event_id="", sender_id=sender_id, user_message=raw_user_message) + reply_to_event_id="", sender_id=sender_id, user_message=raw_user_message, markdown_formatted=self.markdown_formatted) except Exception as e: logger.error(f"Error: {e}", exc_info=True) @@ -503,7 +522,7 @@ class Bot: text = text.strip() try: await send_room_message(self.client, room_id, reply_message=text, - reply_to_event_id="", sender_id=sender_id, user_message=raw_user_message) + reply_to_event_id="", sender_id=sender_id, user_message=raw_user_message, markdown_formatted=self.markdown_formatted) except Exception as e: logger.error(f"Error: {e}", exc_info=True) @@ -520,7 +539,7 @@ class Bot: text = text.strip() try: await send_room_message(self.client, room_id, reply_message=text, - reply_to_event_id="", sender_id=sender_id, user_message=raw_user_message) + reply_to_event_id="", sender_id=sender_id, user_message=raw_user_message, markdown_formatted=self.markdown_formatted) except Exception as e: logger.error(f"Error: {e}", exc_info=True) diff --git a/config.json.sample b/config.json.sample index e06b502..baf6c95 100644 --- a/config.json.sample +++ b/config.json.sample @@ -8,5 +8,6 @@ "bing_api_endpoint": "http://api:3000/conversation", "jailbreakEnabled": true, "access_token": "xxxxxxx", - "bing_auth_cookie": "xxxxxxxxxxx" + "bing_auth_cookie": "xxxxxxxxxxx", + "markdown_formatted": true } diff --git a/main.py b/main.py index 101bd52..59b6076 100644 --- a/main.py +++ b/main.py @@ -22,6 +22,7 @@ async def main(): access_token=config.get('access_token'), jailbreakEnabled=config.get('jailbreakEnabled'), bing_auth_cookie=config.get('bing_auth_cookie'), + markdown_formatted=config.get('markdown_formatted'), ) else: @@ -35,6 +36,7 @@ async def main(): access_token=os.environ.get("ACCESS_TOKEN"), jailbreakEnabled=os.environ.get("JAILBREAKENABLED", "false").lower() in ('true', '1', 't'), bing_auth_cookie=os.environ.get("BING_AUTH_COOKIE"), + markdown_formatted=os.environ.get("MARKDOWN_FORMATTED", "false").lower() in ('true', '1', 't'), ) await matrix_bot.login() diff --git a/send_message.py b/send_message.py index 76ac1fd..2bd2bc9 100644 --- a/send_message.py +++ b/send_message.py @@ -1,22 +1,40 @@ from nio import AsyncClient +import re +import markdown + async def send_room_message(client: AsyncClient, room_id: str, reply_message: str, sender_id: str = '', user_message: str = '', - reply_to_event_id: str = '') -> None: + reply_to_event_id: str = '', + markdown_formatted: bool = False) -> None: + NORMAL_BODY = content = {"msgtype": "m.text", "body": reply_message, } if reply_to_event_id == '': - content = {"msgtype": "m.text", "body": reply_message, } + if markdown_formatted: + # only format message contains multiline codes + if re.search(r"```", reply_message) is not None: + content = { + "msgtype": "m.text", + "body": reply_message, + "format": "org.matrix.custom.html", + "formatted_body": markdown.markdown(reply_message, extensions=['nl2br', 'tables', 'fenced_code']) + } + else: + content = NORMAL_BODY + + else: + content = NORMAL_BODY else: body = r'> <' + sender_id + r'> ' + user_message + r'\n\n' + reply_message format = r'org.matrix.custom.html' formatted_body = r'
In reply to ' + sender_id \ - + r'
' + user_message + r'
' + reply_message + + r'">In reply to ' + sender_id \ + + r'
' + user_message + r'' + reply_message - content={"msgtype": "m.text", "body": body, "format": format, "formatted_body": formatted_body, - "m.relates_to": {"m.in_reply_to": {"event_id": reply_to_event_id}}, } + content = {"msgtype": "m.text", "body": body, "format": format, "formatted_body": formatted_body, + "m.relates_to": {"m.in_reply_to": {"event_id": reply_to_event_id}}, } await client.room_send( room_id, message_type="m.room.message",