Dragonnext commited on
Commit
3b877e1
·
verified ·
1 Parent(s): 106b321

Upload 8 files

Browse files
Files changed (6) hide show
  1. README.md +3 -3
  2. package-lock.json +43 -0
  3. package.json +14 -0
  4. requirements.txt +3 -0
  5. server.py +199 -0
  6. tokenizer.js +9 -0
README.md CHANGED
@@ -1,8 +1,8 @@
1
  ---
2
  title: Saya
3
- emoji: 🏢
4
- colorFrom: yellow
5
- colorTo: pink
6
  sdk: docker
7
  pinned: false
8
  ---
 
1
  ---
2
  title: Saya
3
+ emoji: 🍃
4
+ colorFrom: green
5
+ colorTo: gray
6
  sdk: docker
7
  pinned: false
8
  ---
package-lock.json ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "a server",
3
+ "version": "1.0.0",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "a server",
9
+ "version": "1.0.0",
10
+ "license": "ISC",
11
+ "dependencies": {
12
+ "@anthropic-ai/tokenizer": "^0.0.4"
13
+ }
14
+ },
15
+ "node_modules/@anthropic-ai/tokenizer": {
16
+ "version": "0.0.4",
17
+ "resolved": "https://registry.npmjs.org/@anthropic-ai/tokenizer/-/tokenizer-0.0.4.tgz",
18
+ "integrity": "sha512-EHRKbxlxlc8W4KCBEseByJ7YwyYCmgu9OyN59H9+IYIGPoKv8tXyQXinkeGDI+cI8Tiuz9wk2jZb/kK7AyvL7g==",
19
+ "dependencies": {
20
+ "@types/node": "^18.11.18",
21
+ "tiktoken": "^1.0.10"
22
+ }
23
+ },
24
+ "node_modules/@types/node": {
25
+ "version": "18.19.30",
26
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.30.tgz",
27
+ "integrity": "sha512-453z1zPuJLVDbyahaa1sSD5C2sht6ZpHp5rgJNs+H8YGqhluCXcuOUmBYsAo0Tos0cHySJ3lVUGbGgLlqIkpyg==",
28
+ "dependencies": {
29
+ "undici-types": "~5.26.4"
30
+ }
31
+ },
32
+ "node_modules/tiktoken": {
33
+ "version": "1.0.13",
34
+ "resolved": "https://registry.npmjs.org/tiktoken/-/tiktoken-1.0.13.tgz",
35
+ "integrity": "sha512-JaL9ZnvTbGFMDIBeGdVkLt4qWTeCPw+n7Ock+wceAGRenuHA6nOOvMJFliNDyXsjg2osGKJWsXtO2xc74VxyDw=="
36
+ },
37
+ "node_modules/undici-types": {
38
+ "version": "5.26.5",
39
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
40
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
41
+ }
42
+ }
43
+ }
package.json ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "a server",
3
+ "version": "1.0.0",
4
+ "description": "A server",
5
+ "main": "tokenizer.js",
6
+ "dependencies": {
7
+ "@anthropic-ai/tokenizer": "^0.0.4"
8
+ },
9
+ "scripts": {
10
+ "start": "node tokenizer.js"
11
+ },
12
+ "author": "",
13
+ "license": "ISC"
14
+ }
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ Flask==2.1.2
2
+ Werkzeug==2.1.1
3
+ requests==2.27.1
server.py ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+ from flask import Flask, request, Response, redirect, jsonify, stream_with_context
3
+ import random, subprocess, string, json
4
+ import os
5
+ import logging
6
+ from logging import NullHandler
7
+ import subprocess
8
+ from functools import wrap
9
+
10
+ # Copied pepsi (thanks <3) made some modification so it works for me :v hue hue, nah doesn't use that shitty api thingy :v world sim whatever >.>
11
+
12
+ def validate_token(token):
13
+ if token == os.environ.get('PASSWORD'):
14
+ return True
15
+ else:
16
+ return False
17
+
18
+ def requires_auth_bearer(f):
19
+ @wraps(f)
20
+ def decorated(*args, **kwargs):
21
+ if 'X-Api-Key' not in request.headers:
22
+ return jsonify({'error': 'You need special Saya password :3c'}), 401
23
+ token = request.headers['X-Api-Key']
24
+ if not validate_token(token):
25
+ return jsonify({'error': 'hue hue hue hue hue hue '}), 401
26
+ return f(*args, **kwargs)
27
+ return decorated
28
+
29
+ app = Flask(__name__)
30
+ app.config['JSONIFY_PRETTYPRINT_REGULAR'] = True
31
+
32
+ state = {
33
+ "current_requests": 0,
34
+ "total_prompts_sent": 0,
35
+ "total_tokens": 0,
36
+ "logging_enabled": os.environ.get('LOGGING_ENABLED', 'False').lower() in ['true', '1', 't']
37
+ }
38
+
39
+ ## ill ne ver turn on logging i just wanted to show its off on page (same pepsi same :V)
40
+ def configure_logging():
41
+ app.logger.addHandler(NullHandler())
42
+ app.logger.propagate = False
43
+ bloody_log = logging.getLogger('bloody')
44
+ bloody_log.setLevel(logging.ERROR)
45
+ bloody_log.addHandler(NullHandler())
46
+
47
+ configure_logging()
48
+
49
+ def get_token_count(text):
50
+ result = subprocess.run(['node', 'tokenizer.js', text], capture_output=True, text=True)
51
+ return int(result.stdout.strip())
52
+
53
+ def generate_message_id():
54
+ chars = string.ascii_uppercase + string.digits + string.ascii_lowercase
55
+ return 'msg_' + ''.join(random.choices(chars, k=16))
56
+
57
+
58
+ @app.errorhandler(404)
59
+ def page_not_found(e):
60
+ return redirect(random.choice([
61
+ 'https://youtu.be/0o0y-MNqdQU',
62
+ 'https://youtu.be/oAJC1Pn78ZA',
63
+ 'https://youtu.be/p_5tTM9D7l0',
64
+ 'https://youtu.be/H0gEjUEneBI',
65
+ 'https://youtu.be/Hj8icpQldzc',
66
+ 'https://youtu.be/-9_sTTYXcwc',
67
+ 'https://youtu.be/LmsuxO5rfEU',
68
+ 'https://youtu.be/VJkzfV7kNYQ',
69
+ 'https://youtu.be/oCikD1xcv0o',
70
+ 'https://youtu.be/k9TSVx9gAW0',
71
+ 'https://youtu.be/Xiiy8vEWj-g',
72
+ 'https://youtu.be/FKLd1YdmIwA',
73
+ 'https://youtu.be/RJ4iaQAF6SI',
74
+ 'https://youtu.be/KPad2ftEwqc'
75
+ ])), 302
76
+
77
+ @app.route('/saya/messages', methods=['POST'])
78
+ @requires_auth_bearer
79
+ def proxy_message():
80
+ state["total_prompts_sent"] += 1
81
+ state["current_requests"] += 1
82
+
83
+ data = request.get_json()
84
+ if not data or 'messages' not in data:
85
+ abort(400, 'Bad Request: No messages found in the request.')
86
+ full_text = ' '.join(msg.get('content', '') for msg in data['messages'])
87
+ token_count = get_token_count(full_text)
88
+
89
+ data["model"] = os.environ.get('MODEL')
90
+
91
+ headers = {
92
+ "Authorization": f"Bearer {os.environ.get('KEY')}",
93
+ 'Content-Type': 'application/json',
94
+ 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/13.2b11866 Mobile/16A366 Safari/605.1.15',
95
+ 'Origin': os.environ.get('ORIGIN'),
96
+ 'Referer': os.environ.get('REFERER'),
97
+ "Accept": "*/*",
98
+ "Accept-Language": "en-US,en;q=0.5",
99
+ "Sec-Fetch-Dest": "empty",
100
+ "Sec-Fetch-Mode": "cors",
101
+ "Sec-Fetch-Site": "same-origin",
102
+ "Sec-GPC": "1"
103
+ }
104
+ proxied_url = os.environ.get('PROXIED_URL')
105
+ response = requests.post(proxied_url, headers=headers, data=json.dumps(data), stream=True)
106
+
107
+ if not data.get('stream', False):
108
+ output = ''.join(chunk.decode('utf-8') for chunk in response.iter_content(chunk_size=1024) if chunk)
109
+ response_json = {
110
+ "content": [{"text": output, "type": "text"}],
111
+ "id": generate_message_id(),
112
+ "model": ":^)",
113
+ "role": "assistant",
114
+ "stop_reason": "end_turn",
115
+ "stop_sequence": None,
116
+ "type": "message",
117
+ "usage": {
118
+ "input_tokens": token_count,
119
+ "output_tokens": 25,
120
+ }
121
+ }
122
+ state["current_requests"] -= 1
123
+ return Response(json.dumps(response_json), headers={'Content-Type': 'application/json'}, status=response.status_code)
124
+
125
+ @stream_with_context
126
+ def generate_stream():
127
+ tokens_sent = 0
128
+ text_buffer = ''
129
+ try:
130
+ yield 'event: message_start\n'
131
+ yield f'data: {{"type": "message_start", "message": {{"id": "{generate_message_id()}", "type": "message", "role": "assistant", "content": [], "model": "claude-3-opus-20240229", "stop_reason": null, "stop_sequence": null, "usage": {{"input_tokens": 25, "output_tokens": 1}}}}}}\n\n'
132
+ yield 'event: content_block_start\n'
133
+ yield 'data: {"type": "content_block_start", "index": 0, "content_block": {"type": "text", "text": ""}}\n\n'
134
+ incomplete_chunk=""
135
+ for chunk in response.iter_content(chunk_size=256):
136
+ if chunk:
137
+ decoded_chunk = incomplete_chunk+chunk.decode('utf-8', 'xmlcharrefreplace')
138
+ if "data:" in decoded_chunk:
139
+ if 'null}]}' not in decoded_chunk:
140
+ incomplete_chunk+= decoded_chunk
141
+ else:
142
+ for chunkparts in decoded_chunk.split("\n"):
143
+ if "data:" in chunkparts and "null}]}" in chunkparts:
144
+ data = json.loads(chunkparts.replace("data: ",""))
145
+ try:
146
+ text_buffer += data["choices"][0]["delta"]["content"]
147
+ data_dump = json.dumps({"type": "content_block_delta", "index": 0, "delta": {"type": "text_delta", "text": data["choices"][0]["delta"]["content"]}})
148
+ yield f'event: content_block_delta\n'
149
+ yield f'data: {data_dump}\n\n'
150
+
151
+
152
+ if 'content_block_stop' in chunkparts:
153
+ tokens_sent += get_token_count(text_buffer)
154
+ text_buffer = ''
155
+ incomplete_chunk=""
156
+ except:
157
+ pass
158
+ else:
159
+ incomplete_chunk=chunkparts
160
+ else:
161
+ if decoded_chunk[0] != ":":
162
+ incomplete_chunk+=decoded_chunk
163
+
164
+ yield 'event: content_block_stop\n'
165
+ yield 'data: {"type": "content_block_stop", "index": 0}\n\n'
166
+ yield 'event: message_delta\n'
167
+ yield 'data: {"type": "message_delta", "delta": {"stop_reason": "end_turn", "stop_sequence":null, "usage":{"output_tokens": 15}}}\n\n'
168
+ yield 'event: message_stop\n'
169
+ yield 'data: {"type": "message_stop"}\n\n'
170
+ except GeneratorExit:
171
+ pass
172
+ finally:
173
+ if text_buffer:
174
+ tokens_sent += get_token_count(text_buffer)
175
+ state["current_requests"] -= 1
176
+ state["total_tokens"] += tokens_sent
177
+
178
+ return Response(generate_stream(), headers={'Content-Type': 'text/event-stream'})
179
+
180
+ @app.route('/')
181
+ def index():
182
+ space_host = os.environ.get('SPACE_HOST', 'default-space-host')
183
+ endpoint = f"https://{space_host}/saya"
184
+ payload = '''<body style="background-image: url('https://images.dragonetwork.pl/wp12317828.jpg'); background-size: cover; background-repeat: no-repeat;">
185
+ <div style="background-color: rgba(0, 0, 0, 0.5); padding: 20px;">
186
+ <p style="color: white; font-weight: bold; font-size: 200%;">
187
+ <span>Endpoint:</span> <span>''' + endpoint + '''</span><br>
188
+ <span>Prompt Logging:</span> <span>''' + str(state["logging_enabled"]) + '''</span><br>
189
+ <span>Prompters Now:</span> <span>''' + str(state["current_requests"]) + '''</span><br>
190
+ <span>Total Prompts:</span> <span>''' + str(state["total_prompts_sent"]) + '''</span><br>
191
+ <span>Total Tokens:</span> <span>''' + str(state["total_tokens"]) + '''</span><br>
192
+ <span>Password Protected?:</span> <span>yes :3c</span><br>
193
+ </p>
194
+ </div>
195
+ </body>'''
196
+ return payload, 200
197
+
198
+ if __name__ == '__main__':
199
+ app.run(host='0.0.0.0', port=7860, debug=False)
tokenizer.js ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ const { getTokenizer } = require('@anthropic-ai/tokenizer');
2
+ const tokenizer = getTokenizer();
3
+ function getTokenCount(text) {
4
+ const tokens = tokenizer.encode(text.normalize('NFKC'), 'all');
5
+ return tokens.length;
6
+ }
7
+ const text = process.argv[2];
8
+ const tokenCount = getTokenCount(text);
9
+ console.log(tokenCount);