diff --git a/README.md b/README.md index 6809a3c..9117e01 100644 --- a/README.md +++ b/README.md @@ -46,4 +46,8 @@ To interact with the bot, simply send a message to the bot in the Matrix room wi - `!chat` To chat using official api with context associated support ``` !chat Can you tell me a joke? -``` \ No newline at end of file +``` + +## Bing AI +https://github.com/waylaidwanderer/node-chatgpt-api +![](https://i.imgur.com/KuYddd5.jpg) \ No newline at end of file diff --git a/bing.py b/bing.py new file mode 100644 index 0000000..a8ab863 --- /dev/null +++ b/bing.py @@ -0,0 +1,45 @@ +import aiohttp +import json +import asyncio +from log import getlogger +# api_endpoint = "http://localhost:3000/conversation" +logger = getlogger() +python_boolean_to_json = { + "true": True, +} + + +class BingBot: + def __init__(self, bing_api_endpoint: str): + self.data = { + 'jailbreakConversationId': json.dumps(python_boolean_to_json['true']), + 'clientOptions.clientToUse': 'bing' + } + self.bing_api_endpoint = bing_api_endpoint + + async def ask_bing(self, prompt) -> str: + self.data['message'] = prompt + async with aiohttp.ClientSession() as session: + max_try = 5 + while max_try > 0: + try: + resp = await session.post(url=self.bing_api_endpoint, json=self.data) + status_code = resp.status + body = await resp.read() + if not status_code == 200: + # print failed reason + logger.warning(str(resp.reason)) + max_try = max_try - 1 + # print(await resp.text()) + await asyncio.sleep(2) + continue + json_body = json.loads(body) + # print(json_body['jailbreakConversationId']) + self.data['jailbreakConversationId'] = json_body['jailbreakConversationId'] + self.data['parentMessageId'] = json_body['messageId'] + return json_body['response'] + except Exception as e: + logger.error("Error Exception", exc_info=True) + print(f"Error: {e}") + pass + return "Error, please retry" diff --git a/bot.py b/bot.py index 31d3db1..b2987a4 100644 --- a/bot.py +++ b/bot.py @@ -9,10 +9,11 @@ from ask_gpt import ask from send_message import send_room_message from v3 import Chatbot from log import getlogger +from bing import BingBot """ free api_endpoint from https://github.com/ayaka14732/ChatGPTAPIFree """ -api_endpoint_list = { +chatgpt_api_endpoint_list = { "free": "https://chatgpt-api.shn.hk/v1/", "paid": "https://api.openai.com/v1/chat/completions" } @@ -21,13 +22,14 @@ logger = getlogger() class Bot: def __init__( - self, - homeserver: str, - user_id: str, - password: str, - device_id: str, - api_key: Optional[str] = "", - room_id: Optional[str] = '', + self, + homeserver: str, + user_id: str, + password: str, + device_id: str, + api_key: Optional[str] = "", + room_id: Optional[str] = '', + bing_api_endpoint: Optional[str] = '', ): self.homeserver = homeserver self.user_id = user_id @@ -35,6 +37,7 @@ class Bot: self.device_id = device_id self.room_id = room_id self.api_key = api_key + self.bing_api_endpoint = bing_api_endpoint # initialize AsyncClient object self.store_path = os.getcwd() self.config = AsyncClientConfig(store=SqliteStore, @@ -46,21 +49,27 @@ class Bot: # regular expression to match keyword [!gpt {prompt}] [!chat {prompt}] self.gpt_prog = re.compile(r"^\s*!gpt\s*(.+)$") self.chat_prog = re.compile(r"^\s*!chat\s*(.+)$") - # initialize chatbot and api_endpoint + self.bing_prog = re.compile(r"^\s*!bing\s*(.+)$") + # initialize chatbot and chatgpt_api_endpoint if self.api_key != '': self.chatbot = Chatbot(api_key=self.api_key) - self.api_endpoint = api_endpoint_list['paid'] + self.chatgpt_api_endpoint = chatgpt_api_endpoint_list['paid'] # request header for !gpt command self.headers = { "Content-Type": "application/json", "Authorization": "Bearer " + self.api_key, } else: + self.chatgpt_api_endpoint = chatgpt_api_endpoint_list['free'] self.headers = { "Content-Type": "application/json", } + # initialize bingbot + if self.bing_api_endpoint != '': + self.bingbot = BingBot(bing_api_endpoint) + # message_callback event async def message_callback(self, room: MatrixRoom, event: RoomMessageText) -> None: # print info to console @@ -75,6 +84,7 @@ class Bot: room_id = room.room_id else: room_id = self.room_id + # chatgpt n = self.chat_prog.match(event.body) if n: @@ -101,8 +111,8 @@ class Bot: await self.client.room_typing(room_id) prompt = m.group(1) try: - # 默认等待30s - text = await asyncio.wait_for(ask(prompt, self.api_endpoint, self.headers), timeout=30) + # timeout 30s + text = await asyncio.wait_for(ask(prompt, self.chatgpt_api_endpoint, self.headers), timeout=30) except TimeoutError: logger.error("timeoutException", exc_info=True) text = "Timeout error" @@ -110,6 +120,22 @@ class Bot: text = text.strip() await send_room_message(self.client, room_id, send_text=text) + # bing ai + if self.bing_api_endpoint != '': + b = self.bing_prog.match(event.body) + if b: + # sending typing state + await self.client.room_typing(room_id) + prompt = b.group(1) + try: + # timeout 30s + text = await asyncio.wait_for(self.bingbot.ask_bing(prompt), timeout=30) + except TimeoutError: + logger.error("timeoutException", exc_info=True) + text = "Timeout error" + text = text.strip() + await send_room_message(self.client, room_id, send_text=text) + # bot login async def login(self) -> None: resp = await self.client.login(password=self.password) diff --git a/compose.yaml b/compose.yaml index 7c196eb..51580c1 100644 --- a/compose.yaml +++ b/compose.yaml @@ -7,5 +7,18 @@ services: # context: . # dockerfile: ./Dockerfile volumes: - - ./config.json:/app/config.json + - ./app:/app + networks: + - matrix_network + # api: + # # bing api + # image: hibobmaster/node-chatgpt-api:latest + # container_name: node-chatgpt-api + # restart: always + # volumes: + # - ./settings.js:/var/chatgpt-api/settings.js + # networks: + # - matrix_network +networks: + matrix_network: \ No newline at end of file diff --git a/config.json.sample b/config.json.sample index 762b4ec..d8ade41 100644 --- a/config.json.sample +++ b/config.json.sample @@ -4,5 +4,6 @@ "password": "xxxxxxxxxxxxxxxxxx", "device_id": "ECYEOKVPLG", "room_id": "!FYCmBSkCRUNvZDBaDQ:matrix.qqs.tw", - "api_key": "xxxxxxxxxxxxxxxxxxxxxxxx" + "api_key": "xxxxxxxxxxxxxxxxxxxxxxxx", + "bing_api_endpoint": "" } \ No newline at end of file diff --git a/main.py b/main.py index 448bf1e..056c131 100644 --- a/main.py +++ b/main.py @@ -13,6 +13,7 @@ async def main(): device_id=config['device_id'], room_id=config.get('room_id', ''), # provide a default value when the key does not exist api_key=config.get('api_key', ''), + bing_api_endpoint=config.get('bing_api_endpoint', ''), ) await matrix_bot.login() await matrix_bot.sync_forever() diff --git a/test.py b/test.py index 825fe3c..bc41f13 100644 --- a/test.py +++ b/test.py @@ -2,9 +2,12 @@ from v3 import Chatbot import asyncio from ask_gpt import ask import json +from bing import BingBot + fp = open("config.json", "r") config = json.load(fp) api_key = config.get('api_key', '') +bing_api_endpoint = config.get('bing_api_endpoint', '') api_endpoint_list = { "free": "https://chatgpt-api.shn.hk/v1/", "paid": "https://api.openai.com/v1/chat/completions" @@ -34,7 +37,22 @@ async def test_ask_gpt_free(prompt: str): api_endpoint = api_endpoint_list['free'] print(await ask(prompt, api_endpoint, headers)) + +async def test_bingbot(): + if bing_api_endpoint != '': + bingbot = BingBot(bing_api_endpoint) + prompt1 = "Hello World" + prompt2 = "Do you know Victor Marie Hugo" + prompt3 = "Can you tell me something about him?" + resp1 = await bingbot.ask_bing(prompt1) + resp2 = await bingbot.ask_bing(prompt2) + resp3 = await bingbot.ask_bing(prompt3) + print(resp1) + print(resp2) + print(resp3) + if __name__ == "__main__": test_v3("Hello World") asyncio.run(test_ask_gpt_paid("Hello World")) asyncio.run(test_ask_gpt_free("Hello World")) + asyncio.run(test_bingbot())