XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 1
返回提交历史

XFEstudio/gpt4free

Add upload image support in You

98c7b5ed
Heiner Lohaus <hlohaus@users.noreply.github.com>
提交于

代码差异

1 个文件 +105 -50
Modified g4f/Provider/You.py +105 -50
@@ -3,67 +3,114 @@ from __future__ import annotations
3 3 import json
4 4 import base64
5 5 import uuid
6 from aiohttp import ClientSession, FormData
6 7
7 from ..requests import StreamSession
8 from ..typing import AsyncGenerator, Messages
9 from .base_provider import AsyncGeneratorProvider, format_prompt
10
8 from ..typing import AsyncGenerator, Messages, ImageType, Cookies
9 from .base_provider import AsyncGeneratorProvider
10 from .helper import get_connector, format_prompt
11 from ..image import to_bytes
12 from ..defaults import DEFAULT_HEADERS
11 13
12 14 class You(AsyncGeneratorProvider):
13 15 url = "https://you.com"
14 16 working = True
15 17 supports_gpt_35_turbo = True
16 18 supports_gpt_4 = True
17 _session_used = 0
18 _session_token = None
19 _cookies = None
20 _cookies_used = 0
19 21
20 22 @classmethod
21 23 async def create_async_generator(
22 24 cls,
23 25 model: str,
24 26 messages: Messages,
27 image: ImageType = None,
28 image_name: str = None,
25 29 proxy: str = None,
26 timeout: int = 120,
30 chat_mode: str = "default",
27 31 **kwargs,
28 32 ) -> AsyncGenerator:
29 async with StreamSession(proxies={"https": proxy}, impersonate="chrome107", timeout=timeout) as session:
33 async with ClientSession(
34 connector=get_connector(kwargs.get("connector"), proxy),
35 headers=DEFAULT_HEADERS
36 ) as client:
37 if image:
38 chat_mode = "agent"
39 elif model == "gpt-4":
40 chat_mode = model
41 cookies = await cls.get_cookies(client) if chat_mode != "default" else None
42 upload = json.dumps([await cls.upload_file(client, cookies, to_bytes(image), image_name)]) if image else ""
43 #questions = [message["content"] for message in messages if message["role"] == "user"]
44 # chat = [
45 # {"question": questions[idx-1], "answer": message["content"]}
46 # for idx, message in enumerate(messages)
47 # if message["role"] == "assistant"
48 # and idx < len(questions)
49 # ]
30 50 headers = {
31 51 "Accept": "text/event-stream",
32 52 "Referer": f"{cls.url}/search?fromSearchBar=true&tbm=youchat",
33 53 }
34 54 data = {
55 "userFiles": upload,
56 "selectedChatMode": chat_mode,
35 57 "q": format_prompt(messages),
36 58 "domain": "youchat",
37 "chat": "", "selectedChatMode": "gpt-4" if model == "gpt-4" else "default"
59 #"chat": json.dumps(chat),
38 60 }
39 async with session.get(
61 async with client.post(
40 62 f"{cls.url}/api/streamingSearch",
41 params=data,
63 data=data,
42 64 headers=headers,
43 cookies=cls.get_cookies(await cls.get_session_token(proxy, timeout)) if model == "gpt-4" else None
65 cookies=cookies
44 66 ) as response:
45 67 response.raise_for_status()
46 start = b'data: {"youChatToken": '
47 async for line in response.iter_lines():
48 if line.startswith(start):
49 yield json.loads(line[len(start):-1])
68 async for line in response.content:
69 if line.startswith(b'event: '):
70 event = line[7:-1]
71 elif line.startswith(b'data: '):
72 if event == b"youChatUpdate" or event == b"youChatToken":
73 data = json.loads(line[6:-1])
74 if event == b"youChatToken" and "youChatToken" in data:
75 yield data["youChatToken"]
76 elif event == b"youChatUpdate" and "t" in data:
77 yield data["t"]
50 78
51 79 @classmethod
52 async def get_session_token(cls, proxy: str, timeout: int):
53 if not cls._session_token or cls._session_used >= 5:
54 cls._session_token = await cls.create_session_token(proxy, timeout)
55 cls._session_used += 1
56 return cls._session_token
80 async def upload_file(cls, client: ClientSession, cookies: Cookies, file: bytes, filename: str = None) -> dict:
81 async with client.get(
82 f"{cls.url}/api/get_nonce",
83 cookies=cookies,
84 ) as response:
85 response.raise_for_status()
86 upload_nonce = await response.text()
87 data = FormData()
88 data.add_field('file', file, filename=filename)
89 async with client.post(
90 f"{cls.url}/api/upload",
91 data=data,
92 headers={
93 "X-Upload-Nonce": upload_nonce,
94 },
95 cookies=cookies
96 ) as response:
97 if not response.ok:
98 raise RuntimeError(f"Response: {await response.text()}")
99 result = await response.json()
100 result["user_filename"] = filename
101 result["size"] = len(file)
102 return result
57 103
58 def get_cookies(access_token: str, session_jwt: str = "0"):
59 return {
60 'stytch_session_jwt': session_jwt,
61 'ydc_stytch_session': access_token,
62 'ydc_stytch_session_jwt': session_jwt
63 }
104 @classmethod
105 async def get_cookies(cls, client: ClientSession) -> Cookies:
106 if not cls._cookies or cls._cookies_used >= 5:
107 cls._cookies = await cls.create_cookies(client)
108 cls._cookies_used = 0
109 cls._cookies_used += 1
110 return cls._cookies
64 111
65 112 @classmethod
66 def get_jwt(cls):
113 def get_sdk(cls) -> str:
67 114 return base64.standard_b64encode(json.dumps({
68 115 "event_id":f"event-id-{str(uuid.uuid4())}",
69 116 "app_session_id":f"app-session-id-{str(uuid.uuid4())}",
@@ -75,26 +122,34 @@ class You(AsyncGeneratorProvider):
75 122 "sdk":{"identifier":"Stytch.js Javascript SDK","version":"3.3.0"
76 123 }}).encode()).decode()
77 124
125 def get_auth() -> str:
126 auth_uuid = "507a52ad-7e69-496b-aee0-1c9863c7c8"
127 auth_token = f"public-token-live-{auth_uuid}bb:public-token-live-{auth_uuid}19"
128 auth = base64.standard_b64encode(auth_token.encode()).decode()
129 return f"Basic {auth}",
130
78 131 @classmethod
79 async def create_session_token(cls, proxy: str, timeout: int):
80 async with StreamSession(proxies={"https": proxy}, impersonate="chrome110", timeout=timeout) as session:
81 user_uuid = str(uuid.uuid4())
82 auth_uuid = "507a52ad-7e69-496b-aee0-1c9863c7c8"
83 auth_token = f"public-token-live-{auth_uuid}bb:public-token-live-{auth_uuid}19"
84 auth = base64.standard_b64encode(auth_token.encode()).decode()
85 async with session.post(
86 "https://web.stytch.com/sdk/v1/passwords",
87 headers={
88 "Authorization": f"Basic {auth}",
89 "X-SDK-Client": cls.get_jwt(),
90 "X-SDK-Parent-Host": "https://you.com"
91 },
92 json={
93 "email": f"{user_uuid}@gmail.com",
94 "password": f"{user_uuid}#{user_uuid}",
95 "session_duration_minutes": 129600
96 }
97 ) as response:
98 if not response.ok:
99 raise RuntimeError(f"Response: {await response.text()}")
100 return (await response.json())["data"]["session_token"]
132 async def create_cookies(cls, client: ClientSession) -> Cookies:
133 user_uuid = str(uuid.uuid4())
134 async with client.post(
135 "https://web.stytch.com/sdk/v1/passwords",
136 headers={
137 "Authorization": cls.get_auth(),
138 "X-SDK-Client": cls.get_sdk(),
139 "X-SDK-Parent-Host": cls.url
140 },
141 json={
142 "email": f"{user_uuid}@gmail.com",
143 "password": f"{user_uuid}#{user_uuid}",
144 "session_duration_minutes": 129600
145 }
146 ) as response:
147 if not response.ok:
148 raise RuntimeError(f"Response: {await response.text()}")
149 session = (await response.json())["data"]
150 return {
151 "stytch_session": session["session_token"],
152 'stytch_session_jwt': session["session_jwt"],
153 'ydc_stytch_session': session["session_token"],
154 'ydc_stytch_session_jwt': session["session_jwt"],
155 }