# OmniRoute Auto-Combo Engine (नेपाली) 🌐 **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) · 🇱🇻 [lv](../../../lv/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) · 🇳🇱 [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) --- > **प्रयोगकर्ताहरूका लागि**: छिटो सुरु गर्न चाहनुहुन्छ? सरल व्याख्या र उदाहरणहरूका लागि [Auto-Combo प्रयोगकर्ता गाइड](../getting-started/AUTO-COMBO-GUIDE.md) हेर्नुहोस्। > अनुकूलनशील स्कोरिङ + शून्य-कन्फिग स्वतः-राउटिङसहितका स्व-व्यवस्थित मोडेल शृङ्खलाहरू ## शून्य-कन्फिग स्वतः-राउटिङ (`auto/` उपसर्ग) > **नयाँ:** कम्बो सिर्जना गर्न आवश्यक छैन। कुनै पनि क्लाइन्टमा सीधै `auto/` उपसर्ग प्रयोग गर्नुहोस्। ### द्रुत उदाहरणहरू | मोडेल ID | भेरियन्ट | व्यवहार | | -------------- | -------------- | --------------------------------------------------------------------------- | | `auto` | पूर्वनिर्धारित | सबै जडान गरिएका प्रदायकहरू, LKGP रणनीति, सन्तुलित भारहरू | | `auto/coding` | कोडिङ | गुणस्तर-प्राथमिक भारहरू, कोड उत्पादनका लागि उपयुक्त | | `auto/fast` | छिटो | न्यून-विलम्बता भारित चयन | | `auto/cheap` | सस्तो | लागत-अनुकूलित राउटिङ (पहिले सबैभन्दा कम लागत) | | `auto/offline` | अफलाइन | सबैभन्दा बढी कोटा उपलब्धता भएका प्रदायकहरूलाई प्राथमिकता | | `auto/smart` | स्मार्ट | गुणस्तर-प्राथमिक + अझ राम्रो मोडेल पहिचानका लागि उच्च अन्वेषण दर (10%) | | `auto/lkgp` | lkgp | स्पष्ट LKGP (पूर्वनिर्धारित `auto` सरह) | | `auto/chaos` | केओस | समानान्तर फ्यान-आउट, प्रत्येक प्रदायकबाट एउटा मोडेल (त्रुटि इन्जेक्सन होइन) | ### श्रेणी × टियर संयोजन (`auto/:`) OpenRouter-शैलीका प्रत्ययहरूले **कस्तो प्रकारको रुट** (श्रेणी) लाई **त्यसलाई कसरी अनुकूलन गर्ने** (टियर) बाट अलग गर्छन्, जसले गर्दा तिनलाई स्वतन्त्र रूपमा संयोजन गर्न सकिन्छ (#4235 Phase B, `open-sse/services/autoCombo/suffixComposition.ts`): - **श्रेणीहरू** (क्षमताका आधारमा उम्मेदवार पूल फिल्टर गर्ने): `coding` · `reasoning` · `vision` · `chat` · `multimodal`। `vision`/`multimodal` ले भिजन-सक्षम मोडेलहरू राख्छन्; `reasoning` ले रिजनिङ/थिङ्किङ मोडेलहरू राख्छ। - **टियरहरू** (स्कोरिङ भारहरू / पूल फिल्टर छनोट गर्ने): `fast` (छिटो डेलिभरी) · `cheap` (उपनाम `floor`, लागत-बचतकर्ता) · `reliable` (सर्किट-ब्रेकर स्वास्थ्य + विलम्बता स्थिरता) · `free` / `pro` (`classifyTier` मार्फत मोडेल टियरअनुसार पूल फिल्टर गर्ने — निःशुल्क-टियर विरुद्ध प्रिमियम)। | उदाहरण | यसमा रूपान्तरण हुन्छ | | ---------------------- | ---------------------------------------------------- | | `auto/coding:fast` | कोडिङ पूल, न्यून-विलम्बता भारहरू | | `auto/coding:cheap` | कोडिङ पूल, लागत-अनुकूलित (उपनाम `auto/coding:floor`) | | `auto/reasoning:pro` | रिजनिङ/थिङ्किङ मोडेलहरू मात्र, प्रिमियम टियर | | `auto/vision` | भिजन-सक्षम मोडेलहरू (टियर छैन → सन्तुलित भारहरू) | | `auto/multimodal:free` | मल्टिमोडल-सक्षम मोडेलहरू, निःशुल्क टियर मात्र | कुनै पनि मान्य `auto/[:]` माग हुँदा समाधान हुन्छ; चयनित उपसमूहलाई `/v1/models` र ड्यासबोर्डमा विज्ञापन गरिन्छ (`open-sse/services/autoCombo/builtinCatalog.ts` मा `AUTO_SUFFIX_VARIANTS`)। फिल्टरिङ **फेल-ओपन** हुन्छ — यदि कुनै सर्तसँग जडान भएका कुनै पनि मोडेल मेल खाँदैनन् भने, पूर्ण पूल प्रयोग गरिन्छ, जसले गर्दा राउटिङ कहिल्यै बिग्रँदैन। मूल स्कोरर (`combo.ts`) अपरिवर्तित छ; श्रेणी/टियर फिल्टर `buildAutoCandidates` मा लागू गरिन्छ। > **लाइभ मोडेल इन्टेलिजेन्स:** `ARENA_ELO_SYNC_ENABLED` फ्ल्याग सक्रिय हुँदा स्वतः-राउटिङको उपयुक्तता लाइभ **Arena ELO** र्याङ्किङ + **models.dev** टियर डेटाबाट निर्देशित हुन्छ (अन्यथा स्थिर फिटनेस म्यापमा फर्कन्छ)। **प्रयोग गर्ने तरिका:** ```bash # OpenAI ढाँचा समर्थन गर्ने कुनै पनि IDE वा CLI उपकरण Base URL: http://localhost:20128/v1 API Key: # आफ्नो कोड/कन्फिगमा मोडेल यसरी सेट गर्नुहोस्: model: "auto" # सन्तुलित पूर्वनिर्धारित model: "auto/coding" # कोडिङ कार्यहरूका लागि उत्कृष्ट model: "auto/fast" # उपलब्धमध्ये सबैभन्दा छिटो model: "auto/cheap" # प्रति टोकन सबैभन्दा सस्तो ``` **के हुन्छ:** 1. OmniRoute ले `src/sse/handlers/chat.ts` मा `auto/` उपसर्ग पत्ता लगाउँछ 2. डेटाबेसबाट सबै **सक्रिय प्रदायक जडानहरू** क्वेरी गर्छ 3. मान्य क्रेडेन्सियलहरू (API कुञ्जी वा OAuth टोकन) भएकाहरू मात्र फिल्टर गर्छ 4. प्रत्येक जडानका लागि मोडेल निर्धारण गर्छ (`connection.defaultModel` वा प्रदायकको पहिलो मोडेल) 5. मेमोरीमा **भर्चुअल कम्बो** निर्माण गर्छ (DB मा भण्डारण गरिँदैन) 6. चयन गरिएको भेरियन्टको भार प्रोफाइल + LKGP रणनीति प्रयोग गरेर राउट गर्छ **मुख्य विशेषताहरू:** - ✅ **सधैँ सक्रिय:** कुनै टगल, कम्बो सिर्जना वा कन्फिगरेसन आवश्यक छैन - ✅ **डायनामिक:** हाल जडान गरिएका प्रदायकहरूलाई स्वचालित रूपमा प्रतिबिम्बित गर्छ - ✅ **सत्र स्थिरता:** LKGP ले पछिल्लो सफल प्रदायकलाई प्राथमिकता दिइने सुनिश्चित गर्छ - ✅ **बहु-खाता सचेत:** प्रत्येक प्रदायक जडान छुट्टै उम्मेदवार बन्छ - ✅ **DB लेखाइ छैन:** भर्चुअल कम्बो अनुरोधका लागि मात्र अस्तित्वमा रहन्छ, कुनै पनि पर्सिस्टेन्स ओभरहेड हुँदैन ### प्रति-कुञ्जी उम्मेदवार नियन्त्रण (#7819, स्तर 1+2) `GET /v1/auto-combo/{channel}/candidates` (`{channel}` = `auto/` पछिको प्रत्यय, वा आधार च्यानलका लागि शाब्दिक `auto`) एउटा **पढ्न-मात्र** एन्डपोइन्ट हो, जसले अवस्थित रिजिलियन्स रिडहरू पुनः प्रयोग गर्दै, लाइभ पहुँचयोग्यताको विवरणसहित `auto/*` च्यानलको हालको उम्मेदवार पूल सूचीबद्ध गर्छ (कहिल्यै कच्चा ब्रेकर `state` होइन): - प्रदायक सर्किट ब्रेकर — `getCircuitBreaker(provider).getStatus()` / `.canExecute()` - जडान कुलडाउन — समाधान गरिएको `provider_connections` पङ्क्तिमा रहेको `rateLimitedUntil` / `testStatus` - मोडेल लकआउट — `isModelLocked(provider, connectionId, model)` प्रत्येक उम्मेदवारमा यस API कुञ्जीको `excluded` फ्ल्याग पनि हुन्छ। बहिष्करणहरू प्रति-API-कुञ्जी भण्डारण गरिन्छ (`auto_candidate_overrides` तालिका, माइग्रेसन `128`) — OmniRoute मा `users` तालिका नभएको एकल-टेनेन्ट प्रणाली भएकाले `apiKeyId` नै वास्तविक प्रति-कलर पहिचानको सबैभन्दा नजिकको विकल्प हो — र यसलाई `open-sse/services/autoCombo/virtualFactory.ts` को उम्मेदवार-पूल चोकपोइन्टमा शुद्ध, एकाइ-परीक्षित `filterExcludedCandidates()` (`open-sse/services/autoCombo/candidateOverrides.ts`) मार्फत लागू गरिन्छ। फिल्टर **फेल-ओपन** हुन्छ: सेट नगरिएको apiKeyId/channel वा DB लुकअप विफलता दुवैले पूललाई फिल्टर नगरिएको अवस्थामा छोड्छन्, त्यसैले कुनै ओभरराइड कन्फिगर नगरेको अपरेटरले यस सुविधाअघिकै बाइट-समान राउटिङ देख्छ। **फलो-अप मुद्दाका लागि स्थगित:** प्रति-candidate तौलहरू + स्पष्ट क्रम निर्धारण (Level 3 — विद्यमान weighted/priority रणनीति मार्गहरूमा समावेश हुन्छ) र प्रत्येक `auto/*` च्यानलका लागि विशिष्ट `combo.ts` रणनीति पिन गर्ने (Level 4)। single-tenant मोडेललाई ध्यानमा राख्दा overrides प्रति-API-key नै रहनुपर्छ वा global बन्नुपर्छ भन्ने खुला प्रश्नका लागि #7819 योजना हेर्नुहोस्। **पर्दापछाडि:** ```txt अनुरोध: { model: "auto/coding" } ↓ src/sse/handlers/chat.ts ले prefix पत्ता लगाउँछ ↓ createVirtualAutoCombo('coding') → सक्रिय connections बाट candidatePool ↓ handleComboChat (persist गरिएका combos कै engine) ↓ Auto-scoring ले प्रत्येक अनुरोधका लागि उत्कृष्ट provider/model चयन गर्छ ``` **कार्यान्वयन फाइलहरू:** | फाइल | उद्देश्य | | --------------------------------------------------------- | ---------------------------------------------- | | `open-sse/services/autoCombo/autoPrefix.ts` | Prefix parser (`parseAutoPrefix`) | | `open-sse/services/autoCombo/virtualFactory.ts` | Virtual `AutoComboConfig` objects सिर्जना गर्छ | | `open-sse/services/autoCombo/providerRegistryAccessor.ts` | Provider registry mock गर्नका लागि test hook | | `src/sse/handlers/chat.ts` | Integration: auto prefix short-circuit | | `src/shared/constants/providers.ts` | `SYSTEM_PROVIDERS.auto` system entry | ## वास्तविक Model Id सँग मेल खाने Combo नामहरू कुनै combo को `name` ठ्याक्कै bare model id सँग समान हुनु (उदाहरणका लागि, `gpt-5.5` नाम भएको combo) **जानाजानी प्रयोग गरिने, समर्थित ढाँचा** हो, bug होइन: यो [#6940](https://github.com/diegosouzapw/OmniRoute/issues/6940) मा दस्तावेज गरिएको प्रत्येक model-id का लागि provider fallback संयन्त्र हो। bare-model-id resolution भन्दा पहिले combo resolution जाँचिने भएकाले (`src/sse/services/model.ts` मा `getComboForModel()`), bare id `gpt-5.5` को अनुरोधलाई सिधै एउटै provider तर्फ पठाउनुको सट्टा combo का targets (उदाहरणका लागि, `acme-responses/gpt-5.5`, `backup-responses/gpt-5.5`) मार्फत route गरिन्छ — यसले [#3227/#3233](https://github.com/diegosouzapw/OmniRoute/issues/3227) का लागि बनाइएको combo-before-rewrite precedence पुनः प्रयोग गर्छ र `tests/unit/responses-combo-resolution-3227.test.ts` तथा `tests/unit/combo-name-codex-responses-rewrite.test.ts` द्वारा regression परीक्षण गरिएको छ। वास्तविक model id लाई छायामा पार्ने नामसहित combo सिर्जना वा पुनःनामकरण गर्दा त्यसलाई **कहिल्यै अस्वीकार गरिँदैन** — त्यसो गर्दा यो दस्तावेज गरिएको workflow बिग्रन्थ्यो। यसको सट्टा (#8530), (नयाँ) नाम वास्तविक model id सँग बाझिँदा `POST /api/combos` र `PUT /api/combos/[id]` ले response मा non-blocking `warning` field संलग्न गर्छन्: ```json { "warning": { "code": "COMBO_NAME_SHADOWS_MODEL", "modelId": "gpt-5.5", "providerId": "openai" } } ``` Boot हुँदा, `scanComboModelNameCollisionsAtBoot()` (`src/instrumentation-node.ts`) ले model id लाई छायामा पार्ने प्रत्येक विद्यमान combo सूचीकृत गर्दै एक-लाइनको `[STARTUP]` warning पनि log गर्छ, जसले जानाजानी (#6940 अनुसार) नभई संयोगवश यस्तो अवस्थामा पुगेका operators लाई संकेत दिन्छ। Detection helper `src/lib/combos/modelNameCollision.ts` मा छ। ## Client बाट Custom Combo कल गर्ने Persist गरिएका combos (Settings → Combos) client ले `model` field मा combo को **ठ्याक्कै मिल्ने नाम** पठाउँदा मात्र प्रयोग हुन्छन् — combo नामको fuzzy वा partial matching हुँदैन, र `auto/` prefix पनि संलग्न हुँदैन। Resolution क्रम (`src/sse/services/model.ts` मा `getComboForModel()`): 1. combo नामको ठ्याक्कै match (`model: "my-combo"`), 2. `combo/` prefix (`model: "combo/my-combo"`), 3. model→combo glob mappings (`/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"}]}' ``` दुईवटा सामान्य समस्या: - **`auto` ले तपाईंका combos प्रयोग गर्दैन।** `auto`/`auto/*` ले आफ्नै zero-config candidate pool बनाउँछ र कुनै combo को नाम अक्षरशः `auto` भएमा मात्र persist गरिएका combos हेर्छ (सिफारिस गरिँदैन)। combo मार्फत route गर्न, त्यसको ठ्याक्कै नाम पठाउनुहोस् — `auto` होइन। - **`openrouter/auto` एउटा वास्तविक सशुल्क OpenRouter product** ("Auto Best Available") हो, OmniRoute alias होइन। यो OpenRouter registry (`open-sse/config/providers/registry/openrouter/index.ts`) को एकल static model entry हो र यसको billing छुट्टै हुन्छ। यसलाई `auto` pools बाट हटाउन Settings → Routing → Hide paid models प्रयोग गर्नुहोस्। यहाँ दस्तावेज गरिएको मूल अन्योलबारे [#7992](https://github.com/diegosouzapw/OmniRoute/issues/7992) र [#7111](https://github.com/diegosouzapw/OmniRoute/issues/7111) हेर्नुहोस्। ## यसले कसरी काम गर्छ (स्थायी रूपमा भण्डारण गरिएका Auto-Combos) Auto-Combo Engine ले **16-कारक स्कोरिङ प्रकार्य** (`open-sse/services/autoCombo/scoring.ts` → `DEFAULT_WEIGHTS` मा परिभाषित) प्रयोग गरेर प्रत्येक अनुरोधका लागि उत्कृष्ट प्रदायक/मोडेल गतिशील रूपमा चयन गर्छ। पूर्वनिर्धारित भारहरूको योगफल `1.0` हुन्छ; अनुकूलन गरिएका भारहरूलाई `normalizeScoringWeights()` द्वारा पुनः सामान्यीकरण गरिन्छ। सोह्रमध्ये दुई — `cacheAffinity` र `resetWindowAffinity` — को पूर्वनिर्धारित भार `0` छ; `reliability` को भार `DEFAULT_WEIGHTS` मा `0` भए पनि सामान्य प्याकहरूमा `0.03` र `reliability-first` मा `0.04` छ, र `quality` को भार प्याकहरूमा `0.02` (`quality-first` मा `0.03`) छ: तिनलाई अझै पनि प्रत्येक उम्मेदवारका लागि गणना गरिन्छ, र `cacheAffinity` ले स्कोरबाहिर prompt-cache डिडुप्लिकेसनलाई नियन्त्रित गर्छ, त्यसैले शून्य-पूर्वनिर्धारित कारकहरूले पूर्वनिर्धारित रूपमा मत दिँदैनन् तर प्याकहरूले दिन्छन्। ![Auto-Combo को 16-कारक स्कोरिङ](../diagrams/exported/auto-combo-scoring.svg) > स्रोत: [diagrams/auto-combo-scoring.mmd](../diagrams/auto-combo-scoring.mmd) (`npm run docs:render-diagrams` मार्फत पुनः उत्पन्न गर्नुहोस्)। फाइलनाम ऐतिहासिक हो; स्रोत र रेन्डर गरिएको रेखाचित्रले `DEFAULT_WEIGHTS` मा घोषित सबै 16 कारक देखाउँछन्। | कारक | पूर्वनिर्धारित भार | विवरण | | :-------------------- | :----------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `quota` | 0.1429 | बाँकी कोटा / दर-सीमा अतिरिक्त क्षमता [0..1] | | `health` | 0.1605 | सर्किट ब्रेकरबाट प्राप्त स्वास्थ्य स्कोर (CLOSED=1.0, HALF_OPEN=0.5, OPEN=0.0) | | `costInv` | 0.1429 | **मिश्रित** लागतको व्युत्क्रम (60% इनपुट + 40% आउटपुट टोकन मूल्य, सामान्यीकृत) — सस्तो = उच्च स्कोर | | `latencyInv` | 0.1143 | पूलअनुसार सामान्यीकृत p95 विलम्बताको व्युत्क्रम — छिटो = उच्च स्कोर | | `taskFit` | 0.0762 | कार्य-प्रकार उपयुक्तता (कोडिङ, समीक्षा, योजना, विश्लेषण, डिबगिङ, दस्तावेजीकरण) | | `stability` | 0.0476 | विलम्बता मानक विचलनबाट प्राप्त भिन्नता-आधारित स्थिरता — प्रतिक्रिया समय धेरै उतारचढाव हुने उम्मेदवारले कम स्कोर प्राप्त गर्छ | | `tierPriority` | 0.0476 | खाता-तह प्राथमिकता — Ultra=1.0, Pro=0.67, Standard=0.33, Free=0.0 | | `tierAffinity` | 0.0476 | उम्मेदवारको तह र म्यानिफेस्टद्वारा सिफारिस गरिएको तहबीचको सामीप्य | | `specificityMatch` | 0.0476 | अनुरोधको विशिष्टता (म्यानिफेस्ट सङ्केत) र मोडेल तहबीचको मेल | | `contextAffinity` | 0.0476 | अनुरोधको कन्टेक्स्ट-विन्डो आवश्यकता र मोडेलको कन्टेक्स्ट विन्डोबीचको सामीप्य | | `sessionAvailability` | 0.0476 | यस सत्रका लागि उम्मेदवार जडानको OAuth सत्र उपलब्धता (`getOAuthSessionAvailability()`; गैर-OAuth जडानहरूले 1.0 स्कोर प्राप्त गर्छन्) | | `connectionDensity` | 0.0476 | एउटै प्रदायकका जडानहरूमा भार फैलाउँछ (केन्द्रीकरण-विरोधी) | | `cacheAffinity` | 0.00 | यस अनुरोधको prompt-cache उपसर्ग पहिल्यै राखेको हुनसक्ने जडानतर्फ Rendezvous-hash सामीप्य (`open-sse/services/combo/promptCacheAffinity.ts`); पूर्वनिर्धारित रूपमा असक्षम (#8008) | | `resetWindowAffinity` | 0.00 | अनुकूल कोटा रिसेट विन्डो भएका जडानहरूतर्फ झुकाव (पूर्वनिर्धारित रूपमा असक्षम) | | `quality` | 0.03 | राउटिङ-इभेन्ट गुणस्तर ट्र्याकरबाट प्राप्त प्रतिक्रियाद्वारा सञ्चालित आउटपुट-गुणस्तर सङ्केत; अवलोकन नभएका उम्मेदवारहरूले तटस्थ 0.5 प्राप्त गर्छन् | | `reliability` | 0.00 | दस-नमुना न्यूनतम सीमापछिको 24h प्रयोग इतिहासबाट प्राप्त अवलोकित सफलताको हिस्सा, `1 - failureRate` (अन्यथा वास्तविक-समय मेट्रिक्स); अवलोकन नभएका उम्मेदवारहरूको मान 1.0 हुन्छ। पूर्वनिर्धारित रूपमा असक्षम | `quality` (`open-sse/services/routing/quality.ts`): `cold restart → ∅`; `observations = 0 → score 0.5`. **योगफल:** `DEFAULT_WEIGHTS` मा घोषित गरिएअनुसार `0.1429 + 0.1605 + 0.1429 + 0.1143 + 0.0762 + (7 × 0.0476) + 0.00 + 0.00 + 0.03 + 0.00 = 1.0`; प्रयोगकर्ताद्वारा कन्फिगर गरिएका भारहरूलाई स्कोरिङअघि `normalizeScoringWeights()` द्वारा वितरणमा पुनः सामान्यीकरण गरिन्छ। ## मोड प्याकहरू `open-sse/services/autoCombo/modePacks.ts` मा 6 वटा पूर्व-परिभाषित तौल प्रोफाइलहरू छन्। प्रत्येक प्याकले चयनलाई एउटा लक्ष्यतर्फ झुकाउन पूर्वनिर्धारित तौलहरू पूर्ण रूपमा प्रतिस्थापन गर्छ। प्रत्येक प्याकको योगफल पहिले नै `1.0` हुन्छ (चार दशमलवमा देखाउँदा `0.9999`), त्यसैले प्याक सक्रिय हुँदा `normalizeScoringWeights()` ले अर्थपूर्ण रूपमा सच्याउनुपर्ने केही हुँदैन — तलका मानहरू, राउन्डिङलाई छोडेर, स्कोररले लागू गर्ने मानहरू नै हुन्। | कारक | 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 | टिप्पणीहरू: - **प्याकहरूले `quality` र `reliability` समावेश गर्छन्** (`quality 0.02`, `quality-first 0.03`; `reliability 0.03`, `reliability-first 0.04`) र तौल नक्सालाई पूर्ण रूपमा प्रतिस्थापन गर्छन् (`weights = pack`, मर्ज होइन)। `DEFAULT_WEIGHTS` मा `quality 0.03 / reliability 0` हुन्छ; `balanced`/`default` चयन गर्दा ती पूर्वनिर्धारित मानहरू कायम रहन्छन्, जबकि कुनै प्याक चयन गर्दा माथिका प्याक मानहरू प्रयोग हुन्छन्। चिसो पूलमा (अझै कुनै अवलोकन नभएकोले `quality 0.5` र `reliability 1`) यी दुई कारकहरूले सामान्य प्याकअन्तर्गत `+0.04` (`0.03 + 0.01`), `quality-first` अन्तर्गत `+0.045` र `reliability-first` अन्तर्गत `+0.05` थप्छन्। - `tierAffinity`, `specificityMatch` र `resetWindowAffinity` प्रत्येक प्याकमा स्पष्ट रूपमा `0` छन्। - प्रत्येक प्याकको जोड एक नजरमा: - **ship-fast** → latencyInv 0.3048 + health 0.2667 (कम विलम्बता, स्वस्थ जडानहरू) - **cost-saver** → costInv 0.3324 (सबैभन्दा सस्ता टोकनहरू विजयी हुन्छन्) - **quality-first** → taskFit 0.3524 + stability 0.1429 + quality 0.03, जुन कुनै पनि प्याकमध्ये सबैभन्दा उच्च हो (कार्यका लागि सर्वोत्तम र सुसंगत मोडेल) - **offline-friendly** → quota 0.3324 + health 0.2667 (गति/लागतको परवाह नगरी अधिकतम अतिरिक्त क्षमता) - **reliability-first** → health 0.3524 + stability 0.1905 + reliability 0.04, जुन कुनै पनि प्याकमध्ये सबैभन्दा उच्च हो (न्यूनतम अप्रत्याशितता) - **chaos-mode** → health 0.4000 + taskFit 0.1905 (तौल प्याक `auto/chaos` ले आफ्ना प्यानल सदस्यहरूलाई प्रदान गर्ने मान; समानान्तर फ्यान-आउटले यी तौलहरू पढ्दैन, र यो त्रुटि-इन्जेक्सन प्रोफाइल होइन, [CHAOS-MODE.md](../guides/CHAOS-MODE.md#autochaos-parallel-fan-out) हेर्नुहोस्) ### प्रति-अनुरोध नियन्त्रणहरू (हेडरहरू) — #6023 / #6024 / #6025 / #3470 एउटा `auto` कम्बोलाई भण्डारण गरिएको कम्बो कन्फिगरेसन परिवर्तन नगरी, तीनवटा हेडरमार्फत **प्रत्येक अनुरोधका लागि** निर्देशित गर्न सकिन्छ। यी केवल `auto` रणनीतिमा र तिनलाई समावेश गर्ने अनुरोधमा मात्र लागू हुन्छन्; हेडर अनुपस्थित हुँदा कम्बोका सुरक्षित गरिएका `modePack`/`budgetCap`/`budgetFallback` प्रयोग गरिन्छ। | हेडर | स्वीकार गर्ने मानहरू | प्रभाव | | :---------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `X-OmniRoute-Mode` | पूर्वनिर्धारित उपनाम (`fast`, `balanced`, `quality`, `cheap`, `reliable`, `offline`) वा कच्चा प्याक नाम (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`, `reliability-first`) | यस अनुरोधका लागि स्कोरिङ भारहरू अधिलेखन गर्छ। `balanced`/`default` ले पूर्वनिर्धारित भारहरू लागू गर्छन् (कुनै प्याक हुँदैन)। अज्ञात मानहरू बेवास्ता गरिन्छन् (कन्फिग सुरक्षित रहन्छ)। | | `X-OmniRoute-Budget` | धनात्मक सङ्ख्या (प्रति अनुरोध अधिकतम USD) | कडा लागत सीमा: अनुमानित लागत यो सीमाभन्दा बढी हुने उम्मेदवारहरू छनोटअघि फिल्टर गरिन्छन्। **हरेक** उम्मेदवारले यो सीमा नाघ्दा के हुन्छ भन्ने कुरा तलको `X-OmniRoute-Budget-Fallback` द्वारा नियन्त्रित हुन्छ। | | `X-OmniRoute-Budget-Fallback` | `cheapest` (पूर्वनिर्धारित, उपनामहरू: `cheapest-viable`, `soft`) वा `strict` (उपनामहरू: `block`, `hard`) | `cheapest`: सीमा अझै नाघे पनि समग्रमा सबैभन्दा सस्तो उम्मेदवारमा फलब्याक गर्छ (पुरानो व्यवहार)। `strict`: छनोट गर्न अस्वीकार गर्छ — मौन रूपमा बढी खर्च गर्नुको सट्टा अनुरोध `HTTP 402` सहित तुरुन्तै असफल हुन्छ। अज्ञात मानहरू बेवास्ता गरिन्छन्। | | `X-OmniRoute-Effort` | `auto` (अन्य मानहरू आरक्षित छन्) | अनुकूली सोच बजेट: जब अनुरोधमा कुनै पनि स्वरूपको reasoning फिल्ड (`reasoning_effort`, `reasoning`, `thinking`) **हुँदैन**, गेटवेले निर्धारणात्मक अनुरोध-संरचना सङ्केतहरू (अन्तिम प्रयोगकर्ता सन्देशको लम्बाइ, अन्तिम प्रयोगकर्ता सन्देशसम्मको सन्दर्भ आकार, अघिल्ला उपकरण नतिजाहरू, उपकरण-लुपको गहिराइ) का आधारमा `auto` लाई `low`/`medium`/`high` मा समाधान गर्छ। सङ्केतहरू हालको टर्नमा सीमित हुन्छन् — अन्तिम प्रयोगकर्ता सन्देशपछिका सबै कुरा बेवास्ता गरिन्छन् — त्यसैले उपकरण लुपभित्रका प्रत्येक अनुरोध एउटै स्तरमा समाधान हुन्छन् (स्टेटलेस प्रति-टर्न पिन, कुनै सत्र अवस्था छैन, र अपस्ट्रिम प्रम्प्ट-क्यास प्रिफिक्सहरू भङ्ग गर्ने मध्य-लुप वृद्धि हुँदैन)। क्लाइन्टले स्पष्ट रूपमा दिएको reasoning फिल्डले सधैँ प्राथमिकता पाउँछ। अपस्ट्रिम डिस्प्याच OpenAI Chat Completions संरचनामा (`targetFormat === FORMATS.OPENAI`) समाधान हुने अनुरोधहरूमा मात्र सीमित — `reasoning_effort` OpenAI-स्वरूपको फिल्ड भएकाले Claude वा Gemini लक्षित अनुरोधमा यो हेडरले कुनै प्रभाव पार्दैन (`open-sse/handlers/chatCore/adaptiveEffortWiring.ts` हेर्नुहोस्)। | ```bash # सबैभन्दा छिटो प्रोफाइल लागू गर्नुहोस्, यस अनुरोधलाई $0.05 मा सीमित गर्नुहोस्, र बढी खर्च गर्नुको सट्टा पूर्ण रूपमा रोक्नुहोस् 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"}]}' ``` समाधान एउटा शुद्ध फङ्सन (`open-sse/services/autoCombo/requestControls.ts`) हो; समाधान गरिएका मानहरू इन्जिनका विद्यमान `config.modePack` / `config.budgetCap` / `config.budgetFallback` इनपुटहरूमा पठाइन्छन्। कम्बोमा भण्डारण गरिएको `config.budgetFallback` ("strict" | "cheapest") ले स्थायी नीति निर्धारण गर्छ; हेडरले एकल अनुरोधका लागि त्यसलाई ओभरराइड गर्छ। ## सबै राउटिङ रणनीतिहरू OmniRoute को कम्बो इन्जिनले **20 वटा राउटिङ रणनीतिहरू** समर्थन गर्छ (`src/shared/constants/routingStrategies.ts` → `ROUTING_STRATEGY_VALUES` मा घोषणा गरिएका)। Auto Combo इन्जिन स्वयं `auto` रणनीतिअन्तर्गत उपलब्ध छ; अन्य रणनीतिहरू सुरक्षित गरिएका कम्बोहरूका लागि उपलब्ध छन्। | रणनीति | विवरण | | :------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `priority` | स्पष्ट प्राथमिकतासहित पहिलो-लक्ष्यमा आधारित क्रमबद्ध सूची | | `weighted` | प्रत्येक लक्ष्यको तौलअनुसार भारित अनियमित छनोट | | `round-robin` | लक्ष्यहरूलाई क्रमैसँग चक्रीय रूपमा प्रयोग गर्ने (ब्याचमा; तल हेर्नुहोस्) | | `context-relay` | लक्ष्यहरूबीच कन्टेक्स्ट हस्तान्तरण गर्ने (लामो संवादहरू) | | `fill-first` | अर्कोमा जानुअघि प्रत्येक लक्ष्यको कोटा पूरा गर्ने | | `p2c` | २-विकल्पको शक्ति प्रयोग गर्ने अनियमित लोड सन्तुलन | | `random` | समान सम्भावनायुक्त अनियमित छनोट | | `least-used` | हालको सबैभन्दा कम लोड भएको लक्ष्य छान्ने | | `cost-optimized` | क्याटलग मूल्य निर्धारणका आधारमा प्रत्येक अनुरोधको $ लागत न्यूनतम गर्ने | | `reset-aware` ⭐ | कोटा रिसेट समयका आधारमा प्राथमिकता दिने — छोटो रिसेट विन्डोलाई उच्च स्थान दिने | | `reset-window` | सबैभन्दा चाँडै कोटा विन्डो रिसेट हुने लक्ष्यलाई प्राथमिकता दिने | | `headroom` | सबैभन्दा धेरै बाँकी कोटा क्षमता भएको लक्ष्य छान्ने | | `quota-weighted` | कोटा सकिएका खाताहरू छोडेर, बाँकी कोटालाई चालू लोडले भाग गर्दा प्राप्त अनुपातअनुसार बाँकी खातामध्ये छनोट गर्ने; विद्यमान संवादहरू एउटै लक्ष्यमा पिन रहन्छन् | | `strict-random` | दोहोरिएका लक्ष्यहरू नहटाई अनियमित छनोट गर्ने | | `auto` | Auto Combo स्कोरिङ (16-कारक) प्रयोग गर्ने — **सिफारिस गरिएको** | | `lkgp` | अन्तिम-ज्ञात-सफल मार्ग (अन्तिम सफल प्रदायकमा पिन गर्छ, त्यसपछि नियमहरूमा फलब्याक गर्छ) | | `context-optimized` | हालको कन्टेक्स्ट आकारसँग सबैभन्दा उपयुक्त लक्ष्य छान्ने | | `cache-optimized` | प्रम्प्ट-क्यास सामीप्यअनुसार लक्ष्यहरू पुनः क्रमबद्ध गर्ने — यो अनुरोधको क्यास गरिएको प्रिफिक्स पहिले नै राखेको हुन सक्ने सबैभन्दा सम्भावित कनेक्सनलाई पहिले प्रयास गरिन्छ (`open-sse/services/combo/promptCacheAffinity.ts`, #8008) | | `fusion` 🧬 | मोडेलहरूको प्यानलमा समानान्तर रूपमा अनुरोध पठाउने, त्यसपछि निर्णायकमार्फत एउटै उत्तर संश्लेषण गर्ने (तल हेर्नुहोस्) | | `pipeline` | प्रत्येक चरणको आउटपुटलाई अर्को चरणको इनपुटमा प्रवाह गर्दै लक्ष्यहरू क्रमिक रूपमा चलाउने; अन्तिम उत्तर मात्र फर्काइन्छ (#6396) | ⭐ = v3.8.0 मा नयाँ · 🧬 = v3.8.36 मा नयाँ ### `weighted` को अर्थविज्ञान `weighted` एउटा **प्रत्येक अनुरोधमा हुने अनुपातिक अनियमित छनोट** हो (`open-sse/services/combo/targetSorters.ts` → `selectWeightedTarget`), बराबरी गर्ने संयन्त्र होइन: - प्रत्येक अनुरोधले `weight / totalWeight` सम्भावनाका आधारमा **एउटा** चरण छान्छ; बाँकी चरणहरूलाई त्यस अनुरोधको फलब्याक शृङ्खलाका रूपमा घट्दो तौलअनुसार क्रमबद्ध गरिन्छ। - `0` तौल भएको (वा तौल नदिइएको) चरणलाई, अन्य कुनै चरणको तौल > 0 हुँदा **कहिल्यै छानिँदैन** — छानिएको चरण असफल भएपछि मात्र त्यसले फलब्याकका रूपमा काम गर्न सक्छ। **सबै** तौल 0 हुँदा मात्र छनोट समान सम्भावनायुक्त हुन्छ। - सबै लक्ष्यहरू अनुपलब्ध भएका चरणहरू — प्रदायक सर्किट ब्रेकर `OPEN`, कनेक्सन कूलडाउन, मोडेल लकआउट — छनोट हुनुअघि नै हटाइन्छन् (`open-sse/services/combo/targetResolution.ts`), त्यसैले एउटा मात्र स्वस्थ चरणले अस्थायी रूपमा हरेक अनुरोध जित्न सक्छ। - `stickyWeightedLimit` (कम्बो कन्फिग, पूर्वनिर्धारित `1` = बन्द) ले पुनः छनोट गर्नुअघि छानिएको चरणलाई त्यति सङ्ख्याका लगातार सफलताहरूसम्म पिन गर्छ। कडा रोटेसनका लागि `round-robin` प्रयोग गर्नुहोस्; `weighted` मा समान तौलहरूले सांख्यिकीय — कडा होइन — सन्तुलन दिन्छन्। ### एजेन्टिक पाइपलाइन मोड कम्तीमा दुई मोडेल भएको `pipeline` कम्बोले `config.agenticOrchestration.enabled` मार्फत प्लानर/एक्जिक्युटर राउटिङ रोज्न सक्छ। पहिलो टार्गेटले योजना र अन्तिम उत्तरहरूको जिम्मेवारी लिन्छ; दोस्रो टार्गेटले क्लाइन्ट-नेटिभ टुल कलहरू उत्सर्जन गर्छ। OmniRoute ले अनुरोध प्रोटोकलबाट टुल-रिजल्ट निरन्तरताहरू पत्ता लगाउँछ, अर्को टुल चरण आवश्यक छ कि छैन भनेर प्लानरलाई सोध्छ, र एक्जिक्युटर वा प्लानरमध्ये कुनै एकलाई गतिशील रूपमा क्लाइन्टले देख्ने अन्तिम चरण बनाउँछ। दोस्रो टार्गेटपछिका अतिरिक्त मोडेलहरू क्रमबद्ध एक्जिक्युटर ब्याकअपहरू हुन्। असफल HTTP प्रतिक्रिया वा ट्रान्सपोर्ट अपवादले उही प्लानर निर्णय र नेटिभ टुलहरू साथमा राख्दै, तर त्यस एक्जिक्युटरको आफ्नै चरण प्रम्प्ट र रिजोल्भ गरिएको कनेक्सन प्रयोग गर्दै अर्को एक्जिक्युटरतर्फ अघि बढाउँछ। पहिलो सफल प्रतिक्रिया SSE स्ट्रिमिङसहित अपरिवर्तित रूपमा फिर्ता गरिन्छ; सफल स्ट्रिम सुरु भएपछि भएका विफलताहरूलाई यहाँ पुनः प्रयास गर्न सकिँदैन। सबै एक्जिक्युटर असफल भएमा, अन्तिम विफलता फिर्ता गरिन्छ। क्लाइन्टद्वारा गरिएका रद्दीकरणहरूले डिस्प्याच रोक्छन्। ```json { "strategy": "pipeline", "models": [{ "model": "provider/planner" }, { "model": "provider/executor" }], "config": { "agenticOrchestration": { "enabled": true, "maxToolRounds": 8 } } } ``` एक्जिक्युटरले एउटै प्रतिक्रियामा धेरै स्वतन्त्र कलहरू उत्सर्जन गर्न सक्छ। निर्भर कलहरू पछिल्ला क्लाइन्ट टुल-रिजल्ट चरणहरूमा ह्यान्डल गरिन्छन्, जहाँ प्लानरले प्रत्येक परिणाम समीक्षा गर्छ। `maxToolRounds` को पूर्वनिर्धारित मान `8` हो र यसले `1`–`32` स्वीकार गर्छ; सीमा पुगेपछि, प्लानरले उपलब्धमध्ये उत्कृष्ट अन्तिम उत्तर दिनुपर्छ। आन्तरिक प्लानर निर्णयहरू बफर गरिन्छन्, जबकि चयन गरिएको क्लाइन्टले देख्ने प्रतिक्रियाले मूल स्ट्रिमिङ प्राथमिकतालाई कायम राख्छ। ### `round-robin` स्टिकी ब्याच र अकाउन्ट विस्तार राउन्ड-रोबिन ब्याचमा हुन्छ, प्रत्येक चरणमा एउटा अनुरोध हुने गरी होइन: - `stickyRoundRobinLimit` (पहिले कम्बो कन्फिग, त्यसपछि `comboStickyRoundRobinLimit`, त्यसपछि `settings.stickyRoundRobinLimit`, पूर्वनिर्धारित **3**) ले रोटेट गर्नुअघि त्यति सङ्ख्याका लगातार सफलताहरूका लागि उही टार्गेट कायम राख्छ। प्रत्येक अनुरोधमा रोटेसनका लागि कम्बो ओभरराइडलाई `1` मा सेट गर्नुहोस्। कम्बो एडिटरले प्रभावकारी मान र त्यो कुन तहबाट आएको हो भन्ने देखाउँछ। - `connectionAwareExpansion` (पहिले कम्बो कन्फिग, त्यसपछि सेटिङ्स, पूर्वनिर्धारित **false**) ले रोटेसनअघि प्रत्येक प्रोभाइडर-स्तरीय चरणलाई प्रति-अकाउन्ट टार्गेटहरूमा विस्तार गर्छ। ग्रुप-B रणनीतिहरू (priority, weighted, round-robin, random, p2c, least-used, cost-optimized, lkgp, fill-first, strict-random, context-optimized, cache-optimized, context-relay, fusion, pipeline) ले यो सक्रिय नभएसम्म प्रोभाइडर-स्तरीय दृश्य कायम राख्छन्। कम्बो एडिटरले inherit / on / off विकल्पहरू उपलब्ध गराउँछ; inherit ले ग्लोबल पूर्वनिर्धारित मान (off) प्रयोग गर्छ। - प्रम्प्ट-क्यास लोकालिटी राउटिङ (`promptCacheAffinityEnabled`, पूर्वनिर्धारित **true**) ले पिन गरिएका कनेक्सनहरूलाई पुनः क्रमबद्ध गर्छ, ताकि मिल्ने क्यास कुञ्जीहरू एउटै अकाउन्टमा रहून्। पिन गरिएका प्रति-अकाउन्ट चरणहरूमा यसले राउन्ड-रोबिन र वेटेड रोटेसनभन्दा प्राथमिकता पाउँछ। तपाईंलाई कडा रोटेसन चाहिन्छ भने Settings → Combo defaults अन्तर्गत यसलाई बन्द गर्नुहोस्। यसका लागि प्रति-कम्बो ओभरराइड छैन। एउटै मोडेलमा बहु-अकाउन्ट रोटेसनका लागि, तीनवटा पिन गरिएका `connectionId` हरूको सट्टा स्टिकी सीमा `1` भएको **एउटा डायनामिक-अकाउन्ट चरण** (खाली `connectionId`, सम्पूर्ण पूल) लाई प्राथमिकता दिनुहोस्। RR काउन्टर अघि बढिरहँदा पनि पिन गरिएका चरणहरू र एफिनिटी एउटै अकाउन्टमा समेटिन्छन्। ## फ्युजन रणनीति `fusion` एउटा यस्तो रणनीति हो जसले कुनै एकल लक्ष्य चयन **गर्दैन**। यसले प्रम्प्टलाई **प्रत्येक प्यानल मोडेलमा समानान्तर रूपमा** पठाउँछ, त्यसपछि कन्फिगर गर्न मिल्ने **निर्णायक मोडेल** ले सबै प्यानल प्रतिक्रियाबाट एउटा अन्तिम उत्तर संश्लेषण गर्छ। यो upstream `decolua/9router` (OpenRouter को Fusion डिजाइन) बाट पोर्ट गरिएको हो; यसको कार्यान्वयन `open-sse/services/fusion.ts` मा छ। यसले कसरी काम गर्छ: 0. **उपकरणयुक्त बाइपास** — गैर-रिक्त `tools` एरे भएको र `tool_choice` लाई स्पष्ट रूपमा `"none"` नतोकिएको अनुरोधले प्यानललाई पूर्ण रूपमा छोड्छ: यो अपरिवर्तित रूपमा पास गरिएका `tools`/`tool_choice` सहित सिधै एउटा मोडेलमा (कन्फिगर गरिएको निर्णायक, वा `panel[0]`) रुट हुन्छ। प्यानल सदस्यहरूसँग उपकरण पहुँच हुँदैन र निर्णायकको संश्लेषण निर्देशनले उपकरण-कल उत्सर्जनलाई निरुत्साहित गर्छ, त्यसैले एजेन्टिक/उपकरण-कल गर्ने क्लाइन्टहरूले संश्लेषित गद्यको सट्टा वास्तविक उपकरण-कल निर्णय प्राप्त गर्छन् (#6771)। 1. **फ्यान-आउट** (उपकरणरहित अनुरोधहरूमा मात्र) — प्रम्प्टलाई सबै प्यानल मोडेलमा एकैपटक पठाइन्छ, उपकरणहरू हटाएर नन-स्ट्रिमिङ हुन बाध्य पारिन्छ (निर्णायकलाई संश्लेषण गर्न पूर्ण गद्य चाहिन्छ)। 2. **कोरम-ग्रेस सङ्कलन** — `minPanel` उत्तरहरू प्राप्त हुनेबित्तिकै पछाडि परेकाहरूका लागि छोटो ग्रेस टाइमर सुरु हुन्छ, त्यसपछि सङ्कलन भएका उत्तरहरू लिएर फ्युजन अगाडि बढ्छ। यसले सबैभन्दा ढिलो मोडेलका कारण कुल प्रतीक्षा समयमा पर्ने असरलाई सीमित गर्छ, जुन हार्ड टाइमआउटद्वारा बाँधिएको हुन्छ। 3. **निर्णायक संश्लेषण** — प्यानल उत्तरहरूलाई अज्ञातीकृत गरिन्छ (`Source 1`, `Source 2`, … — ताकि निर्णायकले मोडेल ब्रान्ड होइन, विषयवस्तुको महत्त्व मूल्याङ्कन गरोस्) र निर्णायकलाई दिइन्छ, जसले सहमति / विरोधाभास / आंशिक समेटाइ / अद्वितीय अन्तर्दृष्टि / छुटेका पक्षहरूको विश्लेषण गर्छ, त्यसपछि **एउटा** आधिकारिक उत्तर लेख्छ। निर्णायक कलले क्लाइन्टको मूल `stream` फ्ल्याग + उपकरणहरू कायम राख्छ, त्यसैले स्ट्रिमिङ र डाउनस्ट्रिम उपकरण प्रयोग अझै काम गर्छ। 4. **सहज अवनति** — 0 प्यानल उत्तर → `503`; ठ्याक्कै 1 बाँकी उत्तर → त्यो उत्तर सिधै फर्काइन्छ (फ्युज गर्न केही हुँदैन); एकल-मोडेल प्यानलले सिधै उत्तर दिन्छ। प्यानल सदस्य अर्को कम्बोलाई सन्दर्भ गर्ने `combo-ref` चरण (`{kind: "combo-ref", comboName: "..."}`) पनि हुन सक्छ — यो **एउटा ब्ल्याक-बक्स प्यानल आवाज** का रूपमा समाधान हुन्छ (सन्दर्भित कम्बोमा पूर्ण पुनरावर्ती डिस्प्याच, त्यस कम्बोका आफ्नै लक्ष्यहरूको फ्यान-आउट होइन), र यसमा अन्य हरेक combo-ref प्रयोग गर्ने रणनीतिले पहिलेदेखि प्रयोग गर्ने उही गहिराइ/चक्र सुरक्षा लागू हुन्छ (#6764)। ### कन्फिगरेसन कम्बोको `config` ब्लबमा कन्फिगर गरिन्छ (स्किमा माइग्रेसन आवश्यक छैन — यसले विद्यमान `combos` तालिका पुनः प्रयोग गर्छ): | फिल्ड | प्रकार | पूर्वनिर्धारित | उद्देश्य | | :--------------------------------------- | :------- | :----------------- | :--------------------------------------------------------------------------------- | | `config.judgeModel` | `string` | पहिलो प्यानल मोडेल | अन्तिम उत्तर संश्लेषण गर्ने मोडेल | | `config.fusionTuning.minPanel` | `number` | `2` | ग्रेस टाइमर सुरु हुनुअघि आवश्यक सफल उत्तरहरू (`[2, panelSize]` भित्र सीमित गरिन्छ) | | `config.fusionTuning.stragglerGraceMs` | `number` | `8000` | कोरम पुगेपछि पछाडि परेकाहरूका लागि कति समय पर्खने | | `config.fusionTuning.panelHardTimeoutMs` | `number` | `90000` | एउटा अड्किएको मोडेलले अनुरोध रोक्न नसकोस् भनेर तोकिएको पूर्ण अधिकतम सीमा | पूर्वनिर्धारित मानहरू `FUSION_DEFAULTS` (`open-sse/services/fusion.ts`) मा छन्। ### उदाहरण ```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 } } }' ``` त्यसपछि यसलाई अन्य कुनै कम्बोजस्तै कल गर्नुहोस्: `{"model":"fusion-panel","messages":[...]}`। ## भर्चुअल अटो-कम्बो फ्याक्ट्री Auto Combo इन्जिनलाई पूर्व-परिभाषित कम्बोहरू आवश्यक पर्दैन। यसको सट्टा, `open-sse/services/autoCombo/virtualFactory.ts` ले तत्कालै उम्मेदवारहरू निर्माण गर्छ: 1. `getProviderConnections({ isActive: true })` (सबै सक्षम जडानहरू) प्राप्त गर्छ 2. वैध क्रेडेन्सियल भएका जडानहरूमा फिल्टर गर्छ (API key वा `hasUsableOAuthToken()` मार्फत म्याद नसकिएको OAuth token) 3. मोडेल उपलब्धता + मूल्य निर्धारणका लागि `getProviderRegistry()` सँग क्रस-रेफरेन्स गर्छ 4. प्रत्येक `(provider, model, connection)` ट्युपलका लागि, एउटा `VirtualAutoComboCandidate` निर्माण गर्छ 5. डिस्प्याच लक्ष्यका रूपमा `connection.defaultModel` (वा registry को पहिलो मोडेल) चयन गर्छ 6. 16-कारक `scorePool()` र भेरियन्टको weight pack प्रयोग गरेर प्रत्येक उम्मेदवारलाई स्कोर गर्छ 7. `handleComboChat()` का लागि नतिजास्वरूप प्राप्त इन-मेमोरी `AutoComboConfig` फर्काउँछ — DB मा कहिल्यै स्थायी रूपमा भण्डारण हुँदैन यसको अर्थ **`auto/*` सक्षम गरिएको नयाँ provider थप्दा उम्मेदवार पूल स्वतः विस्तार हुन्छ** — म्यानुअल रूपमा कम्बो सम्पादन गर्नुपर्दैन। भर्चुअल कम्बो प्रत्येक अनुरोधमा पुनःनिर्माण हुन्छ, त्यसैले भर्खरै थपिएका वा पुनः स्वस्थ भएका जडानहरू तत्काल समावेश हुन्छन्। ## स्व-उपचार - **अस्थायी बहिष्करण**: स्कोर < 0.2 → 5 मिनेटका लागि बहिष्कृत (क्रमिक backoff, अधिकतम 30 मिनेट) - **Circuit breaker सचेतना**: OPEN → स्वतः बहिष्कृत; HALF_OPEN → परीक्षण अनुरोधहरू - **घटना मोड**: >50% OPEN → अन्वेषण निष्क्रिय गर्ने, स्थिरता अधिकतम बनाउने - **Cooldown पुनःप्राप्ति**: बहिष्करणपछि, पहिलो अनुरोध घटाइएको timeout सहितको "probe" हुन्छ ## Bandit अन्वेषण 5% अनुरोधहरू (कन्फिगर गर्न मिल्ने) अन्वेषणका लागि अनियमित provider हरूमा रुट गरिन्छन्। घटना मोडमा यो निष्क्रिय हुन्छ। ## API यहाँ **कुनै समर्पित `POST /api/combos/auto` एन्डपोइन्ट छैन** — Auto-Combo दुई तरिकाले प्रयोग गरिन्छ: 1. **शून्य-कन्फिगरेसन (सिफारिस गरिएको):** `model: "auto"` वा `model: "auto/"` सहित कुनै पनि च्याट कम्प्लिसन अनुरोध पठाउनुहोस्। भर्चुअल फ्याक्ट्रीले प्रत्येक अनुरोधका लागि कम्बो निर्माण गर्छ — कुनै स्थायी भण्डारण वा API कल आवश्यक पर्दैन। 2. **`strategy: "auto"` सहित स्थायी कम्बो:** `POST /api/combos` मार्फत नियमित कम्बो सिर्जना गर्नुहोस् र `strategy: "auto"` का साथै `config.auto.weights` / `config.auto.candidatePool` सेट गर्नुहोस्। उही स्कोरिङ इन्जिन प्रयोग गरिन्छ; कम्बो `combos` मा भण्डारण हुन्छ र ID द्वारा पुनः प्रयोग गर्न सकिन्छ। खोजका लागि, `GET /api/combos/auto` ले प्रत्येक भेरियन्टलाई त्यसको समाधान गरिएको क्यान्डिडेट पूलका साथै `context_length` / `max_output_tokens` सहित सूचीबद्ध गर्छ — जुन क्यान्डिडेट पूलका विन्डोहरूमध्ये अधिकतम मान हो। क्लाइन्टहरू (जस्तै opencode प्लगइन) ले `0` को सट्टा यी मानहरू विज्ञापन गर्नुपर्छ: शून्य कन्टेक्स्टले opencode को स्वचालित कम्प्याक्सन पूर्ण रूपमा निष्क्रिय गर्छ, जसले गर्दा गेटवेको हिस्ट्री पर्जले कन्टेक्स्ट नष्ट नगरेसम्म सेसनहरू बढिरहन्छन्। MAX विज्ञापन गर्न सुरक्षित छ किनभने auto-combo कन्टेक्स्ट प्रि-फिल्टरले अत्यधिक ठूला अनुरोधहरूलाई ठूला-विन्डो भएका क्यान्डिडेटहरूतर्फ रुट गर्छ। ```bash # शून्य-कन्फिगरेसन प्रयोग (कम्बो सिर्जना आवश्यक छैन) 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"}]}' # नियमित combos एन्डपोइन्टमार्फत स्थायी auto कम्बो 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}}}}' ``` ### Auto राउटर रणनीतिहरू स्थायी `strategy: "auto"` कम्बोहरूले `config.routerStrategy` (वा पुरानो `config.auto.routerStrategy`) लाई निम्नमध्ये एउटामा सेट गर्न सक्छन्: - `rules` — पूर्वनिर्धारित भारित स्कोरिङ - `score` — कन्फिगर गरिएको सबैभन्दा उच्च भारित स्कोर चयन गर्छ। ठ्याक्कै बराबर स्कोर हुँदा कन्फिगर गरिएको क्यान्डिडेट क्रम कायम रहन्छ; विद्यमान `explorationRate` ले पूर्ण श्रेणीकृत पूलबाट नमुना लिन्छ। - `cost` / `eco` — सबैभन्दा सस्तो स्वस्थ प्रदायक - `latency` / `fast` — विश्वसनीयता पेनाल्टीसहित सबैभन्दा कम p95 लेटेन्सी - `sla-aware` / `sla` — p95 लेटेन्सी, त्रुटि-दर र वैकल्पिक लागत SLO हरू पूरा गर्ने क्यान्डिडेटहरूलाई प्राथमिकता दिन्छ - `lkgp` — पछिल्लो ज्ञात राम्रो प्रदायकलाई पहिले - `nadir` — प्रम्प्टका लागि पूलको कुन मोडेल आवश्यक छ भनेर [Nadir](https://getnadir.com) को निर्णय API लाई सोध्छ; अप्ट-इन, विफल हुँदा `rules` मा खुला रूपमा फलब्याक हुन्छ ### राउटर रणनीतिहरू विस्तृत रूपमा auto-combo इन्जिनले 7 वटा प्लगेबल **RouterStrategy** कार्यान्वयनहरू उपलब्ध गराउँछ, जसलाई तपाईं `config.routerStrategy` (वा पुरानो `config.auto.routerStrategy`) मार्फत परिवर्तन गर्न सक्नुहुन्छ। प्रत्येक रणनीतिले `RoutingContext` (कार्य प्रकार, टुल/भिजन सङ्केतहरू, टोकन अनुमान, वैकल्पिक SLA नीति, वैकल्पिक पछिल्लो-ज्ञात-राम्रो प्रदायक) का आधारमा क्यान्डिडेट पूलबाट एउटा प्रदायक चयन गर्छ। #### 1. `rules` (पूर्वनिर्धारित) — 16-कारक भारित स्कोरिङ विद्यमान स्कोरिङ इन्जिनलाई र्याप गर्छ। `OPEN` सर्किट-ब्रेकर क्यान्डिडेटहरूलाई फिल्टर गर्छ, त्यसपछि हालको कार्य प्रकार र `getTaskFitness()` सहित `scorePool()` चलाएर सबैभन्दा उच्च स्कोर भएको प्रदायक चयन गर्छ। ```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 /* ... */ }; } } ``` **कहिले प्रयोग गर्ने**: पूर्वनिर्धारित। सबै सङ्केतहरूबीच सन्तुलित सम्झौता चाहिँदा प्रयोग गर्नुहोस्। **उपनाम**: `rules` (कुनै उपनाम छैन) --- #### 2. `cost` / `eco` — सबैभन्दा सस्तो स्वस्थ प्रदायक क्यान्डिडेट पूललाई `costPer1MTokens` अनुसार (बढ्दो क्रममा) क्रमबद्ध गर्छ र सबैभन्दा सस्तो चयन गर्छ। पहिले `OPEN` क्यान्डिडेटहरूलाई फिल्टर गर्छ। ```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 /* ... */ }; } } ``` **कहिले प्रयोग गर्ने**: लागत-संवेदनशील वर्कलोड, ब्याच प्रोसेसिङ वा ब्याकग्राउन्ड कार्यहरू। **उपनामहरू**: `cost`, `eco` --- #### 3. `latency` / `fast` — विश्वसनीयता पेनाल्टीसहित सबैभन्दा कम p95 लेटेन्सी `p95LatencyMs + (errorRate * 1000)` अनुसार क्रमबद्ध गर्छ। त्रुटि-दर पेनाल्टीले नाममात्रको लेटेन्सी कम भए पनि अविश्वसनीय प्रदायकहरूलाई तल्लो श्रेणीमा राख्ने सुनिश्चित गर्छ। ```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 /* ... */ }; } } ``` **कहिले प्रयोग गर्ने**: रियल-टाइम च्याट, अटोकम्प्लिट वा अन्तरक्रियात्मक कोडिङ सहायकजस्ता लेटेन्सी-संवेदनशील वर्कलोडहरू। **उपनामहरू**: `latency`, `fast` --- #### 4. `sla-aware` / `sla` — लेटेन्सी/त्रुटि/लागत SLO अनुपालन प्रत्येक क्यान्डिडेटले कन्फिगर गरिएको SLO नीति कति राम्रोसँग पूरा गर्छ भन्ने आधारमा स्कोर गर्छ: | कारक | भार | सूत्र | | --------------- | --- | ----------------------------------------------------- | | विलम्बता स्कोर | 35% | `threshold / max(value, ε)` | | त्रुटि स्कोर | 35% | `threshold / max(value, ε)` | | स्वास्थ्य स्कोर | 15% | `1.0` (CLOSED) / `0.5` (HALF_OPEN) / `0.0` (OPEN) | | लागत स्कोर | 10% | `threshold / max(value, ε)` वा व्युत्क्रम सामान्यीकृत | | स्थिरता स्कोर | 5% | विलम्बता stddev को व्युत्क्रम सामान्यीकृत मान | जब `hardConstraints: true` हुन्छ, उम्मेदवारहरूलाई मुख्य रूपमा **उल्लङ्घन स्कोर** (तिनीहरूले कुनै SLO लाई कति बढी पार गर्छन्) अनुसार, त्यसपछि समग्र स्कोरअनुसार क्रमबद्ध गरिन्छ। अन्यथा, समग्र स्कोर मात्र प्रयोग गरिन्छ। ```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) { // ... policy विरुद्ध प्रत्येक उम्मेदवारको स्कोर गणना गर्छ: { targetP95Ms, maxErrorRate, maxCostPer1MTokens, hardConstraints } } } ``` **SLA फिल्डहरू** (combo config मा सेट गरिने): ```json { "strategy": "auto", "config": { "routerStrategy": "sla-aware", "slaTargetP95Ms": 1500, "slaMaxErrorRate": 0.05, "slaMaxCostPer1MTokens": 5, "slaHardConstraints": true } } ``` **कहिले प्रयोग गर्ने**: कडा विलम्बता, त्रुटि-दर वा लागत बजेट भएका उत्पादन कार्यभारहरूमा। **उपनामहरू**: `sla-aware`, `sla` --- #### 5. `lkgp` — अन्तिम ज्ञात राम्रो प्रदायक पहिले पहिले **अन्तिम ज्ञात राम्रो प्रदायक** (सेट गरिएको भए) प्रयास गर्छ, त्यसपछि `rules` रणनीतिमा फर्किन्छ। यो सत्र स्थिरताका लागि उपयोगी छ — एउटै प्रदायकले कुराकानीका फलो-अप अनुरोधहरू सम्हाल्छ। ```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 /* ... */ }; } } // rules रणनीतिमा फर्किने return getStrategy("rules").select(pool, context); } } ``` **कहिले प्रयोग गर्ने**: एउटै प्रदायकले फलो-अप अनुरोधहरू सम्हालोस् भन्ने चाहना भएका बहु-चरणीय कुराकानीहरूमा (उदाहरणका लागि, क्यासिङ, सन्दर्भ निरन्तरता वा मूल्य निर्धारणको एकरूपताका लागि)। **उपनाम**: `lkgp` (कुनै उपनाम छैन) --- #### 6. `nadir` — Nadir मार्फत प्रम्प्ट-सचेत मोडेल छनोट माथिका प्रत्येक रणनीतिले उम्मेदवारहरूलाई आफ्नै टेलिमेट्रीका आधारमा श्रेणीबद्ध गर्छन्; तीमध्ये कुनैले पनि अनुरोध पढ्दैन। `nadir` ले अन्तिम प्रयोगकर्ता पालो र pool का model ids लाई [Nadir](https://getnadir.com) को निर्णय API (`POST /v1/bucket`) मा पठाउँछ र उक्त मेनुबाट Nadir ले छानेको मोडेलमा रुट गर्छ (`simple` → सक्षम मोडेलहरूमध्ये सबैभन्दा सस्तो, `complex` → अग्रणी मोडेल)। उक्त मोडेल सेवा गर्ने connection अझै पनि `rules` द्वारा छनोट गरिन्छ, त्यसैले quota, स्वास्थ्य र लागतले कुन account छनोट गर्ने भन्ने निर्णय गरिरहन्छन्। ```json { "strategy": "auto", "config": { "routerStrategy": "nadir", "nadir": { "apiKey": "ndr_...", "baseUrl": "https://api.getnadir.com", "timeoutMs": 2000 } } } ``` यी दुई string का लागि `OMNIROUTE_NADIR_API_KEY` र `OMNIROUTE_NADIR_BASE_URL` env fallback हुन्। `baseUrl` self-hosted Nadir का लागि मात्र आवश्यक हुन्छ (अन्त्यमा रहेको `/v1` स्वीकार गरिन्छ)। कुञ्जीविहीन call हरू Nadir को anonymous tier मा जान्छन्, जुन प्रत्येक IP अनुसार rate-limited हुन्छ। बाहिर पठाइने सामग्री: अन्तिम प्रयोगकर्ता सन्देशको पाठ (पहिलो 16k वर्ण), उम्मेदवार model ids र `source: "omniroute"` channel tag। कुनै system prompt, history, tools वा headers पठाइँदैन। असफलताको व्यवहार fail-open हुन्छ: timeout (पूर्वनिर्धारित 2000 ms), non-2xx, पहुँच गर्न नसकिने host, विकृत response वा pool बाहिरको selection भएमा `rules` निर्णय प्रयोग गरिन्छ र कारणको अगाडि `NadirStrategy: fallback (…)` थपिन्छ। असफल call पछि रणनीतिले 30 s सम्म network प्रयोग गर्दैन, त्यसैले outage हुँदा प्रत्येक अनुरोधमा एउटाको सट्टा प्रत्येक 30 s मा एउटा timeout मात्र लाग्छ। Nadir ले वास्तवमै छनोट गरेको अवस्थामा मात्र routing events ले `strategy: "nadir"` रिपोर्ट गर्छन्। **कहिले प्रयोग गर्ने**: विभिन्न model tier (सानो, मध्यम र अग्रणी मोडेल) समेटिएको pool मा मिश्रित-कठिनाइ भएको traffic का लागि, जहाँ सधैँ अग्रणी मोडेल प्रयोग गर्दा लाग्ने लागत घटाउन चाहनुहुन्छ। **उपनाम**: `nadir` (कुनै उपनाम छैन) --- ### अनुकूल router रणनीतिहरू तपाईंले public API मार्फत आफ्नै `RouterStrategy` implementation दर्ता गर्न सक्नुहुन्छ: ```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) { // तपाईंको routing logic यहाँ 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()); ``` त्यसपछि यसलाई प्रयोग गर्नुहोस्: ```json { "strategy": "auto", "config": { "routerStrategy": "my-custom" } } ``` --- ### Router रणनीति छनोट मार्गदर्शिका | प्रयोग अवस्था | रणनीति | कारण | | -------------------- | ----------- | -------------------------------------------- | | सन्तुलित कार्यभार | `rules` | पूर्वनिर्धारित — सबै कारकहरू विचार गर्छ | | लागत न्यून गर्ने | `cost` | सधैँ सबैभन्दा सस्तो छनोट गर्छ | | विलम्बता न्यून गर्ने | `latency` | सबैभन्दा छिटो भरपर्दो प्रदायक छनोट गर्छ | | कडा SLO हरू | `sla-aware` | p95/त्रुटि/लागत threshold अनुसार फिल्टर गर्छ | | बहु-चरणीय chat | `lkgp` | सत्र स्थिरता | | मिश्रित कठिनाइ | `nadir` | प्रत्येक prompt का लागि model tier छनोट गर्छ | SLA-सचेत फिल्डहरू: ```json { "strategy": "auto", "config": { "routerStrategy": "sla-aware", "slaTargetP95Ms": 1500, "slaMaxErrorRate": 0.05, "slaMaxCostPer1MTokens": 5, "slaHardConstraints": true } } ``` ## कार्य उपयुक्तता 6 प्रकारका कार्यहरू (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`) मा 30+ मोडेलहरूको मूल्याङ्कन गरिएको छ। वाइल्डकार्ड ढाँचाहरूलाई समर्थन गर्छ (उदाहरणका लागि, `*-coder` → उच्च कोडिङ स्कोर)। ## Auto भेरियन्टहरूको पुनरावलोकन मूल `auto` (पूर्वनिर्धारित) सहित `autoPrefix.ts` मा घोषणा गरिएका 6 वटा `AutoVariant` मानहरू जोड्दा, **आह्वान गर्न मिल्ने 7 वटा मोडेल ID** छन्: `auto`, `auto/coding`, `auto/fast`, `auto/cheap`, `auto/offline`, `auto/smart`, `auto/lkgp` (`AutoVariant` ले आफैंमा 6 वटा मानहरू सूचीबद्ध गर्छ; सातौँ विकल्प "भेरियन्ट छैन" — मूल `auto` — हो, जसलाई `parseAutoPrefix()` ले `variant: undefined` का रूपमा व्यवस्थापन गर्छ।) ## टियरहरू Auto-Combo मा कसरी समाहित हुन्छन् 16-फ्याक्टर स्कोरिङ फङ्सन (`open-sse/services/autoCombo/scoring.ts`) ले टियर सदस्यतालाई दुई सङ्केतका रूपमा लिन्छ: `tierPriority` (0.0476) र `tierAffinity` (0.0476)। पूर्ण `DEFAULT_WEIGHTS` सेटका लागि माथिको प्रामाणिक [स्कोरिङ फ्याक्टर तालिका](#how-it-works-persisted-auto-combos) हेर्नुहोस् — प्रति-प्याक ओभरराइडहरू (ship-fast/cost-saver/quality-first/ offline-friendly) "प्रति प्याक तौल प्रोफाइलहरू" तालिकामा सूचीबद्ध छन्। टियरले मात्र Tier 1 लाई पहिले आउन **बाध्य पार्दैन** — यदि Tier 1 को विलम्बता खराब छ वा लागत-विरुद्ध-गुणस्तर अनुकूलतम छैन भने, Tier 2 विजयी हुन्छ। टियर क्रम बाध्य पार्न, कम्बो रणनीति `priority` प्रयोग गर्नुहोस् र प्रदायकहरूलाई टियरअनुसार क्रमबद्ध गर्नुहोस्। Tier 1 (सदस्यता) लाई बलियो प्राथमिकता दिन, `tierPriority` को तौल बढाउनुहोस्: ```json { "strategy": "auto", "config": { "auto": { "weights": { "tierPriority": 0.3, "costInv": 0.05 } } } } ``` टियरका परिभाषाहरू र प्रदायक वर्गीकरणका लागि [`docs/guides/TIERS.md`](../guides/TIERS.md) हेर्नुहोस्। ## परीक्षण र कभरेज ### निर्धारणात्मक राउटिङ-निर्णय म्याट्रिक्स (`npm run test:combo:matrix`) `tests/integration/combo-matrix/*.test.ts` ले नक्कली अपस्ट्रिमसहितको वास्तविक कम्बो पाइपलाइनमार्फत सबै 19 सार्वजनिक रणनीतिहरूको राउटिङ **निर्णय**लाई सुरुदेखि अन्त्यसम्म प्रमाणित गर्छ। कभरेजमा निम्न समावेश छन्: - सबै 19 वटा `ROUTING_STRATEGY_VALUES` रणनीतिहरू (ordered, weighted, cost, context, fusion, …)। - `quota-share` (आन्तरिक) सुरुदेखि अन्त्यसम्म: वास्तविक `selectQuotaShareTarget` सीम (`registerQuotaFetcher` / `setLKGP` / `__setHeadroomSaturationFetcherForTests`) मार्फत DRR निष्पक्षता + संतृप्ति प्राथमिकीकरण न्यूनीकरण। - प्रत्येक लक्षित सङ्ख्यामा `context-relay` को विश्वव्यापी हस्तान्तरण कभरेज। यो सुइट CI (`test:integration` कार्य) मा `--test-concurrency=1` र `--test-force-exit` सहित चल्छ, त्यसैले यो निर्धारणात्मक हुन्छ र यसलाई प्रत्यक्ष प्रमाण-पत्रहरू आवश्यक पर्दैनन्। ### गेट गरिएको प्रत्यक्ष स्मोक परीक्षण (CI मा छैन — वास्तविक प्रदायकहरू) | आदेश | यसले के गर्छ | | :------------------------------------- | :-------------------------------------------------------------------------------------------- | | `npm run test:combo:live` | `RUN_COMBO_LIVE=1` सहित इन-प्रोसेस वास्तविक राउटिङ; प्रत्यक्ष OmniRoute DB को स्न्यापसट लिन्छ | | `npm run test:combo:live:vps` | प्रत्यक्ष OmniRoute सर्भरविरुद्ध HTTP कलहरू (`COMBO_LIVE_BASE_URL` सेट गर्नुहोस्) | | `npm run test:combo:live:vps:failover` | उही, जानाजानी सिर्जना गरिएका फेलओभर परिदृश्यहरूसहित | यी स्मोक परीक्षणहरूले वास्तविक वायर पथ (कम्बो → प्रदायक → पूर्णता) प्रयोग गर्छन्। प्रत्यक्ष प्रमाण-पत्रहरू र VPS पहुँच आवश्यक पर्ने भएकाले तिनीहरूलाई जानाजानी CI बाट बाहिर राखिएको छ। --- ## फाइलहरू | फाइल | उद्देश्य | | :-------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------- | | `open-sse/services/autoCombo/scoring.ts` | १६-कारक स्कोरिङ प्रकार्य, `DEFAULT_WEIGHTS`, पूल नर्म | | `open-sse/services/autoCombo/taskFitness.ts` | मोडेल × कार्य उपयुक्तता लुकअप | | `open-sse/services/autoCombo/engine.ts` | चयन तर्क, ब्यान्डिट, बजेट सीमा | | `open-sse/services/autoCombo/selfHealing.ts` | बहिष्करण, प्रोबहरू, घटना मोड | | `open-sse/services/autoCombo/modePacks.ts` | ६ वजन प्रोफाइलहरू (द्रुत-वितरण, लागत-बचतकर्ता, गुणस्तर-पहिलो, अफलाइन-अनुकूल, विश्वसनीयता-पहिलो, केअस-मोड) | | `open-sse/services/autoCombo/autoPrefix.ts` | `auto/` प्रिफिक्स पार्सर + ६ भेरियन्टहरू | | `open-sse/services/autoCombo/virtualFactory.ts` | लाइभ जडानहरूबाट इन-मेमोरी `AutoComboConfig` निर्माण गर्छ | | `open-sse/services/autoCombo/providerRegistryAccessor.ts` | प्रदायक रजिस्ट्री मक गर्नका लागि परीक्षण हुक | | `src/shared/constants/routingStrategies.ts` | `ROUTING_STRATEGY_VALUES` (२० रणनीतिहरू) | | `src/sse/handlers/chat.ts` | एकीकरण: अटो-प्रिफिक्स सर्ट-सर्किट |