Skip to content

[Bug][Model Routing][Auxiliary] 「Auxiliary / Memory」のモデル選択がRuntime adaptersへ反映されず、実行は常にLocal経路になる #502

Description

@VIUK-XV

概要

Advanced Model Settingsには Auxiliary / Memory scopeがあり、Registry上のモデルを用途別に選択できます。

AIModelTuningScope でも:

enum AIModelTuningScope {
    case persona
    case story
    case auxiliary
}

が定義され、classifier / memory / scene / safety系Roleはすべて .auxiliary へ集約されます。

しかしproductionの補助AI adaptersは、その選択を実行時に参照していません。

現行production経路

Classifier / Memory / Scene補助は LocalAuxiliaryAI.generate(...) を使います。

例:

RuntimeMemorySelector
  -> LocalAuxiliaryAI.generate(... role: .memoryRetrieval)

RuntimeMemorySummarizer
  -> LocalAuxiliaryAI.generate(... role: .memoryExtraction)

RuntimeSceneCharacterSelector
  -> LocalAuxiliaryAI.generate(... role: .sceneCharacterSelection)

RuntimeSceneSummarizer
  -> LocalAuxiliaryAI.generate(... role: .sceneSummary)

RuntimeNextSceneSuggester
  -> LocalAuxiliaryAI.generate(... role: .nextSceneSuggestion)

RuntimeSmallModelClassifier も同じ LocalAuxiliaryAI.generate(... role: .classifier) です。

LocalAuxiliaryAIのrouting

現行 LocalAuxiliaryAI.generate は:

let preferred: AIModelConfiguration? = {
    guard let auxiliaryID = modelManager.auxiliaryModelID,
          let model = modelManager.installedModels.first(where: { $0.id == auxiliaryID }) else {
        return AIModelRegistry.shared
            .configurations(for: role)
            .first(where: { $0.identity.providerID == .localRuntime })
    }
    return AIModelRegistry.shared.localArtifactConfiguration(
        artifactID: model.id,
        displayName: model.displayName,
        roles: [role]
    )
}()
...
AIModelRouter.shared.generate(
    request: request,
    role: role,
    preferredConfigurationID: preferred?.id,
    allowsFallback: false
)

となっています。

つまり選択順は:

  1. Settingsの専用 auxiliaryModelID があればそのlocal artifact
  2. なければ、そのRoleで最初の localRuntime configuration

だけです。

AIModelTuningStore.configurationIDForCurrentMode(...) / preferredConfigurationID(.auxiliary) / simpleModelRoute は一切参照していません。

再現

  1. RegistryへAnthropicまたはOpenAI-compatible configurationを追加
  2. classifier 等のAuxiliary Roleを付与
  3. Settings → Advanced → Auxiliary / Memoryでそのconfigurationを選択
  4. Persona/Storyを使い、memory extraction / retrieval / scene summary等を発生させる

期待

Advancedで選択したconfigurationがAuxiliary処理に使われる。

実際

production adaptersはLocalAuxiliaryAIへ入り、local artifactしか選択しません。

local runtimeが利用できなければ、online configurationが選択済みでも補助処理はnil/fallbackになります。

Simple routeも同様

Simple設定の:

  • 端末内を優先
  • オンラインを優先

もAuxiliary adaptersでは読まれません。

そのため オンラインを優先 にしても、Memory/Classifier/Scene helperはlocal経路を使い続けます。

UI上の問題

Advanced UIは AIAdvancedScopeSettingsView(scope: .auxiliary) を表示し、ユーザーは「Auxiliary / Memoryのモデルを選んだ」と認識します。

しかし実行側にはそのsource-of-truthが接続されていないため、現在のUIは一部設定がno-opです。

さらにscope設計上の注意

.auxiliary.routingRole は現在 .classifier 固定です。

case .auxiliary: return .classifier

そのためAdvanced画面の候補集合自体もclassifier Roleのconfigurationに依存します。

一方実処理では:

  • memoryExtraction
  • memoryRetrieval
  • sceneCharacterSelection
  • sceneSummary
  • nextSceneSuggestion
  • safety

など別Roleを使用します。

1つのAuxiliary preference UUIDを全Roleへ共有する設計なら、選んだconfigurationが各Roleを持つか、Role別fallbackをどうするかを明示する必要があります。

影響

  • AdvancedのAuxiliary model selectionが実行へ反映されない
  • Simple online preferenceも無視される
  • local model未導入時、online helper configurationがあっても利用できない
  • 設定画面と実際のProvider/cost/privacyが一致しない
  • Registryに複数の補助Role configurationを用意してもUI選択がroutingへ届かない
  • #278でproduction helperをMockからRuntimeへ移行しても、routing semanticsがSettingsと分離したまま

修正案

LocalAuxiliaryAI ではなくprovider-neutralなAuxiliary routing entry pointを作る。

例:

let configurations = AIModelRegistry.shared.configurations(for: role)
let preferred = AIModelTuningStore.shared.configurationIDForCurrentMode(
    for: role,
    configurations: configurations,
    fallbackProviderID: .localRuntime
)

AIModelRouter.shared.generate(
    request: request,
    role: role,
    preferredConfigurationID: preferred,
    allowsFallback: ...
)

専用 auxiliaryModelID はlocal artifactをpinするUIとして、このresolverへ明示的なconversation/device overrideとして渡す。

また .auxiliary を全Role共通設定にするなら:

  • selected configurationが対象Roleを持たない場合の挙動
  • Role追加/解除時のpreferred UUID整合性
  • provider fallback policy

を統一する。

テスト

  • Advanced Auxiliary = Anthropic → memoryExtractionがAnthropicへ行く
  • Advanced Auxiliary = OpenAI-compatible → sceneSummaryが選択構成へ行く
  • Simple online → online helperを優先
  • Simple onDevice → local helperを優先
  • dedicated auxiliary local artifact →そのartifactを使用
  • selected configが対象Roleを持たない場合にsilentな別Providerへ誤routingしない
  • local unavailable + online selected時にnilへ落ちない

既存Issueとの違い

#460はStory本文生成の旧iori/NAGI familyと新Registry routingの競合です。
#474はLocal multi-model artifactとRegistryの紐付け問題です。

本Issueは Classifier/Memory/Scene等のAuxiliary production adaptersが、SettingsのSimple/Advanced routing source-of-truth自体を参照していない現存routing bugです。

優先度

高。設定画面でモデルを選べるにもかかわらず、補助AIの実Providerがその選択と一致しません。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions