Severian commited on
Commit
40a4a3c
·
verified ·
1 Parent(s): 4b04903

Update server.py

Browse files
Files changed (1) hide show
  1. server.py +105 -66
server.py CHANGED
@@ -1,39 +1,35 @@
1
  import os
2
- from flask import Flask, request, jsonify
3
  import requests
4
  import logging
 
 
 
5
  from dotenv import load_dotenv
6
- import json
7
- from typing import Dict, Any, Tuple, Union
8
 
9
  # Load environment variables
10
  load_dotenv()
11
 
12
- app = Flask(__name__)
 
 
13
 
 
14
  ANTHROPIC_API_URL = os.getenv(
15
  'ANTHROPIC_API_URL',
16
  'https://relay.stagwellmarketingcloud.io/anthropic/v1/messages'
17
  )
18
  API_KEY = os.getenv('ANTHROPIC_API_KEY')
19
 
20
- # Configure logging
21
- logging.basicConfig(level=logging.INFO)
22
- logger = logging.getLogger(__name__)
23
-
24
- def transform_to_anthropic_request(
25
- request_data: Dict[str, Any]
26
- ) -> Dict[str, Any]:
27
  """Transform OpenAI-style request to Anthropic format."""
28
  if 'messages' in request_data:
29
- # Chat completion format
30
  return {
31
  "model": request_data.get('model', 'claude-3-5-sonnet-20240620'),
32
  "max_tokens": request_data.get('max_tokens', 1024),
33
  "messages": request_data['messages']
34
  }
35
  else:
36
- # Regular completion format
37
  return {
38
  "model": request_data.get('model', 'claude-3-5-sonnet-20240620'),
39
  "max_tokens": request_data.get('max_tokens', 1024),
@@ -79,59 +75,102 @@ def make_anthropic_request(
79
  logger.error(error_msg)
80
  return {"error": error_msg}, 500
81
 
82
- # Routes remain mostly unchanged, but use new helper functions
83
- @app.route('/v1/completions', methods=['POST'])
84
- def completions():
85
- """Handle completion-style requests."""
86
- logger.info(f"Received completion request: {json.dumps(request.json)}")
87
-
88
- anthropic_response, status_code = make_anthropic_request(request.json)
89
- if status_code != 200:
90
- return jsonify(anthropic_response), status_code
91
-
92
- return jsonify({
93
- "id": "cmpl-" + anthropic_response.get('id', 'default'),
94
- "object": "text_completion",
95
- "created": anthropic_response.get('created', 0),
96
- "choices": [{
97
- "text": anthropic_response['content'][0]['text'],
98
- "index": 0,
99
- "finish_reason": "stop"
100
- }],
101
- "usage": {
102
- "prompt_tokens": -1,
103
- "completion_tokens": -1,
104
- "total_tokens": -1
105
- }
106
- }), 200
107
 
108
- @app.route('/v1/chat/completions', methods=['POST'])
109
- def chat_completions():
110
- """Handle chat completion-style requests."""
111
- logger.info(f"Received chat completion request: {json.dumps(request.json)}")
112
-
113
- anthropic_response, status_code = make_anthropic_request(request.json)
114
- if status_code != 200:
115
- return jsonify(anthropic_response), status_code
 
 
 
 
 
 
 
 
 
 
 
 
 
116
 
117
- return jsonify({
118
- "id": "chatcmpl-" + anthropic_response.get('id', 'default'),
119
- "object": "chat.completion",
120
- "created": anthropic_response.get('created', 0),
121
- "choices": [{
122
- "index": 0,
123
- "message": {
124
- "role": "assistant",
125
- "content": anthropic_response['content'][0]['text']
126
- },
127
- "finish_reason": "stop"
128
- }],
129
- "usage": {
130
- "prompt_tokens": -1,
131
- "completion_tokens": -1,
132
- "total_tokens": -1
133
- }
134
- }), 200
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
 
136
- if __name__ == '__main__':
137
- app.run(host='0.0.0.0', port=4224)
 
1
  import os
2
+ import json
3
  import requests
4
  import logging
5
+ from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
6
+ from urllib.parse import parse_qs, urlparse
7
+ from typing import Dict, Any, Tuple
8
  from dotenv import load_dotenv
 
 
9
 
10
  # Load environment variables
11
  load_dotenv()
12
 
13
+ # Configure logging
14
+ logging.basicConfig(level=logging.INFO)
15
+ logger = logging.getLogger(__name__)
16
 
17
+ # Constants
18
  ANTHROPIC_API_URL = os.getenv(
19
  'ANTHROPIC_API_URL',
20
  'https://relay.stagwellmarketingcloud.io/anthropic/v1/messages'
21
  )
22
  API_KEY = os.getenv('ANTHROPIC_API_KEY')
23
 
24
+ def transform_to_anthropic_request(request_data: Dict[str, Any]) -> Dict[str, Any]:
 
 
 
 
 
 
25
  """Transform OpenAI-style request to Anthropic format."""
26
  if 'messages' in request_data:
 
27
  return {
28
  "model": request_data.get('model', 'claude-3-5-sonnet-20240620'),
29
  "max_tokens": request_data.get('max_tokens', 1024),
30
  "messages": request_data['messages']
31
  }
32
  else:
 
33
  return {
34
  "model": request_data.get('model', 'claude-3-5-sonnet-20240620'),
35
  "max_tokens": request_data.get('max_tokens', 1024),
 
75
  logger.error(error_msg)
76
  return {"error": error_msg}, 500
77
 
78
+ class AnthropicProxyHandler(SimpleHTTPRequestHandler):
79
+ def send_json_response(self, data: Dict[str, Any], status: int = 200):
80
+ """Helper method to send JSON responses."""
81
+ self.send_response(status)
82
+ self.send_header('Content-Type', 'application/json')
83
+ self.end_headers()
84
+ self.wfile.write(json.dumps(data).encode('utf-8'))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
 
86
+ def do_GET(self):
87
+ """Handle GET requests."""
88
+ if self.path == "/v1":
89
+ self.send_json_response({"status": True})
90
+ elif self.path == "/v1/models":
91
+ self.send_json_response({
92
+ "data": [{
93
+ "id": "claude-3-5-sonnet-20240620",
94
+ "object": "model",
95
+ "created": 1706745202,
96
+ "owned_by": "anthropic"
97
+ }]
98
+ })
99
+ else:
100
+ super().do_GET()
101
+
102
+ def do_POST(self):
103
+ """Handle POST requests."""
104
+ content_length = int(self.headers.get('Content-Length', 0))
105
+ request_body = self.rfile.read(content_length)
106
+ request_data = json.loads(request_body)
107
 
108
+ if self.path == "/v1/completions":
109
+ logger.info(f"Received completion request: {json.dumps(request_data)}")
110
+
111
+ response, status_code = make_anthropic_request(request_data)
112
+ if status_code != 200:
113
+ self.send_json_response(response, status_code)
114
+ return
115
+
116
+ completion_response = {
117
+ "id": "cmpl-" + response.get('id', 'default'),
118
+ "object": "text_completion",
119
+ "created": response.get('created', 0),
120
+ "choices": [{
121
+ "text": response['content'][0]['text'],
122
+ "index": 0,
123
+ "finish_reason": "stop"
124
+ }],
125
+ "usage": {
126
+ "prompt_tokens": -1,
127
+ "completion_tokens": -1,
128
+ "total_tokens": -1
129
+ }
130
+ }
131
+ self.send_json_response(completion_response)
132
+
133
+ elif self.path == "/v1/chat/completions":
134
+ logger.info(
135
+ f"Received chat completion request: {json.dumps(request_data)}"
136
+ )
137
+
138
+ response, status_code = make_anthropic_request(request_data)
139
+ if status_code != 200:
140
+ self.send_json_response(response, status_code)
141
+ return
142
+
143
+ chat_response = {
144
+ "id": "chatcmpl-" + response.get('id', 'default'),
145
+ "object": "chat.completion",
146
+ "created": response.get('created', 0),
147
+ "choices": [{
148
+ "index": 0,
149
+ "message": {
150
+ "role": "assistant",
151
+ "content": response['content'][0]['text']
152
+ },
153
+ "finish_reason": "stop"
154
+ }],
155
+ "usage": {
156
+ "prompt_tokens": -1,
157
+ "completion_tokens": -1,
158
+ "total_tokens": -1
159
+ }
160
+ }
161
+ self.send_json_response(chat_response)
162
+
163
+ else:
164
+ self.send_json_response(
165
+ {"error": "Invalid endpoint"},
166
+ status=404
167
+ )
168
+
169
+ def run_server(port: int = 7860):
170
+ """Start the server on the specified port."""
171
+ server = ThreadingHTTPServer(("", port), AnthropicProxyHandler)
172
+ logger.info(f"Starting server on port {port}")
173
+ server.serve_forever()
174
 
175
+ if __name__ == "__main__":
176
+ run_server()