mirror of
https://github.com/Warky-Devs/vecna.git
synced 2026-08-07 10:47:38 +00:00
1953a4f4f9
* implement proxy handler for various OpenAI API routes * add error handling for request body and response streaming * introduce new error response format for API compatibility * add tests for recover middleware to handle panics gracefully
453 lines
12 KiB
YAML
453 lines
12 KiB
YAML
openapi: "3.1.0"
|
|
info:
|
|
title: vecna Embedding Adapter
|
|
description: >
|
|
Proxies text to a backing embedding model and adapts the result vectors
|
|
between dimensions. Also forwards the rest of the OpenAI-compatible API
|
|
surface (chat, completions, models, audio, images, moderations, rerank)
|
|
verbatim to the resolved target, with no adaptation applied.
|
|
version: "1.0.0"
|
|
|
|
servers:
|
|
- url: http://localhost:8080
|
|
|
|
security:
|
|
- BearerAuth: []
|
|
|
|
components:
|
|
securitySchemes:
|
|
BearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
|
|
schemas:
|
|
Error:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
type:
|
|
type: string
|
|
code:
|
|
type: integer
|
|
|
|
OpenAIEmbedRequest:
|
|
type: object
|
|
required: [input, model]
|
|
properties:
|
|
input:
|
|
oneOf:
|
|
- type: string
|
|
- type: array
|
|
items:
|
|
type: string
|
|
model:
|
|
type: string
|
|
|
|
OpenAIEmbedResponse:
|
|
type: object
|
|
properties:
|
|
object:
|
|
type: string
|
|
example: list
|
|
model:
|
|
type: string
|
|
data:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
object:
|
|
type: string
|
|
example: embedding
|
|
index:
|
|
type: integer
|
|
embedding:
|
|
type: array
|
|
items:
|
|
type: number
|
|
format: float
|
|
usage:
|
|
type: object
|
|
properties:
|
|
prompt_tokens:
|
|
type: integer
|
|
total_tokens:
|
|
type: integer
|
|
|
|
GoogleEmbedContentRequest:
|
|
type: object
|
|
required: [content]
|
|
properties:
|
|
content:
|
|
type: object
|
|
properties:
|
|
parts:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
text:
|
|
type: string
|
|
taskType:
|
|
type: string
|
|
|
|
GoogleEmbedContentResponse:
|
|
type: object
|
|
properties:
|
|
embedding:
|
|
type: object
|
|
properties:
|
|
values:
|
|
type: array
|
|
items:
|
|
type: number
|
|
format: float
|
|
|
|
GoogleBatchRequest:
|
|
type: object
|
|
required: [requests]
|
|
properties:
|
|
requests:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/GoogleEmbedContentRequest'
|
|
|
|
GoogleBatchResponse:
|
|
type: object
|
|
properties:
|
|
embeddings:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
values:
|
|
type: array
|
|
items:
|
|
type: number
|
|
format: float
|
|
|
|
headers:
|
|
X-Vecna-Forward-Ms:
|
|
description: Time spent forwarding the request to the backing model (milliseconds).
|
|
schema:
|
|
type: integer
|
|
X-Vecna-Translate-Ms:
|
|
description: Time spent in the dimension adapter (milliseconds).
|
|
schema:
|
|
type: integer
|
|
X-Vecna-Total-Ms:
|
|
description: Total request wall-clock time (milliseconds).
|
|
schema:
|
|
type: integer
|
|
|
|
paths:
|
|
/v1/embeddings:
|
|
post:
|
|
summary: OpenAI-compatible embeddings
|
|
operationId: openaiEmbeddings
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/OpenAIEmbedRequest'
|
|
responses:
|
|
"200":
|
|
description: Adapted embeddings
|
|
headers:
|
|
X-Vecna-Forward-Ms:
|
|
$ref: '#/components/headers/X-Vecna-Forward-Ms'
|
|
X-Vecna-Translate-Ms:
|
|
$ref: '#/components/headers/X-Vecna-Translate-Ms'
|
|
X-Vecna-Total-Ms:
|
|
$ref: '#/components/headers/X-Vecna-Total-Ms'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/OpenAIEmbedResponse'
|
|
"400":
|
|
description: Bad request
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Error'
|
|
"401":
|
|
description: Unauthorized
|
|
"502":
|
|
description: Backing model error
|
|
|
|
get:
|
|
summary: OpenAI-compatible embeddings (query-param convenience form)
|
|
operationId: openaiEmbeddingsGet
|
|
parameters:
|
|
- name: input
|
|
in: query
|
|
required: true
|
|
description: Repeatable — one or more texts to embed.
|
|
schema:
|
|
type: array
|
|
items:
|
|
type: string
|
|
- name: model
|
|
in: query
|
|
schema:
|
|
type: string
|
|
responses:
|
|
"200":
|
|
description: Adapted embeddings
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/OpenAIEmbedResponse'
|
|
"400":
|
|
description: Bad request
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Error'
|
|
"401":
|
|
description: Unauthorized
|
|
"502":
|
|
description: Backing model error
|
|
|
|
/v1/models/{model}:embedContent:
|
|
post:
|
|
summary: Google-compatible single embedContent
|
|
operationId: googleEmbedContent
|
|
parameters:
|
|
- name: model
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/GoogleEmbedContentRequest'
|
|
responses:
|
|
"200":
|
|
description: Adapted embedding
|
|
headers:
|
|
X-Vecna-Forward-Ms:
|
|
$ref: '#/components/headers/X-Vecna-Forward-Ms'
|
|
X-Vecna-Translate-Ms:
|
|
$ref: '#/components/headers/X-Vecna-Translate-Ms'
|
|
X-Vecna-Total-Ms:
|
|
$ref: '#/components/headers/X-Vecna-Total-Ms'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/GoogleEmbedContentResponse'
|
|
"400":
|
|
description: Bad request
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Error'
|
|
"401":
|
|
description: Unauthorized
|
|
"502":
|
|
description: Backing model error
|
|
|
|
/v1/models/{model}:batchEmbedContents:
|
|
post:
|
|
summary: Google-compatible batch batchEmbedContents
|
|
operationId: googleBatchEmbedContents
|
|
parameters:
|
|
- name: model
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/GoogleBatchRequest'
|
|
responses:
|
|
"200":
|
|
description: Adapted embeddings
|
|
headers:
|
|
X-Vecna-Forward-Ms:
|
|
$ref: '#/components/headers/X-Vecna-Forward-Ms'
|
|
X-Vecna-Translate-Ms:
|
|
$ref: '#/components/headers/X-Vecna-Translate-Ms'
|
|
X-Vecna-Total-Ms:
|
|
$ref: '#/components/headers/X-Vecna-Total-Ms'
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/GoogleBatchResponse'
|
|
"400":
|
|
description: Bad request
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Error'
|
|
"401":
|
|
description: Unauthorized
|
|
"502":
|
|
description: Backing model error
|
|
|
|
# --- Generic OpenAI-compatible passthrough -------------------------------
|
|
# Forwarded verbatim to the resolved target (chosen by the body's "model"
|
|
# field, falling back to forward.default). No vecna-specific processing —
|
|
# request/response shape is whatever the backing model's API defines.
|
|
# Each also exists under /map/{mapping}/... to force a specific target.
|
|
/v1/models:
|
|
get:
|
|
summary: List models (passthrough)
|
|
operationId: listModels
|
|
responses:
|
|
"200":
|
|
description: Backend-defined model list
|
|
"401":
|
|
description: Unauthorized
|
|
"502":
|
|
description: Backing model error
|
|
|
|
/v1/models/{model}:
|
|
get:
|
|
summary: Retrieve a model (passthrough)
|
|
operationId: retrieveModel
|
|
parameters:
|
|
- name: model
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
"200":
|
|
description: Backend-defined model object
|
|
"401":
|
|
description: Unauthorized
|
|
"502":
|
|
description: Backing model error
|
|
|
|
/v1/chat/completions:
|
|
post:
|
|
summary: Chat completions (passthrough, streaming supported)
|
|
operationId: chatCompletions
|
|
responses:
|
|
"200":
|
|
description: Backend-defined chat completion (or SSE stream if "stream":true)
|
|
"401":
|
|
description: Unauthorized
|
|
"502":
|
|
description: Backing model error
|
|
|
|
/v1/completions:
|
|
post:
|
|
summary: Legacy completions (passthrough, streaming supported)
|
|
operationId: completions
|
|
responses:
|
|
"200":
|
|
description: Backend-defined completion (or SSE stream if "stream":true)
|
|
"401":
|
|
description: Unauthorized
|
|
"502":
|
|
description: Backing model error
|
|
|
|
/v1/moderations:
|
|
post:
|
|
summary: Moderations (passthrough)
|
|
operationId: moderations
|
|
responses:
|
|
"200":
|
|
description: Backend-defined moderation result
|
|
"401":
|
|
description: Unauthorized
|
|
"502":
|
|
description: Backing model error
|
|
|
|
/v1/images/generations:
|
|
post:
|
|
summary: Image generation (passthrough)
|
|
operationId: imageGenerations
|
|
responses:
|
|
"200":
|
|
description: Backend-defined image result
|
|
"401":
|
|
description: Unauthorized
|
|
"502":
|
|
description: Backing model error
|
|
|
|
/v1/images/edits:
|
|
post:
|
|
summary: Image edits (passthrough, multipart/form-data)
|
|
operationId: imageEdits
|
|
responses:
|
|
"200":
|
|
description: Backend-defined image result
|
|
"401":
|
|
description: Unauthorized
|
|
"502":
|
|
description: Backing model error
|
|
|
|
/v1/images/variations:
|
|
post:
|
|
summary: Image variations (passthrough, multipart/form-data)
|
|
operationId: imageVariations
|
|
responses:
|
|
"200":
|
|
description: Backend-defined image result
|
|
"401":
|
|
description: Unauthorized
|
|
"502":
|
|
description: Backing model error
|
|
|
|
/v1/audio/speech:
|
|
post:
|
|
summary: Text-to-speech (passthrough)
|
|
operationId: audioSpeech
|
|
responses:
|
|
"200":
|
|
description: Backend-defined audio bytes
|
|
"401":
|
|
description: Unauthorized
|
|
"502":
|
|
description: Backing model error
|
|
|
|
/v1/audio/transcriptions:
|
|
post:
|
|
summary: Speech-to-text (passthrough, multipart/form-data)
|
|
operationId: audioTranscriptions
|
|
responses:
|
|
"200":
|
|
description: Backend-defined transcription
|
|
"401":
|
|
description: Unauthorized
|
|
"502":
|
|
description: Backing model error
|
|
|
|
/v1/audio/translations:
|
|
post:
|
|
summary: Speech translation (passthrough, multipart/form-data)
|
|
operationId: audioTranslations
|
|
responses:
|
|
"200":
|
|
description: Backend-defined translation
|
|
"401":
|
|
description: Unauthorized
|
|
"502":
|
|
description: Backing model error
|
|
|
|
/v1/rerank:
|
|
post:
|
|
summary: Rerank (passthrough — Cohere/Infinity/vLLM-style)
|
|
operationId: rerank
|
|
responses:
|
|
"200":
|
|
description: Backend-defined rerank result
|
|
"401":
|
|
description: Unauthorized
|
|
"502":
|
|
description: Backing model error
|