From 34419243e25d3bcccc456e91d04fa1132ff99aea Mon Sep 17 00:00:00 2001 From: congxu Date: Sun, 23 Jul 2023 19:41:32 +0800 Subject: [PATCH] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 0d97dc3ef421da37676a7ebfce61ccae45952173 Author: congxu Date: Sun Jul 23 19:30:15 2023 +0800 Squashed commit of the following: commit 41762a1c579cdcc73b3f08447cf7cabd58947b83 Merge: e0d2e34 a786fa4 Author: zhayujie Date: Fri Jul 21 17:18:56 2023 +0800 Merge pull request #1332 from zhayujie/feat-1.3.3 fix: reduce memory usage commit a786fa4b7503b3034c303cfbc63f93d7d102bfe0 Author: zhayujie Date: Fri Jul 21 17:16:34 2023 +0800 fix: reduce the expiration time and avoid storing the original message text to decrease memory usage commit e4c7602c0c8fc8ba30a0372922749f0cbea33c83 Author: zhayujie Date: Fri Jul 21 17:14:11 2023 +0800 docs: update README.md commit e0d2e34980a34a07fd81c760d1316728e507e235 Merge: 2361e3c 9ef8e1b Author: zhayujie Date: Fri Jul 21 10:50:16 2023 +0800 Merge pull request #1328 from zhayujie/feat-1.3.3 feat: support global plugin config for docker env commit 9ef8e1be3ff8ce1475faec9ef18a638d9085c6a3 Author: zhayujie Date: Thu Jul 20 16:08:19 2023 +0800 feat: move loading config method to base class commit aae9b648333af45616a5d3c9a0b591b3b321c783 Author: zhayujie Date: Thu Jul 20 14:46:41 2023 +0800 fix: reduce unnecessary error traceback logs commit 4bab4299f28f0660cb4c76a5b97e20e78f5a90ff Author: zhayujie Date: Thu Jul 20 14:24:40 2023 +0800 fix: global plugin config read commit 954e55f4b41b59b283ecd4f395279d1fa44c9869 Author: zhayujie Date: Thu Jul 20 11:36:02 2023 +0800 feat: add plugin global config to support docker volumes commit 2361e3c28cffe79e5488acc893bcb9bcc8561fd7 Author: zhayujie Date: Wed Jul 19 18:23:59 2023 +0800 docs: update README for railway cancelled free service commit 8aac86f0a9f7f755a4ad9ec035d1d18de6880ea9 Merge: 94b47a5 6384e93 Author: zhayujie Date: Wed Jul 5 01:44:06 2023 +0800 Merge pull request #1291 from 6vision/master (tool)fix azure model commit 6384e9310b17499679198acb7d1cf0f498b6e230 Author: vision Date: Wed Jul 5 01:06:53 2023 +0800 plugin(tool): 更新0.4.6 1、temp fix summary tool not ending bug 2、兼容0613 gpt-3.5 3、add azure's model name: gpt-35-turbo commit 7a9205dfba0a85ec9a9baaaecae02334d7c34fce Author: vision Date: Wed Jul 5 01:01:46 2023 +0800 fix azure model 更新chatgpt_tool_hub至0.4.6,拉取最新代码。tool即可使用azure接口! commit 94b47a56f4f2dacef31a749c13c9ec4626598919 Merge: 709b5be f970b2c Author: Jianglang Date: Sat Jul 1 18:37:07 2023 +0800 Merge pull request #1282 from haikerapples/master_haiker_timetask 内置 timetask 插件 commit 709b5be634a2d4bfa466a21bb3f207ed82fb8d38 Author: zhayujie Date: Sat Jul 1 13:17:08 2023 +0800 fix: group voice config and azure model calc support commit f970b2c1681ac956fa5d31861be24b3ca332ee9e Author: haikerwang Date: Thu Jun 29 00:58:57 2023 +0800 内置 timetask 插件 commit da90198e46917602817373865c2c05cc50c3a6b3 Merge: 549b7c6 973acb3 Author: congxu Date: Wed Jun 28 13:51:16 2023 +0800 Merge remote-tracking branch 'upstream/master' commit 549b7c6f5b036a5e9a865c1d47984de1abcfc1f1 Author: congxu Date: Wed Jun 28 13:48:19 2023 +0800 Squashed commit of the following: commit 973acb37ed41fdd90017e44e8670cfe74cde3d11 Author: zhayujie Date: Tue Jun 27 22:28:51 2023 +0800 docs: update README.md commit 1c9020a56518e4feacd905d0c7999b85aa7315e9 Author: zhayujie Date: Mon Jun 26 23:52:32 2023 +0800 docs: update README.md commit c5f1d0042c6c143c677cd4e1c0f2c7b944d90121 Author: zhayujie Date: Mon Jun 26 20:11:35 2023 +0800 docs: update README.md commit fa706e8b1dbff679df709e6abcbe28556e3c8bab Merge: db27dfe 12c170f Author: zhayujie Date: Mon Jun 26 14:16:18 2023 +0800 Merge pull request #1275 from zhayujie/feat-docker chore: remove useless docker files commit 12c170f2274b04584e5cd927baf6e12566b657db Author: zhayujie Date: Mon Jun 26 14:05:08 2023 +0800 chore: remove useless docker files commit db27dfe227d571805909d23ca6f2f3d0503800fa Author: zhayujie Date: Mon Jun 26 13:10:51 2023 +0800 docs: modify docker deploy steps commit 2db46733928af7d8b12fb818e155a80d9023b1fa Author: zhayujie Date: Mon Jun 26 12:29:09 2023 +0800 chore: fixed openai version commit 38619db62973a4ae4e438807afd1bf0c69f07279 Merge: 98b8ff2 930fd43 Author: zhayujie Date: Mon Jun 26 12:00:57 2023 +0800 Merge pull request #1274 from zhayujie/feat-dockerhub feat: modify docker-compose file to pull image from dockerhub commit 930fd436eac488cae12da75460e643b88f0f9521 Author: zhayujie Date: Mon Jun 26 11:58:55 2023 +0800 feat: modify docker-compose file to pull image from dockerhub commit 98b8ff2fc83efdce8ea200f74dd9dc19e149dede Merge: 957f257 d066268 Author: zhayujie Date: Mon Jun 26 01:24:24 2023 +0800 Merge pull request #1271 from zhayujie/feat-dockerhub feat: publish to dockerhub in github CI simultaneously commit d0662683f99e63ae0666716e56ded8246c4a35c0 Author: zhayujie Date: Mon Jun 26 01:20:04 2023 +0800 feat: publish to dockerhub in github CI simultaneously commit 973acb37ed41fdd90017e44e8670cfe74cde3d11 Author: zhayujie Date: Tue Jun 27 22:28:51 2023 +0800 docs: update README.md commit 1c9020a56518e4feacd905d0c7999b85aa7315e9 Author: zhayujie Date: Mon Jun 26 23:52:32 2023 +0800 docs: update README.md commit c5f1d0042c6c143c677cd4e1c0f2c7b944d90121 Author: zhayujie Date: Mon Jun 26 20:11:35 2023 +0800 docs: update README.md commit fa706e8b1dbff679df709e6abcbe28556e3c8bab Merge: db27dfe 12c170f Author: zhayujie Date: Mon Jun 26 14:16:18 2023 +0800 Merge pull request #1275 from zhayujie/feat-docker chore: remove useless docker files commit 12c170f2274b04584e5cd927baf6e12566b657db Author: zhayujie Date: Mon Jun 26 14:05:08 2023 +0800 chore: remove useless docker files commit db27dfe227d571805909d23ca6f2f3d0503800fa Author: zhayujie Date: Mon Jun 26 13:10:51 2023 +0800 docs: modify docker deploy steps commit 2db46733928af7d8b12fb818e155a80d9023b1fa Author: zhayujie Date: Mon Jun 26 12:29:09 2023 +0800 chore: fixed openai version commit 38619db62973a4ae4e438807afd1bf0c69f07279 Merge: 98b8ff2 930fd43 Author: zhayujie Date: Mon Jun 26 12:00:57 2023 +0800 Merge pull request #1274 from zhayujie/feat-dockerhub feat: modify docker-compose file to pull image from dockerhub commit 930fd436eac488cae12da75460e643b88f0f9521 Author: zhayujie Date: Mon Jun 26 11:58:55 2023 +0800 feat: modify docker-compose file to pull image from dockerhub commit 98b8ff2fc83efdce8ea200f74dd9dc19e149dede Merge: 957f257 d066268 Author: zhayujie Date: Mon Jun 26 01:24:24 2023 +0800 Merge pull request #1271 from zhayujie/feat-dockerhub feat: publish to dockerhub in github CI simultaneously commit d0662683f99e63ae0666716e56ded8246c4a35c0 Author: zhayujie Date: Mon Jun 26 01:20:04 2023 +0800 feat: publish to dockerhub in github CI simultaneously commit f4bb107947d6c687bf1ba778e9411ddc38f34f70 Merge: f918674 957f257 Author: congxu Date: Sun Jun 18 17:05:07 2023 +0800 Merge pull request #35 from zhayujie/master update commit 957f2574a9b8da484fffcd1fe18d6faec831993f Merge: 4dc5356 109b362 Author: zhayujie Date: Sat Jun 17 16:50:11 2023 +0800 Merge pull request #1257 from 6vision/master add reply_suffix commit 109b362ebd816afad1cac557c6250b70eeae8de2 Author: vision Date: Sat Jun 17 16:42:52 2023 +0800 Update config.py commit ff3fdfa738a41e5a28aac8648394093bc5bd17ae Author: vision Date: Sat Jun 17 16:36:08 2023 +0800 add reply_suffix commit e2636ed54a4cdf6e75f0a51833b08e0de7302932 Author: vision Date: Sat Jun 17 15:53:49 2023 +0800 add replay_suffix 增加自动回复后缀的可选配置参数 commit dbe2f17e1a9d5c4cfc65eeac9c3c425b98ef3e47 Author: vision Date: Sat Jun 17 15:46:03 2023 +0800 add reply_suffix 增加私聊和群聊回复后缀的可选配置 commit 4dc535673f86e89872a4d9d30340f9511291bd0b Merge: 3aa2e6a f414b64 Author: zhayujie Date: Fri Jun 16 15:48:04 2023 +0800 Merge pull request #1252 from 6vision/master Update Tool README.md commit f414b6408e5aefe101b79617cf77c9ace2e43328 Author: vision Date: Fri Jun 16 15:08:57 2023 +0800 Update README.md commit 3aa2e6a04d02613a49cdf362163dea1c42dcc658 Author: lanvent Date: Fri Jun 16 00:51:29 2023 +0800 fix: caclucate tokens correctly for *0613 models commit 1963ff273fb774d92086a9bced662847a02d959c Author: lanvent Date: Wed Jun 14 13:38:34 2023 +0800 chore(hello): change plugin logic commit bb737a71d5919002717cbd714ba7335a87edde07 Author: lanvent Date: Wed Jun 14 13:36:07 2023 +0800 feat: update counting tokens for new models commit a582a46ce95a6608898772cefe910a0a2bea0a33 Author: zhayujie Date: Mon Jun 12 14:05:47 2023 +0800 fix: call super init commit abf80a32660c49949f6fd49023b1d1a75ad15145 Author: zhayujie Date: Mon Jun 12 13:52:49 2023 +0800 docs: update README commit f91867489ed66aa793024166fd2d7b81bca220d5 Merge: e60d90a d768f5c Author: congxu Date: Sun Jun 11 15:21:47 2023 +0800 Merge pull request #34 from zhayujie/master update0611 commit d768f5c66d41b27429fc94bc31ae43e7e6d115fb Author: Jianglang Date: Sun Jun 11 00:02:18 2023 +0800 Update README.md commit b25e8433517010ddc72797c0d81af2dadb2f8caf Author: lanvent Date: Sat Jun 10 23:52:25 2023 +0800 feat(link_ai_bot.py): add support for creating images using OpenAI's DALL-E API commit 419a3e518ece086e3f5e93ca5c7f2754ef1ca13f Author: lanvent Date: Sat Jun 10 23:42:43 2023 +0800 feat: make plugin compatible with LINKAI in most cases commit d1b867a7c0a07ebeb6cd422acdbd0606ee7984ee Merge: c34d70b 94c0af3 Author: lanvent Date: Sat Jun 10 21:27:03 2023 +0800 feat: support scene without app code in linkai commit c34d70b3cb4f661c73e9a27b3219521ff2082621 Author: lanvent Date: Sat Jun 10 11:22:12 2023 +0800 fix: add warning log when pysilk module is not installed commit a33df9312fb8201c85762540f480879eda90c310 Author: lanvent Date: Sat Jun 10 11:06:50 2023 +0800 fix: warning message when using azure model commit ebf8db0b375e64caf8622ad1d04fb6ff3d4b3dd2 Merge: 4c5e885 e539ae3 Author: Jianglang Date: Sat Jun 10 00:48:41 2023 +0800 Merge pull request #1238 from chenzefeng09/fix_baidu_voice_init fix: baidu voice init params type error commit e539ae3b69e661dfba9dbf6db827f6894e495f8d Author: chenzefeng.09 Date: Fri Jun 9 18:54:58 2023 +0800 fix: baidu voice init params type error commit 4c5e8850aa138b32b0c51fed2d1caffcd123d63a Author: lanvent Date: Fri Jun 9 14:46:43 2023 +0800 fix: env vars type error (#1127) commit 94c0af30370385734ed68a4a5e3c196c95bc37f3 Author: zhayujie Date: Thu Jun 8 23:57:59 2023 +0800 feat: support scen without app code commit 165182c68ff360b0ba111da69527216c99c3914f Author: zhayujie Date: Thu Jun 8 20:58:59 2023 +0800 config: remove the config temporarily and consider integrating it as a plugin commit 65b9542599432dcac3faa3b512e280098061f580 Merge: d01d1f8 ff97ae7 Author: Jianglang Date: Thu Jun 8 11:53:14 2023 +0800 Merge pull request #1221 from Zhaoyi-Yan/patch-3 add \n after @nickname for group chat commit d01d1f88301b91e6175c721c4e9e5882a9f897a0 Merge: ad3e9f3 f96b4d2 Author: Jianglang Date: Thu Jun 8 11:48:44 2023 +0800 Merge pull request #1220 from Zhaoyi-Yan/patch-2 Add azure_deployment_id to Readme for Azure chatgpt. commit ad3e9f3d42fe6bad9902dd5cbfd14fdf142ce39f Author: Jianglang Date: Thu Jun 8 11:44:17 2023 +0800 Update README.md commit 45899740952a0150e38657e3a3a8bdf505ee704a Author: Jianglang Date: Thu Jun 8 11:42:39 2023 +0800 Update README.md commit ed4553ddf85f8267d6b3243e86b053832d88ef38 Author: Jianglang Date: Thu Jun 8 11:42:12 2023 +0800 Update README.md commit ff97ae73f1cd253645bc26ad8101b68055a68322 Author: Zhaoyi-Yan Date: Tue Jun 6 15:16:57 2023 +0800 add \n after @nickname for group chat commit f96b4d2781b95d627faf54d7cbe47b94072ce4b7 Author: Zhaoyi-Yan Date: Tue Jun 6 14:44:09 2023 +0800 Add azure_deployment_id to Readme for Azure chatgpt. commit ce32cfffdb69cc70be63bea80392ac4417fdb849 Author: zhayujie Date: Tue Jun 6 14:02:32 2023 +0800 docs: update README.md commit f66df8531e9ce8a50085f71f1f88c514fdce7066 Author: zhayujie Date: Tue Jun 6 09:54:34 2023 +0800 Update README.md commit dfe1c23e76d8d665f897daf2b40cc92661023a4e Merge: 12dc742 07fd819 Author: zhayujie Date: Mon Jun 5 23:55:25 2023 +0800 Merge pull request #1218 from zhayujie/feature-app-market feat: no quota hint and add group qrcode commit 07fd81919face6525087c5aa6ef74101076c6831 Author: zhayujie Date: Mon Jun 5 23:53:34 2023 +0800 docs: udapte readme commit 210042bb817e55491a2bb67485a63b9ad7ae0484 Author: zhayujie Date: Mon Jun 5 23:21:24 2023 +0800 feat: no quota hint and add group qrcode commit e60d90aa345fc68204f257adffb7a489bb45cbfa Merge: 6e9aa7b 12dc742 Author: congxu Date: Sun Jun 4 10:54:21 2023 +0800 Merge pull request #33 from zhayujie/master make railway happy commit 12dc7427e9628ce0c5edf6c6cd02853bd3dcffd0 Author: lanvent Date: Fri Jun 2 22:15:20 2023 +0800 make railway happy commit 6e9aa7b5b718c452e3bbbdf51aec6c514fec07a6 Author: congxu Date: Fri Jun 2 16:26:09 2023 +0800 Update banwords.txt commit 06bdf55d2a62b60b147a2a096e976e8d893e5c19 Merge: 2d14f40 b476085 Author: congxu Date: Thu Jun 1 16:58:50 2023 +0800 Merge pull request #31 from zhayujie/master 11 commit 2d14f4045254ce917051f91b5b50d6d6ece855a4 Merge: 17b7f74 1fd570b Author: congxu Date: Thu Jun 1 16:57:48 2023 +0800 Merge pull request #32 from congxuma/master 11 commit 17b7f742f06c939aa58039bf52b8a0518f3204ef Author: congxu Date: Thu Jun 1 15:56:26 2023 +0800 Update getnews.py commit ad55738a88a38bc888996b8b27937de4b05d9344 Author: congxu Date: Thu Jun 1 15:46:02 2023 +0800 Update getnews.py commit b476085110b19319d455bef9115f6f715b81ecd2 Author: lanvent Date: Tue May 30 23:42:06 2023 +0800 fix: custom GPT model bug commit 776cdaf63c0651eb05abede6b878a72b8f77ad92 Merge: c29d391 69b6855 Author: zhayujie Date: Mon May 29 16:36:38 2023 +0800 Merge pull request #1168 from zhayujie/feature-app-market fix: config name optimize commit 69b685574568ef080dcddefb755b2271b6150d53 Author: zhayujie Date: Mon May 29 15:55:48 2023 +0800 fix: comment modify commit 3590babd8bfb1bea7f2e3835585094e846a4d41d Author: zhayujie Date: Mon May 29 15:52:26 2023 +0800 fix: config name optimize commit c29d391c1d4f0bc9281786be455ae36c77acc367 Merge: f1a00d5 50e44db Author: zhayujie Date: Mon May 29 15:41:12 2023 +0800 Merge pull request #1167 from zhayujie/feature-app-market feature: support online knowledge base commit 50e44dbb2aa9d3f9a80dcbf4faddf26da3fc9f57 Author: zhayujie Date: Sun May 28 22:12:36 2023 +0800 fix: session save commit 34277a394073cf025612d66d5743f4763522f125 Author: zhayujie Date: Sun May 28 19:08:23 2023 +0800 feat: add app market commit 1fd570b8bd9b99cbbf7300a2f196031806a95127 Author: congxu Date: Tue May 23 19:46:35 2023 +0800 Update banwords.txt commit 6bb8be5256fe42b07b3e4e4049108319c26f47c7 Merge: 02cb436 930898a Author: congxu Date: Sun May 21 09:54:49 2023 +0800 Merge pull request #19 from tudou2/master update commit 930898aa578b74653d25a80c14d6b81f80d10778 Author: congxu Date: Fri May 19 16:35:23 2023 +0800 Update getnews.py commit b26ee20518b6c491a45a9cf5a7626e99cb4aa279 Merge: d29fe5b f1a00d5 Author: congxu Date: Thu May 18 13:47:42 2023 +0800 Merge pull request #30 from zhayujie/master pdate commit f1a00d58ca3f382c921a2b41e27df1a445c464d0 Author: lanvent Date: Wed May 17 22:24:25 2023 +0800 chore(Dockerfile.latest): comment out the sed command to replace apt source with tuna mirror The sed command to replace the apt source with the tuna mirror has been commented out. This is because the command is not necessary for the current build and may cause issues in the future. commit d1a5f17ae818a7f36fa251577b4ffb4bbc2eb5da Merge: 9ee0ea8 6409f49 Author: Jianglang Date: Wed May 17 16:13:03 2023 +0800 Merge pull request #1102 from goldfishh/master plugin(tool): 更新0.4.4 commit 02cb436cbec827b9be247745d0bb771f3432099f Merge: ea2fe6c d29fe5b Author: congxu Date: Tue May 16 13:56:07 2023 +0800 Merge pull request #18 from tudou2/master 0516 update commit d29fe5b69228aa1457ebb2829b3d9019cb773cc5 Merge: 6d3d9d2 9ee0ea8 Author: congxu Date: Tue May 16 13:55:09 2023 +0800 Merge pull request #29 from zhayujie/master update 0516 commit 6409f496090faf668def25eeb0753cf60b59de49 Author: goldfishh Date: Tue May 16 00:21:40 2023 +0800 plugin(tool): 更新0.4.4 1. 支持azure、api转发服务 2. 修复browser代理无前缀报错的问题 3. 优化core prompt 4. 修复系列issue提到的问题 commit 9ee0ea88b5344457fe93951eb81ca1ea537b27e0 Merge: a3819d8 3e92d07 Author: Jianglang Date: Mon May 15 23:34:04 2023 +0800 Merge pull request #1089 from taoguoliang/master-fork feat(命令): 添加set_gpt_model、set_gpt_model、set_gpt_model 几个命令的使用 commit a3819d86733e0e6ff13ea64afbb95f97d30e38d8 Merge: e595972 2d7dd71 Author: Jianglang Date: Mon May 15 23:32:03 2023 +0800 Merge pull request #1096 from lichengzhe/master 处理cloudflare Bad Gateway异常,自动重试。 commit 2d7dd71a3dc6ec2cbdbf828e6138ab380d790866 Author: lichengzhe <38408577@qq.com> Date: Mon May 15 14:04:55 2023 +0800 Bad Gateway exception retry commit 0e8195ae6111b61e7a7b0d0decde3a8595ca399c Author: lichengzhe <38408577@qq.com> Date: Mon May 15 13:55:14 2023 +0800 Bad Gateway exception retry commit 3e92d076184933ff48368b38e4a8bf10e3c6f432 Author: taoguoliang <852765192@qq.com> Date: Sun May 7 15:22:24 2023 +0800 feat(命令): 添加set_gpt_model、set_gpt_model、set_gpt_model 几个命令的使用 commit e59597280dd79a98a031c780f220705570dcaa19 Merge: 9d2cb75 f2e3d69 Author: Jianglang Date: Thu May 11 20:21:05 2023 +0800 Merge pull request #1079 from 6vision/6vision-patch-1 Update README.md commit ea2fe6c51c1ec750d46a0b626806563e0322cb6f Merge: ec4b459 6d3d9d2 Author: congxu Date: Thu May 11 17:39:37 2023 +0800 Merge pull request #17 from tudou2/master update commit 6d3d9d28981d36b1c439717cb25c757b23982f0e Merge: 362b899 9d2cb75 Author: congxu Date: Thu May 11 17:36:18 2023 +0800 Merge pull request #28 from zhayujie/master pp commit f2e3d69d8ae7c1a7d74fb419b0aae058459a70b6 Author: vision Date: Thu May 11 15:49:55 2023 +0800 Update README.md 新闻类工具整合后,工具名称变更了,调整一下位置,更能引起注意 commit 9d2cb75c84cd08e5b723dd414919ac38c1a7b417 Author: lanvent Date: Wed May 10 23:11:18 2023 +0800 fix(docker): chown /usr/local/lib in debian dockerfile commit 362b8991817e9b3e976a953cd70fc9c2389e7cae Author: congxu Date: Wed May 10 10:19:41 2023 +0800 Update config.json commit f971505c4a489e97449d98a3896595357dacc301 Author: Jianglang Date: Tue May 9 23:29:03 2023 +0800 Update README.md commit 2133c1d6afee5f5f92d201c41994f950a77b9aed Author: lanvent Date: Tue May 9 23:08:20 2023 +0800 fix(Dockerfile): create /home/noroot directory and change ownership of it commit ec4b459a1209ba73a7abd58a17f7a0b65d3d4e76 Merge: 1b2d612 95623a3 Author: congxu Date: Tue May 9 15:42:47 2023 +0800 Merge pull request #16 from tudou2/master update commit 95623a303ccc6508fc27aa8c40f52e7447db41e3 Merge: f97fe59 0bf06dd Author: congxu Date: Tue May 9 11:30:48 2023 +0800 Merge pull request #27 from zhayujie/master up commit 0bf06ddfd332ea14e8898b9c3de930cbc9450f9e Merge: 024a50d e4eebd6 Author: Jianglang Date: Mon May 8 17:33:46 2023 +0800 Merge pull request #1046 from theLastWinner/master fix(企业微信):补充缺失依赖textwrap commit 024a50d642082258f1d1a8fedc89792a95308d58 Merge: 4f1ed19 c905598 Author: Jianglang Date: Mon May 8 17:33:22 2023 +0800 Merge pull request #1045 from wqh0109663/master fix docker entrypoint commit e4eebd64d15a7c5d561412a9270875fc024ee330 Author: 林督翔 Date: Mon May 8 09:39:32 2023 +0800 fix(企业微信):补充缺失依赖textwrap commit c9055989e926d24e81b294ea62b71f532f7c7ffa Author: wuqih Date: Mon May 8 09:09:46 2023 +0800 fix commit 4f1ed197ce527857dae58ccf3a9af9bc38a66ccf Author: lanvent Date: Sun May 7 23:36:35 2023 +0800 fix: compatible with python 3.7 commit f97fe59a0b84fe5c0a123fb06e07fb0f4f60f217 Author: congxu Date: Sun May 7 21:31:19 2023 +0800 Update getnews.py commit 116140404e711c463bc495c0b878658b7e07bb01 Author: congxu Date: Sun May 7 21:14:44 2023 +0800 Update getnews.py commit 257017edf80ef1bd3e98c5b76d2ddfd17416a994 Author: congxu Date: Sun May 7 20:08:03 2023 +0800 Update banwords.txt commit aad0e06ef33890c7941418e09e12f7e1931aa0a2 Merge: 1aab2ba 3e710aa Author: congxu Date: Sun May 7 14:05:42 2023 +0800 Merge pull request #26 from zhayujie/master update fix commit 1aab2ba784ea9fd215a1b8e95c95dd1f69ec236d Author: congxu Date: Sat May 6 19:40:26 2023 +0800 Update getnews.py commit 3e710aa2a1af2002e753cb600ee3f0fa48398e80 Merge: 3001ba9 b6226a4 Author: Jianglang Date: Sat May 6 17:16:06 2023 +0800 Merge pull request #1032 from wqh0109663/master 修复docker入口错误 commit b6226a45bb73ecfe5e809afd3230a652f8cf0026 Author: wuqih Date: Sat May 6 14:29:36 2023 +0800 fix commit 1b2d612adbfa1b1866aac30855f00d50d3442796 Merge: c5d07f1 35807f6 Author: congxu Date: Fri Apr 28 16:32:24 2023 +0800 Merge pull request #15 from tudou2/master update commit 35807f6f5349a136551160611f160c3c938ff54b Merge: ea0f746 2ba7269 Author: congxu Date: Fri Apr 28 14:40:47 2023 +0800 Merge pull request #25 from tudou2/test_code Test code commit c5d07f1db466b08907a11a2ffd3acb2d4f7592ae Merge: 4656003 ea0f746 Author: congxu Date: Thu Apr 27 13:28:33 2023 +0800 Merge pull request #14 from tudou2/master update commit 46560038650e800ca8156c70ce085bac463b3c9c Merge: c959f20 089e7fd Author: congxu Date: Mon Apr 24 11:45:06 2023 +0800 Merge pull request #13 from tudou2/master merge commit c959f209153ad73b81f817c8c933b9ec99aef01d Merge: 20c29ab 572aba9 Author: congxu Date: Fri Apr 21 13:12:48 2023 +0800 Merge pull request #12 from tudou2/master pull 0421 commit 20c29ab19eb34431fe2d988ae3c0e28d8abd8135 Merge: 520fc04 96a4ee8 Author: congxu Date: Wed Apr 19 17:56:10 2023 +0800 Merge pull request #11 from tudou2/master update commit 520fc046f37ded67f31719f5b7a2274fe1435309 Merge: e13dbc6 1c0874a Author: congxu Date: Wed Apr 19 12:35:02 2023 +0800 Merge pull request #10 from tudou2/master 0419 commit e13dbc6aaf5687e0e9f3e72fd1fad8443d4fe6ae Merge: 76a0b8a 86caf6d Author: congxu Date: Tue Apr 18 19:24:55 2023 +0800 Merge pull request #9 from tudou2/master update0418 commit 76a0b8ae64aabcd1213d1a965f755e0d96968cb1 Merge: e8a811f 0689673 Author: congxu Date: Mon Apr 17 22:50:23 2023 +0800 Merge pull request #8 from tudou2/master tt commit e8a811f31ceb6be57108c52c21624c73b38b8fa9 Merge: 51fb215 e9a8511 Author: congxu Date: Mon Apr 17 15:04:57 2023 +0800 Merge pull request #7 from tudou2/master update commit 51fb215fff6bf3848691317be63c8a98c4ed2e37 Merge: 7264827 edec73f Author: congxu Date: Mon Apr 17 12:42:18 2023 +0800 Merge pull request #6 from tudou2/master update pull commit 7264827e60d6f7fcbcdda32b1b3e1c820ceadd5e Merge: 614d7eb b797ee4 Author: congxu Date: Mon Apr 17 10:24:43 2023 +0800 Merge pull request #5 from tudou2/master update commit 614d7ebaa21a743796edc0ebcd5f3c5aa5f7ddaa Merge: f3ce5c4 9df2178 Author: congxu Date: Thu Apr 13 18:22:08 2023 +0800 Merge pull request #4 from tudou2/master update commit f3ce5c45a9a7b6f376d21aa3932152f3edbfc25b Author: congxu Date: Thu Apr 13 18:20:45 2023 +0800 Update getnews.py commit df1cbdf0d4e5239e2921312a4790c3166110d765 Merge: 62324b0 aaee15e Author: congxu Date: Thu Apr 13 17:41:00 2023 +0800 Merge pull request #3 from tudou2/master update --- README.md | 83 +++++++++++-- bot/bot_factory.py | 5 + bot/chatgpt/chat_gpt_bot.py | 26 ++-- bot/chatgpt/chat_gpt_session.py | 17 +-- bot/linkai/link_ai_bot.py | 108 ++++++++++++++++ bridge/bridge.py | 2 + channel/chat_channel.py | 9 +- channel/wechat/wechat_channel.py | 7 +- channel/wechatcom/README.md | 10 +- channel/wechatcom/wechatcomapp_channel.py | 6 +- channel/wechatmp/passive_reply.py | 2 +- common/const.py | 1 + config-template.json | 6 +- config.py | 34 ++++- docker/Dockerfile.alpine | 39 ------ docker/Dockerfile.alpine.latest | 29 ----- docker/Dockerfile.debian | 40 ------ docker/Dockerfile.latest | 7 +- docker/build.alpine.sh | 15 --- docker/build.debian.sh | 15 --- .../Dockerfile.alpine | 23 ---- .../Dockerfile.debian | 24 ---- .../docker-compose.yaml | 24 ---- .../entrypoint.sh | 117 ------------------ ...docker-compose.yaml => docker-compose.yml} | 17 +-- docker/sample-chatgpt-on-wechat/.env | 16 --- docker/sample-chatgpt-on-wechat/Makefile | 26 ---- docker/sample-chatgpt-on-wechat/Name | 1 - docs/images/contact.jpg | Bin 0 -> 154407 bytes lib/itchat/components/register.py | 5 +- nixpacks.toml | 6 +- plugins/banwords/banwords.py | 19 +-- plugins/banwords/banwords.txt | 9 +- plugins/bdunit/bdunit.py | 8 +- plugins/config.json.template | 24 ++++ plugins/dungeon/dungeon.py | 2 +- plugins/event.py | 3 + plugins/godcmd/godcmd.py | 53 ++++++-- plugins/hello/hello.py | 4 +- plugins/plugin.py | 22 ++++ plugins/plugin_getnews/getnews.py | 33 ++++- plugins/plugin_manager.py | 33 ++++- plugins/role/role.py | 2 +- plugins/source.json | 6 +- plugins/tool/README.md | 15 ++- plugins/tool/config.json | 2 +- plugins/tool/tool.py | 14 +-- requirements-optional.txt | 2 +- requirements.txt | 2 +- translate/baidu/baidu_translate.py | 7 +- voice/audio_convert.py | 8 +- voice/baidu/baidu_voice.py | 6 +- 52 files changed, 498 insertions(+), 496 deletions(-) create mode 100644 bot/linkai/link_ai_bot.py delete mode 100644 docker/Dockerfile.alpine delete mode 100644 docker/Dockerfile.alpine.latest delete mode 100644 docker/Dockerfile.debian delete mode 100644 docker/build.alpine.sh delete mode 100644 docker/build.debian.sh delete mode 100644 docker/chatgpt-on-wechat-voice-reply/Dockerfile.alpine delete mode 100644 docker/chatgpt-on-wechat-voice-reply/Dockerfile.debian delete mode 100644 docker/chatgpt-on-wechat-voice-reply/docker-compose.yaml delete mode 100755 docker/chatgpt-on-wechat-voice-reply/entrypoint.sh rename docker/{docker-compose.yaml => docker-compose.yml} (68%) delete mode 100644 docker/sample-chatgpt-on-wechat/.env delete mode 100644 docker/sample-chatgpt-on-wechat/Makefile delete mode 100644 docker/sample-chatgpt-on-wechat/Name create mode 100644 docs/images/contact.jpg create mode 100644 plugins/config.json.template diff --git a/README.md b/README.md index 4385a5ed7..341c7344b 100644 --- a/README.md +++ b/README.md @@ -13,19 +13,23 @@ > 欢迎接入更多应用,参考 [Terminal代码](https://github.com/zhayujie/chatgpt-on-wechat/blob/master/channel/terminal/terminal_channel.py)实现接收和发送消息逻辑即可接入。 同时欢迎增加新的插件,参考 [插件说明文档](https://github.com/zhayujie/chatgpt-on-wechat/tree/master/plugins)。 -**一键部署:** - -[![Deploy on Railway](https://railway.app/button.svg)](https://railway.app/template/qApznZ?referralCode=RC3znh) - # 演示 https://user-images.githubusercontent.com/26161723/233777277-e3b9928e-b88f-43e2-b0e0-3cbc923bc799.mp4 Demo made by [Visionn](https://www.wangpc.cc/) +# 交流群 + +添加小助手微信进群,请备注 "wechat": + + + # 更新日志 ->**2023.04.26:** 支持企业微信应用号部署,兼容插件,并支持语音图片交互,支持Railway部署,[使用文档](https://github.com/zhayujie/chatgpt-on-wechat/blob/master/channel/wechatcom/README.md)。(contributed by [@lanvent](https://github.com/lanvent) in [#944](https://github.com/zhayujie/chatgpt-on-wechat/pull/944)) +>**2023.06.12:** 接入 [LinkAI](https://chat.link-ai.tech/console) 平台,可在线创建 个人知识库,并接入微信、公众号及企业微信中。使用参考 [接入文档](https://link-ai.tech/platform/link-app/wechat)。 + +>**2023.04.26:** 支持企业微信应用号部署,兼容插件,并支持语音图片交互,私人助理理想选择,[使用文档](https://github.com/zhayujie/chatgpt-on-wechat/blob/master/channel/wechatcom/README.md)。(contributed by [@lanvent](https://github.com/lanvent) in [#944](https://github.com/zhayujie/chatgpt-on-wechat/pull/944)) >**2023.04.05:** 支持微信公众号部署,兼容插件,并支持语音图片交互,[使用文档](https://github.com/zhayujie/chatgpt-on-wechat/blob/master/channel/wechatmp/README.md)。(contributed by [@JS00000](https://github.com/JS00000) in [#686](https://github.com/zhayujie/chatgpt-on-wechat/pull/686)) @@ -54,6 +58,8 @@ Demo made by [Visionn](https://www.wangpc.cc/) 支持 Linux、MacOS、Windows 系统(可在Linux服务器上长期运行),同时需安装 `Python`。 > 建议Python版本在 3.7.1~3.9.X 之间,推荐3.8版本,3.10及以上版本在 MacOS 可用,其他系统上不确定能否正常运行。 +> 注意:Docker 或 Railway 部署无需安装python环境和下载源码,可直接快进到下一节。 + **(1) 克隆项目代码:** ```bash @@ -116,6 +122,7 @@ pip3 install azure-cognitiveservices-speech "speech_recognition": false, # 是否开启语音识别 "group_speech_recognition": false, # 是否开启群组语音识别 "use_azure_chatgpt": false, # 是否使用Azure ChatGPT service代替openai ChatGPT service. 当设置为true时需要设置 open_ai_api_base,如 https://xxx.openai.azure.com/ + "azure_deployment_id": "", # 采用Azure ChatGPT时,模型部署名称 "character_desc": "你是ChatGPT, 一个由OpenAI训练的大型语言模型, 你旨在回答并解决人们的任何问题,并且可以使用多种语言与人交流。", # 人格描述 # 订阅消息,公众号和企业微信channel中请填写,当被订阅时会自动回复,可使用特殊占位符。目前支持的占位符有{trigger_prefix},在程序中它会自动替换成bot的触发词。 "subscribe_msg": "感谢您的关注!\n这里是ChatGPT,可以自由对话。\n支持语音对话。\n支持图片输出,画字开头的消息将按要求创作图片。\n支持角色扮演和文字冒险等丰富插件。\n输入{trigger_prefix}#help 查看详细指令。" @@ -143,11 +150,11 @@ pip3 install azure-cognitiveservices-speech **4.其他配置** -+ `model`: 模型名称,目前支持 `gpt-3.5-turbo`, `text-davinci-003`, `gpt-4`, `gpt-4-32k` (其中gpt-4 api暂未开放) ++ `model`: 模型名称,目前支持 `gpt-3.5-turbo`, `text-davinci-003`, `gpt-4`, `gpt-4-32k` (其中gpt-4 api暂未完全开放,申请通过后可使用) + `temperature`,`frequency_penalty`,`presence_penalty`: Chat API接口参数,详情参考[OpenAI官方文档。](https://platform.openai.com/docs/api-reference/chat) + `proxy`:由于目前 `openai` 接口国内无法访问,需配置代理客户端的地址,详情参考 [#351](https://github.com/zhayujie/chatgpt-on-wechat/issues/351) + 对于图像生成,在满足个人或群组触发条件外,还需要额外的关键词前缀来触发,对应配置 `image_create_prefix ` -+ 关于OpenAI对话及图片接口的参数配置(内容自由度、回复字数限制、图片大小等),可以参考 [对话接口](https://beta.openai.com/docs/api-reference/completions) 和 [图像接口](https://beta.openai.com/docs/api-reference/completions) 文档直接在 [代码](https://github.com/zhayujie/chatgpt-on-wechat/blob/master/bot/openai/open_ai_bot.py) `bot/openai/open_ai_bot.py` 中进行调整。 ++ 关于OpenAI对话及图片接口的参数配置(内容自由度、回复字数限制、图片大小等),可以参考 [对话接口](https://beta.openai.com/docs/api-reference/completions) 和 [图像接口](https://beta.openai.com/docs/api-reference/completions) 文档,在[`config.py`](https://github.com/zhayujie/chatgpt-on-wechat/blob/master/config.py)中检查哪些参数在本项目中是可配置的。 + `conversation_max_tokens`:表示能够记忆的上下文最大字数(一问一答为一组对话,如果累积的对话字数超出限制,就会优先移除最早的一组对话) + `rate_limit_chatgpt`,`rate_limit_dalle`:每分钟最高问答速率、画图速率,超速后排队按序处理。 + `clear_memory_commands`: 对话内指令,主动清空前文记忆,字符串数组可自定义指令别名。 @@ -155,7 +162,7 @@ pip3 install azure-cognitiveservices-speech + `character_desc` 配置中保存着你对机器人说的一段话,他会记住这段话并作为他的设定,你可以为他定制任何人格 (关于会话上下文的更多内容参考该 [issue](https://github.com/zhayujie/chatgpt-on-wechat/issues/43)) + `subscribe_msg`:订阅消息,公众号和企业微信channel中请填写,当被订阅时会自动回复, 可使用特殊占位符。目前支持的占位符有{trigger_prefix},在程序中它会自动替换成bot的触发词。 -**所有可选的配置项均在该[文件](https://github.com/zhayujie/chatgpt-on-wechat/blob/master/config.py)中列出。** +**本说明文档可能会未及时更新,当前所有可选的配置项均在该[`config.py`](https://github.com/zhayujie/chatgpt-on-wechat/blob/master/config.py)中列出。** ## 运行 @@ -186,21 +193,71 @@ nohup python3 app.py & tail -f nohup.out # 在后台运行程序并通 ### 3.Docker部署 -参考文档 [Docker部署](https://github.com/limccn/chatgpt-on-wechat/wiki/Docker%E9%83%A8%E7%BD%B2) (Contributed by [limccn](https://github.com/limccn))。 +> 使用docker部署无需下载源码和安装依赖,只需要获取 docker-compose.yml 配置文件并启动容器即可。 + +> 前提是需要安装好 `docker` 及 `docker-compose`,安装成功的表现是执行 `docker -v` 和 `docker-compose version` (或 docker compose version) 可以查看到版本号,可前往 [docker官网](https://docs.docker.com/engine/install/) 进行下载。 + +#### (1) 下载 docker-compose.yml 文件 + +```bash +wget https://open-1317903499.cos.ap-guangzhou.myqcloud.com/docker-compose.yml +``` + +下载完成后打开 `docker-compose.yml` 修改所需配置,如 `OPEN_AI_API_KEY` 和 `GROUP_NAME_WHITE_LIST` 等。 + +#### (2) 启动容器 + +在 `docker-compose.yml` 所在目录下执行以下命令启动容器: + +```bash +sudo docker compose up -d +``` + +运行 `sudo docker ps` 能查看到 NAMES 为 chatgpt-on-wechat 的容器即表示运行成功。 + +注意: + + - 如果 `docker-compose` 是 1.X 版本 则需要执行 `sudo docker-compose up -d` 来启动容器 + - 该命令会自动去 [docker hub](https://hub.docker.com/r/zhayujie/chatgpt-on-wechat) 拉取 latest 版本的镜像,latest 镜像会在每次项目 release 新的版本时生成 + +最后运行以下命令可查看容器运行日志,扫描日志中的二维码即可完成登录: + +```bash +sudo docker logs -f chatgpt-on-wechat +``` + +#### (3) 插件使用 -### 4. Railway部署 (✅推荐) -> Railway每月提供5刀和最多500小时的免费额度。 -1. 进入 [Railway](https://railway.app/template/qApznZ?referralCode=RC3znh)。 +如果需要在docker容器中修改插件配置,可通过挂载的方式完成,将 [插件配置文件](https://github.com/zhayujie/chatgpt-on-wechat/blob/master/plugins/config.json.template) +重命名为 `config.json`,放置于 `docker-compose.yml` 相同目录下,并在 `docker-compose.yml` 中的 `chatgpt-on-wechat` 部分下添加 `volumes` 映射: + +``` +volumes: + - ./config.json:/app/plugins/config.json +``` + +### 4. Railway部署 + +> Railway 每月提供5刀和最多500小时的免费额度。 (07.11更新: 目前大部分账号已无法免费部署) + +1. 进入 [Railway](https://railway.app/template/qApznZ?referralCode=RC3znh) 2. 点击 `Deploy Now` 按钮。 3. 设置环境变量来重载程序运行的参数,例如`open_ai_api_key`, `character_desc`。 +**一键部署:** + + [![Deploy on Railway](https://railway.app/button.svg)](https://railway.app/template/qApznZ?referralCode=RC3znh) + ## 常见问题 FAQs: +或直接在线咨询 [项目小助手](https://chat.link-ai.tech/app/Kv2fXJcH) (beta版本,语料完善中,回复仅供参考) ## 联系 -欢迎提交PR、Issues,以及Star支持一下。程序运行遇到问题优先查看 [常见问题列表](https://github.com/zhayujie/chatgpt-on-wechat/wiki/FAQs) ,其次前往 [Issues](https://github.com/zhayujie/chatgpt-on-wechat/issues) 中搜索。如果你想了解更多项目细节,并与开发者们交流更多关于AI技术的实践,欢迎加入星球: +欢迎提交PR、Issues,以及Star支持一下。程序运行遇到问题可以查看 [常见问题列表](https://github.com/zhayujie/chatgpt-on-wechat/wiki/FAQs) ,其次前往 [Issues](https://github.com/zhayujie/chatgpt-on-wechat/issues) 中搜索。 + +如果你想了解更多项目细节,与开发者们交流更多关于AI技术的实践,欢迎加入星球: diff --git a/bot/bot_factory.py b/bot/bot_factory.py index 77797e76a..2e9cb2d6a 100644 --- a/bot/bot_factory.py +++ b/bot/bot_factory.py @@ -33,4 +33,9 @@ def create_bot(bot_type): from bot.chatgpt.chat_gpt_bot import AzureChatGPTBot return AzureChatGPTBot() + + elif bot_type == const.LINKAI: + from bot.linkai.link_ai_bot import LinkAIBot + return LinkAIBot() + raise RuntimeError diff --git a/bot/chatgpt/chat_gpt_bot.py b/bot/chatgpt/chat_gpt_bot.py index b46751abf..ba357c00b 100644 --- a/bot/chatgpt/chat_gpt_bot.py +++ b/bot/chatgpt/chat_gpt_bot.py @@ -36,7 +36,7 @@ def __init__(self): "model": conf().get("model") or "gpt-3.5-turbo", # 对话模型的名称 "temperature": conf().get("temperature", 0.9), # 值在[0,1]之间,越大表示回复越具有不确定性 # "max_tokens":4096, # 回复最大的字符数 - "top_p": 1, + "top_p": conf().get("top_p", 1), "frequency_penalty": conf().get("frequency_penalty", 0.0), # [-2,2]之间,该值越大则更倾向于产生不同的内容 "presence_penalty": conf().get("presence_penalty", 0.0), # [-2,2]之间,该值越大则更倾向于产生不同的内容 "request_timeout": conf().get("request_timeout", None), # 请求超时时间,openai接口默认设置为600,对于难问题一般需要较长时间 @@ -66,12 +66,16 @@ def reply(self, query, context=None): logger.debug("[CHATGPT] session query={}".format(session.messages)) api_key = context.get("openai_api_key") - + model = context.get("gpt_model") + new_args = None + if model: + new_args = self.args.copy() + new_args["model"] = model # if context.get('stream'): # # reply in stream # return self.reply_text_stream(query, new_query, session_id) - reply_content = self.reply_text(session, api_key) + reply_content = self.reply_text(session, api_key, args=new_args) logger.debug( "[CHATGPT] new_query={}, session_id={}, reply_cont={}, completion_tokens={}".format( session.messages, @@ -102,7 +106,7 @@ 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, retry_count=0) -> dict: + def reply_text(self, session: ChatGPTSession, api_key=None, args=None, retry_count=0) -> dict: """ call openai's ChatCompletion to get the answer :param session: a conversation session @@ -114,7 +118,10 @@ def reply_text(self, session: ChatGPTSession, api_key=None, retry_count=0) -> di if conf().get("rate_limit_chatgpt") and not self.tb4chatgpt.get_token(): raise openai.error.RateLimitError("RateLimitError: rate limit exceeded") # if api_key == None, the default openai.api_key will be used - response = openai.ChatCompletion.create(api_key=api_key, messages=session.messages, **self.args) + if args is None: + args = self.args + response = openai.ChatCompletion.create(api_key=api_key, messages=session.messages, **args) + # logger.debug("[CHATGPT] response={}".format(response)) # logger.info("[ChatGPT] reply={}, total_tokens={}".format(response.choices[0]['message']['content'], response["usage"]["total_tokens"])) return { "total_tokens": response["usage"]["total_tokens"], @@ -134,18 +141,23 @@ def reply_text(self, session: ChatGPTSession, api_key=None, retry_count=0) -> di result["content"] = "我没有收到你的消息" if need_retry: time.sleep(5) + elif isinstance(e, openai.error.APIError): + logger.warn("[CHATGPT] Bad Gateway: {}".format(e)) + result["content"] = "请再问我一次" + if need_retry: + time.sleep(10) elif isinstance(e, openai.error.APIConnectionError): logger.warn("[CHATGPT] APIConnectionError: {}".format(e)) need_retry = False result["content"] = "我连接不到你的网络" else: - logger.warn("[CHATGPT] Exception: {}".format(e)) + logger.exception("[CHATGPT] Exception: {}".format(e)) need_retry = False self.sessions.clear_session(session.session_id) if need_retry: logger.warn("[CHATGPT] 第{}次重试".format(retry_count + 1)) - return self.reply_text(session, api_key, retry_count + 1) + return self.reply_text(session, api_key, args, retry_count + 1) else: return result diff --git a/bot/chatgpt/chat_gpt_session.py b/bot/chatgpt/chat_gpt_session.py index e6c319b36..299ae19f1 100644 --- a/bot/chatgpt/chat_gpt_session.py +++ b/bot/chatgpt/chat_gpt_session.py @@ -57,24 +57,25 @@ def num_tokens_from_messages(messages, model): """Returns the number of tokens used by a list of messages.""" import tiktoken + if model in ["gpt-3.5-turbo-0301", "gpt-35-turbo"]: + return num_tokens_from_messages(messages, model="gpt-3.5-turbo") + elif model in ["gpt-4-0314", "gpt-4-0613", "gpt-4-32k", "gpt-4-32k-0613", "gpt-3.5-turbo-0613", "gpt-3.5-turbo-16k", "gpt-3.5-turbo-16k-0613", "gpt-35-turbo-16k"]: + return num_tokens_from_messages(messages, model="gpt-4") + try: encoding = tiktoken.encoding_for_model(model) except KeyError: logger.debug("Warning: model not found. Using cl100k_base encoding.") encoding = tiktoken.get_encoding("cl100k_base") - if model == "gpt-3.5-turbo" or model == "gpt-35-turbo": - return num_tokens_from_messages(messages, model="gpt-3.5-turbo-0301") - elif model == "gpt-4": - return num_tokens_from_messages(messages, model="gpt-4-0314") - elif model == "gpt-3.5-turbo-0301": + if model == "gpt-3.5-turbo": tokens_per_message = 4 # every message follows <|start|>{role/name}\n{content}<|end|>\n tokens_per_name = -1 # if there's a name, the role is omitted - elif model == "gpt-4-0314": + elif model == "gpt-4": tokens_per_message = 3 tokens_per_name = 1 else: - logger.warn(f"num_tokens_from_messages() is not implemented for model {model}. Returning num tokens assuming gpt-3.5-turbo-0301.") - return num_tokens_from_messages(messages, model="gpt-3.5-turbo-0301") + logger.warn(f"num_tokens_from_messages() is not implemented for model {model}. Returning num tokens assuming gpt-3.5-turbo.") + return num_tokens_from_messages(messages, model="gpt-3.5-turbo") num_tokens = 0 for message in messages: num_tokens += tokens_per_message diff --git a/bot/linkai/link_ai_bot.py b/bot/linkai/link_ai_bot.py new file mode 100644 index 000000000..804b53ba7 --- /dev/null +++ b/bot/linkai/link_ai_bot.py @@ -0,0 +1,108 @@ +# access LinkAI knowledge base platform +# docs: https://link-ai.tech/platform/link-app/wechat + +import time + +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 LinkAIBot(Bot, OpenAIImage): + # authentication failed + AUTH_FAILED_CODE = 401 + NO_QUOTA_CODE = 406 + + def __init__(self): + super().__init__() + self.base_url = "https://api.link-ai.chat/v1" + self.sessions = SessionManager(ChatGPTSession, model=conf().get("model") or "gpt-3.5-turbo") + + 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, retstring = self.create_img(query, 0) + reply = None + if ok: + reply = Reply(ReplyType.IMAGE_URL, retstring) + else: + reply = Reply(ReplyType.ERROR, retstring) + return reply + else: + reply = Reply(ReplyType.ERROR, "Bot不支持处理{}类型的消息".format(context.type)) + return reply + + def _chat(self, query, context, retry_count=0): + if retry_count >= 2: + # exit from retry 2 times + logger.warn("[LINKAI] failed after maximum number of retry times") + return Reply(ReplyType.ERROR, "请再问我一次吧") + + try: + # load config + if context.get("generate_breaked_by"): + logger.info(f"[LINKAI] won't set appcode because a plugin ({context['generate_breaked_by']}) affected the context") + app_code = None + else: + app_code = conf().get("linkai_app_code") + linkai_api_key = conf().get("linkai_api_key") + + session_id = context["session_id"] + + session = self.sessions.session_query(query, session_id) + + # remove system message + if app_code and session.messages[0].get("role") == "system": + session.messages.pop(0) + + logger.info(f"[LINKAI] query={query}, app_code={app_code}") + + body = { + "appCode": app_code, + "messages": session.messages, + "model": conf().get("model") or "gpt-3.5-turbo", # 对话模型的名称 + "temperature": conf().get("temperature"), + "top_p": conf().get("top_p", 1), + "frequency_penalty": conf().get("frequency_penalty", 0.0), # [-2,2]之间,该值越大则更倾向于产生不同的内容 + "presence_penalty": conf().get("presence_penalty", 0.0), # [-2,2]之间,该值越大则更倾向于产生不同的内容 + } + headers = {"Authorization": "Bearer " + linkai_api_key} + + # do http request + res = requests.post(url=self.base_url + "/chat/completion", json=body, headers=headers).json() + + if not res or not res["success"]: + if res.get("code") == self.AUTH_FAILED_CODE: + logger.exception(f"[LINKAI] please check your linkai_api_key, res={res}") + return Reply(ReplyType.ERROR, "请再问我一次吧") + + elif res.get("code") == self.NO_QUOTA_CODE: + logger.exception(f"[LINKAI] please check your account quota, https://chat.link-ai.tech/console/account") + return Reply(ReplyType.ERROR, "提问太快啦,请休息一下再问我吧") + + else: + # retry + time.sleep(2) + logger.warn(f"[LINKAI] do retry, times={retry_count}") + return self._chat(query, context, retry_count + 1) + + # execute success + reply_content = res["data"]["content"] + logger.info(f"[LINKAI] reply={reply_content}") + self.sessions.session_reply(reply_content, session_id) + return Reply(ReplyType.TEXT, reply_content) + + except Exception as e: + logger.exception(e) + # retry + time.sleep(2) + logger.warn(f"[LINKAI] do retry, times={retry_count}") + return self._chat(query, context, retry_count + 1) diff --git a/bridge/bridge.py b/bridge/bridge.py index 78fe23458..d3fbd9565 100644 --- a/bridge/bridge.py +++ b/bridge/bridge.py @@ -23,6 +23,8 @@ def __init__(self): self.btype["chat"] = const.OPEN_AI if conf().get("use_azure_chatgpt", False): self.btype["chat"] = const.CHATGPTONAZURE + if conf().get("use_linkai") and conf().get("linkai_api_key"): + self.btype["chat"] = const.LINKAI self.bots = {} def get_bot(self, typename): diff --git a/channel/chat_channel.py b/channel/chat_channel.py index a9b90f2aa..ffb49c8bf 100644 --- a/channel/chat_channel.py +++ b/channel/chat_channel.py @@ -50,6 +50,7 @@ def _compose_context(self, ctype: ContextType, content, **kwargs): cmsg = context["msg"] user_data = conf().get_user_data(cmsg.from_user_id) context["openai_api_key"] = user_data.get("openai_api_key") + context["gpt_model"] = user_data.get("gpt_model") if context.get("isgroup", False): group_name = cmsg.other_user_nickname group_id = cmsg.other_user_id @@ -161,6 +162,8 @@ def _generate_reply(self, context: Context, reply: Reply = Reply()) -> Reply: reply = e_context["reply"] if not e_context.is_pass(): logger.debug("[WX] ready to handle context: type={}, content={}".format(context.type, context.content)) + if e_context.is_break(): + context["generate_breaked_by"] = e_context["breaked_by"] if context.type == ContextType.TEXT or context.type == ContextType.IMAGE_CREATE: # 文字和图片消息 reply = super().build_reply_content(context.content, context) elif context.type == ContextType.VOICE: # 语音消息 @@ -219,10 +222,10 @@ def _decorate_reply(self, context: Context, reply: Reply) -> Reply: reply = super().build_text_to_voice(reply.content) return self._decorate_reply(context, reply) if context.get("isgroup", False): - reply_text = "@" + context["msg"].actual_user_nickname + " " + reply_text.strip() - reply_text = conf().get("group_chat_reply_prefix", "") + reply_text + reply_text = "@" + context["msg"].actual_user_nickname + "\n" + reply_text.strip() + reply_text = conf().get("group_chat_reply_prefix", "") + reply_text + conf().get("group_chat_reply_suffix", "") else: - reply_text = conf().get("single_chat_reply_prefix", "") + reply_text + reply_text = conf().get("single_chat_reply_prefix", "") + reply_text + conf().get("single_chat_reply_suffix", "") reply.content = reply_text elif reply.type == ReplyType.ERROR or reply.type == ReplyType.INFO: reply.content = "[" + str(reply.type) + "]\n" + reply.content diff --git a/channel/wechat/wechat_channel.py b/channel/wechat/wechat_channel.py index c888157f3..c547c6a1b 100644 --- a/channel/wechat/wechat_channel.py +++ b/channel/wechat/wechat_channel.py @@ -23,7 +23,6 @@ from config import conf, get_appdata_dir from lib import itchat from lib.itchat.content import * -from plugins import * @itchat.msg_register([TEXT, VOICE, PICTURE, NOTE]) @@ -54,7 +53,7 @@ def wrapper(self, cmsg: ChatMessage): if msgId in self.receivedMsgs: logger.info("Wechat message {} already received, ignore".format(msgId)) return - self.receivedMsgs[msgId] = cmsg + self.receivedMsgs[msgId] = True create_time = cmsg.create_time # 消息时间戳 if conf().get("hot_reload") == True and int(create_time) < int(time.time()) - 60: # 跳过1分钟前的历史消息 logger.debug("[WX]history message {} skipped".format(msgId)) @@ -106,7 +105,7 @@ class WechatChannel(ChatChannel): def __init__(self): super().__init__() - self.receivedMsgs = ExpiredDict(60 * 60 * 24) + self.receivedMsgs = ExpiredDict(60 * 60) def startup(self): itchat.instance.receivingRetryCount = 600 # 修改断线超时时间 @@ -160,7 +159,7 @@ def handle_single(self, cmsg: ChatMessage): @_check def handle_group(self, cmsg: ChatMessage): if cmsg.ctype == ContextType.VOICE: - if conf().get("speech_recognition") != True: + if conf().get("group_speech_recognition") != True: return logger.debug("[WX]receive voice for group msg: {}".format(cmsg.content)) elif cmsg.ctype == ContextType.IMAGE: diff --git a/channel/wechatcom/README.md b/channel/wechatcom/README.md index 1b2fe1aa6..2f54a79fd 100644 --- a/channel/wechatcom/README.md +++ b/channel/wechatcom/README.md @@ -1,6 +1,6 @@ # 企业微信应用号channel -企业微信官方提供了客服、应用等API,本channel使用的是企业微信的应用API的能力。 +企业微信官方提供了客服、应用等API,本channel使用的是企业微信的自建应用API的能力。 因为未来可能还会开发客服能力,所以本channel的类型名叫作`wechatcom_app`。 @@ -72,13 +72,11 @@ Error code: 60020, message: "not allow to access from your ip, ...from ip: xx.xx 意思是IP不可信,需要参考上一步的`企业可信IP`配置,把这里的IP加进去。 -### Railway部署方式 +~~### Railway部署方式~~(2023-06-08已失效) -公众号不能在`Railway`上部署,但企业微信应用[可以](https://railway.app/template/-FHS--?referralCode=RC3znh)! +~~公众号不能在`Railway`上部署,但企业微信应用[可以](https://railway.app/template/-FHS--?referralCode=RC3znh)!~~ -[![Deploy on Railway](https://railway.app/button.svg)](https://railway.app/template/-FHS--?referralCode=RC3znh) - -填写配置后,将部署完成后的网址```**.railway.app/wxcomapp```,填写在上一步的URL中。发送信息后观察日志,把报错的IP加入到可信IP。(每次重启后都需要加入可信IP) +~~填写配置后,将部署完成后的网址```**.railway.app/wxcomapp```,填写在上一步的URL中。发送信息后观察日志,把报错的IP加入到可信IP。(每次重启后都需要加入可信IP)~~ ## 测试体验 diff --git a/channel/wechatcom/wechatcomapp_channel.py b/channel/wechatcom/wechatcomapp_channel.py index 72804e4ad..1a0859690 100644 --- a/channel/wechatcom/wechatcomapp_channel.py +++ b/channel/wechatcom/wechatcomapp_channel.py @@ -93,7 +93,8 @@ def send(self, reply: Reply, context: Context): image_storage = io.BytesIO() for block in pic_res.iter_content(1024): image_storage.write(block) - if (sz := fsize(image_storage)) >= 10 * 1024 * 1024: + sz = fsize(image_storage) + if sz >= 10 * 1024 * 1024: logger.info("[wechatcom] image too large, ready to compress, sz={}".format(sz)) image_storage = compress_imgfile(image_storage, 10 * 1024 * 1024 - 1) logger.info("[wechatcom] image compressed, sz={}".format(fsize(image_storage))) @@ -109,7 +110,8 @@ def send(self, reply: Reply, context: Context): logger.info("[wechatcom] sendImage url={}, receiver={}".format(img_url, receiver)) elif reply.type == ReplyType.IMAGE: # 从文件读取图片 image_storage = reply.content - if (sz := fsize(image_storage)) >= 10 * 1024 * 1024: + sz = fsize(image_storage) + if sz >= 10 * 1024 * 1024: logger.info("[wechatcom] image too large, ready to compress, sz={}".format(sz)) image_storage = compress_imgfile(image_storage, 10 * 1024 * 1024 - 1) logger.info("[wechatcom] image compressed, sz={}".format(fsize(image_storage))) diff --git a/channel/wechatmp/passive_reply.py b/channel/wechatmp/passive_reply.py index 2941d4447..dc15a1453 100644 --- a/channel/wechatmp/passive_reply.py +++ b/channel/wechatmp/passive_reply.py @@ -5,7 +5,7 @@ import web from wechatpy import parse_message from wechatpy.replies import ImageReply, VoiceReply, create_reply - +import textwrap from bridge.context import * from bridge.reply import * from channel.wechatmp.common import * diff --git a/common/const.py b/common/const.py index b60d44576..481741d13 100644 --- a/common/const.py +++ b/common/const.py @@ -3,5 +3,6 @@ CHATGPT = "chatGPT" BAIDU = "baidu" CHATGPTONAZURE = "chatGPTOnAzure" +LINKAI = "linkai" VERSION = "1.3.0" diff --git a/config-template.json b/config-template.json index d179ff813..ae930de37 100644 --- a/config-template.json +++ b/config-template.json @@ -2,6 +2,7 @@ "open_ai_api_key": "YOUR API KEY", "model": "gpt-3.5-turbo", "proxy": "", + "hot_reload": false, "single_chat_prefix": [ "bot", "@bot" @@ -28,5 +29,8 @@ "conversation_max_tokens": 1000, "expires_in_seconds": 3600, "character_desc": "你是ChatGPT, 一个由OpenAI训练的大型语言模型, 你旨在回答并解决人们的任何问题,并且可以使用多种语言与人交流。", - "subscribe_msg": "感谢您的关注!\n这里是ChatGPT,可以自由对话。\n支持语音对话。\n支持图片输入。\n支持图片输出,画字开头的消息将按要求创作图片。\n支持tool、角色扮演和文字冒险等丰富的插件。\n输入{trigger_prefix}#help 查看详细指令。" + "subscribe_msg": "感谢您的关注!\n这里是ChatGPT,可以自由对话。\n支持语音对话。\n支持图片输入。\n支持图片输出,画字开头的消息将按要求创作图片。\n支持tool、角色扮演和文字冒险等丰富的插件。\n输入{trigger_prefix}#help 查看详细指令。", + "use_linkai": false, + "linkai_api_key": "", + "linkai_app_code": "" } diff --git a/config.py b/config.py index a460656ba..cc827cddc 100644 --- a/config.py +++ b/config.py @@ -22,8 +22,10 @@ # Bot触发配置 "single_chat_prefix": ["bot", "@bot"], # 私聊时文本需要包含该前缀才能触发机器人回复 "single_chat_reply_prefix": "[bot] ", # 私聊时自动回复的前缀,用于区分真人 - "group_chat_prefix": ["@bot"], # 群聊时包含该前缀则会触发机器人回复 + "single_chat_reply_suffix": "", # 私聊时自动回复的后缀,\n 可以换行 + "group_chat_prefix": ["@bot"], # 群聊时包含该前缀则会触发机器人回复 "group_chat_reply_prefix": "", # 群聊时自动回复的前缀 + "group_chat_reply_suffix": "", # 群聊时自动回复的后缀,\n 可以换行 "group_chat_keyword": [], # 群聊时包含该关键词则会触发机器人回复 "group_at_off": False, # 是否关闭群聊时@bot的触发 "group_name_white_list": ["ChatGPT测试群", "ChatGPT测试群2"], # 开启自动回复的群名称列表 @@ -36,7 +38,8 @@ # chatgpt会话参数 "expires_in_seconds": 3600, # 无操作会话的过期时间 - "character_desc": "你是ChatGPT, 一个由OpenAI训练的大型语言模型, 你旨在回答并解决人们的任何问题,并且可以使用多种语言与人交流。", # 人格描述 + # 人格描述 + "character_desc": "你是ChatGPT, 一个由OpenAI训练的大型语言模型, 你旨在回答并解决人们的任何问题,并且可以使用多种语言与人交流。", "conversation_max_tokens": 1000, # 支持上下文记忆的最多字符数 # chatgpt限流配置 "rate_limit_chatgpt": 20, # chatgpt的调用频率限制 @@ -101,6 +104,10 @@ "appdata_dir": "", # 数据目录 # 插件配置 "plugin_trigger_prefix": "$", # 规范插件提供聊天相关指令的前缀,建议不要和管理员指令前缀"#"冲突 + # 知识库平台配置 + "use_linkai": False, + "linkai_api_key": "", + "linkai_app_code": "" } @@ -224,3 +231,26 @@ def subscribe_msg(): trigger_prefix = conf().get("single_chat_prefix", [""])[0] msg = conf().get("subscribe_msg", "") return msg.format(trigger_prefix=trigger_prefix) + + +# global plugin config +plugin_config = {} + + +def write_plugin_config(pconf: dict): + """ + 写入插件全局配置 + :param pconf: 全量插件配置 + """ + global plugin_config + for k in pconf: + plugin_config[k.lower()] = pconf[k] + + +def pconf(plugin_name: str) -> dict: + """ + 根据插件名称获取配置 + :param plugin_name: 插件名称 + :return: 该插件的配置项 + """ + return plugin_config.get(plugin_name.lower()) diff --git a/docker/Dockerfile.alpine b/docker/Dockerfile.alpine deleted file mode 100644 index 61f80c28f..000000000 --- a/docker/Dockerfile.alpine +++ /dev/null @@ -1,39 +0,0 @@ -FROM python:3.10-alpine - -LABEL maintainer="foo@bar.com" -ARG TZ='Asia/Shanghai' - -ARG CHATGPT_ON_WECHAT_VER - -ENV BUILD_PREFIX=/app - -RUN apk add --no-cache \ - bash \ - curl \ - wget \ - && export BUILD_GITHUB_TAG=${CHATGPT_ON_WECHAT_VER:-`curl -sL "https://api.github.com/repos/zhayujie/chatgpt-on-wechat/releases/latest" | \ - grep '"tag_name":' | \ - sed -E 's/.*"([^"]+)".*/\1/'`} \ - && wget -t 3 -T 30 -nv -O chatgpt-on-wechat-${BUILD_GITHUB_TAG}.tar.gz \ - https://github.com/zhayujie/chatgpt-on-wechat/archive/refs/tags/${BUILD_GITHUB_TAG}.tar.gz \ - && tar -xzf chatgpt-on-wechat-${BUILD_GITHUB_TAG}.tar.gz \ - && mv chatgpt-on-wechat-${BUILD_GITHUB_TAG} ${BUILD_PREFIX} \ - && rm chatgpt-on-wechat-${BUILD_GITHUB_TAG}.tar.gz \ - && cd ${BUILD_PREFIX} \ - && cp config-template.json ${BUILD_PREFIX}/config.json \ - && /usr/local/bin/python -m pip install --no-cache --upgrade pip \ - && pip install --no-cache -r requirements.txt --extra-index-url https://alpine-wheels.github.io/index\ - && pip install --no-cache -r requirements-optional.txt --extra-index-url https://alpine-wheels.github.io/index\ - && apk del curl wget - -WORKDIR ${BUILD_PREFIX} - -ADD ./entrypoint.sh /entrypoint.sh - -RUN chmod +x /entrypoint.sh \ - && adduser -D -h /home/noroot -u 1000 -s /bin/bash noroot \ - && chown -R noroot:noroot ${BUILD_PREFIX} - -USER noroot - -ENTRYPOINT ["/entrypoint.sh"] diff --git a/docker/Dockerfile.alpine.latest b/docker/Dockerfile.alpine.latest deleted file mode 100644 index 432075cd1..000000000 --- a/docker/Dockerfile.alpine.latest +++ /dev/null @@ -1,29 +0,0 @@ -FROM python:3.10-alpine - -LABEL maintainer="foo@bar.com" -ARG TZ='Asia/Shanghai' - -ARG CHATGPT_ON_WECHAT_VER - -ENV BUILD_PREFIX=/app - -ADD . ${BUILD_PREFIX} - -RUN apk add --no-cache bash ffmpeg espeak \ - && cd ${BUILD_PREFIX} \ - && cp config-template.json config.json \ - && /usr/local/bin/python -m pip install --no-cache --upgrade pip \ - && pip install --no-cache -r requirements.txt --extra-index-url https://alpine-wheels.github.io/index\ - && pip install --no-cache -r requirements-optional.txt --extra-index-url https://alpine-wheels.github.io/index - -WORKDIR ${BUILD_PREFIX} - -ADD docker/entrypoint.sh /entrypoint.sh - -RUN chmod +x /entrypoint.sh \ - && adduser -D -h /home/noroot -u 1000 -s /bin/bash noroot \ - && chown -R noroot:noroot ${BUILD_PREFIX} - -USER noroot - -ENTRYPOINT ["docker/entrypoint.sh"] \ No newline at end of file diff --git a/docker/Dockerfile.debian b/docker/Dockerfile.debian deleted file mode 100644 index 798642d06..000000000 --- a/docker/Dockerfile.debian +++ /dev/null @@ -1,40 +0,0 @@ -FROM python:3.10 - -LABEL maintainer="foo@bar.com" -ARG TZ='Asia/Shanghai' - -ARG CHATGPT_ON_WECHAT_VER - -ENV BUILD_PREFIX=/app - -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - wget \ - curl \ - && rm -rf /var/lib/apt/lists/* \ - && export BUILD_GITHUB_TAG=${CHATGPT_ON_WECHAT_VER:-`curl -sL "https://api.github.com/repos/zhayujie/chatgpt-on-wechat/releases/latest" | \ - grep '"tag_name":' | \ - sed -E 's/.*"([^"]+)".*/\1/'`} \ - && wget -t 3 -T 30 -nv -O chatgpt-on-wechat-${BUILD_GITHUB_TAG}.tar.gz \ - https://github.com/zhayujie/chatgpt-on-wechat/archive/refs/tags/${BUILD_GITHUB_TAG}.tar.gz \ - && tar -xzf chatgpt-on-wechat-${BUILD_GITHUB_TAG}.tar.gz \ - && mv chatgpt-on-wechat-${BUILD_GITHUB_TAG} ${BUILD_PREFIX} \ - && rm chatgpt-on-wechat-${BUILD_GITHUB_TAG}.tar.gz \ - && cd ${BUILD_PREFIX} \ - && cp config-template.json ${BUILD_PREFIX}/config.json \ - && /usr/local/bin/python -m pip install --no-cache --upgrade pip \ - && pip install --no-cache -r requirements.txt \ - && pip install --no-cache -r requirements-optional.txt - -WORKDIR ${BUILD_PREFIX} - -ADD ./entrypoint.sh /entrypoint.sh - -RUN chmod +x /entrypoint.sh \ - && groupadd -r noroot \ - && useradd -r -g noroot -s /bin/bash -d /home/noroot noroot \ - && chown -R noroot:noroot ${BUILD_PREFIX} - -USER noroot - -ENTRYPOINT ["/entrypoint.sh"] diff --git a/docker/Dockerfile.latest b/docker/Dockerfile.latest index 7ec3909ee..59e9b60ec 100644 --- a/docker/Dockerfile.latest +++ b/docker/Dockerfile.latest @@ -6,7 +6,7 @@ ARG TZ='Asia/Shanghai' ARG CHATGPT_ON_WECHAT_VER RUN echo /etc/apt/sources.list -RUN sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list +# RUN sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list ENV BUILD_PREFIX=/app ADD . ${BUILD_PREFIX} @@ -25,10 +25,11 @@ WORKDIR ${BUILD_PREFIX} ADD docker/entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh \ + && mkdir -p /home/noroot \ && groupadd -r noroot \ && useradd -r -g noroot -s /bin/bash -d /home/noroot noroot \ - && chown -R noroot:noroot ${BUILD_PREFIX} + && chown -R noroot:noroot /home/noroot ${BUILD_PREFIX} /usr/local/lib USER noroot -ENTRYPOINT ["docker/entrypoint.sh"] \ No newline at end of file +ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file diff --git a/docker/build.alpine.sh b/docker/build.alpine.sh deleted file mode 100644 index fae7b3459..000000000 --- a/docker/build.alpine.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -# fetch latest release tag -CHATGPT_ON_WECHAT_TAG=`curl -sL "https://api.github.com/repos/zhayujie/chatgpt-on-wechat/releases/latest" | \ - grep '"tag_name":' | \ - sed -E 's/.*"([^"]+)".*/\1/'` - -# build image -docker build -f Dockerfile.alpine \ - --build-arg CHATGPT_ON_WECHAT_VER=$CHATGPT_ON_WECHAT_TAG \ - -t zhayujie/chatgpt-on-wechat . - -# tag image -docker tag zhayujie/chatgpt-on-wechat zhayujie/chatgpt-on-wechat:alpine -docker tag zhayujie/chatgpt-on-wechat zhayujie/chatgpt-on-wechat:$CHATGPT_ON_WECHAT_TAG-alpine diff --git a/docker/build.debian.sh b/docker/build.debian.sh deleted file mode 100644 index 9b2d4f391..000000000 --- a/docker/build.debian.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -# fetch latest release tag -CHATGPT_ON_WECHAT_TAG=`curl -sL "https://api.github.com/repos/zhayujie/chatgpt-on-wechat/releases/latest" | \ - grep '"tag_name":' | \ - sed -E 's/.*"([^"]+)".*/\1/'` - -# build image -docker build -f Dockerfile.debian \ - --build-arg CHATGPT_ON_WECHAT_VER=$CHATGPT_ON_WECHAT_TAG \ - -t zhayujie/chatgpt-on-wechat . - -# tag image -docker tag zhayujie/chatgpt-on-wechat zhayujie/chatgpt-on-wechat:debian -docker tag zhayujie/chatgpt-on-wechat zhayujie/chatgpt-on-wechat:$CHATGPT_ON_WECHAT_TAG-debian \ No newline at end of file diff --git a/docker/chatgpt-on-wechat-voice-reply/Dockerfile.alpine b/docker/chatgpt-on-wechat-voice-reply/Dockerfile.alpine deleted file mode 100644 index 91e94284f..000000000 --- a/docker/chatgpt-on-wechat-voice-reply/Dockerfile.alpine +++ /dev/null @@ -1,23 +0,0 @@ -FROM zhayujie/chatgpt-on-wechat:alpine - -LABEL maintainer="foo@bar.com" -ARG TZ='Asia/Shanghai' - -USER root - -RUN apk add --no-cache \ - ffmpeg \ - espeak \ - && pip install --no-cache \ - baidu-aip \ - chardet \ - SpeechRecognition - -# replace entrypoint -ADD ./entrypoint.sh /entrypoint.sh - -RUN chmod +x /entrypoint.sh - -USER noroot - -ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file diff --git a/docker/chatgpt-on-wechat-voice-reply/Dockerfile.debian b/docker/chatgpt-on-wechat-voice-reply/Dockerfile.debian deleted file mode 100644 index df58d02a9..000000000 --- a/docker/chatgpt-on-wechat-voice-reply/Dockerfile.debian +++ /dev/null @@ -1,24 +0,0 @@ -FROM zhayujie/chatgpt-on-wechat:debian - -LABEL maintainer="foo@bar.com" -ARG TZ='Asia/Shanghai' - -USER root - -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - ffmpeg \ - espeak \ - && pip install --no-cache \ - baidu-aip \ - chardet \ - SpeechRecognition - -# replace entrypoint -ADD ./entrypoint.sh /entrypoint.sh - -RUN chmod +x /entrypoint.sh - -USER noroot - -ENTRYPOINT ["/entrypoint.sh"] diff --git a/docker/chatgpt-on-wechat-voice-reply/docker-compose.yaml b/docker/chatgpt-on-wechat-voice-reply/docker-compose.yaml deleted file mode 100644 index 95ace286b..000000000 --- a/docker/chatgpt-on-wechat-voice-reply/docker-compose.yaml +++ /dev/null @@ -1,24 +0,0 @@ -version: '2.0' -services: - chatgpt-on-wechat: - build: - context: ./ - dockerfile: Dockerfile.alpine - image: zhayujie/chatgpt-on-wechat-voice-reply - container_name: chatgpt-on-wechat-voice-reply - environment: - OPEN_AI_API_KEY: 'YOUR API KEY' - OPEN_AI_PROXY: '' - SINGLE_CHAT_PREFIX: '["bot", "@bot"]' - SINGLE_CHAT_REPLY_PREFIX: '"[bot] "' - GROUP_CHAT_PREFIX: '["@bot"]' - GROUP_NAME_WHITE_LIST: '["ChatGPT测试群", "ChatGPT测试群2"]' - IMAGE_CREATE_PREFIX: '["画", "看", "找"]' - CONVERSATION_MAX_TOKENS: 1000 - SPEECH_RECOGNITION: 'true' - CHARACTER_DESC: '你是ChatGPT, 一个由OpenAI训练的大型语言模型, 你旨在回答并解决人们的任何问题,并且可以使用多种语言与人交流。' - EXPIRES_IN_SECONDS: 3600 - VOICE_REPLY_VOICE: 'true' - BAIDU_APP_ID: 'YOUR BAIDU APP ID' - BAIDU_API_KEY: 'YOUR BAIDU API KEY' - BAIDU_SECRET_KEY: 'YOUR BAIDU SERVICE KEY' \ No newline at end of file diff --git a/docker/chatgpt-on-wechat-voice-reply/entrypoint.sh b/docker/chatgpt-on-wechat-voice-reply/entrypoint.sh deleted file mode 100755 index 81241f313..000000000 --- a/docker/chatgpt-on-wechat-voice-reply/entrypoint.sh +++ /dev/null @@ -1,117 +0,0 @@ -#!/bin/bash -set -e - -# build prefix -CHATGPT_ON_WECHAT_PREFIX=${CHATGPT_ON_WECHAT_PREFIX:-""} -# path to config.json -CHATGPT_ON_WECHAT_CONFIG_PATH=${CHATGPT_ON_WECHAT_CONFIG_PATH:-""} -# execution command line -CHATGPT_ON_WECHAT_EXEC=${CHATGPT_ON_WECHAT_EXEC:-""} - -OPEN_AI_API_KEY=${OPEN_AI_API_KEY:-""} -OPEN_AI_PROXY=${OPEN_AI_PROXY:-""} -SINGLE_CHAT_PREFIX=${SINGLE_CHAT_PREFIX:-""} -SINGLE_CHAT_REPLY_PREFIX=${SINGLE_CHAT_REPLY_PREFIX:-""} -GROUP_CHAT_PREFIX=${GROUP_CHAT_PREFIX:-""} -GROUP_NAME_WHITE_LIST=${GROUP_NAME_WHITE_LIST:-""} -IMAGE_CREATE_PREFIX=${IMAGE_CREATE_PREFIX:-""} -CONVERSATION_MAX_TOKENS=${CONVERSATION_MAX_TOKENS:-""} -SPEECH_RECOGNITION=${SPEECH_RECOGNITION:-""} -CHARACTER_DESC=${CHARACTER_DESC:-""} -EXPIRES_IN_SECONDS=${EXPIRES_IN_SECONDS:-""} - -VOICE_REPLY_VOICE=${VOICE_REPLY_VOICE:-""} -BAIDU_APP_ID=${BAIDU_APP_ID:-""} -BAIDU_API_KEY=${BAIDU_API_KEY:-""} -BAIDU_SECRET_KEY=${BAIDU_SECRET_KEY:-""} - -# CHATGPT_ON_WECHAT_PREFIX is empty, use /app -if [ "$CHATGPT_ON_WECHAT_PREFIX" == "" ] ; then - CHATGPT_ON_WECHAT_PREFIX=/app -fi - -# CHATGPT_ON_WECHAT_CONFIG_PATH is empty, use '/app/config.json' -if [ "$CHATGPT_ON_WECHAT_CONFIG_PATH" == "" ] ; then - CHATGPT_ON_WECHAT_CONFIG_PATH=$CHATGPT_ON_WECHAT_PREFIX/config.json -fi - -# CHATGPT_ON_WECHAT_EXEC is empty, use ‘python app.py’ -if [ "$CHATGPT_ON_WECHAT_EXEC" == "" ] ; then - CHATGPT_ON_WECHAT_EXEC="python app.py" -fi - -# modify content in config.json -if [ "$OPEN_AI_API_KEY" != "" ] ; then - sed -i "s/\"open_ai_api_key\".*,$/\"open_ai_api_key\": \"$OPEN_AI_API_KEY\",/" $CHATGPT_ON_WECHAT_CONFIG_PATH -else - echo -e "\033[31m[Warning] You need to set OPEN_AI_API_KEY before running!\033[0m" -fi - -# use http_proxy as default -if [ "$HTTP_PROXY" != "" ] ; then - sed -i "s/\"proxy\".*,$/\"proxy\": \"$HTTP_PROXY\",/" $CHATGPT_ON_WECHAT_CONFIG_PATH -fi - -if [ "$OPEN_AI_PROXY" != "" ] ; then - sed -i "s/\"proxy\".*,$/\"proxy\": \"$OPEN_AI_PROXY\",/" $CHATGPT_ON_WECHAT_CONFIG_PATH -fi - -if [ "$SINGLE_CHAT_PREFIX" != "" ] ; then - sed -i "s/\"single_chat_prefix\".*,$/\"single_chat_prefix\": $SINGLE_CHAT_PREFIX,/" $CHATGPT_ON_WECHAT_CONFIG_PATH -fi - -if [ "$SINGLE_CHAT_REPLY_PREFIX" != "" ] ; then - sed -i "s/\"single_chat_reply_prefix\".*,$/\"single_chat_reply_prefix\": $SINGLE_CHAT_REPLY_PREFIX,/" $CHATGPT_ON_WECHAT_CONFIG_PATH -fi - -if [ "$GROUP_CHAT_PREFIX" != "" ] ; then - sed -i "s/\"group_chat_prefix\".*,$/\"group_chat_prefix\": $GROUP_CHAT_PREFIX,/" $CHATGPT_ON_WECHAT_CONFIG_PATH -fi - -if [ "$GROUP_NAME_WHITE_LIST" != "" ] ; then - sed -i "s/\"group_name_white_list\".*,$/\"group_name_white_list\": $GROUP_NAME_WHITE_LIST,/" $CHATGPT_ON_WECHAT_CONFIG_PATH -fi - -if [ "$IMAGE_CREATE_PREFIX" != "" ] ; then - sed -i "s/\"image_create_prefix\".*,$/\"image_create_prefix\": $IMAGE_CREATE_PREFIX,/" $CHATGPT_ON_WECHAT_CONFIG_PATH -fi - -if [ "$CONVERSATION_MAX_TOKENS" != "" ] ; then - sed -i "s/\"conversation_max_tokens\".*,$/\"conversation_max_tokens\": $CONVERSATION_MAX_TOKENS,/" $CHATGPT_ON_WECHAT_CONFIG_PATH -fi - -if [ "$SPEECH_RECOGNITION" != "" ] ; then - sed -i "s/\"speech_recognition\".*,$/\"speech_recognition\": $SPEECH_RECOGNITION,/" $CHATGPT_ON_WECHAT_CONFIG_PATH -fi - -if [ "$CHARACTER_DESC" != "" ] ; then - sed -i "s/\"character_desc\".*,$/\"character_desc\": \"$CHARACTER_DESC\",/" $CHATGPT_ON_WECHAT_CONFIG_PATH -fi - -if [ "$EXPIRES_IN_SECONDS" != "" ] ; then - sed -i "s/\"expires_in_seconds\".*$/\"expires_in_seconds\": $EXPIRES_IN_SECONDS/" $CHATGPT_ON_WECHAT_CONFIG_PATH -fi - -# append -if [ "$BAIDU_SECRET_KEY" != "" ] ; then - sed -i "1a \ \ \"baidu_secret_key\": \"$BAIDU_SECRET_KEY\"," $CHATGPT_ON_WECHAT_CONFIG_PATH -fi - -if [ "$BAIDU_API_KEY" != "" ] ; then - sed -i "1a \ \ \"baidu_api_key\": \"$BAIDU_API_KEY\"," $CHATGPT_ON_WECHAT_CONFIG_PATH -fi - -if [ "$BAIDU_APP_ID" != "" ] ; then - sed -i "1a \ \ \"baidu_app_id\": \"$BAIDU_APP_ID\"," $CHATGPT_ON_WECHAT_CONFIG_PATH -fi - -if [ "$VOICE_REPLY_VOICE" != "" ] ; then - sed -i "1a \ \ \"voice_reply_voice\": $VOICE_REPLY_VOICE," $CHATGPT_ON_WECHAT_CONFIG_PATH -fi - -# go to prefix dir -cd $CHATGPT_ON_WECHAT_PREFIX -# excute -$CHATGPT_ON_WECHAT_EXEC - - diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yml similarity index 68% rename from docker/docker-compose.yaml rename to docker/docker-compose.yml index 51ff2b9d2..b70f3efad 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yml @@ -1,20 +1,23 @@ version: '2.0' services: chatgpt-on-wechat: - build: - context: ./ - dockerfile: Dockerfile.alpine image: zhayujie/chatgpt-on-wechat - container_name: sample-chatgpt-on-wechat + container_name: chatgpt-on-wechat + security_opt: + - seccomp:unconfined environment: OPEN_AI_API_KEY: 'YOUR API KEY' - OPEN_AI_PROXY: '' + MODEL: 'gpt-3.5-turbo' + PROXY: '' SINGLE_CHAT_PREFIX: '["bot", "@bot"]' SINGLE_CHAT_REPLY_PREFIX: '"[bot] "' GROUP_CHAT_PREFIX: '["@bot"]' GROUP_NAME_WHITE_LIST: '["ChatGPT测试群", "ChatGPT测试群2"]' IMAGE_CREATE_PREFIX: '["画", "看", "找"]' CONVERSATION_MAX_TOKENS: 1000 - SPEECH_RECOGNITION: "False" + SPEECH_RECOGNITION: 'False' CHARACTER_DESC: '你是ChatGPT, 一个由OpenAI训练的大型语言模型, 你旨在回答并解决人们的任何问题,并且可以使用多种语言与人交流。' - EXPIRES_IN_SECONDS: 3600 \ No newline at end of file + EXPIRES_IN_SECONDS: 3600 + USE_LINKAI: 'False' + LINKAI_API_KEY: '' + LINKAI_APP_CODE: '' diff --git a/docker/sample-chatgpt-on-wechat/.env b/docker/sample-chatgpt-on-wechat/.env deleted file mode 100644 index 9a65cec62..000000000 --- a/docker/sample-chatgpt-on-wechat/.env +++ /dev/null @@ -1,16 +0,0 @@ -OPEN_AI_API_KEY=YOUR API KEY -OPEN_AI_PROXY= -SINGLE_CHAT_PREFIX=["bot", "@bot"] -SINGLE_CHAT_REPLY_PREFIX="[bot] " -GROUP_CHAT_PREFIX=["@bot"] -GROUP_NAME_WHITE_LIST=["ChatGPT测试群", "ChatGPT测试群2"] -IMAGE_CREATE_PREFIX=["画", "看", "找"] -CONVERSATION_MAX_TOKENS=1000 -SPEECH_RECOGNITION=false -CHARACTER_DESC=你是ChatGPT, 一个由OpenAI训练的大型语言模型, 你旨在回答并解决人们的任何问题,并且可以使用多种语言与人交流。 -EXPIRES_IN_SECONDS=3600 - -# Optional -#CHATGPT_ON_WECHAT_PREFIX=/app -#CHATGPT_ON_WECHAT_CONFIG_PATH=/app/config.json -#CHATGPT_ON_WECHAT_EXEC=python app.py \ No newline at end of file diff --git a/docker/sample-chatgpt-on-wechat/Makefile b/docker/sample-chatgpt-on-wechat/Makefile deleted file mode 100644 index 456063456..000000000 --- a/docker/sample-chatgpt-on-wechat/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -IMG:=`cat Name` -MOUNT:= -PORT_MAP:= -DOTENV:=.env -CONTAINER_NAME:=sample-chatgpt-on-wechat - -echo: - echo $(IMG) - -run_d: - docker rm $(CONTAINER_NAME) || echo - docker run -dt --name $(CONTAINER_NAME) $(PORT_MAP) \ - --env-file=$(DOTENV) \ - $(MOUNT) $(IMG) - -run_i: - docker rm $(CONTAINER_NAME) || echo - docker run -it --name $(CONTAINER_NAME) $(PORT_MAP) \ - --env-file=$(DOTENV) \ - $(MOUNT) $(IMG) - -stop: - docker stop $(CONTAINER_NAME) - -rm: stop - docker rm $(CONTAINER_NAME) diff --git a/docker/sample-chatgpt-on-wechat/Name b/docker/sample-chatgpt-on-wechat/Name deleted file mode 100644 index 47a5dd5b8..000000000 --- a/docker/sample-chatgpt-on-wechat/Name +++ /dev/null @@ -1 +0,0 @@ -zhayujie/chatgpt-on-wechat diff --git a/docs/images/contact.jpg b/docs/images/contact.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3a8a4123bdecb07a2cab1fcd8e858d2d60fb2277 GIT binary patch literal 154407 zcmb@t2UJr_^f!7!Z_=xjfFM;xdM79yL7Iq)7?Fe&26MqpwSz_5Y)z^nx z*;pExnj8M@6w8W}zrQyXI{^6j1_#<0UlhG|{e~$08rT~Mzy&A*qE601{uivQ%>VHG z_xYFqe>dEZzkLTr&;H@{U-thQ!QtW>K66EXy(skf9;Ork53;@(IV7_=* zu>T*r6r{NW!486S(;wRXA9~;qedix~;cuBMHu_+heQ+Ip=0@6=G`izf{-yixDNK4=O-}t!yZ?u!so&R_`Il2Ew|04@n z6KvSPGsxfDDdO*!|37a&-XY+4{Y~QFoy8;2#0Grw{~5QtewY5EeeYbh{5Rhdl;~gD zBgDk+U)niH9~{en>bf`?T>6*x^}hV)egEa@=4oX5FYOs@dgWg_(9h;S{;olWw*Tfk z1%lN7svC0G?!v#chpXv-JR?1>*#Da!>Us6@zjV-D+yD9y>7oB$eqe~re|>ffH2P0Q zpCGX2|7y#_)AYac!5&w@wf0Z{ot^%tZ>~Yt{_BH_tAXLaWn6vj{_DSg@Wuc5`+NVL z_kYL1)!X>L{Gd?V|LO(@UimNIKiKNO@$qsp`!l!x)&&dzL%y_w$bk^mO+K7QFzjAXiaSU*~gYL>12~DgnTs_4ua@0PIctU1tzphX2X) z=LG-_18}aF{7>E;P>VEzb3}mgfASsRF1XsUA_KP(7!5N%fklfvSzFpXxi+0@Vi90X0C)OwCIzMtzoA zom!vTlKKX<8+9Nxf;xdZi~1$?8|shLJ=CMr3)Gv`M>KRaTr{FIXKA!(Ola(AoM{4R z5Hv|NxipnD4K$rJqcn>&J2Yh46SP9Katz!?efD%zTPjgV~zdlR1X@IrCfQUgkySBNk2; zSr&bkn=BzLDJ&H%pIIhZ_D-BQA$daY#ElcdCsIySo#;3*cLLAK#d?m_l+}e5$(qO7 zz&gUZ#m2~Xn(YGHEw)IuEVlP-Lu{MujO>!^`s_~Z2=+Yo5A5UY2OL}+3LKUkJ{(CL zuQ>WResR)sN^%-OwuC&!A}NZ&4o63!>hl z&qX^$cf^FmOvFOOip2)S2&be@*`0cD3Uz8$oJm|=+)ezMc)R$H1XRL8B1)oKV(K*G zY4y_{r?XG@oIaG4lC+nMlWdgyCB-jgDitYJEj1&3LK-F=ApKH$OomQIUFNRL3z=bA zDp?g-57|7~Avr2JRXI<&7joau(4Nsa<9p`inenqMXD^%$JzITt@f`0t^K%c*HJ;m& zmyo|9pC;cUPd=}5-ury%`Dq1C1v7;Q3Lh1A6=fBj74sCwlujraDIt}bl(5Qj%C5=< z$`dMFDi$hnD(xyHRW;Q>)iZGG#rlhf`kMOD`kxJ`4U7#E3u%O%@OxtEsAWz7T4KUz>(m|0|4%v?Tw+4pjz zC17c4nPE9=C1n+0)oe{?ZDpNj{nJLlCd#JAmdh4y`^pw~<>HmpE7Nw;b|H4{SJ|%K zyjpej(B8m4-G1Sk{I%$7{nt-k_q^V8gZ{?V8|60+91I;Y9ae9u+Z%#es!DZWa;$M>EMp(o%}mH⁣T&KoXzF3()nU3Fa3UDw=n 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

vaokz;p9Fx2;ekA=9T61Q5v<&$eC97zxH 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 z z0Srch1C*i+l-cZ9dnWbjMuvbqoKv)lU*9bG94sqV;!^6^{fW+9Ca!M$v$-N|wcEP> zJ-fY&EO$)pT7%OfueI0T6i}BuA@M_un*icRfe~IzKebV9XOBO-s5m?k zb~upk^Bh`#0ix~%-4LMO+5Y#!tLgyF9Q2EirDgvR&t73T+LBd0_G!1o-yQx!!|G*M zqa2%+5iqoOqgjlmxs3_ZG@O3CJy!fX&;VsL%#fJTZD=S-2s&p?H7W5TImEkbi5B-taLz)6F~|Mznc@Ei2Kl$}12RkPr?cnn6k6h)40 z6RxdJM$P~UW(>vyQ-NU}AFb7xJkck1;KyjCXShouZLR5w#&fS*8`gh#M~wfhOCLB{ zbi3KsaWrDLWs2E37S)-zRLNb*zb2^Q=8w>#*)_6RlFx=PEpd`=(dUnx8wdsiHEDrx zlF;PymRObNa0A*!V}p3p&nzC`k|g~;FFlNJ@cFfp|Ev@1l*_>UQ9E}&q&kgt_2AtOCxRsC+REwNR0E-l;*ku;T3ahP93-ZXY6J~|!Wx}! zGW{0(daG!oNFVE1Bj_Dgh7=vINs<_l+FcyrIo<_{Zw537s;C06?~T^zv%f8!U)f;tA|k|l zlKYANMm3v*OS;Wk>7GuZWglYV)3OnI?dud{aE<{?ZnmA-*B5slqjmP3OwpV7&-||i zd}rITu=Q@jo^UvjI&vum!3;#p*dB($K!F1ouk>A9z0;&ecGt(|{pY7D_8VnNtEh|( zhjy{>=`Ux|v!j{U>FJa;*}7{q4+5w&55W8COP4^6I)jd8EoUuBxND#F{V*RfoGVW4 z-1j|FNkRa}D?s-1b%R&zhUIcv8rX^lWbp9@tI5AWVsvZ(CbWLM0kV`E;7WVFksxrI zuT<3ZfnPe)7MA)4=fM}#6fnzR1rK+*PE>ma;P`O2LJC7#GO0~;O&Kg%BIO}66AatI zTLa76x+Tg0rmGW27aI$!?W+Mcg_aPRayZj!v$d2Q_mfdDvhUrc`2E)P5nI#-_t~0G zRWgsXB2t1oI^_KTo+19!7HFQ_CZH$~I=$<_S9c&=iKk@SaZiDugfgssWH}`4uFjPI zo1vGU9Y0~zGUX`WbjzYaVh8_%{w#c+Qq-N(dL;Pt-DLHry`U?MTrvVpmP$dqg;-;I zBy!0W$hE%w`X@HTW#Kb<)Q}QGtVM&17W}M>;;Wjsa_KwRgW&{0v3~A*F@P<00hr*B zr+#1NF>9AojzHw2Ko{B%uyEC%L|>~Y$23gQNeHaE2-iR4jNShA?3LgD5E|xY0KnyA z?BOfqk!`f?$4PV~=Ll%#nDi{^|}YWY3X* z4DLvjDzIsNOFGE$gBnQ(D@Sn#XLn=f`gZ%&#L*X;us=u9f_<2o`OLot+r!%@*}M9y z7lVF#pKr)c0eAJ!ZBp?FN|}M-DCxRDLF6dbl4NRUcVpKDO;~Ol!d54w*MrFSy7QFr zDaNGIQq~7^`P2s#kdu9iQ2(}DwniJfL>ncDw?;M3E}kh89SI}%Ev^(4g!@im%F+Tg zTm9mb2&j~MpAJpG`@ZxKaRO*m2trYtxI1^ zd&HW+<`$l+jHOMqL3Or(Zs(MPVR`*DfOZMoko@tCGM;=Lap2fD^!8GRxS(%y!q+c6 zfBPO5QFqB{MCtYEvn0Aw3pO+GkroBz?Pf6xc$MgB#@Gegz%9W^bm1oGgF)56GfI; z*vq3TwZqT!163=K_1t%(d*AW`{-O)9ZwQNZ&SG; z^uyPYcQO!*Ab7vlr14ck0)lENwG`vlA}A@nfK2S_U?ibtsLp-4pLseq_FKD7ru! z)UsWX@@q_x*|Ky9Y||xoUZ=w!HMMw`BZ2hWrnn%}qUqR za(3b-oy8jV?o!`V6Dyy^rR9Aph*Yh{XvrT|jUCY&B8s>Z}J@TdK_a$DU{ z`UlKaB5ir1R3iy;f$~~H)TlhuI#`(v=KU7Y@W$G;=AdojXAs_D9Cqik{oSSTr>Jwm z)N1G=psopxB&84pBeHAgLB18^Fq(j zIMan+;yTgLgAalOP>sbqB89qIVCRHy3pWC`I*9sHFHp$^qIsVa;fj8n$vrf zU-5yfn=zvyb+>EkS!V|oHjV)dgG?cg)u8gFQUNh&&kwb062`GtfDcs0en9S zKvBP=b;k3QYjrTIgY94$BuBkDb<7#rRi?UVp!|hoJuG@k?JeBme`$!sd&W#fqckMl z3x*3!GLSht5%-(;#@2I`bX7vUk;)vN__#%SLPBYyh$RjgIiydkRQ7r`;%YPRxTk!CFS^r zfr~ri&n#+%eVG!_HgfIiQlV$qm3e{yXw=CkU~B@D>QkwE2IcgPr#KB5?J=srGJtZe zndj+NVYWZ!Km4H46;^j)cqI_=Wt1#F5g+%>`b*v*uFlg3q3oIUl<0c_YUZ*3&7oT4 zaK%gjClQnzmjFX;S4hR$So};((%+Y8aoN}Z(<+O=xmWAG_@w`YMJqH{@Oyo93CWG- zUlN#d>>6DfP=^JPV*tk~h^@TSkk#?W;ZGsbmI`FvXN7w7Y7#y&yiqhKSHuX+ij?k@(oC?Nic~Uea%{T+JeG zJ}=%*RV64>{)r3zhwymE5Qy*aH^}7+G-7_Y{~sb3FFEj)_>KJ-0;QHZe9XX-z@whA z5%n{m3;oE_xaEjT)@`8CZaX~LkPkg^mMP}M($F5;hVCG5;@NGxYgdvNfhz*M zMQX~i<%#ou)0h-cHE2@`Kt`Q7ipMdq0bffN)smLHE0b1ktc3P+ZR0QsSXoZ=neEj0 z+jBE;B62hi6fnS4jkXWaM`C7Zub=jAdRM{hegIv<^xDoyujdn1d%4tDM^DazA@9LZ zyBEMCT5~4zW0Bin2H{W^n%_lg=Oi~XR(XK3Go50;kDhH2OJJy#l$xr6iUk%qA~DL8 z2j&);H~7Sk!jrH}kjTj1rVsKS*C7mI77?IGkwU})fN}|YRIqp;Ay{|v$6c;iVP)R( zxxRJ_0Bmd6_l0~m;Xw6DrfQMR(__ukW{--iYWDl zxnEy|)C=8Gq@JMaqOOLOWyiiw*7>W4(9~K4;%)d0Zc8PaA=z*8>8+LSAQix!?6uO1 zXdsUOEINM0ozQT+d}^D|;B%F+8!A7QT>spa>Q8#07aP7Ws6CN7m*ZOT+MBoY<*qZJ z9|81F3PiZ04hl*l04(X*aX80kF2NC3Bpy6XSfuS5mD+1^=^16q0K$C^$N|G^yL7m(wFL_BODEc7hzjiwUc8wApZ$MW{JFv2h=+~} zP5O5@aybkh1%Qe@K{^?y?_;(aarASbX*?Wng@Cn5yO9P>w6@OwB@p?>25!nN48&~c zFu4fmSZ11;ljDM1=CvX+X0gE1bdP+rbs9imVW6Q)p+D7J} zB?qdARf@A35h!J_Ob;tb}zD{g27q!*`Jw;lBE(~D#mv4y^KT#NVcyh}3P z%WzEI&UZ_Uf%gOZ`4{zI=0&+6%~@YMd@UPtg4V%XvHLlikHW{rog<3PyW)jsMATCV|A!U=X}2T^oxcy>%%WPogHyb=PN%epG5`CkON#VH2wH& zd`40&(fZpvkaqjUINe0DcZI`~9U9$lClcFUy_IS@x9P-Z6xZ=~sM}Db#I4C#GrHH| zd~!<%^n~6m`V@W|;Zg8N|IWHcUnfyzb3UvB5iH|AwO^76TE|R*4xH>Y5J%MgdJZ*lyG(di>|nU%39$nOF0f zL4sJim`8j9xfOO{ZMrU3V9-G6zNSoa8GB8VfRh$`_0p~hp1hZQX8Bc;xMYggQJd~H zV%tPBf#92@8N;C)jySkB>re8CEcsFVjEK`VI`nMYLuR1?tK4^%j!gGe)BQ8~#x?eB zse34YiPp}6>h#ICMfZwL)L+|HF?@QyexJmbbxNn)Mcsyq@*f+`>m)ApT0=*wK3J>L zPgiSEZvN2{o%e~%kdFS=&Y5kqroUIYgEn@-GeZ6$f?LS!`9-pg*4Q853xFxcK4!F! zVDw-{*-n`1(TWhd!E04?Mx0K`*I)?}B?wb4uO>Cutj{yz5eYasxC2^;Tj9_m-O#Qr z(%)A^A@~{$>LP_cM{)}ag%X`9189?2$yGBUEHA`6-LCZ&Z!+(snW`VES-$$dkEegm z!+CM8&q(U{0r9;NuZws(J8iN&{7)DY*%6_ZxiMOJ z4>$SW1KGoh97QY~nSJu$kBvLOeig3ZnY?w2?~w}FZe4T#n2cHX{8zWR&x%+}j{SE| zTi)%@z&)6ZnY}uZJZiem;jMnM@8lOC9!o2N=kO=Zl=s};5#>~HY!aQlQ@7yyAfZ0z zhJJ+nk@#!!pm20$zi3@i`;m8tDpgeawpEN4Za(emWW{VXVU7hZPzNvl-5(2W6tCZ6 z9w0k2So1O3R;U!Zc6Fn1aG(#aS!(!vc9*u!mz}Yqz#Z zzcfeqK>Oq0RzMyGCAt_!iS$e^SF@1;*g+fp31#jU`5{X$p*BNW*5+N39%lxa-4x~m z3YfQi6Km`47`Hl)h&&J&I6SGOU#)#g(j~H zQZ15ZG-vyM3D|>=u9&xToo9U;aBQ?d7OS-|-GnJ(%y^8Nx_g~%+^$W?Lk+U{aaZ&n zUs2if4O1n3e2JDXUN6Z&yP>0uzxATF-NU%mz-R^o&9V9bqg;J|GBRPH*5U&qlF_r9 zg32ldp*o*eUcw{BqumDk$lFX%na~jo68>n zskz!1!?-QJvW+fT?#6*jlkptjO}LrNcjS~8dKFHgw#>~IR?I*Z?wZOy??yiV^1o$# zUb+cj;H@@EW94j~1b~p_G^9NoerJB%;!L*@#b~SKJ@&dJouq*E>b~_88{)#R zHVpE#)gMLId|!@DV4_TOX>xKUh=CoFB$=C7%~C=Yj*&+oB0V$Z82o(|7{Nt*mxqZW zzzzLM{NgfKxAE&lB^Wo6uP4iv-aR5OLk~}Fl^t>n8w;;aPp?c!kH6kBM)OjCul+Go zX3kRaeBpQ1d;wch$n+67rGB>qm-`1Ue#!q4x#-lZW0AkYN2aGRiop&1HIj5OM05S00@EIF4Smdx+H{ek-y_EC(gl@_}cqp7S zXA4T@xx>=+UY@~`btF~M!2w8NfQ|WN?EiY4VyO&z&7a>3lX6Ye4x_CQF0aO-=KXq@ z-X3$4uuSMf(iZQeK%zG^HPK4G(D>j%K~2y^%}FM(WQjs=GBK5;aLwt|FEa+ewYklM zUW3Z)T|p8(Gh~zJ#+J1W;@rw>^tbCIin+5>*o7Y?+@W# zADS=#Z5N$wK(2)qrqqDJ45yp`2uJsP-(czZk(6xYk(UahF+we?dj+uja0)nQTuQQp zXKlr+LTM~Wyvcm3sdwriffrs&oSx-_ee40Z`Z=05(Vo;$5>+JC7nQzIJX#m=kw7-T zj{UIP5)4={kHf7m&w+LP|BCwdc&5Mj|DjSUx)5?%p$NIlebWuyjF1wh$hAo1)@-73 z2}?o|Q*I%-lj~e^%Vl!E55vf9bD7O9pWo^G{XQPQe_h^>z0c0&b)K*1#SYPXEmk%e z!T3wW6*cfyKZ!ov(U*11!Q0kq9g7mpv3={dPP>WU`fV}bQbPKY`xq5CV|VGYmsjAz zZ#Hj|)Ka9yfXll|^ zFO=^Wpn5y_aw!>tP*iEsf?ju>sP$x@TUIN9SAd*FU{KF&SGMG$83TGDhsn@&ojoO--=K%s@48Fm3dI*+lZJ zydxjOyQlD$@aeqqanhsQ75{(udkp%XNQ#a-gbf2jbq`9f^AXtjU*6C&df@^fNH}9= zX+1xeD*v};fA07O6z%XfSwhpQ2WRqsN_JJ2scL~8rUAaSw{V3-vPCF28@Ox7zrd9` zxIj0kP>=>PB}2hPkO$Xn6!h5yh8uLpINyvnRcL%OsNbZ0($0($9x2SW%QpT&2XIoJ zHLyUlbsEEvs9?LZ4%5vb)fBu5vDM8l% ziu?~Qr2i}O3ty)I$H}R@Cl%WqZ33qo`2|NYT|eYu)!<*UenjR=7K@X;j9C$V>^Dwy9OR^+I?wd^(P!K~;|Yp^2y8sQs2X`kJ}tR%I`}Lb^;><$2OLRdoW9K;VH_0ZHd#m`KtCuk&nG5a^J@6h${DlUIfdC;sl@Bj9DM z$~(W^7ReIo{Qcxa_doN4 zA^$e&i1ljNOX=tHLI0G#ir}7A;lJ|sJEyPO>B5+46+8OR8hNF|d$52&{g(^}$5oz! z{yzHJ``wfo=jcv-?J(^k^UO6sI{Bi4I!^o1%)!VOwt-&CbZotLoFyDvNz%tWx&*$F z1U_~xU7fN)p20M;wVG^VhH24>Xn#V{RZdCZnZ+NZ4D74{oDZ_yeh;M@ zJddgeIDDuxLK7H2tXsAyGp+bZ0vs_oMRytOw z-jNv>e0F2ttoH7}vv!HFy<-OI$-d-gQIJnYf^*Y@E|tebA{ZiTJDC@1;+cP5IX zj&T!v;}vZ)@TnPB>J22GMZ>h`&-W(_NB)!*-}S+@Y0~deL8jhi5>%2-wxk;1qB#T! za@;FUPb77|DQ;WqHzpi(UuH0L*$;BWlj$xxOyce}f8wzg+=?i-h$mQl)G>Mq695lmk&+mHn%tMx2g%B{O7mbKs+Pt#wvpokG(oDss_N`V z%{r}L_)%^HqU=Z?x_CV2P8D$DN}FU?K{!wAPflo4dy-pktuj|WJ96&UVICn5&8g9) zZ|s@l{9EM42IzAENX`LilCr?E-&lM=+bTB^J;xzL!gkeS(Nn>}3OkOCyAaCGo0YQj z9FK9vr^ip28|txY!2kzO4<6<{4nv^fO|>brf7@Xv-P_wxn4e(RNQzhITwMm&iIM+%lF{;FFsZTU7EG=uD(Ye8Pp}Z8=%Noy-%QR$Z`rf4kv> z`2o0kisJ!H`No|))0o4*h?^rIb_;@z$yb#P?DW@8UsFiT_b9i1CJ|n|Y^7E9w$5n5 zlMSk@X(&tRn-;AuURHtGg{2>kLF)!w0fefH4&-&t4s@s4dTWsBgl^fzugV5{yvSK5 zj@|&uo8P5ukZ4){3#2e{&=ai7nE)!1szv7feTM|-*G?Nk%{dLUb?8cS-pz0~q_o8D zU*St2J2O&P>m7aFQjYnVAv%pA2p0aWqy@4+Jy#C<55l`G5MCWy&i*1Zg;?iw6$g*! zx-j2rgmG-Rc4}Nk(4KVQb1phtcq|}v(+VNMIOsD!jd|2MGV&5bW(5VA@g{=TmAyme zoS2+W2=G$ol`b#e4#2Pk?}CwAjuQ-w_D=I7v5)nEAO$Dn2>chaR5{vHA6V*TFdryg zcmQjWsK0PkKlsjq7h^@hbc*#91MVZNeSteE(i4vH(Z1ayx`R*vD!aBjVR_3=c;um=LD% z9LsSUesYxlez_It8r$E+fS1nN{*zH$-Nd{wI2@eIv_rR_B&8$(h1bupNf#1vFg~ z#m1@-qJfm7L>lZya%qcDCm+Tp4uwc@8}hBr1hd`GTs^P=t#zNd>C-!~XSbKfexC?`AXysJ z5vE$FW62Clzhx8g46HmNr5`%bE2#L(6z0g09Dw9;@$xtz+Y0U}eV_K6z~8i#;fkNw z$eW#k$3 z5FDZj#ZDcDiS?HwRz~sUoOh*|&bu%GqvUiNMZ` zQq;yyZ?M6}Sjeik^Dpcg0E4R)Fea#07+X6D8ZxD)Z9$l^5L1Dv$r7ukD^qrr`H*(( zYRk#Zz=uku-Le;D!ZOq9zVR%+Z@C7RS70fn)m>cXhhwyt-}1Of_A!P-v!`nOO|z0c za^t`eT%>Kr5ZaDeEexkm=7k4OGem*7d+CV{yr}U2wFdE8_$WMu*w;752Cs)}1HlD5 zZ-M2(+GYz)QjsaBC24Y}%?%(}lj4FdGD@F>m^lwldw^vi5vd8VXG z2Tg?3vv>xZHwCUD2I_#!=GGQ}Wc0|=cJ|(f<0)BoS3Vh?6_Kul_T_agnhwnMa)&xS zES5~olYQ9cq1C;WV;s>sJl*%CVWJH3(@891u5Z7~Up=I1{u2Iw z70aYR>0~yjBSOD_M6`}OKiHJu;5U~Xk%?x%zJvHRxEYWfL@!e-o@Ipn-!&oVSNP#5 zjw5C|@d6gwn!8}$Fiv1s+edLyZS>r5Vo#eVdiTmk*eNH-b_tmG6})>g0*(ZOcnZKmTkyZ6?zajvmYIcY z!Gzyj;hG~TlRW_?Oz2kUKQ*$qyq!333L5fX;lj~xpUC6~ofHMoA26}_oJ_w@gLJa^ zOXI3>pa8w0l)o0yBM$mt(x=tVMQrxC+1wO#3p|hOi}IRYs4c?>8As{Yt{pSk__ug7h9*cJ;2=9+MvI!oJq2 zk?q1XxI0wLqn?Lu{%v_mtcJOF1#LR2UzSwRC5OHzl(beXp*Q?TI%6L>TVY{+th6}@ zAB8^pw;J~L39Tl#HYT^uky)vtGv5wq{h-?v2cJ#{YPe+}UJ2fSR>MomdJI6%7=#)$ z>eOqnZqoluGgHyu zc6;CCcl9WDRVPs$jm+7QqaU26AEwL7?)&a24J+$%iGo~J(iY?(%&+xFd3YO2o@QR6 zC)rXk&4;b+DO>+RoNB|{N6!w#uiIV;pMTm3P;q2e%nqQsF>P9W=yAJG(vco>VhzGYN6fRXTt-9(>2d5%;JWo4zCj1jS%om!mV=-r^Y>Vb;ofAPS zh<)C&Ph$fZwwC=J|Clg_Y`_Su`y%%P;_L+##tSJxoK>0}>eXRnRXXc9I}YRfzH>S- z71pbw)Z?=WY1mn!FuQsPq5dp5v{fl_^XGzsuYs8)5RZ0nhLI(etvErHb={!8@(iKe zkYg_}e*U<2#mk^;x@mbYtnedDnk}6;BM_BnQy8JIMbq=$R3knvi!Uf|iaq8Ggc#`p zW%%g~Oj&rVa#(U!D!#e!DCUt7$Ju!Fyvt%m_;*TsP&p$d-#F!b|-Cn%ob?9BWHGW+b5_@l>EPQ?`t35~qY zDyOuq_%knG{4v@Ie^vW4zH5T$RjmD6Mf_m&KSDchOmCL(OMsWtbHQG@R})_PcQY`B zyx|Z$?llvEij5B2|LbWzJFu`Z0Pj^e);F;iDMrC>AMOWt?C}CL1^oxgU+YoG=^Bze z+4~(m{HBGa|(>O_PDzX{( z3h_0d@&>277UdL3?T)sy(_T31{bv}DDG1)FFyevgrsZToZZ3=K%aaXC`>EL=H2I;n zU~xw2z8H!g6`_K9B}6dwF+7rhsHsE)Z>n93B=}$44lbweob_|`vs#Ob56Wl7s+ndy zO{;9;gx~sb*3CO2!oTAeF!sjyI#oeH?+_AqWwtACVBH~)ul9zWnu;9HR=3o*(n!>` z+)=3*va1mjZM}DKnmkl^;J^&bK{u+Ms$20T!`9fdX0qbRO_KI=f~@2RE>5G#|qH$C56(61}@szn4b^*9HHnU<(vI-a_Ze1#r4i(9?% z2;eJ+KS(&#_;ejH3TmxmzWB@%re**x3Zo!k=XP};OL^g z#JU)0tG--q$UjAi_S9xW@7zDvd9JiN*4$dySQpOOP2 z&ng;X4cG0#!MvA;&O=R^CB<(+8T_gB2^;uEd^j@cB^A48Zd)6in?w6j&kqhp``F&7H|jBk^c>*Hk&vH` zMXaL}jIZ5$*gqTV9WGV^pEmCMQOXBFFCc4uZpmVy+1{V-^!aH%Zhmwbi) z7O4-P1RV>bS<*LWF;TnOxnJpytBHkkk1-XaZGB@x`ufw`x4~`qC%PFNSH#uBU{A>m z5{^OLqcM#LYn(<$;Ts-F%s+9!Bo<1};pk5ZAJ@n)+@p*ByW1$d;f9JP{v;5%%jb^b``HTewX`28D z4I0pLYam0v8X!HJ{blA~=e%&`j(MOqvS_3uW~di_@5yNWrX-t_P{=%s9>tU;VL6KT z7Sp7u*fHOw+O8a0aHz|ZvNfI9$@}Z43^3Pc;2zLXe^U5cj*@$FcGwK@LJvY(fL5c~ zbKb!os|NPgJGhk?rW(tg65djC9`Q?3oT(WFr1<0Kp#^2jf6h8HyLbU7BkfgG(JQ}+ z=6cnsFD9dij|uz4D-(nGN;aO@y$KOJr-s9=pS&z4*N|Pp4KshajF>F;uJK=7gVx?XJ_z+(5%;@sYW}G?{RIY6uhn1HYzlI5 znO%Ie=w`W{z1mcvz0{(3TdC7DOu^fzfzUQ1@XKiQu=ggICY2luUjpY!9{7}dMcF?dEs?x{SOv$5L>{>SkNT*O zp8=+tPYYRs*0i6pJ82gtW5bwQH$_z}{Px&oC}a`8#)2 z=AT^rYv4gTV(incIf$r(+#M<`moSulI{zP%kUVIVrDLb-|IPp4QCTM31c9u=j6cJqd0tEn+UK)gH9t?;ayDVF8G z#LCldCrHTO)=B4*+1xiXmHFt~+`$3ylkO($l&$mw5R#yvMis##-o(h2>nBNrt2*wh zW9V@hBj@8&p1q9#7)%4+7%a>|mcsMdC5`pfy=9|S`s)fXr^q8@K;FZ^eYXlb6u{C^ zOiOT)JIYd@6yYeZCQ7E_OE-}jxbo<9l=xs6G!^ilvj&7%FWgnSX}MjsM=N6u_5ykr zSgX9N;g6Wt7l(Dr@!|O5Jz{FGAy0qLz@)lb?Y4N}*Mobfj{%eZ@gLOT*=5js>!hr& z5}h{iFWBFyo|{tlV2j0%9sP9E5?TS8mS|1!%Z~WT+W{^OX_bTY9j3{6HR{3e!%DG( z!AY@IE#CnTfXQUS0QPaC3>ynmK_0N7A7t_y6V~zNC&}7T_s~nFz#E0M?oaRx7Ncdd zYgRCi*nY|awgDDQ6rl!JDTb_m2lsHplR=sV8h#u;ou=9;(7Gt{gSY#qOU~|@DTO6v zx`Lw&@yM#A>*5}gT{Fu+loFZy7!#H5b*hZTk~Y(b43iKqphkFc(t#V1LXtM+~@`c-kKvuEFBQWEn zZ>lPpY?cz(7ce%E^-5m$6siw1t=UfR|K%}F;I~~~_o6jEDOFwH;IN`_FFXLMsAqlS zfYr}i86G}q?EG$+s*yl5+s61YcEZ7tlhOu=z>1n!x?)oJR_di-&3aLG!PoIk%;Va? zi7(X{7aY=Nx07bguJi>hfM**wJfM7-2Om{&TMJdpCZDM>D1)@i^kJ0+3_4+iCUxGn zE0jw6trZub0qoIu_TpoIEPHDq3 z55xb1C@fFF-7WNqB{1Bv>=njO9UeGU9fTrYc^Ht{(^Z)bjAWtgWW4JQ#F%=c*DTXc zfO&YIy1>}29^zE@5k|Bb8D@%JNBMQ^%CrjBnxh!40*D|Mc*{_SqNM4vSH{IXDn6fq z4a(F4{`&1BBk1oSZS!HbsHGK?!6+S;9Av~%cQ|~;*=WMl1+V=RbSU%TMJ$eat>9mL z>Fuo(?*U8JHh67{g~kbf5`MO!w^cX~QU@hLXRB#7P=@(A2t&xqf}j&v;B7+7mjL0W z_P*PUCEbH|r)CrWf?YzuD#^yLv0uZhV#~K(R^d#CyXfxS!xj1dGsM*|KKLDshsTo| zNg-y_)MIiF0pR2q4P2?^nR;c{9$|UdA3El1H}VIRV)@hQ-&DPI+CPl!-^QvaNk4o; znXdRIw6Enc{vZRCYwQZ}q15}CF#MH5pciC%c)e<#{Y2qN1D9D^DG*0pAEohU+?!941JnfQembSDwX2MKzfNKVv^?MU3ET109X0eJE#V)q+0$0dZYfnz;EEvMeR7A=;nnh4guFSkeast1ZUbkg_t z-2$KXQfhrUcf{;tu1bmOfjLy`#|ItV5EIygkQ9T`&uERW+&Y>^Z+hR(xeh`1>HwkX zyUHEYb2Zj@8^2&VZdtXjiM(BoJJt{|eLDo+Vu12OdB#856Ls2q8eY-qQL2V<*TA6V z=9ynR+Kk)miLcSs3S};slrsJdPY?PMyGS|^rsc7>|8za!4S}tDAJj;b%A;ViSZA{W zsLukNm3cw;0uQg{^t$2aKa>O$i$Nu#Up$N_?}jR!G*&b+o=5(!WF5~IouhXOC)ZT0 zt?7+T4sToND@abGZGr#2kiC$DVKaYDG6PSGV`mhAo#6oPSZ5~YF^)l|g?RzZ6QG;# z2V2y?z913%^@>u|75D{WbKwwP6+WF!`Htk{DLj^jryqBr`=$#VMbOXhdn>I`NXc=z ziCZ1kX2DCBw{A4x%L>AyImd2Mt$ZOqmbNKv?ezd9~ZW#y>4cEWjHpyGriXmPaO9wM`PFnHdrav~kV> znWeqmo1Pnks2{4I=a9X;f8fIS>D*mt6GCK?ehCQ)E-ygUcCz!RYed0kY+^A?b-{7n zk0syMh^Nb+2&cYiy)$(b!G&=V^`Awo8mFwa$l(1~0IEvRf4+`vUBS8gq^U11oH zZi4PP?nY2QJ0jJIKAGJyKXbf?468`e;9`3VsCU`|`z+D!Tc_>tS~gz~@qcM(H(=z3 zM7|Mx7@~OPw<#B)T;^xbg;kc%%~$$2gU>nLCj2zx-lOD4hHanq^S<&)+TZ8W6?)G) zK*)hZ{-1W~S8XK2y+IXlKD&<$1G&jqIj-N*bBR5{c@6vdTO{18mF`O>C>*Ob{vkqhdI_p1hne|$EgPdj_`8obE{cUb_xXy;p&I_g!D+Et5Ru+;^gdW+E-{Evb zgI3PZ*BC>Su2NMAZH{Hhg@ulE0rDKC@nr4oFfW!O8n?Y43n&zVILZPZ6jgsf9sK(W zhE-I!cuG3%gZ}N6#1J?RJS9{!;By*U8kENl5#T6&U;(8|8%Gv{i6I7x>7$@pZ^C0f zn&{HLRRBw15NIMT8zl;`^rp7y{~!ZWaL!#zA_ZiCa=oPf|9?PVlMWktr`ioc^I*Z_ zqVS6unE8Ky3%(qFSE@Bz(2JF64EkMsY}PTyN)6BRL|~`K4W}3t9v8s>{|6;wreip# zkTw7FlLP-UE7*{II`XX9ln>{ly$zuumpS`qW`je($NAO1&FT1`Hzv@1{38x9I5JPb z80kXU_`*eA)kuC}Y=P=0|6syU2pods>>n*WbqIe(`afePE@eR}M!2KcNnnL( zW=b5PRsf*Z8+^RU)@fDawEOcKT+`6fq{dCkjfP(OCDI*E|NHZ!DeW8nYsqft>G!}E zqHT&SN-IovgiD307zKWN_q9s4;I3OGNDfxG+p9r1GOC%FFEDnB6w{U3$T=opra*9^ z3sJHtn4(Q^Ky`K#fb6u;`ltyh?8aQJZSib~PU`VSjzq5p$Qh`U8ee$_x0>4UeK>h9 z@-HHY^n-H%rC9SRE5(?-Op;v{)}MZHEjHmV;*B2RR6of~$Mi77yZ!_av!W!_JJP`w z>_Gw*H`OU?IKo_M&VcsR7+;nfxvv*o=jtqjYCD@?x)*YV>C}8`OrYM)Ugls&3tWHp zUG$+|9$|;YXL9lgsnk}vj`Tgeyi*_MHVw%I=S0%?Fbq2n4WtZU6EHT;YUg}j8Xf{H z!xl}MjuuUhSCWCecE-^PV+}5kqfUwX{fLZ~&jEFzv&eJMdsNGaZ0nZn{s0&J40`B(sk-_iK9>O*O{P0{Ch%t zB@>np?_AZ?o(<6lqFK5*1+@JiGB5RUI<#Ci$>?9cfg-+V3+dPyd{`|~8(4{lkImbM zcPGNq`6K@7%KaGb=82w*9e86T&E>}=YjDjMqYlxLhn9RKW9GX)G3x(34T|>N^zN(E zol@{{eO-HCDO6=PBqO_IU=Yj@hh$SBCBnxO0gkUc@|YfO(;q zhTr^?!fdTkeA#ju$lHII=q#JOL`-G-2{~PR-2!j2ER6`RdQ&N2hgKN-PUQu%VsxbrKaHFqUDx0rT#1lg+-W?6Ysb*{qjgwQsHI z7NPSRwt4EjGo}$u1vU7hN@aGiEtZ{cUk`KKR0{qp#VyG%$0OXFCfbWq=N)0`dC>0a z{n$Z0Ls%;Y#oO_f?vH-zgWH_SD?QP!&m4$*UUIc95yJ5saB|+tPHK@xKM0}`^~ zPlr-|8e{3kbkLKo!E*HMDqhZD1OjaOS9B$Cqvkb%vFroz)^0Y*?!Y0jb3BW{}D z4Im0~>qDQ)vDa_stSP%|nc(Hpd6nj#8g^(doD6SVf3w>%S80X8Ke9l^>AL9&Ep8m`P2Q5LBG!5?5w3qI z@@oyqQZjQm330DJEyj7Yy_8I5U7W%3(|;%zFW;$0Nmnq0dx4#^#o$%n1F~J0d%ves zr$Y3fqj^~8oLx>TO^>wg-f9PR?-P&eGD_O(2U)2nhYsCKEB3^!dof!g|N0D7hdxEy ze`wvjAKlCQ9^XKGZ6VR;`tiZ|surB(SB*bR=WUV{=&F|}Vv1@L)*rc(4+xsGU(!Xy zJxdi^Jzi;MZ1gVn)o_->(fFZgISsCJYKdpBlK#p|%Q(#hWbu8PT)uscPt6Gg0=|)* zTa%Mp9?CcVpdaf_P6cQCIV8iaFQH&YzjY$`u$C8!G!{cH>IS{)0e1iS*jr~OHjRW* z<^=mjNOcgCg0i(-@7jg@J@NDuo~7G)qy$g&2MFzUEiKC~XZ`l~H?X@-Y1?8D{uO`? zD2p%}zTuPPVnN)imIe6ZWg zJ)Pd8o&E6xR%I*m>54kYuwp*ths#4QlttFVK3sg4^K>B&wZIj;0G=n` zGG4St9nl#y7+U-?Vadd=D1E=NesW~Q>YWQ;l@OBKwt=Q2#2QKq+Y?hLuof}UP_;hf0j=YgiM7;-S)W_F3p9u2MF2q&&NSbV%S(%N45|_{@J-_hK=d_ zu1iS-XbLJaDPIeW;wtSE#AG5y2^~v@C&XFJJ`TGNGg^^rYwUAEJE|M?=75=~dvUYk zAqk{L7D#>LQh}9K5vI~Zh$xH@rOckX{PE`K zfwAlaYteK*YP~fdF$?~sLoAnjU9aY(m;$f_i{K9s$u9XIt+ALoK@#2hGGsTR06;<> zC5rdhyO=-0=SqdN-}VFFQH$$UAncFF@gx795m-tPT2tWwGM|%hNTvEwrQ^7euI3+Y z5KdtzI4P+XFkuj68DaH?k3`LVX0=&!a0$diX-e2!;+|u>a%G<4oJ72PjvR_lZLxI} zT&)QNxj7Bo=`UMUo~QqW+o088HjtQ#_%}I1BURCJ1CMW@S1MFjZwGo+f`UH_vVXNm z)c9<&5h>w|)WaG(#_nzDJ&YUP02{kh#9+I{oVJKJ8h{AuD>oD}7s@HUl? zed>Cg_hQRw^DPYs^@+GEzx(+(+4DEYMd0cv;&n{Ns1LoDXUxROytI&XS>6boZkh1k z`&7r`c03`y+>E?^#OrT&T;6-%8N8C&8l;S9{o2-D1eS-$+UF=VLtsiI%OR`C$YlLG zJ${cFH+M#qMWtwtr$4hU)=OM0yFDVBT?9t_C+B(~3(~3{O z^%n2lYckQ!UEC;6nL=(|bA|BzerCiwl-%Ire;s=UZQdXx6@t)! z^vkP^=vjSW{uC@R3RUqYXpp*4y?b3$VnvH4=^FDJO!$(y%AreX3Hp=Vv~*qt$9djU z{@)~${LkjNO5JVVOJ2SO^%sORT@@juVs76qwVFmk!ea?t$KYm*Oxh^{xeab&YsY!9NbT_I*689YlsNlVDt8A zd2Kx(`hdyG#^E+iX{pF(yc&=T+rXUY*|~g4)AgC0E9$4eUNvKIhn$>|(dHbz+#!a_ zA4`328*ffJZ+MLB^#uE{+S$kr;Q}~R6Rw@U_lncQ{okI-JluP&OnlBVE+m6HMC$IC zqPK}ebd@w~_De#F439<2CN?D*awqPqfw3rG8-N#bkRJ_yhHjum%bTKm~O?j z_Vk{ZjbsPM-!#Fvyja79kh6Sk5xW)vzBn+ox>}mzTOdlPMketC2lG4b&4j4- zR=%3l7l#Z9`HbW9y?gSNFaZIRZ297dB!Z&__M=lTe)-=3Yd8z-)o~n3$HbM8_t5f> ze{EA55aD6T*QOtjH$0KRBajky?bW_7$KVr$-{<_R+5LvcimjL#AeMFT4zEXSf|#nb z_g}Z@Ht}T0$0C2FIl8>E49O z8zE&uRJsVA&*WUcwk}MgH7}YD$vn>o7?6%0BYl7J-G+nE>v4ZleeR&Xv6@sHz8ySz zc4~m@SV=k`jGj9hUx8XK z-!GqT3%Q!jD9DTb;|shR+c6;Nd*5l!i-8Ce^C-x(cCIrmCTC=zDF?Um`i{9#zZT7z z@tiQ}WW9G87tHIjU9;tAoOqOw5Wpj(==2^mzU3KsspyB9PaVZ>siwY^7Z6;uLYNyK zIc>&7nBUXJ^-_9I+>93OaxO@4IxzNiAbwh!OQl-W5gIk%$ z`OPZf*JDlkU$yaQ>i;o{5;ZyuG5r2*L{8jbV9@X^7Xlmi4X=FPr4EE%)LpTaT&Xr3~`WV zTjv0c^=E0TnV>=cxUQB1)0o$`ae{KEd<=y$_i2rxx9`hcM-7T$@&zXPkE{V#ZKYm* gp6Q^68S$P$3-1k2JjnnLu*t5H5d!@+%zvZ*4=EroJ^%m! literal 0 HcmV?d00001 diff --git a/lib/itchat/components/register.py b/lib/itchat/components/register.py index b8bbc2940..e76f2c46d 100644 --- a/lib/itchat/components/register.py +++ b/lib/itchat/components/register.py @@ -25,8 +25,9 @@ def auto_login(self, hotReload=False, statusStorageDir='itchat.pkl', self.useHotReload = hotReload self.hotReloadDir = statusStorageDir if hotReload: - if rval:=self.load_login_status(statusStorageDir, - loginCallback=loginCallback, exitCallback=exitCallback): + rval=self.load_login_status(statusStorageDir, + loginCallback=loginCallback, exitCallback=exitCallback) + if rval: return logger.error('Hot reload failed, logging in normally, error={}'.format(rval)) self.logout() diff --git a/nixpacks.toml b/nixpacks.toml index d64e95563..627d2e7f2 100644 --- a/nixpacks.toml +++ b/nixpacks.toml @@ -1,7 +1,7 @@ -providers = ['python'] - [phases.setup] nixPkgs = ['python310'] -cmds = ['apt-get update','apt-get install -y --no-install-recommends ffmpeg espeak libavcodec-extra','python -m venv /opt/venv && . /opt/venv/bin/activate && pip install -r requirements-optional.txt'] +cmds = ['apt-get update','apt-get install -y --no-install-recommends ffmpeg espeak libavcodec-extra'] +[phases.install] +cmds = ['python -m venv /opt/venv && . /opt/venv/bin/activate && pip install -r requirements.txt && pip install -r requirements-optional.txt'] [start] cmd = "python ./app.py" \ No newline at end of file diff --git a/plugins/banwords/banwords.py b/plugins/banwords/banwords.py index 118b9631c..2a33a5aff 100644 --- a/plugins/banwords/banwords.py +++ b/plugins/banwords/banwords.py @@ -24,16 +24,17 @@ class Banwords(Plugin): def __init__(self): super().__init__() try: + # load config + conf = super().load_config() curdir = os.path.dirname(__file__) - config_path = os.path.join(curdir, "config.json") - conf = None - if not os.path.exists(config_path): - conf = {"action": "ignore"} - with open(config_path, "w") as f: - json.dump(conf, f, indent=4) - else: - with open(config_path, "r") as f: - conf = json.load(f) + if not conf: + # 配置不存在则写入默认配置 + config_path = os.path.join(curdir, "config.json") + if not os.path.exists(config_path): + conf = {"action": "ignore"} + with open(config_path, "w") as f: + json.dump(conf, f, indent=4) + self.searchr = WordsSearch() self.action = conf["action"] banwords_path = os.path.join(curdir, "banwords.txt") diff --git a/plugins/banwords/banwords.txt b/plugins/banwords/banwords.txt index 8df9926aa..63b5e49cf 100644 --- a/plugins/banwords/banwords.txt +++ b/plugins/banwords/banwords.txt @@ -1,5 +1,7 @@ nipples pennis +8964 +89535 法轮功 刁进平 习尽评 @@ -13,6 +15,7 @@ pennis 招妓 阴唇 操你妈 +你妈的 精子 奸淫 贱人 @@ -120,6 +123,7 @@ pennis 干穴 开苞 口活 +口交 狼友 春药 风艳阁 @@ -174,7 +178,6 @@ pennis 爱图公园 色色五月天 鹿城娱乐 -色色 幼香阁 隐窝窝 乱伦熟女网 @@ -191,7 +194,6 @@ pennis 国家主要部委 国民党 国民党万岁 -台办 台湾党 台湾帝国 台湾共产党 @@ -275,7 +277,8 @@ g网 春宫图 成人影视 xing奴隶 -性奴隶 +奴隶 +性奴 极度高潮 乳房照 膣壁 diff --git a/plugins/bdunit/bdunit.py b/plugins/bdunit/bdunit.py index c99f2b045..1301caa9f 100644 --- a/plugins/bdunit/bdunit.py +++ b/plugins/bdunit/bdunit.py @@ -29,10 +29,8 @@ class BDunit(Plugin): def __init__(self): super().__init__() try: - curdir = os.path.dirname(__file__) - config_path = os.path.join(curdir, "config.json") - conf = None - if not os.path.exists(config_path): + conf = super().load_config() + if not conf: raise Exception("config.json not found") else: with open(config_path, "r") as f: @@ -45,7 +43,7 @@ def __init__(self): self.service_id = os.environ.get("bdubit_service_id","") self.api_key = os.environ.get("bdubit_api_key","") self.secret_key = os.environ.get("bdubit_secret_key","") - + self.access_token = self.get_token() self.handlers[Event.ON_HANDLE_CONTEXT] = self.on_handle_context logger.info("[BDunit] inited") diff --git a/plugins/config.json.template b/plugins/config.json.template new file mode 100644 index 000000000..5c2b19bdc --- /dev/null +++ b/plugins/config.json.template @@ -0,0 +1,24 @@ +{ + "godcmd": { + "password": "", + "admin_users": [] + }, + "banwords": { + "action": "replace", + "reply_filter": true, + "reply_action": "ignore" + }, + "tool": { + "tools": [ + "python", + "url-get", + "terminal", + "meteo-weather" + ], + "kwargs": { + "top_k_results": 2, + "no_default": false, + "model_name": "gpt-3.5-turbo" + } + } +} diff --git a/plugins/dungeon/dungeon.py b/plugins/dungeon/dungeon.py index 07fbde713..dce62cdfb 100644 --- a/plugins/dungeon/dungeon.py +++ b/plugins/dungeon/dungeon.py @@ -64,7 +64,7 @@ def on_handle_context(self, e_context: EventContext): if e_context["context"].type != ContextType.TEXT: return bottype = Bridge().get_bot_type("chat") - if bottype not in [const.OPEN_AI, const.CHATGPT, const.CHATGPTONAZURE]: + if bottype not in [const.OPEN_AI, const.CHATGPT, const.CHATGPTONAZURE, const.LINKAI]: return bot = Bridge().get_bot("chat") content = e_context["context"].content[:] diff --git a/plugins/event.py b/plugins/event.py index df8c609e7..719e6fcac 100644 --- a/plugins/event.py +++ b/plugins/event.py @@ -50,3 +50,6 @@ def __delitem__(self, key): def is_pass(self): return self.action == EventAction.BREAK_PASS + + def is_break(self): + return self.action == EventAction.BREAK or self.action == EventAction.BREAK_PASS diff --git a/plugins/godcmd/godcmd.py b/plugins/godcmd/godcmd.py index 7107bdc16..27d4082f4 100644 --- a/plugins/godcmd/godcmd.py +++ b/plugins/godcmd/godcmd.py @@ -41,6 +41,18 @@ "alias": ["reset_openai_api_key"], "desc": "重置为默认的api_key", }, + "set_gpt_model": { + "alias": ["set_gpt_model"], + "desc": "设置你的私有模型", + }, + "reset_gpt_model": { + "alias": ["reset_gpt_model"], + "desc": "重置你的私有模型", + }, + "gpt_model": { + "alias": ["gpt_model"], + "desc": "查询你使用的模型", + }, "id": { "alias": ["id", "用户"], "desc": "获取用户id", # wechaty和wechatmp的用户id不会变化,可用于绑定管理员 @@ -166,16 +178,13 @@ class Godcmd(Plugin): def __init__(self): super().__init__() - curdir = os.path.dirname(__file__) - config_path = os.path.join(curdir, "config.json") - gconf = None - if not os.path.exists(config_path): - gconf = {"password": "", "admin_users": []} - with open(config_path, "w") as f: - json.dump(gconf, f, indent=4) - else: - with open(config_path, "r") as f: - gconf = json.load(f) + config_path = os.path.join(os.path.dirname(__file__), "config.json") + gconf = super().load_config() + if not gconf: + if not os.path.exists(config_path): + gconf = {"password": "", "admin_users": []} + with open(config_path, "w") as f: + json.dump(gconf, f, indent=4) if gconf["password"] == "": self.temp_password = "".join(random.sample(string.digits, 4)) logger.info("[Godcmd] 因未设置口令,本次的临时口令为%s。" % self.temp_password) @@ -264,8 +273,28 @@ def on_handle_context(self, e_context: EventContext): ok, result = True, "你的OpenAI私有api_key已清除" except Exception as e: ok, result = False, "你没有设置私有api_key" + elif cmd == "set_gpt_model": + if len(args) == 1: + user_data = conf().get_user_data(user) + user_data["gpt_model"] = args[0] + ok, result = True, "你的GPT模型已设置为" + args[0] + else: + ok, result = False, "请提供一个GPT模型" + elif cmd == "gpt_model": + user_data = conf().get_user_data(user) + model = conf().get("model") + if "gpt_model" in user_data: + model = user_data["gpt_model"] + ok, result = True, "你的GPT模型为" + str(model) + elif cmd == "reset_gpt_model": + try: + user_data = conf().get_user_data(user) + user_data.pop("gpt_model") + ok, result = True, "你的GPT模型已重置" + except Exception as e: + ok, result = False, "你没有设置私有GPT模型" elif cmd == "reset": - if bottype in [const.OPEN_AI, const.CHATGPT, const.CHATGPTONAZURE]: + if bottype in [const.OPEN_AI, const.CHATGPT, const.CHATGPTONAZURE, const.LINKAI]: bot.sessions.clear_session(session_id) channel.cancel_session(session_id) ok, result = True, "会话已重置" @@ -288,7 +317,7 @@ def on_handle_context(self, e_context: EventContext): load_config() ok, result = True, "配置已重载" elif cmd == "resetall": - if bottype in [const.OPEN_AI, const.CHATGPT, const.CHATGPTONAZURE]: + if bottype in [const.OPEN_AI, const.CHATGPT, const.CHATGPTONAZURE, const.LINKAI]: channel.cancel_all_session() bot.sessions.clear_all_session() ok, result = True, "重置所有会话成功" diff --git a/plugins/hello/hello.py b/plugins/hello/hello.py index fc8fe7051..cd19384c3 100644 --- a/plugins/hello/hello.py +++ b/plugins/hello/hello.py @@ -34,14 +34,14 @@ def on_handle_context(self, e_context: EventContext): e_context["context"].type = ContextType.TEXT msg: ChatMessage = e_context["context"]["msg"] e_context["context"].content = f'请你随机使用一种风格说一句问候语来欢迎新用户"{msg.actual_user_nickname}"加入群聊。' - e_context.action = EventAction.CONTINUE # 事件继续,交付给下个插件或默认逻辑 + e_context.action = EventAction.BREAK # 事件结束,进入默认处理逻辑 return if e_context["context"].type == ContextType.PATPAT: e_context["context"].type = ContextType.TEXT msg: ChatMessage = e_context["context"]["msg"] e_context["context"].content = f"请你随机使用一种风格介绍你自己,并告诉用户输入#help可以查看帮助信息。" - e_context.action = EventAction.CONTINUE # 事件继续,交付给下个插件或默认逻辑 + e_context.action = EventAction.BREAK # 事件结束,进入默认处理逻辑 return content = e_context["context"].content diff --git a/plugins/plugin.py b/plugins/plugin.py index 6c82c8de7..e7444d2ec 100644 --- a/plugins/plugin.py +++ b/plugins/plugin.py @@ -1,6 +1,28 @@ +import os +import json +from config import pconf +from common.log import logger + + class Plugin: def __init__(self): self.handlers = {} + def load_config(self) -> dict: + """ + 加载当前插件配置 + :return: 插件配置字典 + """ + # 优先获取 plugins/config.json 中的全局配置 + plugin_conf = pconf(self.name) + if not plugin_conf: + # 全局配置不存在,则获取插件目录下的配置 + plugin_config_path = os.path.join(self.path, "config.json") + if os.path.exists(plugin_config_path): + with open(plugin_config_path, "r") as f: + plugin_conf = json.load(f) + logger.debug(f"loading plugin config, plugin_name={self.name}, conf={plugin_conf}") + return plugin_conf + def get_help_text(self, **kwargs): return "暂无帮助信息" diff --git a/plugins/plugin_getnews/getnews.py b/plugins/plugin_getnews/getnews.py index 9c5af9c45..cf4d8ccac 100644 --- a/plugins/plugin_getnews/getnews.py +++ b/plugins/plugin_getnews/getnews.py @@ -54,8 +54,37 @@ def on_handle_context(self, e_context: EventContext): e_context['reply'] = reply e_context.action = EventAction.BREAK_PASS # 事件结束,并跳过处理context的默认逻辑 + + if content == "请重试" or re.match(r"。.*", content): + e_context.action = EventAction.BREAK_PASS # 事件结束,并跳过处理context的默认逻辑 + + if re.search(r"微博|weibo|wb", content) and len(content) <= 5: + reply = Reply() + reply.type = ReplyType.TEXT + + #接口信息 https://tophub.today/ | https://www.alapi.cn/api/view/49 + + url = "https://v2.alapi.cn/api/tophub" + headers = {'Content-Type': "application/x-www-form-urlencoded"} + payload = "token="+getnews_api_token+"&id=KqndgxeLl9" + + #获取新闻 + req = requests.request("POST", url, data=payload, headers=headers) + news_json = json.loads(req.text) + + news_date = news_json['data']['last_update'] + + output = news_date + ' 更新\n' + for i in range(min(len(news_json['data']['list']), 15)): + item = f'%2s.' %str(i+1) + news_json['data']['list'][i]['title'] + ' / '+ news_json['data']['list'][i]['other'] + '\n' + output= output + item + + reply.content = output + + e_context['reply'] = reply + e_context.action = EventAction.BREAK_PASS # 事件结束,并跳过处理context的默认逻辑 - if re.match(r"我是.*", content): + if re.match(r"我是.*", content) and len(content) <= 12: reply = Reply() reply.type = ReplyType.TEXT @@ -130,5 +159,5 @@ def on_handle_context(self, e_context: EventContext): # e_context.action = EventAction.CONTINUE # 事件继续,交付给下个插件或默认逻辑 def get_help_text(self, **kwargs): - help_text = "输入今日新闻,获取今天新闻\n输入今日图片,获取今日摄影" + help_text = "输入今日新闻,获取今天新闻\n输入今日图片,获取今日摄影\n输入微博,获取微博热榜" return help_text diff --git a/plugins/plugin_manager.py b/plugins/plugin_manager.py index d2ee75e39..49c13ca0e 100644 --- a/plugins/plugin_manager.py +++ b/plugins/plugin_manager.py @@ -9,7 +9,7 @@ from common.log import logger from common.singleton import singleton from common.sorted_dict import SortedDict -from config import conf +from config import conf, write_plugin_config from .event import * @@ -62,6 +62,28 @@ def load_config(self): self.save_config() return pconf + @staticmethod + def _load_all_config(): + """ + 背景: 目前插件配置存放于每个插件目录的config.json下,docker运行时不方便进行映射,故增加统一管理的入口,优先 + 加载 plugins/config.json,原插件目录下的config.json 不受影响 + + 从 plugins/config.json 中加载所有插件的配置并写入 config.py 的全局配置中,供插件中使用 + 插件实例中通过 config.pconf(plugin_name) 即可获取该插件的配置 + """ + all_config_path = "./plugins/config.json" + try: + if os.path.exists(all_config_path): + # read from all plugins config + with open(all_config_path, "r", encoding="utf-8") as f: + all_conf = json.load(f) + logger.info(f"load all config from plugins/config.json: {all_conf}") + + # write to global config + write_plugin_config(all_conf) + except Exception as e: + logger.error(e) + def scan_plugins(self): logger.info("Scaning plugins ...") plugins_dir = "./plugins" @@ -88,7 +110,7 @@ def scan_plugins(self): self.loaded[plugin_path] = importlib.import_module(import_path) self.current_plugin_path = None except Exception as e: - logger.exception("Failed to import plugin %s: %s" % (plugin_name, e)) + logger.warn("Failed to import plugin %s: %s" % (plugin_name, e)) continue pconf = self.pconf news = [self.plugins[name] for name in self.plugins] @@ -123,7 +145,7 @@ def activate_plugins(self): # 生成新开启的插件实例 try: instance = plugincls() except Exception as e: - logger.error("Failed to init %s, diabled. %s" % (name, e)) + logger.warn("Failed to init %s, diabled. %s" % (name, e)) self.disable_plugin(name) failed_plugins.append(name) continue @@ -149,6 +171,8 @@ def reload_plugin(self, name: str): def load_plugins(self): self.load_config() self.scan_plugins() + # 加载全量插件配置 + self._load_all_config() pconf = self.pconf logger.debug("plugins.json config={}".format(pconf)) for name, plugin in pconf["plugins"].items(): @@ -163,6 +187,9 @@ def emit_event(self, e_context: EventContext, *args, **kwargs): logger.debug("Plugin %s triggered by event %s" % (name, e_context.event)) instance = self.instances[name] instance.handlers[e_context.event](e_context, *args, **kwargs) + if e_context.is_break(): + e_context["breaked_by"] = name + logger.debug("Plugin %s breaked event %s" % (name, e_context.event)) return e_context def set_plugin_priority(self, name: str, priority: int): diff --git a/plugins/role/role.py b/plugins/role/role.py index 4f1dc879b..c75aa905a 100644 --- a/plugins/role/role.py +++ b/plugins/role/role.py @@ -99,7 +99,7 @@ def on_handle_context(self, e_context: EventContext): if e_context["context"].type != ContextType.TEXT: return btype = Bridge().get_bot_type("chat") - if btype not in [const.OPEN_AI, const.CHATGPT, const.CHATGPTONAZURE]: + if btype not in [const.OPEN_AI, const.CHATGPT, const.CHATGPTONAZURE, const.LINKAI]: return bot = Bridge().get_bot("chat") content = e_context["context"].content[:] diff --git a/plugins/source.json b/plugins/source.json index 990358d76..b3a307b53 100644 --- a/plugins/source.json +++ b/plugins/source.json @@ -11,8 +11,10 @@ "summary": { "url": "https://github.com/lanvent/plugin_summary.git", "desc": "总结聊天记录的插件" - } - , + }, + "timetask": { + "url": "https://github.com/haikerapples/timetask.git", + "desc": "一款定时任务系统的插件"}, "getnews": { "url": "https://github.com/congxuma/plugin_getnews.git", "desc": "测试获取新闻" diff --git a/plugins/tool/README.md b/plugins/tool/README.md index 8bd6949ae..229da4267 100644 --- a/plugins/tool/README.md +++ b/plugins/tool/README.md @@ -57,6 +57,8 @@ $tool reset: 重置工具。 ### 6. news 新闻类工具集合 +> news更新:0.4版本对新闻类工具做了整合,配置文件只要加入`news`一个工具名就会自动加载所有新闻类工具 + #### 6.1. news-api * ###### 从全球 80,000 多个信息源中获取当前和历史新闻文章 @@ -75,7 +77,7 @@ $tool reset: 重置工具。 > 该工具需要解决browser tool 的google-chrome依赖安装 -> news更新:0.4版本对news工具做了整合,只要加入news一个工具就会自动加载所有新闻类工具 + ### 7. bing-search * ###### bing搜索引擎,从此你不用再烦恼搜索要用哪些关键词 @@ -112,24 +114,25 @@ $tool reset: 重置工具。 --- ###### 注1:带*工具需要获取api-key才能使用(在config.json内的kwargs添加项),部分工具需要外网支持 -#### [申请方法](https://github.com/goldfishh/chatgpt-tool-hub/blob/master/docs/apply_optional_tool.md) +## [工具的api申请方法](https://github.com/goldfishh/chatgpt-tool-hub/blob/master/docs/apply_optional_tool.md) ## config.json 配置说明 -###### 默认工具无需配置,其它工具需手动配置,一个例子: +###### 默认工具无需配置,其它工具需手动配置,以增加morning-news和bing-search两个工具为例: ```json { - "tools": ["wikipedia", "你想要添加的其他工具"], // 填入你想用到的额外工具名 + "tools": ["bing-search", "news", "你想要添加的其他工具"], // 填入你想用到的额外工具名,这里加入了工具"bing-search"和工具"news"(news工具会自动加载morning-news、finance-news等子工具) "kwargs": { "debug": true, // 当你遇到问题求助时,需要配置 "request_timeout": 120, // openai接口超时时间 "no_default": false, // 是否不使用默认的4个工具 - // 带*工具需要申请api-key,在这里填入,api_name参考前述`申请方法` + "bing_subscription_key": "4871f273a4804743",//带*工具需要申请api-key,这里填入了工具bing-search对应的api,api_name参考前述`工具的api申请方法` + "morning_news_api_key": "5w1kjNh9VQlUc",// 这里填入了morning-news对应的api, } } ``` 注:config.json文件非必须,未创建仍可使用本tool;带*工具需在kwargs填入对应api-key键值对 -- `tools`:本插件初始化时加载的工具, 上述标题即是对应工具名称,带*工具必须在kwargs中配置相应api-key +- `tools`:本插件初始化时加载的工具, 上述一级标题即是对应工具名称,带*工具必须在kwargs中配置相应api-key - `kwargs`:工具执行时的配置,一般在这里存放**api-key**,或环境配置 - `debug`: 输出chatgpt-tool-hub额外信息用于调试 - `request_timeout`: 访问openai接口的超时时间,默认与wechat-on-chatgpt配置一致,可单独配置 diff --git a/plugins/tool/config.json b/plugins/tool/config.json index 5e2e74d1c..55d0c31a6 100644 --- a/plugins/tool/config.json +++ b/plugins/tool/config.json @@ -2,7 +2,7 @@ "tools": [ "wolfram-alpha", "bing-search"], "kwargs": { "top_k_results": 2, - "no_default": false, + "no_default": true, "model_name": "gpt-3.5-turbo" } } diff --git a/plugins/tool/tool.py b/plugins/tool/tool.py index 4caa083cc..5a2a64fbf 100644 --- a/plugins/tool/tool.py +++ b/plugins/tool/tool.py @@ -10,7 +10,6 @@ from bridge.context import ContextType from bridge.reply import Reply, ReplyType from common import const -from common.log import logger from config import conf from plugins import * @@ -55,6 +54,7 @@ def on_handle_context(self, e_context: EventContext): const.CHATGPT, const.OPEN_AI, const.CHATGPTONAZURE, + const.LINKAI, ): return @@ -118,15 +118,8 @@ def on_handle_context(self, e_context: EventContext): return def _read_json(self) -> dict: - curdir = os.path.dirname(__file__) - config_path = os.path.join(curdir, "config.json") - tool_config = {"tools": [], "kwargs": {}} - if not os.path.exists(config_path): - return tool_config - else: - with open(config_path, "r") as f: - tool_config = json.load(f) - return tool_config + default_config = {"tools": [], "kwargs": {}} + return super().load_config() or default_config def _build_tool_kwargs(self, kwargs: dict): tool_model_name = kwargs.get("model_name") @@ -166,6 +159,7 @@ def _build_tool_kwargs(self, kwargs: dict): "debug": kwargs.get("debug", False), "openai_api_key": conf().get("open_ai_api_key", ""), "open_ai_api_base": conf().get("open_ai_api_base", "https://api.openai.com/v1"), + "deployment_id": conf().get("azure_deployment_id", ""), "proxy": conf().get("proxy", ""), "request_timeout": request_timeout if request_timeout else conf().get("request_timeout", 120), # note: 目前tool暂未对其他模型测试,但这里仍对配置来源做了优先级区分,一般插件配置可覆盖全局配置 diff --git a/requirements-optional.txt b/requirements-optional.txt index c248689f3..92477f37e 100644 --- a/requirements-optional.txt +++ b/requirements-optional.txt @@ -25,4 +25,4 @@ wechatpy # chatgpt-tool-hub plugin --extra-index-url https://pypi.python.org/simple -chatgpt_tool_hub==0.4.3 \ No newline at end of file +chatgpt_tool_hub==0.4.6 diff --git a/requirements.txt b/requirements.txt index e7cf147fd..4e93d6d7b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -openai==0.27.2 +openai>=0.27.8 HTMLParser>=0.0.2 PyQRCode>=1.2.1 qrcode>=7.4.2 diff --git a/translate/baidu/baidu_translate.py b/translate/baidu/baidu_translate.py index bf0a72143..6f99e34e1 100644 --- a/translate/baidu/baidu_translate.py +++ b/translate/baidu/baidu_translate.py @@ -17,13 +17,15 @@ def __init__(self) -> None: self.url = endpoint + path self.appid = conf().get("baidu_translate_app_id") self.appkey = conf().get("baidu_translate_app_key") + if not self.appid or not self.appkey: + raise Exception("baidu translate appid or appkey not set") # For list of language codes, please refer to `https://api.fanyi.baidu.com/doc/21`, need to convert to ISO 639-1 codes def translate(self, query: str, from_lang: str = "", to_lang: str = "en") -> str: if not from_lang: from_lang = "auto" # baidu suppport auto detect salt = random.randint(32768, 65536) - sign = self.make_md5(self.appid + query + str(salt) + self.appkey) + sign = self.make_md5("{}{}{}{}".format(self.appid, query, salt, self.appkey)) headers = {"Content-Type": "application/x-www-form-urlencoded"} payload = {"appid": self.appid, "q": query, "from": from_lang, "to": to_lang, "salt": salt, "sign": sign} @@ -31,7 +33,8 @@ def translate(self, query: str, from_lang: str = "", to_lang: str = "en") -> str while retry_cnt: r = requests.post(self.url, params=payload, headers=headers) result = r.json() - if errcode := result.get("error_code", "52000") != "52000": + errcode = result.get("error_code", "52000") + if errcode != "52000": if errcode == "52001" or errcode == "52002": retry_cnt -= 1 continue diff --git a/voice/audio_convert.py b/voice/audio_convert.py index 9c9515a28..18fe3c2f3 100644 --- a/voice/audio_convert.py +++ b/voice/audio_convert.py @@ -1,7 +1,13 @@ import shutil import wave -import pysilk +from common.log import logger + +try: + import pysilk +except ImportError: + logger.warn("import pysilk failed, wechaty voice message will not be supported.") + from pydub import AudioSegment sil_supports = [8000, 12000, 16000, 24000, 32000, 44100, 48000] # slk转wav时,支持的采样率 diff --git a/voice/baidu/baidu_voice.py b/voice/baidu/baidu_voice.py index 406157b96..fbf53ce89 100644 --- a/voice/baidu/baidu_voice.py +++ b/voice/baidu/baidu_voice.py @@ -43,9 +43,9 @@ def __init__(self): with open(config_path, "r") as fr: bconf = json.load(fr) - self.app_id = conf().get("baidu_app_id") - self.api_key = conf().get("baidu_api_key") - self.secret_key = conf().get("baidu_secret_key") + self.app_id = str(conf().get("baidu_app_id")) + self.api_key = str(conf().get("baidu_api_key")) + self.secret_key = str(conf().get("baidu_secret_key")) self.dev_id = conf().get("baidu_dev_pid") self.lang = bconf["lang"] self.ctp = bconf["ctp"]