refac
This commit is contained in:
@@ -1442,6 +1442,16 @@ async def check_url(request: Request, call_next):
|
||||
scheme="Bearer", credentials=request.cookies.get("token")
|
||||
)
|
||||
|
||||
# Fallback to x-api-key header for Anthropic Messages API routes
|
||||
if request.state.token is None and request.headers.get("x-api-key"):
|
||||
request_path = request.url.path
|
||||
if request_path in ("/api/message", "/api/v1/messages"):
|
||||
from fastapi.security import HTTPAuthorizationCredentials
|
||||
|
||||
request.state.token = HTTPAuthorizationCredentials(
|
||||
scheme="Bearer", credentials=request.headers.get("x-api-key")
|
||||
)
|
||||
|
||||
request.state.enable_api_keys = app.state.config.ENABLE_API_KEYS
|
||||
response = await call_next(request)
|
||||
process_time = int(time.time()) - start_time
|
||||
@@ -1893,6 +1903,69 @@ generate_chat_completions = chat_completion
|
||||
generate_chat_completion = chat_completion
|
||||
|
||||
|
||||
##################################
|
||||
#
|
||||
# Anthropic Messages API Compatible Endpoint
|
||||
#
|
||||
##################################
|
||||
|
||||
|
||||
from open_webui.utils.anthropic import (
|
||||
convert_anthropic_to_openai_payload,
|
||||
convert_openai_to_anthropic_response,
|
||||
openai_stream_to_anthropic_stream,
|
||||
)
|
||||
|
||||
|
||||
@app.post("/api/message")
|
||||
@app.post("/api/v1/messages") # Anthropic Messages API compatible endpoint
|
||||
async def generate_messages(
|
||||
request: Request,
|
||||
form_data: dict,
|
||||
user=Depends(get_verified_user),
|
||||
):
|
||||
"""
|
||||
Anthropic Messages API compatible endpoint.
|
||||
|
||||
Accepts the Anthropic Messages API format, converts internally to OpenAI
|
||||
Chat Completions format, routes through the existing chat completion
|
||||
pipeline, then converts the response back to Anthropic Messages format.
|
||||
|
||||
Supports both streaming and non-streaming requests.
|
||||
All models configured in Open WebUI are accessible via this endpoint.
|
||||
|
||||
Authentication: Supports both standard Authorization header and
|
||||
Anthropic's x-api-key header (via middleware translation).
|
||||
"""
|
||||
# Convert Anthropic payload to OpenAI format
|
||||
requested_model = form_data.get("model", "")
|
||||
|
||||
openai_payload = convert_anthropic_to_openai_payload(form_data)
|
||||
|
||||
# Route through the existing chat_completion handler
|
||||
response = await chat_completion(request, openai_payload, user)
|
||||
|
||||
# Convert response back to Anthropic format
|
||||
if isinstance(response, StreamingResponse):
|
||||
# Streaming response: wrap the generator to convert SSE format
|
||||
return StreamingResponse(
|
||||
openai_stream_to_anthropic_stream(
|
||||
response.body_iterator, model=requested_model
|
||||
),
|
||||
media_type="text/event-stream",
|
||||
headers={
|
||||
"Cache-Control": "no-cache",
|
||||
"Connection": "keep-alive",
|
||||
},
|
||||
)
|
||||
elif isinstance(response, dict):
|
||||
return convert_openai_to_anthropic_response(response, model=requested_model)
|
||||
else:
|
||||
# Passthrough for error responses (JSONResponse, PlainTextResponse, etc.)
|
||||
return response
|
||||
|
||||
|
||||
|
||||
@app.post("/api/chat/completed")
|
||||
async def chat_completed(
|
||||
request: Request, form_data: dict, user=Depends(get_verified_user)
|
||||
|
||||
Reference in New Issue
Block a user