Repository: RockChinQ/revLibs
Branch: master
Commit: 4bb7da653228
Files: 25
Total size: 49.2 KB
Directory structure:
gitextract_2z_xvd8v/
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ └── issue模板.md
│ └── dependabot.yml
├── .gitignore
├── README.md
├── __init__.py
├── main.py
├── pkg/
│ ├── __init__.py
│ ├── accounts/
│ │ └── accmgr.py
│ ├── models/
│ │ ├── forward.py
│ │ └── interface.py
│ ├── process/
│ │ ├── __init__.py
│ │ ├── impls/
│ │ │ ├── __init__.py
│ │ │ ├── bard.py
│ │ │ ├── claude.py
│ │ │ ├── edgegpt.py
│ │ │ ├── fproxy.py
│ │ │ ├── gpt4free.py
│ │ │ ├── hugchat.py
│ │ │ └── v1impl.py
│ │ ├── proccmd.py
│ │ ├── procmsg.py
│ │ └── revss.py
│ └── utils.py
├── requirements.txt
└── revcfg-template.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/ISSUE_TEMPLATE/issue模板.md
================================================
---
name: issue模板
about: 任何问题请使用这个模板创建
title: ""
labels: ''
assignees: ''
---
请您认真填写以下信息。
### 任务
- [ ] 我已严格按照文档中的步骤操作
- [ ] 我已经搜索了相关的issue
### 预期/正在使用的逆向库
我要使用的逆向库是:(例如:New Bing)
### 期望情况
我希望的情况是:
### 实际情况
实际情况是:
================================================
FILE: .github/dependabot.yml
================================================
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "pip" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "daily"
allow:
- dependency-name: "revChatGPT"
- dependency-name: "EdgeGPT"
================================================
FILE: .gitignore
================================================
__pycache__/
================================================
FILE: README.md
================================================
# RevLib Support for QChatGPT
> 2023/8/29 现已支持`gpt4free`,请查看下方的使用方法
> 2023/8/14 现已支持`Claude`和`Bard`,请查看下方的使用方法
> 2023/8/03 逆向库现已支持`函数调用`, 配置方法同[主程序配置方法](https://github.com/RockChinQ/QChatGPT/wiki/%E6%8F%92%E4%BB%B6%E4%BD%BF%E7%94%A8-%E5%86%85%E5%AE%B9%E5%87%BD%E6%95%B0)
得益于[QChatGPT项目](https://github.com/RockChinQ/QChatGPT)的插件功能,此插件将允许接入`ChatGPT网页版`用以替换原项目主线的GPT-3模型接口,提升回复质量。
[官方接口与ChatGPT网页版的区别?](https://github.com/RockChinQ/QChatGPT/wiki/%E5%AE%98%E6%96%B9%E6%8E%A5%E5%8F%A3%E4%B8%8EChatGPT%E7%BD%91%E9%A1%B5%E7%89%88)
## 安装方式
> 若您未安装QChatGPT程序,请先查看原仓库[文档](https://github.com/RockChinQ/QChatGPT)
使用管理员账号私聊机器人发送指令:
```
!plugin https://github.com/RockChinQ/revLibs
```
若无法访问GitHub,可以使用Gitee镜像
```
!plugin https://gitee.com/RockChin/revLibs
```
等待程序获取源码,并解决依赖,这可能需要数分钟的时间。
安装完毕后,请发送:
```
!reload
```
重载插件,生成配置文件,**关闭主程序**。
到`QChatGPT`程序目录编辑`revcfg.py`文件,根据注释修改必填配置项。
配置完成后重新启动主程序以使用。
## Cookies获取方法
大部分逆向库基于Cookies登录,因此需要获取Cookies。这里讲解了获取一个网站的Cookies的详细步骤,您可以先查看下方选择逆向库的步骤,到需要的网站使用以下方式获取Cookies。
1. 安装适用于[Chrome/Edge](https://chrome.google.com/webstore/detail/cookie-editor/hlkenndednhfkekhgcdicdfddnkalmdm) 或 [Firefox](https://addons.mozilla.org/en-US/firefox/addon/cookie-editor/) 的Cookies编辑器插件
2. 访问 目标网站
3. 打开这个插件
4. 点击 `Export` 按钮, 复制JSON格式的Cookies
5. 将`Cookies`保存到指定的文件中
## 选择逆向库
目前支持的逆向库及使用方式如下, 下方所述文件保存位置均为主程序`config.py`同目录,若无此文件,请自行创建:
<details>
<summary>ChatGPT网页版</summary>
本插件默认使用的逆向库,使用方法请参考配置文件注释。
使用的是 [acheong08/ChatGPT](https://github.com/acheong08/ChatGPT)
> **WARNING**
> 必须配置反向代理才能使用,默认的是作者自建的,不一定能用,建议自己搭建。
> 可以参考:[另外一个项目的文档,仅参考 ChatGPT 反向代理搭建方式](https://free-one-api.rockchin.top/#/zh-CN/Adapters?id=%e5%8f%8d%e5%90%91%e4%bb%a3%e7%90%86)
</details>
<details>
<summary>New Bing(暂不可用)</summary>
使用的是 [acheong08/EdgeGPT](https://github.com/acheong08/EdgeGPT)
- 修改`revcfg.py`中的`reverse_lib`的值为`acheong08/EdgeGPT`
- 获取[NewBing](https://bing.com/chat)的Cookies,保存到`cookies.json`中
#### 配置
- new bing逆向库默认输出参考资料, 若不需要, 请在`revcfg.py`中设置:
```python
output_references = False
```
- 设置New Bing的风格
查看revcfg.py中的`new_bing_style`字段,按照说明更改。在运行期间可以通过指令`!style <风格(创意、平衡、精确)>`来更改风格。
</details>
<details>
<summary>HuggingChat</summary>
1. 在`revcfg.py`中修改`reverse_lib`的值为`Soulter/hugging-chat-api`
2. 获取[HuggingChat](https://huggingface.co/chat/)的Cookies,保存到`hugchat.json`中
</details>
<details>
<summary>Claude</summary>
1. 在`revcfg.py`中修改`reverse_lib`的值为`KoushikNavuluri/Claude-API`
2. 获取[Claude](https://claude.ai/chats)的Cookies,保存到`claude.json`中
</details>
<details>
<summary>Google Bard</summary>
1. 在`revcfg.py`中修改`reverse_lib`的值为`dsdanielpark/Bard-API`
2. 获取[Bard](https://bard.google.com/)的Cookies,保存到`bard.json`中
</details>
<details>
<summary>gpt4free</summary>
接入[xtekky/gpt4free](https://github.com/xtekky/gpt4free)自动从数个平台选择可用的 GPT-4,**无需鉴权**,但很不稳定,仅需要在`revcfg.py`中修改`reverse_lib`的值为`xtekky/gpt4free`即可。
#### 配置
- gpt4free 提供了多个渠道,默认情况下程序会自动测试并选择可用的渠道,可以在 `revcfg.py` 中指定要使用的渠道和要排除的渠道
- 向机器人发送 `!provider ls` 来查看所有支持设置的渠道, 发送 `!provider` 查看当前使用的渠道
</details>
<br/>
### 🚫请勿修改`revcfg-template.py`的内容,配置项请在主程序`config.py`同目录的`revcfg.py`中修改🚫
## 特别感谢
> 向所有致力于人工智能民主化的开发者致敬。
> Salute to all developers committed to the democratization of artificial intelligence.
> 인공지능 민주화에 힘쓴 모든 개발자들에게 경의를 표합니다.
> 人工知能の民主化に取り組むすべての開発者に敬意を表します。
================================================
FILE: __init__.py
================================================
================================================
FILE: main.py
================================================
import traceback
from pkg.plugin.models import *
from pkg.plugin.host import EventContext, PluginHost, emit
import time
import os
from revChatGPT.V1 import Chatbot
import plugins.revLibs.pkg.process.revss as revss
import plugins.revLibs.pkg.process.procmsg as procmsg
import plugins.revLibs.pkg.process.proccmd as proccmd
from EdgeGPT.EdgeGPT import ConversationStyle
def check_config():
this_file = __file__
template_file = os.path.join(os.path.dirname(this_file), "revcfg-template.py")
# 检查revlib.py是否存在
if not os.path.exists("revcfg.py"):
# 不存在则使用本模块同目录的revcfg-template.py复制创建
with open(template_file, "r", encoding="utf-8") as f:
template = f.read()
with open("revcfg.py", "w", encoding="utf-8") as f:
f.write(template)
return False
return True
# 注册插件
@register(name="revLibs", description="接入acheong08/ChatGPT、Claude、Bard等逆向库", version="0.9.1", author="RockChinQ")
class RevLibsPlugin(Plugin):
chatbot: Chatbot = None
# 插件加载时触发
def __init__(self, plugin_host: PluginHost):
# 执行依赖库更新
# try:
# import plugins.revLibs.pkg.utils as utils
# # utils.upgrade_revlibs()
# except:
# traceback.print_exc()
# logging.warn("[rev] 依赖库更新失败,不能确保逆向库正常运行")
if not check_config():
logging.error("[rev] 已生成配置文件(revcfg.py),请按照其中注释填写配置文件后重启程序")
# plugin_host.notify_admin("[rev] 已生成配置文件(revcfg.py),请按照其中注释填写配置文件后重启程序")
return
import revcfg
if not hasattr(revcfg, "new_bing_style"):
setattr(revcfg, "new_bing_style", ConversationStyle.balanced)
try:
from plugins.revLibs.pkg.process.impls import v1impl, edgegpt, hugchat, claude, bard, gpt4free
reverse_lib_mapping = {
"acheong08/ChatGPT.V1": v1impl.RevChatGPTV1,
"acheong08/EdgeGPT": edgegpt.EdgeGPTImpl,
"Soulter/hugging-chat-api": hugchat.HugChatImpl,
"KoushikNavuluri/Claude-API": claude.ClaudeImpl,
"dsdanielpark/Bard-API": bard.BardImpl,
"xtekky/gpt4free": gpt4free.GPT4FreeImpl,
}
import plugins.revLibs.pkg.process.revss as revss
if hasattr(revcfg, "reverse_lib") and revcfg.reverse_lib in reverse_lib_mapping:
revss.__rev_interface_impl_class__ = reverse_lib_mapping[revcfg.reverse_lib]
logging.info("[rev] 已加载逆向库{}, 使用接口实现类: {}".format(revcfg.reverse_lib, str(reverse_lib_mapping[revcfg.reverse_lib])))
else:
logging.error("[rev] 未知的逆向库: " + revcfg.reverse_lib + ", 请检查配置文件是否填写正确或尝试更新逆向库插件")
time.sleep(5)
return
except:
# 输出完整的错误信息
# plugin_host.notify_admin("[rev] 逆向库初始化失败,请检查配置文件(revcfg.py)是否正确")
logging.error("[rev] 逆向库初始化失败,请检查配置文件(revcfg.py)是否正确")
logging.error("[rev] " + traceback.format_exc())
return
import config
revcfg.process_message_timeout = config.process_message_timeout
config.process_message_timeout = 10*60
logging.info("[rev] 已将主程序消息处理超时时间设置为10分钟")
@on(PersonNormalMessageReceived)
@on(GroupNormalMessageReceived)
def normal_message_received(inst, event: EventContext, **kwargs):
event.prevent_default()
event.prevent_postorder()
reply = []
try:
prefix = revcfg.reply_prefix
reply_message = ""
reply_message = procmsg.process_message(session_name=kwargs['launcher_type']+"_"+str(kwargs['launcher_id']),
prompt=kwargs['text_message'], **kwargs)
logging.debug("[rev] " + reply_message)
reply_message = reply_message
# 触发NormalMessageResponded事件
args = {
"launcher_type": kwargs['launcher_type'],
"launcher_id": kwargs['launcher_id'],
"sender_id": kwargs['sender_id'],
"session": None,
"prefix": prefix,
"response_text": reply_message,
"finish_reason": "revLibs."+revcfg.reverse_lib+".finish",
}
inter_event: EventContext = emit(NormalMessageResponded, **args)
reply = []
if inter_event.get_return_value("prefix") is not None:
prefix = inter_event.get_return_value("prefix")
if inter_event.get_return_value("reply") is not None:
reply = inter_event.get_return_value("reply")
if not inter_event.is_prevented_default():
reply = [prefix + reply_message]
except Exception as e:
logging.error("[rev] " + traceback.format_exc())
import config
if config.hide_exce_info_to_user:
reply_message = ''
try:
import tips
reply_message = tips.alter_tip_message
except:
if hasattr(config, "alter_tip_message"):
reply_message = config.alter_tip_message
else:
reply_message = "处理消息时出现错误,请联系管理员"
kwargs['host'].notify_admin("[rev] 处理消息时出现错误:\n"+traceback.format_exc())
else:
reply_message = "处理消息时出现错误,请联系管理员"+"\n"+traceback.format_exc()
reply = [revcfg.reply_prefix+reply_message]
if reply_message != "":
event.add_return(
"reply",
reply,
)
@on(PersonCommandSent)
@on(GroupCommandSent)
def command_send(inst, event: EventContext, **kwargs):
reply_message = ""
try:
reply_message = proccmd.process_command(session_name=kwargs['launcher_type']+"_"+str(kwargs['launcher_id']),
**kwargs)
logging.debug("[rev] " + reply_message)
except Exception as e:
logging.error("[rev] " + traceback.format_exc())
reply_message = "处理命令时出现错误,请联系管理员"+"\n"+traceback.format_exc()
if reply_message.strip() != "":
event.add_return(
"reply",
["{}(cmd)".format(revcfg.reply_prefix)+reply_message],
)
event.prevent_default()
event.prevent_postorder()
def make_reply(self, prompt, **kwargs) -> dict:
reply_gen = self.chatbot.ask(prompt, **kwargs)
reply = {}
for r in reply_gen:
reply = r
return reply
# 插件卸载时触发
def __del__(self):
pass
================================================
FILE: pkg/__init__.py
================================================
================================================
FILE: pkg/accounts/accmgr.py
================================================
import time
def get_account_list():
import revcfg
if type(revcfg.openai_account) is dict:
revcfg.openai_account = [revcfg.openai_account]
return revcfg.openai_account
def get_account_brief_name(account: dict):
if 'email' in account:
return account['email']
elif 'session_token' in account:
return "sessionToken: "+account['session_token'][:8]
elif 'access_token' in account:
return "accessToken: "+account['access_token'][:8]
else:
return "未知账户"
def move_account_to_end(account: dict):
# 将账户移动到末尾
import revcfg
account_list = get_account_list()
account_list.remove(account)
account_list.append(account)
revcfg.openai_account = account_list
def delete_invalid_attr(account: dict):
temp_dict = dict(account)
if 'invalid_at' in temp_dict:
del temp_dict['invalid_at']
return temp_dict
def use_account() -> tuple[bool, dict]:
# 计算并返回下一个账户
import revcfg
account_resume_interval = revcfg.openai_account_resume_interval if hasattr(revcfg, 'openai_account_resume_interval') else 60
now = int(time.time())
for account in get_account_list():
if 'invalid_at' in account:
if account['invalid_at'] < now - account_resume_interval * 60:
move_account_to_end(account)
return True, delete_invalid_attr(account)
if 'invalid_at' not in account:
move_account_to_end(account)
return True, delete_invalid_attr(account)
move_account_to_end(get_account_list()[0])
return False, delete_invalid_attr(get_account_list()[0])
def report_invalidation(account: dict):
# 报告账户失效
for acc in get_account_list():
if 'email' in acc and 'email' in account and acc['email'] == account['email']:
acc['invalid_at'] = int(time.time())
return
elif 'session_token' in acc and 'session_token' in account and acc['session_token'] == account['session_token']:
acc['invalid_at'] = int(time.time())
return
elif 'access_token' in acc and 'access_token' in account and acc['access_token'] == account['access_token']:
acc['invalid_at'] = int(time.time())
return
================================================
FILE: pkg/models/forward.py
================================================
from mirai.models.message import MessageComponent
from mirai.models.message import ForwardMessageNode
from mirai.models.base import MiraiBaseModel
from typing import List, Optional
class ForwardMessageDiaplay(MiraiBaseModel):
title: str = "群聊的聊天记录"
brief: str = "[聊天记录]"
source: str = "聊天记录"
preview: List[str] = []
summary: str = "查看x条转发消息"
class Forward(MessageComponent):
"""合并转发。"""
type: str = "Forward"
"""消息组件类型。"""
display: ForwardMessageDiaplay
"""显示信息"""
node_list: List[ForwardMessageNode]
"""转发消息节点列表。"""
def __init__(self, *args, **kwargs):
if len(args) == 1:
self.node_list = args[0]
super().__init__(**kwargs)
super().__init__(*args, **kwargs)
def __str__(self):
return '[聊天记录]'
================================================
FILE: pkg/models/interface.py
================================================
from typing import Tuple
class RevLibInterface:
"""逆向库接口"""
@staticmethod
def create_instance() -> tuple["RevLibInterface", bool, dict]:
raise NotImplementedError
def get_rev_lib_inst(self):
raise NotImplementedError
def get_reply(self, prompt: str, **kwargs) -> Tuple[str, dict]:
raise NotImplementedError
def reset_chat(self, **kwargs):
raise NotImplementedError
def rollback(self):
raise NotImplementedError
================================================
FILE: pkg/process/__init__.py
================================================
================================================
FILE: pkg/process/impls/__init__.py
================================================
================================================
FILE: pkg/process/impls/bard.py
================================================
from typing import Tuple
import logging
from plugins.revLibs.pkg.models.interface import RevLibInterface
from bardapi import Bard
import os
import json
class BardImpl(RevLibInterface):
chatbot: Bard = None
token: str = None
@staticmethod
def create_instance() -> tuple[RevLibInterface, bool, dict]:
import revcfg
# 检查bard的cookies是否存在
if not os.path.exists("bard.json"):
logging.error("Bard cookies不存在")
raise Exception("Bard cookies不存在, 请根据文档进行配置: https://github.com/RockChinQ/revLibs")
cookies_list = []
with open("bard.json", "r", encoding="utf-8") as f:
cookies_list = json.load(f)
return BardImpl(cookies_list), True, cookies_list
def __init__(self, cookies: str = None):
__Secure_1PSID = ""
for cookie in cookies:
if cookie["name"] == "__Secure-1PSID":
__Secure_1PSID = cookie["value"]
break
if __Secure_1PSID == "":
raise Exception("Bard cookies中不含有所需的__Secure-1PSID字段, 请尝试重新获取.")
self.token = __Secure_1PSID
self.chatbot = Bard(token=__Secure_1PSID)
def get_rev_lib_inst(self):
return self.chatbot
def get_reply(self, prompt: str, **kwargs) -> Tuple[str, dict]:
logging.debug("[rev] 请求bard回复: {}".format(prompt))
resp = self.chatbot.get_answer(prompt)
yield resp['content'], resp
def reset_chat(self):
self.chatbot = Bard(token=self.token)
def rollback(self):
pass
================================================
FILE: pkg/process/impls/claude.py
================================================
from typing import Tuple
import logging
from plugins.revLibs.pkg.models.interface import RevLibInterface
from claude_api import Client
import os
import json
class ClaudeImpl(RevLibInterface):
chatbot: Client = None
conversation_id: str = None
@staticmethod
def create_instance() -> tuple[RevLibInterface, bool, dict]:
import revcfg
# 检查claude的cookies是否存在
if not os.path.exists("claude.json"):
logging.error("Claude cookies不存在")
raise Exception("Claude cookies不存在, 请根据文档进行配置: https://github.com/RockChinQ/revLibs")
cookies_list = []
with open("claude.json", "r", encoding="utf-8") as f:
cookies_list = json.load(f)
# 把cookies转换为字符串
cookies = ""
for cookie in cookies_list:
cookies += cookie["name"] + "=" + cookie["value"] + ";"
return ClaudeImpl(cookies), True, cookies_list
def __init__(self, cookies: str = None):
self.chatbot = Client(cookies)
def get_rev_lib_inst(self):
return self.chatbot
def get_reply(self, prompt: str, **kwargs) -> Tuple[str, dict]:
logging.debug("[rev] 请求claude回复: {}".format(prompt))
if self.conversation_id is None:
self.conversation_id = self.chatbot.create_new_chat()['uuid']
resp = self.chatbot.send_message(prompt, self.conversation_id)
yield resp, {}
def reset_chat(self):
self.conversation_id = None
def rollback(self):
pass
================================================
FILE: pkg/process/impls/edgegpt.py
================================================
"""接入acheone08/EdgeGPT
"""
import os
import logging
import json
import asyncio
from plugins.revLibs.pkg.models.interface import RevLibInterface
from EdgeGPT.EdgeGPT import Chatbot, ConversationStyle
ref_num_loop = ['¹', '²', '³', '⁴', '⁵', '⁶', '⁷', '⁸', '⁹', '¹⁰', '¹¹', '¹²', '¹³', '¹⁴', '¹⁵', '¹⁶', '¹⁷', '¹⁸', '¹⁹', '²⁰']
class EdgeGPTImpl(RevLibInterface):
"""使用acheong08/EdgeGPT接入new bing
"""
chatbot: Chatbot = None
style = ConversationStyle.balanced
inst_name: str
wss_link: str = "wss://sydney.bing.com/sydney/ChatHub"
@staticmethod
def create_instance() -> tuple[RevLibInterface, bool]:
import revcfg
return EdgeGPTImpl(revcfg.new_bing_style if hasattr(revcfg, "new_bing_style") else ConversationStyle.balanced), True
def __init__(self, style):
# logging.debug("[rev] 初始化接口实现,使用账户cookies: {}".format(str(cookies)[:30]))
logging.debug("[rev] 初始化New Bing接口实现")
import revcfg
params = {}
if hasattr(revcfg, "new_bing_proxy"):
params["proxy"] = revcfg.new_bing_proxy
logging.info("[rev] 初始化NewBing使用代理: {}".format(revcfg.new_bing_proxy))
if hasattr(revcfg, "new_bing_reverse_proxy") and revcfg.new_bing_reverse_proxy != "":
self.wss_link = revcfg.new_bing_reverse_proxy
logging.info("[rev] 初始化NewBing使用反向代理: {}".format(revcfg.new_bing_reverse_proxy))
if os.path.exists("cookies.json"):
with open("cookies.json", "r") as f:
cookies_list = json.load(f)
params["cookies"] = cookies_list
logging.info("[rev] 初始化NewBing具有Cookies")
self.chatbot = Chatbot(**params)
self.style = style
# 随机一个uuid作为实例名
import uuid
self.inst_name = str(uuid.uuid4())
def get_rev_lib_inst(self):
return self.chatbot
def get_reply(self, prompt: str, **kwargs) -> tuple[str, dict]:
"""获取回复"""
logging.debug("[rev] 请求bing回复: {}".format(prompt))
task = self.chatbot.ask(prompt, conversation_style=self.style, wss_link=self.wss_link)
resp = asyncio.run(task)
logging.debug(json.dumps(resp, indent=4, ensure_ascii=False))
reply_obj = resp["item"]["messages"][-1] if 'messageType' not in resp["item"]["messages"][-1] else resp["item"]["messages"][-2]
body = reply_obj["text"] if "text" in reply_obj else (
reply_obj['hiddenText'] if "hiddenText" in reply_obj else (
reply_obj['spokenText'] if "spokenText" in reply_obj else ""
)
)
if "sourceAttributions" in reply_obj:
refs_str = "参考资料: \n"
index = 1
for ref in reply_obj["sourceAttributions"]:
refs_str += "{}".format(ref_num_loop[index-1]) + " " + ref['providerDisplayName'] + " | " + ref['seeMoreUrl'] + "\n"
index += 1
throttling = resp["item"]["throttling"]
throttling_str = "本次对话: {}/{}".format(throttling["numUserMessagesInConversation"], throttling["maxNumUserMessagesInConversation"])
import revcfg
if hasattr(revcfg, "output_references") and not revcfg.output_references:
# 把正文的[^n^]替换成空
import re
body = re.sub(r"\[\^[0-9]+\^\]", "", body)
else:
# 把正文的[^n^]替换成对应的序号
for i in range(index):
body = body.replace("[^"+str(i+1)+"^]", ref_num_loop[i])
# if throttling["numUserMessagesInConversation"] == 3:
if throttling["numUserMessagesInConversation"] == throttling["maxNumUserMessagesInConversation"]:
self.reset_chat()
throttling_str += "(已达最大次数,下一回合将开启新对话)"
reply_str = body + "\n\n" + ((refs_str + "\n\n") if index != 1 and (not hasattr(revcfg, "output_references") or revcfg.output_references) else "") + throttling_str
yield reply_str, resp
else:
self.reset_chat()
yield "err: 可能由于内容不当,对话已被接口拒绝,下一回合将开启新的会话。", resp
def reset_chat(self):
asyncio.run(self.chatbot.reset())
def rollback(self):
pass
================================================
FILE: pkg/process/impls/fproxy.py
================================================
class Proxy:
funcs: list
def __init__(self, funcs: list):
self.funcs = funcs
def prompt(self, user_prompt: str):
if len(self.funcs) == 0:
return user_prompt
raw = \
"""
# You now have access to the following functions:
```yaml
{functions}```
# P.S.
- `required` means the arguments are required.
# If user's input matches the description of a certain function, please output with following format to call the function:
```json
{{"name": "function_name", "args": {{"arg_name": "arg_value", ...}}}}
```
# If not, you can reply in your own way.
# User's input:
{user_prompt}
# Rules
- You can only call one function at a time.
# Your output:
""".strip()
funcs = ""
for i in range(len(self.funcs)):
# - name: func_name
# description: func_description
# args:
# - name: arg_name
# description: arg_description
# type: int
# - name: arg_name
# description: arg_description
# type: str
# required: [arg_name, ...]
# return: return_type
func = self.funcs[i]
func_desc = func['description'].replace("\n", "")
args = ""
for arg in func['parameters']['properties']:
args += \
f""" - name: {arg}
description: {func['parameters']['properties'][arg]['description']}
type: {func['parameters']['properties'][arg]['type']}
"""
if args.endswith("\n"):
args = args[:-1]
func_str = \
f"""- name: {func['name']}
description: {func_desc}
args:
{args}
required: {str(func['parameters']['required'])}
"""
funcs += func_str
return raw.format(functions=funcs, user_prompt=user_prompt)
def call(self, func_name: str, args: dict) -> tuple[bool, str, any]:
for func in self.funcs:
if func['name'] == func_name:
return func['function'](**args)
return "error: no such function"
def extra_function_call(self, text: str):
"""Extra function call request from text
```json
{
"name": "access_web",
"args": {
"link": "https://www.example.com/search?q=RockChinQ"
}
}
```
"""
import re
import json
# 用正则提取json数据
# 直接找大括号包围的, 匹配全文,不限于一行内
json_strs = re.findall(r"\{.*\}", text, re.S)
func_name = None
args = None
found = False
# 逐个检查json数据是否符合格式
for json_str in json_strs:
try:
# 删除所有// xxx
json_str = re.sub(r",\s*//.*", "", json_str)
json_data = json.loads(json_str)
func_name = json_data['name']
args = json_data['args']
found = True
break
except:
continue
if not found:
return False, None, None
return True, func_name, args
================================================
FILE: pkg/process/impls/gpt4free.py
================================================
from typing import Tuple
import logging
from plugins.revLibs.pkg.models.interface import RevLibInterface
import g4f
from g4f import models
class GPT4FreeImpl(RevLibInterface):
messages: list[dict]
use_model: models.Model = models.gpt_4
use_provider: g4f.Provider.BaseProvider = None
@staticmethod
def create_instance() -> tuple[RevLibInterface, bool, dict]:
return GPT4FreeImpl(), True, {}
@classmethod
def select_provider(cls):
logging.info("[rev] 测试并选择provider,如果某个provider测试过久,可以在revcfg.py中将其排除")
from g4f.Provider import __all__ as providers
providers = providers.copy()
exclude = [
'Acytoo'
]
import revcfg
if hasattr(revcfg, 'g4f_use_adapters') and len(revcfg.g4f_use_adapters) > 0:
providers = revcfg.g4f_use_adapters
logging.debug("[rev] 已指定provider列表: {}".format(providers))
if hasattr(revcfg, 'g4f_exclude_adapters') and len(revcfg.g4f_exclude_adapters) > 0:
exclude = revcfg.g4f_exclude_adapters
logging.debug("[rev] 已指定排除provider列表: {}".format(exclude))
for provider in providers:
if provider in exclude:
continue
logging.info("[rev] 测试provider: {}".format(provider))
provider = getattr(g4f.Provider, provider)
try:
response = g4f.ChatCompletion.create(
model=cls.use_model,
messages=[
{
"role": "user",
"content": "hi"
}
],
provider=provider
)
logging.debug("[rev] 测试provider: {} 成功: {}".format(provider, response))
cls.use_provider = provider
break
except Exception as e:
continue
def __init__(self):
self.messages = []
if GPT4FreeImpl.use_provider is None:
# 测试可用模型
self.select_provider()
def get_rev_lib_inst(self):
return None
def get_reply(self, prompt: str, **kwargs) -> Tuple[str, dict]:
logging.debug("[rev] 请求gpt4free: {} 回复: {}".format(GPT4FreeImpl.use_provider, prompt))
retry = 0
while True:
try:
resp = g4f.ChatCompletion.create(
model=GPT4FreeImpl.use_model,
messages=self.messages+[
{
"role": "user",
"content": prompt
}
],
provider=GPT4FreeImpl.use_provider,
)
self.messages.append(
{
"role": "user",
"content": prompt
}
)
self.messages.append(
{
"role": "assistant",
"content": resp
}
)
yield resp, {}
break
except Exception as e:
retry += 1
if retry >= 3:
raise e
GPT4FreeImpl.select_provider()
def reset_chat(self):
self.messages = []
def rollback(self):
if len(self.messages) < 2:
return
self.messages.pop()
self.messages.pop()
================================================
FILE: pkg/process/impls/hugchat.py
================================================
from typing import Tuple
import logging
from plugins.revLibs.pkg.models.interface import RevLibInterface
from hugchat import hugchat
import os
import json
class HugChatImpl(RevLibInterface):
chatbot: hugchat.ChatBot = None
@staticmethod
def create_instance() -> tuple[RevLibInterface, bool, dict]:
import revcfg
# 检查hugging chat的cookies是否存在
if not os.path.exists("hugchat.json"):
logging.error("HuggingChat cookies不存在")
raise Exception("HuggingChat cookies不存在, 请根据文档进行配置: https://github.com/RockChinQ/revLibs")
cookies_dict = {}
with open("hugchat.json", "r", encoding="utf-8") as f:
cookies_dict = json.load(f)
return HugChatImpl(cookies_dict), True, cookies_dict
def __init__(self, cookies_dict: dict = None):
self.chatbot = hugchat.ChatBot(cookies=cookies_dict)
def get_rev_lib_inst(self):
return self.chatbot
def get_reply(self, prompt: str, **kwargs) -> Tuple[str, dict]:
logging.debug("[rev] 请求hugchat回复: {}".format(prompt))
resp = self.chatbot.chat(prompt)
yield resp, {}
def reset_chat(self):
self.chatbot.new_conversation()
def rollback(self):
pass
================================================
FILE: pkg/process/impls/v1impl.py
================================================
from typing import Tuple
from plugins.revLibs.pkg.models.interface import RevLibInterface
from revChatGPT.V1 import Chatbot
import threading
__thr_locks__ = {}
def get_lock(key: str):
if key not in __thr_locks__:
__thr_locks__[key] = threading.Lock()
return __thr_locks__[key]
import logging
class RevChatGPTV1(RevLibInterface):
"""acheong08/ChatGPT的逆向库接口 V1"""
chatbot: Chatbot = None
inst_name: str
@staticmethod
def create_instance() -> tuple[RevLibInterface, bool, dict]:
import plugins.revLibs.pkg.accounts.accmgr as accmgr
valid_acc, acc = accmgr.use_account()
return RevChatGPTV1(acc), valid_acc, acc
def __init__(self, cfg):
logging.debug("[rev] 初始化接口实现,使用账户配置: {}".format(cfg))
import revcfg
if hasattr(revcfg, "revchatgpt_reverse_proxy") and revcfg.revchatgpt_reverse_proxy != "":
import revChatGPT.V1 as revcgpt
revcgpt.BASE_URL = revcfg.revchatgpt_reverse_proxy
logging.info("[rev] 已指定revchatgpt的反向代理: {}".format(revcfg.revchatgpt_reverse_proxy))
self.chatbot = Chatbot(
config=cfg,
)
self.inst_name = str(cfg)
def get_rev_lib_inst(self):
return self.chatbot
def get_reply(self, prompt: str, **kwargs) -> Tuple[str, dict]:
import revcfg
logging.debug("[rev] 请求ChatGPT回复: {}".format(prompt))
# 构建函数代理
funcs = []
import pkg.plugin.models as models
import pkg.plugin.host as plugin_host
import pkg.openai.funcmgr as funcmgr
if hasattr(models, "require_ver"):
funcs = funcmgr.get_func_schema_list()
for func in funcs:
func['function'] = plugin_host.__function_inst_map__[func['name']]
from .fproxy import Proxy
fp = Proxy(funcs)
try:
get_lock(self.inst_name).acquire()
if self.chatbot is None:
raise Exception("acheong08/ChatGPT.V1 逆向接口未初始化")
prompt = fp.prompt(prompt)
reply_gen = self.chatbot.ask(prompt, **kwargs)
already_reply_msg = ""
reply = {}
first_received = False
for r in reply_gen:
if not first_received:
first_received = True
logging.debug("已响应,正在接收...")
reply = r
if "message" in reply:
assert isinstance(reply['message'], str)
reply['message'] = reply['message'].replace(already_reply_msg, "")
logging.debug("接收完毕: {}".format(reply))
# 检查是否有JSON函数调用
is_func_call, func_name, args = fp.extra_function_call(reply['message'])
while is_func_call:
logging.info("[REV] 执行函数调用: {} {}".format(func_name, args))
result = ""
try:
result = fp.call(func_name, args)
logging.debug("func result: {}".format(result))
logging.info("[REV] 函数调用完成。")
except Exception as e:
logging.info("[REV] 函数调用失败。")
result = "error: failed to call function: "+str(e)
reply = {}
prompt = f"""## Function call result:
```
{result}
```
## Rules
- If you haven't done completely, you can call function again.
- Please reply in the user's language."""
for data in self.chatbot.ask(
prompt=prompt,
):
try:
assert 'message' in data
reply = data
except:
continue
logging.debug("ChatGPT's output: {}".format(reply['message']))
is_func_call, func_name, args = fp.extra_function_call(reply['message'])
yield reply['message'], reply
except Exception as e:
raise e
finally:
get_lock(self.inst_name).release()
def reset_chat(self):
self.chatbot.reset_chat()
def rollback(self):
self.chatbot.rollback_conversation()
================================================
FILE: pkg/process/proccmd.py
================================================
import plugins.revLibs.pkg.process.revss as revss
import plugins.revLibs.pkg.process.impls.v1impl as v1impl
import plugins.revLibs.pkg.process.impls.edgegpt as edgegpt
import plugins.revLibs.pkg.process.impls.gpt4free as gpt4free
def process_command(session_name: str, **kwargs) -> str:
"""处理命令"""
cmd = kwargs['command']
params = kwargs['params']
reply_message = ""
if cmd == 'reset':
session: revss.RevSession = revss.get_session(session_name)
if len(params) >= 1:
prompt_whole_name = session.reset(params[0])
reply_message = "已重置会话,使用情景预设: {}".format(prompt_whole_name)
else:
session.reset()
reply_message = "已重置会话"
elif cmd == 'list':
session: revss.RevSession = revss.get_session(session_name)
page = 1
if len(params)>=1:
page = int(params[0])
cbinst = session.get_rev_lib_inst()
from revChatGPT.V1 import Chatbot
assert isinstance(cbinst, Chatbot)
conversations = cbinst.get_conversations((page-1)*10, 10)
reply_message = "会话列表 (第{}页) 本页{}个会话:\n".format(page, len(conversations))
for conversation in conversations:
reply_message += "#{}: {}\n".format(conversation['id'], conversation['create_time'])
elif cmd == 'prompt':
# cbinst = session.get_rev_lib_inst()
# from revChatGPT.V1 import Chatbot
# assert isinstance(cbinst, Chatbot)
# reply_message = str(cbinst.get_msg_history(session.conversation_id))
reply_message = "正在使用逆向库,暂不支持查看历史消息"
elif cmd == "last":
reply_message = "正在使用逆向库,暂不支持切换到前一次会话"
elif cmd == "next":
reply_message = "正在使用逆向库,暂不支持切换到后一次会话"
elif cmd == "resend":
session: revss.RevSession = revss.get_session(session_name)
if session.__ls_prompt__ == "":
reply_message = "没有上一条成功回复的消息"
else:
reply_message = session.resend()
elif cmd == "accs":
"""查看每个账户的使用情况"""
import plugins.revLibs.pkg.accounts.accmgr as accmgr
if revss.__rev_interface_impl_class__ == v1impl.RevInterfaceImplV1:
reply_message = "账户列表:\n"
for account in accmgr.get_account_list():
"""
- 账户名称
"""
reply_message += "账户: {}\n - ".format(accmgr.get_account_brief_name(account))
using = False
for k in revss.__sessions__:
v: revss.RevSession = revss.__sessions__[k]
if accmgr.get_account_brief_name(v.using_account) == accmgr.get_account_brief_name(account):
reply_message += v.name + ", "
using = True
if not using:
reply_message += "未使用"
else:
reply_message = reply_message[:-2]
reply_message += "\n\n"
reply_message = reply_message[:-1]
else:
reply_message = "仅当使用ChatGPT逆向库时可查看账户负载情况"
elif cmd == "style":
if revss.__rev_interface_impl_class__ == edgegpt.EdgeGPTImpl:
import revcfg
from EdgeGPT import ConversationStyle
if len(params) >= 1:
mapping = {
"创意": ConversationStyle.creative,
"平衡": ConversationStyle.balanced,
"精确": ConversationStyle.precise,
}
if params[0] not in mapping:
reply_message = "风格参数错误,可选参数: 创意, 平衡, 精确"
return reply_message
setattr(revcfg, "new_bing_style", mapping[params[0]])
reply_message = "已切换到{}风格,重置会话后生效".format(params[0])
else:
current = "创意"
if getattr(revcfg, "new_bing_style") == ConversationStyle.balanced:
current = "平衡"
elif getattr(revcfg, "new_bing_style") == ConversationStyle.precise:
current = "精确"
reply_message = "当前风格为: {},可选参数: 创意, 平衡, 精确\n例如: !style 创意".format(current)
else:
reply_message = "仅当使用New Bing逆向库时可切换风格"
elif cmd == "provider":
if revss.__rev_interface_impl_class__ == gpt4free.GPT4FreeImpl:
if len(params) >= 1:
if params[0] == 'ls':
from g4f.Provider import __all__ as providers
providers = providers.copy()
reply_message = "适配器列表:\n"
for adapter in providers:
reply_message += " - {}\n".format(adapter)
reply_message = reply_message[:-1]
else:
if gpt4free.GPT4FreeImpl.use_provider is None:
reply_message = "当前未选择适配器,第一次对话时将测试并选择适配器"
else:
reply_message = "当前使用的适配器: {}".format(gpt4free.GPT4FreeImpl.use_provider)
else:
reply_message = "仅当使用gpt4free逆向库时可查看适配器"
return reply_message
================================================
FILE: pkg/process/procmsg.py
================================================
import time
import plugins.revLibs.pkg.process.revss as revss
from pkg.plugin.host import PluginHost
import logging
from mirai import MessageChain
from mirai.models.message import ForwardMessageNode
from plugins.revLibs.pkg.models.forward import Forward, ForwardMessageDiaplay
import traceback
import pkg.utils.context as context
import pkg.qqbot.manager as qqmgr
__host__: PluginHost = None
def process_message(session_name: str, prompt: str, host: PluginHost, **kwargs) -> str:
"""处理消息"""
global __host__
logging.info("[rev] 收到{}消息: {}".format(session_name, prompt))
if __host__ is None:
__host__ = host
if host is None:
host = __host__
import revcfg
# 重试循环
fail_times = 0
reply_message = ""
while True:
session: revss.RevSession = revss.get_session(session_name)
try:
if hasattr(revcfg, "blog_msg_strategy"):
logging.warning("[rev] 逆向库不再进行长消息处理,请使用主程序的长消息处理功能,详情请查看主程序的config-template.py")
all_reply = ""
for section in session.get_reply(prompt):
all_reply += section
reply_message = all_reply
# 发送使用量信息
from pkg.utils.context import get_openai_manager
openai_mgr = get_openai_manager()
openai_mgr.audit_mgr.report_to_server(
revcfg.reverse_lib,
len(reply_message)
)
break
except Exception as e:
traceback.print_exc()
if str(e).__contains__("Too many requests in 1 hour"):
session.__init__(session_name)
logging.warn("超过一小时限次,切换会话账户")
continue
if fail_times < revcfg.retry_when_fail:
fail_times += 1
logging.error(traceback.format_exc())
logging.warn("失败,重试({}/{})...".format(fail_times, revcfg.retry_when_fail))
time.sleep(2)
continue
else:
raise e
return reply_message
================================================
FILE: pkg/process/revss.py
================================================
# 逆向库的session
from plugins.revLibs.pkg.models.interface import RevLibInterface
from plugins.revLibs.pkg.process.impls.v1impl import RevChatGPTV1
from plugins.revLibs.pkg.process.impls.edgegpt import EdgeGPTImpl
from plugins.revLibs.pkg.process.impls.hugchat import HugChatImpl
from plugins.revLibs.pkg.process.impls.claude import ClaudeImpl
from plugins.revLibs.pkg.process.impls.bard import BardImpl
import pkg.openai.dprompt as dprompt
import uuid
import time
import logging
import threading
import config
__sessions__ = {}
"""所有session"""
__rev_interface_impl_class__: RevLibInterface = None
class RevSession:
name: str
conversation_id: str = None
"""会话id,第一次获取到回复时生成"""
parent_id: str = None
"""父会话id"""
__rev_interface_impl__: RevLibInterface = None
__ls_prompt__: str = ""
__set_prompt__: str = ""
using_account: dict = None
last_interaction_time: int = 0
"""最后一次交互时间"""
getting_reply: bool = False
def __init__(self, name: str):
self.name = name
logging.debug("[rev] 逆向库接口实现为 {}".format(__rev_interface_impl_class__))
self.__rev_interface_impl__, valid, acc = __rev_interface_impl_class__.create_instance()
self.using_account = acc
self.reset()
# if __rev_interface_impl_class__ is RevChatGPTV1:
# logging.debug("[rev] 逆向接口实现为RevChatGPTV1")
# self.__rev_interface_impl__, valid, acc = __rev_interface_impl_class__.create_instance()
# self.using_account = acc
# self.reset()
# elif __rev_interface_impl_class__ is EdgeGPTImpl:
# logging.debug("[rev] 逆向接口实现为EdgeGPTImpl")
# self.__rev_interface_impl__,_ = __rev_interface_impl_class__.create_instance()
# self.reset()
# elif __rev_interface_impl_class__ is HugChatImpl:
# logging.debug("[rev] 逆向接口实现为HugChatImpl")
# self.__rev_interface_impl__,_,_ = __rev_interface_impl_class__.create_instance()
# self.reset()
# elif __rev_interface_impl_class__ is ClaudeImpl:
# logging.debug("[rev] 逆向接口实现为ClaudeImpl")
# self.__rev_interface_impl__,_,_ = __rev_interface_impl_class__.create_instance()
# self.reset()
# elif __rev_interface_impl_class__ is BardImpl:
# logging.debug("[rev] 逆向接口实现为BardImpl")
# self.__rev_interface_impl__,_,_ = __rev_interface_impl_class__.create_instance()
# self.reset()
threading.Thread(target=self.check_expire_loop, daemon=True).start()
def check_expire_loop(self):
while True:
time.sleep(60)
if self not in __sessions__.values():
break
if self.last_interaction_time < int(time.time()) - config.session_expire_time and not self.getting_reply:
# 删除此session
logging.info("[rev] 会话 {} 已过期,自动重置".format(self.name))
del __sessions__[self.name]
break
def get_rev_lib_inst(self):
return self.__rev_interface_impl__.get_rev_lib_inst()
def get_reply(self, prompt: str, **kwargs) -> str:
"""获取回复"""
self.getting_reply = True
if self.__rev_interface_impl__ is None:
raise Exception("逆向接口未初始化")
self.last_interaction_time = int(time.time())
self.__ls_prompt__ = prompt
if self.conversation_id is not None:
kwargs['conversation_id'] = self.conversation_id
using_name = dprompt.mode_inst().get_using_name()
dprompt_, _ = dprompt.mode_inst().get_prompt(using_name)
if self.__set_prompt__ != "":
dprompt_ = self.__set_prompt__
self.__set_prompt__ = ""
if dprompt_ != "" and self.conversation_id is None and __rev_interface_impl_class__ is not EdgeGPTImpl: # new bing不使用情景预设
if type(dprompt_) == list:
dprompt_ = dprompt_[0]['content']
# prompt = dprompt_ +" \n"+ prompt
prompt = f"{dprompt_} \n{prompt}"
logging.info("[rev] 使用情景预设: {}".format(dprompt_))
# 改成迭代器以支持回复分节
for reply_period_msg, reply_period_dict in self.__rev_interface_impl__.get_reply(prompt, **kwargs):
if __rev_interface_impl_class__ is RevChatGPTV1:
self.conversation_id = reply_period_dict['conversation_id']
else:
self.conversation_id = uuid.uuid4().hex
yield reply_period_msg
self.getting_reply = False
def reset(self, using_prompt_name: str = None) -> str:
"""重置会话"""
self.conversation_id = None
self.parent_id = None
self.__ls_prompt__ = ""
self.__rev_interface_impl__.reset_chat()
if using_prompt_name is not None:
for key in dprompt.mode_inst().list():
if key.startswith(using_prompt_name):
using_prompt_name = key
break
self.__set_prompt__ = dprompt.mode_inst().get_prompt(using_prompt_name)
return using_prompt_name
def resend(self):
"""重新发送上一条消息"""
self.__rev_interface_impl__.rollback()
import plugins.revLibs.pkg.process.procmsg as procmsg # 不优雅的解决办法
return procmsg.process_message(self.name, self.__ls_prompt__, None, launcher_type=self.name.split("_")[0], launcher_id=int(self.name.split("_")[1]))
def get_session(name: str) -> RevSession:
"""获取session"""
if name not in __sessions__:
# 创建session
__sessions__[name] = RevSession(name)
return __sessions__[name]
================================================
FILE: pkg/utils.py
================================================
from pip._internal import main as pipmain
def upgrade_revlibs():
"""更新逆向库"""
pipmain(['install', '--upgrade', 'revChatGPT', '--quiet'])
import main
main.reset_logging()
================================================
FILE: requirements.txt
================================================
revChatGPT~=6.8.6
EdgeGPT~=0.13.2
hugchat
requests
claude-api
bardapi
g4f==0.1.9.3
PyExecJS
================================================
FILE: revcfg-template.py
================================================
from EdgeGPT.EdgeGPT import ConversationStyle
# 选择使用的逆向库
# 目前支持以下库:
# - "acheong08/ChatGPT.V1": acheong08/ChatGPT库的V1版本
# - "acheong08/EdgeGPT": acheong08/EdgeGPT库,接入new bing
# - "Soulter/hugging-chat-api": Soulter/hugging-chat-api库,接入hugging chat
# - "KoushikNavuluri/Claude-API": KoushikNavuluri/Claude-API库,接入Claude
# - "dsdanielpark/Bard-API": dsdanielpark/Bard-API库,接入Bard
# - "xtekky/gpt4free": xtekky/gpt4free库,接入多个平台的免费的 GPT-4,无需鉴权
reverse_lib = "acheong08/ChatGPT.V1"
# [必填][❗此说明很重要,请您认真阅读❗] OpenAI账户信息
# *仅使用acheong08/ChatGPT.V1时填写
# 目前支持三种登录方式:
# - 账号密码登录(仅支持ChatGPT Plus账号)
# - SessionToken登录(仅Microsoft、Google账号注册的账号)
# - accessToken登录(普通账号请使用此方法登录)
#
# *账号密码登录方式,例如:
# openai_account = {
# "email": "your email",
# "password": "your password"
# }
#
# *若要使用SessionToken登录方式,请删掉email和password参数,添加session_token参数:
# 例如:
# openai_account = {
# "session_token": "your session token"
# }
#
# *若要使用accessToken登录方式,请删掉email和password参数,添加access_token参数:
# 你可以在 https://chat.openai.com/api/auth/session 返回的数据中找到你的accessToken,记得先登录再获取
# 例如:
# openai_account = {
# "access_token": "your access token"
# }
#
# 除了登录信息,还支持以下可选参数:
# - proxy: 代理服务器地址,格式为"protocol:ip:port",例如"https://localhost:1080"
# - paid: 是否订阅了ChatGPT Plus服务,若为True则使用ChatGPT Plus服务
# - model: 使用的模型, 若要使用GPT-4, 可以添加此参数并设置为"gpt-4"
# 可选参数填写格式示例:
# openai_account = [
# {
# "access_token": "your access_token",
# "proxy": "https://localhost:1080",
# "paid": True,
# "model": "gpt-4"
# }
# ]
#
# **若要使用多个账户均衡负载,可以以列表的形式添加多个账户信息,例如:
# openai_account = [
# {
# "access_token": "your access_token",
# },
# {
# "access_token": "your access_token",
# }
# ]
# 其中每个账户的格式符合前文所述的格式
openai_account = [
{
"access_token": "your access_token",
}
]
# 账号重新恢复使用的时间间隔
# 以分钟为单位
openai_account_resume_interval = 60
# New Bing的代理地址
# 参考config.py中openai的代理地址
# 若为None则不使用代理
new_bing_proxy = None
# New Bing的Style
# 请将此值设置为以下之一:
# ConversationStyle.creative 有创意
# ConversationStyle.balanced 平衡
# ConversationStyle.precise 精确
new_bing_style = ConversationStyle.balanced
# 使用New Bing时是否显示参考资料
output_references = True
# 使用 revChatGPT 时使用的反向代理
# 现在不用反向代理基本没法用了吧,可以自己上github找一下
# 用来搭建 ChatGPT 反向代理的项目
# 或者到 QChatGPT 主页找到社区群加进去有公用的反向代理
# 这里默认的是作者的反向代理,但是不保证一直可用
revchatgpt_reverse_proxy = "https://chatproxy.rockchin.top/api/"
# 使用 New Bing (EdgeGPT) 时使用的反向代理
# 参考 revchatgpt_reverse_proxy,但是你需要的是 New Bing 的反向代理
# 需要不同的项目,社区群里也有公用的
new_bing_reverse_proxy = ""
# 消息回复前缀
# 建议保留此前缀,以便区分GPT-3和此插件的回复
reply_prefix = "[REV]"
# 获取回复失败时的重试次数
# 若为0则不重试
retry_when_fail = 3
# 使用 gpt4free 时,仅使用的适配器名称列表
# 程序将在这些适配器中选择一个可用的适配器
# 例如:
# g4f_use_adapters = ['Acytoo', 'FakeGpt']
#
# 若为 空列表 则会测试所有适配器并自动选择
# 所有适配器列表可以在
# https://github.com/xtekky/gpt4free/blob/main/g4f/Provider/__init__.py
# 中找到
# 也可以再启动机器人之后,发送命令 `!provider ls` 列出所有适配器
#
# 注意:设置此字段可能会影响可用性,请确认指定的适配器可用
g4f_use_adapters = []
# 使用 gpt4free 时,排除的适配器名称
# 此字段优先级高于 g4f_use_adapters
g4f_exclude_adapters = []
gitextract_2z_xvd8v/ ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ └── issue模板.md │ └── dependabot.yml ├── .gitignore ├── README.md ├── __init__.py ├── main.py ├── pkg/ │ ├── __init__.py │ ├── accounts/ │ │ └── accmgr.py │ ├── models/ │ │ ├── forward.py │ │ └── interface.py │ ├── process/ │ │ ├── __init__.py │ │ ├── impls/ │ │ │ ├── __init__.py │ │ │ ├── bard.py │ │ │ ├── claude.py │ │ │ ├── edgegpt.py │ │ │ ├── fproxy.py │ │ │ ├── gpt4free.py │ │ │ ├── hugchat.py │ │ │ └── v1impl.py │ │ ├── proccmd.py │ │ ├── procmsg.py │ │ └── revss.py │ └── utils.py ├── requirements.txt └── revcfg-template.py
SYMBOL INDEX (81 symbols across 15 files)
FILE: main.py
function check_config (line 17) | def check_config():
class RevLibsPlugin (line 38) | class RevLibsPlugin(Plugin):
method __init__ (line 43) | def __init__(self, plugin_host: PluginHost):
method make_reply (line 187) | def make_reply(self, prompt, **kwargs) -> dict:
method __del__ (line 197) | def __del__(self):
FILE: pkg/accounts/accmgr.py
function get_account_list (line 4) | def get_account_list():
function get_account_brief_name (line 11) | def get_account_brief_name(account: dict):
function move_account_to_end (line 22) | def move_account_to_end(account: dict):
function delete_invalid_attr (line 32) | def delete_invalid_attr(account: dict):
function use_account (line 39) | def use_account() -> tuple[bool, dict]:
function report_invalidation (line 60) | def report_invalidation(account: dict):
FILE: pkg/models/forward.py
class ForwardMessageDiaplay (line 7) | class ForwardMessageDiaplay(MiraiBaseModel):
class Forward (line 15) | class Forward(MessageComponent):
method __init__ (line 23) | def __init__(self, *args, **kwargs):
method __str__ (line 29) | def __str__(self):
FILE: pkg/models/interface.py
class RevLibInterface (line 4) | class RevLibInterface:
method create_instance (line 8) | def create_instance() -> tuple["RevLibInterface", bool, dict]:
method get_rev_lib_inst (line 11) | def get_rev_lib_inst(self):
method get_reply (line 14) | def get_reply(self, prompt: str, **kwargs) -> Tuple[str, dict]:
method reset_chat (line 17) | def reset_chat(self, **kwargs):
method rollback (line 20) | def rollback(self):
FILE: pkg/process/impls/bard.py
class BardImpl (line 12) | class BardImpl(RevLibInterface):
method create_instance (line 19) | def create_instance() -> tuple[RevLibInterface, bool, dict]:
method __init__ (line 32) | def __init__(self, cookies: str = None):
method get_rev_lib_inst (line 48) | def get_rev_lib_inst(self):
method get_reply (line 51) | def get_reply(self, prompt: str, **kwargs) -> Tuple[str, dict]:
method reset_chat (line 58) | def reset_chat(self):
method rollback (line 61) | def rollback(self):
FILE: pkg/process/impls/claude.py
class ClaudeImpl (line 12) | class ClaudeImpl(RevLibInterface):
method create_instance (line 19) | def create_instance() -> tuple[RevLibInterface, bool, dict]:
method __init__ (line 38) | def __init__(self, cookies: str = None):
method get_rev_lib_inst (line 41) | def get_rev_lib_inst(self):
method get_reply (line 44) | def get_reply(self, prompt: str, **kwargs) -> Tuple[str, dict]:
method reset_chat (line 54) | def reset_chat(self):
method rollback (line 57) | def rollback(self):
FILE: pkg/process/impls/edgegpt.py
class EdgeGPTImpl (line 15) | class EdgeGPTImpl(RevLibInterface):
method create_instance (line 27) | def create_instance() -> tuple[RevLibInterface, bool]:
method __init__ (line 32) | def __init__(self, style):
method get_rev_lib_inst (line 60) | def get_rev_lib_inst(self):
method get_reply (line 63) | def get_reply(self, prompt: str, **kwargs) -> tuple[str, dict]:
method reset_chat (line 110) | def reset_chat(self):
method rollback (line 113) | def rollback(self):
FILE: pkg/process/impls/fproxy.py
class Proxy (line 1) | class Proxy:
method __init__ (line 6) | def __init__(self, funcs: list):
method prompt (line 9) | def prompt(self, user_prompt: str):
method call (line 78) | def call(self, func_name: str, args: dict) -> tuple[bool, str, any]:
method extra_function_call (line 84) | def extra_function_call(self, text: str):
FILE: pkg/process/impls/gpt4free.py
class GPT4FreeImpl (line 10) | class GPT4FreeImpl(RevLibInterface):
method create_instance (line 19) | def create_instance() -> tuple[RevLibInterface, bool, dict]:
method select_provider (line 23) | def select_provider(cls):
method __init__ (line 69) | def __init__(self):
method get_rev_lib_inst (line 76) | def get_rev_lib_inst(self):
method get_reply (line 79) | def get_reply(self, prompt: str, **kwargs) -> Tuple[str, dict]:
method reset_chat (line 119) | def reset_chat(self):
method rollback (line 122) | def rollback(self):
FILE: pkg/process/impls/hugchat.py
class HugChatImpl (line 12) | class HugChatImpl(RevLibInterface):
method create_instance (line 17) | def create_instance() -> tuple[RevLibInterface, bool, dict]:
method __init__ (line 29) | def __init__(self, cookies_dict: dict = None):
method get_rev_lib_inst (line 32) | def get_rev_lib_inst(self):
method get_reply (line 35) | def get_reply(self, prompt: str, **kwargs) -> Tuple[str, dict]:
method reset_chat (line 42) | def reset_chat(self):
method rollback (line 45) | def rollback(self):
FILE: pkg/process/impls/v1impl.py
function get_lock (line 11) | def get_lock(key: str):
class RevChatGPTV1 (line 20) | class RevChatGPTV1(RevLibInterface):
method create_instance (line 27) | def create_instance() -> tuple[RevLibInterface, bool, dict]:
method __init__ (line 32) | def __init__(self, cfg):
method get_rev_lib_inst (line 48) | def get_rev_lib_inst(self):
method get_reply (line 51) | def get_reply(self, prompt: str, **kwargs) -> Tuple[str, dict]:
method reset_chat (line 142) | def reset_chat(self):
method rollback (line 145) | def rollback(self):
FILE: pkg/process/proccmd.py
function process_command (line 7) | def process_command(session_name: str, **kwargs) -> str:
FILE: pkg/process/procmsg.py
function process_message (line 15) | def process_message(session_name: str, prompt: str, host: PluginHost, **...
FILE: pkg/process/revss.py
class RevSession (line 23) | class RevSession:
method __init__ (line 45) | def __init__(self, name: str):
method check_expire_loop (line 77) | def check_expire_loop(self):
method get_rev_lib_inst (line 88) | def get_rev_lib_inst(self):
method get_reply (line 91) | def get_reply(self, prompt: str, **kwargs) -> str:
method reset (line 128) | def reset(self, using_prompt_name: str = None) -> str:
method resend (line 142) | def resend(self):
function get_session (line 150) | def get_session(name: str) -> RevSession:
FILE: pkg/utils.py
function upgrade_revlibs (line 3) | def upgrade_revlibs():
Condensed preview — 25 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (60K chars).
[
{
"path": ".github/ISSUE_TEMPLATE/issue模板.md",
"chars": 223,
"preview": "---\nname: issue模板\nabout: 任何问题请使用这个模板创建\ntitle: \"\"\nlabels: ''\nassignees: ''\n\n---\n\n请您认真填写以下信息。\n\n### 任务\n\n- [ ] 我已严格按照文档中的步骤操"
},
{
"path": ".github/dependabot.yml",
"chars": 585,
"preview": "# To get started with Dependabot version updates, you'll need to specify which\n# package ecosystems to update and where "
},
{
"path": ".gitignore",
"chars": 12,
"preview": "__pycache__/"
},
{
"path": "README.md",
"chars": 3317,
"preview": "# RevLib Support for QChatGPT\n\n> 2023/8/29 现已支持`gpt4free`,请查看下方的使用方法 \n> 2023/8/14 现已支持`Claude`和`Bard`,请查看下方的使用方法 \n> 20"
},
{
"path": "__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "main.py",
"chars": 7073,
"preview": "import traceback\n\nfrom pkg.plugin.models import *\nfrom pkg.plugin.host import EventContext, PluginHost, emit\n\nimport tim"
},
{
"path": "pkg/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "pkg/accounts/accmgr.py",
"chars": 2279,
"preview": "import time\n\n\ndef get_account_list():\n import revcfg\n if type(revcfg.openai_account) is dict:\n revcfg.opena"
},
{
"path": "pkg/models/forward.py",
"chars": 803,
"preview": "from mirai.models.message import MessageComponent\nfrom mirai.models.message import ForwardMessageNode\nfrom mirai.models."
},
{
"path": "pkg/models/interface.py",
"chars": 486,
"preview": "from typing import Tuple\n\n\nclass RevLibInterface:\n \"\"\"逆向库接口\"\"\"\n\n @staticmethod\n def create_instance() -> tuple["
},
{
"path": "pkg/process/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "pkg/process/impls/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "pkg/process/impls/bard.py",
"chars": 1558,
"preview": "from typing import Tuple\nimport logging\n\nfrom plugins.revLibs.pkg.models.interface import RevLibInterface\n\nfrom bardapi "
},
{
"path": "pkg/process/impls/claude.py",
"chars": 1532,
"preview": "from typing import Tuple\nimport logging\n\nfrom plugins.revLibs.pkg.models.interface import RevLibInterface\n\nfrom claude_a"
},
{
"path": "pkg/process/impls/edgegpt.py",
"chars": 4227,
"preview": "\"\"\"接入acheone08/EdgeGPT\n\"\"\"\nimport os\nimport logging\nimport json\nimport asyncio\n\nfrom plugins.revLibs.pkg.models.interfac"
},
{
"path": "pkg/process/impls/fproxy.py",
"chars": 3072,
"preview": "class Proxy:\n\n funcs: list\n\n\n def __init__(self, funcs: list):\n self.funcs = funcs\n\n def prompt(self, us"
},
{
"path": "pkg/process/impls/gpt4free.py",
"chars": 3572,
"preview": "from typing import Tuple\nimport logging\n\nfrom plugins.revLibs.pkg.models.interface import RevLibInterface\n\nimport g4f\nfr"
},
{
"path": "pkg/process/impls/hugchat.py",
"chars": 1254,
"preview": "from typing import Tuple\nimport logging\n\nfrom plugins.revLibs.pkg.models.interface import RevLibInterface\n\nfrom hugchat "
},
{
"path": "pkg/process/impls/v1impl.py",
"chars": 4268,
"preview": "from typing import Tuple\nfrom plugins.revLibs.pkg.models.interface import RevLibInterface\n\nfrom revChatGPT.V1 import Cha"
},
{
"path": "pkg/process/proccmd.py",
"chars": 5078,
"preview": "import plugins.revLibs.pkg.process.revss as revss\nimport plugins.revLibs.pkg.process.impls.v1impl as v1impl\nimport plugi"
},
{
"path": "pkg/process/procmsg.py",
"chars": 2061,
"preview": "import time\nimport plugins.revLibs.pkg.process.revss as revss\nfrom pkg.plugin.host import PluginHost\nimport logging\nfrom"
},
{
"path": "pkg/process/revss.py",
"chars": 5678,
"preview": "# 逆向库的session\nfrom plugins.revLibs.pkg.models.interface import RevLibInterface\nfrom plugins.revLibs.pkg.process.impls.v1"
},
{
"path": "pkg/utils.py",
"chars": 185,
"preview": "from pip._internal import main as pipmain\n\ndef upgrade_revlibs():\n \"\"\"更新逆向库\"\"\"\n pipmain(['install', '--upgrade', '"
},
{
"path": "requirements.txt",
"chars": 92,
"preview": "revChatGPT~=6.8.6\nEdgeGPT~=0.13.2\nhugchat\nrequests\nclaude-api\nbardapi\ng4f==0.1.9.3\nPyExecJS\n"
},
{
"path": "revcfg-template.py",
"chars": 2985,
"preview": "from EdgeGPT.EdgeGPT import ConversationStyle\n# 选择使用的逆向库\n# 目前支持以下库:\n# - \"acheong08/ChatGPT.V1\": acheong08/ChatGPT库的V1版本\n"
}
]
About this extraction
This page contains the full source code of the RockChinQ/revLibs GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 25 files (49.2 KB), approximately 14.0k tokens, and a symbol index with 81 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.