一个逆向工程的 Python API 封装,用于 Quora 的 Poe,它提供了免费访问 ChatGPT、GPT-4 和 Claude 的功能。

作者:Sec-Labs | 发布时间:

项目地址

https://github.com/ading2210/poe-api

Python Poe API

这是一个对 Quora 的 Poe 进行了逆向工程的 API 包装器,它让你可以自由访问 OpenAI 的 ChatGPT 和 GPT-4,以及 Anthropic 的 Claude。

目录:

目录由 markdown-toc 生成。

 

功能:

  • 使用 Token 登录
  • 代理请求 + Websocket
  • 下载机器人列表
  • 发送消息
  • 流式传输机器人响应
  • 清除对话上下文
  • 下载对话历史
  • 删除消息
  • 清空整个对话
  • 创建自定义机器人
  • 编辑你的自定义机器人
  • 使用现有的第三方机器人

安装:

你可以通过运行以下命令来安装这个库:

pip3 install poe-api

文档:

例子可以在 /examples 目录中找到。要运行这些例子,请将你的 Token 作为命令行参数传递。

python3 examples/temporary_message.py "TOKEN_HERE"

找到你的 Token:

在任何桌面 Web 浏览器上登录 Poe,然后打开你的浏览器开发工具(也称为“检查”),并在以下菜单中查找 p-b cookie 的值:

  • Chromium:Devtools > Application > Cookies > poe.com
  • Firefox:Devtools > Storage > Cookies
  • Safari:Devtools > Storage > Cookies

使用客户端:

要使用这个库,只需导入 poe 并创建一个 poe.Client 实例。Client 类接受以下参数:

  • token - 要使用的 Token。
  • proxy = None - 要使用的代理,格式为 protocol://host:port。建议使用 socks5h 协议,因为它还代理了 DNS 查询。
  • device_id = None - 要使用的设备 ID。如果未指定,则会随机生成并存储在磁盘上。
  • headers = headers - 要使用的头信息。默认为 poe.headers 中指定的头信息。
  • client_identifier = client_identifier - 将传递到 TLS 客户端库中的客户端标识符。默认为 poe.client_identifier 中指定的标识符。

常规例子:

import poe
client = poe.Client("TOKEN_HERE")

代理例子:

import poe
client = poe.Client("TOKEN_HERE", proxy="socks5h://178.62.100.151:59166")

请注意,以下例子假设 client 是你的 poe.Client 实例的名称。如果 Token 无效,将引发 RuntimeError。

下载可用的机器人:

客户端在初始化时下载所有可用的机器人,并将它们存储在 client.bots 中。将机器人代码名称映射到其显示名称的字典可以在 client.bot_names 中找到。如果你想刷新这些值,可以调用 client.get_bots。此函数接受以下参数:

  • download_next_data = True - 是否重新下载 __NEXT_DATA__,如果机器人列表已更改,则需要此数据。
print(json.dumps(client.bot_names, indent=2))
"""
{
  "capybara": "Sage",
  "a2": "Claude-instant",
  "nutria": "Dragonfly",
  "a2_100k": "Claude-instant-100k",
  "beaver": "GPT-4",
  "chinchilla": "ChatGPT",
  "a2_2": "Claude+"
}
"""

请注意,在免费帐户上,Claude+(a2_2)每天有 3 条消息的限制,GPT-4(beaver)每天有 1 条消息的限制。对于所有其他聊天机器人,似乎有每分钟 10 条消息的速率限制。

使用第三方机器人:

要获取第三方机器人的列表,请使用 client.explore_bots,它接受以下参数:

  • end_cursor = None - 获取列表时要使用的游标。
  • count = 25 - 返回的机器人数量。

该函数将返回一个包含机器人列表和下一页游标的字典:

print(json.dumps(client.explore_bots(count=1), indent=2))
"""
{
  "bots": [
    {
      "id": "Qm90OjEwMzI2MDI=",
      "displayName": "leocooks",
      "deletionState": "not_deleted",
      "image": {
        "__typename": "UrlBotImage",
        "url": "https://qph.cf2.quoracdn.net/main-thumb-pb-1032602-200-uorvomwowfgmatdvrtwajtwwqlujmmgu.jpeg"
      },
      "botId": 1032602,
      "followerCount": 1922,
      "description": "Above average meals for average cooks, made simple by world-renowned chef, Leonardo",
      "__typename": "Bot"
    }
  ],
  "end_cursor": "1000172"
}
"""

要获取特定的第三方机器人,可以使用 client.get_bot_by_codename,它接受机器人的代码名称作为其唯一参数。

client.get_bot_by_codename("JapaneseTutor")

由于自定义机器人的显示名称与代码名称相同,因此你只需将机器人的显示名称传递到 client.send_message 中即可向其发送消息。

创建新机器人:

你可以使用 client.create_bot 函数创建新的机器人,它接受以下参数:

  • handle - 新机器人的 Handle。
  • prompt = "" - 新机器人的提示。
  • base_model = "chinchilla" - 新机器人使用的模型。这必须是 "chinchilla"(ChatGPT)或 "a2"(Claude)之一。
  • description = "" - 新机器人的描述。
  • intro_message = "" - 新机器人的介绍消息。如果这是一个空字符串,则机器人将没有介绍消息。
  • prompt_public = True - 提示是否应该公开可见。
  • pfp_url = None - 机器人资料图片的 URL。目前,使用此库没有上传自定义图片的方法。
  • linkification = False - 机器人是否应该将响应中的某些文本转换为可点击的链接。
  • markdown_rendering = True - 是否要启用机器人响应的 Markdown 渲染。
  • suggested_replies = False - 机器人是否应该在每次响应后建议可能的回复。
  • private = False - 机器人是否应该是私有的。

如果要让新机器人使用自己的 API(如此处所述 链接):

  • api_key = None - 新机器人的 API 密钥。
  • api_bot = False - 机器人是否已启用 API 功能。
  • api_url = None - 新机器人的 API URL。

有关如何创建和编辑机器人的完整示例位于 examples/create_bot.py 中。

new_bot = client.create_bot(bot_name, "prompt goes here", base_model="a2")

编辑机器人:

你可以使用 client.edit_bot 函数编辑自定义机器人,它接受以下参数:

  • bot_id - 要编辑的机器人的 botId
  • handle - 要编辑的机器人的 Handle。
  • prompt - 新机器人的提示。
  • base_model = "chinchilla" - 新模型机器人使用的模型。这必须是 "chinchilla"(ChatGPT)或 "a2"(Claude)之一。以前,它可以设置为 "beaver"(GPT-4),从而绕过免费帐户的限制,但现在已修复。
  • description = "" - 新机器人的描述。
  • intro_message = "" - 新机器人的介绍消息。如果这是一个空字符串,则机器人将没有介绍消息。
  • prompt_public = True - 提示是否应该公开可见。
  • pfp_url = None - 机器人资料图片的 URL。目前,使用此库没有上传自定义图片的方法。
  • linkification = False - 机器人是否应该将响应中的某些文本转换为可点击的链接。
  • markdown_rendering = True - 是否要启用机器人响应的 Markdown 渲染。
  • suggested_replies = False - 机器人是否应该在每次响应后建议可能的回复。
  • private = False - 机器人是否应该是私有的。

机器人 API 相关参数:

  • api_key = None - 机器人的新 API 密钥。
  • api_url = None - 机器人的新 API URL。

有关如何创建和编辑机器人的完整示例位于 examples/create_bot.py 中。

edit_result = client.edit_bot(1086981, "bot_handle_here", base_model="a2")

发送消息:

你可以使用 client.send_message 函数向聊天机器人发送消息,它接受以下参数:

  • chatbot - 聊天机器人的代码名称。(例如:capybara
  • message - 要发送给聊天机器人的消息。
  • with_chat_break = False - 是否应清除对话上下文。
  • timeout = 20 - 接收到的块之间的最大秒数,直到引发 RuntimeError

该函数是一个生成器,每当生成的消息更新时,它就会返回最新版本的消息。

流示例:

message = "Summarize the GNU GPL v3"
for chunk in client.send_message("capybara", message):
  print(chunk["text_new"], end="", flush=True)

非流示例:

message = "Summarize the GNU GPL v3"
for chunk in client.send_message("capybara", message):
  pass
print(chunk["text"])

你还可以使用 threading 并行发送多条消息,并分别接收它们的响应,如 /examples/parallel_messages.py 中所示。请注意,如果发送消息过快,服务器会给出错误,但请求最终会成功。

清除对话上下文:

如果你想在不发送消息的情况下清除对话的上下文,可以使用 client.send_chat_break。唯一的参数是要清除其上下文的机器人的代码名称。

client.send_chat_break("capybara")

该函数返回表示聊天中断的消息。

下载对话历史记录:

要下载会话中的过去消息,请使用 client.get_message_history 函数,它接受以下参数:

  • chatbot - 聊天机器人的代码名称。
  • count = 25 - 要下载的消息数。
  • cursor = None - 要从其中开始而不是从最新消息开始的消息 ID。

请注意,如果您不指定光标,则客户端必须执行额外的请求以确定最新的光标。

返回的消息按照从旧到新的顺序排列。

message_history = client.get_message_history("capybara", count=10)
print(json.dumps(message_history, indent=2))
"""
[
  {
    "node": {
      "id": "TWVzc2FnZToxMDEwNzYyODU=",
      "messageId": 101076285,
      "creationTime": 1679298157718888,
      "text": "",
      "author": "chat_break",
      "linkifiedText": "",
      "state": "complete",
      "suggestedReplies": [],
      "vote": null,
      "voteReason": null,
      "__typename": "Message"
    },
    "cursor": "101076285",
    "id": "TWVzc2FnZUVkZ2U6MTAxMDc2Mjg1OjEwMTA3NjI4NQ=="
  },
  ...
]
"""

删除消息:

要删除消息,请使用 client.delete_message 函数,它接受一个参数。你可以将单个消息 ID 传递给它以删除单个消息,或者你可以传递消息 ID 的列表以一次删除多个消息。

#删除单个消息
client.delete_message(96105719)

#一次删除多个消息
client.delete_message([96105719, 96097108, 96097078, 96084421, 96084402])

清空对话:

要清空整个对话或仅删除最后几条消息,你可以使用 client.purge_conversation 函数。此函数接受以下参数:

  • chatbot - 聊天机器人的代码名称。
  • count = -1 - 要删除的消息数,从最新的消息开始计算。默认行为是删除每个单独的消息。
#仅清空最后10条消息
client.purge_conversation("capybara", count=10)

#清空整个对话
client.purge_conversation("capybara")

清空所有对话:

要清空帐户中的所有对话,使用 client.purge_all_conversations 函数。此函数不需要任何参数。

>>> client.purge_all_conversations()

获取剩余消息数:

要获取对话配额中剩余的消息数,请使用 client.get_remaining_messages 函数。此函数接受以下参数:

  • chatbot - 聊天机器人的代码名称。

该函数将返回剩余的消息数,如果机器人没有配额,则返回 None

>>> client.get_remaining_messages("beaver")
1

其他:

更改日志级别:

如果要显示调试消息,只需调用 poe.logger.setLevel

import poe
import logging
poe.logger.setLevel(logging.INFO)

设置自定义 User-Agent:

如果要更改伪造的标头,请在导入库后设置 poe.headers

要使用你的浏览器自己的标头,请访问此网站,并复制粘贴其内容。

import poe
poe.headers = {
  "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0",
  "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
  "Accept-Encoding": "gzip, deflate, br",
  "Accept-Language": "en-US,en;q=0.5",
  "Te": "trailers",
  "Upgrade-Insecure-Requests": "1"
}

以下标头将被忽略和覆盖:

{
  "Referrer": "https://poe.com/",
  "Origin": "https://poe.com",
  "Host": "poe.com",
  "Sec-Fetch-Dest": "empty",
  "Sec-Fetch-Mode": "cors",
  "Sec-Fetch-Site": "same-origin"
}

以前,这是通过 poe.user_agent 进行的,但现在该变量完全被忽略。

你还需要更改 poe.client_identifier 以匹配你设置的用户代理。请参阅 Python-TLS-Client 文档 获取一些示例值。请注意,伪造 Chrome/Firefox 版本 >= 110 可能是可检测的。

poe.client_identifier = "chrome_107"

设置自定义设备 ID:

如果要更改伪造的设备 ID,可以使用 poe.set_device_id,它接受以下参数:

  • user_id - 要更改设备 ID 的帐户的用户 ID。用户 ID 可在 client.viewer["poeUser"]["id"] 处找到。
  • device_id - 新的设备 ID。这是一个32个字符的 UUID 字符串,格式如下:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
poe.set_device_id("UGMlVXqlcLYyMOATMDsKNTMz", "6d659b04-043a-41f8-97c7-fb7d7fe9ad34")

设备 ID 保存在 Unix-like 系统中的 ~/.config/poe-api/device_id.json,在 Windows 中的 C:\Users\<user>\AppData\Roaming\poe-api\device_id.json 中。

此外,可以使用 poe.get_device_id 函数或 client.device_id 来检索保存的设备 ID。

>>> poe.get_device_id("UGMlVXqlcLYyMOATMDsKNTMz")
#6d659b04-043a-41f8-97c7-fb7d7fe9ad34

>>> client.device_id
#6d659b04-043a-41f8-97c7-fb7d7fe9ad34
标签:工具分享, ChatGPT