feat(router,inference,config): pin narration to a configured model_id
[router.narration] model_id selects which provider handles narration turns instead of generic capability routing — lets a small/fast model own narration while the main model keeps CHAT/STEERING. - NarrationSettings.modelId parsed from TOML, threaded via RouterConfig .narrationModelId into DefaultRouterFacade.narrate (3-arg route) - DefaultInferenceRouter: exact-id match against healthy providers, with a post-select health check; any miss logs WARN and falls back to capability routing (never fails the narration turn) - onUserInput unchanged — only narrate uses the pinned model (tested)
This commit is contained in:
@@ -8,5 +8,6 @@ dependencies {
|
||||
implementation(project(":core:events"))
|
||||
implementation(project(":core:context"))
|
||||
implementation(project(":core:artifacts"))
|
||||
implementation "org.slf4j:slf4j-api:2.0.16"
|
||||
}
|
||||
tasks.named("koverVerify").configure { enabled = false }
|
||||
|
||||
@@ -9,6 +9,8 @@ import kotlin.time.Duration.Companion.seconds
|
||||
import kotlin.time.TimeMark
|
||||
import kotlin.time.TimeSource
|
||||
|
||||
private val log = org.slf4j.LoggerFactory.getLogger(DefaultInferenceRouter::class.java)
|
||||
|
||||
private data class HealthEntry(
|
||||
val health: ProviderHealth,
|
||||
val mark: TimeMark,
|
||||
@@ -57,4 +59,36 @@ class DefaultInferenceRouter(
|
||||
}
|
||||
return selected
|
||||
}
|
||||
|
||||
override suspend fun route(
|
||||
stageId: StageId,
|
||||
requiredCapabilities: Set<ModelCapability>,
|
||||
modelId: String?,
|
||||
): InferenceProvider {
|
||||
if (modelId == null) return route(stageId, requiredCapabilities)
|
||||
|
||||
val all = registry.listAll()
|
||||
val healthy = all.filter { cachedHealth(it) !is ProviderHealth.Unavailable }
|
||||
val matched = healthy.firstOrNull { it.id.value == modelId }
|
||||
if (matched == null) {
|
||||
log.warn(
|
||||
"narration model_id '{}' matched no healthy provider — falling back to capability routing",
|
||||
modelId,
|
||||
)
|
||||
return route(stageId, requiredCapabilities)
|
||||
}
|
||||
when (val postHealth = matched.healthCheck()) {
|
||||
is ProviderHealth.Unavailable -> {
|
||||
log.warn(
|
||||
"narration model_id '{}' provider failed post-select health check ({})" +
|
||||
" — falling back to capability routing",
|
||||
modelId,
|
||||
postHealth.reason,
|
||||
)
|
||||
return route(stageId, requiredCapabilities)
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
return matched
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user