beatrice

GraphQL API for LLM-powered smart-novel features. The service is model-provider-agnostic — configure it against any OpenAI-compatible endpoint via env vars.

See the repo for setup and self-hosting instructions.

API Endpoints
<<url is missing>>

Endpoint

All operations are served at POST /graphql on the deployed instance.

Queries

audioVoices

Description

Voice names available for TTS synthesis, from the configured default provider. Cached for the process lifetime after the first call. English text only for now — this limitation will be addressed later.

Response

Returns [String!]!

Example

Query
query audioVoices {
  audioVoices
}
Response
{"data": {"audioVoices": ["xyz789"]}}

healthcheck

Description

Healthcheck API which returns basic info about the service and if it is running.

Response

Returns a HealthCheck!

Example

Query
query healthcheck {
  healthcheck {
    isRunning
    model
    version
  }
}
Response
{
  "data": {
    "healthcheck": {
      "isRunning": true,
      "model": "qwen2.5:3b",
      "version": "1.0.1"
    }
  }
}

Mutations

explainWord

Description

Return a structured explanation of a word as it is used in the given context.

Response

Returns a WordExplanationType!

Arguments
Name Description
word - String! The single word to explain. Must be 1..64 characters.
context - String! The sentence or paragraph the word appears in — used to disambiguate its meaning. Must be 1..2000 characters.

Example

Query
mutation explainWord(
  $word: String!,
  $context: String!
) {
  explainWord(
    word: $word,
    context: $context
  ) {
    meaning
    simplifiedExplanation
    synonyms
    antonyms
  }
}
Variables
{
  "word": "impulse",
  "context": "She acted on impulse and booked a flight home the same night."
}
Response
{
  "data": {
    "explainWord": {
      "meaning": "A sudden strong urge to do something impulsive.",
      "simplifiedExplanation": "A quick feeling that makes you want to do something without thinking.",
      "synonyms": ["urge", "whim", "impulse", "instinct"],
      "antonyms": ["hesitation", "deliberation", "restraint"]
    }
  }
}

generateAudio

Description

Queue a TTS synthesis job. Publishes to RabbitMQ and returns immediately (HTTP 202) with a jobId — actual synthesis and upload happen asynchronously; progress and completion are reported via statusCallbackUrl.

Response

Returns a GenerateAudioResult!

Arguments
Name Description
text - String! Text to synthesize. Length is capped by the GENERATE_AUDIO__MAX_TEXT_LENGTH env var.
voice - String! Voice name — must be one returned by audioVoices.
genUploadUrl - String! Callback Beatrice POSTs to when it needs a presigned upload URL. Host must be in the GENERATE_AUDIO__CALLBACK__ALLOWED_HOSTS allow-list.
statusCallbackUrl - String! Callback Beatrice POSTs progress/state updates to. Host must be in the GENERATE_AUDIO__CALLBACK__ALLOWED_HOSTS allow-list.
instruct - String Qwen3-TTS-only. A style guide applied to the whole call, e.g. 'A male narrator with a clear voice. Treat bracketed words like [dramatic] as emotion cues, not literal text.' text is never parsed or stripped by Beatrice — any inline tags in it are passed through verbatim for the model to interpret per this guide. Rejected when the configured provider isn't Qwen3-TTS. Default = null

Example

Query
mutation generateAudio(
  $text: String!,
  $voice: String!,
  $genUploadUrl: String!,
  $statusCallbackUrl: String!,
  $instruct: String
) {
  generateAudio(
    text: $text,
    voice: $voice,
    genUploadUrl: $genUploadUrl,
    statusCallbackUrl: $statusCallbackUrl,
    instruct: $instruct
  ) {
    jobId
  }
}
Variables
{
  "text": "The graffiti was ephemeral.",
  "voice": "abc123",
  "genUploadUrl": "xyz789",
  "statusCallbackUrl": "abc123",
  "instruct": null
}
Response
{"data": {"generateAudio": {"jobId": "550e8400-e29b-41d4-a716-446655440000"}}}

normalizeTextForTts

Description

Return an LLM-normalised version of the given text suitable for TTS.

Response

Returns a String!

Arguments
Name Description
text - String! Raw text to be normalised for TTS — numbers, acronyms, symbols, and dates are rewritten into the form a speech engine can read aloud naturally. Must be 1..4000 characters.

Example

Query
mutation normalizeTextForTts($text: String!) {
  normalizeTextForTts(text: $text)
}
Variables
{"text": "Dr. Smith met with 3 clients at 9am on 12/03/2024."}
Response
{"data": {"normalizeTextForTts": "xyz789"}}

Types

Boolean

Description

The Boolean scalar type represents true or false.

GenerateAudioResult

Description

Result of queuing a generateAudio job.

Fields
Field Name Description
jobId - String! UUID identifying this synthesis job. Use it to correlate statusCallbackUrl updates.
Example
{"jobId": "550e8400-e29b-41d4-a716-446655440000"}

HealthCheck

Description

Snapshot of service liveness and configured model.

Fields
Field Name Description
isRunning - Boolean! Always true when this resolver executes.
model - String! LLM model this service is currently configured to use.
version - String! Service version — matches the Docker Hub image tag published from the same commit.
Example
{"isRunning": true, "model": "qwen2.5:3b", "version": "1.0.1"}

String

Description

The String scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.

Example
"xyz789"

WordExplanationType

Description

Structured explanation of one word as it is used in a specific context.

Fields
Field Name Description
meaning - String! Concise dictionary-style definition of the word as used in context.
simplifiedExplanation - String! Same idea expressed for a younger or non-native reader.
synonyms - [String!]! Up to five words meaning roughly the same thing.
antonyms - [String!]! Up to five words meaning roughly the opposite.
Example
{
  "meaning": "A sudden strong urge to do something impulsive.",
  "simplifiedExplanation": "A quick feeling that makes you want to do something without thinking.",
  "synonyms": ["urge", "whim", "impulse", "instinct"],
  "antonyms": ["hesitation", "deliberation", "restraint"]
}