Skip to content

Commit

Permalink
增加 BingChat 搜索调用扩展
Browse files Browse the repository at this point in the history
  • Loading branch information
KroMiose committed Mar 28, 2024
1 parent 4b1cd86 commit c2abfc0
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ nb plugin install nonebot-plugin-naturel-gpt
- [x] TTS 文字转语音: 让 TA 开口说话!(通过扩展模块实现)
- [x] 潜在人格唤醒机制: 当用户呼叫未启用的人格时,可自动切换人格 (可选开关)
- [x] 定时任务: 可以用自然语言直接定时,让 TA 提醒你该吃饭了!
- [x] 在线搜索/读链接: GPT3.5 的数据库过时了?通过主动搜索扩展让 TA 可以实时检索到最新的信息 (仿 newbing 效果)
- [x] 在线搜索/读链接: GPT3.5 的数据库过时了?通过主动搜索扩展让 TA 可以实时检索到最新的信息 (支持 Google, Bing Copilot 等)
- [x] 输出内容转图片: 使用 htmlrender 将 TA 的回复转换为图片,降低风控几率 (可选开关,感谢 @HMScygnet 提供 pr)
- [x] Minecraft 服务器接入,让她在游戏中为你服务,使用 GPT 的能力编写各种复杂的 NBT 指令
- [x] 消息节流机制,短时间内接受到大量消息时,只对最后一条消息进行回复 (可配置)
Expand Down
28 changes: 28 additions & 0 deletions docs/extension_list.md
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,34 @@ max_results: 3

<hr />

## [必应聊天扩展模块](https://github.com/KroMiose/nonebot_plugin_naturel_gpt/blob/main/extensions/ext_bing_chat.py)

!> 请勿与其它搜索拓展一并启用

### 简介 <!-- {docsify-ignore} -->

赋予 bot 使用必应 Copilot 查询复杂问题的能力

### 配置 <!-- {docsify-ignore} -->

请根据下方示例配置中的注释来编辑你的扩展配置

```yml
# [必填] Bing Cookie [_U]
# 获取方式:
# 1. 打开 `https://www.bing.com/` 并登录 Microsoft 账号 (!注意: 使用此扩展有账号封禁风险,请自行权衡,作者不对其产生的任何影响负责!)
# 2. 按 F12 打开开发者工具,切换到 Storage 选项卡,找到 `Cookies` -> `https://www.bing.com` -> `Name = _U`,复制其 `Value` 字段值填写到此处
_u: ""

# 访问 Bing 的代理服务器地址
proxy: null

# 限制必应回答的最大长度
res_size: 1000
```

<hr />

## [主动搜索扩展模块](https://github.com/KroMiose/nonebot_plugin_naturel_gpt/blob/main/extensions/ext_search.py)

!> 请勿与其它搜索拓展一并启用
Expand Down
94 changes: 94 additions & 0 deletions extensions/ext_bing_chat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import time
from typing import Optional

from nonebot import logger

from .Extension import Extension

try:
from bing_chat import BingGPT
from bing_chat.conversation_style import ConversationStyle
except ImportError:
logger.error("BingChat 模块导入失败,请在 Bot 运行环境中使用 `pip install bing-chat` 安装")

# 扩展的配置信息,用于ai理解扩展的功能 *必填*
ext_config: dict = {
"name": "ask", # 扩展名称,用于标识扩展
"arguments": {
"question": "str", # 关键字
},
# 扩展的描述信息,用于提示ai理解扩展的功能 *必填* 尽量简短 使用英文更节省token
# 如果bot无法理解扩展的功能,可适当添加使用示例 格式: /#扩展名&参数1&...&参数n#/
"description": "Ask a **specific question** through BingChat online search. (usage in response: /#ask&什么是BingChat?#/ Because BingChat is a chat AI, you need to ask questions in a chat tone, not just simple search terms. Generally you should ask questions in Chinese)",
# 参考词,用于上下文参考使用,为空则每次都会被参考(消耗token)
"refer_word": [],
# 每次消息回复中最大调用次数,不填则默认为99
"max_call_times_per_msg": 1,
# 作者信息
"author": "KroMiose",
# 版本
"version": "0.0.1",
# 扩展简介
"intro": "使用 BingChat 进行在线查询",
# 调用时是否打断响应 启用后将会在调用后截断后续响应内容
"interrupt": True,
}


class CustomExtension(Extension):
async def call(self, arg_dict: dict, _: dict) -> dict:
custom_config: dict = self.get_custom_config()
proxy = custom_config.get("proxy", None)
_u = custom_config.get("_u", None)
res_size = custom_config.get("res_size", 1000)
re_use_time = custom_config.get("re_use_time", 10)

if proxy and (not proxy.startswith("http")):
proxy = "http://" + proxy

raw_question = arg_dict.get("question", None)

if (
raw_question is None
or raw_question == self._last_question
or time.time() - self._last_call_time < 10
):
return {}

question = f"在下面的对话中,请尽可能准确简洁地回答我的问题。不要提供任何无关的信息或回应,也不要问我是否需要帮助。 \n\n我的第一个问题是: {raw_question} (请使用中文回答)"

try:
text = await ask_question(_u, question, proxy)
text = text[: res_size] + "..." if len(text) > res_size else text
except Exception:
return {
"text": f"[BingChat] 未找到关于 '{raw_question}' 的信息或请求发生错误",
"image": None,
"voice": None,
}
else:
self._last_question = raw_question
self._last_call_time = time.time()
return {
"text": f"[BingChat] 搜索: {raw_question} [完成]",
"notify": {
"sender": "[BingChat]",
"msg": f"[Question answer from BingChat (question:{raw_question}) (The following information will not be sent directly to chat. Please make a statement based on that information.y)]\n{text}",
},
"wake_up": True,
}

def __init__(self, custom_config: dict):
super().__init__(ext_config.copy(), custom_config)
self._last_question = None
self._last_call_time = 0
self._current_reuse_time = 0


async def ask_question(_u: str, question: str, proxy: Optional[str]) -> str:
c = BingGPT.Chatbot(
proxy=proxy,
cookies=[{"name": "_U", "value": _u}],
)
response = await c.ask(question, conversation_style=ConversationStyle.precise)
return response["item"]["result"]["message"]

0 comments on commit c2abfc0

Please sign in to comment.