feat: refactor image genderation backend
This commit is contained in:
parent
06ccd8c61c
commit
0b20e0ac1a
4 changed files with 51 additions and 29 deletions
14
README.md
14
README.md
|
@ -4,8 +4,8 @@ This is a simple Mattermost Bot that uses OpenAI's GPT API(or self-host models)
|
||||||
|
|
||||||
## Feature
|
## Feature
|
||||||
|
|
||||||
1. Support Openai ChatGPT
|
1. Support official openai api and self host models([LocalAI](https://localai.io/model-compatibility/))
|
||||||
3. ChatGPT web ([pandora](https://github.com/pengzhile/pandora))
|
2. Image Generation with [DALL·E](https://platform.openai.com/docs/api-reference/images/create) or [LocalAI](https://localai.io/features/image-generation/) or [stable-diffusion-webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/API)
|
||||||
## Installation and Setup
|
## Installation and Setup
|
||||||
|
|
||||||
See https://github.com/hibobmaster/mattermost_bot/wiki
|
See https://github.com/hibobmaster/mattermost_bot/wiki
|
||||||
|
@ -21,18 +21,14 @@ docker compose up -d
|
||||||
- `!help` help message
|
- `!help` help message
|
||||||
- `!gpt + [prompt]` generate a one time response from chatGPT
|
- `!gpt + [prompt]` generate a one time response from chatGPT
|
||||||
- `!chat + [prompt]` chat using official chatGPT api with context conversation
|
- `!chat + [prompt]` chat using official chatGPT api with context conversation
|
||||||
- `!pic + [prompt]` generate an image from Bing Image Creator
|
- `!pic + [prompt]` Image generation with DALL·E or LocalAI or stable-diffusion-webui
|
||||||
|
|
||||||
The following commands need pandora http api: https://github.com/pengzhile/pandora/blob/master/doc/wiki_en.md#http-restful-api
|
|
||||||
- `!talk + [prompt]` chat using chatGPT web with context conversation
|
|
||||||
- `!goon` ask chatGPT to complete the missing part from previous conversation
|
|
||||||
- `!new` start a new converstaion
|
- `!new` start a new converstaion
|
||||||
|
|
||||||
## Demo
|
## Demo
|
||||||
Remove support for Bing AI, Google Bard due to technical problems.
|
Remove support for Bing AI, Google Bard due to technical problems.
|
||||||
![demo1](https://i.imgur.com/XRAQB4B.jpg)
|
![gpt command](https://imgur.com/vdT83Ln.jpg)
|
||||||
![demo2](https://i.imgur.com/if72kyH.jpg)
|
![image generation](https://i.imgur.com/GHczfkv.jpg)
|
||||||
![demo3](https://i.imgur.com/GHczfkv.jpg)
|
|
||||||
|
|
||||||
## Thanks
|
## Thanks
|
||||||
<a href="https://jb.gg/OpenSourceSupport" target="_blank">
|
<a href="https://jb.gg/OpenSourceSupport" target="_blank">
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
aiofiles
|
|
||||||
httpx
|
httpx
|
||||||
Pillow
|
Pillow
|
||||||
tiktoken
|
tiktoken
|
||||||
|
|
47
src/bot.py
47
src/bot.py
|
@ -4,9 +4,11 @@ import json
|
||||||
import asyncio
|
import asyncio
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
|
from pathlib import Path
|
||||||
from gptbot import Chatbot
|
from gptbot import Chatbot
|
||||||
from log import getlogger
|
from log import getlogger
|
||||||
import httpx
|
import httpx
|
||||||
|
import imagegen
|
||||||
|
|
||||||
logger = getlogger()
|
logger = getlogger()
|
||||||
|
|
||||||
|
@ -78,6 +80,11 @@ class Bot:
|
||||||
self.image_generation_backend: str = image_generation_backend
|
self.image_generation_backend: str = image_generation_backend
|
||||||
self.timeout = timeout or 120.0
|
self.timeout = timeout or 120.0
|
||||||
|
|
||||||
|
self.base_path = Path(os.path.dirname(__file__)).parent
|
||||||
|
|
||||||
|
if not os.path.exists(self.base_path / "images"):
|
||||||
|
os.mkdir(self.base_path / "images")
|
||||||
|
|
||||||
# httpx session
|
# httpx session
|
||||||
self.httpx_client = httpx.AsyncClient()
|
self.httpx_client = httpx.AsyncClient()
|
||||||
|
|
||||||
|
@ -213,19 +220,35 @@ class Bot:
|
||||||
raise Exception(e)
|
raise Exception(e)
|
||||||
|
|
||||||
# !pic command trigger handler
|
# !pic command trigger handler
|
||||||
|
if self.image_generation_endpoint and self.image_generation_backend:
|
||||||
if self.pic_prog.match(message):
|
if self.pic_prog.match(message):
|
||||||
prompt = self.pic_prog.match(message).group(1)
|
prompt = self.pic_prog.match(message).group(1)
|
||||||
# generate image
|
# generate image
|
||||||
try:
|
try:
|
||||||
links = await self.imagegen.get_images(prompt)
|
# generate image
|
||||||
image_path = await self.imagegen.save_images(links, "images")
|
b64_datas = await imagegen.get_images(
|
||||||
except Exception as e:
|
self.httpx_client,
|
||||||
logger.error(e, exc_info=True)
|
self.image_generation_endpoint,
|
||||||
raise Exception(e)
|
prompt,
|
||||||
|
self.image_generation_backend,
|
||||||
|
timeount=self.timeout,
|
||||||
|
api_key=self.openai_api_key,
|
||||||
|
n=1,
|
||||||
|
size="256x256",
|
||||||
|
)
|
||||||
|
image_path_list = await asyncio.to_thread(
|
||||||
|
imagegen.save_images,
|
||||||
|
b64_datas,
|
||||||
|
self.base_path / "images",
|
||||||
|
)
|
||||||
# send image
|
# send image
|
||||||
try:
|
for image_path in image_path_list:
|
||||||
await self.send_file(channel_id, prompt, image_path)
|
await self.send_file(
|
||||||
|
channel_id,
|
||||||
|
f"{prompt}",
|
||||||
|
image_path,
|
||||||
|
root_id,
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(e, exc_info=True)
|
logger.error(e, exc_info=True)
|
||||||
raise Exception(e)
|
raise Exception(e)
|
||||||
|
@ -248,7 +271,9 @@ class Bot:
|
||||||
)
|
)
|
||||||
|
|
||||||
# send file to room
|
# send file to room
|
||||||
async def send_file(self, channel_id: str, message: str, filepath: str) -> None:
|
async def send_file(
|
||||||
|
self, channel_id: str, message: str, filepath: str, root_id: str
|
||||||
|
) -> None:
|
||||||
filename = os.path.split(filepath)[-1]
|
filename = os.path.split(filepath)[-1]
|
||||||
try:
|
try:
|
||||||
file_id = await self.driver.files.upload_file(
|
file_id = await self.driver.files.upload_file(
|
||||||
|
@ -256,7 +281,8 @@ class Bot:
|
||||||
files={
|
files={
|
||||||
"files": (filename, open(filepath, "rb")),
|
"files": (filename, open(filepath, "rb")),
|
||||||
},
|
},
|
||||||
)["file_infos"][0]["id"]
|
)
|
||||||
|
file_id = file_id["file_infos"][0]["id"]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(e, exc_info=True)
|
logger.error(e, exc_info=True)
|
||||||
raise Exception(e)
|
raise Exception(e)
|
||||||
|
@ -267,6 +293,7 @@ class Bot:
|
||||||
"channel_id": channel_id,
|
"channel_id": channel_id,
|
||||||
"message": message,
|
"message": message,
|
||||||
"file_ids": [file_id],
|
"file_ids": [file_id],
|
||||||
|
"root_id": root_id,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
# remove image after posting
|
# remove image after posting
|
||||||
|
|
|
@ -15,7 +15,7 @@ async def get_images(
|
||||||
url,
|
url,
|
||||||
headers={
|
headers={
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"Authorization": "Bearer " + kwargs.get("api_key"),
|
"Authorization": f"Bearer {kwargs.get('api_key')}",
|
||||||
},
|
},
|
||||||
json={
|
json={
|
||||||
"prompt": prompt,
|
"prompt": prompt,
|
||||||
|
|
Loading…
Reference in a new issue