dingtalk / main.py
qgyd2021's picture
update
7331450
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import argparse
import logging
import os
import platform
import re
import string
from typing import List, Tuple
from project_settings import project_path
os.environ["HUGGINGFACE_HUB_CACHE"] = (project_path / "cache/huggingface/hub").as_posix()
logging.basicConfig(
level=logging.INFO if platform.system() == "Windows" else logging.INFO,
format="%(asctime)s %(levelname)s %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
logger = logging.getLogger(__name__)
import dingtalk_stream
from dingtalk_stream import AckMessage
import gradio as gr
from threading import Thread
import torch
from transformers.models.gpt2.modeling_gpt2 import GPT2LMHeadModel
from transformers.models.bert.tokenization_bert import BertTokenizer
from project_settings import environment
def get_args():
parser = argparse.ArgumentParser()
parser.add_argument(
"--client_id",
default=environment.get("client_id"),
type=str,
)
parser.add_argument(
"--client_secret",
default=environment.get("client_secret"),
type=str,
)
parser.add_argument(
"--model_name",
default=(project_path / "trained_models/lib_service_4chan").as_posix() if platform.system() == "Windows" else "qgyd2021/lip_service_4chan",
type=str,
)
parser.add_argument(
"--dingtalk_develop_md_file",
default="dingtalk_develop.md",
type=str,
)
args = parser.parse_args()
return args
class LipService4ChanHandler(dingtalk_stream.ChatbotHandler):
def __init__(self,
model_name: str = "qgyd2021/lip_service_4chan",
max_input_len: int = 512,
max_new_tokens: int = 512,
top_p: float = 0.9,
temperature: float = 0.35,
repetition_penalty: float = 1.0,
device: str = "cuda" if torch.cuda.is_available() else "cpu",
):
super(LipService4ChanHandler, self).__init__()
self.model_name = model_name
self.max_input_len = max_input_len
self.max_new_tokens = max_new_tokens
self.top_p = top_p
self.temperature = temperature
self.repetition_penalty = repetition_penalty
self.device = device
tokenizer = BertTokenizer.from_pretrained(model_name)
model = GPT2LMHeadModel.from_pretrained(model_name)
model = model.eval()
self.model = model
self.tokenizer = tokenizer
async def process(self, callback: dingtalk_stream.CallbackMessage):
incoming_message = dingtalk_stream.ChatbotMessage.from_dict(callback.data)
text = incoming_message.text.content.strip()
logger.info("incoming message: {};".format(text))
answer = self.get_answer(text)
self.reply_text(answer, incoming_message)
logger.info("incoming message: {}; reply text: {};".format(text, answer))
return AckMessage.STATUS_OK, "OK"
@staticmethod
def remove_space_between_cn_en(text: str):
splits = re.split(" ", text)
if len(splits) < 2:
return text
result = ""
for t in splits:
if t == "":
continue
if re.search(f"[a-zA-Z0-9{string.punctuation}]$", result) and re.search("^[a-zA-Z0-9]", t):
result += " "
result += t
else:
if not result == "":
result += t
else:
result = t
if text.endswith(" "):
result += " "
return result
def get_answer(self, text: str):
prompt_encoded = self.tokenizer.__call__(text, add_special_tokens=True)
input_ids: List[int] = prompt_encoded["input_ids"]
input_ids = torch.tensor([input_ids], dtype=torch.long)
input_ids = input_ids[:, -self.max_input_len:]
self.tokenizer.eos_token = self.tokenizer.sep_token
self.tokenizer.eos_token_id = self.tokenizer.sep_token_id
# generate
with torch.no_grad():
outputs = self.model.generate(
input_ids=input_ids,
max_new_tokens=self.max_new_tokens,
do_sample=True,
top_p=self.top_p,
temperature=self.temperature,
repetition_penalty=self.repetition_penalty,
eos_token_id=self.tokenizer.sep_token_id,
pad_token_id=self.tokenizer.pad_token_id,
)
outputs = outputs.tolist()[0][len(input_ids[0]):]
answer = self.tokenizer.decode(outputs)
answer = answer.strip().replace(self.tokenizer.eos_token, "").strip()
answer = self.remove_space_between_cn_en(answer)
return answer
def dingtalk_server(client: dingtalk_stream.DingTalkStreamClient):
client.start_forever()
def main():
args = get_args()
# ding talk
credential = dingtalk_stream.Credential(
client_id=args.client_id,
client_secret=args.client_secret,
)
client = dingtalk_stream.DingTalkStreamClient(credential, logger)
client.register_callback_handler(
dingtalk_stream.chatbot.ChatbotMessage.TOPIC,
LipService4ChanHandler(
model_name=args.model_name
)
)
# client.start_forever()
# background task
thread = Thread(target=dingtalk_server, kwargs={"client": client})
thread.start()
with open(args.dingtalk_develop_md_file, "r", encoding="utf-8") as f:
dingtalk_develop_md = f.read()
# ui
with gr.Blocks() as blocks:
gr.Markdown(value=dingtalk_develop_md)
blocks.queue().launch(
share=False if platform.system() == "Windows" else False,
server_name="127.0.0.1" if platform.system() == "Windows" else "0.0.0.0",
server_port=7860
)
return
if __name__ == '__main__':
main()