mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-01 17:00:21 +08:00
Merge remote-tracking branch 'origin/aether-rust-pioneer' into aether-rust-pioneer
# Conflicts: # crates/aether-data-contracts/src/repository/usage/mod.rs # crates/aether-data/src/repository/global_models/postgres.rs # crates/aether-data/src/repository/usage/postgres/mod.rs
This commit is contained in:
144
docs/api/embeddings.md
Normal file
144
docs/api/embeddings.md
Normal file
@@ -0,0 +1,144 @@
|
||||
# Embeddings API
|
||||
|
||||
Aether supports OpenAI compatible embedding requests through `POST /v1/embeddings`. Embedding requests are separate from chat and responses requests. They use `input`, never `messages`, and they are always non streaming.
|
||||
|
||||
## Quick Start
|
||||
|
||||
Run this against your Aether gateway URL with a user API key that can access the model and the `openai:embedding` API format.
|
||||
|
||||
```bash
|
||||
curl -sS "http://localhost:8084/v1/embeddings" \
|
||||
-H "Authorization: Bearer sk-your-aether-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"model": "text-embedding-3-small",
|
||||
"input": ["hello", "world"],
|
||||
"encoding_format": "float"
|
||||
}'
|
||||
```
|
||||
|
||||
## Public Endpoint
|
||||
|
||||
| Method | Path | Client API format | Route kind |
|
||||
| --- | --- | --- | --- |
|
||||
| `POST` | `/v1/embeddings` | `openai:embedding` | `embedding` |
|
||||
|
||||
The gateway classifies this endpoint as an OpenAI family embedding route with endpoint signature `openai:embedding`. It is not handled as chat or responses.
|
||||
|
||||
## Request Body
|
||||
|
||||
Required fields:
|
||||
|
||||
| Field | Type | Notes |
|
||||
| --- | --- | --- |
|
||||
| `model` | string | Must name a model allowed for the API key and user. Blank strings are rejected. |
|
||||
| `input` | string, string array, integer token array, or nested integer token arrays | Must be non empty. Empty strings, empty arrays, and nested arrays with empty token arrays are rejected. |
|
||||
|
||||
Optional fields that pass through the embedding conversion path when supported by the provider:
|
||||
|
||||
| Field | Notes |
|
||||
| --- | --- |
|
||||
| `encoding_format` | Passed to OpenAI compatible providers. |
|
||||
| `dimensions` | Passed to providers whose embedding request shape supports it. |
|
||||
| `user` | Passed to OpenAI compatible providers. |
|
||||
| `task` | Passed to Jina and OpenAI compatible embedding requests. Jina defaults to `text-matching` when no task is supplied. |
|
||||
|
||||
Accepted `input` shapes:
|
||||
|
||||
```json
|
||||
{ "model": "text-embedding-3-small", "input": "hello" }
|
||||
```
|
||||
|
||||
```json
|
||||
{ "model": "text-embedding-3-small", "input": ["hello", "world"] }
|
||||
```
|
||||
|
||||
```json
|
||||
{ "model": "text-embedding-3-small", "input": [1, 2, 3] }
|
||||
```
|
||||
|
||||
```json
|
||||
{ "model": "text-embedding-3-small", "input": [[1, 2], [3, 4]] }
|
||||
```
|
||||
|
||||
Use string or string array input when routing to Gemini or Doubao embedding providers. Token arrays are accepted by the OpenAI compatible public endpoint, but Gemini and Doubao provider request emitters require text input.
|
||||
|
||||
## Provider Format Mapping
|
||||
|
||||
Embedding routes can select only embedding provider API formats. Chat, responses, image, and generation formats are not valid provider targets for this request type.
|
||||
|
||||
| Provider API format | Upstream path shape | Provider request shape |
|
||||
| --- | --- | --- |
|
||||
| `openai:embedding` | `/v1/embeddings` | OpenAI compatible `{ "model", "input" }` payload. |
|
||||
| `jina:embedding` | `/v1/embeddings` | OpenAI compatible payload with a Jina `task`. Defaults to `text-matching` if omitted. |
|
||||
| `gemini:embedding` | `models/{model}:embedContent` | Single text input uses `content.parts[].text`. Multiple text inputs use `requests[].content.parts[].text`. |
|
||||
| `doubao:embedding` | `/embeddings/multimodal` | Text input is emitted as `input` items like `{ "type": "text", "text": "..." }`. |
|
||||
|
||||
Custom provider endpoint paths are available when the endpoint is configured for an embedding API format. Gemini custom paths can use `{model}` and `{action}`. For `gemini:embedding`, `{action}` expands to `embedContent`.
|
||||
|
||||
## Model And Catalog Requirements
|
||||
|
||||
To use embeddings through the gateway:
|
||||
|
||||
1. The global model should include embedding metadata, for example `supported_capabilities: ["embedding"]`, `config.model_type: "embedding"`, or `config.api_formats` with one of the embedding formats.
|
||||
2. The provider model or mapping must expose an embedding API format, one of `openai:embedding`, `gemini:embedding`, `jina:embedding`, or `doubao:embedding`.
|
||||
3. The user and API key must be allowed to access the model and the `openai:embedding` client API format.
|
||||
4. Public and admin catalog responses expose `supports_embedding` so clients can display embedding capability separately from chat.
|
||||
|
||||
Billing fails closed for embedding global models. A model marked as embedding capable must define either `default_price_per_request` or `default_tiered_pricing.tiers[].input_price_per_1m`. Missing request pricing and missing input token pricing cause the model record to be rejected instead of treated as free.
|
||||
|
||||
No schema migration is needed for embedding metadata. Existing model capability, config, provider mapping, API format, and pricing fields carry the data.
|
||||
|
||||
## Failure Behavior
|
||||
|
||||
The gateway validates deterministic request errors before local execution or provider transport.
|
||||
|
||||
| Case | Example request body or setup | Status | Error detail |
|
||||
| --- | --- | --- | --- |
|
||||
| Invalid JSON | `{` | `400` | `Embedding request JSON body is invalid` |
|
||||
| Missing model | `{ "input": "hello" }` | `400` | `Embedding request model is required` |
|
||||
| Empty input | `{ "model": "text-embedding-3-small", "input": [] }` | `400` | `Embedding request input is required` |
|
||||
| Chat `messages` payload | `{ "model": "text-embedding-3-small", "messages": [] }` | `400` | `Embedding request must use input, not chat messages` |
|
||||
| Streaming requested | `{ "model": "text-embedding-3-small", "input": "hello", "stream": true }` | `400` | `Embedding requests do not support streaming` |
|
||||
| Non JSON content type | `Content-Type: text/plain` with an embedding JSON body | `400` | `Embedding request content-type must be application/json` |
|
||||
| Chat only model | API key allows `text-embedding-3-small`, request uses `gpt-5` | `403` | The key is not allowed to access that model. |
|
||||
| Chat only API format | API key allows `openai:chat` but not `openai:embedding` | `403` | The key is not allowed to access `openai:embedding`. |
|
||||
|
||||
Failure examples:
|
||||
|
||||
```bash
|
||||
curl -sS "http://localhost:8084/v1/embeddings" \
|
||||
-H "Authorization: Bearer sk-your-aether-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"model":"text-embedding-3-small","messages":[]}'
|
||||
```
|
||||
|
||||
```bash
|
||||
curl -sS "http://localhost:8084/v1/embeddings" \
|
||||
-H "Authorization: Bearer sk-your-aether-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"input":"hello"}'
|
||||
```
|
||||
|
||||
```bash
|
||||
curl -sS "http://localhost:8084/v1/embeddings" \
|
||||
-H "Authorization: Bearer sk-your-aether-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"model":"text-embedding-3-small","input":[]}'
|
||||
```
|
||||
|
||||
```bash
|
||||
curl -sS "http://localhost:8084/v1/embeddings" \
|
||||
-H "Authorization: Bearer sk-your-aether-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"model":"text-embedding-3-small","input":"hello","stream":true}'
|
||||
```
|
||||
|
||||
```bash
|
||||
curl -sS "http://localhost:8084/v1/embeddings" \
|
||||
-H "Authorization: Bearer sk-your-aether-key" \
|
||||
-H "Content-Type: text/plain" \
|
||||
-d '{"model":"text-embedding-3-small","input":"hello"}'
|
||||
```
|
||||
|
||||
If a valid embedding request passes local validation but no usable provider transport is available, the gateway can return a provider or service availability error. That is different from the deterministic request validation errors above.
|
||||
58
docs/api/rerank.md
Normal file
58
docs/api/rerank.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# Rerank API
|
||||
|
||||
Aether exposes an OpenAI-compatible rerank surface at `POST /v1/rerank` and can route it to providers configured as `openai:rerank` or `jina:rerank`.
|
||||
|
||||
## Request
|
||||
|
||||
```http
|
||||
POST /v1/rerank
|
||||
Authorization: Bearer <aether-api-key>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"model": "bge-reranker-base",
|
||||
"query": "What document discusses gateway routing?",
|
||||
"documents": [
|
||||
"Aether routes public AI requests through the Rust gateway.",
|
||||
"This document discusses unrelated content."
|
||||
],
|
||||
"top_n": 1,
|
||||
"return_documents": true
|
||||
}
|
||||
```
|
||||
|
||||
Fields:
|
||||
|
||||
| Field | Required | Notes |
|
||||
| --- | --- | --- |
|
||||
| `model` | Yes | Aether global model name. |
|
||||
| `query` | Yes | Non-empty query string. |
|
||||
| `documents` | Yes | Non-empty array of strings or provider-native document objects. |
|
||||
| `top_n` | No | Positive integer. |
|
||||
| `return_documents` | No | Provider-compatible flag for including matched documents. |
|
||||
|
||||
## Response
|
||||
|
||||
Aether forwards the provider JSON response. OpenAI-compatible and Jina-compatible rerank providers commonly return `results[]`:
|
||||
|
||||
```json
|
||||
{
|
||||
"model": "bge-reranker-base",
|
||||
"results": [
|
||||
{
|
||||
"index": 0,
|
||||
"relevance_score": 0.98,
|
||||
"document": {
|
||||
"text": "Aether routes public AI requests through the Rust gateway."
|
||||
}
|
||||
}
|
||||
],
|
||||
"usage": {
|
||||
"total_tokens": 32
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Rerank requests must be JSON and do not support `stream` or chat `messages` payloads.
|
||||
Reference in New Issue
Block a user