Compare commits

..

22 Commits

Author SHA1 Message Date
Rock Chin
1b69f0b668 doc: 整理README.md 2023-03-03 09:18:48 +08:00
Rock Chin
46b310ceb9 doc: 现已接入ChatGPT官方API 2023-03-03 00:35:15 +08:00
Rock Chin
85fe44ec92 Merge pull request #194 from LINSTCL/new-model-abstract
feat: 重构模型-接口抽象
feat: 适配官方GPT-3.5模型ChatCompletion接口
2023-03-03 00:33:00 +08:00
Rock Chin
fdcec0fbf7 doc: 致谢贡献者 2023-03-03 00:28:14 +08:00
Rock Chin
2664ea8622 feat: 删除config-template中对话角色的字段 2023-03-03 00:25:26 +08:00
Rock Chin
862724da74 doc: config-template.py添加模型参数说明 2023-03-03 00:23:44 +08:00
Rock Chin
a1c167fb7f feat: 功能完成 2023-03-03 00:21:16 +08:00
Rock Chin
adc2290fc1 Merge branch 'new-model-abstract' of https://github.com/LINSTCL/QChatGPT into new-model-abstract 2023-03-03 00:11:06 +08:00
Rock Chin
8713fd8130 feat: 完善会话处理的逻辑 2023-03-03 00:07:53 +08:00
LINSTCL
77df3d1ae5 修复使用文本完成模型生成对话型文本时输出随机AI名的问题 2023-03-02 23:50:51 +08:00
LINSTCL
2234e9db0e 修改对话拼接逻辑 2023-03-02 23:25:42 +08:00
Rock Chin
dd3d403de8 feat(modelmgr.py): 模型列表 2023-03-02 23:20:28 +08:00
Rock Chin
5364c36a79 feat(session.py): prompt默认值改为[] 2023-03-02 22:42:07 +08:00
Rock Chin
118fbe3f7d perf(modelmgr.py): 类名称强调其为一个请求对象 2023-03-02 19:50:31 +08:00
Rock Chin
61ec8e96f2 test: 模型-接口兼容性测试 2023-03-02 19:49:36 +08:00
LINSTCL
19289527ae 旧版本数据库兼容 2023-03-02 19:40:36 +08:00
Rock Chin
77fdd6ddb8 doc: 添加对官方ChatGPT API接入工作的说明 2023-03-02 18:15:13 +08:00
Rock Chin
f7830b5e9d feat(modelmgr.py): 完善可选模型列表 2023-03-02 17:57:39 +08:00
LINSTCL
13e5d76a44 修复模型切换角色改变引起的BUG 2023-03-02 16:52:23 +08:00
LINSTCL
7b8ad2e315 修复模型切换角色改变引起的BUG 2023-03-02 16:47:50 +08:00
Rock Chin
623f094e5b doc: 添加注释;完善格式 2023-03-02 16:41:03 +08:00
LINSTCL
fd25d61b56 重构了模型抽象,用来更好的支持gpt-3.5-turbo 2023-03-02 15:31:12 +08:00
9 changed files with 301 additions and 140 deletions

View File

@@ -1,28 +1,20 @@
# QChatGPT🤖
### 🎉现已支持接入ChatGPT网页版详情请完成部署并查看底部**插件**小节或[此仓库](https://github.com/RockChinQ/revLibs)
> 2023/3/3 现已在主线支持官方ChatGPT接口使用方法查看[#195](https://github.com/RockChinQ/QChatGPT/issues/195)
> 2023/3/2 OpenAI已发布ChatGPT官方接口我们正在全力接入预计明日前完成请查看[此PR](https://github.com/RockChinQ/QChatGPT/pull/194)
> 2023/2/16 现已支持接入ChatGPT网页版详情请完成部署并查看底部**插件**小节或[此仓库](https://github.com/RockChinQ/revLibs)
- 到[项目Wiki](https://github.com/RockChinQ/QChatGPT/wiki)可了解项目详细信息
- 由bilibili TheLazy制作的[视频教程](https://www.bilibili.com/video/BV15v4y1X7aP)
- 测试号: 2196084348已加载逆向库插件、每分钟限速、~~1480613886已加载逆向库插件~~(被封)
- 交流、答疑群: ~~204785790~~已满、691226829
- **进群提问前请您`确保`已经找遍文档和issue均无法解决**
- **进群提问前请您`确保`已经找遍文档和issue均无法解决**
- **进群提问前请您`确保`已经找遍文档和issue均无法解决**
- QQ频道机器人见[QQChannelChatGPT](https://github.com/Soulter/QQChannelChatGPT)
通过调用OpenAI GPT-3模型提供的Completion API来实现一个更加智能的QQ机器人
通过调用OpenAI的ChatGPT等语言模型来实现一个更加智能的QQ机器人
## ✅功能
<details>
<summary>✅回复符合上下文</summary>
- 程序向模型发送近几次对话内容,模型根据上下文生成回复
- 您可在`config.py`中修改`prompt_submit_length`自定义联系上下文的范围
</details>
<details>
<summary>✅支持敏感词过滤,避免账号风险</summary>
@@ -30,7 +22,6 @@
- 编辑`sensitive.json`,并在`config.py`中修改`sensitive_word_filter`的值以开启此功能
</details>
<details>
<summary>✅群内多种响应规则不必at</summary>
@@ -38,14 +29,6 @@
- 详细见`config.py`中的`response_rules`字段
</details>
<details>
<summary>✅使用官方api不需要网络代理稳定快捷</summary>
- 不使用ChatGPT逆向接口而使用官方的Completion API稳定性高
- 您可以在`config.py`中自定义`completion_api_params`字段设置向官方API提交的参数以自定义机器人的风格
</details>
<details>
<summary>✅完善的多api-key管理超额自动切换</summary>
@@ -55,13 +38,6 @@
- 运行期间向机器人说`!usage`以查看当前使用情况
</details>
<details>
<summary>✅组件少部署方便提供一键安装器及Docker安装</summary>
- 手动部署步骤少
- 提供自动安装器及docker方式详见以下安装步骤
</details>
<details>
<summary>✅支持预设指令文字</summary>
@@ -70,13 +46,6 @@
- 支持设置多个预设情景,并通过!reset、!default等指令控制详细请查看[wiki指令](https://github.com/RockChinQ/QChatGPT/wiki/%E5%8A%9F%E8%83%BD%E4%BD%BF%E7%94%A8#%E6%9C%BA%E5%99%A8%E4%BA%BA%E6%8C%87%E4%BB%A4)
</details>
<details>
<summary>✅完善的会话管理,重启不丢失</summary>
- 使用SQLite进行会话内容持久化
- 最后一次对话一定时间后自动保存,请到`config.py`中修改`session_expire_time`的值以自定义时间
- 运行期间可使用`!reset` `!list` `!last` `!next` `!prompt`等指令管理会话
</details>
<details>
<summary>✅支持对话、绘图等模型,可玩性更高</summary>
@@ -224,7 +193,7 @@ python3 main.py
- [revLibs](https://github.com/RockChinQ/revLibs) - 将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)
- [hello_plugin](https://github.com/RockChinQ/hello_plugin) - `hello_plugin` 的储存库形式,插件开发模板
- [dominoar/QchatPlugins](https://github.com/dominoar/QchatPlugins) - dominoar编写的诸多新功能插件语言输出、Ranimg、屏蔽词规则等
- [dominoar/QChatPlugins](https://github.com/dominoar/QchatPlugins) - dominoar编写的诸多新功能插件语言输出、Ranimg、屏蔽词规则等
- [dominoar/QCP-NovelAi](https://github.com/dominoar/QCP-NovelAi) - NovelAI 故事叙述与绘画
## 😘致谢
@@ -233,6 +202,7 @@ python3 main.py
- [@mikumifa](https://github.com/mikumifa) 本项目Docker部署仓库开发者
- [@dominoar](https://github.com/dominoar) 为本项目开发多种插件
- [@hissincn](https://github.com/hissincn) 本项目贡献者
- [@LINSTCL](https://github.com/LINSTCL) GPT-3.5官方模型适配贡献者
以及其他所有为本项目提供支持的朋友们。

View File

@@ -112,10 +112,23 @@ encourage_sponsor_at_start = True
# 注意较大的prompt_submit_length会导致OpenAI账户额度消耗更快
prompt_submit_length = 1024
# OpenAI的completion API的参数
# OpenAI补全API的参数
# 请在下方填写模型,程序自动选择接口
# 现已支持的模型有:
#
# 'gpt-3.5-turbo'
# 'gpt-3.5-turbo-0301'
# 'text-davinci-003'
# 'text-davinci-002'
# 'code-davinci-002'
# 'code-cushman-001'
# 'text-curie-001'
# 'text-babbage-001'
# 'text-ada-001'
#
# 具体请查看OpenAI的文档: https://beta.openai.com/docs/api-reference/completions/create
completion_api_params = {
"model": "text-davinci-003",
"model": "gpt-3.5-turbo",
"temperature": 0.9, # 数值越低得到的回答越理性,取值范围[0, 1]
"max_tokens": 512, # 每次获取OpenAI接口响应的文字量上限, 不高于4096
"top_p": 1, # 生成的文本的文本与要求的符合度, 取值范围[0, 1]
@@ -138,14 +151,6 @@ include_image_description = True
# 消息处理的超时时间,单位为秒
process_message_timeout = 30
# 会话对象名称,此配置与会话对象管理相关,
# 若不了解相关功能,无需修改此配置
# 详细说明请查看https://github.com/RockChinQ/QChatGPT/wiki/%E6%8A%80%E6%9C%AF%E4%BF%A1%E6%81%AF#%E4%BC%9A%E8%AF%9Dsession
# user_name: 管理员(主人)的名字
# bot_name: 机器人的名字
user_name = 'You'
bot_name = 'Bot'
# [暂未实现] 群内会话是否启用多对象名称
# 若不启用群内会话的prompt只使用user_name和bot_name
multi_subject = False

View File

@@ -206,7 +206,7 @@ class DatabaseManager:
}
# 列出与某个对象的所有对话session
def list_history(self, session_name: str, capacity: int, page: int, replace: str = ""):
def list_history(self, session_name: str, capacity: int, page: int):
self.execute("""
select `name`, `type`, `number`, `create_timestamp`, `last_interact_timestamp`, `prompt`, `status`
from `sessions` where `name` = '{}' order by `last_interact_timestamp` desc limit {} offset {}
@@ -227,7 +227,7 @@ class DatabaseManager:
'subject_number': subject_number,
'create_timestamp': create_timestamp,
'last_interact_timestamp': last_interact_timestamp,
'prompt': prompt if replace == "" else prompt.replace(replace, "")
'prompt': prompt
})
return sessions

View File

@@ -5,7 +5,7 @@ import openai
import pkg.openai.keymgr
import pkg.utils.context
import pkg.audit.gatherer
from pkg.openai.modelmgr import ModelRequest, create_openai_model_request
# 为其他模块提供与OpenAI交互的接口
class OpenAIInteract:
@@ -32,24 +32,27 @@ class OpenAIInteract:
pkg.utils.context.set_openai_manager(self)
# 请求OpenAI Completion
def request_completion(self, prompt, stop):
def request_completion(self, prompts):
config = pkg.utils.context.get_config()
response = openai.Completion.create(
prompt=prompt,
stop=stop,
# 根据模型选择使用的接口
ai: ModelRequest = create_openai_model_request(config.completion_api_params['model'], 'user')
ai.request(
prompts,
**config.completion_api_params
)
response = ai.get_response()
logging.debug("OpenAI response: %s", response)
if 'model' in config.completion_api_params:
self.audit_mgr.report_text_model_usage(config.completion_api_params['model'],
response['usage']['total_tokens'])
ai.get_total_tokens())
elif 'engine' in config.completion_api_params:
self.audit_mgr.report_text_model_usage(config.completion_api_params['engine'],
response['usage']['total_tokens'])
return response
return ai.get_message()
def request_image(self, prompt):

View File

@@ -1,7 +1,19 @@
# 提供与模型交互的抽象接口
import openai, logging
COMPLETION_MODELS = {
'text-davinci-003'
'text-davinci-003',
'text-davinci-002',
'code-davinci-002',
'code-cushman-001',
'text-curie-001',
'text-babbage-001',
'text-ada-001',
}
CHAT_COMPLETION_MODELS = {
'gpt-3.5-turbo',
'gpt-3.5-turbo-0301',
}
EDIT_MODELS = {
@@ -13,22 +25,97 @@ IMAGE_MODELS = {
}
# ModelManager
# 由session包含
class ModelMgr(object):
class ModelRequest():
"""模型请求抽象类"""
can_chat = False
using_completion_model = ""
using_edit_model = ""
using_image_model = ""
def __init__(self, model_name, user_name, request_fun):
self.model_name = model_name
self.user_name = user_name
self.request_fun = request_fun
def __init__(self):
pass
def request(self, **kwargs):
ret = self.request_fun(**kwargs)
self.ret = self.ret_handle(ret)
self.message = self.ret["choices"][0]["message"]
def get_using_completion_model(self):
return self.using_completion_model
def __msg_handle__(self, msg):
"""将prompt dict转换成接口需要的格式"""
return msg
def ret_handle(self):
return
def get_total_tokens(self):
return self.ret['usage']['total_tokens']
def get_message(self):
return self.message
def get_response(self):
return self.ret
def get_using_edit_model(self):
return self.using_edit_model
class ChatCompletionModel(ModelRequest):
"""ChatCompletion接口实现"""
Chat_role = ['system', 'user', 'assistant']
def __init__(self, model_name, user_name):
request_fun = openai.ChatCompletion.create
self.can_chat = True
super().__init__(model_name, user_name, request_fun)
def get_using_image_model(self):
return self.using_image_model
def request(self, prompts, **kwargs):
self.ret = self.request_fun(messages = self.__msg_handle__(prompts), **kwargs, user=self.user_name)
self.ret_handle()
self.message = self.ret["choices"][0]["message"]['content']
def __msg_handle__(self, msgs):
temp_msgs = []
# 把msgs拷贝进temp_msgs
for msg in msgs:
temp_msgs.append(msg.copy())
return temp_msgs
def get_content(self):
return self.message
class CompletionModel(ModelRequest):
"""Completion接口实现"""
def __init__(self, model_name, user_name):
request_fun = openai.Completion.create
super().__init__(model_name, user_name, request_fun)
def request(self, prompts, **kwargs):
self.ret = self.request_fun(prompt = self.__msg_handle__(prompts), **kwargs)
self.ret_handle()
self.message = self.ret["choices"][0]["text"]
def __msg_handle__(self, msgs):
prompt = ''
for msg in msgs:
prompt = prompt + "{}: {}\n".format(msg['role'], msg['content'])
# for msg in msgs:
# if msg['role'] == 'assistant':
# prompt = prompt + "{}\n".format(msg['content'])
# else:
# prompt = prompt + "{}:{}\n".format(msg['role'] , msg['content'])
prompt = prompt + "assistant: "
return prompt
def get_text(self):
return self.message
def create_openai_model_request(model_name: str, user_name: str = 'user') -> ModelRequest:
"""使用给定的模型名称创建模型请求对象"""
if model_name in CHAT_COMPLETION_MODELS:
model = ChatCompletionModel(model_name, user_name)
elif model_name in COMPLETION_MODELS:
model = CompletionModel(model_name, user_name)
else :
log = "找不到模型[{}],请检查配置文件".format(model_name)
logging.error(log)
raise IndexError(log)
logging.debug("使用接口[{}]创建模型请求[{}]".format(model.__class__.__name__, model_name))
return model

View File

@@ -1,8 +1,10 @@
import logging
import threading
import time
import json
import pkg.openai.manager
import pkg.openai.modelmgr
import pkg.database.manager
import pkg.utils.context
@@ -17,6 +19,32 @@ class SessionOfflineStatus:
ON_GOING = 'on_going'
EXPLICITLY_CLOSED = 'explicitly_closed'
# 重置session.prompt
def reset_session_prompt(session_name, prompt):
# 备份原始数据
bak_path = 'logs/{}-{}.bak'.format(
session_name,
time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
)
f = open(bak_path, 'w+')
f.write(prompt)
f.close()
# 生成新数据
config = pkg.utils.context.get_config()
prompt = [
{
'role': 'system',
'content': config.default_prompt['default']
}
]
# 警告
logging.warning(
"""
用户[{}]的数据已被重置,有可能是因为数据版本过旧或存储错误
原始数据将备份在:
{}""".format(session_name, bak_path)
)
return prompt
# 从数据加载session
def load_sessions():
@@ -33,7 +61,11 @@ def load_sessions():
temp_session.name = session_name
temp_session.create_timestamp = session_data[session_name]['create_timestamp']
temp_session.last_interact_timestamp = session_data[session_name]['last_interact_timestamp']
temp_session.prompt = session_data[session_name]['prompt']
try:
temp_session.prompt = json.loads(session_data[session_name]['prompt'])
except Exception:
temp_session.prompt = reset_session_prompt(session_name, session_data[session_name]['prompt'])
temp_session.persistence()
sessions[session_name] = temp_session
@@ -60,12 +92,7 @@ def dump_session(session_name: str):
class Session:
name = ''
prompt = ""
import config
user_name = config.user_name if hasattr(config, 'user_name') and config.user_name != '' else 'You'
bot_name = config.bot_name if hasattr(config, 'bot_name') and config.bot_name != '' else 'Bot'
prompt = []
create_timestamp = 0
@@ -99,11 +126,15 @@ class Session:
else:
current_default_prompt = dprompt.get_prompt(use_default)
user_name = config.user_name if hasattr(config, 'user_name') and config.user_name != '' else 'You'
bot_name = config.bot_name if hasattr(config, 'bot_name') and config.bot_name != '' else 'Bot'
return (user_name + ":{}\n".format(current_default_prompt) + bot_name + ":好的\n") \
if current_default_prompt != '' else ''
return [
{
'role': 'user',
'content': current_default_prompt
},{
'role': 'assistant',
'content': 'ok'
}
]
def __init__(self, name: str):
self.name = name
@@ -165,22 +196,16 @@ class Session:
if event.is_prevented_default():
return None
# max_rounds = config.prompt_submit_round_amount if hasattr(config, 'prompt_submit_round_amount') else 7
config = pkg.utils.context.get_config()
max_rounds = 1000 # 不再限制回合数
max_length = config.prompt_submit_length if hasattr(config, "prompt_submit_length") else 1024
# 向API请求补全
response = pkg.utils.context.get_openai_manager().request_completion(
self.cut_out(self.prompt + self.user_name + ':' +
text + '\n' + self.bot_name + ':',
max_rounds, max_length),
self.user_name + ':')
message = pkg.utils.context.get_openai_manager().request_completion(
self.cut_out(text, max_length),
)
self.prompt += self.user_name + ':' + text + '\n' + self.bot_name + ':'
# print(response)
# 处理回复
res_test = response["choices"][0]["text"]
# 成功获取,处理回复
res_test = message
res_ans = res_test
# 去除开头可能的提示
@@ -189,50 +214,56 @@ class Session:
del (res_ans_spt[0])
res_ans = '\n\n'.join(res_ans_spt)
self.prompt += "{}".format(res_ans) + '\n'
# 将此次对话的双方内容加入到prompt中
self.prompt.append({'role':'user', 'content':text})
self.prompt.append({'role':'assistant', 'content':res_ans})
if self.just_switched_to_exist_session:
self.just_switched_to_exist_session = False
self.set_ongoing()
return res_ans
return res_ans if res_ans[0]!='\n' else res_ans[1:]
# 删除上一回合并返回上一回合的问题
def undo(self) -> str:
self.last_interact_timestamp = int(time.time())
# 删除上一回合
to_delete = self.cut_out(self.prompt, 1, 1024)
self.prompt = self.prompt.replace(to_delete, '')
if self.prompt[-1]['role'] != 'user':
res = self.prompt[-1]['content']
self.prompt.remove(self.prompt[-2])
else:
res = self.prompt[-2]['content']
self.prompt.remove(self.prompt[-1])
# 返回上一回合的问题
return to_delete.split(self.bot_name + ':')[0].split(self.user_name + ':')[1].strip()
return res
# 从尾部截取prompt里不多于max_rounds个回合长度不大于max_tokens的字符串
# 保证都是完整的对话
def cut_out(self, prompt: str, max_rounds: int, max_tokens: int) -> str:
# 分隔出每个回合
rounds_spt_by_user_name = prompt.split(self.user_name + ':')
# 构建对话体
def cut_out(self, msg: str, max_tokens: int) -> list:
"""将现有prompt进行切割处理使得新的prompt长度不超过max_tokens"""
# 如果用户消息长度超过max_tokens直接返回
temp_prompt = [
{
'role': 'user',
'content': msg
}
]
result = ''
checked_rounds = 0
# 从后往前遍历加到result前面检查result是否符合要求
for i in range(len(rounds_spt_by_user_name) - 1, 0, -1):
result_temp = self.user_name + ':' + rounds_spt_by_user_name[i] + result
checked_rounds += 1
if checked_rounds > max_rounds:
token_count = len(msg)
# 倒序遍历prompt
for i in range(len(self.prompt) - 1, -1, -1):
if token_count >= max_tokens:
break
if int((len(result_temp.encode('utf-8')) - len(result_temp)) / 2 + len(result_temp)) > max_tokens:
break
# 将prompt加到temp_prompt头部
temp_prompt.insert(0, self.prompt[i])
token_count += len(self.prompt[i]['content'])
result = result_temp
logging.debug('cut_out: {}'.format(str(temp_prompt)))
logging.debug('cut_out: {}'.format(result))
return result
return temp_prompt
# 持久化session
def persistence(self):
@@ -247,11 +278,11 @@ class Session:
subject_number = int(name_spt[1])
db_inst.persistence_session(subject_type, subject_number, self.create_timestamp, self.last_interact_timestamp,
self.prompt)
json.dumps(self.prompt))
# 重置session
def reset(self, explicit: bool = False, expired: bool = False, schedule_new: bool = True, use_prompt: str = None):
if not self.prompt.endswith(':好的\n'):
if self.prompt[-1]['role'] != "system":
self.persistence()
if explicit:
# 触发插件事件
@@ -291,7 +322,11 @@ class Session:
self.create_timestamp = last_one['create_timestamp']
self.last_interact_timestamp = last_one['last_interact_timestamp']
self.prompt = last_one['prompt']
try:
self.prompt = json.loads(last_one['prompt'])
except json.decoder.JSONDecodeError:
self.prompt = reset_session_prompt(self.name, last_one['prompt'])
self.persistence()
self.just_switched_to_exist_session = True
return self
@@ -306,14 +341,17 @@ class Session:
self.create_timestamp = next_one['create_timestamp']
self.last_interact_timestamp = next_one['last_interact_timestamp']
self.prompt = next_one['prompt']
try:
self.prompt = json.loads(next_one['prompt'])
except json.decoder.JSONDecodeError:
self.prompt = reset_session_prompt(self.name, next_one['prompt'])
self.persistence()
self.just_switched_to_exist_session = True
return self
def list_history(self, capacity: int = 10, page: int = 0):
return pkg.utils.context.get_database_manager().list_history(self.name, capacity, page,
self.get_default_prompt())
return pkg.utils.context.get_database_manager().list_history(self.name, capacity, page)
def draw_image(self, prompt: str):
return pkg.utils.context.get_openai_manager().request_image(prompt)

View File

@@ -185,11 +185,7 @@ def process_command(session_name: str, text_message: str, mgr, config,
else:
datetime_str = datetime.datetime.fromtimestamp(result.create_timestamp).strftime(
'%Y-%m-%d %H:%M:%S')
reply = ["[bot]已切换到前一次的对话:\n创建时间:{}\n".format(
datetime_str) + result.prompt[
:min(100,
len(result.prompt))] + \
("..." if len(result.prompt) > 100 else "#END#")]
reply = ["[bot]已切换到前一次的对话:\n创建时间:{}\n".format(datetime_str)]
elif cmd == 'next':
result = pkg.openai.session.get_session(session_name).next_session()
if result is None:
@@ -197,13 +193,18 @@ def process_command(session_name: str, text_message: str, mgr, config,
else:
datetime_str = datetime.datetime.fromtimestamp(result.create_timestamp).strftime(
'%Y-%m-%d %H:%M:%S')
reply = ["[bot]已切换到后一次的对话:\n创建时间:{}\n".format(
datetime_str) + result.prompt[
:min(100,
len(result.prompt))] + \
("..." if len(result.prompt) > 100 else "#END#")]
reply = ["[bot]已切换到后一次的对话:\n创建时间:{}\n".format(datetime_str)]
elif cmd == 'prompt':
reply = ["[bot]当前对话所有内容:\n" + pkg.openai.session.get_session(session_name).prompt]
msgs = ""
session:list = pkg.openai.session.get_session(session_name).prompt
for msg in session:
if len(params) != 0 and params[0] in ['-all', '-a']:
msgs = msgs + "{}: {}\n\n".format(msg['role'], msg['content'])
elif len(msg['content']) > 30:
msgs = msgs + "[{}]: {}...\n\n".format(msg['role'], msg['content'][:30])
else:
msgs = msgs + "[{}]: {}\n\n".format(msg['role'], msg['content'])
reply = ["[bot]当前对话所有内容:\n{}".format(msgs)]
elif cmd == 'list':
pkg.openai.session.get_session(session_name).persistence()
page = 0
@@ -223,10 +224,21 @@ def process_command(session_name: str, text_message: str, mgr, config,
for i in range(len(results)):
# 时间(使用create_timestamp转换) 序号 部分内容
datetime_obj = datetime.datetime.fromtimestamp(results[i]['create_timestamp'])
reply_str += "#{} 创建:{} {}\n".format(i + page * 10,
datetime_obj.strftime("%Y-%m-%d %H:%M:%S"),
results[i]['prompt'][
:min(20, len(results[i]['prompt']))])
msg = ""
try:
msg = json.loads(results[i]['prompt'])
except json.decoder.JSONDecodeError:
msg = pkg.openai.session.reset_session_prompt(session_name, results[i]['prompt'])
# 持久化
pkg.openai.session.get_session(session_name).persistence()
if len(msg) >= 2:
reply_str += "#{} 创建:{} {}\n".format(i + page * 10,
datetime_obj.strftime("%Y-%m-%d %H:%M:%S"),
msg[1]['content'])
else:
reply_str += "#{} 创建:{} {}\n".format(i + page * 10,
datetime_obj.strftime("%Y-%m-%d %H:%M:%S"),
"无内容")
if results[i]['create_timestamp'] == pkg.openai.session.get_session(
session_name).create_timestamp:
current = i + page * 10

View File

@@ -1,5 +1,5 @@
requests~=2.28.1
openai~=0.26.5
openai~=0.27.0
pip~=22.3.1
dulwich~=0.21.3
colorlog~=6.6.0

View File

@@ -0,0 +1,46 @@
import openai
import time
# 测试completion api
models = [
'gpt-3.5-turbo',
'gpt-3.5-turbo-0301',
'text-davinci-003',
'text-davinci-002',
'code-davinci-002',
'code-cushman-001',
'text-curie-001',
'text-babbage-001',
'text-ada-001',
]
openai.api_key = "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"
for model in models:
print('Testing model: ', model)
# completion api
try:
response = openai.Completion.create(
model=model,
prompt="Say this is a test",
max_tokens=7,
temperature=0
)
print(' completion api: ', response['choices'][0]['text'].strip())
except Exception as e:
print(' completion api err: ', e)
# chat completion api
try:
completion = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "user", "content": "Hello!"}
]
)
print(" chat api: ",completion.choices[0].message['content'].strip())
except Exception as e:
print(' chat api err: ', e)
time.sleep(60)