Add a Gemini API proxy route.

This commit is contained in:
Hemang
2025-03-03 11:44:53 +01:00
parent d9d4ba0344
commit 32fa1c080d
4 changed files with 70 additions and 3 deletions
+1
View File
@@ -3,3 +3,4 @@
# If you want to push to a local instance of explorer, then specify the app-api docker container name like:
# http://<app-api-docker-container-name>:8000 to push to the local explorer instance.
INVARIANT_API_URL=https://explorer.invariantlabs.ai
GUADRAILS_API_URL=https://guardrail.invariantnet.com
+61
View File
@@ -0,0 +1,61 @@
"""Proxy service to forward requests to the Gemini APIs"""
import json
from common.config_manager import ProxyConfig, ProxyConfigManager
from fastapi import APIRouter, Depends, Request, Response
from utils.constants import IGNORED_HEADERS
proxy = APIRouter()
def _extract_dataset_name_and_endpoint(endpoint: str):
"""Extracts the dataset name and endpoint from the given endpoint."""
endpoint_parts = endpoint.split("/")
dataset_name = None
if endpoint_parts[1] == "models":
# Case 1: Without dataset_name
# `endpoint = <version>/models/<model-name>:generateContent`
reconstructed_endpoint = "/".join(endpoint_parts)
elif endpoint_parts[2] == "models":
# Case 2: With dataset_name
# `endpoint = <dataset-name>/<version>/models/<model-name>:generateContent`
dataset_name = endpoint_parts[0]
reconstructed_endpoint = "/".join(endpoint_parts[1:])
else:
# Case 3: Invalid endpoint
return Response(
content=f"Invalid endpoint: {endpoint} - the endpoint should be in the format: \
/api/v1/proxy/gemini/<version>/models/<model-name>:generateContent or \
/api/v1/proxy/gemini/<dataset-name>/<version>models/<model-name>:generateContent",
status_code=400,
)
return dataset_name, reconstructed_endpoint
@proxy.post(
"/gemini/{endpoint:path}",
)
async def gemini_generate_content_proxy(
request: Request,
endpoint: str,
config: ProxyConfig = Depends(ProxyConfigManager.get_config), # pylint: disable=unused-argument
) -> Response:
"""Proxy calls to the OpenAI APIs"""
headers = {
k: v for k, v in request.headers.items() if k.lower() not in IGNORED_HEADERS
}
headers["accept-encoding"] = "identity"
request_body_bytes = await request.body()
request_body_json = json.loads(request_body_bytes)
api_key = headers.get("x-goog-api-key")
print(f"API Key: {api_key}")
print("request body json: ", request_body_json)
dataset_name, reconstructed_endpoint = _extract_dataset_name_and_endpoint(endpoint)
print(f"API Key: {api_key}")
print("Processed Endpoint: ", reconstructed_endpoint)
print("Dataset Name: ", dataset_name)
return {}
+3
View File
@@ -3,6 +3,7 @@
import fastapi
import uvicorn
from routes.anthropic import proxy as anthropic_proxy
from routes.gemini import proxy as gemini_proxy
from routes.open_ai import proxy as open_ai_proxy
from starlette_compress import CompressMiddleware
@@ -26,6 +27,8 @@ router.include_router(open_ai_proxy, prefix="/proxy", tags=["open_ai_proxy"])
router.include_router(anthropic_proxy, prefix="/proxy", tags=["anthropic_proxy"])
router.include_router(gemini_proxy, prefix="/proxy", tags=["gemini_proxy"])
app.include_router(router)
+5 -3
View File
@@ -20,11 +20,13 @@ up() {
shift
done
if [[ -n "$POLICIES_FILE_PATH" && -f "$POLICIES_FILE_PATH" ]]; then
POLICIES_FILE_PATH=$(realpath "$POLICIES_FILE_PATH")
else
if [[ -n "$POLICIES_FILE_PATH" ]]; then
if [[ -f "$POLICIES_FILE_PATH" ]]; then
POLICIES_FILE_PATH=$(realpath "$POLICIES_FILE_PATH")
else
echo "Error: Specified policies file does not exist: $POLICIES_FILE_PATH"
exit 1
fi
fi
# Start Docker Compose with the correct environment variable