# OmniRoute Auto-Combo Engine (Latviešu) 🌐 **Languages:** 🇺🇸 [English](../../../../routing/AUTO-COMBO.md) · 🇪🇹 [am](../../../am/docs/routing/AUTO-COMBO.md) · 🇸🇦 [ar](../../../ar/docs/routing/AUTO-COMBO.md) · 🇦🇿 [az](../../../az/docs/routing/AUTO-COMBO.md) · 🇧🇬 [bg](../../../bg/docs/routing/AUTO-COMBO.md) · 🇧🇩 [bn](../../../bn/docs/routing/AUTO-COMBO.md) · 🇧🇦 [bs](../../../bs/docs/routing/AUTO-COMBO.md) · 🇨🇿 [cs](../../../cs/docs/routing/AUTO-COMBO.md) · 🇩🇰 [da](../../../da/docs/routing/AUTO-COMBO.md) · 🇩🇪 [de](../../../de/docs/routing/AUTO-COMBO.md) · 🇬🇷 [el](../../../el/docs/routing/AUTO-COMBO.md) · 🇪🇸 [es](../../../es/docs/routing/AUTO-COMBO.md) · 🇪🇪 [et](../../../et/docs/routing/AUTO-COMBO.md) · 🇮🇷 [fa](../../../fa/docs/routing/AUTO-COMBO.md) · 🇫🇮 [fi](../../../fi/docs/routing/AUTO-COMBO.md) · 🇫🇷 [fr](../../../fr/docs/routing/AUTO-COMBO.md) · 🇮🇪 [ga](../../../ga/docs/routing/AUTO-COMBO.md) · 🇮🇳 [gu](../../../gu/docs/routing/AUTO-COMBO.md) · 🇳🇬 [ha](../../../ha/docs/routing/AUTO-COMBO.md) · 🇮🇱 [he](../../../he/docs/routing/AUTO-COMBO.md) · 🇮🇳 [hi](../../../hi/docs/routing/AUTO-COMBO.md) · 🇭🇷 [hr](../../../hr/docs/routing/AUTO-COMBO.md) · 🇭🇺 [hu](../../../hu/docs/routing/AUTO-COMBO.md) · 🇦🇲 [hy](../../../hy/docs/routing/AUTO-COMBO.md) · 🇮🇩 [id](../../../id/docs/routing/AUTO-COMBO.md) · 🇳🇬 [ig](../../../ig/docs/routing/AUTO-COMBO.md) · 🇮🇹 [it](../../../it/docs/routing/AUTO-COMBO.md) · 🇯🇵 [ja](../../../ja/docs/routing/AUTO-COMBO.md) · 🇬🇪 [ka](../../../ka/docs/routing/AUTO-COMBO.md) · 🇰🇭 [km](../../../km/docs/routing/AUTO-COMBO.md) · 🇮🇳 [kn](../../../kn/docs/routing/AUTO-COMBO.md) · 🇰🇷 [ko](../../../ko/docs/routing/AUTO-COMBO.md) · 🇱🇹 [lt](../../../lt/docs/routing/AUTO-COMBO.md) · 🇮🇳 [ml](../../../ml/docs/routing/AUTO-COMBO.md) · 🇮🇳 [mr](../../../mr/docs/routing/AUTO-COMBO.md) · 🇲🇾 [ms](../../../ms/docs/routing/AUTO-COMBO.md) · 🇲🇹 [mt](../../../mt/docs/routing/AUTO-COMBO.md) · 🇲🇲 [my](../../../my/docs/routing/AUTO-COMBO.md) · 🇳🇵 [ne](../../../ne/docs/routing/AUTO-COMBO.md) · 🇳🇱 [nl](../../../nl/docs/routing/AUTO-COMBO.md) · 🇳🇴 [no](../../../no/docs/routing/AUTO-COMBO.md) · 🇮🇳 [or](../../../or/docs/routing/AUTO-COMBO.md) · 🇮🇳 [pa](../../../pa/docs/routing/AUTO-COMBO.md) · 🇵🇭 [phi](../../../phi/docs/routing/AUTO-COMBO.md) · 🇵🇱 [pl](../../../pl/docs/routing/AUTO-COMBO.md) · 🇵🇹 [pt](../../../pt/docs/routing/AUTO-COMBO.md) · 🇧🇷 [pt-BR](../../../pt-BR/docs/routing/AUTO-COMBO.md) · 🇷🇴 [ro](../../../ro/docs/routing/AUTO-COMBO.md) · 🇷🇺 [ru](../../../ru/docs/routing/AUTO-COMBO.md) · 🇱🇰 [si](../../../si/docs/routing/AUTO-COMBO.md) · 🇸🇰 [sk](../../../sk/docs/routing/AUTO-COMBO.md) · 🇸🇮 [sl](../../../sl/docs/routing/AUTO-COMBO.md) · 🇷🇸 [sr](../../../sr/docs/routing/AUTO-COMBO.md) · 🇸🇪 [sv](../../../sv/docs/routing/AUTO-COMBO.md) · 🇰🇪 [sw](../../../sw/docs/routing/AUTO-COMBO.md) · 🇮🇳 [ta](../../../ta/docs/routing/AUTO-COMBO.md) · 🇮🇳 [te](../../../te/docs/routing/AUTO-COMBO.md) · 🇹🇭 [th](../../../th/docs/routing/AUTO-COMBO.md) · 🇹🇷 [tr](../../../tr/docs/routing/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../../../uk-UA/docs/routing/AUTO-COMBO.md) · 🇵🇰 [ur](../../../ur/docs/routing/AUTO-COMBO.md) · 🇺🇿 [uz](../../../uz/docs/routing/AUTO-COMBO.md) · 🇻🇳 [vi](../../../vi/docs/routing/AUTO-COMBO.md) · 🇳🇬 [yo](../../../yo/docs/routing/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../../../zh-CN/docs/routing/AUTO-COMBO.md) · 🇹🇼 [zh-TW](../../../zh-TW/docs/routing/AUTO-COMBO.md) --- > **Lietotājiem**: Vai meklējat ātru darba sākšanu? Vienkāršus skaidrojumus un piemērus skatiet [Auto-Combo lietotāja rokasgrāmatā](../getting-started/AUTO-COMBO-GUIDE.md). > Pašpārvaldošas modeļu ķēdes ar adaptīvu vērtēšanu + automātisku maršrutēšanu bez konfigurācijas ## Automātiskā maršrutēšana bez konfigurācijas (`auto/` prefikss) > **JAUNUMS:** Kombinācija nav jāveido. Izmantojiet `auto/` prefiksu tieši jebkurā klientā. ### Īsi piemēri | Modeļa ID | Variants | Darbība | | -------------- | -------- | ----------------------------------------------------------------------------------- | | `auto` | default | Visi pievienotie nodrošinātāji, LKGP stratēģija, līdzsvaroti svari | | `auto/coding` | coding | Uz kvalitāti orientēti svari, piemēroti koda ģenerēšanai | | `auto/fast` | fast | Svērta atlase ar zemu latentumu | | `auto/cheap` | cheap | Izmaksu ziņā optimizēta maršrutēšana (vispirms zemākās izmaksas) | | `auto/offline` | offline | Dod priekšroku nodrošinātājiem ar vislielāko pieejamo kvotu | | `auto/smart` | smart | Prioritāte kvalitātei + lielāks izpētes koeficients (10%) labākai modeļu atklāšanai | | `auto/lkgp` | lkgp | Nepārprotams LKGP (tas pats, kas noklusējuma `auto`) | | `auto/chaos` | chaos | Paralēla izsūtīšana, viens modelis katram nodrošinātājam (nevis kļūmju injicēšana) | ### Kategorijas × līmeņa kompozīcija (`auto/:`) OpenRouter stila sufiksi nodala **maršruta veidu** (kategoriju) no **tā optimizācijas veida** (līmeņa), tāpēc tos var brīvi kombinēt (#4235 Phase B, `open-sse/services/autoCombo/suffixComposition.ts`): - **Kategorijas** (filtrē kandidātu kopu pēc iespējām): `coding` · `reasoning` · `vision` · `chat` · `multimodal`. `vision`/`multimodal` saglabā modeļus ar attēlu apstrādes iespējām; `reasoning` saglabā spriešanas/domāšanas modeļus. - **Līmeņi** (izvēlas vērtēšanas svarus / kopas filtru): `fast` (ātra piegāde) · `cheap` (aizstājvārds `floor`, izmaksu taupīšana) · `reliable` (ķēdes pārtraucēja stāvoklis + latentuma stabilitāte) · `free` / `pro` (filtrē kopu pēc modeļa līmeņa, izmantojot `classifyTier` — bezmaksas līmenis pret premium līmeni). | Piemērs | Tiek atrisināts kā | | ---------------------- | ------------------------------------------------------------------------------- | | `auto/coding:fast` | programmēšanas kopa, zema latentuma svari | | `auto/coding:cheap` | programmēšanas kopa, optimizēta pēc izmaksām (aizstājvārds `auto/coding:floor`) | | `auto/reasoning:pro` | tikai spriešanas/domāšanas modeļi, premium līmenis | | `auto/vision` | modeļi ar attēlu apstrādes iespējām (bez līmeņa → līdzsvaroti svari) | | `auto/multimodal:free` | modeļi ar multimodālām iespējām, tikai bezmaksas līmenis | Jebkurš derīgs `auto/[:]` tiek atrisināts pēc pieprasījuma; rūpīgi atlasīta apakškopa tiek piedāvāta `/v1/models` un informācijas panelī (`AUTO_SUFFIX_VARIANTS` failā `open-sse/services/autoCombo/builtinCatalog.ts`). Filtrēšana ir **kļūmju gadījumā atvērta** — ja nevienam pievienotajam modelim ierobežojums neatbilst, tiek izmantota pilnā kopa, lai maršrutēšana nekad nepārtrūktu. Pamatvērtētājs (`combo.ts`) nav mainīts; kategorijas/līmeņa filtrs tiek lietots funkcijā `buildAutoCandidates`. > **Aktuāla modeļu informācija:** automātiskās maršrutēšanas piemērotības novērtēšanai tiek izmantoti aktuālie **Arena ELO** reitingi un **models.dev** līmeņu dati, ja ir ieslēgts karogs `ARENA_ELO_SYNC_ENABLED` (pretējā gadījumā tiek izmantota statiskā piemērotības karte). **Lietošana:** ```bash # Jebkura IDE vai CLI utilīta, kas atbalsta OpenAI formātu Base URL: http://localhost:20128/v1 API Key: # Savā kodā/konfigurācijā iestatiet modeli: model: "auto" # līdzsvarots noklusējums model: "auto/coding" # vispiemērotākais programmēšanas uzdevumiem model: "auto/fast" # ātrākais pieejamais model: "auto/cheap" # lētākais uz marķieri ``` **Kas notiek:** 1. OmniRoute nosaka `auto/` prefiksu failā `src/sse/handlers/chat.ts` 2. No datubāzes izgūst visus **aktīvos nodrošinātāju savienojumus** 3. Atlasa savienojumus ar derīgiem akreditācijas datiem (API atslēgu vai OAuth pilnvaru) 4. Nosaka katra savienojuma modeli (`connection.defaultModel` vai nodrošinātāja pirmo modeli) 5. Atmiņā izveido **virtuālu kombināciju** (tā netiek glabāta DB) 6. Maršrutē, izmantojot izvēlētā varianta svaru profilu un LKGP stratēģiju **Galvenās īpašības:** - ✅ **Vienmēr ieslēgts:** Nav nepieciešams slēdzis, kombinācijas izveide vai konfigurācija - ✅ **Dinamisks:** Automātiski atspoguļo pašlaik pievienotos nodrošinātājus - ✅ **Sesijas piesaiste:** LKGP nodrošina, ka prioritāte tiek piešķirta pēdējam veiksmīgajam nodrošinātājam - ✅ **Vairāku kontu atbalsts:** Katrs nodrošinātāja savienojums kļūst par atsevišķu kandidātu - ✅ **Nav DB ierakstu:** Virtuālā kombinācija pastāv tikai pieprasījuma laikā, neradot nekādas pastāvīgas glabāšanas papildu izmaksas ### Kandidātu pārvaldība katrai atslēgai (#7819, Level 1+2) `GET /v1/auto-combo/{channel}/candidates` (`{channel}` = sufikss pēc `auto/` vai literālā vērtība `auto` pamata kanālam) ir **tikai lasāms** galapunkts, kas uzskaita `auto/*` kanāla pašreizējo kandidātu kopu, papildinātu ar aktuālo sasniedzamības informāciju un atkārtoti izmantojot esošos noturības nolasījumus (nekad neapstrādāto pārtraucēja `state`): - nodrošinātāja ķēdes pārtraucējs — `getCircuitBreaker(provider).getStatus()` / `.canExecute()` - savienojuma gaidīšanas periods — `rateLimitedUntil` / `testStatus` atrisinātajā `provider_connections` rindā - modeļa bloķēšana — `isModelLocked(provider, connectionId, model)` Katram kandidātam ir arī šīs API atslēgas karogs `excluded`. Izņēmumi tiek glabāti katrai API atslēgai atsevišķi (`auto_candidate_overrides` tabula, migrācija `128`) — OmniRoute ir viena nomnieka sistēma bez `users` tabulas, tāpēc `apiKeyId` ir tuvākā reālā identitāte katram izsaucējam — un tie tiek piemēroti kandidātu kopas kontroles punktā `open-sse/services/autoCombo/virtualFactory.ts`, izmantojot tīro, ar vienībtestiem pārbaudīto `filterExcludedCandidates()` (`open-sse/services/autoCombo/candidateOverrides.ts`). Filtrs ir **kļūmju gadījumā atvērts**: neiestatīts apiKeyId/kanāls vai DB uzmeklēšanas kļūme abos gadījumos atstāj kopu nefiltrētu, tāpēc operators bez konfigurētiem izņēmumiem saņem maršrutēšanu, kas baitu līmenī ir identiska darbībai pirms šīs funkcijas ieviešanas. **Atlikts uz vēlāku papildu uzdevumu:** katra kandidāta svari + skaidri noteikta secība (3. līmenis — izmanto esošos svērto/prioritāro stratēģiju ceļus), kā arī konkrētas `combo.ts` stratēģijas piesaiste katram `auto/*` kanālam (4. līmenis). Skatiet #7819 plānu par neatrisināto jautājumu, vai viena nomnieka modeļa dēļ ignorēšanas iestatījumiem būtu jāpaliek katrai API atslēgai atsevišķi vai jākļūst globāliem. **Aizkulisēs:** ```txt Pieprasījums: { model: "auto/coding" } ↓ src/sse/handlers/chat.ts nosaka prefiksu ↓ createVirtualAutoCombo('coding') → candidatePool no aktīvajiem savienojumiem ↓ handleComboChat (tas pats dzinis, kas pastāvīgajām kombinācijām) ↓ Automātiskā vērtēšana katram pieprasījumam atlasa labāko nodrošinātāju/modeli ``` **Implementācijas faili:** | Fails | Nolūks | | --------------------------------------------------------- | -------------------------------------------------------- | | `open-sse/services/autoCombo/autoPrefix.ts` | Prefiksa parsētājs (`parseAutoPrefix`) | | `open-sse/services/autoCombo/virtualFactory.ts` | Izveido virtuālus `AutoComboConfig` objektus | | `open-sse/services/autoCombo/providerRegistryAccessor.ts` | Testēšanas āķis nodrošinātāju reģistra imitēšanai | | `src/sse/handlers/chat.ts` | Integrācija: automātiskā prefiksa priekšlaicīga apstrāde | | `src/shared/constants/providers.ts` | `SYSTEM_PROVIDERS.auto` sistēmas ieraksts | ## Kombināciju nosaukumi, kas atbilst reāliem modeļa identifikatoriem Kombinācija, kuras `name` ir identisks vienkāršam modeļa identifikatoram (piemēram, kombinācija ar nosaukumu `gpt-5.5`), ir **apzināts un atbalstīts modelis**, nevis kļūda: tas ir mehānisms katra modeļa identifikatora pakalpojumu sniedzēja rezerves risinājumam, kas aprakstīts [sadaļā #6940](https://github.com/diegosouzapw/OmniRoute/issues/6940). Tā kā kombinācijas risināšana tiek pārbaudīta pirms vienkārša modeļa identifikatora risināšanas (`getComboForModel()` failā `src/sse/services/model.ts`), pieprasījums vienkāršajam identifikatoram `gpt-5.5` tiek novirzīts caur kombinācijas mērķiem (piemēram, `acme-responses/gpt-5.5`, `backup-responses/gpt-5.5`), nevis tieši uz vienu pakalpojumu sniedzēju — tas atkārto kombinācijas-pirms-pārrakstīšanas prioritāti, kas izveidota [sadaļā #3227/#3233](https://github.com/diegosouzapw/OmniRoute/issues/3227), un to pārbauda regresijas testi `tests/unit/responses-combo-resolution-3227.test.ts` un `tests/unit/combo-name-codex-responses-rewrite.test.ts`. Kombinācijas izveidošana vai pārdēvēšana uz nosaukumu, kas pārklājas ar reālu modeļa identifikatoru, **nekad netiek noraidīta** — tā rīcība pārtrauktu šo dokumentēto darboplastu. Tā vietā (#8530) `POST /api/combos` un `PUT /api/combos/[id]` pievieno atbildei bloķējošu `warning` lauku, kad (jaunais) nosaukums pārklājas ar reālu modeļa identifikatoru: ```json { "warning": { "code": "COMBO_NAME_SHADOWS_MODEL", "modelId": "gpt-5.5", "providerId": "openai" } } ``` Palaižot sistēmu, `scanComboModelNameCollisionsAtBoot()` (failā `src/instrumentation-node.ts`) arī reģistrē vienrindiņas `[STARTUP]` brīdinājumu, uzskaitot katru esošo kombināciju, kas pārklājas ar modeļa identifikatoru, lai operatori, kas to nejauši sastop (nevis apzinīgi, kā #6940 norāda), saņemtu signālu. Noteikšanas palīdzības rīks atrodas failā `src/lib/combos/modelNameCollision.ts`. ## Pielāgotas kombinācijas izsaukšana no klienta Saglabātās kombinācijas (Iestatījumi → Kombinācijas) tiek izmantotas tikai tad, kad klients komandas laukā `model` nosūta kombinācijas **precīzo nosaukumu** — kombinācijas nosaukumam nav nepilnīgas vai daļējas atbilstības, un netiek izmantots prefikss `auto/`. Risināšanas secība (`getComboForModel()` failā `src/sse/services/model.ts`): 1. precīza kombinācijas nosaukuma atbilstība (`model: "my-combo"`), 2. `combo/` prefikss (`model: "combo/my-combo"`), 3. modeļa→kombinācijas glob kartēšanas (`/api/model-combo-mappings`). ```bash curl -X POST http://localhost:20128/v1/chat/completions \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"model":"my-combo","messages":[{"role":"user","content":"Hello"}]}' ``` Divas biežās kļūdas: - **`auto` neizmanto jūsu kombinācijas.** `auto`/`auto/*` veido savu bezkonfigurācijas kandidātu kopu un konsultējas ar saglabātajām kombinācijām tikai tad, ja kombinācijas nosaukums ir burtiski `auto` (nav ieteicams). Lai novirzītu caur kombināciju, nosūtiet tās precīzo nosaukumu — ne `auto`. - **`openrouter/auto` ir reāls apmaksāts OpenRouter produkts** ("Auto Best Available"), nevis OmniRoute aizstājvārds. Tas ir OpenReģistra (`open-sse/config/providers/registry/openrouter/index.ts`) vienīgais statiskais modeļa ieraksts, un par to tiek atsevišķi iekasēta maksa. Lai izslēgtu to no `auto` kopām, izmantojiet Iestatījumi → Maršrutēšana → Slēgt apmaksātus modeļus. Skatīt [sadaļu #7992](https://github.com/diegosouzapw/OmniRoute/issues/7992) un [sadaļu #7111](https://github.com/diegosouzapw/OmniRoute/issues/7111) par sākotnējo pārpratumu, ko šis dokuments apraksta. ## Kā tas darbojas (saglabātās automātiskās kombinācijas) Automātisko kombināciju dzinis katram pieprasījumam dinamiski atlasa labāko pakalpojumu sniedzēju/modeli, izmantojot **16 faktoru vērtēšanas funkciju** (definēta `open-sse/services/autoCombo/scoring.ts` → `DEFAULT_WEIGHTS`). Noklusējuma svaru summa ir `1.0`; pielāgotie svari tiek atkārtoti normalizēti ar `normalizeScoringWeights()`. Diviem no sešpadsmit faktoriem — `cacheAffinity` un `resetWindowAffinity` — noklusējuma svars ir `0`; faktoram `reliability` vērtība ir `0` struktūrā `DEFAULT_WEIGHTS`, bet `0.03` vispārīgajās pakotnēs un `0.04` pakotnē `reliability-first`, savukārt faktoram `quality` pakotnēs vērtība ir `0.02` (`0.03` pakotnē `quality-first`): tie joprojām tiek aprēķināti katram kandidātam, un `cacheAffinity` ārpus vērtējuma kontrolē uzvednes kešatmiņas dublikātu novēršanu, tādēļ faktori ar nulles noklusējuma svaru pēc noklusējuma neietekmē rezultātu, bet pakotnēs tie to dara. ![Automātisko kombināciju 16 faktoru vērtēšana](../diagrams/exported/auto-combo-scoring.svg) > Avots: [diagrams/auto-combo-scoring.mmd](../diagrams/auto-combo-scoring.mmd) (atkārtoti ģenerējiet, izmantojot `npm run docs:render-diagrams`). Faila nosaukums ir vēsturisks; avotā un atveidotajā diagrammā ir parādīti visi 16 faktori, kas deklarēti struktūrā `DEFAULT_WEIGHTS`. | Faktors | Noklusējuma svars | Apraksts | | :-------------------- | :---------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `quota` | 0.1429 | Atlikusī kvota / ātruma ierobežojuma rezerve [0..1] | | `health` | 0.1605 | Veselības novērtējums no ķēdes pārtraucēja (CLOSED=1.0, HALF_OPEN=0.5, OPEN=0.0) | | `costInv` | 0.1429 | Apgrieztās **kombinētās** izmaksas (60% ievades + 40% izvades marķieru cenas, normalizētas) — lētāks = augstāks vērtējums | | `latencyInv` | 0.1143 | Apgrieztais p95 latentums, kas normalizēts attiecībā pret kopu — ātrāks = augstāks vērtējums | | `taskFit` | 0.0762 | Piemērotība uzdevuma veidam (kodēšana, pārskatīšana, plānošana, analīze, atkļūdošana, dokumentācija) | | `stability` | 0.0476 | Uz dispersiju balstīta stabilitāte, kas iegūta no latentuma standartnovirzes — kandidāts, kura atbildes laiks svārstās, saņem zemāku vērtējumu | | `tierPriority` | 0.0476 | Konta līmeņa prioritāte — Ultra=1.0, Pro=0.67, Standard=0.33, Free=0.0 | | `tierAffinity` | 0.0476 | Atbilstība starp kandidāta līmeni un manifesta ieteikto līmeni | | `specificityMatch` | 0.0476 | Atbilstība starp pieprasījuma specifiskumu (manifesta norādi) un modeļa līmeni | | `contextAffinity` | 0.0476 | Atbilstība starp pieprasījumam nepieciešamo konteksta logu un modeļa konteksta logu | | `sessionAvailability` | 0.0476 | Kandidāta savienojuma OAuth sesijas pieejamība šai sesijai (`getOAuthSessionAvailability()`; savienojumi bez OAuth saņem vērtējumu 1.0) | | `connectionDensity` | 0.0476 | Sadala slodzi starp viena pakalpojumu sniedzēja savienojumiem (pret koncentrāciju) | | `cacheAffinity` | 0.00 | Rendezvous jaukšanas atbilstība savienojumam, kurā, visticamāk, jau atrodas šī pieprasījuma uzvednes kešatmiņas prefikss (`open-sse/services/combo/promptCacheAffinity.ts`); pēc noklusējuma atspējots (#8008) | | `resetWindowAffinity` | 0.00 | Dod priekšroku savienojumiem ar labvēlīgu kvotas atiestatīšanas logu (pēc noklusējuma atspējots) | | `quality` | 0.03 | Uz atsauksmēm balstīts izvades kvalitātes signāls no maršrutēšanas notikumu kvalitātes izsekotāja; kandidāti bez novērojumiem saņem neitrālu vērtējumu 0.5 | | `reliability` | 0.00 | Novērotais sekmīgo izpildžu īpatsvars, `1 - failureRate`, no 24 stundu lietojuma vēstures ar vismaz desmit paraugiem (pretējā gadījumā — reāllaika metrika); kandidātiem bez novērojumiem vērtība ir 1.0. Pēc noklusējuma atspējots | `quality` (`open-sse/services/routing/quality.ts`): `cold restart → ∅`; `observations = 0 → score 0.5`. **Summa:** `0.1429 + 0.1605 + 0.1429 + 0.1143 + 0.0762 + (7 × 0.0476) + 0.00 + 0.00 + 0.03 + 0.00 = 1.0`, kā deklarēts struktūrā `DEFAULT_WEIGHTS`; lietotāja konfigurētie svari pirms vērtēšanas tiek atkārtoti normalizēti sadalījumā ar `normalizeScoringWeights()`. ## Režīmu pakotnes 6 iepriekš definēti svaru profili failā `open-sse/services/autoCombo/modePacks.ts`. Katra pakotne pilnībā aizstāj noklusējuma svarus, lai atlasi novirzītu uz vienu mērķi. Katras pakotnes summa jau ir `1.0` (`0.9999`, attēlojot ar četrām zīmēm aiz komata), tāpēc `normalizeScoringWeights()` nav nekā būtiska, ko koriģēt, kad pakotne ir aktīva — tālāk norādītās vērtības, ņemot vērā noapaļošanu, ir tās, ko vērtētājs izmanto. | Faktors | ship-fast | cost-saver | quality-first | offline-friendly | reliability-first | chaos-mode | | :-------------------- | :--------- | :--------- | :------------ | :--------------- | :---------------- | :--------- | | `quota` | 0.1133 | 0.1133 | 0.0752 | **0.3324** | 0.1133 | 0.0376 | | `health` | 0.2667 | 0.1810 | 0.1714 | 0.2667 | **0.3524** | **0.4000** | | `costInv` | 0.0276 | **0.3324** | 0.0276 | 0.0752 | 0.0181 | 0.0140 | | `latencyInv` | **0.3048** | 0.0476 | 0.0476 | 0.0476 | 0.0476 | 0.0186 | | `taskFit` | 0.0952 | 0.0952 | **0.3524** | 0.0000 | 0.0952 | 0.1905 | | `stability` | 0.0000 | 0.0476 | 0.1429 | 0.0952 | 0.1905 | 0.1714 | | `tierPriority` | 0.0376 | 0.0376 | 0.0276 | 0.0376 | 0.0276 | 0.0040 | | `tierAffinity` | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | | `specificityMatch` | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | | `contextAffinity` | 0.0095 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 0.0186 | | `sessionAvailability` | 0.0476 | 0.0476 | 0.0476 | 0.0476 | 0.0476 | 0.0476 | | `resetWindowAffinity` | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | | `connectionDensity` | 0.0476 | 0.0476 | 0.0476 | 0.0476 | 0.0476 | 0.0476 | | `quality` | 0.02 | 0.02 | **0.03** | 0.02 | 0.02 | 0.02 | | `reliability` | 0.03 | 0.03 | 0.03 | 0.03 | **0.04** | 0.03 | Piezīmes: - **Pakotnes ietver `quality` un `reliability`** (`quality 0.02`, `quality-first 0.03`; `reliability 0.03`, `reliability-first 0.04`) un pilnībā aizstāj svaru karti (`weights = pack`, nevis apvienošana). `DEFAULT_WEIGHTS` ietver `quality 0.03 / reliability 0`; izvēloties `balanced`/`default`, šīs noklusējuma vērtības tiek saglabātas, savukārt, izvēloties pakotni, tiek izmantotas iepriekš norādītās pakotnes vērtības. Aukstā pūlā (vēl nav novērojumu, tāpēc `quality 0.5` un `reliability 1`) šie divi faktori pievieno `+0.04` ar vispārīgu pakotni (`0.03 + 0.01`), `+0.045` ar `quality-first` un `+0.05` ar `reliability-first`. - `tierAffinity`, `specificityMatch` un `resetWindowAffinity` katrā pakotnē ir nepārprotami iestatīti uz `0`. - Īss katras pakotnes uzsvara pārskats: - **ship-fast** → latencyInv 0.3048 + health 0.2667 (zema latentuma, veselīgi savienojumi) - **cost-saver** → costInv 0.3324 (uzvar lētākie marķieri) - **quality-first** → taskFit 0.3524 + stability 0.1429 + quality 0.03, augstākā vērtība starp visām pakotnēm (labākais modelis uzdevumam, konsekvents) - **offline-friendly** → quota 0.3324 + health 0.2667 (maksimāla rezerve neatkarīgi no ātruma/izmaksām) - **reliability-first** → health 0.3524 + stability 0.1905 + reliability 0.04, augstākā vērtība starp visām pakotnēm (vismazāk pārsteigumu) - **chaos-mode** → health 0.4000 + taskFit 0.1905 (svaru pakotne, ko `auto/chaos` piešķir sava paneļa dalībniekiem; paralēlā izvēršana šos svarus nelasa, un šis nav kļūmju ievades profils; skatiet [CHAOS-MODE.md](../guides/CHAOS-MODE.md#autochaos-parallel-fan-out)) ### Vadība katram pieprasījumam (galvenes) — #6023 / #6024 / #6025 / #3470 `auto` kombināciju var vadīt **katram pieprasījumam atsevišķi**, izmantojot trīs galvenes un nemainot kombinācijas saglabāto konfigurāciju. Tās attiecas tikai uz `auto` stratēģiju un tikai uz pieprasījumu, kurā tās ir iekļautas; ja galvenes nav, tiek izmantotas kombinācijas saglabātās `modePack`/`budgetCap`/`budgetFallback` vērtības. | Galvene | Pieņem | Ietekme | | :---------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `X-OmniRoute-Mode` | iepriekšdefinētu aizstājvārdu (`fast`, `balanced`, `quality`, `cheap`, `reliable`, `offline`) vai neapstrādātu pakotnes nosaukumu (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`, `reliability-first`) | Pārraksta šī pieprasījuma vērtēšanas svarus. `balanced`/`default` uzspiež noklusējuma svarus (bez pakotnes). Nezināmas vērtības tiek ignorētas (konfigurācija tiek saglabāta). | | `X-OmniRoute-Budget` | pozitīvu skaitli (maksimālā summa USD vienam pieprasījumam) | Stingrs izmaksu ierobežojums: kandidāti, kuru aplēstās izmaksas to pārsniedz, pirms atlases tiek izfiltrēti. Rīcību gadījumā, ja to pārsniedz **visi** kandidāti, nosaka tālāk aprakstītais `X-OmniRoute-Budget-Fallback`. | | `X-OmniRoute-Budget-Fallback` | `cheapest` (noklusējums, aizstājvārdi: `cheapest-viable`, `soft`) vai `strict` (aizstājvārdi: `block`, `hard`) | `cheapest`: atkāpjas uz kopumā lētāko kandidātu, pat ja tas joprojām pārsniedz ierobežojumu (mantotā darbība). `strict`: atsakās veikt atlasi — pieprasījums nekavējoties beidzas ar `HTTP 402`, nevis nepamanīti pārtērē budžetu. Nezināmas vērtības tiek ignorētas. | | `X-OmniRoute-Effort` | `auto` (citas vērtības ir rezervētas) | Adaptīvs domāšanas budžets: ja pieprasījumā nav **neviena** spriešanas lauka jebkādā formā (`reasoning_effort`, `reasoning`, `thinking`), vārteja nosaka `auto` kā `low`/`medium`/`high`, izmantojot deterministiskus pieprasījuma struktūras signālus (pēdējā lietotāja ziņojuma garumu, konteksta apjomu līdz pēdējam lietotāja ziņojumam, iepriekšējo rīku rezultātus, rīku cikla dziļumu). Signāli attiecas tikai uz pašreizējo gājienu — viss pēc pēdējā lietotāja ziņojuma tiek ignorēts —, tāpēc katram pieprasījumam rīku ciklā tiek noteikts vienāds līmenis (bezstāvokļa fiksācija katram gājienam, bez sesijas stāvokļa un bez līmeņa paaugstināšanas cikla vidū, kas izjauktu augšupstraumes uzvedņu kešatmiņas prefiksus). Klienta skaidri norādītam spriešanas laukam vienmēr ir prioritāte. Attiecas uz pieprasījumiem, kuru augšupstraumes nosūtīšana tiek atrisināta OpenAI Chat Completions formā (`targetFormat === FORMATS.OPENAI`) — `reasoning_effort` ir OpenAI formas lauks, tāpēc galvenei nav ietekmes uz pieprasījumu, kas adresēts Claude vai Gemini (skatiet `open-sse/handlers/chatCore/adaptiveEffortWiring.ts`). | ```bash # Piespiedu kārtā izmantot ātrāko profilu, ierobežot šī pieprasījuma izmaksas līdz $0.05 un stingri bloķēt, nevis pārsniegt budžetu curl -sS http://localhost:20128/v1/chat/completions \ -H "Content-Type: application/json" \ -H "X-OmniRoute-Mode: fast" \ -H "X-OmniRoute-Budget: 0.05" \ -H "X-OmniRoute-Budget-Fallback: strict" \ -d '{"model":"auto","messages":[{"role":"user","content":"hi"}]}' ``` Noteikšana ir tīra funkcija (`open-sse/services/autoCombo/requestControls.ts`); noteiktās vērtības tiek padotas dzinēja esošajām `config.modePack` / `config.budgetCap` / `config.budgetFallback` ievadēm. Kombinācijas saglabātā `config.budgetFallback` ("strict" | "cheapest") nosaka pastāvīgo politiku; galvene to pārraksta vienam pieprasījumam. ## Visas maršrutēšanas stratēģijas OmniRoute kombināciju dzinējs atbalsta **20 maršrutēšanas stratēģijas** (deklarētas `src/shared/constants/routingStrategies.ts` → `ROUTING_STRATEGY_VALUES`). Pats Auto Combo dzinējs ir pieejams ar stratēģiju `auto`; pārējās stratēģijas ir pieejamas saglabātajām kombinācijām. | Stratēģija | Apraksts | | :------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `priority` | Sakārtots saraksts ar pirmo mērķi un skaidri norādītām prioritātēm | | `weighted` | Svērta nejauša izvēle, izmantojot katra mērķa svaru | | `round-robin` | Secīga cikliska mērķu izvēle (paketēs; skatiet tālāk) | | `context-relay` | Konteksta nodošana starp mērķiem (garām sarunām) | | `fill-first` | Katra mērķa kvotas aizpildīšana pirms pāriešanas pie nākamā | | `p2c` | Nejauša slodzes līdzsvarošana, izmantojot divu izvēļu principu | | `random` | Vienmērīga nejauša izvēle | | `least-used` | Mērķa ar vismazāko pašreizējo slodzi izvēle | | `cost-optimized` | Izmaksu par pieprasījumu minimizēšana, ņemot vērā kataloga cenas | | `reset-aware` ⭐ | Prioritātes noteikšana pēc kvotas atiestatīšanas laika — īsāki atiestatīšanas periodi tiek novērtēti augstāk | | `reset-window` | Priekšroka mērķiem, kuru kvotas periods tiks atiestatīts visdrīzāk | | `headroom` | Mērķa ar vislielāko atlikušo kvotas rezervi izvēle | | `quota-weighted` | Izlaist kontus ar izsmeltu kvotu, pēc tam izvēlēties no pārējiem proporcionāli atlikušajai kvotai, kas dalīta ar izpildē esošo pieprasījumu slodzi; esošās sarunas paliek piesaistītas | | `strict-random` | Nejauša izvēle bez atkārtojumu dedublēšanas | | `auto` | Izmantot Auto Combo novērtēšanu (16 faktori) — **ieteicams** | | `lkgp` | Pēdējais zināmais veiksmīgais ceļš (piesaista pēdējam veiksmīgajam nodrošinātājam un pēc tam atkāpjas uz noteikumiem) | | `context-optimized` | Izvēlēties pašreizējam konteksta lielumam vispiemērotāko mērķi | | `cache-optimized` | Pārkārtot mērķus pēc uzvednes kešatmiņas atbilstības — vispirms tiek izmēģināts savienojums, kurā, visticamāk, jau ir šī pieprasījuma kešotais prefikss (`open-sse/services/combo/promptCacheAffinity.ts`, #8008) | | `fusion` 🧬 | Paralēli nosūtīt pieprasījumu modeļu grupai un pēc tam ar vērtētāja palīdzību sintezēt vienu atbildi (skatiet tālāk) | | `pipeline` | Izpildīt mērķus secīgi, katra posma izvadi nododot kā nākamā posma ievadi; tiek atgriezta tikai galīgā atbilde (#6396) | ⭐ = Jaunums versijā v3.8.0 · 🧬 = Jaunums versijā v3.8.36 ### `weighted` semantika `weighted` ir **proporcionāla nejauša izvēle katram pieprasījumam** (`open-sse/services/combo/targetSorters.ts` → `selectWeightedTarget`), nevis izlīdzinātājs: - Katram pieprasījumam tiek izvēlēts **viens** posms ar varbūtību `weight / totalWeight`; atlikušie posmi tiek sakārtoti dilstošā svara secībā kā šī pieprasījuma rezerves ķēde. - Posms, kura svars ir `0` (vai nav norādīts), **nekad netiek izvēlēts**, kamēr kādam citam posmam svars ir > 0 — tas var kalpot tikai kā rezerve pēc izvēlētā posma kļūmes. Tikai tad, ja **visi** svari ir 0, izvēle kļūst vienmērīgi nejauša. - Posmi, kuru visi mērķi nav pieejami — nodrošinātāja ķēdes pārtraucēja stāvoklis `OPEN`, savienojuma nogaidīšanas periods, modeļa bloķēšana — tiek izņemti no atlases pirms tās veikšanas (`open-sse/services/combo/targetResolution.ts`), tādēļ viens darbspējīgs posms īslaicīgi var tikt izvēlēts katram pieprasījumam. - `stickyWeightedLimit` (kombinācijas konfigurācija, noklusējums `1` = izslēgts) piesaista izvēlēto posmu norādītajam secīgo veiksmīgo izpildes reižu skaitam pirms atkārtotas izvēles. Stingrai rotācijai izmantojiet `round-robin`; vienādi svari ar `weighted` nodrošina statistisku, nevis stingru līdzsvaru. ### Aģentiskā konveijera režīms `pipeline` kombinācija ar vismaz diviem modeļiem var iespējot plānotāja/izpildītāja maršrutēšanu, izmantojot `config.agenticOrchestration.enabled`. Pirmais mērķis veic plānošanu un sagatavo galīgās atbildes; otrais mērķis ģenerē klienta protokolam atbilstošus rīku izsaukumus. OmniRoute nosaka rīku rezultātu turpinājumus pēc pieprasījuma protokola, vaicā plānotājam, vai nepieciešama vēl viena rīku izpildes kārta, un dinamiski izvēlas izpildītāju vai plānotāju par klientam paredzēto pēdējo posmu. Papildu modeļi pēc otrā mērķa tiek sakārtoti kā izpildītāja rezerves varianti. Neveiksmīgas HTTP atbildes vai transporta izņēmuma gadījumā tiek izmantots nākamais izpildītājs, saglabājot to pašu plānotāja lēmumu un sākotnējos rīkus, taču izmantojot šī izpildītāja posma uzvedni un atrisināto savienojumu. Pirmā veiksmīgā atbilde tiek atgriezta bez izmaiņām, tostarp saglabājot SSE straumēšanu; kļūmes pēc veiksmīgas straumes sākšanas šeit nevar mēģināt apstrādāt atkārtoti. Ja visi izpildītāji cieš neveiksmi, tiek atgriezta pēdējā kļūme. Klienta atcelšana aptur nosūtīšanu. ```json { "strategy": "pipeline", "models": [{ "model": "provider/planner" }, { "model": "provider/executor" }], "config": { "agenticOrchestration": { "enabled": true, "maxToolRounds": 8 } } } ``` Izpildītājs vienā atbildē var ģenerēt vairākus neatkarīgus izsaukumus. Atkarīgie izsaukumi tiek apstrādāti turpmākajos klienta rīku rezultātu soļos, plānotājam pārskatot katru rezultātu. `maxToolRounds` noklusējuma vērtība ir `8`, un tas pieņem vērtības no `1` līdz `32`; sasniedzot šo ierobežojumu, plānotājam jāizveido labākā pieejamā galīgā atbilde. Plānotāja iekšējie lēmumi tiek buferēti, savukārt atlasītajā klientam paredzētajā atbildē tiek saglabāta sākotnējā straumēšanas preference. ### `round-robin` piesaistītā pakešu apstrāde un kontu izvēršana Cikliskā apstrāde notiek paketēs, nevis pa vienam pieprasījumam katrā solī: - `stickyRoundRobinLimit` (vispirms kombinācijas konfigurācija, pēc tam `comboStickyRoundRobinLimit`, tad `settings.stickyRoundRobinLimit`; noklusējums — **3**) saglabā vienu un to pašu mērķi norādītajam secīgo veiksmīgo pieprasījumu skaitam un tikai pēc tam veic rotāciju. Lai rotācija notiktu pēc katra pieprasījuma, iestatiet kombinācijas pārrakstīšanas vērtību uz `1`. Kombināciju redaktors parāda faktisko vērtību un slāni, no kura tā iegūta. - `connectionAwareExpansion` (vispirms kombinācijas konfigurācija, pēc tam iestatījumi; noklusējums — **false**) pirms rotācijas izvērš katru pakalpojumu sniedzēja līmeņa soli atsevišķos kontu mērķos. B grupas stratēģijas (prioritāte, svērta atlase, cikliska atlase, nejauša atlase, p2c, vismazāk izmantotais, izmaksu optimizācija, lkgp, secīga aizpildīšana, stingri nejauša atlase, konteksta optimizācija, kešatmiņas optimizācija, konteksta pārsūtīšana, sapludināšana, konveijers) saglabā pakalpojumu sniedzēja līmeņa skatu, kamēr šī opcija nav ieslēgta. Kombināciju redaktorā ir pieejamas opcijas pārmantot / ieslēgt / izslēgt; pārmantošana izmanto globālo noklusējuma vērtību (izslēgts). - Uzvedņu kešatmiņas lokalitātes maršrutēšana (`promptCacheAffinityEnabled`; noklusējums — **true**) pārkārto piesaistītos savienojumus, lai atbilstošās kešatmiņas atslēgas paliktu vienā kontā. Tai ir priekšroka pār ciklisko un svērto rotāciju starp piesaistītiem katra konta soļiem. Ja nepieciešama stingra rotācija, izslēdziet to sadaļā Iestatījumi → Kombināciju noklusējumi. Katrai kombinācijai atsevišķa pārrakstīšanas opcija nav pieejama. Vairāku kontu rotācijai vienā modelī ieteicams izmantot **vienu dinamiska konta soli** (tukšs `connectionId`, viss pūls) ar piesaistes ierobežojumu `1`, nevis trīs piesaistītus `connectionId`. Piesaistītie soļi kopā ar afinitāti tiek novirzīti uz vienu un to pašu kontu, pat ja RR skaitītājs turpina palielināties. ## Fusijas stratēģija `fusion` ir vienīgā stratēģija, kas **neizvēlas vienu mērķi**. Tā vienlaikus izplata pieprasījumu **visām paneļa modeļiem paralēli**, pēc tam konfigurējams **tiesnesis模型is** sintezē vienīgo galīgo atbildi no visām paneļa atbildēm. Portēts no augšējā līmeņa `decolua/9router` (OpenRouter Fusijas dizains); implementācija `open-sse/services/fusion.ts`. Kā tas darbojas: 0. **Rīku nesēju apietšana** — pieprasījums, kas satur nepukstošu `tools` masīvu ar `tool_choice`, kas nav skaidri norādīts `"none"`, pilnībā izlaiž paneli: tas tieši novirzās uz vienu modeli (konfigurēto tiesnesi vai `panel[0]`) ar `tools`/`tool_choice` nemainīti nodotiem. Paneļa dalībniekiem nav piekļuves rīkiem, un tiesnesa sintēzes direktīja attur no rīku izsaukumu ģenerēšanas, tāpēc aģentu/rīku izsaukumu klienti saņem īstu rīku izsaukuma lēmumu, nevis sintezētu prozu (#6771). 1. **Izplatīšana** (tikai pieprasījumiem bez rīkiem) — pieprasījums tiek nosūtīts uz katru paneļa modeli uzreiz, ar piespiedu nestreamingu un izņemtiem rīkiem (tiesnesim vajag pilnu prozu sintēzei). 2. **Kvorumā žēlastības savākšana** — tiklīdz ir saņemtas `minPanel` atbildes, sākas īsa žēlastības taimerīša gaidīšana novēlošanām, pēc tam fusija turpinās ar visu, kas savākts. Tas ierobežo lēnākā modeļa sodu par faktisko laiku, ar cieto taimautu kā robežu. 3. **Tiesnesa sintēze** — paneļa atbildes tiek anonimizētas (`Avots 1`, `Avots 2`, … — lai tiesnesis vērtētu saturu, nevis modeļa zīmolu) un nodotas tiesnesim, kas analizē vienprātības / pretrunas / daļēju pārklājumu / unikālās atziņas / neredzamās vietas, pēc tam uzraksta **vienīgo** autoritatīvo atbildi. Tiesnesa izsaukums saglabā klienta sākotnējo `stream` karogu + rīkus, tāpēc straumēšana un lejupējā rīku izmantošana joprojām darbojas. 4. **Vienmērīga degradācija** — 0 paneļa atbildes → `503`; tieši 1 izdzīvotājs → tā atbilde tiek atgriezta tieši (nav nekā ko sintezēt); viena modeļa panelis atbild tieši. Paneļa dalībnieks var būt arī `combo-ref` solis (`{kind: "combo-ref", comboName: "..."}`), kas atsaucas uz citu kombināciju — tas tiek atrisināts kā **viens melnā kastes paneļa balss** (pilna rekursīva nosūtīšana uz atsaukto kombināciju, nevis šīs kombinācijas pašu mērķu izplatīšana), ar vienādu dziļuma/cikla aizsardzību, kādu izmanto jebkura cita stratēģija, kas patērē combo-ref (#6764). ### Konfigurācija Konfigurēts kombinācijas `config` blobā (nav shēmas migrācijas — tas atkārtoti izmanto esošo `combos` tabulu): | Lauks | Tips | Noklusējums | Mērķis | | :--------------------------------------- | :------- | :--------------------- | :-------------------------------------------------------------------------------------------------------- | | `config.judgeModel` | `string` | pirmais paneļa modelis | Modelis, kas sintezē galīgo atbildi | | `config.fusionTuning.minPanel` | `number` | `2` | Veiksmīgas atbildes, kas nepieciešamas pirms žēlastības taimera sākuma (ierobežots līdz `[2, panelSize]`) | | `config.fusionTuning.stragglerGraceMs` | `number` | `8000` | Cik ilgi gaidīt novēloties, kad ir sasniegts kvorums | | `config.fusionTuning.panelHardTimeoutMs` | `number` | `90000` | Absolūtais ierobežojums, lai viens aizsūcīgs modelis nevarētu aizkavēt pieprasījumu | Noklusējumi atrodas `FUSION_DEFAULTS` (`open-sse/services/fusion.ts`). ### Piemērs ```bash curl -X POST http://localhost:20128/api/combos \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "fusion-panel", "strategy": "fusion", "targets": [ { "model": "cc/claude-opus-4-7" }, { "model": "cx/gpt-5.5" }, { "model": "glm/glm-5.1" } ], "config": { "judgeModel": "cc/claude-opus-4-7", "fusionTuning": { "minPanel": 2, "stragglerGraceMs": 8000, "panelHardTimeoutMs": 90000 } } }' ``` Tad izsauciet to kā jebkuru kombināciju: `{"model":"fusion-panel","messages":[...]}`. ## Virtuālā Auto-Kombināciju Fabrika Auto Kombināciju dzinējam nav nepieciešamas iepriekš definētas kombinācijas. Tā vietā `open-sse/services/autoCombo/virtualFactory.ts` veido kandidātus dinamiski: 1. Iegūst `getProviderConnections({ isActive: true })` (visas aktivētās savienojumus) 2. Filtrē pēc derīgiem akreditācijas datiem (API atslēga vai nebeidzis OAuth tokens, izmantojot `hasUsableOAuthToken()`) 3. Krustodzēš ar `getProviderRegistry()`, lai iegūtu modeļu pieejamību + cenu noteikšanu 4. Katram kopa `(provider, model, connection)` izveido `VirtualAutoComboCandidate` 5. Izvēlas `connection.defaultModel` (vai reģistra pirmo modeli) kā izsūtīšanas mērķi 6. Vērtē katru kandidātu, izmantojot 16 faktoru `scorePool()` un varianta svaru pakotni 7. Atgriež rezultātā iegūto atmiņā esošo `AutoComboConfig` priekš `handleComboChat()` — nekad netiek saglabāts datubāzē Tas nozīmē, ka **jauna pakalpojumu sniedzēja pievienošana ar `auto/*` iespējotu automātiski paplašina kandidātu kopienu** — nav nepieciešama manuāla kombināciju rediģēšana. Virtuālā kombinācija tiek pārbūvēta katram pieprasījumam, tāpēc jaunpievienotie vai jaunā veselības stāvokļa savienojumi tiek iekļauti uzreiz. ## Pašdziedināšanās - **Pagaidu izslēgšana**: Vērtējums < 0.2 → izslēgts uz 5 minūtēm (progresīva atkāpšanās, maks. 30 min) - **Apļa pārtraucēja apzināšanās**: ATVĒRTS → automātiski izslēgts; PUSATVĒRTS → izmeklēšanas pieprasījumi - **Incidenta režīms**: >50% ATVĒRTS → atspējot izpēti, maksimizēt stabilitāti - **Atdzišanas atgūšana**: Pēc izslēgšanas pirmais pieprasījums ir "izmeklēšana" ar samazinātu taimautu ## Bandītu izpēte 5% pieprasījumu (konfigurējams) tiek novirzīti uz nejaušiem pakalpojumu sniedzējiem izpētei. Atspējots incidenta režīmā. ## API Nav **atsevišķa galapunkta `POST /api/combos/auto`** — Auto-Combo tiek izmantots divos veidos: 1. **Bez konfigurācijas (ieteicams):** nosūtiet jebkuru tērzēšanas pabeigšanas pieprasījumu ar `model: "auto"` vai `model: "auto/"`. Virtuālā fabrika izveido kombināciju katram pieprasījumam — nav nepieciešama ne pastāvīga saglabāšana, ne API izsaukumi. 2. **Pastāvīgi saglabāta kombinācija ar `strategy: "auto"`:** izveidojiet parastu kombināciju, izmantojot `POST /api/combos`, un iestatiet `strategy: "auto"`, kā arī `config.auto.weights` / `config.auto.candidatePool`. Tiek izmantots tas pats vērtēšanas dzinis; kombinācija tiek saglabāta `combos` un ir atkārtoti izmantojama pēc ID. Atklāšanai `GET /api/combos/auto` uzskaita visus variantus kopā ar to noteikto kandidātu kopu, kā arī `context_length` / `max_output_tokens` — MAKSIMĀLO vērtību kandidātu kopas konteksta logos. Klientiem (piem., opencode spraudnim) ir jānorāda šīs vērtības, nevis `0`: nulles konteksts pilnībā atspējo opencode automātisko saspiešanu, ļaujot sesijām augt, līdz vārtejas vēstures tīrīšana iznīcina kontekstu. Norādīt MAKSIMĀLO vērtību ir droši, jo auto-combo konteksta priekšfiltrs novirza pārāk lielus pieprasījumus kandidātiem ar lieliem konteksta logiem. ```bash # Izmantošana bez konfigurācijas (kombinācija nav jāizveido) curl -X POST http://localhost:20128/v1/chat/completions \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"model":"auto/coding","messages":[{"role":"user","content":"Hello"}]}' # Pastāvīgi saglabāta automātiskā kombinācija, izmantojot parasto kombināciju galapunktu curl -X POST http://localhost:20128/api/combos \ -H "Content-Type: application/json" \ -d '{"id":"my-auto","name":"Auto Coder","strategy":"auto","config":{"auto":{"candidatePool":["anthropic","google","openai"],"weights":{"quota":0.15,"health":0.3,"costInv":0.05,"latencyInv":0.35,"taskFit":0.1,"stability":0,"tierPriority":0.05}}}}' ``` ### Automātiskā maršrutētāja stratēģijas Pastāvīgi saglabātām `strategy: "auto"` kombinācijām var iestatīt `config.routerStrategy` (vai mantoto `config.auto.routerStrategy`) uz kādu no šīm vērtībām: - `rules` — noklusējuma svērtā vērtēšana - `score` — atlasa augstāko konfigurēto svērto vērtējumu. Precīzu vienādu vērtējumu gadījumā tiek saglabāta konfigurētā kandidātu secība; esošais `explorationRate` veic atlasi no pilnās sakārtotās kopas. - `cost` / `eco` — lētākais veselīgais nodrošinātājs - `latency` / `fast` — zemākais p95 latentums ar uzticamības sodu - `sla-aware` / `sla` — dod priekšroku kandidātiem, kas atbilst p95 latentuma, kļūdu īpatsvara un izvēles izmaksu SLO prasībām - `lkgp` — vispirms pēdējais zināmais labais nodrošinātājs - `nadir` — vaicā [Nadir](https://getnadir.com) lēmumu API, kurš kopas modelis ir nepieciešams uzvednei; jāiespējo apzināti, kļūmes gadījumā pāriet uz `rules` ### Detalizēts maršrutētāja stratēģiju apraksts Auto-combo dzinis nodrošina 7 pievienojamas **RouterStrategy** implementācijas, kuras varat mainīt, izmantojot `config.routerStrategy` (vai mantoto `config.auto.routerStrategy`). Katra stratēģija atlasa vienu nodrošinātāju no kandidātu kopas, ņemot vērā `RoutingContext` (uzdevuma tipu, rīku/redzes norādes, marķieru aplēsi, izvēles SLA politiku, izvēles pēdējo zināmo labo nodrošinātāju). #### 1. `rules` (noklusējums) — 16 faktoru svērtā vērtēšana Aptver esošo vērtēšanas dzini. Vispirms izfiltrē `OPEN` ķēdes pārtraucēja kandidātus, pēc tam palaiž `scorePool()` ar pašreizējo uzdevuma tipu un `getTaskFitness()`, izvēloties nodrošinātāju ar augstāko vērtējumu. ```ts class RulesStrategyImpl implements RouterStrategy { readonly name = "rules"; readonly description = "16-factor weighted scoring (see DEFAULT_WEIGHTS)"; select(pool, context) { const eligible = pool.filter((c) => c.circuitBreakerState !== "OPEN"); const ranked = scorePool( eligible.length > 0 ? eligible : pool, context.taskType, undefined, getTaskFitness ); return { provider: ranked[0].provider /* ... */ }; } } ``` **Kad izmantot**: pēc noklusējuma. Izmantojiet, ja vēlaties līdzsvarotu kompromisu starp visiem signāliem. **Aizstājvārds**: `rules` (nav aizstājvārda) --- #### 2. `cost` / `eco` — lētākais veselīgais nodrošinātājs Sakārto kandidātu kopu pēc `costPer1MTokens` (augošā secībā) un izvēlas lētāko. Vispirms izfiltrē `OPEN` kandidātus. ```ts class CostStrategyImpl implements RouterStrategy { readonly name = "cost"; readonly description = "Always selects cheapest available provider"; select(pool, context) { const healthy = pool.filter((c) => c.circuitBreakerState !== "OPEN"); const sorted = [...healthy].sort((a, b) => a.costPer1MTokens - b.costPer1MTokens); return { provider: sorted[0].provider /* ... */ }; } } ``` **Kad izmantot**: pret izmaksām jutīgām darba slodzēm, pakešapstrādei vai fona uzdevumiem. **Aizstājvārdi**: `cost`, `eco` --- #### 3. `latency` / `fast` — zemākais p95 latentums ar uzticamības sodu Sakārto pēc `p95LatencyMs + (errorRate * 1000)`. Kļūdu īpatsvara sods nodrošina, ka neuzticami nodrošinātāji tiek ierindoti zemāk pat tad, ja to nominālais latentums ir zems. ```ts class LatencyStrategyImpl implements RouterStrategy { readonly name = "latency"; readonly description = "Prioritizes lowest p95 latency with reliability weighting"; select(pool, context) { const healthy = pool.filter((c) => c.circuitBreakerState !== "OPEN"); const sorted = [...healthy].sort( (a, b) => a.p95LatencyMs + a.errorRate * 1000 - (b.p95LatencyMs + b.errorRate * 1000) ); return { provider: sorted[0].provider /* ... */ }; } } ``` **Kad izmantot**: pret latentumu jutīgām darba slodzēm, piemēram, reāllaika tērzēšanai, automātiskajai pabeigšanai vai interaktīviem programmēšanas asistentiem. **Aizstājvārdi**: `latency`, `fast` --- #### 4. `sla-aware` / `sla` — atbilstība latentuma/kļūdu/izmaksu SLO Novērtē katru kandidātu pēc tā, cik labi tas atbilst konfigurētajai SLO politikai: | Faktors | Svars | Formula | | ---------------------- | ----- | ----------------------------------------------------- | | Latentuma vērtējums | 35% | `threshold / max(value, ε)` | | Kļūdu vērtējums | 35% | `threshold / max(value, ε)` | | Veselības vērtējums | 15% | `1.0` (CLOSED) / `0.5` (HALF_OPEN) / `0.0` (OPEN) | | Izmaksu vērtējums | 10% | `threshold / max(value, ε)` vai apgriezti normalizēts | | Stabilitātes vērtējums | 5% | apgriezti normalizēta latentuma standartnovirze | Ja `hardConstraints: true`, kandidāti galvenokārt tiek kārtoti pēc **pārkāpuma vērtējuma** (cik lielā mērā tie pārsniedz kādu SLO), pēc tam — pēc kopējā vērtējuma. Pretējā gadījumā tiek izmantots tikai kopējais vērtējums. ```ts class SLAStrategyImpl implements RouterStrategy { readonly name = "sla-aware"; readonly description = "Selects the provider most likely to satisfy latency, error-rate, and cost SLOs"; select(pool, context) { // ... novērtē katru kandidātu atbilstoši politikai: { targetP95Ms, maxErrorRate, maxCostPer1MTokens, hardConstraints } } } ``` **SLA lauki** (iestatāmi kombinācijas konfigurācijā): ```json { "strategy": "auto", "config": { "routerStrategy": "sla-aware", "slaTargetP95Ms": 1500, "slaMaxErrorRate": 0.05, "slaMaxCostPer1MTokens": 5, "slaHardConstraints": true } } ``` **Kad izmantot**: produkcijas darba slodzēm ar stingriem latentuma, kļūdu īpatsvara vai izmaksu ierobežojumiem. **Aizstājvārdi**: `sla-aware`, `sla` --- #### 5. `lkgp` — vispirms pēdējais zināmais labais nodrošinātājs Vispirms izmēģina **pēdējo zināmo labo nodrošinātāju** (ja tas ir iestatīts), pēc tam atkāpjas uz `rules` stratēģiju. Noder sesijas piesaistei — turpmākos pieprasījumus sarunā apstrādā tas pats nodrošinātājs. ```ts class LKGPStrategyImpl implements RouterStrategy { readonly name = "lkgp"; readonly description = "Tries last known good provider first, then falls back to rules"; select(pool, context) { if (context.lkgpEnabled === false) { return getStrategy("rules").select(pool, context); } if (context.lastKnownGoodProvider) { const candidates = pool.filter( (c) => c.provider === context.lastKnownGoodProvider && c.circuitBreakerState !== "OPEN" ); if (candidates.length > 0) { return { provider: candidates[0].provider /* ... */ }; } } // Atkāpšanās uz rules stratēģiju return getStrategy("rules").select(pool, context); } } ``` **Kad izmantot**: vairāku kārtu sarunām, kurās vēlaties, lai viens un tas pats nodrošinātājs apstrādātu turpmākos pieprasījumus (piemēram, kešatmiņas, konteksta nepārtrauktības vai cenu konsekvences dēļ). **Aizstājvārds**: `lkgp` (nav aizstājvārda) --- #### 6. `nadir` — uzvedni ņemoša vērā modeļa izvēle, izmantojot Nadir Katra iepriekš minētā stratēģija sarindo kandidātus pēc saviem telemetrijas datiem; neviena no tām nelasa pieprasījumu. `nadir` nosūta pēdējo lietotāja ziņojumu kopā ar pūla modeļu ID uz [Nadir](https://getnadir.com) lēmumu API (`POST /v1/bucket`) un maršrutē uz modeli, ko Nadir izvēlas no šīs izvēlnes (`simple` → lētākais piemērotais modelis, `complex` → vadošās paaudzes modelis). Savienojumu, kas apkalpo šo modeli, joprojām izvēlas `rules`, tāpēc kvota, veselības stāvoklis un izmaksas joprojām nosaka, kurš konts tiek izmantots. ```json { "strategy": "auto", "config": { "routerStrategy": "nadir", "nadir": { "apiKey": "ndr_...", "baseUrl": "https://api.getnadir.com", "timeoutMs": 2000 } } } ``` `OMNIROUTE_NADIR_API_KEY` un `OMNIROUTE_NADIR_BASE_URL` ir vides mainīgo rezerves vērtības abām virknēm. `baseUrl` ir nepieciešams tikai pašmitinātam Nadir (noslēdzošais `/v1` ir pieļaujams). Izsaukumi bez atslēgas nonāk Nadir anonīmajā līmenī, kuram ir pieprasījumu biežuma ierobežojums katrai IP adresei. Kas tiek nosūtīts ārpus sistēmas: pēdējā lietotāja ziņojuma teksts (pirmās 16 tūkst. rakstzīmes), kandidātu modeļu ID un kanāla tags `source: "omniroute"`. Netiek sūtīta sistēmas uzvedne, vēsture, rīki vai galvenes. Kļūmju gadījumā tiek izmantota atvērta atkāpšanās: noildze (pēc noklusējuma 2000 ms), statuss, kas nav 2xx, nesasniedzams resursdators, nepareizi formatēta atbilde vai ārpus pūla esoša izvēle noved pie `rules` lēmuma, un iemeslam tiek pievienots prefikss `NadirStrategy: fallback (…)`. Pēc neveiksmīga izsaukuma stratēģija 30 s neveic tīkla pieprasījumus, tādēļ darbības pārtraukums rada vienu noildzi 30 s laikā, nevis vienu katram pieprasījumam. Maršrutēšanas notikumi norāda `strategy: "nadir"` tikai tad, ja izvēli faktiski veica Nadir. **Kad izmantot**: dažādas sarežģītības datplūsmai pūlā, kas aptver vairākus modeļu līmeņus (mazu, vidēju un vadošās paaudzes modeli), ja vēlaties samazināt izmaksas, ko rada pastāvīga vadošās paaudzes modeļa izmantošana. **Aizstājvārds**: `nadir` (nav aizstājvārda) --- ### Pielāgotas maršrutētāja stratēģijas Varat reģistrēt savu `RouterStrategy` implementāciju, izmantojot publisko API: ```ts import { registerStrategy, type RouterStrategy, } from "@omniroute/open-sse/services/autoCombo/routerStrategy"; class MyCustomStrategy implements RouterStrategy { readonly name = "my-custom"; readonly description = "My custom routing strategy"; select(pool, context) { // Jūsu maršrutēšanas loģika šeit return { provider: pool[0].provider, model: pool[0].model, strategy: this.name, reason: "MyCustomStrategy: ...", candidatesConsidered: pool.length, finalScore: 1.0, }; } } registerStrategy("my-custom", new MyCustomStrategy()); ``` Pēc tam izmantojiet to: ```json { "strategy": "auto", "config": { "routerStrategy": "my-custom" } } ``` --- ### Maršrutētāja stratēģijas izvēles ceļvedis | Lietošanas gadījums | Stratēģija | Iemesls | | ------------------------ | ----------- | --------------------------------------- | | Līdzsvarota darba slodze | `rules` | Noklusējums — ņem vērā visus faktorus | | Izmaksu samazināšana | `cost` | Vienmēr izvēlas lētāko | | Latentuma samazināšana | `latency` | Izvēlas ātrāko uzticamo nodrošinātāju | | Stingri SLO | `sla-aware` | Filtrē pēc p95/kļūdu/izmaksu sliekšņiem | | Vairāku kārtu tērzēšana | `lkgp` | Sesijas piesaiste | | Dažāda sarežģītība | `nadir` | Izvēlas modeļa līmeni katrai uzvednei | SLA apzinātās stratēģijas lauki: ```json { "strategy": "auto", "config": { "routerStrategy": "sla-aware", "slaTargetP95Ms": 1500, "slaMaxErrorRate": 0.05, "slaMaxCostPer1MTokens": 5, "slaHardConstraints": true } } ``` ## Uzdevuma piemērotība 30+ modeļi vērtēti 6 uzdevumu tipos (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Atbalsta aizstājējzīmju rakstus (piemēram, `*-coder` → augsts koda izstrādes vērtējums). ## Auto varianta atkārtojums Ieskaitot tukšo `auto` (noklusējuma) un 6 `AutoVariant` vērtības, kas deklarētas `autoPrefix.ts`, kopā ir **7 izsaucamu modeļu ID**: `auto`, `auto/coding`, `auto/fast`, `auto/cheap`, `auto/offline`, `auto/smart`, `auto/lkgp` (`AutoVariant` pats uzskaita 6 vērtības; 7. iespēja ir "nav varianta" — tukšais `auto` — ko apstrādā `parseAutoPrefix()` kā `variant: undefined`.) ## Kā līmeņi iekļaujas Auto-Combo 16 faktoru vērtēšanas funkcija (`open-sse/services/autoCombo/scoring.ts`) līmeņa piederību izmanto kā divus signālus: `tierPriority` (0.0476) un `tierAffinity` (0.0476). Pilnu `DEFAULT_WEIGHTS` kopu skatiet iepriekš esošajā kanoniskajā [vērtēšanas faktoru tabulā](#how-it-works-persisted-auto-combos) — atsevišķu pakotņu pārrakstījumi (ship-fast/cost-saver/quality-first/ offline-friendly) ir norādīti tabulā "Svaru profili katrai pakotnei". Līmenis pats par sevi **nenodrošina**, ka 1. līmenis būs pirmais — ja 1. līmeņa latentums ir pārāk liels vai izmaksu un kvalitātes attiecība nav optimāla, uzvar 2. līmenis. Lai uzspiestu līmeņu secību, izmantojiet kombinācijas stratēģiju `priority` un sakārtojiet nodrošinātājus pēc līmeņa. Lai izteikti dotu priekšroku 1. līmenim (abonementam), palieliniet `tierPriority` svaru: ```json { "strategy": "auto", "config": { "auto": { "weights": { "tierPriority": 0.3, "costInv": 0.05 } } } } ``` Līmeņu definīcijas un nodrošinātāju klasifikāciju skatiet failā [`docs/guides/TIERS.md`](../guides/TIERS.md). ## Testēšana un pārklājums ### Deterministisks maršrutēšanas lēmumu matrica (`npm run test:combo:matrix`) `tests/integration/combo-matrix/*.test.ts` pierāda visu 19 publisko stratēģiju maršrutēšanas **lēmumu** end-to-end caur reālo kombinācijas konveijeru ar ģenerētu augšējo līmeni. Pārklājums ietver: - Visas 19 `ROUTING_STRATEGY_VALUES` stratēģijas (sakārtotas, svarītas, izmaksas, konteksts, saplūšana, …). - `quota-share` (iekšējs) end-to-end: DRR taisnīgums + piesātinājuma degradēšana caur reālo `selectQuotaShareTarget` šuvi (`registerQuotaFetcher` / `setLKGP` / `__setHeadroomSaturationFetcherForTests`). - `context-relay` universālā pārneses pārklājums visos mērķa skaitļos. Šī testa komplekta tiek palaists CI (`test:integration` darbs) ar `--test-concurrency=1` un `--test-force-exit`, lai tas būtu deterministisks un neprasītu dzīvos akreditīvus. ### Vārtots dzīvais dūmu tests (NAV CI — reāli sniedzēji) | Komanda | Ko tā dara | | :------------------------------------- | :------------------------------------------------------------------------------------ | | `npm run test:combo:live` | Procesā reāla maršrutēšana ar `RUN_COMBO_LIVE=1`; saglabā dzīvo OmniRoute DB snapšotu | | `npm run test:combo:live:vps` | HTTP pieprasījumi pret dzīvu OmniRoute serveri (iestatiet `COMBO_LIVE_BASE_URL`) | | `npm run test:combo:live:vps:failover` | Tas pats, ar tīšiem failover scenārijiem | Šie dūmu testi izmanto reālo tīkla ceļu (kombinācija → sniedzējs → pabeigšana). Tie ir apzināti izslēgti no CI, jo tiem nepieciešami dzīvie akreditīvi un VPS piekļuve. --- ## Faili | Fails | Mērķis | | :-------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------- | | `open-sse/services/autoCombo/scoring.ts` | 16 faktoru vērtēšanas funkcija, `DEFAULT_WEIGHTS`, kopas normalizācija | | `open-sse/services/autoCombo/taskFitness.ts` | Modeļa × uzdevuma piemērotības uzmeklēšana | | `open-sse/services/autoCombo/engine.ts` | Atlases loģika, bandīts, budžeta ierobežojums | | `open-sse/services/autoCombo/selfHealing.ts` | Izslēgšana, zondes, incidentu režīms | | `open-sse/services/autoCombo/modePacks.ts` | 6 svaru profili (ātra piegāde, izmaksu taupīšana, kvalitāte pirmajā vietā, piemērots bezsaistei, uzticamība pirmajā vietā, haosa režīms) | | `open-sse/services/autoCombo/autoPrefix.ts` | `auto/` prefiksa parsētājs + 6 varianti | | `open-sse/services/autoCombo/virtualFactory.ts` | Izveido atmiņā glabātu `AutoComboConfig` no aktīvajiem savienojumiem | | `open-sse/services/autoCombo/providerRegistryAccessor.ts` | Testēšanas āķis pakalpojumu sniedzēju reģistra imitēšanai | | `src/shared/constants/routingStrategies.ts` | `ROUTING_STRATEGY_VALUES` (20 stratēģijas) | | `src/sse/handlers/chat.ts` | Integrācija: auto-prefiksa agrīna apstrādes pārtraukšana |