mirror of
https://github.com/lanqian528/chat2api.git
synced 2026-06-13 21:02:46 +08:00
fix repeat history
This commit is contained in:
parent
80eb04d646
commit
269b076de3
13
Dockerfile
13
Dockerfile
@ -1,17 +1,10 @@
|
||||
FROM python:3.11-slim as builder
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt
|
||||
|
||||
FROM python:3.11-slim
|
||||
FROM python:3.11-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY --from=builder /install /usr/local
|
||||
COPY . /app
|
||||
|
||||
COPY . .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
EXPOSE 5005
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
# CHAT2API
|
||||
|
||||
免费的GPT3.5 api
|
||||
🌟无需账号即可使用免费、无限的gpt3.5,目前只能转gpt3.5
|
||||
|
||||
### 注:仅ip属地支持免登录使用ChatGpt可以使用
|
||||
🔍以假乱真,回复格式与真实api完全一致,支持max_tokens,stream等参数
|
||||
|
||||
## Deploy
|
||||
|
||||
@ -52,6 +52,10 @@ curl --location 'http://127.0.0.1:5005/v1/chat/completions' \
|
||||
"stream": true
|
||||
}'
|
||||
```
|
||||
## 常见问题
|
||||
|
||||
- 当返回错误代码`403`时:这意味着当前IP地址被 CF 盾拦截,请尝试更换IP地址,或者在环境变量 `PROXY_URL` 中设置代理。
|
||||
- 来自`Xiaofei`的礼物:将环境变量设置为 `CHATGPT_BASE_URL=http://api.angelxf.me:8080/api` ,可无视CF盾和IP问题。
|
||||
|
||||
## 高级设置
|
||||
|
||||
|
||||
14
chat2api.py
14
chat2api.py
@ -1,12 +1,9 @@
|
||||
import warnings
|
||||
|
||||
from fastapi import FastAPI, Request, Depends
|
||||
from fastapi import FastAPI, Request
|
||||
from fastapi.responses import StreamingResponse, JSONResponse
|
||||
|
||||
from chatgpt.ChatService import ChatService
|
||||
from utils.shared_session import create_shared_async_session
|
||||
|
||||
warnings.filterwarnings('ignore')
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@ -15,13 +12,16 @@ chat_requirements_token_list = []
|
||||
|
||||
|
||||
@app.post("/v1/chat/completions")
|
||||
# async def send_conversation(request: Request, session=Depends(create_shared_async_session)):
|
||||
async def send_conversation(request: Request):
|
||||
data = await request.json()
|
||||
chat_service = ChatService()
|
||||
try:
|
||||
data = await request.json()
|
||||
except Exception:
|
||||
return JSONResponse({"error": "Invalid JSON body"}, status_code=400)
|
||||
try:
|
||||
chat_service = ChatService()
|
||||
await chat_service.get_chat_requirements()
|
||||
except:
|
||||
chat_service = ChatService()
|
||||
await chat_service.get_chat_requirements()
|
||||
chat_service.prepare_send_conversation(data)
|
||||
stream = data.get("stream", False)
|
||||
|
||||
@ -3,9 +3,8 @@ import random
|
||||
import string
|
||||
import time
|
||||
import uuid
|
||||
from contextlib import aclosing
|
||||
|
||||
from curl_cffi import requests
|
||||
import httpx
|
||||
from fastapi import HTTPException
|
||||
|
||||
from api.chat_completions import num_tokens_from_messages, model_system_fingerprint, model_proxy, \
|
||||
@ -18,27 +17,22 @@ async def stream_response(response, model, max_tokens):
|
||||
chat_id = f"chatcmpl-{''.join(random.choice(string.ascii_letters + string.digits) for _ in range(29))}"
|
||||
system_fingerprint_list = model_system_fingerprint.get(model, None)
|
||||
system_fingerprint = random.choice(system_fingerprint_list) if system_fingerprint_list else None
|
||||
created_time = int(time.time())
|
||||
completion_tokens = -1
|
||||
len_last_content = 0
|
||||
end = False
|
||||
status = None
|
||||
async for chunk in response.aiter_lines():
|
||||
if end:
|
||||
yield f"data: [DONE]\n\n"
|
||||
break
|
||||
try:
|
||||
chunk = chunk.decode("utf-8")
|
||||
if chunk == "data: [DONE]":
|
||||
yield f"data: [DONE]\n\n"
|
||||
elif not chunk.startswith("data: "):
|
||||
continue
|
||||
else:
|
||||
chunk_old_data = json.loads(chunk[6:])
|
||||
if chunk_old_data["message"]["status"] == "in_progress":
|
||||
status = "in_progress"
|
||||
if status != "in_progress":
|
||||
continue
|
||||
if not chunk_old_data["message"]["author"]["role"] == "assistant":
|
||||
if not chunk_old_data["message"]["status"] == "in_progress" and not chunk_old_data["message"]["metadata"].get("finish_details", {}):
|
||||
continue
|
||||
content = chunk_old_data["message"]["content"]["parts"][0]
|
||||
if not content:
|
||||
@ -47,7 +41,7 @@ async def stream_response(response, model, max_tokens):
|
||||
delta = {"content": content[len_last_content:]}
|
||||
len_last_content = len(content)
|
||||
finish_reason = None
|
||||
if chunk_old_data["message"]["end_turn"]:
|
||||
if chunk_old_data["message"]["metadata"].get("finish_details", {}):
|
||||
delta = {}
|
||||
finish_reason = "stop"
|
||||
end = True
|
||||
@ -55,13 +49,10 @@ async def stream_response(response, model, max_tokens):
|
||||
delta = {}
|
||||
finish_reason = "length"
|
||||
end = True
|
||||
if completion_tokens > max_tokens:
|
||||
yield f"data: [DONE]\n\n"
|
||||
break
|
||||
chunk_new_data = {
|
||||
"id": chat_id,
|
||||
"object": "chat.completion.chunk",
|
||||
"created": int(time.time()),
|
||||
"created": created_time,
|
||||
"model": model,
|
||||
"choices": [
|
||||
{
|
||||
@ -83,9 +74,10 @@ async def stream_response(response, model, max_tokens):
|
||||
|
||||
async def chat_response(resp, model, prompt_tokens, max_tokens):
|
||||
last_resp = None
|
||||
for i in resp:
|
||||
for i in reversed(resp):
|
||||
if i != "" and i != "data: [DONE]" and i.startswith("data: "):
|
||||
last_resp = i
|
||||
break
|
||||
resp = json.loads(last_resp[6:])
|
||||
|
||||
chat_id = f"chatcmpl-{''.join(random.choice(string.ascii_letters + string.digits) for _ in range(29))}"
|
||||
@ -143,11 +135,7 @@ def api_messages_to_chat(api_messages):
|
||||
|
||||
class ChatService:
|
||||
def __init__(self, session=None):
|
||||
self.session = session
|
||||
self.proxies = {
|
||||
"http": proxy_url,
|
||||
"https": proxy_url,
|
||||
}
|
||||
self.s = httpx.AsyncClient(proxies=proxy_url)
|
||||
self.user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/"
|
||||
self.oai_device_id = str(uuid.uuid4())
|
||||
self.chat_token = None
|
||||
@ -170,16 +158,14 @@ class ChatService:
|
||||
'sec-fetch-site': 'same-origin',
|
||||
'user-agent': self.user_agent
|
||||
}
|
||||
# r = await self.session.post(url, headers=headers, json={}, proxies=self.proxies)
|
||||
async with requests.AsyncSession() as s:
|
||||
r = await s.post(url, headers=headers, json={}, proxies=self.proxies)
|
||||
if r.status_code != 200:
|
||||
raise HTTPException(status_code=r.status_code, detail=r.text)
|
||||
else:
|
||||
self.chat_token = r.json().get('token')
|
||||
if not self.chat_token:
|
||||
raise HTTPException(status_code=500, detail="Chat token not found")
|
||||
return self.chat_token
|
||||
r = await self.s.post(url, headers=headers, json={})
|
||||
if r.status_code != 200:
|
||||
raise HTTPException(status_code=r.status_code, detail=r.text)
|
||||
else:
|
||||
self.chat_token = r.json().get('token')
|
||||
if not self.chat_token:
|
||||
raise HTTPException(status_code=500, detail="Chat token not found")
|
||||
return self.chat_token
|
||||
|
||||
def prepare_send_conversation(self, data):
|
||||
self.headers = {
|
||||
@ -225,21 +211,12 @@ class ChatService:
|
||||
model = model_proxy.get(model, model)
|
||||
max_tokens = data.get("max_tokens", 2147483647)
|
||||
|
||||
# async with aclosing(await self.session.post(url, headers=self.headers, json=self.chat_request, proxies=self.proxies, stream=True)) as r:
|
||||
|
||||
# async with self.session.stream("POST", url, headers=self.headers, json=self.chat_request, proxies=self.proxies) as r:
|
||||
# async for chunk in r.aiter_content():
|
||||
# print("Status: ", r.status_code)
|
||||
# assert r.status_code == 200
|
||||
# print("CHUNK", chunk)
|
||||
# yield chunk
|
||||
|
||||
async with requests.AsyncSession() as s:
|
||||
r = await s.post(url, headers=self.headers, json=self.chat_request, proxies=self.proxies, stream=True)
|
||||
if r.status_code != 200:
|
||||
raise HTTPException(status_code=r.status_code, detail=r.text)
|
||||
async for chunk in stream_response(r, model, max_tokens):
|
||||
yield chunk
|
||||
r = await self.s.send(
|
||||
self.s.build_request("POST", url, headers=self.headers, json=self.chat_request, timeout=600), stream=True)
|
||||
if r.status_code != 200:
|
||||
raise HTTPException(status_code=r.status_code, detail=r.text)
|
||||
async for chunk in stream_response(r, model, max_tokens):
|
||||
yield chunk
|
||||
|
||||
async def send_conversation(self, data):
|
||||
url = f'{chatgpt_base_url}/conversation'
|
||||
@ -249,9 +226,9 @@ class ChatService:
|
||||
prompt_tokens = num_tokens_from_messages(api_messages, model)
|
||||
max_tokens = data.get("max_tokens", 2147483647)
|
||||
|
||||
async with requests.AsyncSession() as s:
|
||||
r = await s.post(url, headers=self.headers, json=self.chat_request, proxies=self.proxies, stream=True)
|
||||
if r.status_code != 200:
|
||||
raise HTTPException(status_code=r.status_code, detail=r.text)
|
||||
resp = (await r.atext()).split("\n")
|
||||
return await chat_response(resp, model, prompt_tokens, max_tokens)
|
||||
r = await self.s.send(
|
||||
self.s.build_request("POST", url, headers=self.headers, json=self.chat_request, timeout=600), stream=False)
|
||||
if r.status_code != 200:
|
||||
raise HTTPException(status_code=r.status_code, detail=r.text)
|
||||
resp = r.text.split("\n")
|
||||
return await chat_response(resp, model, prompt_tokens, max_tokens)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
fastapi
|
||||
curl_cffi
|
||||
httpx
|
||||
uvicorn
|
||||
tiktoken
|
||||
@ -1,23 +0,0 @@
|
||||
import random
|
||||
import time
|
||||
|
||||
from curl_cffi import CurlHttpVersion, requests
|
||||
from curl_cffi.requests import AsyncSession
|
||||
|
||||
|
||||
async def create_shared_async_session():
|
||||
browsers = ["chrome120", "chrome99_android"]
|
||||
selected_browsers = random.choice(browsers)
|
||||
async with AsyncSession(
|
||||
impersonate=selected_browsers,
|
||||
http_version=CurlHttpVersion.V2TLS, timeout=600) as session:
|
||||
yield session
|
||||
|
||||
|
||||
def create_shared_session():
|
||||
random.seed(int(time.time()))
|
||||
browsers = ["chrome120", "chrome99_android"]
|
||||
selected_browsers = random.choice(browsers)
|
||||
session = requests.Session(impersonate=selected_browsers,
|
||||
http_version=CurlHttpVersion.V2TLS, timeout=600)
|
||||
return session
|
||||
Loading…
Reference in New Issue
Block a user