feat: Support chatgpt web session isolation
This commit is contained in:
parent
2e3fb4ae30
commit
4eef6284d8
7 changed files with 76 additions and 56 deletions
|
@ -5,5 +5,5 @@ OPENAI_API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
BING_API_ENDPOINT="http://api:3000/conversation"
|
BING_API_ENDPOINT="http://api:3000/conversation"
|
||||||
BARD_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx."
|
BARD_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx."
|
||||||
BING_AUTH_COOKIE="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
BING_AUTH_COOKIE="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
PANDORA_API_ENDPOINT="http://127.0.0.1:8008"
|
PANDORA_API_ENDPOINT="http://pandora:8008"
|
||||||
PANDORA_API_MODEL="text-davinci-002-render-sha-mobile"
|
PANDORA_API_MODEL="text-davinci-002-render-sha-mobile"
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -134,3 +134,6 @@ dmypy.json
|
||||||
|
|
||||||
# Pyre type checker
|
# Pyre type checker
|
||||||
.pyre/
|
.pyre/
|
||||||
|
|
||||||
|
# custom
|
||||||
|
compose-local-dev.yaml
|
|
@ -6,7 +6,7 @@ This is a simple Mattermost Bot that uses OpenAI's GPT API and Bing AI and Googl
|
||||||
|
|
||||||
1. Support Openai ChatGPT and Bing AI and Google Bard
|
1. Support Openai ChatGPT and Bing AI and Google Bard
|
||||||
2. Support Bing Image Creator
|
2. Support Bing Image Creator
|
||||||
3. [pandora](https://github.com/pengzhile/pandora)
|
3. [pandora](https://github.com/pengzhile/pandora) with Session isolation support
|
||||||
|
|
||||||
## Installation and Setup
|
## Installation and Setup
|
||||||
|
|
||||||
|
|
65
bot.py
65
bot.py
|
@ -120,9 +120,9 @@ class Bot:
|
||||||
if pandora_api_endpoint is not None:
|
if pandora_api_endpoint is not None:
|
||||||
self.pandora_api_endpoint = pandora_api_endpoint
|
self.pandora_api_endpoint = pandora_api_endpoint
|
||||||
self.pandora = Pandora(
|
self.pandora = Pandora(
|
||||||
api_endpoint=pandora_api_endpoint
|
api_endpoint=pandora_api_endpoint,
|
||||||
|
clientSession=self.session
|
||||||
)
|
)
|
||||||
self.pandora_init()
|
|
||||||
if pandora_api_model is None:
|
if pandora_api_model is None:
|
||||||
self.pandora_api_model = "text-davinci-002-render-sha-mobile"
|
self.pandora_api_model = "text-davinci-002-render-sha-mobile"
|
||||||
else:
|
else:
|
||||||
|
@ -155,24 +155,22 @@ class Bot:
|
||||||
self.goon_prog = re.compile(r"^\s*!goon\s*.*$")
|
self.goon_prog = re.compile(r"^\s*!goon\s*.*$")
|
||||||
self.new_prog = re.compile(r"^\s*!new\s*.*$")
|
self.new_prog = re.compile(r"^\s*!new\s*.*$")
|
||||||
|
|
||||||
|
self.pandora_data = {}
|
||||||
|
|
||||||
# close session
|
# close session
|
||||||
def __del__(self) -> None:
|
def __del__(self) -> None:
|
||||||
self.driver.disconnect()
|
self.driver.disconnect()
|
||||||
|
|
||||||
async def __aenter__(self):
|
|
||||||
return self
|
|
||||||
|
|
||||||
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
||||||
await self.session.close()
|
|
||||||
|
|
||||||
def login(self) -> None:
|
def login(self) -> None:
|
||||||
self.driver.login()
|
self.driver.login()
|
||||||
|
|
||||||
def pandora_init(self) -> None:
|
def pandora_init(self, user_id: str) -> None:
|
||||||
self.conversation_id = None
|
self.pandora_data[user_id] = {
|
||||||
self.parent_message_id = str(uuid.uuid4())
|
"conversation_id": None,
|
||||||
self.first_time = True
|
"parent_message_id": str(uuid.uuid4()),
|
||||||
|
"first_time": True
|
||||||
|
}
|
||||||
|
|
||||||
async def run(self) -> None:
|
async def run(self) -> None:
|
||||||
await self.driver.init_websocket(self.websocket_handler)
|
await self.driver.init_websocket(self.websocket_handler)
|
||||||
|
|
||||||
|
@ -190,6 +188,9 @@ class Bot:
|
||||||
sender_name = response["data"]["sender_name"]
|
sender_name = response["data"]["sender_name"]
|
||||||
raw_message = raw_data_dict["message"]
|
raw_message = raw_data_dict["message"]
|
||||||
|
|
||||||
|
if user_id not in self.pandora_data:
|
||||||
|
self.pandora_init(user_id)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
asyncio.create_task(
|
asyncio.create_task(
|
||||||
self.message_callback(
|
self.message_callback(
|
||||||
|
@ -250,32 +251,32 @@ class Bot:
|
||||||
if self.talk_prog.match(message):
|
if self.talk_prog.match(message):
|
||||||
prompt = self.talk_prog.match(message).group(1)
|
prompt = self.talk_prog.match(message).group(1)
|
||||||
try:
|
try:
|
||||||
if self.conversation_id is not None:
|
if self.pandora_data[user_id]["conversation_id"] is not None:
|
||||||
data = {
|
data = {
|
||||||
"prompt": prompt,
|
"prompt": prompt,
|
||||||
"model": self.pandora_api_model,
|
"model": self.pandora_api_model,
|
||||||
"parent_message_id": self.parent_message_id,
|
"parent_message_id": self.pandora_data[user_id]["parent_message_id"],
|
||||||
"conversation_id": self.conversation_id,
|
"conversation_id": self.pandora_data[user_id]["conversation_id"],
|
||||||
"stream": False,
|
"stream": False,
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
data = {
|
data = {
|
||||||
"prompt": prompt,
|
"prompt": prompt,
|
||||||
"model": self.pandora_api_model,
|
"model": self.pandora_api_model,
|
||||||
"parent_message_id": self.parent_message_id,
|
"parent_message_id": self.pandora_data[user_id]["parent_message_id"],
|
||||||
"stream": False,
|
"stream": False,
|
||||||
}
|
}
|
||||||
response = await self.pandora.talk(data)
|
response = await self.pandora.talk(data)
|
||||||
self.conversation_id = response['conversation_id']
|
self.pandora_data[user_id]["conversation_id"] = response['conversation_id']
|
||||||
self.parent_message_id = response['message']['id']
|
self.pandora_data[user_id]["parent_message_id"] = response['message']['id']
|
||||||
content = response['message']['content']['parts'][0]
|
content = response['message']['content']['parts'][0]
|
||||||
if self.first_time:
|
if self.pandora_data[user_id]["first_time"]:
|
||||||
self.first_time = False
|
self.pandora_data[user_id]["first_time"] = False
|
||||||
data = {
|
data = {
|
||||||
"model": self.pandora_api_model,
|
"model": self.pandora_api_model,
|
||||||
"message_id": self.parent_message_id,
|
"message_id": self.pandora_data[user_id]["parent_message_id"],
|
||||||
}
|
}
|
||||||
await self.pandora.gen_title(data, self.conversation_id)
|
await self.pandora.gen_title(data, self.pandora_data[user_id]["conversation_id"])
|
||||||
|
|
||||||
await asyncio.to_thread(
|
await asyncio.to_thread(
|
||||||
self.send_message, channel_id, f"{content}"
|
self.send_message, channel_id, f"{content}"
|
||||||
|
@ -285,17 +286,17 @@ class Bot:
|
||||||
raise Exception(e)
|
raise Exception(e)
|
||||||
|
|
||||||
# !goon command trigger handler
|
# !goon command trigger handler
|
||||||
if self.goon_prog.match(message) and self.conversation_id is not None:
|
if self.goon_prog.match(message) and self.pandora_data[user_id]["conversation_id"] is not None:
|
||||||
try:
|
try:
|
||||||
data = {
|
data = {
|
||||||
"model": self.pandora_api_model,
|
"model": self.pandora_api_model,
|
||||||
"parent_message_id": self.parent_message_id,
|
"parent_message_id": self.pandora_data[user_id]["parent_message_id"],
|
||||||
"conversation_id": self.conversation_id,
|
"conversation_id": self.pandora_data[user_id]["conversation_id"],
|
||||||
"stream": False,
|
"stream": False,
|
||||||
}
|
}
|
||||||
response = await self.pandora.goon(data)
|
response = await self.pandora.goon(data)
|
||||||
self.conversation_id = response['conversation_id']
|
self.pandora_data[user_id]["conversation_id"] = response['conversation_id']
|
||||||
self.parent_message_id = response['message']['id']
|
self.pandora_data[user_id]["parent_message_id"] = response['message']['id']
|
||||||
content = response['message']['content']['parts'][0]
|
content = response['message']['content']['parts'][0]
|
||||||
await asyncio.to_thread(
|
await asyncio.to_thread(
|
||||||
self.send_message, channel_id, f"{content}"
|
self.send_message, channel_id, f"{content}"
|
||||||
|
@ -306,7 +307,13 @@ class Bot:
|
||||||
|
|
||||||
# !new command trigger handler
|
# !new command trigger handler
|
||||||
if self.new_prog.match(message):
|
if self.new_prog.match(message):
|
||||||
self.pandora_init()
|
self.pandora_init(user_id)
|
||||||
|
try:
|
||||||
|
await asyncio.to_thread(
|
||||||
|
self.send_message, channel_id, "New conversation created, please use !talk to start chatting!"
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
if self.bard_token is not None:
|
if self.bard_token is not None:
|
||||||
# !bard command trigger handler
|
# !bard command trigger handler
|
||||||
|
|
54
compose.yaml
54
compose.yaml
|
@ -1,23 +1,33 @@
|
||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
image: ghcr.io/hibobmaster/mattermost_bot:latest
|
image: ghcr.io/hibobmaster/mattermost_bot:latest
|
||||||
container_name: mattermost_bot
|
container_name: mattermost_bot
|
||||||
restart: always
|
restart: unless-stopped
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
# volumes:
|
# volumes:
|
||||||
# use env file or config.json
|
# use env file or config.json
|
||||||
# - ./config.json:/app/config.json
|
# - ./config.json:/app/config.json
|
||||||
networks:
|
networks:
|
||||||
- mattermost_network
|
- mattermost_network
|
||||||
|
|
||||||
# api:
|
# api:
|
||||||
# image: hibobmaster/node-chatgpt-api:latest
|
# image: hibobmaster/node-chatgpt-api:latest
|
||||||
# container_name: node-chatgpt-api
|
# container_name: node-chatgpt-api
|
||||||
# volumes:
|
# volumes:
|
||||||
# - ./settings.js:/var/chatgpt-api/settings.js
|
# - ./settings.js:/var/chatgpt-api/settings.js
|
||||||
# networks:
|
# networks:
|
||||||
# - mattermost_network
|
# - mattermost_network
|
||||||
|
|
||||||
networks:
|
# pandora:
|
||||||
|
# image: pengzhile/pandora
|
||||||
|
# container_name: pandora
|
||||||
|
# restart: unless-stopped
|
||||||
|
# environment:
|
||||||
|
# - PANDORA_ACCESS_TOKEN="xxxxxxxxxxxxxx"
|
||||||
|
# - PANDORA_SERVER="0.0.0.0:8008"
|
||||||
|
# networks:
|
||||||
|
# - mattermost_network
|
||||||
|
|
||||||
|
networks:
|
||||||
mattermost_network:
|
mattermost_network:
|
2
main.py
2
main.py
|
@ -3,7 +3,6 @@ import json
|
||||||
import os
|
import os
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
async def main():
|
||||||
if os.path.exists("config.json"):
|
if os.path.exists("config.json"):
|
||||||
fp = open("config.json", "r", encoding="utf-8")
|
fp = open("config.json", "r", encoding="utf-8")
|
||||||
|
@ -51,3 +50,4 @@ async def main():
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
asyncio.run(main())
|
asyncio.run(main())
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,9 @@ import uuid
|
||||||
import aiohttp
|
import aiohttp
|
||||||
import asyncio
|
import asyncio
|
||||||
class Pandora:
|
class Pandora:
|
||||||
def __init__(self, api_endpoint: str) -> None:
|
def __init__(self, api_endpoint: str, clientSession: aiohttp.ClientSession) -> None:
|
||||||
self.api_endpoint = api_endpoint.rstrip('/')
|
self.api_endpoint = api_endpoint.rstrip('/')
|
||||||
self.session = aiohttp.ClientSession()
|
self.session = clientSession
|
||||||
|
|
||||||
async def __aenter__(self):
|
async def __aenter__(self):
|
||||||
return self
|
return self
|
||||||
|
|
Loading…
Reference in a new issue