Files
2026-05-30 13:19:58 +08:00

18 KiB
Raw Permalink Blame History

API Reference

Complete reference for the AHA REST API.

Overview

AHA provides an OpenAI-compatible REST API for running AI model inference. All endpoints follow standard HTTP conventions and return JSON responses.

Base URL

By default, the API server runs on:

http://127.0.0.1:10100

You can customize this when starting the service:

aha cli -m Qwen/Qwen3-0.6B -a 0.0.0.0 -p 8080

Authentication

Currently, AHA does not require authentication. All endpoints are publicly accessible on the configured address/port.

Security Note: If you expose the API to external networks, consider implementing authentication through a reverse proxy (e.g., nginx, traefik).

Content Types

All requests should use:

Content-Type: application/json

Response Format

Success responses follow this structure:

{
  "data": { ... },
  "model": "model-name",
  "usage": {
    "total_tokens": 30
  }
}

Error responses:

{
  "error": {
    "message": "Error description",
    "type": "error_type",
    "code": "error_code"
  }
}

Endpoints

Health Check

Check the service health status. This endpoint is useful for container orchestration (Kubernetes), load balancers, and monitoring systems.

Endpoint

GET /health

Response

Healthy (HTTP 200):

{
  "status": "ok"
}

Unhealthy (HTTP 503):

{
  "status": "unhealthy",
  "error": "model not initialized"
}

Example

curl http://127.0.0.1:10100/health

Models

Get information about the currently loaded model (OpenAI API compatible format).

Endpoint

GET /models

Response

Success (HTTP 200):

{
  "object": "list",
  "data": [
    {
      "id": "Qwen/Qwen3-0.6B",
      "object": "model",
      "created": null,
      "owned_by": "Qwen"
    }
  ]
}

Not Initialized (HTTP 503):

{
  "error": "model not initialized"
}

Fields

Field Type Description
object string Fixed value: "list"
data array Array of model objects (currently contains one loaded model)
id string Model identifier in kebab-case (e.g., "Qwen/Qwen3-0.6B")
object string Fixed value: "model"
created integer|null Unix timestamp (currently null)
owned_by string Model owner/organization name

Example

curl http://127.0.0.1:10100/models

Chat Completions

Generate chat completions or text responses.

Endpoint

POST /chat/completions

Request Body

Parameter Type Required Description
model string Yes Model identifier (e.g., "Qwen/Qwen3-0.6B")
messages array Yes Array of message objects
temperature number No Sampling temperature (0-2, default: 1)
top_p number No Nucleus sampling (0-1, default: 1)
max_tokens integer No Maximum tokens to generate
stream boolean No Enable streaming (default: false)

Message Object

Field Type Required Description
role string Yes "system", "user", or "assistant"
content string/array Yes Message content (string or multimodal array)

Multimodal Content

For vision/audio models, content can be an array:

{
  "role": "user",
  "content": [
    {"type": "text", "text": "Describe this image"},
    {"type": "image", "image_url": {"url": "file:///path/to/image.jpg"}}
  ]
}

Supported content types:

  • text - Text content
  • image_url - Image file (file://, base64://, https:// or http://)
  • audio_url - Audio file (file://, base64://, https:// or http://)

Examples

Simple Chat:

curl http://127.0.0.1:10100/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen/Qwen3-0.6B",
    "messages": [
      {"role": "user", "content": "Hello!"}
    ]
  }'

With System Message:

curl http://127.0.0.1:10100/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen/Qwen3-0.6B",
    "messages": [
      {"role": "system", "content": "You are a helpful assistant."},
      {"role": "user", "content": "Explain Rust in one sentence."}
    ],
    "max_tokens": 50,
    "temperature": 0.7
  }'

Vision Understanding:

curl http://127.0.0.1:10100/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen/Qwen3-VL-2B-Instruct",
    "messages": [
      {
        "role": "user",
        "content": [
          {"type": "text", "text": "What is in this image?"},
          {"type": "image", "image_url": {"url": "file:///path/to/image.jpg"}}
        ]
      }
    ]
  }'

OCR (Text Extraction):

curl http://127.0.0.1:10100/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek-ai/DeepSeek-OCR",
    "messages": [
      {
        "role": "user",
        "content": [
          {"type": "text", "text": "Extract all text"},
          {"type": "image", "image_url": {"url": "file:///path/to/document.png"}}
        ]
      }
    ]
  }'

ASR (Speech Recognition):

curl http://127.0.0.1:10100/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "ZhipuAI/GLM-ASR-Nano-2512",
    "messages": [
      {
        "role": "user",
        "content": [
          {"type": "text", "text": "Transcribe this audio"},
          {"type": "audio", "audio_url": {"url": "file:///path/to/audio.wav"}}
        ]
      }
    ]
  }'

Note: For OpenAI-standard audio transcription with multipart/form-data file upload, see the Audio Transcriptions endpoint.

Streaming Response:

curl http://127.0.0.1:10100/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen/Qwen3-0.6B",
    "messages": [
      {"role": "user", "content": "Tell me a story"}
    ],
    "stream": true
  }'

Streaming responses are sent as Server-Sent Events (SSE):

data: {"id": "1", "choices": [{"delta": {"content": "Once"}}]}

data: {"id": "1", "choices": [{"delta": {"content": " upon"}}]}

data: [DONE]

Response

Non-streaming:

{
  "id": "chatcmpl-123",
  "object": "chat.completion",
  "created": 1677652288,
  "model": "Qwen/Qwen3-0.6B",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Hello! How can I help you today?"
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "total_tokens": 19
  }
}

Audio Speech

Generate speech from text (Text-to-Speech).

Endpoint

POST /audio/speech

Request Body

Parameter Type Required Description
model string Yes Model identifier (e.g., "OpenBMB/VoxCPM-1.5")
messages array Yes Array of message objects

Example

curl http://127.0.0.1:10100/audio/speech \
  -H "Content-Type: application/json" \
  -d '{
    "model": "OpenBMB/VoxCPM-1.5",
    "messages": [
      {
        "role": "user",
        "content": [
          {"type": "text", "text": "Hello, this is AHA speaking."}
        ]
      }
    ]
  }'

Response

Returns audio data in base64 WAV format.

Audio Transcriptions

Transcribe audio files to text (Automatic Speech Recognition).

This endpoint provides OpenAI-compatible audio transcription using multipart/form-data format.

Endpoints

POST /audio/transcriptions
POST /v1/audio/transcriptions

Both endpoints use the same handler and return identical responses. The /v1/audio/transcriptions path follows OpenAI's standard API convention.

Request Body

Parameter Type Required Description
file file Yes The audio file to transcribe (wav, mp3, m4a, etc.)
model string No Model identifier (optional, ignored - uses loaded model)
language string No Language code (e.g., "zh", "en", "yue")
prompt string No Optional text to guide transcription (not implemented, ignored)
response_format string No Response format, only "json" or "text" supported (default: "json")
temperature number No Sampling temperature (0.0 to 1.0, default: 0.0)

Supported Languages

Code Language Code Language
zh Chinese en English
yue Cantonese ar Arabic
de German fr French
es Spanish pt Portuguese
id Indonesian it Italian
ko Korean ru Russian
th Thai vi Vietnamese
ja Japanese tr Turkish
hi Hindi ms Malay
nl Dutch sv Swedish
da Danish fi Finnish
pl Polish cs Czech
fil Filipino fa Persian
el Greek ro Romanian
hu Hungarian mk Macedonian

Examples

Basic transcription:

curl -X POST http://127.0.0.1:10100/audio/transcriptions \
  -H "Authorization: Bearer NO_NEED" \
  -F file="@./audio.wav" \
  -F model="Qwen/Qwen3-ASR-0.6B"

With language specification:

curl -X POST http://127.0.0.1:10100/v1/audio/transcriptions \
  -H "Authorization: Bearer NO_NEED" \
  -F file="@./chinese_audio.wav" \
  -F model="Qwen/Qwen3-ASR-0.6B" \
  -F language="zh"

With temperature:

curl -X POST http://127.0.0.1:10100/v1/audio/transcriptions \
  -H "Authorization: Bearer NO_NEED" \
  -F file="@./audio.wav" \
  -F model="Qwen/Qwen3-ASR-0.6B" \
  -F temperature="0.0"

Response

Success (HTTP 200):

{
  "text": "Transcribed text from the audio file"
}

Error (HTTP 400):

{
  "error": {
    "message": "Audio file is required",
    "type": "invalid_request_error",
    "code": "missing_file"
  }
}

Error (HTTP 503):

{
  "error": {
    "message": "Model not initialized",
    "type": "service_unavailable",
    "code": "model_not_loaded"
  }
}

File Upload Limit

Maximum audio file size: 100 MB

Images Remove Background

Remove background from images.

Endpoint

POST /images/remove_background

Request Body

Parameter Type Required Description
model string Yes Model identifier (e.g., "AI-ModelScope/RMBG-2.0")
messages array Yes Array of message objects

Example

From File:

curl http://127.0.0.1:10100/images/remove_background \
  -H "Content-Type: application/json" \
  -d '{
    "model": "AI-ModelScope/RMBG-2.0",
    "messages": [
      {
        "role": "user",
        "content": [
          {"type": "image", "image_url": {"url": "file:///path/to/document.jpg"}}
        ]
      }
    ]
  }'

From Base64:

curl http://127.0.0.1:10100/images/remove_background \
  -H "Content-Type: application/json" \
  -d '{
    "model": "AI-ModelScope/RMBG-2.0",
    "messages": [
      {
        "role": "user",
        "content": [
          {"type": "image", "image_url": {"url": "base64://$(base64 -w 0 photo.png)"}}
        ]
      }
    ]
  }'

Response

Returns the processed image in base64 PNG format.

Embeddings

Generate text embeddings.

Endpoints

POST /embeddings
POST /v1/embeddings

Request Body

Parameter Type Required Description
model string No Model identifier (optional, ignored - uses loaded model)
input string or array Yes Text or array of texts to embed

Examples

Single text

curl http://127.0.0.1:10100/embeddings \
  -H "Content-Type: application/json" \
  -d '{
    "input": "Hello world"
  }'

Multiple texts

curl http://127.0.0.1:10100/embeddings \
  -H "Content-Type: application/json" \
  -d '{
    "input": ["Hello world", "How are you?", "Goodbye"]
  }'

Response

Success (HTTP 200):

{
  "object": "list",
  "data": [
    {
      "object": "embedding",
      "index": 0,
      "embedding": [0.1, 0.2, 0.3, ...]
    }
  ],
  "model": "model-name"
}

Error (HTTP 400):

{
  "error": "embedding input must be a string or an array of strings"
}

Rerank

Re-rank a list of documents according to a query.

Endpoint

POST /rerank
POST /v1/rerank

Request Body

Parameter Type Required Description
model string No 模型标识符
query string Yes Query text
documents array Yes Array of document texts to re-rank
top_n int No Return top N results (optional)

Example

Basic re-ranking

curl http://127.0.0.1:10100/rerank \
  -H "Content-Type: application/json" \
  -d '{
    "query": "artificial intelligence",
    "documents": [
      "Machine learning is a form of artificial intelligence",
      "Apple is a fruit",
      "Deep learning belongs to the field of artificial intelligence"
    ]
  }'

Limit return count

curl http://127.0.0.1:10100/rerank \
  -H "Content-Type: application/json" \
  -d '{
    "query": "artificial intelligence",
    "documents": [
      "Machine learning is a form of artificial intelligence",
      "Apple is a fruit", 
      "Deep learning belongs to the field of artificial intelligence"
    ],
    "top_n": 2
  }'

Response

Success (HTTP 200):

{
  "object": "list",
  "model": "model-name",
  "results": [
    {
      "index": 0,
      "relevance_score": 0.95,
      "document": "Machine learning is a form of artificial intelligence"
    },
    {
      "index": 2,
      "relevance_score": 0.87,
      "document": "Deep learning belongs to the field of artificial intelligence"
    }
  ]
}

Error (HTTP 400):

{
  "error": "rerank query cannot be empty"
}

Parameter Description

Parameter Type Description
model string Model identifier
object string Fixed value: "list"
results array Re-ranked results array
index int Original document index
relevance_score f32 Relevance score (higher is more relevant)
document string Original document text

Graceful Shutdown

Gracefully shut down the AHA server. This endpoint initiates a graceful shutdown process that:

  1. Stops accepting new connections
  2. Waits for existing requests to complete (up to 1 second)
  3. Cleans up PID files
  4. Exits the process

Endpoint

POST /shutdown

Request Body

None (empty request)

Response

Success (HTTP 200):

{
  "message": "Shutting down..."
}

Forbidden (HTTP 403):

When remote shutdown is not allowed:

{
  "error": "Remote shutdown not allowed. Use --allow-remote-shutdown flag to enable (not recommended)."
}

Security

By default, the shutdown endpoint only allows requests from localhost (127.0.0.1). To enable remote shutdown, start the server with the --allow-remote-shutdown flag:

aha serv -m Qwen/Qwen3-0.6B --allow-remote-shutdown

Warning: Enabling remote shutdown is not recommended for production use unless properly secured.

Example

curl -X POST http://127.0.0.1:10100/shutdown

Logging

All shutdown requests are logged to stderr with the format:

[SHUTDOWN] Shutdown requested (remote_allowed: false)

Error Handling

Error Codes

Code Description
400 Bad Request - Invalid parameters
404 Not Found - Model or endpoint not found
500 Internal Server Error - Model inference error
503 Service Unavailable - Model not loaded

Error Response Format

{
  "error": {
    "message": "Model 'unknown-model' not found",
    "type": "invalid_request_error",
    "code": "model_not_found"
  }
}

Rate Limiting

Currently, AHA does not implement rate limiting. The server can handle concurrent requests limited only by system resources.

File Upload Limits

  • String data: 5 MB
  • File uploads: 100 MB

OpenAI Compatibility

AHA's text generation API is designed to be compatible with OpenAI's API format. Multimodal APIs are derived from the text generation API with minimal changes:

Python Example

from openai import OpenAI

client = OpenAI(
    base_url="http://127.0.0.1:10100",
    api_key="dummy"  # Not used but required by library
)

response = client.chat.completions.create(
    model="Qwen/Qwen3-0.6B",
    messages=[
        {"role": "user", "content": "Hello!"}
    ]
)

print(response.choices[0].message.content)

JavaScript Example

import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'http://127.0.0.1:10100',
  apiKey: 'dummy'  // Not used but required
});

const response = await client.chat.completions.create({
  model: 'Qwen/Qwen3-0.6B',
  messages: [{ role: 'user', content: 'Hello!' }]
});

console.log(response.choices[0].message.content);

Best Practices

1. Use Streaming for Long Responses

For long text generation, use streaming to get responses incrementally:

curl ... -d '{"stream": true, ...}'

2. Set Appropriate Token Limits

Prevent excessively long responses:

{
  "max_tokens": 500
}

3. Adjust Temperature

Control response creativity:

  • 0.0-0.3: Deterministic, focused
  • 0.4-0.7: Balanced (default: 1.0)
  • 0.8-2.0: Creative, varied

4. Use System Messages

Set behavior with system messages:

{
  "messages": [
    {"role": "system", "content": "You are a technical writer."},
    {"role": "user", "content": "..."}
  ]
}

See Also