openai2


Nameopenai2 JSON
Version 1.7.12 PyPI version JSON
download
home_pageNone
SummaryChatGPT 工具包,支持多模态对话(gpt-4o)、连续对话、流式对话(逐字显示)、生成图像(DALL·E)、对话存档与载入、对话回滚、对话伪造、轮询 api_key 池、群聊多角色模拟、在命令行对话、限制历史消息数量、异步请求。
upload_time2024-09-14 02:06:44
maintainerNone
docs_urlNone
authorNone
requires_pythonNone
licenseNone
keywords openai chatgpt openai2
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # 项目描述

ChatGPT 工具包,支持多模态对话(gpt-4o)、连续对话、流式对话(逐字显示)、生成图像(DALL·E)、对话存档与载入、对话回滚、对话伪造、轮询 api_key 池、群聊多角色模拟、在命令行对话、限制历史消息数量、异步请求。

# 作者

江南雨上

[主页](https://lcctoor.com/index.html) \| [Github](https://github.com/lcctoor) \| [PyPi](https://pypi.org/user/lcctoor) \| [微信](https://lcctoor.com/cdn/WeChatQRC.jpg) \| [邮箱](mailto:lcctoor@outlook.com) \| [捐赠](https://lcctoor.com/cdn/DonationQRC-0rmb.jpg)

# Bug提交、功能提议

你可以通过 [Github-Issues](https://github.com/lcctoor/arts/issues)、[微信](https://lcctoor.com/cdn/WeChatQRC.jpg) 与我联系。

# 安装

```
pip install openai2
```

# 获取api_key

[获取链接1](https://platform.openai.com/account/api-keys)

[获取链接2](https://www.baidu.com/s?wd=%E8%8E%B7%E5%8F%96%20openai%20api_key)

# 教程 ([查看美化版](https://github.com/lcctoor/arts/blob/main/arts/openai2/README.md#项目描述) 👈)

## 导入

```python
from openai2 import Chat
```

## 创建对话

```python
api_key = 'api_key'  # 更换成自己的api_key

Tony = Chat(api_key=api_key, model="gpt-3.5-turbo")
Lucy = Chat(api_key=api_key, model="gpt-3.5-turbo")  # 每个实例可使用 相同 或者 不同 的api_key
```

## 对话

```python
Tony.request('自然数50的后面是几?')  # >>> '51'
Lucy.request('自然数100的后面是几?')  # >>> '101'

Tony.request('再往后是几?')  # >>> '52'
Lucy.request('再往后是几?')  # >>> '102'

Tony.request('再往后呢?')  # >>> '53'
Lucy.request('再往后呢?')  # >>> '103'
```

## 流式对话 ([查看演示](https://lcctoor.com/openai2/oa_/流式对话演示.mp4) 👈)

```python
for answer in Lucy.stream_request('世界上最大的海洋是哪个?'):
    print(answer)
世
界
上
最
大
的
海
洋
是
太
平
洋
。
```

## 异步对话

```python
import asyncio
from openai2 import Chat

Tony = Chat(api_key=api_key, model="gpt-3.5-turbo")

async def main():
    answer = await Tony.async_request('世界上最大的海洋是哪个')
    print(answer)

asyncio.run(main())  # >>> '世界上最大的海洋是太平洋。'
```

## 异步流式对话

```python
async for answer in Tony.async_stream_request('世界上最大的海洋是哪个?'):
    print(answer)
世
界
上
最
大
的
海
洋
是
太
平
洋
。
```

## 多模态对话(gpt-4o)

```python
from pathlib import Path
from openai2 import Chat, Multimodal_Part


Bruce = Chat(api_key='sk-jg93...', model="gpt-4o")


pic = Path(rf'C:\鼠标.jpeg').read_bytes()

answer = Bruce.request(

    '下面这张图片里画了什么?',
  
    Multimodal_Part.jpeg(pic)
)

print(answer)  # >>> '这张图片里画了一个鼠标。'
```

注:

1、Multimodal_Part 除了 jpeg 方法以外,还有 png、text …… 等方法。

2、对于 str 型对象,以下这两种写法是等价的:`Bruce.request(..., '这张图片里画了什么', ...)`、`Bruce.request(..., Multimodal_Part.text('这张图片里画了什么'), ...)`。

3、多模态对话支持同步对话、异步对话、同步流式对话、异步流式对话…… 相对于普通对话,唯一的区别就是支持多模态。

4、目前已知支持多模态对话的模型有:gpt-4o、gpt-4o-mini、gpt-4o-2024-05-13、gpt-4o-mini-2024-07-18。

## 对话回滚

```python
Anna = Chat(api_key=api_key, model="gpt-3.5-turbo")

Anna.request('自然数1的后面是几?')  # >>> 2
Anna.request('再往后是几?')  # >>> 3
Anna.request('再往后呢?')  # >>> 4
Anna.request('再往后呢?')  # >>> 5
Anna.request('再往后呢?')  # >>> 6
Anna.request('再往后呢?')  # >>> 7
Anna.request('再往后呢?')  # >>> 8

# 回滚1轮对话
Anna.rollback()  # >>> [user]:再往后呢? [assistant]:7

# 再回滚3轮对话
Anna.rollback(n=3)  # >>> [user]:再往后呢? [assistant]:4

Anna.request('再往后呢?')  # >>> 5
```

注:

1、执行 `Anna.rollback(n=x)` 可回滚 x 轮对话。

2、`Anna.rollback()` 相当于 `Anna.rollback(n=1)` 。

## 轮询 api_key 池

```python
from openai2 import Chat, AKPool

AK1 = '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_key

Carl = Chat(api_key=AK2, model="gpt-3.5-turbo")  # 令 Carl 和 Denny 使用同一个'api_key池', 系统将自动充分利用每个api_key
Denny = 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_key

```python
AK5 = 'sk-jg93...'
AK6 = AKPool(['sk-vb7l...', 'sk-d3lv...'])
...

Carl.reset_api_key(AK5)  # 重置 api_key
Carl.reset_api_key(AK6)  # 再次重置 api_key
...
```

## 对话导出与导入

### 对话导出

```python
Ariel = Chat(api_key=api_key, model="gpt-3.5-turbo")

Ariel.request('自然数1的后面是几?')  # >>> 2
Ariel.request('再往后是几?')  # >>> 3

Ariel.fetch_messages()
# 返回:
# [
#     {'role': 'user', 'content': '自然数1的后面是几?'},
#     {'role': 'assistant', 'content': '2'},
#     {'role': 'user', 'content': '再往后是几?'},
#     {'role': 'assistant', 'content': '3'}
# ]
```

### 对话存档

你可以把导出的对话持久化保存:

```python
import json
from pathlib import Path

record = Ariel.fetch_messages()
record = json.dumps(record, ensure_ascii=False)
Path('record.json').write_text(record, encoding="utf8")
```

### 对话导入

导出的对话可以再导入到其它对话中:

```python
record = Ariel.fetch_messages()

Jenny = Chat(api_key=api_key, model="gpt-3.5-turbo")
Jenny.add_dialogs(*record)

Jenny.request('再往后呢?')  # >>> 4
```

导出的对话也可以再导入到原对话中,但这样做会在原对话中产生重复的历史消息。

### 对话伪造

利用对话导入功能,可以伪造对话:

```python
from openai2 import Chat, user_msg, assistant_msg

Mickey = 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。非常抱歉给你带来困扰!
```

注:对话导出与导入可以穿插在对话中的任何时刻。

## 生成图像(DALL·E)

返回图片的二进制:

```python
from pathlib import Path
from openai2 import Chat

Tony = Chat(api_key='sk-jg93...', model="dall-e-2")

images = Tony.dalle('请画一只猫', image_count=2)

for i, x in enumerate(images):
    Path(f"第{i}张.png").write_bytes(x)
```

返回图片的URL:

```python
from pathlib import Path
from openai2 import Chat

Tony = Chat(api_key='sk-jg93...', model="dall-e-2")

images = Tony.dalle('请画一只猫', image_count=2, return_format='url')

for i, url in enumerate(images):
    print(f"第{i}张的URL是:", url)
```

## 异步生成图像(DALL·E)

返回图片的二进制:

```python
import asyncio
from pathlib import Path
from openai2 import Chat

async def main():
    Tony = Chat(api_key='sk-jg93...', model="dall-e-2")

    images = await Tony.async_dalle('请画一只猫', image_count=2)
    
    for i, x in enumerate(images):
        Path(f"第{i}张.png").write_bytes(x)

asyncio.run(main())
```

返回图片的URL:

```python
import asyncio
from pathlib import Path
from openai2 import Chat

async def main():
    Tony = Chat(api_key='sk-jg93...', model="dall-e-2")

    images = await Tony.async_dalle('请画一只猫', image_count=2, return_format='url')
    
    for i, url in enumerate(images):
        print(f"第{i}张的URL是:", url)

asyncio.run(main())
```

## 群聊多角色模拟

```python
import json
from openai2 import GroupChat

api_key = '...'  # 更换成自己的 api_key
group = 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 数量,此时可使用 msg_max_count 参数来限制历史消息数量。当消息数量超出 msg_max_count 后,程序会自动移除最早的记录,使消息数量减少到恰好等于 msg_max_count 。

```python
msg_max_count = 6  # 最多保留6条历史消息

Ariel = Chat(api_key=api_key, model="gpt-3.5-turbo", msg_max_count=msg_max_count)

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': '太平洋'}
# ]
```

### 锁定消息

当程序自动移除消息记录时,也许我们希望某些消息不要被移除,此时可将这些消息锁定。

```python
msg_max_count = 6

Ariel = Chat(api_key=api_key, model="gpt-3.5-turbo", msg_max_count=msg_max_count)

Ariel.request('英国的首都是什么?')  # >>> '伦敦'
Ariel.request('日本首都是什么?')  # >>> '东京'
Ariel.request('意大利的首都是什么?')  # >>> '罗马'
```

此时共有 6 条消息记录:

| 消息                 | 正序索引 | 逆序索引 |
| -------------------- | :------: | :------: |
| 英国的首都是什么?   |    0    |    -6    |
| 伦敦                 |    1    |    -5    |
| 日本首都是什么?     |    2    |    -4    |
| 东京                 |    3    |    -3    |
| 意大利的首都是什么? |    4    |    -2    |
| 罗马                 |    5    |    -1    |

锁定索引为 0、-2、-1 的消息:

```python
Ariel.pin_messages(0, -2, -1)  # 索引无须按顺序填写: pin_messages(0, 1, 2) 与 pin_messages(0, 2, 1) 等价.
```

继续请求:

```python
Ariel.request('美国的首都是什么?')  # >>> '华盛顿'
```

由于设置了 msg_max_count = 6,此时共有 6 条消息记录:

| 消息                 | 正序索引 | 逆序索引 | 锁定状态 |
| -------------------- | :------: | :------: | :------: |
| 英国的首都是什么?   |    0    |    -6    |  已锁定  |
| 东京                 |    1    |    -5    |    -    |
| 意大利的首都是什么? |    2    |    -4    |  已锁定  |
| 罗马                 |    3    |    -3    |  已锁定  |
| 美国的首都是什么?   |    4    |    -2    |    -    |
| 华盛顿               |    5    |    -1    |    -    |

继续执行:

```python
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 方法将已锁定的消息解除锁定。

```python
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` 的所有参数。

[查看相关参数](https://platform.openai.com/docs/api-reference/chat) 👈

## 在命令行对话 ([查看演示](https://lcctoor.com/openai2/oa_/命令行对话演示.mp4) 👈)

```cpp
openai2 add_apikey sk-T92mZYXHLWKt1234gtPKT3BlbkFJ
openai2 chat
```

指令集

| 指令                               | 功能                         | 说明                     |
| ---------------------------------- | ---------------------------- | ------------------------ |
| openai2  add_apikey  你的apikey | 添加 1 个 apikey             | 如需添加多个,可执行多次 |
| openai2  read_apikey              | 查看所有 apikey              |                          |
| openai2  clear_apikey             | 清除所有 apikey              |                          |
| openai2  chat                     | 继续上次的对话               |                          |
| openai2  newchat                  | 清空对话记录, 然后开始新对话 |                          |

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "openai2",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": "openai, chatgpt, openai2",
    "author": null,
    "author_email": "\u6c5f\u5357\u96e8\u4e0a <lcctoor@outlook.com>",
    "download_url": "https://files.pythonhosted.org/packages/d8/21/c9d1da0df1275f1dd4e300738679879b7111a75535ed3d061d9edc71990d/openai2-1.7.12.tar.gz",
    "platform": null,
    "description": "# \u9879\u76ee\u63cf\u8ff0\n\nChatGPT \u5de5\u5177\u5305\uff0c\u652f\u6301\u591a\u6a21\u6001\u5bf9\u8bdd\uff08gpt-4o\uff09\u3001\u8fde\u7eed\u5bf9\u8bdd\u3001\u6d41\u5f0f\u5bf9\u8bdd\uff08\u9010\u5b57\u663e\u793a\uff09\u3001\u751f\u6210\u56fe\u50cf\uff08DALL\u00b7E\uff09\u3001\u5bf9\u8bdd\u5b58\u6863\u4e0e\u8f7d\u5165\u3001\u5bf9\u8bdd\u56de\u6eda\u3001\u5bf9\u8bdd\u4f2a\u9020\u3001\u8f6e\u8be2 api_key \u6c60\u3001\u7fa4\u804a\u591a\u89d2\u8272\u6a21\u62df\u3001\u5728\u547d\u4ee4\u884c\u5bf9\u8bdd\u3001\u9650\u5236\u5386\u53f2\u6d88\u606f\u6570\u91cf\u3001\u5f02\u6b65\u8bf7\u6c42\u3002\n\n# \u4f5c\u8005\n\n\u6c5f\u5357\u96e8\u4e0a\n\n[\u4e3b\u9875](https://lcctoor.com/index.html) \\| [Github](https://github.com/lcctoor) \\| [PyPi](https://pypi.org/user/lcctoor) \\| [\u5fae\u4fe1](https://lcctoor.com/cdn/WeChatQRC.jpg) \\| [\u90ae\u7bb1](mailto:lcctoor@outlook.com) \\| [\u6350\u8d60](https://lcctoor.com/cdn/DonationQRC-0rmb.jpg)\n\n# Bug\u63d0\u4ea4\u3001\u529f\u80fd\u63d0\u8bae\n\n\u4f60\u53ef\u4ee5\u901a\u8fc7 [Github-Issues](https://github.com/lcctoor/arts/issues)\u3001[\u5fae\u4fe1](https://lcctoor.com/cdn/WeChatQRC.jpg) \u4e0e\u6211\u8054\u7cfb\u3002\n\n# \u5b89\u88c5\n\n```\npip install openai2\n```\n\n# \u83b7\u53d6api_key\n\n[\u83b7\u53d6\u94fe\u63a51](https://platform.openai.com/account/api-keys)\n\n[\u83b7\u53d6\u94fe\u63a52](https://www.baidu.com/s?wd=%E8%8E%B7%E5%8F%96%20openai%20api_key)\n\n# \u6559\u7a0b ([\u67e5\u770b\u7f8e\u5316\u7248](https://github.com/lcctoor/arts/blob/main/arts/openai2/README.md#\u9879\u76ee\u63cf\u8ff0) \ud83d\udc48)\n\n## \u5bfc\u5165\n\n```python\nfrom openai2 import Chat\n```\n\n## \u521b\u5efa\u5bf9\u8bdd\n\n```python\napi_key = 'api_key'  # \u66f4\u6362\u6210\u81ea\u5df1\u7684api_key\n\nTony = Chat(api_key=api_key, model=\"gpt-3.5-turbo\")\nLucy = Chat(api_key=api_key, model=\"gpt-3.5-turbo\")  # \u6bcf\u4e2a\u5b9e\u4f8b\u53ef\u4f7f\u7528 \u76f8\u540c \u6216\u8005 \u4e0d\u540c \u7684api_key\n```\n\n## \u5bf9\u8bdd\n\n```python\nTony.request('\u81ea\u7136\u657050\u7684\u540e\u9762\u662f\u51e0?')  # >>> '51'\nLucy.request('\u81ea\u7136\u6570100\u7684\u540e\u9762\u662f\u51e0?')  # >>> '101'\n\nTony.request('\u518d\u5f80\u540e\u662f\u51e0?')  # >>> '52'\nLucy.request('\u518d\u5f80\u540e\u662f\u51e0?')  # >>> '102'\n\nTony.request('\u518d\u5f80\u540e\u5462?')  # >>> '53'\nLucy.request('\u518d\u5f80\u540e\u5462?')  # >>> '103'\n```\n\n## \u6d41\u5f0f\u5bf9\u8bdd ([\u67e5\u770b\u6f14\u793a](https://lcctoor.com/openai2/oa_/\u6d41\u5f0f\u5bf9\u8bdd\u6f14\u793a.mp4) \ud83d\udc48)\n\n```python\nfor answer in Lucy.stream_request('\u4e16\u754c\u4e0a\u6700\u5927\u7684\u6d77\u6d0b\u662f\u54ea\u4e2a?'):\n    print(answer)\n\u4e16\n\u754c\n\u4e0a\n\u6700\n\u5927\n\u7684\n\u6d77\n\u6d0b\n\u662f\n\u592a\n\u5e73\n\u6d0b\n\u3002\n```\n\n## \u5f02\u6b65\u5bf9\u8bdd\n\n```python\nimport asyncio\nfrom openai2 import Chat\n\nTony = Chat(api_key=api_key, model=\"gpt-3.5-turbo\")\n\nasync def main():\n    answer = await Tony.async_request('\u4e16\u754c\u4e0a\u6700\u5927\u7684\u6d77\u6d0b\u662f\u54ea\u4e2a')\n    print(answer)\n\nasyncio.run(main())  # >>> '\u4e16\u754c\u4e0a\u6700\u5927\u7684\u6d77\u6d0b\u662f\u592a\u5e73\u6d0b\u3002'\n```\n\n## \u5f02\u6b65\u6d41\u5f0f\u5bf9\u8bdd\n\n```python\nasync for answer in Tony.async_stream_request('\u4e16\u754c\u4e0a\u6700\u5927\u7684\u6d77\u6d0b\u662f\u54ea\u4e2a?'):\n    print(answer)\n\u4e16\n\u754c\n\u4e0a\n\u6700\n\u5927\n\u7684\n\u6d77\n\u6d0b\n\u662f\n\u592a\n\u5e73\n\u6d0b\n\u3002\n```\n\n## \u591a\u6a21\u6001\u5bf9\u8bdd\uff08gpt-4o\uff09\n\n```python\nfrom pathlib import Path\nfrom openai2 import Chat, Multimodal_Part\n\n\nBruce = Chat(api_key='sk-jg93...', model=\"gpt-4o\")\n\n\npic = Path(rf'C:\\\u9f20\u6807.jpeg').read_bytes()\n\nanswer = Bruce.request(\n\n    '\u4e0b\u9762\u8fd9\u5f20\u56fe\u7247\u91cc\u753b\u4e86\u4ec0\u4e48\uff1f',\n  \n    Multimodal_Part.jpeg(pic)\n)\n\nprint(answer)  # >>> '\u8fd9\u5f20\u56fe\u7247\u91cc\u753b\u4e86\u4e00\u4e2a\u9f20\u6807\u3002'\n```\n\n\u6ce8\uff1a\n\n1\u3001Multimodal_Part \u9664\u4e86 jpeg \u65b9\u6cd5\u4ee5\u5916\uff0c\u8fd8\u6709 png\u3001text \u2026\u2026 \u7b49\u65b9\u6cd5\u3002\n\n2\u3001\u5bf9\u4e8e str \u578b\u5bf9\u8c61\uff0c\u4ee5\u4e0b\u8fd9\u4e24\u79cd\u5199\u6cd5\u662f\u7b49\u4ef7\u7684\uff1a`Bruce.request(..., '\u8fd9\u5f20\u56fe\u7247\u91cc\u753b\u4e86\u4ec0\u4e48', ...)`\u3001`Bruce.request(..., Multimodal_Part.text('\u8fd9\u5f20\u56fe\u7247\u91cc\u753b\u4e86\u4ec0\u4e48'), ...)`\u3002\n\n3\u3001\u591a\u6a21\u6001\u5bf9\u8bdd\u652f\u6301\u540c\u6b65\u5bf9\u8bdd\u3001\u5f02\u6b65\u5bf9\u8bdd\u3001\u540c\u6b65\u6d41\u5f0f\u5bf9\u8bdd\u3001\u5f02\u6b65\u6d41\u5f0f\u5bf9\u8bdd\u2026\u2026 \u76f8\u5bf9\u4e8e\u666e\u901a\u5bf9\u8bdd\uff0c\u552f\u4e00\u7684\u533a\u522b\u5c31\u662f\u652f\u6301\u591a\u6a21\u6001\u3002\n\n4\u3001\u76ee\u524d\u5df2\u77e5\u652f\u6301\u591a\u6a21\u6001\u5bf9\u8bdd\u7684\u6a21\u578b\u6709\uff1agpt-4o\u3001gpt-4o-mini\u3001gpt-4o-2024-05-13\u3001gpt-4o-mini-2024-07-18\u3002\n\n## \u5bf9\u8bdd\u56de\u6eda\n\n```python\nAnna = Chat(api_key=api_key, model=\"gpt-3.5-turbo\")\n\nAnna.request('\u81ea\u7136\u65701\u7684\u540e\u9762\u662f\u51e0?')  # >>> 2\nAnna.request('\u518d\u5f80\u540e\u662f\u51e0?')  # >>> 3\nAnna.request('\u518d\u5f80\u540e\u5462?')  # >>> 4\nAnna.request('\u518d\u5f80\u540e\u5462?')  # >>> 5\nAnna.request('\u518d\u5f80\u540e\u5462?')  # >>> 6\nAnna.request('\u518d\u5f80\u540e\u5462?')  # >>> 7\nAnna.request('\u518d\u5f80\u540e\u5462?')  # >>> 8\n\n# \u56de\u6eda1\u8f6e\u5bf9\u8bdd\nAnna.rollback()  # >>> [user]:\u518d\u5f80\u540e\u5462? [assistant]:7\n\n# \u518d\u56de\u6eda3\u8f6e\u5bf9\u8bdd\nAnna.rollback(n=3)  # >>> [user]:\u518d\u5f80\u540e\u5462? [assistant]:4\n\nAnna.request('\u518d\u5f80\u540e\u5462?')  # >>> 5\n```\n\n\u6ce8\uff1a\n\n1\u3001\u6267\u884c `Anna.rollback(n=x)` \u53ef\u56de\u6eda x \u8f6e\u5bf9\u8bdd\u3002\n\n2\u3001`Anna.rollback()` \u76f8\u5f53\u4e8e `Anna.rollback(n=1)` \u3002\n\n## \u8f6e\u8be2 api_key \u6c60\n\n```python\nfrom openai2 import Chat, AKPool\n\nAK1 = 'sk-ug8w...'\nAK2 = AKPool(['sk-mf40...', 'sk-m6g7...', ...])\nAK3 = AKPool(['sk-affe...', 'sk-fam4...', ...])\n\nDuke = Chat(api_key=AK1, model=\"gpt-3.5-turbo\")  # \u4ee4 Duke \u4f7f\u7528\u56fa\u5b9a\u7684 api_key\n\nCarl = Chat(api_key=AK2, model=\"gpt-3.5-turbo\")  # \u4ee4 Carl \u548c Denny \u4f7f\u7528\u540c\u4e00\u4e2a'api_key\u6c60', \u7cfb\u7edf\u5c06\u81ea\u52a8\u5145\u5206\u5229\u7528\u6bcf\u4e2aapi_key\nDenny = Chat(api_key=AK2, model=\"gpt-3.5-turbo\")\n\nChris = Chat(api_key=AK3, model=\"gpt-3.5-turbo\")  # \u4ee4 Chris \u4f7f\u7528\u72ec\u7acb\u7684'api_key\u6c60'\n```\n\n\u6ce8\uff1a\u5141\u8bb8\uff08\u800c\u975e\u4e0d\u5141\u8bb8\uff09\u540c\u4e00\u4e2a api_key \u6295\u653e\u5230\u4e0d\u540c\u7684 api_key \u6c60\u4e2d\uff0c\u4f46\u6bcf\u4e2a api_key \u6c60\u90fd\u662f\u72ec\u7acb\u8c03\u5ea6\uff0c\u4e0d\u4f1a\u4e92\u76f8\u901a\u4fe1\u3002\n\n## \u91cd\u7f6e api_key\n\n```python\nAK5 = 'sk-jg93...'\nAK6 = AKPool(['sk-vb7l...', 'sk-d3lv...'])\n...\n\nCarl.reset_api_key(AK5)  # \u91cd\u7f6e api_key\nCarl.reset_api_key(AK6)  # \u518d\u6b21\u91cd\u7f6e api_key\n...\n```\n\n## \u5bf9\u8bdd\u5bfc\u51fa\u4e0e\u5bfc\u5165\n\n### \u5bf9\u8bdd\u5bfc\u51fa\n\n```python\nAriel = Chat(api_key=api_key, model=\"gpt-3.5-turbo\")\n\nAriel.request('\u81ea\u7136\u65701\u7684\u540e\u9762\u662f\u51e0?')  # >>> 2\nAriel.request('\u518d\u5f80\u540e\u662f\u51e0?')  # >>> 3\n\nAriel.fetch_messages()\n# \u8fd4\u56de:\n# [\n#     {'role': 'user', 'content': '\u81ea\u7136\u65701\u7684\u540e\u9762\u662f\u51e0?'},\n#     {'role': 'assistant', 'content': '2'},\n#     {'role': 'user', 'content': '\u518d\u5f80\u540e\u662f\u51e0?'},\n#     {'role': 'assistant', 'content': '3'}\n# ]\n```\n\n### \u5bf9\u8bdd\u5b58\u6863\n\n\u4f60\u53ef\u4ee5\u628a\u5bfc\u51fa\u7684\u5bf9\u8bdd\u6301\u4e45\u5316\u4fdd\u5b58\uff1a\n\n```python\nimport json\nfrom pathlib import Path\n\nrecord = Ariel.fetch_messages()\nrecord = json.dumps(record, ensure_ascii=False)\nPath('record.json').write_text(record, encoding=\"utf8\")\n```\n\n### \u5bf9\u8bdd\u5bfc\u5165\n\n\u5bfc\u51fa\u7684\u5bf9\u8bdd\u53ef\u4ee5\u518d\u5bfc\u5165\u5230\u5176\u5b83\u5bf9\u8bdd\u4e2d\uff1a\n\n```python\nrecord = Ariel.fetch_messages()\n\nJenny = Chat(api_key=api_key, model=\"gpt-3.5-turbo\")\nJenny.add_dialogs(*record)\n\nJenny.request('\u518d\u5f80\u540e\u5462?')  # >>> 4\n```\n\n\u5bfc\u51fa\u7684\u5bf9\u8bdd\u4e5f\u53ef\u4ee5\u518d\u5bfc\u5165\u5230\u539f\u5bf9\u8bdd\u4e2d\uff0c\u4f46\u8fd9\u6837\u505a\u4f1a\u5728\u539f\u5bf9\u8bdd\u4e2d\u4ea7\u751f\u91cd\u590d\u7684\u5386\u53f2\u6d88\u606f\u3002\n\n### \u5bf9\u8bdd\u4f2a\u9020\n\n\u5229\u7528\u5bf9\u8bdd\u5bfc\u5165\u529f\u80fd\uff0c\u53ef\u4ee5\u4f2a\u9020\u5bf9\u8bdd\uff1a\n\n```python\nfrom openai2 import Chat, user_msg, assistant_msg\n\nMickey = Chat(api_key=api_key, model=\"gpt-3.5-turbo\")\n\nMickey.add_dialogs(\n    user_msg('\u8bf7\u95ee1+1=\u51e0?'),  # \u7b49\u4ef7\u4e8e {\"role\": \"user\", \"content\": '\u8bf7\u95ee1+1=\u51e0?'}\n    assistant_msg('1+1=10'),  # \u7b49\u4ef7\u4e8e {\"role\": \"assistant\", \"content\": '1+1=10'}\n    {\"role\": \"user\", \"content\": '\u90a310+10=\u51e0?'},\n    {\"role\": \"assistant\", \"content\": '10+10=\u4f60\u5927\u7237, \u4f60\u63d0\u7684\u8fd9\u4e9b\u95ee\u9898\u771f\u5f31\u667a!'},\n)\n\nanswer = Mickey.request('\u54e6\u543c, \u4f60\u8fd8\u6562\u9a82\u6211\u5440?')\nprint(answer)  # >>> \u975e\u5e38\u62b1\u6b49\uff0c\u6211\u521a\u624d\u7684\u56de\u7b54\u6709\u4e9b\u4e0d\u9002\u5f53\u30021+1=2, 10+10=20\u3002\u975e\u5e38\u62b1\u6b49\u7ed9\u4f60\u5e26\u6765\u56f0\u6270\uff01\n```\n\n\u6ce8\uff1a\u5bf9\u8bdd\u5bfc\u51fa\u4e0e\u5bfc\u5165\u53ef\u4ee5\u7a7f\u63d2\u5728\u5bf9\u8bdd\u4e2d\u7684\u4efb\u4f55\u65f6\u523b\u3002\n\n## \u751f\u6210\u56fe\u50cf\uff08DALL\u00b7E\uff09\n\n\u8fd4\u56de\u56fe\u7247\u7684\u4e8c\u8fdb\u5236\uff1a\n\n```python\nfrom pathlib import Path\nfrom openai2 import Chat\n\nTony = Chat(api_key='sk-jg93...', model=\"dall-e-2\")\n\nimages = Tony.dalle('\u8bf7\u753b\u4e00\u53ea\u732b', image_count=2)\n\nfor i, x in enumerate(images):\n    Path(f\"\u7b2c{i}\u5f20.png\").write_bytes(x)\n```\n\n\u8fd4\u56de\u56fe\u7247\u7684URL\uff1a\n\n```python\nfrom pathlib import Path\nfrom openai2 import Chat\n\nTony = Chat(api_key='sk-jg93...', model=\"dall-e-2\")\n\nimages = Tony.dalle('\u8bf7\u753b\u4e00\u53ea\u732b', image_count=2, return_format='url')\n\nfor i, url in enumerate(images):\n    print(f\"\u7b2c{i}\u5f20\u7684URL\u662f\uff1a\", url)\n```\n\n## \u5f02\u6b65\u751f\u6210\u56fe\u50cf\uff08DALL\u00b7E\uff09\n\n\u8fd4\u56de\u56fe\u7247\u7684\u4e8c\u8fdb\u5236\uff1a\n\n```python\nimport asyncio\nfrom pathlib import Path\nfrom openai2 import Chat\n\nasync def main():\n    Tony = Chat(api_key='sk-jg93...', model=\"dall-e-2\")\n\n    images = await Tony.async_dalle('\u8bf7\u753b\u4e00\u53ea\u732b', image_count=2)\n    \n    for i, x in enumerate(images):\n        Path(f\"\u7b2c{i}\u5f20.png\").write_bytes(x)\n\nasyncio.run(main())\n```\n\n\u8fd4\u56de\u56fe\u7247\u7684URL\uff1a\n\n```python\nimport asyncio\nfrom pathlib import Path\nfrom openai2 import Chat\n\nasync def main():\n    Tony = Chat(api_key='sk-jg93...', model=\"dall-e-2\")\n\n    images = await Tony.async_dalle('\u8bf7\u753b\u4e00\u53ea\u732b', image_count=2, return_format='url')\n    \n    for i, url in enumerate(images):\n        print(f\"\u7b2c{i}\u5f20\u7684URL\u662f\uff1a\", url)\n\nasyncio.run(main())\n```\n\n## \u7fa4\u804a\u591a\u89d2\u8272\u6a21\u62df\n\n```python\nimport json\nfrom openai2 import GroupChat\n\napi_key = '...'  # \u66f4\u6362\u6210\u81ea\u5df1\u7684 api_key\ngroup = GroupChat(api_key=api_key, model=\"gpt-3.5-turbo\")\n\n# \u8bbe\u7f6e\u89d2\u8272\ngroup.roles['\u82cf\u8f7c'] = '\u5b8b\u671d\u8bd7\u4eba\uff0c\u4ed6\u7684\u8bcd\u98ce\u683c\u72ec\u7279\uff0c\u65e2\u6709\u5112\u5bb6\u7684\u6559\u8bf2\uff0c\u53c8\u6709\u751f\u6d3b\u7684\u4e50\u8da3\u3002'\ngroup.roles['\u674e\u6e05\u7167'] = '\u5b8b\u4ee3\u8457\u540d\u7684\u5973\u8bcd\u4eba\uff0c\u5176\u8bcd\u53e5\u4f18\u7f8e\uff0c\u60c5\u611f\u771f\u631a\u3002'\ngroup.roles['\u675c\u752b'] = '\u5510\u671d\u8457\u540d\u8bd7\u4eba\u3002'\n\n# \u6dfb\u52a0\u89d2\u8272\u5386\u53f2\u5bf9\u8bdd\ngroup.add_dialog(speaker='\u82cf\u8f7c', audiences=['\u674e\u6e05\u7167'], remark='\u4f60\u597d\u5440')\ngroup.add_dialog(speaker='\u674e\u6e05\u7167', audiences=['\u82cf\u8f7c'], remark='\u597d\u4e45\u4e0d\u89c1, \u4f60\u6700\u8fd1\u5728\u5fd9\u4ec0\u4e48?')\ngroup.add_dialog(speaker='\u675c\u752b', audiences=['\u82cf\u8f7c'], remark='\u4e0a\u6b21\u6258\u4f60\u5e2e\u6211\u5199\u7684\u90a3\u9996\u300a\u8305\u5c4b\u4e3a\u79cb\u98ce\u6240\u7834\u6b4c\u300b\u5199\u597d\u4e86\u5417?')\n\n# \u8ba9 ChatGPT \u6a21\u62df\u89d2\u8272\u53d1\u8a00\nanswer = group.request([\n    ('\u82cf\u8f7c', ['\u674e\u6e05\u7167']),  # \u7b2c 1 \u4e2a\u5143\u7d20\u8868\u793a\u8bf4\u8bdd\u4eba, \u7b2c 2 \u4e2a\u5143\u7d20\u8868\u793a\u5bf9\u8c01\u8bf4\u8bdd. \u7531\u4e8e\u4e00\u4e2a\u4eba\u53ef\u4ee5\u540c\u65f6\u5bf9\u591a\u4e2a\u4eba\u8bf4\u8bdd, \u56e0\u6b64\u7b2c 2 \u4e2a\u5143\u7d20\u4e3a\u5217\u8868\n    ('\u82cf\u8f7c', ['\u675c\u752b']),\n])\n\ntry:\n    print( json.loads(answer) )\nexcept:\n    print(answer)\n\n# \u8fd4\u56de:\n[\n    {\n        \"speaker\": \"\u82cf\u8f7c\",\n        \"audiences\": \"\u674e\u6e05\u7167\",\n        \"remark\": \"\u6700\u8fd1\u6211\u5728\u5199\u4e00\u9996\u65b0\u7684\u8bd7\uff0c\u9898\u76ee\u662f\u300a\u542c\u96e8\u300b\"\n    },\n    {\n        \"speaker\": \"\u82cf\u8f7c\",\n        \"audiences\": \"\u675c\u752b\",\n        \"remark\": \"\u90a3\u9996\u300a\u8305\u5c4b\u4e3a\u79cb\u98ce\u6240\u7834\u6b4c\u300b\u5df2\u7ecf\u5199\u597d\u5566\uff0c\u6211\u5728\u4fe1\u91cc\u5bc4\u7ed9\u4f60\u4e86\uff0c\u8bf7\u67e5\u6536\"\n    }\n]\n```\n\n## \u9650\u5236\u5386\u53f2\u6d88\u606f\u6570\u91cf\n\n### \u9650\u5236\u5386\u53f2\u6d88\u606f\u6570\u91cf\n\n\u968f\u7740\u5bf9\u8bdd\u6b21\u6570\u8d8a\u6765\u8d8a\u591a\uff0c\u6700\u7ec8\u4e0a\u4e0b\u6587\u957f\u5ea6\u5c31\u4f1a\u8d85\u51fa openai \u63a5\u53e3\u9650\u5b9a\u7684\u6700\u5927 token \u6570\u91cf\uff0c\u6b64\u65f6\u53ef\u4f7f\u7528 msg_max_count \u53c2\u6570\u6765\u9650\u5236\u5386\u53f2\u6d88\u606f\u6570\u91cf\u3002\u5f53\u6d88\u606f\u6570\u91cf\u8d85\u51fa msg_max_count \u540e\uff0c\u7a0b\u5e8f\u4f1a\u81ea\u52a8\u79fb\u9664\u6700\u65e9\u7684\u8bb0\u5f55\uff0c\u4f7f\u6d88\u606f\u6570\u91cf\u51cf\u5c11\u5230\u6070\u597d\u7b49\u4e8e msg_max_count \u3002\n\n```python\nmsg_max_count = 6  # \u6700\u591a\u4fdd\u75596\u6761\u5386\u53f2\u6d88\u606f\n\nAriel = Chat(api_key=api_key, model=\"gpt-3.5-turbo\", msg_max_count=msg_max_count)\n\nAriel.request('\u82f1\u56fd\u7684\u9996\u90fd\u662f\u4ec0\u4e48\uff1f')  # >>> '\u4f26\u6566'\nAriel.request('\u65e5\u672c\u9996\u90fd\u662f\u4ec0\u4e48\uff1f')  # >>> '\u4e1c\u4eac'\nAriel.request('\u610f\u5927\u5229\u7684\u9996\u90fd\u662f\u4ec0\u4e48\uff1f')  # >>> '\u7f57\u9a6c'\nAriel.request('\u7f8e\u56fd\u7684\u9996\u90fd\u662f\u4ec0\u4e48\uff1f')  # >>> '\u534e\u76db\u987f'\nAriel.request('\u4e16\u754c\u4e0a\u56fd\u571f\u9762\u79ef\u6700\u5927\u7684\u56fd\u5bb6\u662f\u54ea\u4e2a\uff1f')  # >>> '\u4fc4\u7f57\u65af'\nAriel.request('\u6cd5\u56fd\u7684\u9996\u90fd\u53eb\u4ec0\u4e48\uff1f')  # >>> '\u5df4\u9ece'\nAriel.request('\u9752\u86d9\u7684\u5e7c\u4f53\u53eb\u4ec0\u4e48\uff1f')  # >>> '\u874c\u86aa'\nAriel.request('\u4e16\u754c\u4e0a\u6700\u5927\u7684\u6d77\u6d0b\u662f\u4ec0\u4e48\uff1f')  # >>> '\u592a\u5e73\u6d0b'\n\nAriel.fetch_messages()\n\n# \u8fd4\u56de:\n# [\n#     {'role': 'user', 'content': '\u6cd5\u56fd\u7684\u9996\u90fd\u53eb\u4ec0\u4e48\uff1f'},\n#     {'role': 'assistant', 'content': '\u5df4\u9ece'},\n#     {'role': 'user', 'content': '\u9752\u86d9\u7684\u5e7c\u4f53\u53eb\u4ec0\u4e48\uff1f'},\n#     {'role': 'assistant', 'content': '\u874c\u86aa'},\n#     {'role': 'user', 'content': '\u4e16\u754c\u4e0a\u6700\u5927\u7684\u6d77\u6d0b\u662f\u4ec0\u4e48\uff1f'},\n#     {'role': 'assistant', 'content': '\u592a\u5e73\u6d0b'}\n# ]\n```\n\n### \u9501\u5b9a\u6d88\u606f\n\n\u5f53\u7a0b\u5e8f\u81ea\u52a8\u79fb\u9664\u6d88\u606f\u8bb0\u5f55\u65f6\uff0c\u4e5f\u8bb8\u6211\u4eec\u5e0c\u671b\u67d0\u4e9b\u6d88\u606f\u4e0d\u8981\u88ab\u79fb\u9664\uff0c\u6b64\u65f6\u53ef\u5c06\u8fd9\u4e9b\u6d88\u606f\u9501\u5b9a\u3002\n\n```python\nmsg_max_count = 6\n\nAriel = Chat(api_key=api_key, model=\"gpt-3.5-turbo\", msg_max_count=msg_max_count)\n\nAriel.request('\u82f1\u56fd\u7684\u9996\u90fd\u662f\u4ec0\u4e48\uff1f')  # >>> '\u4f26\u6566'\nAriel.request('\u65e5\u672c\u9996\u90fd\u662f\u4ec0\u4e48\uff1f')  # >>> '\u4e1c\u4eac'\nAriel.request('\u610f\u5927\u5229\u7684\u9996\u90fd\u662f\u4ec0\u4e48\uff1f')  # >>> '\u7f57\u9a6c'\n```\n\n\u6b64\u65f6\u5171\u6709 6 \u6761\u6d88\u606f\u8bb0\u5f55\uff1a\n\n| \u6d88\u606f                 | \u6b63\u5e8f\u7d22\u5f15 | \u9006\u5e8f\u7d22\u5f15 |\n| -------------------- | :------: | :------: |\n| \u82f1\u56fd\u7684\u9996\u90fd\u662f\u4ec0\u4e48\uff1f   |    0    |    -6    |\n| \u4f26\u6566                 |    1    |    -5    |\n| \u65e5\u672c\u9996\u90fd\u662f\u4ec0\u4e48\uff1f     |    2    |    -4    |\n| \u4e1c\u4eac                 |    3    |    -3    |\n| \u610f\u5927\u5229\u7684\u9996\u90fd\u662f\u4ec0\u4e48\uff1f |    4    |    -2    |\n| \u7f57\u9a6c                 |    5    |    -1    |\n\n\u9501\u5b9a\u7d22\u5f15\u4e3a 0\u3001-2\u3001-1 \u7684\u6d88\u606f\uff1a\n\n```python\nAriel.pin_messages(0, -2, -1)  # \u7d22\u5f15\u65e0\u987b\u6309\u987a\u5e8f\u586b\u5199: pin_messages(0, 1, 2) \u4e0e pin_messages(0, 2, 1) \u7b49\u4ef7.\n```\n\n\u7ee7\u7eed\u8bf7\u6c42\uff1a\n\n```python\nAriel.request('\u7f8e\u56fd\u7684\u9996\u90fd\u662f\u4ec0\u4e48\uff1f')  # >>> '\u534e\u76db\u987f'\n```\n\n\u7531\u4e8e\u8bbe\u7f6e\u4e86 msg_max_count = 6\uff0c\u6b64\u65f6\u5171\u6709 6 \u6761\u6d88\u606f\u8bb0\u5f55\uff1a\n\n| \u6d88\u606f                 | \u6b63\u5e8f\u7d22\u5f15 | \u9006\u5e8f\u7d22\u5f15 | \u9501\u5b9a\u72b6\u6001 |\n| -------------------- | :------: | :------: | :------: |\n| \u82f1\u56fd\u7684\u9996\u90fd\u662f\u4ec0\u4e48\uff1f   |    0    |    -6    |  \u5df2\u9501\u5b9a  |\n| \u4e1c\u4eac                 |    1    |    -5    |    -    |\n| \u610f\u5927\u5229\u7684\u9996\u90fd\u662f\u4ec0\u4e48\uff1f |    2    |    -4    |  \u5df2\u9501\u5b9a  |\n| \u7f57\u9a6c                 |    3    |    -3    |  \u5df2\u9501\u5b9a  |\n| \u7f8e\u56fd\u7684\u9996\u90fd\u662f\u4ec0\u4e48\uff1f   |    4    |    -2    |    -    |\n| \u534e\u76db\u987f               |    5    |    -1    |    -    |\n\n\u7ee7\u7eed\u6267\u884c\uff1a\n\n```python\nAriel.pin_messages(-2)  # \u9501\u5b9a'\u7f8e\u56fd\u7684\u9996\u90fd\u662f\u4ec0\u4e48\uff1f'\n\nAriel.request('\u4e16\u754c\u4e0a\u56fd\u571f\u9762\u79ef\u6700\u5927\u7684\u56fd\u5bb6\u662f\u54ea\u4e2a\uff1f')  # >>> '\u4fc4\u7f57\u65af'\nAriel.request('\u6cd5\u56fd\u7684\u9996\u90fd\u53eb\u4ec0\u4e48\uff1f')  # >>> '\u5df4\u9ece'\nAriel.request('\u9752\u86d9\u7684\u5e7c\u4f53\u53eb\u4ec0\u4e48\uff1f')  # >>> '\u874c\u86aa'\nAriel.request('\u4e16\u754c\u4e0a\u6700\u5927\u7684\u6d77\u6d0b\u662f\u4ec0\u4e48\uff1f')  # >>> '\u592a\u5e73\u6d0b'\n\nAriel.fetch_messages()\n\n# \u8fd4\u56de:\n# [\n#     {'role': 'user', 'content': '\u82f1\u56fd\u7684\u9996\u90fd\u662f\u4ec0\u4e48\uff1f'},       # \u88ab\u9501\u5b9a\u7684\u6d88\u606f\n#     {'role': 'user', 'content': '\u610f\u5927\u5229\u7684\u9996\u90fd\u662f\u4ec0\u4e48\uff1f'},     # \u88ab\u9501\u5b9a\u7684\u6d88\u606f\n#     {'role': 'assistant', 'content': '\u7f57\u9a6c'},               # \u88ab\u9501\u5b9a\u7684\u6d88\u606f\n#     {'role': 'user', 'content': '\u7f8e\u56fd\u7684\u9996\u90fd\u662f\u4ec0\u4e48\uff1f'},       # \u88ab\u9501\u5b9a\u7684\u6d88\u606f\n#     {'role': 'user', 'content': '\u4e16\u754c\u4e0a\u6700\u5927\u7684\u6d77\u6d0b\u662f\u4ec0\u4e48\uff1f'},\n#     {'role': 'assistant', 'content': '\u592a\u5e73\u6d0b'}\n# ]\n```\n\n\u6ce8\uff1apin_messages \u65b9\u6cd5\u4e5f\u5141\u8bb8\u4f20\u5165\u201c\u5df2\u9501\u5b9a\u7684\u6d88\u606f\u201d\u7684\u7d22\u5f15\uff0c\u8fd9\u4f7f\u5f97\u5f53\u4e0d\u786e\u5b9a\u67d0\u4e9b\u6d88\u606f\u7684\u72b6\u6001\u65f6\uff0c\u53ef\u4ee5\u653e\u5fc3\u5730\u5c06\u5b83\u4eec\u7684\u7d22\u5f15\u4f20\u8fdb\u53bb\u3002\n\n### \u89e3\u9501\u6d88\u606f\n\n\u53ef\u4f7f\u7528 unpin_messages \u65b9\u6cd5\u5c06\u5df2\u9501\u5b9a\u7684\u6d88\u606f\u89e3\u9664\u9501\u5b9a\u3002\n\n```python\nAriel.unpin_messages(0, -2, -1)  # \u89e3\u9501\u7d22\u5f15\u4e3a 0\u3001-2\u3001-1 \u7684\u6d88\u606f\n```\n\n\u6ce8\uff1aunpin_messages \u65b9\u6cd5\u4e5f\u5141\u8bb8\u4f20\u5165\u201c\u672a\u9501\u5b9a\u7684\u6d88\u606f\u201d\u7684\u7d22\u5f15\uff0c\u8fd9\u4f7f\u5f97\u5f53\u4e0d\u786e\u5b9a\u67d0\u4e9b\u6d88\u606f\u7684\u72b6\u6001\u65f6\uff0c\u53ef\u4ee5\u653e\u5fc3\u5730\u5c06\u5b83\u4eec\u7684\u7d22\u5f15\u4f20\u8fdb\u53bb\u3002\n\n## \u66f4\u591a\u65b9\u6cd5\n\n1\u3001`openai2.Chat` \u5e95\u5c42\u8c03\u7528\u4e86 `openai.OpenAI`\uff0c\u652f\u6301 `openai.OpenAI` \u7684\u6240\u6709\u53c2\u6570\u3002\n\n2\u3001`openai2.Chat.request` \u4e0e `openai2.Chat.stream_request` \u5e95\u5c42\u8c03\u7528\u4e86 `openai.OpenAI.chat.completions.create`\uff0c\u652f\u6301 `openai.OpenAI.chat.completions.create` \u7684\u6240\u6709\u53c2\u6570\u3002\n\n3\u3001`openai2.Chat.async_request` \u4e0e `openai2.Chat.async_stream_request` \u5e95\u5c42\u8c03\u7528\u4e86 `openai.AsyncOpenAI.chat.completions.create`\uff0c\u652f\u6301 `openai.AsyncOpenAI.chat.completions.create` \u7684\u6240\u6709\u53c2\u6570\u3002\n\n[\u67e5\u770b\u76f8\u5173\u53c2\u6570](https://platform.openai.com/docs/api-reference/chat) \ud83d\udc48\n\n## \u5728\u547d\u4ee4\u884c\u5bf9\u8bdd ([\u67e5\u770b\u6f14\u793a](https://lcctoor.com/openai2/oa_/\u547d\u4ee4\u884c\u5bf9\u8bdd\u6f14\u793a.mp4) \ud83d\udc48)\n\n```cpp\nopenai2 add_apikey sk-T92mZYXHLWKt1234gtPKT3BlbkFJ\nopenai2 chat\n```\n\n\u6307\u4ee4\u96c6\n\n| \u6307\u4ee4                               | \u529f\u80fd                         | \u8bf4\u660e                     |\n| ---------------------------------- | ---------------------------- | ------------------------ |\n| openai2\u00a0\u00a0add_apikey\u00a0 \u4f60\u7684apikey | \u6dfb\u52a0 1 \u4e2a apikey             | \u5982\u9700\u6dfb\u52a0\u591a\u4e2a\uff0c\u53ef\u6267\u884c\u591a\u6b21 |\n| openai2\u00a0 read_apikey              | \u67e5\u770b\u6240\u6709 apikey              |                          |\n| openai2\u00a0 clear_apikey             | \u6e05\u9664\u6240\u6709 apikey              |                          |\n| openai2\u00a0 chat                     | \u7ee7\u7eed\u4e0a\u6b21\u7684\u5bf9\u8bdd               |                          |\n| openai2\u00a0 newchat                  | \u6e05\u7a7a\u5bf9\u8bdd\u8bb0\u5f55, \u7136\u540e\u5f00\u59cb\u65b0\u5bf9\u8bdd |                          |\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "ChatGPT \u5de5\u5177\u5305\uff0c\u652f\u6301\u591a\u6a21\u6001\u5bf9\u8bdd\uff08gpt-4o\uff09\u3001\u8fde\u7eed\u5bf9\u8bdd\u3001\u6d41\u5f0f\u5bf9\u8bdd\uff08\u9010\u5b57\u663e\u793a\uff09\u3001\u751f\u6210\u56fe\u50cf\uff08DALL\u00b7E\uff09\u3001\u5bf9\u8bdd\u5b58\u6863\u4e0e\u8f7d\u5165\u3001\u5bf9\u8bdd\u56de\u6eda\u3001\u5bf9\u8bdd\u4f2a\u9020\u3001\u8f6e\u8be2 api_key \u6c60\u3001\u7fa4\u804a\u591a\u89d2\u8272\u6a21\u62df\u3001\u5728\u547d\u4ee4\u884c\u5bf9\u8bdd\u3001\u9650\u5236\u5386\u53f2\u6d88\u606f\u6570\u91cf\u3001\u5f02\u6b65\u8bf7\u6c42\u3002",
    "version": "1.7.12",
    "project_urls": {
        "Source": "https://github.com/lcctoor/arts/tree/main/arts/openai2"
    },
    "split_keywords": [
        "openai",
        " chatgpt",
        " openai2"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "bfb90b523d196bdb51567fd3ea598ba9f867c38b670d07574d5d17d91394cd6e",
                "md5": "1cf4f10ea0131f912ecff4e4d2d18c8a",
                "sha256": "04bb836b93a008eea128fc922b071789cc56d21ec085c8ef602e7c8fab74d9e9"
            },
            "downloads": -1,
            "filename": "openai2-1.7.12-py2.py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "1cf4f10ea0131f912ecff4e4d2d18c8a",
            "packagetype": "bdist_wheel",
            "python_version": "py2.py3",
            "requires_python": null,
            "size": 10446,
            "upload_time": "2024-09-14T02:06:41",
            "upload_time_iso_8601": "2024-09-14T02:06:41.384607Z",
            "url": "https://files.pythonhosted.org/packages/bf/b9/0b523d196bdb51567fd3ea598ba9f867c38b670d07574d5d17d91394cd6e/openai2-1.7.12-py2.py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "d821c9d1da0df1275f1dd4e300738679879b7111a75535ed3d061d9edc71990d",
                "md5": "bbaff2b90db0c27d64deaab168747850",
                "sha256": "4551de8b50ac579937500e3e0e0c6f0bcb79c8950032c3a3269da6a6cc82f1b9"
            },
            "downloads": -1,
            "filename": "openai2-1.7.12.tar.gz",
            "has_sig": false,
            "md5_digest": "bbaff2b90db0c27d64deaab168747850",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 20893,
            "upload_time": "2024-09-14T02:06:44",
            "upload_time_iso_8601": "2024-09-14T02:06:44.511049Z",
            "url": "https://files.pythonhosted.org/packages/d8/21/c9d1da0df1275f1dd4e300738679879b7111a75535ed3d061d9edc71990d/openai2-1.7.12.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-09-14 02:06:44",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "lcctoor",
    "github_project": "arts",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "openai2"
}
        
Elapsed time: 0.41484s