Configure the OpenAI-compatible endpoint and model #220
Closed
opened 2026-08-25 02:21:39 +01:00 by naps62-yolo
·
1 comment
No Branch/Tag Specified
main
ui-mobile-first
codex/fix-action-button-reload
translation
qbit-2
docker
bugs
blitz/subtitles
fix/255-provider-reorder
blitz/feedback-3
subtitles/251-icon-vocab
subtitles/237-relocate-subs
fix/248-title-move-creates-root
blitz/feedback-2
issue/227-abandoned-pack-visible
issue/245-backoff-anchor
issue/240-design-coherence
issue/211-waived-rule
issue/232-plainer-words
issue/246-policy-reclassify
issue/244-root-slash-stored
issue/231-settings-rows
issue/241-reclassify-on-root-change
issue/239-failure-window
issue/230-icon-only
issue/243-root-path-edges
issue/238-attention-liveness
issue/229-back-button
issue/236-root-path-move
issue/226-attention-threshold
issue/228-root-move
blitz/size-bands
size-bands/209-runtime-scale
size-bands/210-size-waiver
size-bands/208-runtime-design
blitz/reliability
reliability/155-sqlx-migrations
reliability/176-refresh-on-add
removal-nav/175-removal-controls
removal-nav/174-season-file-removal
removal-nav/172-search-titles
removal-nav/173-homepage-library
removal-nav/171-untrack-clears
removal-nav/170-chip-align
removal-nav/169-design-amendment
feedback/167-deck-autosearch
feedback/165-chip-colour
feedback/166-header-rail
feedback/163-drop-cast
feedback/164-control-geometry
feedback/162-season-ordering
feedback/161-search-episodes
feedback/160-autotrack-seed
feedback/159-design-amend
blitz/rich-metadata
rich/151-grid
rich/148-search-rows
rich/150-series-meta
rich/149-movie-page
rich/147-search-art
rich/156-rating-null
rich/146-meta-api
rich/145-poster-cols
rich/144-trailer
rich/143-meta-detail
rich/142-design-amend
blitz/153-empty-episode-titles
blitz/152-deck-routes
blitz/141-season-vanished-api
blitz/129-series-detail-view
blitz/140-attention-episode-numbers
blitz/137-season-removals
blitz/133-attention-tv-lanes
blitz/139-movie-id-episode-guard
blitz/134-stale-attention-queue
blitz/124-rss-episode-matching
blitz/136-imdb-series-lookup
blitz/132-manual-commands
blitz/128-series-delete-files
blitz/131-status-seasons-input
blitz/138-plural-season-range
blitz/135-pack-name-parse
blitz/122-upstream-removals
blitz/130-add-series-search
blitz/121-series-refresh
blitz/127-unified-search-tv
blitz/123-episode-matching
blitz/126-tv-attention
blitz/119-tracked-rule
blitz/125-season-deck
blitz/120-tvdb-id
blitz/118-season-zero
blitz/117-design-amend
issue/115-avail-search
issue/112-name-truncate
issue/111-score-colors
No results found.
Labels
Clear labels
area/api
area/ci
area/compat
area/core
area/daemon
area/db
area/dl
area/indexer
area/infra
area/meta
area/parse
area/probe
area/subs
area/web
difficulty/easy
difficulty/hard
difficulty/moderate
difficulty/trivial
phase/1-skeleton
phase/2-logic
phase/3-sourcing
phase/4-movies
phase/5-ui
phase/6-tv
phase/7-people
phase/8-compat
phase/9-subtitles
type/bug
type/chore
type/feature
type/test
arr-api
CI and test harness
arr-compat
arr-core
arr-daemon
arr-db
arr-dl
arr-indexer
workspace and tooling
arr-meta
arr-parse
arr-probe
arr-subs crate: providers, extraction, translation, sync
web/
bounded, obvious approach, few files
subtle correctness or cross-cutting
multiple files, judgement, an interface to design
one file, mechanical, no design decisions
workspace, CI, config, database, empty API and SPA
parsing and policy engine, pure, no network
TMDB and Prowlarr, read-only
movies end to end
search, buckets, library views, queues
seasons, episodes, tracking, derived status
owner tags and notifications
Jellyseerr shim
build order: subtitles, DESIGN.md §15
Projects
Clear projects
No projects
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: yolo/arr#220
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Decided by the operator; DESIGN.md §15 amended in
ab001b5. Implement that.The OpenAI-compatible backend's base URL and model name are database rows,
in
subtitle_settingsbesidetranslation_engine, editable from/settingswithout a restart. Only the API key stays in the environment.
The reasoning §15 now records: that backend is not "OpenAI", it is anything
speaking that request shape —
llama.cpp, a local gateway, a hosted provider.Which endpoint and which model are in use is something the operator tries and
changes, not a property of the deployment fixed at start-up.
What to do
0028— this number is yours; #222 takes0029. (0026 belongs to another milestone, 0027 is taken.)add
openai_base_urlandopenai_modeltosubtitle_settings. Bothnullable; a null base URL means the backend's own default.
ARR_TRANSLATE_OPENAI_MODEL/translate_openai_modelandARR_TRANSLATE_OPENAI_BASE_URL/translate_openai_base_urlfromarr-daemon's config. #216 added the modelone as an explicit stopgap; this replaces it.
ARR_TRANSLATE_OPENAI_API_KEYstays — it is a secret, and §10 keeps those out of the database.
llama.cppserves withoutauthentication, so the backend must be constructible with a base URL and no
API key. Do not gate construction on the key being present.
remote-command timeout:
OpenAishould re-read base URL and model pertranslation, or the settings handler should rebuild it. #219's shared-cell
approach in
crates/arr-subs/src/command.rsis the precedent — follow itrather than inventing a second mechanism.
/settings: two fields in the SUBTITLES section (#204), shown whenopenaiis amongavailable_engines. Neither is a secret, so both rendernormally. Placeholder text should make clear a base URL is optional and
what a local one looks like.
field, consistent with how
translation_engineis already validated.Note the health lamp (#200) probes the OpenAI-compatible engine via
models;it must probe whatever base URL is currently configured, not a start-up copy.
Depends on: #191, #198, #204, #216, #219
Decide where the OpenAI model name is configuredto Configure the OpenAI-compatible endpoint and modelImplemented on
subtitles/220-openai-endpoint.openai_base_urlandopenai_modelare nowsubtitle_settingscolumns(migration
0028), both nullable, NULL meaning the backend's own default.The backend reads them from an
OpenAiEndpointcell it re-checks on everytranslate and every probe, so an edit reaches the running process without a
restart — the same shape #219 built for the remote-command timeout. The
daemon seeds that cell from the row at startup and the settings handler
repoints it on every PUT, which also moves the health lamp: verified live
against a stub
modelsendpoint, the lamp went fromunreachabletookon the PUT alone.
ARR_TRANSLATE_OPENAI_MODEL/translate_openai_modelandARR_TRANSLATE_OPENAI_BASE_URL/translate_openai_base_urlare gone.deny_unknown_fieldsturns a config file that still carries either into aparse error, so an operator upgrading sees the move rather than a silently
ignored setting.
ARR_TRANSLATE_OPENAI_API_KEYstays, and constructionnever depends on it — a
llama.cppendpoint with no key is valid./settingsgets the two fields as their own labelled row under theSUBTITLES section, shown when
openaiis amongavailable_engines.Placeholders say the base URL is optional and show a local one. A base URL
that does not parse is a 422 naming the field. A base URL typed without a
trailing slash is normalised, so
http://box:8080/v1reaches/v1/chat/completionsrather than the host root.just cipassed: 714 tests, clippy clean, web typecheck and token check clean.Findings
OpenAiEndpointhad to live in its own ungated module(
arr-subs/src/openai_endpoint.rs) rather than inopenai.rs, becausepub mod openaiis behindtranslate-openaiwhilearr-apimust validateand hold the endpoint in every build — the columns exist whether or not the
backend was compiled in. Worth knowing before the next settings field that
belongs to a feature-gated backend: the same split will be needed.
arr-apihas notranslate-*features of its own and depends onarr-subswithout them, so any
#[cfg(feature = "translate-openai")]written insidearr-apiis always false. Nothing in the tree does that today, but it is aneasy mistake for a later issue to make and it fails silently rather than at
compile time.
not
commandis amongavailable_engines, unlike the new OpenAI fields.Not in scope here; worth an issue if the inconsistency matters.