Çalışma Zamanı
Model & Provider
Model profili, bir LLM sağlayıcısına nasıl bağlanılacağını tanımlar. Luma provider-neutral bir adapter katmanı kullanır: aynı .luma programı OpenAI-compatible bir gateway'de, Anthropic'te, Gemini'de veya Azure'da değişmeden çalışır — tool çağrısı biçimleri ve structured output kuralları adapter tarafından çevrilir.
Model profili
model Primary {
provider: "openai-compatible"
base_url: "https://gateway.example/v1"
model: "text-model-l"
api_key: getEnv("api_key")
timeout: 30000
max_tokens: 4000
capabilities: ["json_schema", "tool_calling"]
cache: true
cache_ttl: 60000
cache_max_entries: 256
stream: false
reasoning: false
multimodal: false
cost_per_1k_tokens: 0.002
}
agent Analist {
model: Primary
}| Anahtar | Zorunlu | Varsayılan | Açıklama |
|---|---|---|---|
provider | evet | — | Adapter seçimi. Geçerli değerler aşağıda. |
base_url | evet | — | Gateway kökü. Endpoint yolu adapter tarafından eklenir. |
model | evet | — | Provider'daki model kimliği. |
api_key | evet | — | Yalnızca getEnv("ENV_ADI") biçimi kabul edilir. |
timeout | hayır | sınırsız | İstek timeout'u (ms). |
max_tokens | hayır | — | Çıktı token limiti. Anthropic'te değer yoksa 4096 kullanılır. |
capabilities | hayır | [] | Capability probe'un doğrulayacağı yetenekler. |
cache | hayır | false | Model yanıt cache'i. |
cache_ttl | hayır | 300000 | Cache girişi ömrü (ms). |
cache_max_entries | hayır | 256 | LRU kapasitesi. |
stream / streaming | hayır | false | SSE akışı — yanıt yine de tam olarak toplanır. |
reasoning | hayır | false | İsteğe reasoning_effort: "medium" ekler. |
multimodal | hayır | false | Prompt içindeki görsel/dosya marker'larının işlenmesini açar. |
cost_per_1k_tokens | hayır | agent'ın oranı | Bu modelin 1000 token başına birim fiyatı. Bu modelin yürüttüğü her istekte agent'ın cost_per_1k_tokens değerini ezer; agent'ın token_budget / cost_budget ayarları aynı defteri okumaya devam eder. Negatif değer parse hatası verir: Model 'Primary' cost_per_1k_tokens cannot be negative. |
Model başına fiyat, tek bir agent birden çok model çalıştırdığında önem kazanır: fiyat verilmezse ucuz model de pahalı model de aynı orandan faturalanır ve escalate policy'sinin max_cost_per_call tavanı maliyeti değil token'ı ölçmüş olur. Agent geneli oran ve bütçeler için → Bütçeler ve limitler.
Yukarıdaki tablodaki her anahtar kendi regex'iyle okunur ve geriye kalanı denetleyen hiçbir şey yoktur. Parser'ın tanımadığı bir satır bildirilmez ve uygulanmaz — ayar yalnızca varsayılanında kalır. Aşağıdaki blok parse olur, çalışır, hiçbir uyarı basmaz ve şu üç satırın üçünü de atar:
model Primary {
provider: "openai-compatible"
base_url: "https://gateway.example/v1"
model: "text-model-l"
api_key: getEnv("api_key")
max_token: 100 // düşürüldü — gerçek anahtardan bir harf eksik
cache_ttll: 5000 // düşürüldü
multimodel: true // düşürüldü — bayrak false kalır
}Bunu söylemeye değer, çünkü dilin geri kalanının öğrettiği alışkanlık bu değil. agent, datasource, query ve command blokları her key: satırını bilinen kümesine karşı denetler ve tanımadığını program başlamadan adıyla reddeder: Agent 'A' has no key 'retryy'; known keys: role, model, temperature, … model bloğunda böyle bir denetim yok; run_policy'de de yok — orada da bilinmeyen anahtar düşürülür, buna karşılık bilinen bir anahtarın yanlış strategy ile kullanımı yine reddedilir (RunPolicy 'R' tie can only be used with the vote strategy.).
En çok canını yakan yer boolean bayraklardır; çünkü düşürülmüş bir bayrak, hiç yazılmamış bir bayraktan ayırt edilemez. multimodel: true, multimodal'ı false'ta bırakır; prompt içindeki görsel ve dosya marker'ları da o zaman yazıldığı gibi — base64 yüküyle birlikte — düz metin olarak gider: token harcanır, görsel görülmez, hiçbir yerde tanı çıkmaz. Yukarıdaki tabloyu allowlist say ve bir ayarı hiç yazmamışsın gibi davranan bir modeli önce bir yazım sorusu olarak oku.
Agent'ta model ayarı yoksa ya da tırnak içinde ham bir model kimliği (model: "org/text-model-s") verilmişse, bağlantı .env'deki base_url / api_key / model üzerinden kurulur ve provider openai-compatible kabul edilir. Yeni projelerde adlandırılmış profil kullanmak tercih edilir — capability probe, cache ve run policy yalnızca profillerle çalışır.
Provider adapter'ları
provider değeri | Adapter | Endpoint | Auth başlığı |
|---|---|---|---|
openai-compatible · openai · gateway · deepseek | OpenAI Chat Completions | {base_url}/chat/completions | Authorization: Bearer … |
anthropic | Anthropic Messages | {base_url}/messages | x-api-key + anthropic-version: 2023-06-01 |
gemini · google | Gemini generateContent | {base_url}/v1beta/models/{model}:generateContent | x-goog-api-key |
azure · azure-openai | Azure OpenAI | {base_url}/chat/completions | api-key |
base_url zaten endpoint yolunu içeriyorsa (örn. …/chat/completions) tekrar eklenmez; query string korunur. Bilinmeyen bir provider adı, hiçbir istek yapılmadan parse zamanında reddedilir: Error: Model 'M' has unknown provider '…'. Valid values: …
Tool çağrısı eşlemesi
| Adapter | Tool bildirimi | Model → çağrı | Runtime → sonuç |
|---|---|---|---|
| OpenAI / Azure | tools[].function | tool_calls[] | role: "tool" mesajı |
| Anthropic | tools[].input_schema | tool_use bloğu | tool_result içeren user mesajı |
| Gemini | functionDeclarations | functionCall | functionResponse |
Structured output desteği
| Adapter | Schema provider'a nasıl iletilir |
|---|---|
| OpenAI / Azure | response_format: { type: "json_schema", json_schema: { strict: true, schema } } |
| Gemini | generationConfig.responseMimeType: "application/json" + responseSchema |
| Anthropic | Schema tek bir tool olarak bildirilir (tools[0].input_schema) ve tool_choice: { type: "tool", name } ile zorunlu kılınır; dönen tool_use.input yapılandırılmış çıktıdır. Yalnızca agent kendi tool'larını bildirmediğinde geçerlidir — bildirdiğinde native tool döngüsü devreye girer ve schema system mesajıyla taşınır. |
Strict json_schema modu oneOf'u doğrudan reddediyor ve kökün type: "object" olmasını istiyor. Bu yüzden tagged union anyOf olarak emit ediliyor — üyeler zaten const tag'leriyle ayrık olduğu için hiçbir şey kaybolmuyor — ve yalnızca OpenAPI'ye ait discriminator anahtar kelimesi hiç gönderilmiyor, çünkü onu okuyan provider yok ve strict mod reddediyor.
ask union'ın kendisini hedeflediğinde istek, union'ın adını taşıyan tek alanlı bir zarfa sarılıyor ve yanıt doğrulamadan önce açılıyor. Programın zarfı hiç görmüyor; zarf, provider'ın "kök nesne olmalı" kuralının senin şemalarının dışında kalması için var.
Bu, provider'a göre dallanmak yerine her adapter için aynı şekilde emit ediliyor; böylece interpreter ile transpiled artifact byte-byte aynı kalıyor. Sahadan #96 olarak bildirildi — v0.5.0'a kadar eski oneOf emit'i, her tagged-union ask'inin strict provider tarafından 400 ile reddedilmesi demekti.
Agent kendi tools'unu bildirdiğinde schema'yı tool olarak gönderme yöntemi kullanılamaz; biçim, system mesajı ve Luma'nın yerel doğrulamasına geri düşer. retry: 2 gibi bir değer, doğrulama hatasını modele geri besleyerek bu farkı büyük ölçüde kapatır.
İsteğin şekillenmesi
Her ask için gönderilen gövde şu kurallarla oluşturulur:
| Alan | Kaynak / kural |
|---|---|
model | Profil model değeri. |
messages | system (schema + context talimatı + role) → memory geçmişi → user (prompt). |
temperature | Agent temperature; verilmezse 0. |
max_tokens | Agent max_tokens, yoksa profil değeri; ikisi de yoksa gönderilmez. |
stream | Profil stream değeri. |
reasoning_effort | Profilde reasoning: true ise "medium". |
tools + tool_choice | Agent'ın tools listesi doluysa gönderilir. ask üzerinde using tool yoksa tool_choice "auto"'dur; varsa o tek tool'a sabitlenir. |
response_format | Tool yoksa her istekte; tool varsa yalnızca en az bir tool çağrısı gerçekleştikten sonra. |
Korelasyon başlıkları her istekte gönderilir: x-luma-run-id → logical_run_id (mantıksal çalıştırma) x-luma-attempt-id → attempt_id (retry / policy adayı) x-luma-request-id → local_request_id (tekil HTTP isteği) Yanıttan okunan provider kimliği: x-request-id · request-id · anthropic-request-id → provider_request_id
Bu değerler telemetry event'lerine de yazılır; gateway loglarıyla trace'i eşleştirmeni sağlar. → Correlation
Yanıt işleme
ham yanıt (JSON veya SSE)
↓ adapter normalizasyonu → { content, refusal, toolCalls, usage }
↓ refusal varsa → MODEL_REFUSAL (retryable: false)
↓ toolCalls varsa → tool'ları çalıştır, sonucu ekle, döngüye dön
↓ content boş → MODEL_EMPTY_CONTENT (retryable)
↓ ```json çitleri temizlenir
↓ JSON.parse başarısız → MODEL_INVALID_RESPONSE (retryable)
↓ yerel schema doğrulaması başarısız → MODEL_INVALID_RESPONSE (retryable)
↓ sonuçModel yanıtı ```json … ``` bloğu içine sararsa çitler otomatik temizlenir. Ham yanıtı görmek için LUMA_DEBUG_MODEL_RESPONSE=1 kullan.
Capability probe
Program başlamadan önce Luma, kullanılacak her model için gateway'in /models endpoint'ine bir istek atar ve modelin gerekli yetenekleri desteklediğini doğrular.
| Yetenek | Ne zaman aranır |
|---|---|
json_schema | LLM method'u olan her agent ve her üst düzey ask için. |
tool_calling | Agent'ın tools listesi doluysa. |
streaming · reasoning · multimodal | Profilde ilgili bayrak açıksa. |
Profildeki capabilities | Listelenen her değer ayrıca doğrulanır. |
| Durum | warn varsayılan | strict |
|---|---|---|
| Gateway'e ulaşılamıyor | Uyarı yazar, devam eder | Program durur |
Model /models yanıtında yok | Uyarı yazar, devam eder | Program durur |
| Yetenek bilgisi eksik | Uyarı yazar, devam eder | Program durur |
Yetenek açıkça false | durur | durur |
{
"model_runtime": {
"capability_policy": "strict",
"capability_probe_timeout_ms": 5000
}
}export LUMA_CAPABILITY_POLICY=strict export LUMA_CAPABILITY_PROBE_TIMEOUT_MS=3000
Environment değişkenleri config'i ezer. Probe timeout'u varsayılan 5000 ms'dir ve Ctrl-C ile iptal edilebilir.
Warning: 'text-model-l' has no json_schema capability information.
Çoğu gateway /models yanıtında capabilities nesnesi döndürmez; bu uyarı normaldir ve programı engellemez. Sıkı kontrol istiyorsan strict moda geç — ama gateway'in bu bilgiyi gerçekten verdiğinden emin ol.
Streaming, reasoning, multimodal
model VisionReasoner {
provider: "openai-compatible"
base_url: "https://gateway.example/v1"
model: "vision-model"
api_key: getEnv("api_key")
stream: true
reasoning: true
multimodal: true
}| Bayrak | Etkisi |
|---|---|
stream: true | İstek SSE olarak yapılır; parçalar (içerik, tool call argümanları, usage) toplanır ve yanıt tam olarak döner. Luma parça parça çıktı yayınlamaz — akış yalnızca taşıma katmanındadır. |
reasoning: true | İsteğe reasoning_effort: "medium" eklenir. Reasoning token'ları telemetry'de reasoningTokens olarak raporlanır. |
multimodal: true | Prompt içindeki {{image_url:…}} ve {{file_url:…}} marker'ları content part'larına çevrilir. Bayrak kapalıysa marker'lar düz metin olarak gider. |
Multimodal ayrıntıları ve dosya akışı için → IO & Multimodal.
Model response cache
model Cached {
provider: "openai-compatible"
base_url: "https://gateway.example/v1"
model: "text-model-l"
api_key: getEnv("api_key")
cache: true
cache_ttl: 60000
cache_max_entries: 256
}| Özellik | Davranış |
|---|---|
| Kapsam | Yalnızca cache: true olan profillerde ve istekte tool bildirimi yoksa. |
| Anahtar | provider + base_url + model + isteğin kanonik JSON'u. API key anahtara girmez. |
| Saklanan | Yalnızca schema-valid nihai sonuç. |
| Tahliye | TTL dolduğunda ve cache_max_entries aşıldığında (LRU). |
| Single-flight | Aynı anahtar için eşzamanlı istekler tek çağrıyı paylaşır. |
Run policy: çok modelli stratejiler
run_policy, bir ask çağrısının birden fazla model üzerinde nasıl yürütüleceğini belirler. Agent'a bağlanır ve o agent'ın tüm LLM çağrılarını kapsar.
run_policy Resilient {
strategy: "fallback"
models: [Primary, Backup]
on: ["timeout", "rate_limit", "provider_error", "empty_content"]
max_attempts: 2
}
agent Analist {
model: Primary
run_policy: Resilient
}Stratejiler
| Strategy | Davranış | Model sayısı |
|---|---|---|
single | Tek model. Policy vermemekle aynı; retry normal çalışır. | 0–1 |
fallback | Sırayla dener; yalnızca on listesindeki hata türlerinde sonrakine geçer. | ≥ 1 |
escalate | Ucuz modelden güçlüye uzanan bir merdiven: yalnızca on listesindeki hata türlerinde bir üst basamağa çıkar, bir model yanıt verdiği anda durur. max_cost_per_call tek bir çağrının harcayabileceğini sınırlar. | ≥ 2 |
parallel | Hepsini eşzamanlı çalıştırır. select: "first" ilk başarılıyı, "all" tüm başarılıları döndürür. | ≥ 1 |
race | Hepsini başlatır, ilk başarılı sonucu alır ve diğerlerini iptal eder. | ≥ 1 |
vote | Sonuçları kanonik JSON üzerinden oylar; quorum arar. | ≥ 2 |
fusion | Başarılı adayları bir synthesizer modele verip tek nihai sonuç ürettirir. | ≥ 1 + synthesizer |
combo | Modelleri sıralı pipeline olarak çalıştırır; her aşama öncekinin çıktısını iyileştirir. | ≥ 2 |
Yapılandırma anahtarları
| Anahtar | Hangi strategy'lerde | Varsayılan |
|---|---|---|
models | single hariç hepsinde zorunlu | — |
on | hepsi (pratikte fallback ve escalate) | ["retryable"] |
max_attempts | yalnızca fallback | model sayısı |
max_models | parallel · race · vote · fusion | model sayısı |
max_stages | yalnızca combo | model sayısı |
max_cost_per_call | yalnızca escalate | sınırsız |
quorum | yalnızca vote | floor(n/2) + 1 |
tie | yalnızca vote | fail |
select | yalnızca parallel | first |
synthesizer | yalnızca fusion (zorunlu) | — |
synthesizer_policy | yalnızca fusion | deny_tools |
max_fusion_inputs · fusion_input_tokens | yalnızca fusion | sınırsız |
Bir anahtarı yanlış strategy ile kullanmak parse hatası verir — örneğin tie yalnızca vote için geçerlidir.
on: hangi hatalarda devreye girer
Geçerli trigger değerleri:
retryable timeout rate_limit provider_error empty_content invalid_response refusal invalid_tool_call cancelled unsupported budget_exceeded ayrıca ham error code'ları da yazılabilir: MODEL_TIMEOUT · MODEL_RATE_LIMIT · MODEL_PROVIDER_ERROR · …
"retryable" özel bir değerdir: hatanın retryable bayrağına bakar, koduna değil. Tanınmayan bir trigger parse hatası verir.
Strateji detayları
fallback
run_policy Resilient {
strategy: "fallback"
models: [Primary, Backup, Reserve]
on: ["timeout", "rate_limit", "provider_error"]
max_attempts: 2
}Modeller sırayla denenir. Hata on listesine uymuyorsa hemen fırlatılır — yani bir doğrulama hatası yüzünden gereksiz yere ikinci modele geçilmez. max_attempts kaç modelin deneneceğini sınırlar.
escalate
run_policy Adaptive {
strategy: "escalate"
models: [Cheap, Strong]
on: ["invalid_response", "empty_content"]
max_cost_per_call: 0.02
}
agent Extractor {
model: Cheap
run_policy: Adaptive
retry: 1
cost_budget: 0.5
}Modeller ucuzdan güçlüye uzanan bir merdivendir ve aynı anda tek basamak çalışır. Bir modele ancak kendinden önceki model on listesindeki bir tetikleyiciyle başarısız olduğunda geçilir; listede olmayan bir hata çağırana olduğu gibi iletilir. Ucuz model yanıt verdiğinde güçlü model hiç çağrılmaz — escalate'i combo'dan ayıran nokta budur; combo önceki aşama başarılı olsa bile her aşamayı çalıştırır. En az iki model zorunludur: Escalate run policy 'Adaptive' must specify at least two models, from the cheapest to the strongest.
retryiç döngü, escalation dış döngüdür. Bir aşama retry hakkını çalışmakta olan modelin üzerinde harcar — ucuz model önce kendini düzeltir — güçlü modelin parası ancak ondan sonra ödenir. Yukarıdaki policy,Strong'a hiç ulaşmadan önceCheap'e iki istek atar. Diğer tüm çok modelli stratejiler adaylarınıretry: 0ile çalıştırmayı sürdürür.max_cost_per_call, tek bir policy çağrısının tavanıdır. Her aşamadan sonra, merdivenin tamamının paylaştığı tek bir defter üzerinden kontrol edilir ve tavan dahildir: bir çağrı tam tavan kadar harcayabilir, ama o noktada tırmanacak parası kalmamıştır.- Tavana ulaşmak tırmanışı durdurur ve satın alınmayan model adıyla bildirilir:
MODEL_BUDGET_EXCEEDED·RunPolicy 'Adaptive' spent 0.03 of its max_cost_per_call of 0.02, so it did not escalate to model 'Strong'. - Tavanın aşılması hâlinde sonuç geçerli olsa da döndürülmez; aşım yutulmaz, raporlanır:
MODEL_BUDGET_EXCEEDED·RunPolicy 'Adaptive' spent 0.03 on this call, above its max_cost_per_call of 0.02. - Her aşama, onu yürüten model profilinin
cost_per_1k_tokensdeğeriyle fiyatlanır; profilde fiyat yoksa agent'ın oranına düşülür.escalatealtında bu defter her basamakta sıfırlanmak yerine merdivenin tamamını kapsar, dolayısıyla agent'ıncost_budget/token_budgetayarları da tırmanışı bitirebilir:Agent cost budget exceeded (0.5).Hiçbir yerde fiyat verilmemişse maliyet0hesaplanır ve hiçbir tavan tetiklenmez.
Escalation tetikleyicileri, diğer tüm stratejilerin zaten kullandığı on listesinin ta kendisidir — tek kavram, tek anahtar. escalate_on yazan bir policy sessizce yok sayılmaz, parse zamanında adıyla reddedilir: RunPolicy 'Adaptive' has no escalate_on key; the escalate strategy reads its escalation triggers from the on list. Aynı şekilde max_cost_per_call yalnızca escalate'e aittir (RunPolicy 'Adaptive' max_cost_per_call can only be used with the escalate strategy.) ve 0 tavan reddedilir (RunPolicy 'Adaptive' strategy limit must be positive.).
parallel
run_policy Fanout {
strategy: "parallel"
models: [Primary, Backup]
select: "all"
}
agent Analist {
run_policy: Fanout
fn uret() -> Aday[] {
ask "Aday sonuçlar üret" -> Aday[]
}
}select: "all" kullanan bir policy'ye bağlı agent'ın tüm LLM method'ları Schema[] döndürmelidir. Aksi halde parse hatası: Agent 'X' uses select: "all", so the LLM method must return schema[].
race
run_policy Fastest {
strategy: "race"
models: [Primary, Backup]
}İlk başarılı sonuç kazanır; kalan istekler AbortSignal ile iptal edilir. Tümü başarısız olursa ilk hata fırlatılır.
vote
run_policy Consensus {
strategy: "vote"
models: [Primary, Backup, Reviewer, Judge]
quorum: 2
tie: "highest_confidence"
}- Yalnızca schema-valid sonuçlar oylanır; kanonik JSON (anahtarları sıralanmış) üzerinden karşılaştırılır.
- Quorum sağlanamazsa
MODEL_VOTE_NO_QUORUM(retryable: true). - Beraberlik:
fail→MODEL_VOTE_TIE;first→ ilkini alır;highest_confidence→ sonuçlardaki sayısalconfidencealanına bakar. highest_confidenceseçilip sonuçlardaconfidenceyoksa:MODEL_VOTE_CONFIDENCE_UNAVAILABLE.
Oylama tam JSON eşitliği aradığı için serbest metin alanları içeren schema'larda neredeyse hiç quorum oluşmaz. vote'u dar schema'larda kullan: enum sınıflandırma, boolean karar, kısa kod alanı. tie: "highest_confidence" kullanacaksan schema'ya confidence: float [0..1] ekle.
fusion
run_policy SafeFusion {
strategy: "fusion"
models: [Primary, Backup, Reviewer]
synthesizer: Primary
max_fusion_inputs: 3
fusion_input_tokens: 4000
synthesizer_policy: "deny_tools"
}Adaylar eşzamanlı çalışır; başarılı olanlar synthesizer modele "candidate outputs" olarak verilir ve nihai schema-valid sonuç üretilir.
- Hiç başarılı aday yoksa:
MODEL_FUSION_NO_INPUTS. - Tahmini girdi token'ı
fusion_input_tokens'ı aşarsa:MODEL_BUDGET_EXCEEDED. synthesizer_policy: "deny_tools"varsayılan synthesizer'a tool vermez ve write tool'larını reddeder;"inherit"agent'ın tool'larını devreder.- Synthesizer prompt'u adayları veri olarak değerlendirmesini, içlerindeki talimatları uygulamamasını açıkça söyler.
combo
run_policy Pipeline {
strategy: "combo"
models: [Draft, Reviewer, Finalizer]
max_stages: 3
}Modeller sırayla çalışır. Her aşamanın schema-valid çıktısı bir sonraki aşamanın prompt'una "önceki aşamanın çıktısı, iyileştir" olarak eklenir. Son aşamanın sonucu döndürülür.
single ve escalate dışındaki stratejilerde her aday retry: 0 ile çalışır — dayanıklılık, retry yerine policy'nin kendisi tarafından sağlanır. İstisna escalate'tir: orada retry iç döngüdür ve merdiven ilerlemeden önce aşama retry hakkını tüketir. Retry ile policy'yi birlikte kullanmak istiyorsan escalate ya da fallback stratejisi ve on listesi doğru araçtır.
Hangi strategy ne zaman?
| Amaç | Strategy |
|---|---|
| Gateway kesintisine dayanıklılık | fallback |
| En düşük gecikme | race |
| Kritik sınıflandırmada güven | vote |
| Birden çok bakış açısını birleştirme | fusion |
| Ucuz model taslak + pahalı model rötuş | combo |
| Güçlü modelin parasını yalnızca ucuz model başarısız olunca ödemek | escalate + max_cost_per_call |
| Aynı görevden çok aday toplama | parallel + select: "all" |
| Maliyet kontrolü | single + retry + token_budget |