Eitan177's picture
Upload 5 files
007bea3
from os import listdir
from uuid import uuid4
from time import sleep, time
from threading import Thread
from json import loads, dumps
from random import getrandbits
from websocket import WebSocketApp
from requests import Session, get, post
class Labs:
def __init__(self) -> None:
self.history: list = []
self.session: Session = Session()
self.user_agent: dict = { "User-Agent": "Ask/2.2.1/334 (iOS; iPhone) isiOSOnMac/false", "X-Client-Name": "Perplexity-iOS" }
self.session.headers.update(self.user_agent)
self._init_session_without_login()
self.t: str = self._get_t()
self.sid: str = self._get_sid()
self.queue: list = []
self.finished: bool = True
assert self._ask_anonymous_user(), "failed to ask anonymous user"
self.ws: WebSocketApp = self._init_websocket()
self.ws_thread: Thread = Thread(target=self.ws.run_forever).start()
self._auth_session()
while not (self.ws.sock and self.ws.sock.connected):
sleep(0.01)
def _init_session_without_login(self) -> None:
self.session.get(url=f"https://www.perplexity.ai/search/{str(uuid4())}")
self.session.headers.update(self.user_agent)
def _auth_session(self) -> None:
self.session.get(url="https://www.perplexity.ai/api/auth/session")
def _get_t(self) -> str:
return format(getrandbits(32), "08x")
def _get_sid(self) -> str:
return loads(self.session.get(
url=f"https://labs-api.perplexity.ai/socket.io/?transport=polling&EIO=4"
).text[1:])["sid"]
def _ask_anonymous_user(self) -> bool:
response = self.session.post(
url=f"https://labs-api.perplexity.ai/socket.io/?EIO=4&transport=polling&t={self.t}&sid={self.sid}",
data="40{\"jwt\":\"anonymous-ask-user\"}"
).text
return response == "OK"
def _get_cookies_str(self) -> str:
cookies = ""
for key, value in self.session.cookies.get_dict().items():
cookies += f"{key}={value}; "
return cookies[:-2]
def _init_websocket(self) -> WebSocketApp:
def on_open(ws: WebSocketApp) -> None:
ws.send("2probe")
ws.send("5")
def on_message(ws: WebSocketApp, message: str) -> None:
if message == "2":
ws.send("3")
elif message.startswith("42"):
message = loads(message[2:])[1]
if "status" not in message:
self.queue.append(message)
elif message["status"] == "completed":
self.finished = True
self.history.append({"role": "assistant", "content": message["output"], "priority": 0})
elif message["status"] == "failed":
self.finished = True
headers: dict = self.user_agent
headers["Cookie"] = self._get_cookies_str()
return WebSocketApp(
url=f"wss://labs-api.perplexity.ai/socket.io/?EIO=4&transport=websocket&sid={self.sid}",
header=headers,
on_open=on_open,
on_message=on_message,
on_error=lambda ws, err: print(f"websocket error: {err}")
)
def _c(self, prompt: str, model: str) -> dict:
assert self.finished, "already searching"
assert model in ["codellama-34b-instruct", "llama-2-7b-chat", "llama-2-13b-chat", "llama-2-70b-chat", "mistral-7b-instruct", "pplx-70b-chat"]
self.finished = False
self.history.append({"role": "user", "content": prompt, "priority": 0})
self.ws.send("42[\"perplexity_playground\",{\"version\":\"2.1\",\"source\":\"default\",\"model\":\"" + model + "\",\"messages\":" + dumps(self.history) + "}]")
def chat(self, prompt: str, model: str = "llama-2-7b-chat") -> dict:
self._c(prompt, model)
while (not self.finished) or (len(self.queue) != 0):
if len(self.queue) > 0:
yield self.queue.pop(0)
def chat_sync(self, prompt: str, model: str = "llama-2-7b-chat") -> dict:
self._c(prompt, model)
while not self.finished:
pass
return self.queue.pop(-1)
def close(self) -> None:
self.ws.close()