|
|
|
|
|
|
|
|
from fastapi import FastAPI, Request, HTTPException, Response |
|
|
from fastapi.middleware.cors import CORSMiddleware |
|
|
import re, json |
|
|
import httpx |
|
|
import uuid |
|
|
|
|
|
app = FastAPI() |
|
|
|
|
|
app.add_middleware( |
|
|
CORSMiddleware, |
|
|
allow_origins=["*"], |
|
|
allow_credentials=True, |
|
|
allow_methods=["*"], |
|
|
allow_headers=["*"], |
|
|
) |
|
|
|
|
|
@app.get("/") |
|
|
def greet_json(): |
|
|
return {"Hello": "World!"} |
|
|
|
|
|
@app.get("/v1/{dest_url:path}") |
|
|
async def gre_dest_url(dest_url: str): |
|
|
return dest_url |
|
|
|
|
|
API_CLIENT = "genai-js/0.21.0" |
|
|
DEFAULT_MODEL = "gemini-1.5-pro-latest" |
|
|
|
|
|
async def transform_request(req: dict): |
|
|
|
|
|
return req |
|
|
|
|
|
async def process_completions_response(data: dict, model: str, id: str): |
|
|
|
|
|
choices = [] |
|
|
if "candidates" in data: |
|
|
for i, candidate in enumerate(data["candidates"]): |
|
|
message = {} |
|
|
if "content" in candidate: |
|
|
message["content"] = candidate["content"] |
|
|
else: |
|
|
message["content"] = "" |
|
|
message["role"] = "assistant" |
|
|
choices.append({ |
|
|
"finish_reason": candidate.get("finishReason", "stop"), |
|
|
"index": i, |
|
|
"message": message |
|
|
}) |
|
|
|
|
|
usage = {} |
|
|
if "usageMetadata" in data: |
|
|
usage = { |
|
|
"completion_tokens": data["usageMetadata"].get("tokenCount", 0), |
|
|
"prompt_tokens": 0, |
|
|
"total_tokens": data["usageMetadata"].get("tokenCount", 0) |
|
|
} |
|
|
|
|
|
response_data = { |
|
|
"id": id, |
|
|
"choices": choices, |
|
|
"created": 1678787675, |
|
|
"model": model, |
|
|
"object": "chat.completion", |
|
|
"usage": usage |
|
|
} |
|
|
return json.dumps(response_data, ensure_ascii=False) |
|
|
|
|
|
@app.post("/v1/{dest_url:path}") |
|
|
async def proxy_url(dest_url: str, request: Request): |
|
|
body = await request.body() |
|
|
headers = dict(request.headers) |
|
|
|
|
|
|
|
|
if 'content-length' in headers: |
|
|
del headers['content-length'] |
|
|
if 'host' in headers: |
|
|
del headers['host'] |
|
|
|
|
|
|
|
|
auth = headers.get("Authorization") |
|
|
api_key = auth.split(" ")[1] if auth else None |
|
|
|
|
|
|
|
|
headers["x-goog-api-client"] = API_CLIENT |
|
|
if api_key: |
|
|
headers["x-goog-api-key"] = api_key |
|
|
headers['Content-Type'] = 'application/json' |
|
|
|
|
|
|
|
|
|
|
|
dest_url = re.sub('/', '://', dest_url, count=1) |
|
|
|
|
|
|
|
|
if dest_url.endswith("/chat/completions"): |
|
|
model = DEFAULT_MODEL |
|
|
req_body = json.loads(body.decode('utf-8')) |
|
|
if 'model' in req_body: |
|
|
model = req_body['model'] |
|
|
if model.startswith("models/"): |
|
|
model = model[7:] |
|
|
TASK = "generateContent" |
|
|
url = f"{dest_url.rsplit('/', 1)[0]}/{model}:{TASK}" |
|
|
|
|
|
async with httpx.AsyncClient() as client: |
|
|
try: |
|
|
|
|
|
response = await client.post(url, content=body, headers=headers) |
|
|
|
|
|
|
|
|
if response.status_code == 200: |
|
|
|
|
|
if 'application/json' in response.headers.get('content-type', ''): |
|
|
json_response = response.json() |
|
|
json_response['id'] = f"chatcmpl-{uuid.uuid4()}" |
|
|
processed_response = await process_completions_response(json_response, model, json_response['id']) |
|
|
resp = Response(content=processed_response, media_type="application/json") |
|
|
resp.headers["Access-Control-Allow-Origin"] = "*" |
|
|
return resp |
|
|
else: |
|
|
return {"error": "Response is not in JSON format", "id": f"chatcmpl-{uuid.uuid4()}"} |
|
|
else: |
|
|
|
|
|
try: |
|
|
error_data = response.json() |
|
|
error_data['id'] = f"chatcmpl-{uuid.uuid4()}" |
|
|
except ValueError: |
|
|
error_data = {"status_code": response.status_code, "detail": response.text, "id": f"chatcmpl-{uuid.uuid4()}"} |
|
|
print(f"Error response: {error_data}") |
|
|
resp = Response(content=json.dumps(error_data, ensure_ascii=False), media_type="application/json") |
|
|
resp.headers["Access-Control-Allow-Origin"] = "*" |
|
|
return resp |
|
|
|
|
|
except httpx.RequestError as e: |
|
|
|
|
|
print(f"Request error: {e}") |
|
|
raise HTTPException(status_code=500, detail=str(e)) |
|
|
else: |
|
|
async with httpx.AsyncClient() as client: |
|
|
try: |
|
|
|
|
|
response = await client.post(dest_url, content=body, headers=headers) |
|
|
|
|
|
|
|
|
if response.status_code == 200: |
|
|
|
|
|
if 'application/json' in response.headers.get('content-type', ''): |
|
|
json_response = response.json() |
|
|
json_response['id'] = f"chatcmpl-{uuid.uuid4()}" |
|
|
resp = Response(content=json.dumps(json_response), media_type="application/json") |
|
|
resp.headers["Access-Control-Allow-Origin"] = "*" |
|
|
return resp |
|
|
else: |
|
|
return {"error": "Response is not in JSON format", "id": f"chatcmpl-{uuid.uuid4()}"} |
|
|
else: |
|
|
|
|
|
try: |
|
|
error_data = response.json() |
|
|
error_data['id'] = f"chatcmpl-{uuid.uuid4()}" |
|
|
except ValueError: |
|
|
error_data = {"status_code": response.status_code, "detail": response.text, "id": f"chatcmpl-{uuid.uuid4()}"} |
|
|
resp = Response(content=json.dumps(error_data), media_type="application/json") |
|
|
resp.headers["Access-Control-Allow-Origin"] = "*" |
|
|
return resp |
|
|
|
|
|
except httpx.RequestError as e: |
|
|
|
|
|
raise HTTPException(status_code=500, detail=str(e)) |
|
|
|
|
|
|
|
|
from fastapi import FastAPI, Request, HTTPException, Response |
|
|
import re, json |
|
|
import httpx |
|
|
import uuid |
|
|
|
|
|
app = FastAPI() |
|
|
|
|
|
@app.get("/") |
|
|
def greet_json(): |
|
|
return {"Hello": "World!"} |
|
|
|
|
|
@app.get("/v1/{dest_url:path}") |
|
|
async def gre_dest_url(dest_url: str): |
|
|
return dest_url |
|
|
|
|
|
@app.post("/v1/{dest_url:path}") |
|
|
async def proxy_url(dest_url: str, request: Request): |
|
|
body = await request.body() |
|
|
headers = dict(request.headers) |
|
|
|
|
|
|
|
|
if 'content-length' in headers: |
|
|
del headers['content-length'] |
|
|
if 'host' in headers: |
|
|
del headers['host'] |
|
|
|
|
|
headers['User-Agent']='PostmanRuntime/7.43.0' |
|
|
|
|
|
dest_url = re.sub('/', '://', dest_url, count=1) |
|
|
|
|
|
async with httpx.AsyncClient() as client: |
|
|
try: |
|
|
print(f"Request Headers: {headers}") |
|
|
|
|
|
response = await client.post(dest_url, content=body, headers=headers) |
|
|
|
|
|
|
|
|
if response.status_code == 200: |
|
|
|
|
|
if 'application/json' in response.headers.get('content-type', ''): |
|
|
json_response = response.json() |
|
|
json_response['id'] = f"chatcmpl-{uuid.uuid4()}" |
|
|
|
|
|
|
|
|
resp = Response(content=json.dumps(json_response), media_type="application/json") |
|
|
resp.headers["Access-Control-Allow-Origin"] = "*" |
|
|
return resp |
|
|
else: |
|
|
return {"error": "Response is not in JSON format", "id": f"chatcmpl-{uuid.uuid4()}"} |
|
|
else: |
|
|
|
|
|
try: |
|
|
error_data = response.json() |
|
|
error_data['id'] = f"chatcmpl-{uuid.uuid4()}" |
|
|
except ValueError: |
|
|
error_data = {"status_code": response.status_code, "detail": response.text, "id": f"chatcmpl-{uuid.uuid4()}"} |
|
|
resp = Response(content=str(error_data), media_type="application/json") |
|
|
resp.headers["Access-Control-Allow-Origin"] = "*" |
|
|
return resp |
|
|
|
|
|
except httpx.RequestError as e: |
|
|
|
|
|
raise HTTPException(status_code=500, detail=str(e)) |
|
|
|