Spaces:
Paused
Paused
File size: 6,096 Bytes
3dc447d 40a4a3c 3dc447d 40a4a3c 3dc447d 40a4a3c 3dc447d 40a4a3c 4b04903 3dc447d 40a4a3c 4b04903 3dc447d 4b04903 3dc447d 4b04903 3dc447d 4b04903 3dc447d 4b04903 3dc447d 4b04903 3dc447d 4b04903 3dc447d 4b04903 3dc447d 4b04903 3dc447d 40a4a3c 3dc447d 40a4a3c 3dc447d 40a4a3c 3dc447d 40a4a3c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
import os
import json
import requests
import logging
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
from urllib.parse import parse_qs, urlparse
from typing import Dict, Any, Tuple
from dotenv import load_dotenv
# Load environment variables
load_dotenv()
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Constants
ANTHROPIC_API_URL = os.getenv(
'ANTHROPIC_API_URL',
'https://relay.stagwellmarketingcloud.io/anthropic/v1/messages'
)
API_KEY = os.getenv('ANTHROPIC_API_KEY')
def transform_to_anthropic_request(request_data: Dict[str, Any]) -> Dict[str, Any]:
"""Transform OpenAI-style request to Anthropic format."""
if 'messages' in request_data:
return {
"model": request_data.get('model', 'claude-3-5-sonnet-20240620'),
"max_tokens": request_data.get('max_tokens', 1024),
"messages": request_data['messages']
}
else:
return {
"model": request_data.get('model', 'claude-3-5-sonnet-20240620'),
"max_tokens": request_data.get('max_tokens', 1024),
"messages": [{
"role": "user",
"content": request_data.get('prompt', '')
}]
}
def make_anthropic_request(
request_data: Dict[str, Any]
) -> Tuple[Dict[str, Any], int]:
"""Make request to Anthropic API with proper error handling."""
headers = {
'Authorization': f'Bearer {API_KEY}',
'Content-Type': 'application/json',
}
try:
anthropic_request = transform_to_anthropic_request(request_data)
logger.info(
f"Sending request to Anthropic API: {json.dumps(anthropic_request)}"
)
response = requests.post(
ANTHROPIC_API_URL,
headers=headers,
json=anthropic_request,
timeout=30
)
response.raise_for_status()
return response.json(), 200
except requests.RequestException as e:
error_msg = f"Error communicating with Anthropic API: {str(e)}"
if hasattr(e, 'response') and e.response is not None:
error_msg += f"\nResponse: {e.response.text}"
logger.error(error_msg)
return {"error": error_msg}, e.response.status_code if e.response else 500
except Exception as e:
error_msg = f"Unexpected error: {str(e)}"
logger.error(error_msg)
return {"error": error_msg}, 500
class AnthropicProxyHandler(SimpleHTTPRequestHandler):
def send_json_response(self, data: Dict[str, Any], status: int = 200):
"""Helper method to send JSON responses."""
self.send_response(status)
self.send_header('Content-Type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps(data).encode('utf-8'))
def do_GET(self):
"""Handle GET requests."""
if self.path == "/v1":
self.send_json_response({"status": True})
elif self.path == "/v1/models":
self.send_json_response({
"data": [{
"id": "claude-3-5-sonnet-20240620",
"object": "model",
"created": 1706745202,
"owned_by": "anthropic"
}]
})
else:
super().do_GET()
def do_POST(self):
"""Handle POST requests."""
content_length = int(self.headers.get('Content-Length', 0))
request_body = self.rfile.read(content_length)
request_data = json.loads(request_body)
if self.path == "/v1/completions":
logger.info(f"Received completion request: {json.dumps(request_data)}")
response, status_code = make_anthropic_request(request_data)
if status_code != 200:
self.send_json_response(response, status_code)
return
completion_response = {
"id": "cmpl-" + response.get('id', 'default'),
"object": "text_completion",
"created": response.get('created', 0),
"choices": [{
"text": response['content'][0]['text'],
"index": 0,
"finish_reason": "stop"
}],
"usage": {
"prompt_tokens": -1,
"completion_tokens": -1,
"total_tokens": -1
}
}
self.send_json_response(completion_response)
elif self.path == "/v1/chat/completions":
logger.info(
f"Received chat completion request: {json.dumps(request_data)}"
)
response, status_code = make_anthropic_request(request_data)
if status_code != 200:
self.send_json_response(response, status_code)
return
chat_response = {
"id": "chatcmpl-" + response.get('id', 'default'),
"object": "chat.completion",
"created": response.get('created', 0),
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": response['content'][0]['text']
},
"finish_reason": "stop"
}],
"usage": {
"prompt_tokens": -1,
"completion_tokens": -1,
"total_tokens": -1
}
}
self.send_json_response(chat_response)
else:
self.send_json_response(
{"error": "Invalid endpoint"},
status=404
)
def run_server(port: int = 7860):
"""Start the server on the specified port."""
server = ThreadingHTTPServer(("", port), AnthropicProxyHandler)
logger.info(f"Starting server on port {port}")
server.serve_forever()
if __name__ == "__main__":
run_server() |