Spaces:
Paused
Paused
import os | |
from flask import Flask, request, jsonify | |
import requests | |
import logging | |
from dotenv import load_dotenv | |
import json | |
from typing import Dict, Any, Tuple, Union | |
# Load environment variables | |
load_dotenv() | |
app = Flask(__name__) | |
ANTHROPIC_API_URL = os.getenv( | |
'ANTHROPIC_API_URL', | |
'https://relay.stagwellmarketingcloud.io/anthropic/v1/messages' | |
) | |
API_KEY = os.getenv('ANTHROPIC_API_KEY') | |
# Configure logging | |
logging.basicConfig(level=logging.INFO) | |
logger = logging.getLogger(__name__) | |
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: | |
# Chat completion format | |
return { | |
"model": request_data.get('model', 'claude-3-5-sonnet-20240620'), | |
"max_tokens": request_data.get('max_tokens', 1024), | |
"messages": request_data['messages'] | |
} | |
else: | |
# Regular completion format | |
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 | |
# Routes remain mostly unchanged, but use new helper functions | |
def completions(): | |
"""Handle completion-style requests.""" | |
logger.info(f"Received completion request: {json.dumps(request.json)}") | |
anthropic_response, status_code = make_anthropic_request(request.json) | |
if status_code != 200: | |
return jsonify(anthropic_response), status_code | |
return jsonify({ | |
"id": "cmpl-" + anthropic_response.get('id', 'default'), | |
"object": "text_completion", | |
"created": anthropic_response.get('created', 0), | |
"choices": [{ | |
"text": anthropic_response['content'][0]['text'], | |
"index": 0, | |
"finish_reason": "stop" | |
}], | |
"usage": { | |
"prompt_tokens": -1, | |
"completion_tokens": -1, | |
"total_tokens": -1 | |
} | |
}), 200 | |
def chat_completions(): | |
"""Handle chat completion-style requests.""" | |
logger.info(f"Received chat completion request: {json.dumps(request.json)}") | |
anthropic_response, status_code = make_anthropic_request(request.json) | |
if status_code != 200: | |
return jsonify(anthropic_response), status_code | |
return jsonify({ | |
"id": "chatcmpl-" + anthropic_response.get('id', 'default'), | |
"object": "chat.completion", | |
"created": anthropic_response.get('created', 0), | |
"choices": [{ | |
"index": 0, | |
"message": { | |
"role": "assistant", | |
"content": anthropic_response['content'][0]['text'] | |
}, | |
"finish_reason": "stop" | |
}], | |
"usage": { | |
"prompt_tokens": -1, | |
"completion_tokens": -1, | |
"total_tokens": -1 | |
} | |
}), 200 | |
if __name__ == '__main__': | |
app.run(host='0.0.0.0', port=4224) | |