Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

109 lines
4.9KB

  1. # encoding:utf-8
  2. from bot.bot import Bot
  3. from bot.openai.open_ai_image import OpenAIImage
  4. from bot.openai.open_ai_session import OpenAISession
  5. from bot.session_manager import SessionManager
  6. from bridge.context import ContextType
  7. from bridge.reply import Reply, ReplyType
  8. from config import conf
  9. from common.log import logger
  10. import openai
  11. import openai.error
  12. import time
  13. user_session = dict()
  14. # OpenAI对话模型API (可用)
  15. class OpenAIBot(Bot, OpenAIImage):
  16. def __init__(self):
  17. super().__init__()
  18. openai.api_key = conf().get('open_ai_api_key')
  19. if conf().get('open_ai_api_base'):
  20. openai.api_base = conf().get('open_ai_api_base')
  21. proxy = conf().get('proxy')
  22. if proxy:
  23. openai.proxy = proxy
  24. self.sessions = SessionManager(OpenAISession, model= conf().get("model") or "text-davinci-003")
  25. def reply(self, query, context=None):
  26. # acquire reply content
  27. if context and context.type:
  28. if context.type == ContextType.TEXT:
  29. logger.info("[OPEN_AI] query={}".format(query))
  30. session_id = context['session_id']
  31. reply = None
  32. if query == '#清除记忆':
  33. self.sessions.clear_session(session_id)
  34. reply = Reply(ReplyType.INFO, '记忆已清除')
  35. elif query == '#清除所有':
  36. self.sessions.clear_all_session()
  37. reply = Reply(ReplyType.INFO, '所有人记忆已清除')
  38. else:
  39. session = self.sessions.session_query(query, session_id)
  40. new_query = str(session)
  41. logger.debug("[OPEN_AI] session query={}".format(new_query))
  42. total_tokens, completion_tokens, reply_content = self.reply_text(new_query, session_id, 0)
  43. logger.debug("[OPEN_AI] new_query={}, session_id={}, reply_cont={}, completion_tokens={}".format(new_query, session_id, reply_content, completion_tokens))
  44. if total_tokens == 0 :
  45. reply = Reply(ReplyType.ERROR, reply_content)
  46. else:
  47. self.sessions.session_reply(reply_content, session_id, total_tokens)
  48. reply = Reply(ReplyType.TEXT, reply_content)
  49. return reply
  50. elif context.type == ContextType.IMAGE_CREATE:
  51. ok, retstring = self.create_img(query, 0)
  52. reply = None
  53. if ok:
  54. reply = Reply(ReplyType.IMAGE_URL, retstring)
  55. else:
  56. reply = Reply(ReplyType.ERROR, retstring)
  57. return reply
  58. def reply_text(self, query, session_id, retry_count=0):
  59. try:
  60. response = openai.Completion.create(
  61. model= conf().get("model") or "text-davinci-003", # 对话模型的名称
  62. prompt=query,
  63. temperature=0.9, # 值在[0,1]之间,越大表示回复越具有不确定性
  64. max_tokens=1200, # 回复最大的字符数
  65. top_p=1,
  66. frequency_penalty=0.0, # [-2,2]之间,该值越大则更倾向于产生不同的内容
  67. presence_penalty=0.0, # [-2,2]之间,该值越大则更倾向于产生不同的内容
  68. stop=["\n\n\n"]
  69. )
  70. res_content = response.choices[0]['text'].strip().replace('<|endoftext|>', '')
  71. total_tokens = response["usage"]["total_tokens"]
  72. completion_tokens = response["usage"]["completion_tokens"]
  73. logger.info("[OPEN_AI] reply={}".format(res_content))
  74. return total_tokens, completion_tokens, res_content
  75. except Exception as e:
  76. need_retry = retry_count < 2
  77. result = [0,0,"我现在有点累了,等会再来吧"]
  78. if isinstance(e, openai.error.RateLimitError):
  79. logger.warn("[OPEN_AI] RateLimitError: {}".format(e))
  80. result[2] = "提问太快啦,请休息一下再问我吧"
  81. if need_retry:
  82. time.sleep(5)
  83. elif isinstance(e, openai.error.Timeout):
  84. logger.warn("[OPEN_AI] Timeout: {}".format(e))
  85. result[2] = "我没有收到你的消息"
  86. if need_retry:
  87. time.sleep(5)
  88. elif isinstance(e, openai.error.APIConnectionError):
  89. logger.warn("[OPEN_AI] APIConnectionError: {}".format(e))
  90. need_retry = False
  91. result[2] = "我连接不到你的网络"
  92. else:
  93. logger.warn("[OPEN_AI] Exception: {}".format(e))
  94. need_retry = False
  95. self.sessions.clear_session(session_id)
  96. if need_retry:
  97. logger.warn("[OPEN_AI] 第{}次重试".format(retry_count+1))
  98. return self.reply_text(query, session_id, retry_count+1)
  99. else:
  100. return result