以前にコンソールアプリで AI を扱うチャットアプリを作りました。
今回は Web アプリに組み込んでみます。GitHub のリポジトリはこちら。
こんな感じに文章要約を AI で行います。


今回はその 1。AI を扱う機能を .NET Web アプリに追加するにあたってのプロジェクト構成についてです。
■ 全体の目次です
■ Web アプリに追加する、とは?
Web アプリそのものは別途存在していて、アドオン敵に AI 機能を追加する試みです。
簡単に言うと Web アプリのプロジェクトとは別のプロジェクトで AI の機能を実装します。そして、それらのプロジェクトに依存関係はないものの、実行時には AI 機能を持って Web アプリが動く。そういう夢のような構成です。
■ 基本戦略
簡単に基本を挙げると、Web アプリの起動時に DLL を動的にロードして AI を扱う機能を実装した DLL を読み込みます。
ここでポイントになるのは、.NET の ASP.NET では DLL の中にコントローラーのクラスがあっても、DLL を読み込んだだけでは API として使われないというところです。
■ DLL の中のコントローラーを API として認識させる
Web アプリで動的に読み込んだ際に、Web のルーティングに DLL 内のコントローラークラスを追加する必要があります。それがこのメソッドです。
namespace Microsoft.Extensions.DependencyInjection { public static class MvcCoreMvcBuilderExtensions { public static IMvcBuilder AddApplicationPart(this IMvcBuilder builder, Assembly assembly);
プロジェクトのコードの中ではこんな感じ。
var builder = WebApplication.CreateBuilder(args); // Add services to the container. var mvcBuilder = builder.Services.AddControllersWithViews(); // dll 読み込み { var basePath = Path.Combine(Directory.GetParent(System.Reflection.Assembly.GetEntryAssembly()!.Location!)!.Parent!.Parent!.Parent!.Parent!.FullName, "AI機能を実装したプロジェクトのパス\\bin"); var files = Directory.GetFiles(basePath, "*.dll", SearchOption.AllDirectories).Select(dll => System.Reflection.Assembly.LoadFrom(dll)).ToArray(); foreach (var assembly in files) { mvcBuilder.AddApplicationPart(assembly); } } var app = builder.Build();
■ 足したはずの API が 405 になる
コードを書いてみても DLL に実装し追加したはずの API が 405 Method Not Allowed になることがあります。
パターンは二つ。
読み込み・登録メソッドの記述位置
ASP.NET のアプリのコードはテンプレートから生まれたばかりの場合、 Progmam.cs の最後に次の記述があると思います。
app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}") .WithStaticAssets(); app.Run();
この MapControllerRoute メソッドより前に AddApplicationPart を行ってください。
DLL のビルド
今回のプロジェクト構成では、Web プロジェクトと AI を使う機能のプロジェクトに依存関係がありません。
そのため、Web のプロジェクトのビルドだけでは、DLL 側のビルドが行われず DLL が存在しない ⇒ 存在しないので読み込まれない、となる場合があります。
DLL のプロジェクトもしっかりビルドしておきましょう。
■ DLL 読み込みでエラーになる
起動時に DLL の読み込みで次のようなエラーになることがあります。
System.IO.FileLoadException HResult=0x80131621 Message=Could not load file or assembly 'RKSoftware.AIClientAPI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Assembly with same name is already loaded Source=<例外のソースを評価できません> スタック トレース: <例外のスタック トレースを評価できません>
これは同じ DLL を二回読みこんでしまったのでエラーになっています。
今回 Web のプロジェクトと DLL のプロジェクトで依存関係がありません。そのため Web のプロジェクトからは DLL のプロジェクトの bin フォルダの中の DLL を読み込むようにしています。
そう、bin の中に、Release フォルダと Debug フォルダが生まれるあの bin フォルダです。
DLL のプロジェクト側がリリースビルドをしていようが、デバッグビルドをしていようが、はたまた独自の定義のビルドをしていようがとりあえず読み込めるようにしています。
そのため、Release フォルダと Debug の両方に DLL がビルドされていると両方読み込もうとしてエラーになってしまいます。
デバッグのことだけを考えれば
デバッグのことだけを考えれば対策はないでもないですが、前述の DLL 側のビルドの問題もあり、対策をとっても事故は起こるのでそのままにしています。
■ 次回
次回からは AI を使うコードのある方のプロジェクトの作り方を見ていこうと思います。