mirror of
https://github.com/lanqian528/chat2api.git
synced 2026-06-13 21:02:46 +08:00
delete authorization
This commit is contained in:
parent
c2d3f9fbc5
commit
15d59178da
@ -1,7 +1,7 @@
|
||||
API_PREFIX=your_prefix
|
||||
AUTHORIZATION=your_first_key, your_second_key
|
||||
CHATGPT_BASE_URL=https://chat.openai.com
|
||||
CHATGPT_BASE_URL=https://chatgpt.com
|
||||
HISTORY_DISABLED=true
|
||||
PROXY_URL=your_first_proxy, your_second_proxy
|
||||
ARKOSE_TOKEN_URL=https://arkose.example.com/token
|
||||
POW_DIFFICULTY=4
|
||||
RETRY_TIMES=3
|
||||
|
||||
2
.github/workflows/build_docker.yml
vendored
2
.github/workflows/build_docker.yml
vendored
@ -35,7 +35,7 @@ jobs:
|
||||
images: lanqian528/chat2api
|
||||
tags: |
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
type=raw,value=v1.0.0
|
||||
type=raw,value=v1.0.1
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
|
||||
82
README.md
82
README.md
@ -4,36 +4,26 @@
|
||||
|
||||
🌟 无需账号即可使用免费、无限的 `GPT-3.5`
|
||||
|
||||
💥 支持AccessToken使用账号,支持 `GPT-4`、`GPT-4o`
|
||||
💥 支持AccessToken使用账号,支持 `GPT-4`、`GPT-4o`、 `GPTs`
|
||||
|
||||
🔍 回复格式与真实api完全一致,适配几乎所有客户端
|
||||
|
||||
## 交流群
|
||||
|
||||
https://t.me/chat2api
|
||||
https://t.me/chat2api 要提问请先阅读完仓库介绍
|
||||
|
||||
## 功能
|
||||
|
||||
> 已完成
|
||||
> - [x] 免登录 GPT3.5
|
||||
> - [x] 使用 AccessToken
|
||||
> - [x] GPT3.5 对话 (传入模型名不包含gpt-4,则默认使用gpt-3.5,也就是text-davinci-002-render-sha)
|
||||
> - [x] GPT4.0 对话 (传入模型名包含: gpt-4,gpt-4o,gpt-4-moblie 即可使用对应模型)
|
||||
> - [x] Tokens 计算
|
||||
> - [x] Stream 流式传输
|
||||
> - [x] 配置 PROXY 代理
|
||||
> - [x] 配置 BASE_URL
|
||||
> - [x] 外置 ArkoseToken
|
||||
> - [x] 使用 RefreshToken 代替 AccessToken
|
||||
> - [x] 反向代理 UI (http://127.0.0.1:5005, 不支持登录使用)
|
||||
> - [x] GPT4.0 画图、工具 (beta)
|
||||
> - [x] 支持 WSS (beta)
|
||||
> - [x] 返回 conversation_id (beta)
|
||||
> - [x] 免登录 GPT3.5 对话
|
||||
> - [x] GPT-3.5 对话 (传入模型名不包含gpt-4,则默认使用gpt-3.5,也就是text-davinci-002-render-sha)
|
||||
> - [x] GPT-4 对话 (传入模型名包含: gpt-4,gpt-4o,gpt-4-moblie 即可使用对应模型, 需传入AccessToken)
|
||||
> - [x] GPT-4 画图、代码、联网
|
||||
> - [x] 支持GPTs (传入模型名:gpt-4-gizmo-g-*)
|
||||
> - [x] 上传图片、文件 (格式为API对应格式,支持url和base64)
|
||||
> - [x] 反向代理 UI (http://127.0.0.1:5005, 不支持登录使用)
|
||||
|
||||
> TODO
|
||||
> - [ ] claude2api
|
||||
> - [ ] 暂无,欢迎提 issue
|
||||
|
||||
## 部署
|
||||
@ -91,28 +81,24 @@ docker-compose up -d
|
||||
http://127.0.0.1:5005
|
||||
```
|
||||
|
||||
- 使用 API , 支持传入 AccessToken 或 RefreshToken, 可用 GPT4.0:
|
||||
- 使用 API , 支持传入 AccessToken 或 RefreshToken, 可用 GPT-4, GPT-4o, GPTs:
|
||||
|
||||
```bash
|
||||
curl --location 'http://127.0.0.1:5005/v1/chat/completions' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer {{Token}}' \
|
||||
--data '{
|
||||
"model": "gpt-3.5-turbo",
|
||||
"messages": [{"role": "user", "content": "Say this is a test!"}],
|
||||
"stream": true
|
||||
}'
|
||||
```
|
||||
> `Token` 处填写你账号的 `AccessToken` 或 `RefreshToken`
|
||||
> - `AccessToken` 获取: chatgpt官网登录后,再打开 https://chatgpt.com/api/auth/session 获取 `accessToken` 这个值
|
||||
> - 免登录 gpt3.5 无需传入 Token
|
||||
|
||||
## 常见问题
|
||||
|
||||
> - 错误代码:
|
||||
> - `401`:当前IP不支持免登录,请尝试更换IP地址,或者在环境变量 `PROXY_URL` 中设置代理。
|
||||
> - `403`:当前IP地址被 CF 盾拦截,请尝试更换IP地址,或者在环境变量 `PROXY_URL` 中设置代理。
|
||||
> - `429`:当前IP请求1小时内请求超过限制,请稍后再试,或更换ip。
|
||||
> - `500`:服务器内部错误,请求失败。
|
||||
> - `502`:服务器网关错误,或网络不可用,请尝试更换网络环境。
|
||||
|
||||
## 使用GPT4
|
||||
## ArkoseToken
|
||||
|
||||
> #### 目前支持外部服务提供 ArkoseToken
|
||||
>
|
||||
@ -127,34 +113,50 @@ curl --location 'http://127.0.0.1:5005/v1/chat/completions' \
|
||||
- 请求体:
|
||||
|
||||
```request body
|
||||
{
|
||||
"blob": "rFYaxQNEApDlx/Db.KyrE79pAAFBs70CYtbM4pMNUsc7jIkLGdiDs7vziHRGe78bqWXDo0AYyq2A10qIlcTt89lBYXJqCbONC/nD8C199pEZ/c9ocVKKtM27jZQ7fyOpWd9p5qjKeXT4xEGBFpoE3Re1DwdQeijYp7VMJQyw7RYN+IDB1QEx3aKSO6aTI+ivnhw9ztfn/p1SkvAyyOhur/ArF08WQ+rXQpxpttaSQlzMsIwlYbuUUuYE2f9JrQaYG7qip1DKvju111P6wTNy4QVlMXG32VrzaOWh4nmQ0lOcZ1DmN6u2aeJZotffHV2zOOQAqqnParidTbN+qFre2t77ZwBuGKGqLyT8LeOp02GdFwcyw0kkeX+L7vwYAzBpjA5ky0r0X+i8HpzWt8QCyWzEW9kHn9LLCTwg2MOumzjb66Ad4WDe+C1bAcOKuEyXiYh+a1cWZAOdzEuxEg90yCfI7DZR94BsoDR85gEC/Og88i098u5HV7hZZEOQ6J8fmi68FSyPkN7oLCmBsZCMAZqzapNP/MkeIMExrdw7Jf/PtMrZN4bwM56mWfyIJf5h/zXu8PUajVwE9Pj/M5VtB0spZg49JNeHExosVCAB0C0JW+T8vEIwoqiY4pRQ0lbMHTQZFpU2xURTgcgh+m6g1SEYR1FY3de1XnzfiTQq1RTNJPydj5xpt6r6okr8yIJdRhmVXlQI+pS7vi3+Lls2hnpr7L+l1mcUIMPZNBCs3AUFJNpp6SwQjZkPvKggg1p+uS6PdvKRizM9O9+FKc103AhuSia8KTrvU8tWhBhCzIHCD4LNfnkjuBWSdbDttva4AEXUoPuKkQCWaBzq4lQPUIHFOM9HmNe738vVkNdAuOYffxDNegcpIxLVgZGfbgLQ="
|
||||
}
|
||||
{"blob": "rFYaxQNEApDlx/Db.KyrE79pAAFBs70CYtbM4pMNUsc7jIkLGdiDs7vziHRGe78bqWXDo0AYyq2A10qIlcTt89lBYXJqCbONC/nD8C199pEZ/c9ocVKKtM27jZQ7fyOpWd9p5qjKeXT4xEGBFpoE3Re1DwdQeijYp7VMJQyw7RYN+IDB1QEx3aKSO6aTI+ivnhw9ztfn/p1SkvAyyOhur/ArF08WQ+rXQpxpttaSQlzMsIwlYbuUUuYE2f9JrQaYG7qip1DKvju111P6wTNy4QVlMXG32VrzaOWh4nmQ0lOcZ1DmN6u2aeJZotffHV2zOOQAqqnParidTbN+qFre2t77ZwBuGKGqLyT8LeOp02GdFwcyw0kkeX+L7vwYAzBpjA5ky0r0X+i8HpzWt8QCyWzEW9kHn9LLCTwg2MOumzjb66Ad4WDe+C1bAcOKuEyXiYh+a1cWZAOdzEuxEg90yCfI7DZR94BsoDR85gEC/Og88i098u5HV7hZZEOQ6J8fmi68FSyPkN7oLCmBsZCMAZqzapNP/MkeIMExrdw7Jf/PtMrZN4bwM56mWfyIJf5h/zXu8PUajVwE9Pj/M5VtB0spZg49JNeHExosVCAB0C0JW+T8vEIwoqiY4pRQ0lbMHTQZFpU2xURTgcgh+m6g1SEYR1FY3de1XnzfiTQq1RTNJPydj5xpt6r6okr8yIJdRhmVXlQI+pS7vi3+Lls2hnpr7L+l1mcUIMPZNBCs3AUFJNpp6SwQjZkPvKggg1p+uS6PdvKRizM9O9+FKc103AhuSia8KTrvU8tWhBhCzIHCD4LNfnkjuBWSdbDttva4AEXUoPuKkQCWaBzq4lQPUIHFOM9HmNe738vVkNdAuOYffxDNegcpIxLVgZGfbgLQ="}
|
||||
```
|
||||
|
||||
- 响应体:
|
||||
|
||||
```response body
|
||||
{
|
||||
"token": "45017c7bb17115f36.7290869304|r=ap-southeast-1|meta=3|metabgclr=transparent|metaiconclr=%23757575|guitextcolor=%23000000|pk=0A1D34FC-659D-4E23-B17B-694DCFCF6A6C|at=40|sup=1|rid=3|ag=101|cdn_url=https%3A%2F%2Ftcr9i.openai.com%2Fcdn%2Ffc|lurl=https%3A%2F%2Faudio-ap-southeast-1.arkoselabs.com|surl=https%3A%2F%2Ftcr9i.openai.com|smurl=https%3A%2F%2Ftcr9i.openai.com%2Fcdn%2Ffc%2Fassets%2Fstyle-manager"
|
||||
}
|
||||
{"token": "45017c7bb17115f36.7290869304|r=ap-southeast-1|meta=3|metabgclr=transparent|metaiconclr=%23757575|guitextcolor=%23000000|pk=0A1D34FC-659D-4E23-B17B-694DCFCF6A6C|at=40|sup=1|rid=3|ag=101|cdn_url=https%3A%2F%2Ftcr9i.openai.com%2Fcdn%2Ffc|lurl=https%3A%2F%2Faudio-ap-southeast-1.arkoselabs.com|surl=https%3A%2F%2Ftcr9i.openai.com|smurl=https%3A%2F%2Ftcr9i.openai.com%2Fcdn%2Ffc%2Fassets%2Fstyle-manager"}
|
||||
```
|
||||
|
||||
## 高级设置
|
||||
|
||||
默认情况都不需要设置,除非你有需求
|
||||
|
||||
### 环境变量
|
||||
## 常见问题
|
||||
|
||||
每个环境变量都有默认值,如果不懂环境变量的含义,请不要设置
|
||||
> - 错误代码:
|
||||
> - `401`:当前IP不支持免登录,请尝试更换IP地址,或者在环境变量 `PROXY_URL` 中设置代理。
|
||||
> - `403`:请在日志中查看具体报错信息
|
||||
> - `429`:当前IP请求1小时内请求超过限制,请稍后再试,或更换ip。
|
||||
> - `500`:服务器内部错误,请求失败。
|
||||
> - `502`:服务器网关错误,或网络不可用,请尝试更换网络环境。
|
||||
|
||||
> - 已知情况:
|
||||
> - 日本IP很多不支持免登,免登3.5建议使用美国IP
|
||||
> - 99%的账号都支持免费 `GPT-4o` ,但根据IP地区开启,目前日本和新加坡IP已知开启概率较大
|
||||
|
||||
> - AccessToken 如何获取?
|
||||
> - chatgpt官网登录后,再打开 https://chatgpt.com/api/auth/session 获取 `accessToken` 这个值
|
||||
> - PLUS账号报错`403`?
|
||||
> - PLUS账号需要配置 `ArkoseToken`,请根据上文进行配置
|
||||
> - ArkoseToken 是什么,怎么获取?
|
||||
> - 请参考上文的说明,更多请参考 https://www.arkoselabs.com/
|
||||
|
||||
|
||||
|
||||
## 环境变量
|
||||
|
||||
每个环境变量都有默认值,如果不懂环境变量的含义,请不要设置,更不要传空值
|
||||
|
||||
```
|
||||
API_PREFIX=your_prefix // API前缀,设置后需请求 http://127.0.0.1:5005/your_prefix/v1/chat/completions
|
||||
AUTHORIZATION=your_first_key, your_second_key // 使用免登3.5的Bearer token,不设置则无需Bearer token (不是 AccessToken)
|
||||
CHATGPT_BASE_URL=https://chat.openai.com // ChatGPT网关地址,设置后会改变请求的网站,多个网关用逗号分隔
|
||||
API_PREFIX=your_prefix // API前缀,设置后需请求 /your_prefix/v1/chat/completions
|
||||
CHATGPT_BASE_URL=https://chatgpt.com // ChatGPT网关地址,设置后会改变请求的网站,多个网关用逗号分隔
|
||||
HISTORY_DISABLED=true // 是否不保存聊天记录并返回 conversation_id,true为不保存且不返回
|
||||
PROXY_URL=your_first_proxy, your_second_proxy // 代理url,多个代理用逗号分隔
|
||||
ARKOSE_TOKEN_URL=https://arkose.example.com/token // 获取Arkose token的地址,上文有提供说明
|
||||
POW_DIFFICULTY=4 // 要解决的工作量证明难度,数值越大,计算时间越长,建议3或者4
|
||||
RETRY_TIMES=3 // 出错重试次数
|
||||
```
|
||||
|
||||
|
||||
5
app.py
5
app.py
@ -36,15 +36,12 @@ async def to_send_conversation(request_data, access_token):
|
||||
|
||||
@app.post(f"/{api_prefix}/v1/chat/completions" if api_prefix else "/v1/chat/completions")
|
||||
async def send_conversation(request: Request, token=Depends(verify_token)):
|
||||
access_token = None
|
||||
if token and (token.startswith("eyJhbGciOi") or token.startswith("fk-")):
|
||||
access_token = token
|
||||
try:
|
||||
request_data = await request.json()
|
||||
except Exception:
|
||||
raise HTTPException(status_code=400, detail={"error": "Invalid JSON body"})
|
||||
|
||||
chat_service = await async_retry(to_send_conversation, request_data, access_token)
|
||||
chat_service = await async_retry(to_send_conversation, request_data, token)
|
||||
try:
|
||||
await chat_service.prepare_send_conversation()
|
||||
res = await chat_service.send_conversation()
|
||||
|
||||
@ -51,7 +51,6 @@ class ChatService:
|
||||
self.chat_headers = None
|
||||
self.chat_request = None
|
||||
|
||||
self.s.session.cookies.set("__Secure-next-auth.callback-url", "https%3A%2F%2Fchatgpt.com;", secure=True)
|
||||
self.base_headers = {
|
||||
'Accept': '*/*',
|
||||
'Accept-Encoding': 'gzip, deflate, br, zstd',
|
||||
@ -76,6 +75,9 @@ class ChatService:
|
||||
else:
|
||||
self.base_url = self.host_url + "/backend-anon"
|
||||
|
||||
await get_dpl(self)
|
||||
self.s.session.cookies.set("__Secure-next-auth.callback-url", "https%3A%2F%2Fchatgpt.com;", domain=self.host_url.split("://")[1], secure=True)
|
||||
|
||||
async def get_wss_url(self):
|
||||
url = f'{self.base_url}/register-websocket'
|
||||
headers = self.base_headers.copy()
|
||||
@ -95,7 +97,6 @@ class ChatService:
|
||||
url = f'{self.base_url}/sentinel/chat-requirements'
|
||||
headers = self.base_headers.copy()
|
||||
try:
|
||||
await get_dpl(self)
|
||||
config = get_config(self.user_agent)
|
||||
data = {'p': get_requirements_token(config)}
|
||||
r = await self.s.post(url, headers=headers, json=data, timeout=5)
|
||||
|
||||
@ -294,7 +294,7 @@ async def get_dpl(service):
|
||||
return True
|
||||
headers = service.base_headers.copy()
|
||||
try:
|
||||
r = await service.s.get(f"{service.host_url}/?oai-dm=1", headers=headers)
|
||||
r = await service.s.get(f"{service.host_url}/?oai-dm=1", headers=headers, timeout=5)
|
||||
r.raise_for_status()
|
||||
parser = ScriptSrcParser()
|
||||
parser.feed(r.text)
|
||||
|
||||
@ -20,6 +20,6 @@ async def verify_token(token: str = Depends(oauth2_scheme)):
|
||||
elif not authorization_list:
|
||||
return token
|
||||
elif token and token in authorization_list:
|
||||
return token
|
||||
return None
|
||||
else:
|
||||
raise HTTPException(status_code=401)
|
||||
|
||||
@ -23,7 +23,7 @@ arkose_token_url = os.getenv('ARKOSE_TOKEN_URL', '').replace(' ', '')
|
||||
proxy_url = os.getenv('PROXY_URL', '').replace(' ', '')
|
||||
history_disabled_str = os.getenv('HISTORY_DISABLED', 'true').replace(' ', '')
|
||||
history_disabled = is_true(history_disabled_str)
|
||||
pow_difficulty = int(os.getenv('POW_DIFFICULTY', 3))
|
||||
pow_difficulty = int(os.getenv('POW_DIFFICULTY', 4))
|
||||
retry_times = int(os.getenv('RETRY_TIMES', 3))
|
||||
|
||||
authorization_list = authorization.split(',') if authorization else []
|
||||
@ -32,7 +32,7 @@ arkose_token_url_list = arkose_token_url.split(',') if arkose_token_url else []
|
||||
proxy_url_list = proxy_url.split(',') if proxy_url else []
|
||||
|
||||
logger.info("-" * 60)
|
||||
logger.info("Chat2Api v1.0.0 | https://github.com/lanqian528/chat2api")
|
||||
logger.info("Chat2Api v1.0.1 | https://github.com/lanqian528/chat2api")
|
||||
logger.info("-" * 60)
|
||||
logger.info("Environment variables:")
|
||||
logger.info("API_PREFIX: " + str(api_prefix))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user