|
|
from flask import Flask, Response, request |
|
|
import requests |
|
|
import uuid |
|
|
from datetime import datetime |
|
|
import json |
|
|
from flask_cors import CORS |
|
|
import re |
|
|
import random |
|
|
import string |
|
|
|
|
|
proxy = None |
|
|
ua = 'Mozilla/5.0 (Windows NT 5.0) AppleWebKit/534.2 (KHTML, like Gecko) Chrome/59.0.865.0 Safari/534.2' |
|
|
|
|
|
|
|
|
if proxy: |
|
|
proxies = {'http':proxy,'https':proxy} |
|
|
else: |
|
|
proxies = None |
|
|
|
|
|
models = ['gpt_4', 'gpt_4_turbo', 'gpt_4o', 'claude_2', 'claude_3_opus', 'claude_3_sonnet', 'claude_3_haiku', 'gemini_pro', 'gemini_1_5_pro', 'databricks_dbrx_instruct', 'command_r', 'command_r_plus', 'zephyr', 'claude_3_opus_2k'] |
|
|
|
|
|
headers = { |
|
|
'User-Agent': ua, |
|
|
'Accept': 'text/event-stream', |
|
|
'Referer': 'https://you.com/', |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
app = Flask(__name__) |
|
|
CORS(app) |
|
|
|
|
|
def update_files(content, cookies): |
|
|
response = requests.get('https://you.com/api/get_nonce', cookies=cookies, headers=headers, proxies=proxies) |
|
|
boundary = '----MyCustomBoundary' + ''.join(random.choices(string.ascii_letters + string.digits, k=16)) |
|
|
user_filename = f'{"".join(random.choices(string.ascii_letters + string.digits, k=5))}.txt' |
|
|
multipart_data = ( |
|
|
'--' + boundary + '\r\n' + |
|
|
f'Content-Disposition: form-data; name="file"; filename={user_filename}\r\n' + |
|
|
'Content-Type: text/plain\r\n\r\n' + |
|
|
content |
|
|
+'\r\n' |
|
|
'--' + boundary + '--' |
|
|
) |
|
|
headers123 = { |
|
|
'User-Agent': ua, |
|
|
'Accept': 'text/event-stream', |
|
|
'Referer': 'https://you.com/', |
|
|
'accept': 'multipart/form-data', |
|
|
'accept-language': 'cmn', |
|
|
'content-type': 'multipart/form-data; boundary=' + boundary, |
|
|
'x-upload-nonce': response.text, |
|
|
'Content-Length': str(len(content.encode('utf-8'))), |
|
|
} |
|
|
response = requests.post('https://you.com/api/upload', headers=headers123, data=multipart_data.encode('utf-8'), cookies=cookies, proxies=proxies) |
|
|
filename = response.json()['filename'] |
|
|
return filename, user_filename, str(len(content.encode('utf-8'))) |
|
|
|
|
|
def get_ck_parms(session, session_jwt, chat, chatid, model): |
|
|
cookies = { |
|
|
'youpro_subscription': 'true', |
|
|
'stytch_session': session, |
|
|
'stytch_session_jwt': session_jwt, |
|
|
'ydc_stytch_session': session, |
|
|
'ydc_stytch_session_jwt': session_jwt, |
|
|
} |
|
|
params = {'q': chat, |
|
|
'page': '1', |
|
|
'count': '10', |
|
|
'safeSearch': |
|
|
'Moderate', 'mkt': |
|
|
'zh-HK', 'responseFilter': |
|
|
'WebPages,TimeZone,Computation,RelatedSearches', |
|
|
'domain': 'youchat', |
|
|
'use_personalization_extraction': 'true', |
|
|
'queryTraceId': chatid, |
|
|
'chatId': chatid, |
|
|
'conversationTurnId': '75f82567-3f79-4f4d-bdbc-48847c23cab3', |
|
|
'pastChatLength': '0', |
|
|
'isSmallMediumDevice': 'true', |
|
|
'selectedChatMode': 'custom', |
|
|
'selectedAiModel': model, |
|
|
'traceId': f'{chatid}|{uuid.uuid4()}|{datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S.%fZ")}', |
|
|
'chat': '[]' |
|
|
} |
|
|
return cookies,params |
|
|
|
|
|
def parse_1(data): |
|
|
messages = data['messages'] |
|
|
model = data['model'] |
|
|
try: |
|
|
_stream = data['stream'] |
|
|
except: |
|
|
_stream = False |
|
|
|
|
|
if '使用四到五个字直接返回这句话的简要主题,不要解释、不要标点、不要语气词、不要多余文本,不要加粗,如果没有主题,请直接返回“闲聊”' in str(messages): |
|
|
model = 'gpt_4_turbo' |
|
|
if model == 'gem_pro': |
|
|
model = 'gemini_pro' |
|
|
elif model == 'gem_1_5_pro': |
|
|
model = 'gemini_1_5_pro' |
|
|
elif model not in models: |
|
|
model = 'gpt_4_turbo' |
|
|
if model == 'command_r' or model == 'zephyr' or model == 'claude_2': |
|
|
add_t = "This is the api format of our previous conversation, please understand and reply to the user's last question" |
|
|
messages = add_t + str(messages) |
|
|
elif model == 'databricks_dbrx_instruct' or model == 'gemini_pro'or model == 'gemini_1_5_pro' or model == 'claude_3_opus_2k': |
|
|
for item in reversed(messages): |
|
|
if item['role'] == 'user': |
|
|
messages = item['content'] |
|
|
break |
|
|
return str(messages),model,_stream |
|
|
|
|
|
def chat_liu(chat, model, session, session_jwt): |
|
|
chatid = uuid.uuid4() |
|
|
cookies,params = get_ck_parms(session, session_jwt, chat, chatid, model) |
|
|
response = requests.get( |
|
|
'https://you.com/api/streamingSearch', |
|
|
cookies=cookies, |
|
|
headers=headers, |
|
|
params=params, |
|
|
stream=True, |
|
|
proxies=proxies |
|
|
) |
|
|
if response.status_code == 200: |
|
|
for line in response.iter_lines(): |
|
|
if line: |
|
|
data = line.decode('utf-8') |
|
|
if 'event' in data: |
|
|
continue |
|
|
else: |
|
|
data = data[6:] |
|
|
if 'youChatToken' in data: |
|
|
id = str(uuid.uuid4()) |
|
|
content = json.loads(data)['youChatToken'] |
|
|
if 'Please log in to access GPT-4 mode.' in content and 'Answering your question without GPT-4 mode:' in content: |
|
|
content = 'cookie失效或会员到期,将默认使用智障模型!\n\n' |
|
|
yield "data: {}\n\n".format(json.dumps({ |
|
|
"id": "chatcmpl-"+id, |
|
|
"created": 0, |
|
|
"model": model, |
|
|
"choices": [{ |
|
|
"index": 0, |
|
|
"delta": { |
|
|
"content": content, |
|
|
} |
|
|
}] |
|
|
})) |
|
|
yield bytes(f"data: {['DONE']}", 'utf-8') |
|
|
yield bytes() |
|
|
else: |
|
|
if response.status_code == 403 and 'Just a moment...' in response.text: |
|
|
print('盾') |
|
|
return response.status_code |
|
|
|
|
|
def claude_3_opus_2k(chat, model, session, session_jwt): |
|
|
model = 'claude_3_opus' |
|
|
cookies = { |
|
|
'youpro_subscription': 'true', |
|
|
'stytch_session': session, |
|
|
'stytch_session_jwt': session_jwt, |
|
|
'ydc_stytch_session': session, |
|
|
'ydc_stytch_session_jwt': session_jwt, |
|
|
} |
|
|
|
|
|
with open('wb.txt', 'r', encoding='utf-8') as file: |
|
|
content = file.read() |
|
|
filename, user_filename, size = update_files(content.replace('{tihuan1145141919810}', chat), cookies) |
|
|
chatid = str(uuid.uuid4()) |
|
|
params = {'q': 'Please review the attached prompt', 'page': '1', 'count': '10', 'safeSearch': 'Moderate', 'mkt': 'zh-HK', 'responseFilter': 'WebPages,TimeZone,Computation,RelatedSearches', 'domain': 'youchat', 'use_personalization_extraction': 'true', |
|
|
'queryTraceId': chatid, |
|
|
'chatId': chatid, |
|
|
'conversationTurnId': str(uuid.uuid4()), |
|
|
'pastChatLength': '0', 'isSmallMediumDevice': 'true', 'selectedChatMode': 'custom', |
|
|
'userFiles': '[{"user_filename":"' + user_filename + '","filename":"' + filename + '","size":"' + size + '"}]', |
|
|
'selectedAIModel': 'claude_3_opus', |
|
|
'traceId': f'{chatid}|{uuid.uuid4()}|{datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S.%fZ")}', |
|
|
'chat': '[]'} |
|
|
response = requests.get( |
|
|
'https://you.com/api/streamingSearch', |
|
|
cookies=cookies, |
|
|
headers=headers, |
|
|
params=params, |
|
|
stream=True, |
|
|
proxies=proxies, |
|
|
timeout=500 |
|
|
) |
|
|
if response.status_code == 200: |
|
|
for line in response.iter_lines(): |
|
|
if line: |
|
|
data = line.decode('utf-8') |
|
|
if 'event' in data: |
|
|
continue |
|
|
else: |
|
|
data = data[6:] |
|
|
if 'youChatToken' in data: |
|
|
id = str(uuid.uuid4()) |
|
|
content = json.loads(data)['youChatToken'] |
|
|
if 'Please log in to access GPT-4 mode.' in content and 'Answering your question without GPT-4 mode:' in content: |
|
|
content = 'cookie失效或会员到期,将默认使用智障模型!\n\n' |
|
|
yield "data: {}\n\n".format(json.dumps({ |
|
|
"id": "chatcmpl-"+id, |
|
|
"created": 0, |
|
|
"model": model, |
|
|
"choices": [{ |
|
|
"index": 0, |
|
|
"delta": { |
|
|
"content": content, |
|
|
} |
|
|
}] |
|
|
})) |
|
|
yield bytes(f"data: {['DONE']}", 'utf-8') |
|
|
yield bytes() |
|
|
else: |
|
|
if response.status_code == 403 and 'Just a moment...' in response.text: |
|
|
print('盾') |
|
|
return response.status_code |
|
|
|
|
|
def chat_feiliu(chat, model, session, session_jwt): |
|
|
chatid = uuid.uuid4() |
|
|
cookies,params = get_ck_parms(session, session_jwt, chat, chatid, model) |
|
|
response = requests.get( |
|
|
'https://you.com/api/streamingSearch', |
|
|
cookies=cookies, |
|
|
headers=headers, |
|
|
params=params, |
|
|
stream=True, |
|
|
proxies=proxies |
|
|
) |
|
|
chat_text = '' |
|
|
if response.status_code == 200: |
|
|
for line in response.iter_lines(): |
|
|
if line: |
|
|
data = line.decode('utf-8') |
|
|
if 'event' in data: |
|
|
continue |
|
|
else: |
|
|
data = data[6:] |
|
|
if 'youChatToken' in data: |
|
|
id = str(uuid.uuid4()) |
|
|
content = json.loads(data)['youChatToken'] |
|
|
if 'Please log in to access GPT-4 mode.' in content and 'Answering your question without GPT-4 mode:' in content: |
|
|
content = 'cookie失效或会员到期,将默认使用智障模型!\n\n' |
|
|
chat_text = chat_text + content |
|
|
else: |
|
|
return {"error": f'返回错误|{str(response.status_code)}'}, response.status_code |
|
|
return {"id":f"chatcmpl-{str(uuid.uuid4())}", |
|
|
"OAI-Device-Id":str(uuid.uuid4()), |
|
|
"conversation_id":str(uuid.uuid4()), |
|
|
"created":123, |
|
|
"model":"gpt-3.5-turbo", |
|
|
"choices":[{"index":0,"message":{"role":"assistant","content":chat_text},"finish_reason":"stop"}], |
|
|
"usage":{"prompt_tokens":0,"completion_tokens":0,"total_tokens":0}} |
|
|
|
|
|
|
|
|
@app.route('/') |
|
|
def stream(): |
|
|
return 'ok' |
|
|
|
|
|
@app.route('/v1/chat/completions', methods=['POST', 'OPTIONS']) |
|
|
def chatv1_1(): |
|
|
if request.method == 'OPTIONS': |
|
|
return '', 204 |
|
|
try: |
|
|
try: |
|
|
session_jwt = re.search(r'stytch_session_jwt=([^;]+)', request.headers.get('Authorization')).group(1) |
|
|
session = re.search(r'ydc_stytch_session=([^;]+)', request.headers.get('Authorization')).group(1) |
|
|
except: |
|
|
return {"error": "请确保传入的Authorization正确"}, 401 |
|
|
try: |
|
|
messages,model,_stream = parse_1(request.get_json()) |
|
|
except Exception as e: |
|
|
print(e) |
|
|
return {"error": "Invalid JSON body1"}, 404 |
|
|
try: |
|
|
if model == 'claude_3_opus_2k': |
|
|
if _stream == False: |
|
|
return {"error": "Only supports stream mode"}, 404 |
|
|
return Response(claude_3_opus_2k(str(messages), model, session, session_jwt), mimetype='text/event-stream') |
|
|
except: |
|
|
return {"error": "Upload error or membership expiration"}, 404 |
|
|
|
|
|
if _stream == True: |
|
|
return Response(chat_liu(str(messages), model, session, session_jwt), mimetype='text/event-stream') |
|
|
else: |
|
|
return chat_feiliu(messages, model, session, session_jwt) |
|
|
except Exception as e: |
|
|
print('error') |
|
|
print(e) |
|
|
return {"error": "Invalid JSON body"}, 404 |
|
|
|
|
|
if __name__ == '__main__': |
|
|
app.run(host='0.0.0.0', debug=True, port=8000) |