LUIS から CLU への移行で発生する「Microsoft.CluRecognizer not registered in factory」エラーの原因と解決手順

LUIS から CLU(Conversational Language Understanding)へ移行するとき、「動いたはずのボットが突然 500 エラー」「ログを見ると Microsoft.CluRecognizer が見つからない」という状況にハマりがちです。本記事では、実際に遭遇しやすい 「Type Microsoft.CluRecognizer not registered in factory」エラー を題材に、Bot Framework Composer/SDK 双方での原因と解決手順を、設定ファイルとコード例つきで詳しく整理します。

目次

LUIS → CLU 移行時に出る「Microsoft.CluRecognizer not registered in factory」とは

まず、問題のエラーメッセージを整理します。

エラーメッセージ:
Type Microsoft.CluRecognizer not registered in factory

このメッセージが意味しているのは、次の 1 点だけです。

  • ダイアログ内で指定された $kind: "Microsoft.CluRecognizer" を実行時に解決できない(=その種類のコンポーネントが登録されていない)

つまり、C# コード側で using Microsoft.Bot.Components.Recognizers.CLURecognizer; と書いただけでは不十分で、Bot ランタイムに「この $kind のコンポーネントがここにあるよ」と教える仕組みが必要になります。

ここで押さえておきたいのが、Bot Framework の「宣言型コンポーネント」の仕組みです。

  • .dialog ファイルでは、各アクションや認識器を $kind という文字列で指定する
  • ランタイムは起動時にコンポーネント DLL を読み込み、$kind と .NET の型をひも付けて「factory(工場)」に登録する
  • 登録されていない $kind が出てくると、not registered in factory という例外を投げる

このため、LUIS から CLU へ移行した際には、

  • CLU 用コンポーネント DLL がそもそも読み込まれていない
  • appsettings.json(settings.json)にコンポーネントの登録がない
  • $kind のスペル/大文字小文字が一致していない
  • 自作の認識器クラスに変えてしまい、宣言型登録を忘れている

といった理由で、今回のエラーが発生します。

ありがちな落とし穴を一覧で整理

パターン典型的な原因
Composer では動くが Azure VM にデプロイすると落ちるVM 側ランタイムに CLU コンポーネント DLL がデプロイされていない/runtimeSettings.components がずれている
NuGet と using を追加したのにエラーが続く実行プロジェクトではなく別プロジェクトにだけパッケージを追加している/コンポーネント登録がない
CLURecognizer 型が見つからないコンパイルエラーパッケージ内にその名前の型が存在しない、もしくは DI 登録のやり方がそもそも違う
自作 $kind 名で使おうとして失敗カスタムクラスを declarative コンポーネントとして登録していない

ここから先は、Composer を使っている場合と、.NET SDK で自前ホストしている場合の 2 パターンに分けて、正しい登録方法と設定例を順番に解説していきます。


Bot Framework Composer での解決手順

Composer を使っている場合は、基本的に「Package Manager から入れる」「settings でキーを設定する」の 2 ステップで解決できます。C# のコードを書き換える必要はほとんどありません。

Composer の Package Manager で CLU コンポーネントを追加

Composer の左ペインから Package Manager を開き、次の操作を行います。

  1. Browse タブを選択
  2. Microsoft.Bot.Components.Recognizers.CLURecognizer を検索
  3. 対象ボットのランタイムプロジェクトにインストール

この操作を行うと、プロジェクトの settings/appsettings.json(ローカルでは settings.development.json など)に次のような設定が自動的に追加されます。

{
  "runtimeSettings": {
    "components": [
      {
        "name": "Microsoft.Bot.Components.Recognizers.CLURecognizer"
      }
    ]
  }
}

この components 配列こそが「factory に登録する DLL 一覧」であり、ここに CLU コンポーネントのアセンブリ名が入っていないと、$kind: "Microsoft.CluRecognizer" を見つけられません。

CLU の接続情報を settings に定義する

次に、Azure Language リソースのエンドポイントとキー、CLU プロジェクト名とデプロイ名を設定します。Composer の設定画面、または settings/appsettings.json を直接編集して、次のような形で定義します。

{
  "language": {
    "clu": {
      "endpoint": "https://<your-language-resource>.cognitiveservices.azure.com/",
      "apiKey": "<your-api-key>",
      "projectName": "YourCluProjectName",
      "deploymentName": "production"
    }
  },
  "runtimeSettings": {
    "components": [
      { "name": "Microsoft.Bot.Components.Recognizers.CLURecognizer" }
    ]
  }
}

ここで重要なのは認証方式です。

  • CLU 認識器は基本的に API キー(endpoint + key)方式 を前提としている
  • clientId / clientSecret / tenantId だけを設定しても、CLURuntime 側の期待と合わず認証に失敗する
  • Azure Portal の「言語リソース(Language)」→「キーとエンドポイント」で表示される キー をそのまま apiKey に設定する

設定値の意味を簡単に表にしておきます。

キー例意味
endpointhttps://xxx.cognitiveservices.azure.com/Azure Language リソースのエンドポイント URL
apiKey英数字 32 文字程度「キーとエンドポイント」に表示されるサブスクリプションキー
projectNameMyCluProjectLanguage Studio で作成した CLU プロジェクト名
deploymentNameproduction / staging などLanguage Studio で発行したデプロイメント名

.dialog 側の recognizer 設定($kind と設定値のひも付け)

次に、メインダイアログなどの .dialog ファイルで recognizer を CLU に切り替えます。推奨される設定例は次の通りです。

"recognizer": {
  "$kind": "Microsoft.CluRecognizer",
  "projectName": "=settings.language.clu.projectName",
  "deploymentName": "=settings.language.clu.deploymentName",
  "endpoint": "=settings.language.clu.endpoint",
  "apiKey": "=settings.language.clu.apiKey"
}

ここでのポイントは 2 つです。

  • $kind の値を完全一致で "Microsoft.CluRecognizer" にすること(スペルや大文字小文字を変えない)
  • 設定は =settings... の式で settings.json の値を参照するようにしておくこと

もし既存の LUIS 設定からコピペしている場合は、$kind が Microsoft.LuisRecognizer のままになっていないか、endpointKey など LUIS 向けのプロパティ名が残っていないかもチェックしてください。

Composer 環境で確認しておきたいチェックリスト

  • ✔ 実行しているボットのランタイムプロジェクトに Microsoft.Bot.Components.Recognizers.CLURecognizer がインストールされている
  • ✔ settings/appsettings.json の runtimeSettings.components にコンポーネント名が入っている
  • ✔ .dialog の $kind が Microsoft.CluRecognizer になっている
  • ✔ endpoint / apiKey / projectName / deploymentName がすべて設定されている
  • ✔ Language Studio 側で CLU プロジェクトをデプロイ済みで、deploymentName と一致している
  • ✔ 実行環境(ローカル/VM/App Service)ごとの settings.*.json が正しいファイルに切り替わっている

ここまで揃えば、Composer 環境での「Microsoft.CluRecognizer not registered in factory」エラーはほぼ解消できるはずです。


.NET SDK(自前ホスト)での解決手順

次に、Bot Framework SDK を使って自前ホストしている場合の対処方法です。Adaptive Runtime(Composer ランタイム)をそのまま使うかどうかで若干手順が変わりますが、共通するポイントは次の 3 つです。

  • 実行プロジェクトに CLU の NuGet パッケージを追加する
  • ランタイムにコンポーネントを登録する(多くの場合 runtimeSettings.components で十分)
  • Host.CreateDefaultBuilder(...) の Build / Run より前 に登録処理を行う

NuGet パッケージを「実行プロジェクト」に追加する

ソリューションを複数プロジェクト構成にしている場合、CLU パッケージを誤って共有ライブラリ側にだけインストールしてしまい、Web アプリ(実行プロジェクト)には入っていないケースがよくあります。

  • ボットをホストしている ASP.NET Core プロジェクト(Program.cs があるプロジェクト)を右クリック
  • 「NuGet パッケージの管理」から Microsoft.Bot.Components.Recognizers.CLURecognizer を追加

これにより、ビルド出力フォルダ(bin/<Configuration>/<TargetFramework>/)に Microsoft.Bot.Components.Recognizers.CLURecognizer.dll がコピーされるようになります。デプロイ先でもこの DLL が存在するか、実際にファイルを確認しておくと安心です。

Adaptive Runtime を使う場合の Program.cs 例

Composer と同じ Adaptive Runtime を使う場合の典型的な Program.cs 例です。重要なのは、services.AddBotRuntime() やコンポーネント登録を Build() より前に行うことです。

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =&gt;
        Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hosting, builder) =&gt;
            {
                var root = AppDomain.CurrentDomain.BaseDirectory;
                var env  = hosting.HostingEnvironment.EnvironmentName;

                // Composer 互換の設定読み込み
                builder.AddBotRuntimeConfiguration(root, "settings", env);
                builder.AddCommandLine(args);
            })
            .ConfigureServices((context, services) =&gt;
            {
                // Adaptive Runtime を登録
                services.AddBotRuntime();

                // 通常、CLU 用コンポーネントは appsettings.json の
                // "runtimeSettings.components" に登録しておけば、
                // ここで個別に AddSingleton する必要はない
            })
            .ConfigureWebHostDefaults(webBuilder =&gt;
            {
                webBuilder.UseStartup&lt;Startup&gt;();
            });
}

誤りやすいパターンとして、次のようなコードがあります。

  • CreateHostBuilder(args).Build().Run(); の後ろに WebApplication.CreateBuilder() を書いてしまう
  • 旧来の Startup パターンと .NET 6 以降の最小ホストパターンを混在させる

この場合、後段に書いたコードは実行されず、コンポーネント登録が一切行われないため、当然ながら Microsoft.CluRecognizer not registered in factory が発生します。ホストのスタイルは 1 つに統一し、登録処理は必ず Build の前に書くようにしてください。

services.AddSingleton<CLURecognizer>(); がうまくいかない理由

エラーに悩んだ結果、「とりあえずサービスコレクションに CLURecognizer を登録すればいいのでは?」と考え、次のようなコードを書いてしまうケースもあります。

public static void ConfigureServices(IServiceCollection services)
{
    services.AddControllers().AddNewtonsoftJson();

    // ❌ これでコンパイルエラー、あるいは実行時エラーになる
    services.AddSingleton&lt;CLURecognizer&gt;();
}

これがうまくいかない理由は主に 2 つあります。

  1. パッケージ内にその名前の型が存在しない
    コンポーネントパッケージは、「宣言型(Declarative)コンポーネント」を登録する BotComponent を内部に持っており、開発者が直接 new して使う前提ではないものがほとんどです。そのため、CLURecognizer というクラスが見つからず、コンパイルエラーになります。
  2. factory と DI コンテナは別物
    not registered in factory は「宣言型コンポーネントの factory に登録されていない」という意味であり、DI コンテナ(services.AddSingleton)の登録有無とは別です。DI にインスタンスを登録しても、$kind を解決する仕組みには何も影響しません。

正しいアプローチは、Composer と同様に runtimeSettings.components でコンポーネント DLL を読み込ませ、$kind: "Microsoft.CluRecognizer" を使うことです。C# コード側で個別の Recognizer 型を意識する必要は基本的にありません。

appsettings.json でコンポーネントを登録する

自前ホストでも、設定ファイルの構造は Composer とほぼ同じにできます。例えば次のような appsettings.json を用意し、先ほどの AddBotRuntimeConfiguration で読み込ませます。

{
  "language": {
    "clu": {
      "endpoint": "https://&lt;your-language-resource&gt;.cognitiveservices.azure.com/",
      "apiKey": "&lt;your-api-key&gt;",
      "projectName": "YourCluProjectName",
      "deploymentName": "production"
    }
  },
  "runtimeSettings": {
    "components": [
      { "name": "Microsoft.Bot.Components.Recognizers.CLURecognizer" }
    ]
  }
}

これにより、Adaptive Runtime が起動時に CLU コンポーネントを自動的に読み込み、$kind: "Microsoft.CluRecognizer" を factory に登録してくれます。ダイアログファイルも Composer と同じ形式で記述できます。

SDK 環境でのチェックリスト

  • ✔ 実行プロジェクトに CLU NuGet パッケージが追加されている
  • ✔ ビルド出力フォルダに Microsoft.Bot.Components.Recognizers.CLURecognizer.dll が存在する
  • ✔ Host.CreateDefaultBuilder などのホストビルダーで、services.AddBotRuntime() を Build() より前に呼んでいる
  • ✔ runtimeSettings.components にコンポーネント名が登録されている
  • ✔ .dialog ファイルから参照される設定キー(settings.language.clu.*)がすべて存在する

カスタム認識器名(独自 $kind)を使う場合の注意点

エラーメッセージが次のような形式になっている場合もあります。

Type TreasuryBot.Custom_Recognizer.CustomCluRecognizer not registered in factory.

これは、.dialog ファイルの recognizer に独自の $kind 名を指定しているケースです。

"recognizer": {
  "$kind": "TreasuryBot.Custom_Recognizer.CustomCluRecognizer",
  ...
}

このように $kind を自作クラス名に変えて使う場合は、次の条件を満たしていないと factory で解決できません。

  • 自作認識器クラス(例:CustomCluRecognizer)を作成している
  • そのクラスを宣言型コンポーネントとして登録する BotComponent を実装している
  • 上記 BotComponent を含むアセンブリを runtimeSettings.components に登録している

BotComponent の実装イメージは次のような形になります(概念図)。

public class CustomRecognizerComponent : BotComponent
{
    public override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
    {
        // 必要に応じてサービス登録
    }

    public override void ConfigureDeclarativeTypes(DeclarativeTypeCollection collection)
    {
        collection.Add(
            new DeclarativeType&lt;CustomCluRecognizer&gt;(
                "TreasuryBot.Custom_Recognizer.CustomCluRecognizer"));
    }
}

そして、このコンポーネントを含むアセンブリ名を runtimeSettings.components に登録します。

"runtimeSettings": {
  "components": [
    { "name": "TreasuryBot.Custom_Recognizer" }
  ]
}

ここまでして初めて、自作の $kind が factory で解決されるようになります。特別な理由がなければ、まずは既定の $kind: "Microsoft.CluRecognizer" をそのまま使う方がトラブルも少なく、移行検証もしやすくなります。


LUIS から CLU への移行時に確認しておきたいポイントまとめ

最後に、LUIS から CLU に切り替える際に見落としがちなポイントを、LUIS 時代の設定と対比しながら整理しておきます。

項目LUIS 時代CLU 移行後
$kindMicrosoft.LuisRecognizerMicrosoft.CluRecognizer
認証方式LUIS の endpointKey / authoringKeyLanguage リソースの endpoint + key(API キー)
設定ファイルsettings.language.luis.* などsettings.language.clu.* など CLU 用に新規定義
Azure ポータルのリソースLUIS 専用リソース「言語」リソース+Language Studio の CLU プロジェクト
移行時に出がちなエラー設定不足で LUIS への接続失敗Microsoft.CluRecognizer not registered in factory / 認証エラー/無効な project/deployment 名

特に、次のようなパターンは今回のエラーに直結します。

  • LUIS 用のコンポーネント(Orchestrator など)は登録してあるが、CLU コンポーネントを追加していない
  • ソリューションのどこかには CLU パッケージを入れたが、実行プロジェクトに入れていない
  • ローカルの settings.development.json を書き換えたが、VM 上の appsettings.json を更新し忘れている
  • カスタム $kind を使っているのに BotComponent に declarative 登録を書いていない

トラブルシューティングのステップバイステップ

実際に「Microsoft.CluRecognizer not registered in factory」が出てしまったときに、どの順番で確認すればよいかを簡単な手順としてまとめます。

  1. ビルド出力に DLL があるか確認
    デプロイ先(ローカル/VM/App Service)の bin フォルダを開き、Microsoft.Bot.Components.Recognizers.CLURecognizer.dll が存在するかを確認します。なければ NuGet の入れ先か、デプロイ設定を見直します。
  2. appsettings.json / settings.json の components セクションを確認
    runtimeSettings.components に { "name": "Microsoft.Bot.Components.Recognizers.CLURecognizer" } が入っているかを確認します。環境ごとの設定ファイル(development / production など)のずれにも注意します。
  3. .dialog の $kind を確認
    誤って Microsoft.CluRecogniser のようにスペルミスしていないか、Microsoft.LuisRecognizer のままになっていないかを確認します。
  4. 認証情報とプロジェクト名/デプロイ名を確認
    「キーとエンドポイント」画面のキーを使っているか、Language Studio 上のプロジェクト名・デプロイ名と一致しているかを確認します。認証エラーの場合も、内部での初期化が失敗して似たような例外が見えることがあります。
  5. 自作 $kind の有無を確認
    $kind に自作の名前空間を使っている場合は、BotComponent の declarative 登録があるかを確認します。なければ、既定の Microsoft.CluRecognizer に戻すか、登録コードを追加します。

この順に追っていけば、「どこで CLU が見えなくなっているのか」をかなりの確度で特定できます。


まとめ:エラーの本質と、最短での解消アプローチ

本記事では、LUIS から CLU へ移行した際に発生しがちな Type Microsoft.CluRecognizer not registered in factory エラーについて、Composer/SDK 両方の観点から原因と対処方法を整理しました。

  • エラーの本質は 「$kind: Microsoft.CluRecognizer を解決できるだけのコンポーネント登録がない」こと
  • Composer 環境では、Package Manager で CLU コンポーネントを追加し、runtimeSettings.components に反映されていることを確認するだけで解消できるケースが多い
  • SDK/自前ホストでは、実行プロジェクトに NuGet を追加し、ホストの Build 前に Adaptive Runtime を初期化することが重要
  • 認証は Language リソースの endpoint + API キー を使うのが基本で、clientId / clientSecret / tenantId だけでは動かないことが多い
  • カスタム $kind を使う場合は、BotComponent による declarative 登録が必須
  • services.AddSingleton<CLURecognizer>(); のような直接登録は、型名も仕組みも合わず、根本解決にならない

LUIS の終息に伴い、今後 CLU への移行はますます増えていきますが、「コンポーネント登録」「設定値」「ホスト初期化」の 3 つさえ押さえておけば、今回のようなエラーは比較的シンプルに切り分けられます。この記事をチェックリスト代わりにしながら、自身のボット環境の設定を一つずつ見直してみてください。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次