From 3c9b1a14e9fa5f4bdf5f7f36c737b2670752f00f Mon Sep 17 00:00:00 2001 From: resphinas <2934218525@qq.com> Date: Mon, 28 Aug 2023 16:43:26 +0800 Subject: [PATCH 01/17] claude bot update --- chatgpt-on-wechat | 1 + 1 file changed, 1 insertion(+) create mode 160000 chatgpt-on-wechat diff --git a/chatgpt-on-wechat b/chatgpt-on-wechat new file mode 160000 index 000000000..827e8eddf --- /dev/null +++ b/chatgpt-on-wechat @@ -0,0 +1 @@ +Subproject commit 827e8eddf87b73f310464e3d6c0509e5b6e2ba67 From f98b43514e03fa571bd071e4324e0a55815035a7 Mon Sep 17 00:00:00 2001 From: resphinas <2934218525@qq.com> Date: Mon, 28 Aug 2023 17:18:00 +0800 Subject: [PATCH 02/17] claude_bot --- bot/bot_factory.py | 4 + bot/chatgpt/chat_gpt_bot.py | 4 + bot/claude/claude_ai_bot.py | 229 ++++++++++++++++++++++++ bridge/bridge.py | 2 + chatgpt-on-wechat | 1 - chatgpt-on-wechat-master.iml | 12 ++ common/const.py | 5 +- common/log.py | 4 +- config-template.json | 7 +- config.py | 4 +- lib/itchat/async_components/messages.py | 4 + lib/itchat/components/messages.py | 1 + requirements.txt | 4 + 13 files changed, 274 insertions(+), 7 deletions(-) create mode 100644 bot/claude/claude_ai_bot.py delete mode 160000 chatgpt-on-wechat create mode 100644 chatgpt-on-wechat-master.iml diff --git a/bot/bot_factory.py b/bot/bot_factory.py index 513eb7868..da12f952d 100644 --- a/bot/bot_factory.py +++ b/bot/bot_factory.py @@ -39,4 +39,8 @@ def create_bot(bot_type): elif bot_type == const.LINKAI: from bot.linkai.link_ai_bot import LinkAIBot return LinkAIBot() + + elif bot_type == const.CLAUDEAI: + from bot.claude.claude_ai_bot import ClaudeAIBot + return ClaudeAIBot() raise RuntimeError diff --git a/bot/chatgpt/chat_gpt_bot.py b/bot/chatgpt/chat_gpt_bot.py index 8c9a2504a..00f83e803 100644 --- a/bot/chatgpt/chat_gpt_bot.py +++ b/bot/chatgpt/chat_gpt_bot.py @@ -106,6 +106,10 @@ def reply(self, query, context=None): reply = Reply(ReplyType.ERROR, "Bot不支持处理{}类型的消息".format(context.type)) return reply +<<<<<<< 827e8eddf87b73f310464e3d6c0509e5b6e2ba67 +======= + +>>>>>>> claude bot def reply_text(self, session: ChatGPTSession, api_key=None, args=None, retry_count=0) -> dict: """ call openai's ChatCompletion to get the answer diff --git a/bot/claude/claude_ai_bot.py b/bot/claude/claude_ai_bot.py new file mode 100644 index 000000000..bb1cbd8fb --- /dev/null +++ b/bot/claude/claude_ai_bot.py @@ -0,0 +1,229 @@ +import re +import time +import json +import uuid + +from curl_cffi import requests +from bot.bot import Bot +from bot.chatgpt.chat_gpt_session import ChatGPTSession +from bot.openai.open_ai_image import OpenAIImage +from bot.session_manager import SessionManager +from bridge.context import Context, ContextType +from bridge.reply import Reply, ReplyType +from common.log import logger +from config import conf + + +class ClaudeAIBot(Bot, OpenAIImage): + # authentication failed + AUTH_FAILED_CODE = 401 + NO_QUOTA_CODE = 406 + + def __init__(self): + super().__init__() + self.sessions = SessionManager(ChatGPTSession, model=conf().get("model") or "gpt-3.5-turbo") + self.claude_api_cookie = conf().get("claude_api_cookie") + self.proxy = conf().get("proxy") + self.proxies = { + "http": self.proxy, + "https": self.proxy + } + self.org_uuid = self.get_organization_id() + self.con_uuid = None + self.get_uuid() + + + + + def generate_uuid(self): + random_uuid = uuid.uuid4() + random_uuid_str = str(random_uuid) + formatted_uuid = f"{random_uuid_str[0:8]}-{random_uuid_str[9:13]}-{random_uuid_str[14:18]}-{random_uuid_str[19:23]}-{random_uuid_str[24:]}" + return formatted_uuid + + def get_uuid(self): + if conf().get("claude_uuid") != None: + self.con_uuid = conf().get("claude_uuid") + else: + self.con_uuid = self.generate_uuid() + self.create_new_chat() + + + + def get_organization_id(self): + url = "https://claude.ai/api/organizations" + + headers = { + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0', + 'Accept-Language': 'en-US,en;q=0.5', + 'Referer': 'https://claude.ai/chats', + 'Content-Type': 'application/json', + 'Sec-Fetch-Dest': 'empty', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Site': 'same-origin', + 'Connection': 'keep-alive', + 'Cookie': f'{self.claude_api_cookie}' + } + + response = requests.get(url, headers=headers,impersonate="chrome110",proxies=self.proxies) + res = json.loads(response.text) + uuid = res[0]['uuid'] + + return uuid + def reply(self, query, context: Context = None) -> Reply: + if context.type == ContextType.TEXT: + return self._chat(query, context) + elif context.type == ContextType.IMAGE_CREATE: + ok, res = self.create_img(query, 0) + if ok: + reply = Reply(ReplyType.IMAGE_URL, res) + else: + reply = Reply(ReplyType.ERROR, res) + return reply + else: + reply = Reply(ReplyType.ERROR, "Bot不支持处理{}类型的消息".format(context.type)) + return reply + + def get_organization_id(self): + url = "https://claude.ai/api/organizations" + + headers = { + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0', + 'Accept-Language': 'en-US,en;q=0.5', + 'Referer': 'https://claude.ai/chats', + 'Content-Type': 'application/json', + 'Sec-Fetch-Dest': 'empty', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Site': 'same-origin', + 'Connection': 'keep-alive', + 'Cookie': f'{self.claude_api_cookie}' + } + try: + response = requests.get(url, headers=headers,impersonate="chrome110",proxies =self.proxies ) + res = json.loads(response.text) + uuid = res[0]['uuid'] + except: + print(response.text) + + return uuid + def create_new_chat(self): + url = f"https://claude.ai/api/organizations/{self.org_uuid}/chat_conversations" + + payload = json.dumps({"uuid": self.con_uuid, "name": ""}) + headers = { + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0', + 'Accept-Language': 'en-US,en;q=0.5', + 'Referer': 'https://claude.ai/chats', + 'Content-Type': 'application/json', + 'Origin': 'https://claude.ai', + 'DNT': '1', + 'Connection': 'keep-alive', + 'Cookie': self.claude_api_cookie, + 'Sec-Fetch-Dest': 'empty', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Site': 'same-origin', + 'TE': 'trailers' + } + + response = requests.post( url, headers=headers, data=payload,impersonate="chrome110", proxies= self.proxies) + + # Returns JSON of the newly created conversation information + return response.json() + def _chat(self, query, context, retry_count=0) -> Reply: + """ + 发起对话请求 + :param query: 请求提示词 + :param context: 对话上下文 + :param retry_count: 当前递归重试次数 + :return: 回复 + """ + if retry_count >= 2: + # exit from retry 2 times + logger.warn("[CLAUDEAI] failed after maximum number of retry times") + return Reply(ReplyType.ERROR, "请再问我一次吧") + + try: + + session_id = context["session_id"] + session = self.sessions.session_query(query, session_id) + model = conf().get("model") or "gpt-3.5-turbo" + # remove system message + if session.messages[0].get("role") == "system": + if model == "wenxin": + session.messages.pop(0) + + + logger.info(f"[CLAUDEAI] query={query}") + + # do http request + base_url = "https://claude.ai" + payload = json.dumps({ + "completion": { + "prompt": f"{query}", + "timezone": "Asia/Kolkata", + "model": "claude-2" + }, + "organization_uuid": f"{self.org_uuid}", + "conversation_uuid": f"{self.con_uuid}", + "text": f"{query}", + "attachments": [] + }) + headers = { + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0', + 'Accept': 'text/event-stream, text/event-stream', + 'Accept-Language': 'en-US,en;q=0.5', + 'Referer': 'https://claude.ai/chats', + 'Content-Type': 'application/json', + 'Origin': 'https://claude.ai', + 'DNT': '1', + 'Connection': 'keep-alive', + 'Cookie': f'{self.claude_api_cookie}', + 'Sec-Fetch-Dest': 'empty', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Site': 'same-origin', + 'TE': 'trailers' + } + + res = requests.post(base_url + "/api/append_message", headers=headers, data=payload,impersonate="chrome110",proxies= self.proxies,timeout=400) + + if res.status_code == 200 or "pemission" in res.text: + # execute success + decoded_data = res.content.decode("utf-8") + decoded_data = re.sub('\n+', '\n', decoded_data).strip() + data_strings = decoded_data.split('\n') + completions = [] + for data_string in data_strings: + json_str = data_string[6:].strip() + data = json.loads(json_str) + if 'completion' in data: + completions.append(data['completion']) + + reply_content = ''.join(completions) + logger.info(f"[CLAUDE] reply={reply_content}, total_tokens=100") + self.sessions.session_reply(reply_content, session_id, 100) + return Reply(ReplyType.TEXT, reply_content) + + else: + response = res.json() + error = response.get("error") + logger.error(f"[CLAUDE] chat failed, status_code={res.status_code}, " + f"msg={error.get('message')}, type={error.get('type')}, detail: {res.text}, uuid: {self.con_uuid}") + + if res.status_code >= 500: + # server error, need retry + time.sleep(2) + logger.warn(f"[CLAUDE] do retry, times={retry_count}") + return self._chat(query, context, retry_count + 1) + + return Reply(ReplyType.ERROR, "提问太快啦,请休息一下再问我吧") + + except Exception as e: + logger.exception(e) + # retry + time.sleep(2) + logger.warn(f"[CLAUDE] do retry, times={retry_count}") + return self._chat(query, context, retry_count + 1) diff --git a/bridge/bridge.py b/bridge/bridge.py index 202243842..4a0ef4f1b 100644 --- a/bridge/bridge.py +++ b/bridge/bridge.py @@ -29,6 +29,8 @@ def __init__(self): self.btype["chat"] = const.XUNFEI if conf().get("use_linkai") and conf().get("linkai_api_key"): self.btype["chat"] = const.LINKAI + if model_type in ["claude"]: + self.btype["chat"] = const.CLAUDEAI self.bots = {} def get_bot(self, typename): diff --git a/chatgpt-on-wechat b/chatgpt-on-wechat deleted file mode 160000 index 827e8eddf..000000000 --- a/chatgpt-on-wechat +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 827e8eddf87b73f310464e3d6c0509e5b6e2ba67 diff --git a/chatgpt-on-wechat-master.iml b/chatgpt-on-wechat-master.iml new file mode 100644 index 000000000..049614af8 --- /dev/null +++ b/chatgpt-on-wechat-master.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/common/const.py b/common/const.py index 505ab71fa..ce3eac45e 100644 --- a/common/const.py +++ b/common/const.py @@ -5,7 +5,8 @@ XUNFEI = "xunfei" CHATGPTONAZURE = "chatGPTOnAzure" LINKAI = "linkai" - VERSION = "1.3.0" - MODEL_LIST = ["gpt-3.5-turbo", "gpt-3.5-turbo-16k", "gpt-4", "wenxin", "xunfei"] +CLAUDEAI = "claude" +VERSION = "1.3.0" +MODEL_LIST = ["gpt-3.5-turbo", "gpt-3.5-turbo-16k", "gpt-4", "wenxin", "xunfei","claude"] diff --git a/common/log.py b/common/log.py index f02a365b7..ac64530e2 100644 --- a/common/log.py +++ b/common/log.py @@ -13,14 +13,14 @@ def _reset_logger(log): console_handle.setFormatter( logging.Formatter( "[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d] - %(message)s", - datefmt="%Y-%m-%d %H:%M:%S", + datefmt="%Y-%m-%claude_ai_bot.py%H:%M:%S", ) ) file_handle = logging.FileHandler("run.log", encoding="utf-8") file_handle.setFormatter( logging.Formatter( "[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d] - %(message)s", - datefmt="%Y-%m-%d %H:%M:%S", + datefmt="%Y-%m-%claude_ai_bot.py%H:%M:%S", ) ) log.addHandler(file_handle) diff --git a/config-template.json b/config-template.json index f01633d61..003fbb670 100644 --- a/config-template.json +++ b/config-template.json @@ -2,8 +2,12 @@ "open_ai_api_key": "YOUR API KEY", "model": "gpt-3.5-turbo", "channel_type": "wx", - "proxy": "", + "proxy": "http://127.0.0.1:33210", "hot_reload": false, + "model": "claude", + "channel_type": "wx", + "claude_api_cookie": "intercom-device-id-lupk8zyo=b37192f8-c3a5-408d-8525-60ad8c2cc57c; sessionKey=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; intercom-session-lupk8zyo=dHBseWhqVVIvVW4vZU1NMWM3eUpTQldjQkUwYUMwQVlGQ3g4azR6RlQ3ZDBkTTRqQWd4aGN6ZmY4MSt4aEVERy0tdXY0OGdnUTdYdVhsYWx3c2ErUFFTdz09--58fbe081d071984de6a196e49d513761e8b806e9; cf_clearance=9R_XpUT12.KKIRtXlXUFng05L_sdc0GDwz55ZBGsZ6o-1693003153-0-1-636ec5eb.e36b35e5.346f9a0b-0.2.1693003153; __cf_bm=TLFZA8a7JhAo6NRLVIL0jYsD8nb4cDna6slscBAns3A-1693004564-0-AfWzEcpZbRjF6cLEjxhPUnA84TNQDNQofUkZCuabIKkmQan+BlCvvYIeZod8ISJ/RLq1URvIsp++UwTDJyKfLI8=", + "hot_reload": true, "single_chat_prefix": [ "bot", "@bot" @@ -14,6 +18,7 @@ ], "group_name_white_list": [ "ChatGPT测试群", + "高中数学应用题", "ChatGPT测试群2" ], "group_chat_in_one_session": [ diff --git a/config.py b/config.py index 5853b0dc8..cb043d14f 100644 --- a/config.py +++ b/config.py @@ -120,7 +120,9 @@ "use_linkai": False, "linkai_api_key": "", "linkai_app_code": "", - "linkai_api_base": "https://api.link-ai.chat" # linkAI服务地址,若国内无法访问或延迟较高可改为 https://api.link-ai.tech + "linkai_api_base": "https://api.link-ai.chat", # linkAI服务地址,若国内无法访问或延迟较高可改为 https://api.link-ai.tech + "claude_api_cookie":"", + "claude_uuid":"" } diff --git a/lib/itchat/async_components/messages.py b/lib/itchat/async_components/messages.py index f842f1f53..20726dd9b 100644 --- a/lib/itchat/async_components/messages.py +++ b/lib/itchat/async_components/messages.py @@ -349,7 +349,11 @@ def upload_chunk_file(core, fileDir, fileSymbol, fileSize, ('id', (None, 'WU_FILE_0')), ('name', (None, fileName)), ('type', (None, fileType)), +<<<<<<< 827e8eddf87b73f310464e3d6c0509e5b6e2ba67 ('lastModifiedDate', (None, time.strftime('%a %b %d %Y %H:%M:%S GMT+0800 (CST)'))), +======= + ('lastModifiedDate', (None, time.strftime('%a %b %claude_ai_bot.py%Y %H:%M:%S GMT+0800 (CST)'))), +>>>>>>> claude bot ('size', (None, str(fileSize))), ('chunks', (None, None)), ('chunk', (None, None)), diff --git a/lib/itchat/components/messages.py b/lib/itchat/components/messages.py index 85c0ca2eb..cdeb6fb15 100644 --- a/lib/itchat/components/messages.py +++ b/lib/itchat/components/messages.py @@ -351,6 +351,7 @@ def upload_chunk_file(core, fileDir, fileSymbol, fileSize, ('name', (None, fileName)), ('type', (None, fileType)), ('lastModifiedDate', (None, time.strftime('%a %b %d %Y %H:%M:%S GMT+0800 (CST)'))), + ('lastModifiedDate', (None, time.strftime('%a %b %claude_ai_bot.py%Y %H:%M:%S GMT+0800 (CST)'))), ('size', (None, str(fileSize))), ('chunks', (None, None)), ('chunk', (None, None)), diff --git a/requirements.txt b/requirements.txt index 086312536..4d5bfe4e0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,3 +7,7 @@ chardet>=5.1.0 Pillow pre-commit web.py +<<<<<<< 827e8eddf87b73f310464e3d6c0509e5b6e2ba67 +======= +curl_cffi +>>>>>>> claude bot From 44cc4165d17e490cdc73440cf0013054b880b03c Mon Sep 17 00:00:00 2001 From: resphinas <2934218525@qq.com> Date: Mon, 28 Aug 2023 17:22:20 +0800 Subject: [PATCH 03/17] claude_bot --- bot/chatgpt/chat_gpt_bot.py | 3 --- common/const.py | 2 ++ lib/itchat/async_components/messages.py | 3 --- requirements.txt | 3 --- 4 files changed, 2 insertions(+), 9 deletions(-) diff --git a/bot/chatgpt/chat_gpt_bot.py b/bot/chatgpt/chat_gpt_bot.py index 00f83e803..88a52f19b 100644 --- a/bot/chatgpt/chat_gpt_bot.py +++ b/bot/chatgpt/chat_gpt_bot.py @@ -106,10 +106,7 @@ def reply(self, query, context=None): reply = Reply(ReplyType.ERROR, "Bot不支持处理{}类型的消息".format(context.type)) return reply -<<<<<<< 827e8eddf87b73f310464e3d6c0509e5b6e2ba67 -======= ->>>>>>> claude bot def reply_text(self, session: ChatGPTSession, api_key=None, args=None, retry_count=0) -> dict: """ call openai's ChatCompletion to get the answer diff --git a/common/const.py b/common/const.py index ce3eac45e..a85fec71d 100644 --- a/common/const.py +++ b/common/const.py @@ -5,7 +5,9 @@ XUNFEI = "xunfei" CHATGPTONAZURE = "chatGPTOnAzure" LINKAI = "linkai" + VERSION = "1.3.0" + MODEL_LIST = ["gpt-3.5-turbo", "gpt-3.5-turbo-16k", "gpt-4", "wenxin", "xunfei"] CLAUDEAI = "claude" VERSION = "1.3.0" diff --git a/lib/itchat/async_components/messages.py b/lib/itchat/async_components/messages.py index 20726dd9b..558889bf4 100644 --- a/lib/itchat/async_components/messages.py +++ b/lib/itchat/async_components/messages.py @@ -349,11 +349,8 @@ def upload_chunk_file(core, fileDir, fileSymbol, fileSize, ('id', (None, 'WU_FILE_0')), ('name', (None, fileName)), ('type', (None, fileType)), -<<<<<<< 827e8eddf87b73f310464e3d6c0509e5b6e2ba67 ('lastModifiedDate', (None, time.strftime('%a %b %d %Y %H:%M:%S GMT+0800 (CST)'))), -======= ('lastModifiedDate', (None, time.strftime('%a %b %claude_ai_bot.py%Y %H:%M:%S GMT+0800 (CST)'))), ->>>>>>> claude bot ('size', (None, str(fileSize))), ('chunks', (None, None)), ('chunk', (None, None)), diff --git a/requirements.txt b/requirements.txt index 4d5bfe4e0..74bc96eb2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,7 +7,4 @@ chardet>=5.1.0 Pillow pre-commit web.py -<<<<<<< 827e8eddf87b73f310464e3d6c0509e5b6e2ba67 -======= curl_cffi ->>>>>>> claude bot From cc3a0fc367d7217d520cb2550b8f9cc2acc08d12 Mon Sep 17 00:00:00 2001 From: resphina <69687075+resphinas@users.noreply.github.com> Date: Mon, 28 Aug 2023 17:28:13 +0800 Subject: [PATCH 04/17] Update config-template.json --- config-template.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/config-template.json b/config-template.json index 003fbb670..6956a24aa 100644 --- a/config-template.json +++ b/config-template.json @@ -2,11 +2,11 @@ "open_ai_api_key": "YOUR API KEY", "model": "gpt-3.5-turbo", "channel_type": "wx", - "proxy": "http://127.0.0.1:33210", + "proxy": ", "hot_reload": false, "model": "claude", "channel_type": "wx", - "claude_api_cookie": "intercom-device-id-lupk8zyo=b37192f8-c3a5-408d-8525-60ad8c2cc57c; sessionKey=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; intercom-session-lupk8zyo=dHBseWhqVVIvVW4vZU1NMWM3eUpTQldjQkUwYUMwQVlGQ3g4azR6RlQ3ZDBkTTRqQWd4aGN6ZmY4MSt4aEVERy0tdXY0OGdnUTdYdVhsYWx3c2ErUFFTdz09--58fbe081d071984de6a196e49d513761e8b806e9; cf_clearance=9R_XpUT12.KKIRtXlXUFng05L_sdc0GDwz55ZBGsZ6o-1693003153-0-1-636ec5eb.e36b35e5.346f9a0b-0.2.1693003153; __cf_bm=TLFZA8a7JhAo6NRLVIL0jYsD8nb4cDna6slscBAns3A-1693004564-0-AfWzEcpZbRjF6cLEjxhPUnA84TNQDNQofUkZCuabIKkmQan+BlCvvYIeZod8ISJ/RLq1URvIsp++UwTDJyKfLI8=", + "claude_api_cookie": "", "hot_reload": true, "single_chat_prefix": [ "bot", @@ -18,7 +18,6 @@ ], "group_name_white_list": [ "ChatGPT测试群", - "高中数学应用题", "ChatGPT测试群2" ], "group_chat_in_one_session": [ From 187601da1e2e0969dd20c5b35fbc13e9688f192e Mon Sep 17 00:00:00 2001 From: resphina <69687075+resphinas@users.noreply.github.com> Date: Mon, 28 Aug 2023 17:30:03 +0800 Subject: [PATCH 05/17] Update config-template.json --- config-template.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-template.json b/config-template.json index 6956a24aa..3af9fbcde 100644 --- a/config-template.json +++ b/config-template.json @@ -2,7 +2,7 @@ "open_ai_api_key": "YOUR API KEY", "model": "gpt-3.5-turbo", "channel_type": "wx", - "proxy": ", + "proxy": "", "hot_reload": false, "model": "claude", "channel_type": "wx", From 8d9d5b7b6ff76de657ead33de5681a912ae09950 Mon Sep 17 00:00:00 2001 From: resphina <69687075+resphinas@users.noreply.github.com> Date: Mon, 28 Aug 2023 17:40:27 +0800 Subject: [PATCH 06/17] Update claude_ai_bot.py --- bot/claude/claude_ai_bot.py | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/bot/claude/claude_ai_bot.py b/bot/claude/claude_ai_bot.py index bb1cbd8fb..71cc97018 100644 --- a/bot/claude/claude_ai_bot.py +++ b/bot/claude/claude_ai_bot.py @@ -2,7 +2,6 @@ import time import json import uuid - from curl_cffi import requests from bot.bot import Bot from bot.chatgpt.chat_gpt_session import ChatGPTSession @@ -15,10 +14,6 @@ class ClaudeAIBot(Bot, OpenAIImage): - # authentication failed - AUTH_FAILED_CODE = 401 - NO_QUOTA_CODE = 406 - def __init__(self): super().__init__() self.sessions = SessionManager(ChatGPTSession, model=conf().get("model") or "gpt-3.5-turbo") @@ -32,9 +27,6 @@ def __init__(self): self.con_uuid = None self.get_uuid() - - - def generate_uuid(self): random_uuid = uuid.uuid4() random_uuid_str = str(random_uuid) @@ -48,11 +40,8 @@ def get_uuid(self): self.con_uuid = self.generate_uuid() self.create_new_chat() - - def get_organization_id(self): url = "https://claude.ai/api/organizations" - headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0', @@ -65,12 +54,11 @@ def get_organization_id(self): 'Connection': 'keep-alive', 'Cookie': f'{self.claude_api_cookie}' } - response = requests.get(url, headers=headers,impersonate="chrome110",proxies=self.proxies) res = json.loads(response.text) uuid = res[0]['uuid'] - return uuid + def reply(self, query, context: Context = None) -> Reply: if context.type == ContextType.TEXT: return self._chat(query, context) @@ -108,9 +96,9 @@ def get_organization_id(self): print(response.text) return uuid + def create_new_chat(self): url = f"https://claude.ai/api/organizations/{self.org_uuid}/chat_conversations" - payload = json.dumps({"uuid": self.con_uuid, "name": ""}) headers = { 'User-Agent': @@ -127,11 +115,10 @@ def create_new_chat(self): 'Sec-Fetch-Site': 'same-origin', 'TE': 'trailers' } - response = requests.post( url, headers=headers, data=payload,impersonate="chrome110", proxies= self.proxies) - # Returns JSON of the newly created conversation information return response.json() + def _chat(self, query, context, retry_count=0) -> Reply: """ 发起对话请求 @@ -146,7 +133,6 @@ def _chat(self, query, context, retry_count=0) -> Reply: return Reply(ReplyType.ERROR, "请再问我一次吧") try: - session_id = context["session_id"] session = self.sessions.session_query(query, session_id) model = conf().get("model") or "gpt-3.5-turbo" @@ -154,8 +140,6 @@ def _chat(self, query, context, retry_count=0) -> Reply: if session.messages[0].get("role") == "system": if model == "wenxin": session.messages.pop(0) - - logger.info(f"[CLAUDEAI] query={query}") # do http request @@ -189,7 +173,6 @@ def _chat(self, query, context, retry_count=0) -> Reply: } res = requests.post(base_url + "/api/append_message", headers=headers, data=payload,impersonate="chrome110",proxies= self.proxies,timeout=400) - if res.status_code == 200 or "pemission" in res.text: # execute success decoded_data = res.content.decode("utf-8") @@ -206,7 +189,6 @@ def _chat(self, query, context, retry_count=0) -> Reply: logger.info(f"[CLAUDE] reply={reply_content}, total_tokens=100") self.sessions.session_reply(reply_content, session_id, 100) return Reply(ReplyType.TEXT, reply_content) - else: response = res.json() error = response.get("error") @@ -218,7 +200,6 @@ def _chat(self, query, context, retry_count=0) -> Reply: time.sleep(2) logger.warn(f"[CLAUDE] do retry, times={retry_count}") return self._chat(query, context, retry_count + 1) - return Reply(ReplyType.ERROR, "提问太快啦,请休息一下再问我吧") except Exception as e: From b9e31256105ff5bfa8b2c3ccd6c46e8885b389cf Mon Sep 17 00:00:00 2001 From: resphinas <2934218525@qq.com> Date: Mon, 28 Aug 2023 18:04:28 +0800 Subject: [PATCH 07/17] =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E7=BA=A0=E6=AD=A32?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bot/claude/claude_ai_bot.py | 29 +++++-------------------- common/const.py | 4 ---- common/log.py | 4 ++-- config-template.json | 4 ++-- lib/itchat/async_components/messages.py | 1 - lib/itchat/components/messages.py | 1 - 6 files changed, 9 insertions(+), 34 deletions(-) diff --git a/bot/claude/claude_ai_bot.py b/bot/claude/claude_ai_bot.py index bb1cbd8fb..21ec5a9c6 100644 --- a/bot/claude/claude_ai_bot.py +++ b/bot/claude/claude_ai_bot.py @@ -2,7 +2,6 @@ import time import json import uuid - from curl_cffi import requests from bot.bot import Bot from bot.chatgpt.chat_gpt_session import ChatGPTSession @@ -15,10 +14,6 @@ class ClaudeAIBot(Bot, OpenAIImage): - # authentication failed - AUTH_FAILED_CODE = 401 - NO_QUOTA_CODE = 406 - def __init__(self): super().__init__() self.sessions = SessionManager(ChatGPTSession, model=conf().get("model") or "gpt-3.5-turbo") @@ -32,9 +27,6 @@ def __init__(self): self.con_uuid = None self.get_uuid() - - - def generate_uuid(self): random_uuid = uuid.uuid4() random_uuid_str = str(random_uuid) @@ -48,11 +40,8 @@ def get_uuid(self): self.con_uuid = self.generate_uuid() self.create_new_chat() - - def get_organization_id(self): url = "https://claude.ai/api/organizations" - headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0', @@ -65,12 +54,11 @@ def get_organization_id(self): 'Connection': 'keep-alive', 'Cookie': f'{self.claude_api_cookie}' } - response = requests.get(url, headers=headers,impersonate="chrome110",proxies=self.proxies) res = json.loads(response.text) uuid = res[0]['uuid'] - return uuid + def reply(self, query, context: Context = None) -> Reply: if context.type == ContextType.TEXT: return self._chat(query, context) @@ -108,9 +96,9 @@ def get_organization_id(self): print(response.text) return uuid + def create_new_chat(self): url = f"https://claude.ai/api/organizations/{self.org_uuid}/chat_conversations" - payload = json.dumps({"uuid": self.con_uuid, "name": ""}) headers = { 'User-Agent': @@ -127,11 +115,10 @@ def create_new_chat(self): 'Sec-Fetch-Site': 'same-origin', 'TE': 'trailers' } - response = requests.post( url, headers=headers, data=payload,impersonate="chrome110", proxies= self.proxies) - # Returns JSON of the newly created conversation information return response.json() + def _chat(self, query, context, retry_count=0) -> Reply: """ 发起对话请求 @@ -146,7 +133,6 @@ def _chat(self, query, context, retry_count=0) -> Reply: return Reply(ReplyType.ERROR, "请再问我一次吧") try: - session_id = context["session_id"] session = self.sessions.session_query(query, session_id) model = conf().get("model") or "gpt-3.5-turbo" @@ -154,8 +140,6 @@ def _chat(self, query, context, retry_count=0) -> Reply: if session.messages[0].get("role") == "system": if model == "wenxin": session.messages.pop(0) - - logger.info(f"[CLAUDEAI] query={query}") # do http request @@ -189,7 +173,6 @@ def _chat(self, query, context, retry_count=0) -> Reply: } res = requests.post(base_url + "/api/append_message", headers=headers, data=payload,impersonate="chrome110",proxies= self.proxies,timeout=400) - if res.status_code == 200 or "pemission" in res.text: # execute success decoded_data = res.content.decode("utf-8") @@ -203,10 +186,9 @@ def _chat(self, query, context, retry_count=0) -> Reply: completions.append(data['completion']) reply_content = ''.join(completions) - logger.info(f"[CLAUDE] reply={reply_content}, total_tokens=100") + logger.info(f"[CLAUDE] reply={reply_content}, total_tokens=invisible") self.sessions.session_reply(reply_content, session_id, 100) return Reply(ReplyType.TEXT, reply_content) - else: response = res.json() error = response.get("error") @@ -218,7 +200,6 @@ def _chat(self, query, context, retry_count=0) -> Reply: time.sleep(2) logger.warn(f"[CLAUDE] do retry, times={retry_count}") return self._chat(query, context, retry_count + 1) - return Reply(ReplyType.ERROR, "提问太快啦,请休息一下再问我吧") except Exception as e: @@ -226,4 +207,4 @@ def _chat(self, query, context, retry_count=0) -> Reply: # retry time.sleep(2) logger.warn(f"[CLAUDE] do retry, times={retry_count}") - return self._chat(query, context, retry_count + 1) + return self._chat(query, context, retry_count + 1) \ No newline at end of file diff --git a/common/const.py b/common/const.py index a85fec71d..20e9f89f7 100644 --- a/common/const.py +++ b/common/const.py @@ -5,10 +5,6 @@ XUNFEI = "xunfei" CHATGPTONAZURE = "chatGPTOnAzure" LINKAI = "linkai" - VERSION = "1.3.0" - -MODEL_LIST = ["gpt-3.5-turbo", "gpt-3.5-turbo-16k", "gpt-4", "wenxin", "xunfei"] CLAUDEAI = "claude" -VERSION = "1.3.0" MODEL_LIST = ["gpt-3.5-turbo", "gpt-3.5-turbo-16k", "gpt-4", "wenxin", "xunfei","claude"] diff --git a/common/log.py b/common/log.py index ac64530e2..3f2829408 100644 --- a/common/log.py +++ b/common/log.py @@ -13,14 +13,14 @@ def _reset_logger(log): console_handle.setFormatter( logging.Formatter( "[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d] - %(message)s", - datefmt="%Y-%m-%claude_ai_bot.py%H:%M:%S", + datefmt="%Y-%m-%d %H:%M:%S", ) ) file_handle = logging.FileHandler("run.log", encoding="utf-8") file_handle.setFormatter( logging.Formatter( "[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d] - %(message)s", - datefmt="%Y-%m-%claude_ai_bot.py%H:%M:%S", + datefmt="%Y-%m-%d %H:%M:%S", ) ) log.addHandler(file_handle) diff --git a/config-template.json b/config-template.json index 003fbb670..38d3ef6b1 100644 --- a/config-template.json +++ b/config-template.json @@ -2,11 +2,11 @@ "open_ai_api_key": "YOUR API KEY", "model": "gpt-3.5-turbo", "channel_type": "wx", - "proxy": "http://127.0.0.1:33210", + "proxy": "", "hot_reload": false, "model": "claude", "channel_type": "wx", - "claude_api_cookie": "intercom-device-id-lupk8zyo=b37192f8-c3a5-408d-8525-60ad8c2cc57c; sessionKey=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; intercom-session-lupk8zyo=dHBseWhqVVIvVW4vZU1NMWM3eUpTQldjQkUwYUMwQVlGQ3g4azR6RlQ3ZDBkTTRqQWd4aGN6ZmY4MSt4aEVERy0tdXY0OGdnUTdYdVhsYWx3c2ErUFFTdz09--58fbe081d071984de6a196e49d513761e8b806e9; cf_clearance=9R_XpUT12.KKIRtXlXUFng05L_sdc0GDwz55ZBGsZ6o-1693003153-0-1-636ec5eb.e36b35e5.346f9a0b-0.2.1693003153; __cf_bm=TLFZA8a7JhAo6NRLVIL0jYsD8nb4cDna6slscBAns3A-1693004564-0-AfWzEcpZbRjF6cLEjxhPUnA84TNQDNQofUkZCuabIKkmQan+BlCvvYIeZod8ISJ/RLq1URvIsp++UwTDJyKfLI8=", + "claude_api_cookie": "", "hot_reload": true, "single_chat_prefix": [ "bot", diff --git a/lib/itchat/async_components/messages.py b/lib/itchat/async_components/messages.py index 558889bf4..f842f1f53 100644 --- a/lib/itchat/async_components/messages.py +++ b/lib/itchat/async_components/messages.py @@ -350,7 +350,6 @@ def upload_chunk_file(core, fileDir, fileSymbol, fileSize, ('name', (None, fileName)), ('type', (None, fileType)), ('lastModifiedDate', (None, time.strftime('%a %b %d %Y %H:%M:%S GMT+0800 (CST)'))), - ('lastModifiedDate', (None, time.strftime('%a %b %claude_ai_bot.py%Y %H:%M:%S GMT+0800 (CST)'))), ('size', (None, str(fileSize))), ('chunks', (None, None)), ('chunk', (None, None)), diff --git a/lib/itchat/components/messages.py b/lib/itchat/components/messages.py index cdeb6fb15..85c0ca2eb 100644 --- a/lib/itchat/components/messages.py +++ b/lib/itchat/components/messages.py @@ -351,7 +351,6 @@ def upload_chunk_file(core, fileDir, fileSymbol, fileSize, ('name', (None, fileName)), ('type', (None, fileType)), ('lastModifiedDate', (None, time.strftime('%a %b %d %Y %H:%M:%S GMT+0800 (CST)'))), - ('lastModifiedDate', (None, time.strftime('%a %b %claude_ai_bot.py%Y %H:%M:%S GMT+0800 (CST)'))), ('size', (None, str(fileSize))), ('chunks', (None, None)), ('chunk', (None, None)), From a4ab547f779d0e3ff635d92ce6516422a7a24a89 Mon Sep 17 00:00:00 2001 From: resphinas <2934218525@qq.com> Date: Tue, 29 Aug 2023 05:59:59 +0800 Subject: [PATCH 08/17] proxy update --- bot/claude/claude_ai_bot.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bot/claude/claude_ai_bot.py b/bot/claude/claude_ai_bot.py index 21ec5a9c6..611561404 100644 --- a/bot/claude/claude_ai_bot.py +++ b/bot/claude/claude_ai_bot.py @@ -19,10 +19,13 @@ def __init__(self): self.sessions = SessionManager(ChatGPTSession, model=conf().get("model") or "gpt-3.5-turbo") self.claude_api_cookie = conf().get("claude_api_cookie") self.proxy = conf().get("proxy") - self.proxies = { + if self.proxy: + self.proxies = { "http": self.proxy, "https": self.proxy } + else: + self.proxies = None self.org_uuid = self.get_organization_id() self.con_uuid = None self.get_uuid() From a5a825e4390c5df943e537d9797883747d56e827 Mon Sep 17 00:00:00 2001 From: resphinas <2934218525@qq.com> Date: Tue, 29 Aug 2023 06:45:21 +0800 Subject: [PATCH 09/17] system role remove --- bot/claude/claude_ai_bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/claude/claude_ai_bot.py b/bot/claude/claude_ai_bot.py index 611561404..24ff11fa3 100644 --- a/bot/claude/claude_ai_bot.py +++ b/bot/claude/claude_ai_bot.py @@ -141,7 +141,7 @@ def _chat(self, query, context, retry_count=0) -> Reply: model = conf().get("model") or "gpt-3.5-turbo" # remove system message if session.messages[0].get("role") == "system": - if model == "wenxin": + if model == "wenxin" or model == "claude": session.messages.pop(0) logger.info(f"[CLAUDEAI] query={query}") From 91dc44df530209cbe246ecc3ad7b180f1b1aaed2 Mon Sep 17 00:00:00 2001 From: resphina <69687075+resphinas@users.noreply.github.com> Date: Fri, 1 Sep 2023 09:38:47 +0800 Subject: [PATCH 10/17] Update const.py --- common/const.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/const.py b/common/const.py index 20e9f89f7..959b4c1e4 100644 --- a/common/const.py +++ b/common/const.py @@ -5,6 +5,8 @@ XUNFEI = "xunfei" CHATGPTONAZURE = "chatGPTOnAzure" LINKAI = "linkai" + VERSION = "1.3.0" + CLAUDEAI = "claude" MODEL_LIST = ["gpt-3.5-turbo", "gpt-3.5-turbo-16k", "gpt-4", "wenxin", "xunfei","claude"] From c6e31b2fdc3be3f4ea8506459254ced818e5dc0f Mon Sep 17 00:00:00 2001 From: resphina <69687075+resphinas@users.noreply.github.com> Date: Fri, 1 Sep 2023 09:39:08 +0800 Subject: [PATCH 11/17] Update chat_gpt_bot.py --- bot/chatgpt/chat_gpt_bot.py | 1 - 1 file changed, 1 deletion(-) diff --git a/bot/chatgpt/chat_gpt_bot.py b/bot/chatgpt/chat_gpt_bot.py index 88a52f19b..8c9a2504a 100644 --- a/bot/chatgpt/chat_gpt_bot.py +++ b/bot/chatgpt/chat_gpt_bot.py @@ -106,7 +106,6 @@ def reply(self, query, context=None): reply = Reply(ReplyType.ERROR, "Bot不支持处理{}类型的消息".format(context.type)) return reply - def reply_text(self, session: ChatGPTSession, api_key=None, args=None, retry_count=0) -> dict: """ call openai's ChatCompletion to get the answer From 79e4af315e2486d20cb3e537ed5d149fa002bbed Mon Sep 17 00:00:00 2001 From: resphina <69687075+resphinas@users.noreply.github.com> Date: Fri, 1 Sep 2023 09:39:45 +0800 Subject: [PATCH 12/17] Update log.py --- common/log.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/log.py b/common/log.py index 3f2829408..f02a365b7 100644 --- a/common/log.py +++ b/common/log.py @@ -20,7 +20,7 @@ def _reset_logger(log): file_handle.setFormatter( logging.Formatter( "[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d] - %(message)s", - datefmt="%Y-%m-%d %H:%M:%S", + datefmt="%Y-%m-%d %H:%M:%S", ) ) log.addHandler(file_handle) From 4a670b7df7f99ce6b8c76891e56c728435f8a0f0 Mon Sep 17 00:00:00 2001 From: resphina <69687075+resphinas@users.noreply.github.com> Date: Fri, 1 Sep 2023 09:40:26 +0800 Subject: [PATCH 13/17] Update config-template.json --- config-template.json | 1 - 1 file changed, 1 deletion(-) diff --git a/config-template.json b/config-template.json index 3af9fbcde..779b44d3c 100644 --- a/config-template.json +++ b/config-template.json @@ -7,7 +7,6 @@ "model": "claude", "channel_type": "wx", "claude_api_cookie": "", - "hot_reload": true, "single_chat_prefix": [ "bot", "@bot" From 33a7f8b558e487b77880a8b58ecb4596dd0f75ea Mon Sep 17 00:00:00 2001 From: resphina <69687075+resphinas@users.noreply.github.com> Date: Fri, 1 Sep 2023 10:08:34 +0800 Subject: [PATCH 14/17] Delete chatgpt-on-wechat-master.iml --- chatgpt-on-wechat-master.iml | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 chatgpt-on-wechat-master.iml diff --git a/chatgpt-on-wechat-master.iml b/chatgpt-on-wechat-master.iml deleted file mode 100644 index 049614af8..000000000 --- a/chatgpt-on-wechat-master.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file From 297404b21e6f86ff26e0cecc7fb4a26b775c2819 Mon Sep 17 00:00:00 2001 From: resphina <69687075+resphinas@users.noreply.github.com> Date: Fri, 1 Sep 2023 10:31:45 +0800 Subject: [PATCH 15/17] Update config-template.json --- config-template.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/config-template.json b/config-template.json index 779b44d3c..f995c53ed 100644 --- a/config-template.json +++ b/config-template.json @@ -4,8 +4,6 @@ "channel_type": "wx", "proxy": "", "hot_reload": false, - "model": "claude", - "channel_type": "wx", "claude_api_cookie": "", "single_chat_prefix": [ "bot", From bac70108b226b63c25a39aafbeb2eea36ef4d818 Mon Sep 17 00:00:00 2001 From: resphina <69687075+resphinas@users.noreply.github.com> Date: Fri, 1 Sep 2023 10:32:03 +0800 Subject: [PATCH 16/17] Update requirements.txt --- requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 74bc96eb2..086312536 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,4 +7,3 @@ chardet>=5.1.0 Pillow pre-commit web.py -curl_cffi From 7dc7105ee2893a07ef494da3ac20d1b4b966342c Mon Sep 17 00:00:00 2001 From: resphina <69687075+resphinas@users.noreply.github.com> Date: Fri, 1 Sep 2023 10:32:33 +0800 Subject: [PATCH 17/17] Update requirements-optional.txt --- requirements-optional.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/requirements-optional.txt b/requirements-optional.txt index 1cb8a5521..17c4c1f73 100644 --- a/requirements-optional.txt +++ b/requirements-optional.txt @@ -28,3 +28,6 @@ chatgpt_tool_hub==0.4.6 # xunfei spark websocket-client==1.2.0 + +# claude bot +curl_cffi