← すべてのドキュメント
AI / サーバー

プロバイダー、ストリーミング、DOCX エクスポート

AI Toolkit と組み合わせて使うサーバー側の機能で、すべて RichTextBox.AspNetCore NuGet パッケージ(1.0.0-preview.11 以降)に含まれています。1 行の DI で実際のプロバイダーに接続でき、エンドツーエンドの SSE ストリーミングと、HTML → DOCX のエンドポイントを備えています。

組み込みのプロバイダーリゾルバー

HttpClientFactory、キャンセル、ILogger<T> を使う、そのまま組み込める 3 つの IRichTextBoxAiResolver の実装があります。1 つを選んで Program.cs に登録します。

using RichTextBox.AiResolvers;

builder.Services.AddRichTextBox();
builder.Services.AddRichTextBoxOpenAiResolver(opts =>
{
    opts.ApiKey = builder.Configuration["OpenAI:ApiKey"];
    opts.Model  = "gpt-6-luna";
});

AddRichTextBoxOpenAiResolver は、AddRichTextBoxAnthropicResolver または AddRichTextBoxAzureOpenAiResolver に置き換えられます。3 つとも AiResolverOptions を共有しています。

public class AiResolverOptions
{
    public string  ApiKey        { get; set; }       // required
    public string? Model         { get; set; }       // provider-specific default
    public string? BaseUrl       { get; set; }       // for proxies / Ollama / Groq
    public int     MaxTokens     { get; set; } = 1024;
    public double  Temperature   { get; set; } = 0.4;
    public string? SystemSuffix  { get; set; }       // appended to every mode's system prompt
    public TimeSpan Timeout      { get; set; } = 60s;
}

Azure では、AzureOpenAiResolverOptions に 3 つの追加項目があります。Endpoint(https://my-resource.openai.azure.com)、DeploymentName(モデル名ではありません)、ApiVersion(省略可能)です。

OpenAiResolver は、OpenAI 互換のあらゆるエンドポイントで動作します。Groq、Together.ai、ローカルの Ollama を使う場合は BaseUrl を上書きしてください。

ストリーミングのレスポンス(Server-Sent Events)

MapRichTextBoxUploads() は、POST /richtextbox/ai/stream もマップします(RichTextBoxOptions.AiStreamEndpoint で変更できます)。OpenAI と Anthropic のリゾルバーは IStreamingRichTextBoxAiResolver を実装しています。ストリーミングに対応していないプロバイダーは、透過的に 1 つのデータフレームで返す動作になります。

通信形式

data: <json-encoded delta string>\n\n
data: <json-encoded delta string>\n\n
...
event: response
data: { ...RichTextBoxAiResponse payload... }\n\n
event: done
data: {}\n\n

クライアント

var stream = editor.aiToolkit.streamRequest({
    url: "/richtextbox/ai/stream",
    body: { mode: "rewrite", selectionText: "..." },
    onDelta:    function (chunk, full) { /* render progressively */ },
    onResponse: function (payload)     { /* final structured result */ },
    onDone:     function (fullText)    { },
    onError:    function (err)         { }
});
// stream.abort()  — cancel mid-response
// stream.promise  — resolves with the concatenated full text

ヘルパーは fetch と ReadableStream を使います。ストリーミングに対応していないブラウザーでは、ストリーミングでないエンドポイントに対する XHR に自動的に切り替わります。

DOCX エクスポート

MapRichTextBoxUploads() は、POST /richtextbox/export/docx もマップします(DocxExportEndpoint で変更できます)。MIT ライセンスの DocumentFormat.OpenXml をベースにしており、外部サービスは使いません。

リクエスト

POST /richtextbox/export/docx
Content-Type: application/json

{
    "html": "<h1>Memo</h1><p>Body.</p>",
    "title": "Memo",
    "fileName": "memo.docx"
}

レスポンス

Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document と Content-Disposition: attachment; filename=memo.docx を持つバイナリストリームです。

サポートしている HTML

  • 段落、h1–h6、blockquote、pre、hr
  • 入れ子の番号付きリストと箇条書きリスト
  • 表(見出し行を含む)
  • インライン:b/strong, i/em, u, s/del, sub, sup, code, br
  • ハイパーリンク、インライン画像(data URI のみ。安全のため、外部の URL はスキップします)
  • スタイル属性:font-weight, font-style, text-decoration, color, background-color, text-align

クライアントのヘルパー

editor.aiToolkit.exportDocx({
    url:      "/richtextbox/export/docx",
    fileName: "report.docx",
    title:    "Quarterly report"
});

カスタムリゾルバー

Bedrock、Gemini、独自のモデルなど、それ以外のものを使う場合は、IRichTextBoxAiResolver(必要に応じて IStreamingRichTextBoxAiResolver も)を実装し、そのクラスを登録してください。AI Toolkit のそれ以外の部分は、プロバイダーに依存しません。

public sealed class MyBedrockResolver : IRichTextBoxAiResolver
{
    public async ValueTask<RichTextBoxAiResponse> ResolveAsync(
        RichTextBoxAiRequest request, CancellationToken cancellationToken = default)
    {
        // ...call Bedrock, map response to RichTextBoxAiResponseBuilder...
    }
}

builder.Services.AddRichTextBox();
builder.Services.AddSingleton<IRichTextBoxAiResolver, MyBedrockResolver>();