isididiidid commited on
Commit
db6bd73
·
verified ·
1 Parent(s): 8ec1470

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +185 -0
  2. requirements.txt +2 -0
app.py ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, Response, stream_with_context
2
+ import requests
3
+ import json
4
+ import uuid
5
+ import time
6
+ import os
7
+
8
+ app = Flask(__name__)
9
+
10
+ MODELS = {
11
+ 'claude-3-5-haiku': 'bedrock-anthropic.claude-3-5-haiku',
12
+ 'claude-3-5-sonnet': 'bedrock-anthropic.claude-3-5-sonnet-v2-0',
13
+ 'nova-lite-v1-0': 'bedrock-amazon.nova-lite-v1-0',
14
+ 'nova-pro-v1-0': 'bedrock-amazon.nova-pro-v1-0',
15
+ 'llama3-1-7b': 'bedrock-meta.llama3-1-8b-instruct-v1',
16
+ 'llama3-1-70b': 'bedrock-meta.llama3-1-70b-instruct-v1',
17
+ 'mistral-small': 'bedrock-mistral.mistral-small-2402-v1-0',
18
+ 'mistral-large': 'bedrock-mistral.mistral-large-2407-v1-0'
19
+ }
20
+
21
+ def validate_key(key):
22
+ try:
23
+ parts = key.split('|||', 3)
24
+ if len(parts) != 3:
25
+ return None, None, None
26
+ return parts[0], parts[2], parts[1]
27
+ except:
28
+ return None, None, None
29
+
30
+ def process_messages(messages):
31
+ """處理消息,將system角色轉換為user角色"""
32
+ processed_messages = []
33
+ system_content = ""
34
+
35
+ for msg in messages:
36
+ if msg["role"] == "system":
37
+ system_content += msg["content"] + "\n"
38
+ else:
39
+ processed_messages.append(msg)
40
+
41
+ # 如果有system消息,將其添加到第一個user消息前面
42
+ if system_content:
43
+ if processed_messages and processed_messages[0]["role"] == "user":
44
+ processed_messages[0]["content"] = system_content + "\n" + processed_messages[0]["content"]
45
+ else:
46
+ processed_messages.insert(0, {"role": "user", "content": system_content.strip()})
47
+
48
+ return processed_messages if processed_messages else messages
49
+
50
+ def create_partyrock_request(openai_req, app_id):
51
+ # 處理消息,轉換system角色
52
+ processed_messages = process_messages(openai_req['messages'])
53
+
54
+ return {
55
+ "messages": [
56
+ {
57
+ "role": msg["role"],
58
+ "content": [{"text": msg["content"]}]
59
+ }
60
+ for msg in processed_messages
61
+ ],
62
+ "modelName": MODELS.get(openai_req.get('model', 'claude-3-5-haiku')),
63
+ "context": {"type": "chat-widget", "appId": app_id},
64
+ "options": {"temperature": 0},
65
+ "apiVersion": 3
66
+ }
67
+
68
+ @app.route('/', methods=['GET'])
69
+ def home():
70
+ return {"status": "PartyRock API Service Running", "port": 7860}
71
+
72
+ @app.route('/hf/v1/chat/completions', methods=['POST'])
73
+ def chat():
74
+ try:
75
+ api_key = request.headers.get('Authorization', '').replace('Bearer ', '')
76
+ app_id, cookie, csrf_token = validate_key(api_key)
77
+
78
+ if not app_id or not cookie or not csrf_token:
79
+ return Response("Invalid API key format. Use: appId|||csrf_token|||cookies", status=401)
80
+
81
+ headers = {
82
+ 'accept': 'text/event-stream',
83
+ 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
84
+ 'anti-csrftoken-a2z': csrf_token,
85
+ 'content-type': 'application/json',
86
+ 'origin': 'https://partyrock.aws',
87
+ 'referer': f'https://partyrock.aws/u/chatyt/{app_id}',
88
+ 'cookie': cookie,
89
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
90
+ }
91
+
92
+ response = requests.post(
93
+ 'https://partyrock.aws/stream/getCompletion',
94
+ headers=headers,
95
+ json=create_partyrock_request(request.json, app_id),
96
+ stream=True
97
+ )
98
+
99
+ if response.status_code != 200:
100
+ return Response(f"PartyRock API error: {response.text}", status=response.status_code)
101
+
102
+ if not request.json.get('stream', False):
103
+ try:
104
+ full_content = ""
105
+ buffer = ""
106
+ for chunk in response.iter_content(chunk_size=1024, decode_unicode=True):
107
+ if chunk:
108
+ buffer += chunk
109
+ while '\n' in buffer:
110
+ line, buffer = buffer.split('\n', 1)
111
+ if line.startswith('data: '):
112
+ try:
113
+ data = json.loads(line[6:])
114
+ if data["type"] == "text":
115
+ content = data["text"]
116
+ if isinstance(content, str):
117
+ content = content.encode('latin1').decode('utf-8')
118
+ if content and content != " ":
119
+ full_content += content
120
+ except:
121
+ continue
122
+
123
+ return {
124
+ "id": str(uuid.uuid4()),
125
+ "object": "chat.completion",
126
+ "created": int(time.time()),
127
+ "model": request.json.get('model', 'claude-3-haiku'),
128
+ "choices": [{
129
+ "message": {
130
+ "role": "assistant",
131
+ "content": full_content
132
+ },
133
+ "finish_reason": "stop",
134
+ "index": 0
135
+ }]
136
+ }
137
+ except Exception as e:
138
+ print(f"Error processing response: {str(e)}")
139
+ return Response("Failed to process response", status=500)
140
+
141
+ def generate():
142
+ try:
143
+ buffer = ""
144
+ for chunk in response.iter_content(chunk_size=1024, decode_unicode=True):
145
+ if chunk:
146
+ buffer += chunk
147
+ while '\n' in buffer:
148
+ line, buffer = buffer.split('\n', 1)
149
+ if line.startswith('data: '):
150
+ try:
151
+ data = json.loads(line[6:])
152
+ if data["type"] == "text":
153
+ content = data["text"]
154
+ if isinstance(content, str):
155
+ content = content.encode('latin1').decode('utf-8')
156
+ chunk_resp = {
157
+ "id": str(uuid.uuid4()),
158
+ "object": "chat.completion.chunk",
159
+ "created": int(time.time()),
160
+ "model": request.json.get('model', 'claude-3-haiku'),
161
+ "choices": [{
162
+ "delta": {"content": content},
163
+ "index": 0,
164
+ "finish_reason": None
165
+ }]
166
+ }
167
+ yield f"data: {json.dumps(chunk_resp, ensure_ascii=False)}\n\n"
168
+ except:
169
+ continue
170
+ yield f"data: {json.dumps({'choices':[{'delta':{'content':''},'index':0,'finish_reason':'stop'}]})}\n\n"
171
+ yield "data: [DONE]\n\n"
172
+ except Exception as e:
173
+ print(f"Error in generate: {str(e)}")
174
+ return
175
+
176
+ return Response(
177
+ stream_with_context(generate()),
178
+ content_type='text/event-stream'
179
+ )
180
+ except Exception as e:
181
+ print(f"Error: {str(e)}")
182
+ return Response(f"Internal server error: {str(e)}", status=500)
183
+
184
+ if __name__ == '__main__':
185
+ app.run(host='0.0.0.0', port=7860)
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ flask
2
+ requests