mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-08-30 22:27:13 +00:00
Merge pull request #50 from RockChinQ/response-rules
feat: 支持除@之外的群内其他响应机制 #28
This commit is contained in:
@@ -17,7 +17,7 @@
|
|||||||
<summary>✅回复符合上下文</summary>
|
<summary>✅回复符合上下文</summary>
|
||||||
|
|
||||||
- 程序向模型发送近几次对话内容,模型根据上下文生成回复
|
- 程序向模型发送近几次对话内容,模型根据上下文生成回复
|
||||||
- 您可在`config.py`中修改`prompt_submit_round_amount`及`process_message_timeout`自定义联系上下文的范围
|
- 您可在`config.py`中修改`process_message_timeout`自定义联系上下文的范围
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|||||||
+31
-25
@@ -28,21 +28,9 @@ openai_config = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
# 单个api-key的使用量警告阈值
|
|
||||||
# 当使用此api-key进行请求的文字量达到此阈值时,会在控制台输出警告并通知管理员
|
|
||||||
# 若之后还有未使用超过此值的api-key,则会切换到新的api-key进行请求
|
|
||||||
api_key_usage_threshold = 900000
|
|
||||||
|
|
||||||
# 管理员QQ号,用于接收报错等通知,为0时不发送通知
|
# 管理员QQ号,用于接收报错等通知,为0时不发送通知
|
||||||
admin_qq = 0
|
admin_qq = 0
|
||||||
|
|
||||||
# 回复消息时是否显示[GPT]前缀
|
|
||||||
show_prefix = False
|
|
||||||
|
|
||||||
# 敏感词过滤开关,以同样数量的*代替敏感词回复
|
|
||||||
# 请在sensitive.json中添加敏感词
|
|
||||||
sensitive_word_filter = True
|
|
||||||
|
|
||||||
# 每个会话的预设信息,影响所有会话,无视指令重置
|
# 每个会话的预设信息,影响所有会话,无视指令重置
|
||||||
# 可以通过这个字段指定某些情况的回复,可直接用自然语言描述指令
|
# 可以通过这个字段指定某些情况的回复,可直接用自然语言描述指令
|
||||||
# 例如: 如果我之后想获取帮助,请你说“输入!help获取帮助”,
|
# 例如: 如果我之后想获取帮助,请你说“输入!help获取帮助”,
|
||||||
@@ -50,30 +38,48 @@ sensitive_word_filter = True
|
|||||||
# 可参考 https://github.com/PlexPt/awesome-chatgpt-prompts-zh
|
# 可参考 https://github.com/PlexPt/awesome-chatgpt-prompts-zh
|
||||||
default_prompt = "如果我之后想获取帮助,请你说“输入!help获取帮助”"
|
default_prompt = "如果我之后想获取帮助,请你说“输入!help获取帮助”"
|
||||||
|
|
||||||
# OpenAI的completion API的参数
|
# 群内响应规则
|
||||||
# 具体请查看OpenAI的文档
|
# 符合此消息的群内消息即使不包含at机器人也会响应
|
||||||
completion_api_params = {
|
# 支持消息前缀匹配及正则表达式匹配
|
||||||
"model": "text-davinci-003",
|
# 注意:由消息前缀(prefix)匹配的消息中将会删除此前缀,正则表达式匹配的消息不会删除匹配的部分
|
||||||
"temperature": 0.6, # 数值越低得到的回答越理性,取值范围[0, 1]
|
# 前缀匹配优先级高于正则表达式匹配
|
||||||
"max_tokens": 512, # 每次向OpenAI请求的最大字符数, 不高于4096
|
# 正则表达式简明教程:https://www.runoob.com/regexp/regexp-tutorial.html
|
||||||
"top_p": 1, # 生成的文本的文本与要求的符合度, 取值范围[0, 1]
|
response_rules = {
|
||||||
"frequency_penalty": 0.2,
|
"prefix": ["/ai", "!ai", "!ai", "ai"],
|
||||||
"presence_penalty": 0.4,
|
"regexp": ["为什么.*", "怎么?样.*", "如何.*", "[Hh]ow to.*", "[Ww]hy not.*", "[Ww]hat is.*", ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# 单个api-key的使用量警告阈值
|
||||||
|
# 当使用此api-key进行请求的文字量达到此阈值时,会在控制台输出警告并通知管理员
|
||||||
|
# 若之后还有未使用超过此值的api-key,则会切换到新的api-key进行请求
|
||||||
|
api_key_usage_threshold = 900000
|
||||||
|
|
||||||
|
# 敏感词过滤开关,以同样数量的*代替敏感词回复
|
||||||
|
# 请在sensitive.json中添加敏感词
|
||||||
|
sensitive_word_filter = True
|
||||||
|
|
||||||
# 每次向OpenAI接口发送对话记录上下文的字符数
|
# 每次向OpenAI接口发送对话记录上下文的字符数
|
||||||
# 最大不超过(4096 - max_tokens)个字符,max_tokens为上述completion_api_params中的max_tokens
|
# 最大不超过(4096 - max_tokens)个字符,max_tokens为上述completion_api_params中的max_tokens
|
||||||
# 注意:较大的prompt_submit_length会导致OpenAI账户额度消耗更快
|
# 注意:较大的prompt_submit_length会导致OpenAI账户额度消耗更快
|
||||||
prompt_submit_length = 1536
|
prompt_submit_length = 1536
|
||||||
|
|
||||||
# 每次向OpenAI接口发送对话记录上下文的聊天回合数
|
# OpenAI的completion API的参数
|
||||||
# 不建议过大,向OpenAI接口发送对话上下文时保证内容不超过prompt_submit_length个字符,
|
# 具体请查看OpenAI的文档: https://beta.openai.com/docs/api-reference/completions/create
|
||||||
# 不超过prompt_submit_round_amount个回合
|
completion_api_params = {
|
||||||
prompt_submit_round_amount = 16
|
"model": "text-davinci-003",
|
||||||
|
"temperature": 0.6, # 数值越低得到的回答越理性,取值范围[0, 1]
|
||||||
|
"max_tokens": 512, # 每次向OpenAI请求的最大字符数, 不高于4096
|
||||||
|
"top_p": 1, # 生成的文本的文本与要求的符合度, 取值范围[0, 1]
|
||||||
|
"frequency_penalty": 0.2,
|
||||||
|
"presence_penalty": 1.0,
|
||||||
|
}
|
||||||
|
|
||||||
# 消息处理的超时时间,单位为秒
|
# 消息处理的超时时间,单位为秒
|
||||||
process_message_timeout = 15
|
process_message_timeout = 15
|
||||||
|
|
||||||
|
# 回复消息时是否显示[GPT]前缀
|
||||||
|
show_prefix = False
|
||||||
|
|
||||||
# 消息处理超时重试次数
|
# 消息处理超时重试次数
|
||||||
retry_times = 3
|
retry_times = 3
|
||||||
|
|
||||||
|
|||||||
@@ -139,7 +139,8 @@ class Session:
|
|||||||
def append(self, text: str) -> str:
|
def append(self, text: str) -> str:
|
||||||
self.last_interact_timestamp = int(time.time())
|
self.last_interact_timestamp = int(time.time())
|
||||||
|
|
||||||
max_rounds = config.prompt_submit_round_amount if hasattr(config, 'prompt_submit_round_amount') else 7
|
# max_rounds = config.prompt_submit_round_amount if hasattr(config, 'prompt_submit_round_amount') else 7
|
||||||
|
max_rounds = 1000 # 不再限制回合数
|
||||||
max_length = config.prompt_submit_length if hasattr(config, "prompt_submit_length") else 1024
|
max_length = config.prompt_submit_length if hasattr(config, "prompt_submit_length") else 1024
|
||||||
|
|
||||||
# 向API请求补全
|
# 向API请求补全
|
||||||
|
|||||||
+43
-8
@@ -28,6 +28,29 @@ def go(func, args=()):
|
|||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
|
|
||||||
|
# 检查消息是否符合泛响应匹配机制
|
||||||
|
def check_response_rule(text: str) -> (bool, str):
|
||||||
|
if not hasattr(config, 'response_rules'):
|
||||||
|
return False, ''
|
||||||
|
|
||||||
|
rules = config.response_rules
|
||||||
|
# 检查前缀匹配
|
||||||
|
if 'prefix' in rules:
|
||||||
|
for rule in rules['prefix']:
|
||||||
|
if text.startswith(rule):
|
||||||
|
return True, text.replace(rule, "", 1)
|
||||||
|
|
||||||
|
# 检查正则表达式匹配
|
||||||
|
if 'regexp' in rules:
|
||||||
|
for rule in rules['regexp']:
|
||||||
|
import re
|
||||||
|
match = re.match(rule, text)
|
||||||
|
if match:
|
||||||
|
return True, text
|
||||||
|
|
||||||
|
return False, ""
|
||||||
|
|
||||||
|
|
||||||
# 控制QQ消息输入输出的类
|
# 控制QQ消息输入输出的类
|
||||||
class QQBotManager:
|
class QQBotManager:
|
||||||
timeout = 60
|
timeout = 60
|
||||||
@@ -265,12 +288,10 @@ class QQBotManager:
|
|||||||
|
|
||||||
reply = ''
|
reply = ''
|
||||||
|
|
||||||
if Image in event.message_chain:
|
def process(text = None) -> str:
|
||||||
pass
|
replys = ""
|
||||||
elif At(self.bot.qq) not in event.message_chain:
|
if At(self.bot.qq) in event.message_chain:
|
||||||
pass
|
event.message_chain.remove(At(self.bot.qq))
|
||||||
else:
|
|
||||||
event.message_chain.remove(At(self.bot.qq))
|
|
||||||
|
|
||||||
processing.append("group_{}".format(event.sender.id))
|
processing.append("group_{}".format(event.sender.id))
|
||||||
|
|
||||||
@@ -278,7 +299,8 @@ class QQBotManager:
|
|||||||
failed = 0
|
failed = 0
|
||||||
for i in range(self.retry):
|
for i in range(self.retry):
|
||||||
try:
|
try:
|
||||||
reply = self.process_message('group', event.group.id, str(event.message_chain).strip())
|
replys = self.process_message('group', event.group.id,
|
||||||
|
str(event.message_chain).strip() if text is None else text)
|
||||||
break
|
break
|
||||||
except FunctionTimedOut:
|
except FunctionTimedOut:
|
||||||
failed += 1
|
failed += 1
|
||||||
@@ -286,7 +308,20 @@ class QQBotManager:
|
|||||||
|
|
||||||
if failed == self.retry:
|
if failed == self.retry:
|
||||||
self.notify_admin("{} 请求超时".format("group_{}".format(event.sender.id)))
|
self.notify_admin("{} 请求超时".format("group_{}".format(event.sender.id)))
|
||||||
reply = "[bot]err:请求超时"
|
replys = "[bot]err:请求超时"
|
||||||
|
|
||||||
|
return replys
|
||||||
|
|
||||||
|
if Image in event.message_chain:
|
||||||
|
pass
|
||||||
|
elif At(self.bot.qq) not in event.message_chain:
|
||||||
|
check, result = check_response_rule(str(event.message_chain).strip())
|
||||||
|
|
||||||
|
if check:
|
||||||
|
reply = process(result.strip())
|
||||||
|
else:
|
||||||
|
# 直接调用
|
||||||
|
reply = process()
|
||||||
|
|
||||||
if reply != '':
|
if reply != '':
|
||||||
return self.send(event, reply)
|
return self.send(event, reply)
|
||||||
|
|||||||
Reference in New Issue
Block a user