Skip to content

Commit

Permalink
feat: support azure openai service (#62)
Browse files Browse the repository at this point in the history
  • Loading branch information
iuiaoin committed Jul 20, 2023
1 parent 5ab7426 commit 09899d1
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 20 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ Then fill in the configuration in `config.json`, the following is the descriptio
{
"openai_api_key": "YOUR API SECRET KEY", # Fill in your OpenAI API Key
"model": "gpt-3.5-turbo", # ID of the model to use, support gpt-3.5-turbo, gpt-4, gpt-4-32k etc.
"use_azure_chatgpt": false, # Whether use Azure OpenAI API
"azure_deployment_id": "", # Azure model deployment name
"role_desc": "You are a helpful assistant.", # Role description as system prompt
"session_expired_duration": 3600, # Session memory kept duration
"max_tokens": 1000, # Max tokens of characters for session memory
Expand Down
2 changes: 2 additions & 0 deletions README_ZH.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ pip install -r requirements.txt
{
"openai_api_key": "YOUR API SECRET KEY", # 填入你的 OpenAI API Key
"model": "gpt-3.5-turbo", # 要使用的模型 ID, 支持 gpt-3.5-turbo, gpt-4, gpt-4-32k 等
"use_azure_chatgpt": false, # 是否使用 Azure OpenAI API
"azure_deployment_id": "", # Azure 模型部署名称
"role_desc": "You are a helpful assistant.", # 角色描述, 作为系统 prompt
"session_expired_duration": 3600, # 对话记忆的保留时长
"max_tokens": 1000, # 对话记忆字符的最大 token 数量
Expand Down
11 changes: 11 additions & 0 deletions bot/azure_chatgpt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import openai
from bot.chatgpt import ChatGPTBot
from config import conf


class AzureChatGPTBot(ChatGPTBot):
def __init__(self):
super().__init__()
openai.api_type = "azure"
openai.api_version = "2023-06-01-preview"
self.args["deployment_id"] = conf().get("azure_deployment_id")
21 changes: 21 additions & 0 deletions bot/bot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from common.context import Context
from config import conf
from common.singleton import singleton
from common.reply import Reply


@singleton
class Bot:
def __init__(self):
use_azure_chatgpt = conf().get("use_azure_chatgpt", False)
if use_azure_chatgpt:
from bot.azure_chatgpt import AzureChatGPTBot

self.bot = AzureChatGPTBot()
else:
from bot.chatgpt import ChatGPTBot

self.bot = ChatGPTBot()

def reply(self, context: Context) -> Reply:
return self.bot.reply(context)
34 changes: 17 additions & 17 deletions bot/chatgpt.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import openai
from config import conf
from common.singleton import singleton
from utils.log import logger
from common.session import Session
from common.reply import Reply, ReplyType
from common.context import ContextType, Context


@singleton
class ChatGPTBot:
def __init__(self):
openai.api_key = conf().get("openai_api_key")
Expand All @@ -17,45 +15,47 @@ def __init__(self):
openai.api_base = api_base
if proxy:
openai.proxy = proxy
self.name = self.__class__.__name__
self.args = {
"model": conf().get("model"),
"temperature": conf().get("temperature"),
}

def reply(self, context: Context):
def reply(self, context: Context) -> Reply:
query = context.query
logger.info(f"[ChatGPT] Query={query}")
logger.info(f"[{self.name}] Query={query}")
if context.type == ContextType.CREATE_IMAGE:
return self.reply_img(query)
else:
session_id = context.session_id
session = Session.build_session_query(context)
response = self.reply_text(session)
logger.info(f"[ChatGPT] Response={response['content']}")
logger.info(f"[{self.name}] Response={response['content']}")
if response["completion_tokens"] > 0:
Session.save_session(
response["content"], session_id, response["total_tokens"]
)
return Reply(ReplyType.TEXT, response["content"])

def reply_img(self, query):
def reply_img(self, query) -> Reply:
create_image_size = conf().get("create_image_size", "256x256")
try:
response = openai.Image.create(prompt=query, n=1, size=create_image_size)
image_url = response["data"][0]["url"]
logger.info(f"[ChatGPT] Image={image_url}")
logger.info(f"[{self.name}] Image={image_url}")
return Reply(ReplyType.IMAGE, image_url)
except Exception as e:
logger.error(f"[ChatGPT] Create image failed: {e}")
logger.error(f"[{self.name}] Create image failed: {e}")
return Reply(ReplyType.TEXT, "Image created failed")

def reply_text(self, session):
model = conf().get("model")
temperature = conf().get("temperature")
try:
response = openai.ChatCompletion.create(
model=model,
messages=session,
temperature=temperature,
top_p=1.0,
frequency_penalty=0.0,
presence_penalty=0.0,
**self.args,
)
return {
"total_tokens": response["usage"]["total_tokens"],
Expand All @@ -65,18 +65,18 @@ def reply_text(self, session):
except Exception as e:
result = {"completion_tokens": 0, "content": "Please ask me again"}
if isinstance(e, openai.error.RateLimitError):
logger.warn(f"[ChatGPT] RateLimitError: {e}")
logger.warn(f"[{self.name}] RateLimitError: {e}")
result["content"] = "Ask too frequently, please try again in 20s"
elif isinstance(e, openai.error.APIConnectionError):
logger.warn(f"[ChatGPT] APIConnectionError: {e}")
logger.warn(f"[{self.name}] APIConnectionError: {e}")
result[
"content"
] = "I cannot connect the server, please check the network and try again"
elif isinstance(e, openai.error.Timeout):
logger.warn(f"[ChatGPT] Timeout: {e}")
logger.warn(f"[{self.name}] Timeout: {e}")
result["content"] = "I didn't receive your message, please try again"
elif isinstance(e, openai.error.APIError):
logger.warn(f"[ChatGPT] APIError: {e}")
logger.warn(f"[{self.name}] APIError: {e}")
else:
logger.exception(f"[ChatGPT] Exception: {e}")
logger.exception(f"[{self.name}] Exception: {e}")
return result
4 changes: 2 additions & 2 deletions channel/wechat.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from utils.log import logger
from utils import const
import os
from bot.chatgpt import ChatGPTBot
from bot.bot import Bot
from common.singleton import singleton
from config import conf
from utils.check import check_prefix, is_wx_account
Expand Down Expand Up @@ -144,7 +144,7 @@ def handle_reply(self, msg: Message, context: Context):
if e1.is_bypass:
return self.send(e1.reply, e1.message)

reply = ChatGPTBot().reply(e1.context)
reply = Bot().reply(e1.context)

e2 = PluginManager().emit(
Event(
Expand Down
2 changes: 2 additions & 0 deletions config.template.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"openai_api_key": "YOUR API SECRET KEY",
"model": "gpt-3.5-turbo",
"use_azure_chatgpt": false,
"azure_deployment_id": "",
"role_desc": "You are a helpful assistant.",
"session_expired_duration": 3600,
"max_tokens": 1000,
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ pyfiglet==0.8.post1
requests==2.28.1
termcolor==2.1.1
websocket_client==1.5.1
openai==0.27.2
openai==0.27.8
pydantic==2.0.2
dulwich==0.21.5

0 comments on commit 09899d1

Please sign in to comment.