Package: openai2
项目描述ChatGPT 工具包，支持连续对话、流式对话（逐字显示）、对话存档与载入、对话回滚、对话伪造、轮询 api_key 池、群聊多角色模拟、在命令行对话、限制历史消息数量、异步请求。作者江南雨上主页|Github|PyPi|微信|邮箱|捐赠Bug提交、功能提议您可以通过Github-Issues、微信与我联系。安装pip install openai2获取api_key获取链接1获取链接2教程 (查看美化版👈)导入fromopenai2importChat创建对话api_key='api_key'# 更换成自己的api_keyTony=Chat(api_key=api_key,model="gpt-3.5-turbo")Lucy=Chat(api_key=api_key,model="gpt-3.5-turbo")# 每个实例可使用 相同 或者 不同 的api_key对话Tony.request('自然数50的后面是几?')# >>> 51Lucy.request('自然数100的后面是几?')# >>> 101Tony.request('再往后是几?')# >>> 52Lucy.request('再往后是几?')# >>> 102Tony.request('再往后呢?')# >>> 53Lucy.request('再往后呢?')# >>> 103流式对话 (查看演示👈)foranswerinLucy.stream_request('世界上最大的海洋是哪个?'):print(answer)世界上最大的海洋是太平洋。异步对话importasynciofromopenai2importChatTony=Chat(api_key=api_key,model="gpt-3.5-turbo")asyncdefmain():answer=awaitTony.async_request('世界上最大的海洋是哪个')print(answer)asyncio.run(main())# >>> '世界上最大的海洋是太平洋。'异步流式对话asyncforanswerinTony.async_stream_request('世界上最大的海洋是哪个?'):print(answer)世界上最大的海洋是太平洋。对话回滚Anna=Chat(api_key=api_key,model="gpt-3.5-turbo")Anna.request('自然数1的后面是几?')# >>> 2Anna.request('再往后是几?')# >>> 3Anna.request('再往后呢?')# >>> 4Anna.request('再往后呢?')# >>> 5Anna.request('再往后呢?')# >>> 6Anna.request('再往后呢?')# >>> 7Anna.request('再往后呢?')# >>> 8# 回滚1轮对话Anna.rollback()# >>> [user]:再往后呢? [assistant]:7# 再回滚3轮对话Anna.rollback(n=3)# >>> [user]:再往后呢? [assistant]:4Anna.request('再往后呢?')# >>> 5注：1、执行Anna.rollback(n=x)可回滚 x 轮对话。2、Anna.rollback()相当于Anna.rollback(n=1)。轮询 api_key 池fromopenai2importChat,AKPoolAK1='sk-ug8w...'AK2=AKPool(['sk-mf40...','sk-m6g7...',...])AK3=AKPool(['sk-affe...','sk-fam4...',...])Duke=Chat(api_key=AK1,model="gpt-3.5-turbo")# 令 Duke 使用固定的 api_keyCarl=Chat(api_key=AK2,model="gpt-3.5-turbo")# 令 Carl 和 Denny 使用同一个'api_key池', 系统将自动充分利用每个api_keyDenny=Chat(api_key=AK2,model="gpt-3.5-turbo")Chris=Chat(api_key=AK3,model="gpt-3.5-turbo")# 令 Chris 使用独立的'api_key池'注：允许（而非不允许）同一个 api_key 投放到不同的 api_key 池中，但每个 api_key 池都是独立调度，不会互相通信。重置 api_keyAK5='sk-jg93...'AK6=AKPool(['sk-vb7l...','sk-d3lv...'])...Carl.reset_api_key(AK5)# 重置 api_keyCarl.reset_api_key(AK6)# 再次重置 api_key...对话导出与导入对话导出Ariel=Chat(api_key=api_key,model="gpt-3.5-turbo")Ariel.request('自然数1的后面是几?')# >>> 2Ariel.request('再往后是几?')# >>> 3Ariel.fetch_messages()# 返回:# [#     {'role': 'user', 'content': '自然数1的后面是几?'},#     {'role': 'assistant', 'content': '2'},#     {'role': 'user', 'content': '再往后是几?'},#     {'role': 'assistant', 'content': '3'}# ]对话存档你可以把导出的对话持久化保存：importjsonfrompathlibimportPathrecord=Ariel.fetch_messages()record=json.dumps(record,ensure_ascii=False)Path('record.json').write_text(record,encoding="utf8")对话导入导出的对话可以再导入到其它对话中：record=Ariel.fetch_messages()Jenny=Chat(api_key=api_key,model="gpt-3.5-turbo")Jenny.add_dialogs(*record)Jenny.request('再往后呢?')# >>> 4导出的对话也可以再导入到原对话中，但这样做会在原对话中产生重复的历史消息。对话伪造利用对话导入功能，可以伪造对话：fromopenai2importChat,user_msg,assistant_msgMickey=Chat(api_key=api_key,model="gpt-3.5-turbo")Mickey.add_dialogs(user_msg('请问1+1=几?'),# 等价于 {"role": "user", "content": '请问1+1=几?'}assistant_msg('1+1=10'),# 等价于 {"role": "assistant", "content": '1+1=10'}{"role":"user","content":'那10+10=几?'},{"role":"assistant","content":'10+10=你大爷, 你提的这些问题真弱智!'},)answer=Mickey.request('哦吼, 你还敢骂我呀?')print(answer)# >>> 非常抱歉，我刚才的回答有些不适当。1+1=2, 10+10=20。非常抱歉给你带来困扰！注：对话导出与导入可以穿插在对话中的任何时刻。群聊多角色模拟importjsonfromopenai2importGroupChatapi_key='...'# 更换成自己的 api_keygroup=GroupChat(api_key=api_key,model="gpt-3.5-turbo")# 设置角色group.roles['苏轼']='宋朝诗人，他的词风格独特，既有儒家的教诲，又有生活的乐趣。'group.roles['李清照']='宋代著名的女词人，其词句优美，情感真挚。'group.roles['杜甫']='唐朝著名诗人。'# 添加角色历史对话group.add_dialog(speaker='苏轼',audiences=['李清照'],remark='你好呀')group.add_dialog(speaker='李清照',audiences=['苏轼'],remark='好久不见, 你最近在忙什么?')group.add_dialog(speaker='杜甫',audiences=['苏轼'],remark='上次托你帮我写的那首《茅屋为秋风所破歌》写好了吗?')# 让 ChatGPT 模拟角色发言answer=group.request([('苏轼',['李清照']),# 第 1 个元素表示说话人, 第 2 个元素表示对谁说话. 由于一个人可以同时对多个人说话, 因此第 2 个元素为列表('苏轼',['杜甫']),])try:print(json.loads(answer))except:print(answer)# 返回:[{"speaker":"苏轼","audiences":"李清照","remark":"最近我在写一首新的诗，题目是《听雨》"},{"speaker":"苏轼","audiences":"杜甫","remark":"那首《茅屋为秋风所破歌》已经写好啦，我在信里寄给你了，请查收"}]限制历史消息数量限制历史消息数量随着对话次数越来越多，最终上下文长度就会超出 openai 接口限定的最大 token 数量，此时可使用 MsgMaxCount 参数来限制历史消息数量。当消息数量超出 MsgMaxCount 后，程序会自动移除最早的记录，使消息数量减少到恰好等于 MsgMaxCount 。MsgMaxCount=6# 最多保留6条历史消息Ariel=Chat(api_key=api_key,model="gpt-3.5-turbo",MsgMaxCount=MsgMaxCount)Ariel.request('英国的首都是什么？')# >>> '伦敦'Ariel.request('日本首都是什么？')# >>> '东京'Ariel.request('意大利的首都是什么？')# >>> '罗马'Ariel.request('美国的首都是什么？')# >>> '华盛顿'Ariel.request('世界上国土面积最大的国家是哪个？')# >>> '俄罗斯'Ariel.request('法国的首都叫什么？')# >>> '巴黎'Ariel.request('青蛙的幼体叫什么？')# >>> '蝌蚪'Ariel.request('世界上最大的海洋是什么？')# >>> '太平洋'Ariel.fetch_messages()# 返回:# [#     {'role': 'user', 'content': '法国的首都叫什么？'},#     {'role': 'assistant', 'content': '巴黎'},#     {'role': 'user', 'content': '青蛙的幼体叫什么？'},#     {'role': 'assistant', 'content': '蝌蚪'},#     {'role': 'user', 'content': '世界上最大的海洋是什么？'},#     {'role': 'assistant', 'content': '太平洋'}# ]锁定消息当程序自动移除消息记录时，也许我们希望某些消息不要被移除，此时可将这些消息锁定。MsgMaxCount=6Ariel=Chat(api_key=api_key,model="gpt-3.5-turbo",MsgMaxCount=MsgMaxCount)Ariel.request('英国的首都是什么？')# >>> '伦敦'Ariel.request('日本首都是什么？')# >>> '东京'Ariel.request('意大利的首都是什么？')# >>> '罗马'此时共有 6 条消息记录：消息正序索引逆序索引英国的首都是什么？0-6伦敦1-5日本首都是什么？2-4东京3-3意大利的首都是什么？4-2罗马5-1锁定索引为 0、-2、-1 的消息：Ariel.pin_messages(0,-2,-1)# 索引无须按顺序填写: pin_messages(0, 1, 2) 与 pin_messages(0, 2, 1) 等价.继续请求：Ariel.request('美国的首都是什么？')# >>> '华盛顿'由于设置了 MsgMaxCount = 6，此时共有 6 条消息记录：消息正序索引逆序索引锁定状态英国的首都是什么？0-6已锁定东京1-5-意大利的首都是什么？2-4已锁定罗马3-3已锁定美国的首都是什么？4-2-华盛顿5-1-继续执行：Ariel.pin_messages(-2)# 锁定'美国的首都是什么？'Ariel.request('世界上国土面积最大的国家是哪个？')# >>> '俄罗斯'Ariel.request('法国的首都叫什么？')# >>> '巴黎'Ariel.request('青蛙的幼体叫什么？')# >>> '蝌蚪'Ariel.request('世界上最大的海洋是什么？')# >>> '太平洋'Ariel.fetch_messages()# 返回:# [#     {'role': 'user', 'content': '英国的首都是什么？'},       # 被锁定的消息#     {'role': 'user', 'content': '意大利的首都是什么？'},     # 被锁定的消息#     {'role': 'assistant', 'content': '罗马'},               # 被锁定的消息#     {'role': 'user', 'content': '美国的首都是什么？'},       # 被锁定的消息#     {'role': 'user', 'content': '世界上最大的海洋是什么？'},#     {'role': 'assistant', 'content': '太平洋'}# ]注：pin_messages 方法也允许传入“已锁定的消息”的索引，这使得当不确定某些消息的状态时，可以放心地将它们的索引传进去。解锁消息可使用 unpin_messages 方法将已锁定的消息解除锁定。Ariel.unpin_messages(0,-2,-1)# 解锁索引为 0、-2、-1 的消息注：unpin_messages 方法也允许传入“未锁定的消息”的索引，这使得当不确定某些消息的状态时，可以放心地将它们的索引传进去。更多方法1、openai2.Chat底层调用了openai.OpenAI，支持openai.OpenAI的所有参数。2、openai2.Chat.request与openai2.Chat.stream_request底层调用了openai.OpenAI.chat.completions.create，支持openai.OpenAI.chat.completions.create的所有参数。3、openai2.Chat.async_request与openai2.Chat.async_stream_request底层调用了openai.AsyncOpenAI.chat.completions.create，支持openai.AsyncOpenAI.chat.completions.create的所有参数。查看相关参数👈在命令行对话 (查看演示👈)openai2add_apikeysk-T92mZYXHLWKt1234gtPKT3BlbkFJopenai2chat指令集指令功能说明openai2  add_apikey  你的apikey添加 1 个 apikey如需添加多个，可执行多次openai2  read_apikey查看所有 apikeyopenai2  clear_apikey清除所有 apikeyopenai2  chat继续上次的对话openai2  newchat清空对话记录, 然后开始新对话