diff --git a/app.py b/app.py index 6b1c302..66126aa 100644 --- a/app.py +++ b/app.py @@ -1,6 +1,8 @@ +import types + from fastapi import FastAPI, Request, Depends, HTTPException -from fastapi.responses import StreamingResponse, JSONResponse from fastapi.middleware.cors import CORSMiddleware +from fastapi.responses import StreamingResponse, JSONResponse from chatgpt.ChatService import ChatService from chatgpt.reverseProxy import chatgpt_reverse_proxy @@ -37,11 +39,11 @@ async def send_conversation(request: Request, token=Depends(verify_token)): chat_service = await async_retry(to_send_conversation, request_data, access_token) chat_service.prepare_send_conversation() - stream = request_data.get("stream", False) - if stream is True: - return StreamingResponse(await chat_service.send_conversation_for_stream(), media_type="text/event-stream") + res = await chat_service.send_conversation() + if isinstance(res, types.AsyncGeneratorType): + return StreamingResponse(res, media_type="text/event-stream") else: - return JSONResponse(await chat_service.send_conversation(), media_type="application/json") + return JSONResponse(res, media_type="application/json") @app.api_route("/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD", "PATCH", "TRACE"]) diff --git a/chatgpt/ChatService.py b/chatgpt/ChatService.py index 35d1e8b..a0717a0 100644 --- a/chatgpt/ChatService.py +++ b/chatgpt/ChatService.py @@ -26,7 +26,6 @@ async def stream_response(service, response, model, max_tokens): last_recipient = None end = False message_id = None - all_text = "" async for chunk in response.aiter_lines(): chunk = chunk.decode("utf-8") if end: @@ -108,7 +107,8 @@ async def stream_response(service, response, model, max_tokens): end = True else: continue - all_text += delta.get("content", "") + if not delta.get("content"): + delta = {"role": "assistant", "content": ""} chunk_new_data = { "id": chat_id, "object": "chat.completion.chunk", @@ -285,6 +285,7 @@ class ChatService: self.access_token = access_token self.oai_device_id = str(uuid.uuid4()) + self.persona = None self.chat_token = None self.arkose_token = None self.arkose_token_url = random.choice(arkose_token_url_list) if arkose_token_url_list else None @@ -320,6 +321,7 @@ class ChatService: r = await self.s.post(url, headers=headers, json={}) if r.status_code == 200: resp = r.json() + self.persona = resp.get("persona") arkose = resp.get('arkose', {}) proofofwork = resp.get('proofofwork', {}) turnstile = resp.get('turnstile', {}) @@ -335,8 +337,10 @@ class ChatService: json={"blob": arkose_dx}, timeout=15 ) - self.arkose_token = r2.json()['token'] - except Exception as e: + r2esp = r2.json() + Logger.info(f"arkose_token: {r2esp}") + self.arkose_token = r2esp.get('token') + except Exception: raise HTTPException(status_code=403, detail="Failed to get Arkose token") proofofwork_required = proofofwork.get('required') @@ -417,33 +421,23 @@ class ChatService: } return self.chat_request - async def send_conversation_for_stream(self): - url = f'{self.base_url}/conversation' - model = model_proxy.get(self.model, self.model) - try: - r = await self.s.post(url, headers=self.headers, json=self.chat_request, timeout=600, stream=True) - if r.status_code == 200: - return stream_response(self, r, model, self.max_tokens) - else: - rtext = await r.atext() - if "application/json" == r.headers.get("Content-Type", ""): - detail = json.loads(rtext).get("detail", json.loads(rtext)) - else: - detail = rtext - if r.status_code != 200: - if r.status_code == 403: - raise HTTPException(status_code=r.status_code, detail="cf-please-wait") - raise HTTPException(status_code=r.status_code, detail=detail) - except HTTPException as e: - raise HTTPException(status_code=e.status_code, detail=str(e)) - async def send_conversation(self): url = f'{self.base_url}/conversation' + if "gpt-4" in self.model and self.persona != "chatgpt-paid": + raise HTTPException(status_code=404, detail={ + "message": f"The model `{self.model}` does not exist or you do not have access to it.", + "type": "invalid_request_error", + "param": None, + "code": "model_not_found" + }) model = model_proxy.get(self.model, self.model) try: + stream = self.data.get("stream", False) r = await self.s.post(url, headers=self.headers, json=self.chat_request, timeout=600, stream=True) - if r.status_code == 200: + if r.status_code == 200 and stream is False: return await chat_response(self, r, self.prompt_tokens, model, self.max_tokens) + elif r.status_code == 200 and stream is True: + return stream_response(self, r, model, self.max_tokens) else: rtext = await r.atext() if "application/json" == r.headers.get("Content-Type", ""): diff --git a/chatgpt/refreshToken.py b/chatgpt/refreshToken.py index 1577359..c52d661 100644 --- a/chatgpt/refreshToken.py +++ b/chatgpt/refreshToken.py @@ -41,6 +41,6 @@ async def chat_refresh(refresh_token): refresh_map[refresh_token] = {"token": access_token, "timestamp": int(time.time())} return access_token else: - raise r.text + raise Exception("Unknown or invalid refresh token.") except Exception as e: - raise HTTPException(status_code=500, detail=str(e)) + raise HTTPException(status_code=401, detail=str(e)) diff --git a/utils/authorization.py b/utils/authorization.py index f1ff94e..4b414d0 100644 --- a/utils/authorization.py +++ b/utils/authorization.py @@ -11,10 +11,14 @@ async def verify_token(token: str = Depends(oauth2_scheme)): if token and token.startswith("eyJhbGciOi"): return token elif token and len(token) == 45: - return await rt2ac(token) + try: + access_token = await rt2ac(token) + return access_token + except HTTPException as e: + raise HTTPException(status_code=e.status_code, detail=e.detail) elif not authorization_list: return token elif token and token in authorization_list: return token else: - raise HTTPException(status_code=401, detail="Not authenticated") + raise HTTPException(status_code=401)