Repository: ultrasev/chatrapper Branch: master Commit: 46633bd3d406 Files: 5 Total size: 7.1 KB Directory structure: gitextract_s8xdcfmo/ ├── LICENCE ├── README.md ├── chatrapper/ │ └── __init__.py ├── pyproject.toml └── tests/ └── __init__.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: LICENCE ================================================ MIT License Copyright (c) 2023-2024 ultrasev Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================

ChatGPT API (W)rapper

把网页版 ChatGPT 封装为一个简单的 API,以便在代码中使用。 > OpenAI 对逆向的限制越来越严格,逆向难度越来越大,且各平台的 API 已经很便宜了,像 Groq 的 Llama 3 API 还一直是免费的,不太建议大家继续研究这类项目了。如果特别需要,可以参考作者的另一个项目 [juchats](https://github.com/ultrasev/juchats),有更多免费模型可以使用。 # Installation ```bash pip3 install git+https://github.com/ultrasev/chatrapper.git ``` # Usage 环境变量中设置 `TOKEN`,然后调用 `chat` 函数即可。 ```bash export TOKEN="eyJhbGci..." ``` 在代码中使用 `Rapper`: ```python import os from chatrapper import Rapper token = os.environ.get("TOKEN") rapper = Rapper( access_token=token model="text-davinci-002-render-sha" ) rapper("鲁迅为什么打周树人?") ``` 或者有异步需求的话,可以使用 `AsyncRapper`。这种情况下,最好有多个账号支持,单账号下,同一时间只支持一轮对话。 ```python import os import asyncio from chatrapper import AsyncRapper token = os.environ.get("TOKEN") rapper = AsyncRapper( access_token=token model="text-davinci-002-render-sha" ) async def main(): print(await rapper("鲁迅为什么打周树人?")) asyncio.run(main()) ``` Demo:
# Notes - 一定要保护好自己的 token,不要泄露给他人。 - 合理使用 API,调用频率不宜过高,树大易招风,避免触发风控。 ================================================ FILE: chatrapper/__init__.py ================================================ #!/usr/bin/env python import asyncio import base64 import json import typing from uuid import uuid4 import httpx import websockets import logging from websockets.exceptions import ConnectionClosedError, ConnectionClosedOK class MessageDeserializer(object): def __init__(self, data: str) -> None: self.data = data.lstrip("data: ").strip() def __str__(self) -> str: try: js = json.loads(self.data) return js['message']['content']['parts'][0] except json.decoder.JSONDecodeError: return "" except KeyError: logging.error(f"Error: {self.data}") return "" class AsyncRapper(object): def __init__(self, access_token: str, model: str = "text-davinci-002-render-sha") -> None: """ API (w)rapper for OpenAI's ChatGPT. Args: access_token (str): ChatGPT access token, acquired from https://chat.openai.com/api/auth/session model (str): model name, options include: - "text-davinci-002-render-sha", default model for ChatGPT-3.5 - "GPT-4", GPT-4 model """ self.access_token = access_token self.model = model async def _stream_from_wss(self, chunk: str) -> typing.AsyncGenerator[str, None]: url = json.loads(chunk)['wss_url'] async with websockets.connect(url) as websocket: while True: try: response = await websocket.recv() body = json.loads(response)["body"] body = base64.b64decode(body).decode('utf-8') if 'DONE' in body: break yield body except ConnectionClosedOK: break except ConnectionClosedError: break async def stream(self, text: str) -> typing.AsyncGenerator[str, None]: body = { "action": "next", "arkose_token": "null", "conversation_mode": {"kind": "primary_assistant"}, "force_paragen": False, "force_rate_limit": False, "history_and_training_disabled": True, "messages": [{ "metadata": {}, "author": { "role": "user" }, "content": { "content_type": "text", "parts": [text] } }], "model": self.model, "parent_message_id": str(uuid4()), "timezone_offset_min": -330, "stream": True } async with httpx.AsyncClient() as client: async with client.stream( 'POST', url="https://chat.openai.com/backend-api/conversation", headers={ "accept": "text/event-stream", "accept-language": "en-US", "authorization": f"Bearer {self.access_token}", "content-type": "application/json", "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-origin", "Referer": "https://chat.openai.com/", "Referrer-Policy": "strict-origin-when-cross-origin", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36" }, data=json.dumps(body)) as response: async for chunk in response.aiter_text(): chunk = chunk.lstrip("data: ").strip() if "wss_url" in chunk: async for x in self._stream_from_wss(chunk): yield str(MessageDeserializer(x)) else: yield str(MessageDeserializer(chunk)) async def __call__(self, text: str) -> str: prev = "" async for x in self.stream(text): print(x.replace(prev, ""), end="", flush=True) prev = max(prev, x, key=len) return prev class Rapper(object): def __init__(self, access_token: str, model: str = "text-davinci-002-render-sha") -> None: self._proxy = AsyncRapper(access_token, model) def __call__(self, text: str) -> str: return asyncio.run(self._proxy(text)) ================================================ FILE: pyproject.toml ================================================ [tool.poetry] name = "chatrapper" version = "0.1.0" description = "" authors = ["ultrasev "] readme = "README.md" packages = [{include = "chatrapper"}] [tool.poetry.dependencies] python = "^3.8" uuid = "^1.30" httpx = "^0.27.0" websockets = "^12.0" [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" ================================================ FILE: tests/__init__.py ================================================