Skip to content

AI連携でレコードをRAGの知識ベースに同期する ​

第1版作成 最終更新 (日本時間)
対応バージョンPleasanter 1.5.8.0 以降確認バージョン1.5.8.1

標準の「AI連携」は、期限付きテーブル・記録テーブルのレコードをMarkdownファイルに変換し、DifyまたはOpenAIの知識ベースへ送る機能です。サーバースクリプトを書かずに、業務データを外部AIが参照する文書として登録できます。

最初にファイル出力で文書の内容を確かめ、次に外部サービスへ接続すると、項目の置換とAPI接続の問題を切り分けられます。ファイル出力はプリザンター1.5.8.1の検証環境で確認しています。外部サービスへの実接続・回答生成は未検証です。

全体の流れ ​

図を読み込み中…

プリザンター側が行うのは文書の出力・登録・更新・削除です。質問を受け付けて回答するアプリは連携先で用意します。保存時にAIを呼んで要約や分類をレコードへ書き戻したい場合は、サーバースクリプトから生成AIを使うを参照してください。

以下では、サーバー側の有効化、テーブル側の設定、出力内容の確認、外部接続、更新・削除の運用を順に説明します。回答する画面まで用意したい場合は、OpenAIのRAGでプリザンター画面にBotを付けるへ進んでください。

連携先を選ぶ ​

連携先プリザンターで選ぶ方式文書の取り込み回答する仕組み
DifyDify標準機能がデータセットへ送信Dify側で検索対象のナレッジを使うアプリを構成
OpenAIOpenAi標準機能がVector Storeへ登録Responses APIのfile_searchを呼ぶBot
Azure AI Search + Azure OpenAIMarkdownFile出力ファイルをBlob Storageへ転送し、Searchのインデクサーで取り込む検索結果をAzure OpenAIへ渡すBotなどを別途実装
Amazon Bedrock Knowledge BasesMarkdownFile出力ファイルをS3へ転送し、ナレッジベースの取り込みを実行検索・回答生成APIを呼ぶBotを別途実装

本体が用意する方式はMarkdownFile・Dify・OpenAiの3つです。Azure・AWSの構成は、ファイル出力を入口にする追加実装です。Azure OpenAIのURLを標準OpenAi方式のEndpointへ入れれば同じ設定で使える、という説明ではありません。標準方式はOpenAIのFiles・Vector Store APIとBearer認証を使います。方式の定義、OpenAIの登録API

1. サーバー側で有効にする ​

Implem.Pleasanter/App_Data/Parameters/AiConnect.jsonを編集します。以下は変更する項目の抜粋です。既存のFormatTemplateやリトライ設定は残してください。

json
{
    "Rag": {
        "Enabled": true,
        "DeleteEnabled": false,
        "OutputFilePath": "C:\\Pleasanter\\AiConnect"
    }
}
項目ソースの既定値設定の意味
Rag.EnabledfalseAI連携を有効にする
Rag.OutputFilePathnullMarkdownの出力先ルート。Dify・OpenAIを使う場合も必須
Rag.DeleteEnabledfalseレコード削除に伴う連携文書の削除を有効にする
Rag.FormatTemplateタイトル・管理情報・内容・コメントなどのテンプレートAI連携設定を新規作成するときの連携フォーマットの初期値

出力先はプリザンターの実行ユーザーが書き込める場所を指定します。Linuxでは、例えば/var/lib/pleasanter/ai-connectのようなパスに置き換えてください。設定を反映するため、プリザンターを再起動します。

FormatTemplateは新しいAI連携設定を作るときにコピーされます。すでに作成した設定の送信内容は、テーブル側の「連携フォーマット」を編集します。

根拠はAiConnect.jsonの既定値、フォーマットの初期化、出力先とフォーマットの検査です。

2. ファイル出力で送信内容を確かめる ​

対象のテーブルで「テーブルの管理」→「AI連携」を開き、「新規作成」で次の設定を追加します。

画面項目設定例
タイトルナレッジ出力確認
連携方式マークダウンファイル(内部値はMarkdownFile)
連携フォーマット下のテンプレート
無効オフ
markdown
# [Title]

状況: [Status]

## 内容

[Body]

## 補足

[DescriptionA]

---

URL: {Url}

DescriptionAを使う場合は、対象テーブルで長文項目Aを有効にしてください。不要なら「補足」の部分を削除します。[Title]などは項目の表示値、{Url}はレコード編集画面の絶対URLに置換されます。既定のテンプレートにはコメントも含まれますが、上の例では本文と補足に絞っています。

「追加」でダイアログを閉じた後、テーブル管理画面の「更新」で設定を保存します。「全て無効化」がオフであることも確認してください。

次に、ダミーのタイトル・本文・補足を入れたレコードを1件作成または更新し、次のパスにファイルが出力されることを確認します。通常更新の送信は内部タスクになる場合があるため、保存直後に見つからなければシステムログも確認します。

text
C:\Pleasanter\AiConnect\<テナントID>\<サイトID>\
  pleasanter-<テナントID>-<サイトID>-<連携先ID>-result-<レコードID>.md

記録テーブルはresult、期限付きテーブルはissueになります。同じテナント・サイト・連携設定・レコードでは同じファイル名で書き出します。文字コードはUTF-8(BOMなし)です。

確認する点は、タイトルや本文が置換されていること、必要な長文項目が含まれていること、外部へ渡したくない項目が含まれていないことです。MarkdownFileは外部APIを呼ばないため、ここで失敗した場合は出力先・書き込み権限・フォーマットから調べます。

根拠は項目・URLの置換、出力パス、ファイル名・文字コード、MarkdownFileの送信処理です。

3. DifyまたはOpenAIへ接続する ​

ファイルの内容を確認したら、「テーブルの管理」→「AI連携」で設定を開き、「連携方式」を変更します。「連携設定」に次のJSONを入力し、「変更」でダイアログを閉じ、管理画面の「更新」で保存します。設定を追加する場合は「新規作成」→「追加」→「更新」です。

Dify ​

セルフホスト環境をこれから用意する場合は、AzureにDifyを構築してプリザンターと連携するでVMの作成からHTTPS、ナレッジ、回答アプリまで説明しています。

接続先のデータセットIDと、そのナレッジAPIへアクセスできるAPIキーを用意します。次の値を実際の接続情報に置き換えてください。

json
{
    "Endpoint": "https://dify.example.com/v1",
    "DatasetId": "YOUR_DATASET_ID",
    "ApiKey": "YOUR_DIFY_KNOWLEDGE_API_KEY"
}

本体は、Markdownファイルをdatasets/<DatasetId>/document/create-by-fileへ送信します。既存文書の更新にはupdate-by-fileを使います。新規登録のindexing_techniqueはhigh_quality、process_rule.modeはautomaticで送信されます。この2項目を変更するサイト設定はありません。

根拠はDifyの接続設定の解決、登録・更新リクエストです。

OpenAI ​

接続先のVector Store IDとAPIキーを用意します。OpenAiは設定ファイル中の識別子、OpenAIは画面の表示名です。

json
{
    "Endpoint": "https://api.openai.com/v1",
    "VectorStoreId": "YOUR_VECTOR_STORE_ID",
    "ApiKey": "YOUR_OPENAI_API_KEY"
}

本体はfilesへファイルをアップロードし、vector_stores/<VectorStoreId>/filesへ登録します。ファイルの送信成功と、Vector Storeでのインデックス完了は別の段階です。連携先で文書を参照できる状態になってから、回答アプリで利用してください。

根拠はOpenAIの接続設定の解決、アップロードとVector Storeへの登録です。

Endpointの省略と通信条件 ​

サイト側のEndpointが空文字列なら、AiConnect.jsonのProviderEndpointsにある同じ方式の値を使います。例えば、共通のDify接続先を次のように指定できます。

json
{
    "ProviderEndpoints": {
        "Dify": "https://dify.example.com/v1",
        "OpenAi": "https://api.openai.com/v1"
    }
}

ProviderEndpointsは既定URLの設定です。接続先を制限する許可リストではなく、サイトのEndpointに別のHTTPS URLを指定できます。サイト側とパラメータ側の両方が空なら接続できません。

通常はHTTPSが必要です。HTTPが認められるのは、AllowInsecureLoopbackEndpointをtrueにし、接続先がループバックの場合だけです。別ホストで動くDifyへHTTPで接続するための設定ではありません。

csharp
public static bool AllowedEndpoint(string endpoint)
{
    if (Uri.TryCreate(endpoint, UriKind.Absolute, out var uri) == false)
    {
        return false;
    }
    if (uri.Scheme == Uri.UriSchemeHttps)
    {
        return true;
    }
    if (uri.Scheme == Uri.UriSchemeHttp)
    {
        return Parameters.AiConnect?.AllowInsecureLoopbackEndpoint == true
            && uri.IsLoopback;
    }
    return false;
}

出典: Implem.Pleasanter/Libraries/AiConnect/AiConnectUtilities.cs(31–47行・8d29c7b)

ここではURLのスキームとループバックを検査しています。ProviderEndpointsとの一致は検査していません。

Azure・AWSへファイル出力を取り込む ​

この節はクラウド側の接続を組み立てるための構成例です。クラウドへのデプロイ・実接続は未検証です。プリザンター側は、先に説明したMarkdownFile方式を使います。

図を読み込み中…

Azure AI Search + Azure OpenAI ​

Azure AI SearchのBlobインデクサーはMarkdownを読み取れます。1ファイルを1文書として扱うoneToOneと、見出し単位に複数文書へ分けるoneToManyがあります。プリザンターの出力は1レコード1ファイルですが、Search側で分割する構成なら、各検索結果から元のレコードへ戻れる識別情報も保持します。Markdown取り込みの仕様

構成する順序は次のとおりです。

  1. 対象テーブルをMarkdownFileで出力します。
  2. 対象のテナント・サイトのフォルダだけを、専用Blobコンテナーへ転送します。複数の連携設定があればファイル名の接頭辞でも対象を絞ります。
  3. Azure AI Searchに検索インデックス、Blobのデータソース、インデクサーを作成します。
  4. インデクサーの設定でparsingModeをmarkdownにし、文書の分け方を指定します。次は設定部分の例です。
  5. インデクサーを実行し、ダミーの本文を検索して取得できることを確認します。
  6. Botのサーバー側でSearchへ質問を送り、取得した本文と参照元を回答生成へ渡します。
json
{
    "parameters": {
        "configuration": {
            "parsingMode": "markdown",
            "markdownParsingSubmode": "oneToMany",
            "markdownHeaderDepth": "h2"
        }
    }
}

Azure AI Searchの検索とLLMへの受け渡しをアプリが担当する構成をClassic RAGと呼びます。Azure AI SearchとAzure OpenAIは別の役割で、文書をBlobへ置いただけでチャット画面が完成するわけではありません。AzureのRAG構成

Amazon Bedrock Knowledge Bases ​

Bedrock Knowledge BasesはUTF-8のMarkdown(.md)を取り込めます。プリザンターの出力ファイルを専用S3バケットまたはプレフィックスへ転送し、S3をデータソースとするナレッジベースに取り込みます。対応する文書形式

  1. 対象テーブルをMarkdownFileで出力します。
  2. 対象サイトのファイルだけを専用S3プレフィックスへ転送します。
  3. BedrockでS3をデータソースとするナレッジベースを作成し、利用する埋め込みモデル・保存先を設定します。
  4. データソースの「Sync」またはStartIngestionJobで取り込みを開始します。S3へのアップロードと取り込みは別の処理です。
  5. 取り込みの状態と失敗件数を確認し、ダミーの本文が取得できることを確かめます。取り込みと状態確認の仕様
  6. Botのサーバー側から検索・回答APIを呼び、回答と引用を画面へ返します。

通常のKnowledge BasesではRetrieveAndGenerateで検索と回答生成をまとめて呼べます。Managed Knowledge BasesはこのAPIの対象外なので、採用する種類に応じてRetrieveなどの対応APIを選びます。名称だけで同じAPIを使えると判断しないでください。RetrieveAndGenerateの仕様と対象

更新と削除をつなぐ ​

プリザンターのRag.DeleteEnabledが削除するのは、標準連携先の文書とローカルの出力ファイルです。MarkdownFile方式から別途転送したBlob・S3オブジェクトは、その削除処理に含まれません。

追加実装では、ファイルの転送、クラウド上の古いファイルの削除、検索インデックスへの削除反映までを別々に確認します。出力フォルダ全体を無条件にミラーする構成では、他サイトのファイルも対象になります。転送対象は専用フォルダ・プレフィックスに限定してください。

Botの画面スクリプトは質問・回答の表示として共通化できますが、このサイトのOpenAI BotのサーバーコードをAzure・AWSへそのまま流用はできません。呼び出すAPI、認証、応答中の引用の取り出し方を連携先に合わせた実装が必要です。

4. 既存レコードを同期する ​

接続設定を「変更」→テーブル管理画面の「更新」で保存したら、「AI連携」の一覧で対象の設定を1件だけ選択し、「同期」を実行します。初回登録や、連携フォーマットを変えて既存レコードも書き直したい場合に使います。

「同期」は差分だけを追加する処理ではありません。Dify・OpenAIでは、その連携設定が登録した文書を削除してから、対象テーブルのレコードを再登録します。

図を読み込み中…

削除対象の識別にはpleasanter-<テナントID>-<サイトID>-<連携先ID>-という接頭辞を使います。環境を複製して同じID構成になった検証環境と本番環境では、接続先とAPIキーを分けてください。同じ接続先へ同期すると、互いの文書を削除するおそれがあります。

Rag.DeleteEnabledはレコード削除時の連動を制御します。「同期」の事前削除は別の処理で、DeleteEnabledがfalseでも実行されます。MarkdownFileの全件削除処理は何もしないため、ファイル出力だけの場合は「同期」で古いファイルが一掃されるわけではありません。

根拠は同期の選択・実行条件、削除後の再登録、Difyの削除対象、MarkdownFileの全件削除です。

5. 更新・削除を運用する ​

通常更新と全件同期の実行方式 ​

永続化されたバックグラウンドキューを使う条件は、次の3つです。

  • BackgroundJobs.jsonのBackgroundQueueがtrue。
  • Queueライセンスオプションが利用できる。
  • BackgroundJobs.jsonのOutputFilePathが設定されている。

AiConnect.jsonのRag.OutputFilePathはMarkdownの出力先、BackgroundJobs.jsonのOutputFilePathはキュー側の出力先です。別の設定なので、一方だけ設定してもキュー条件は満たしません。

操作キュー条件を満たすキュー条件を満たさない
通常のレコード作成・更新・削除ジョブとして登録通常はプロセス内のタスクで実行。待機中・実行中の処理数が100を超えると同期実行
「同期」ボタンによる全件再同期ジョブとして登録し、処理IDを返すリクエスト内で全件処理し、結果を返す

キューなしの通常更新は、同時実行数4で、同じレコード・連携設定の処理を順番に実行します。全件同期ではキューなしでもすぐ画面が戻るとは限りません。件数が多い環境では、キュー設定と処理結果を確認してから実行してください。

根拠はキューの判定、キューの有効化条件、通常更新のタスク実行、全件同期の実行方式です。

削除と停止の違い ​

レコード削除に合わせて連携文書とローカルファイルも削除したい場合は、Rag.DeleteEnabledをtrueにします。Enabledがtrueであり、対象の連携設定と「全て無効化」が無効になっていないことも必要です。

「無効」「全て無効化」は処理を止める設定です。停止中の削除も連携しないため、停止を連携先の文書削除の代わりに使わないでください。

根拠は削除の実行条件、外部文書とファイルの削除順序です。

APIキーの保管 ​

APIキーは画面では********でマスクされ、マスク値を保存し直した場合は保存済みのキーが使われます。ただし、設定の記録にはConnectionSettingの文字列をそのまま保持します。マスク表示は保存値の暗号化ではありません。サイトパッケージを渡す前に認証情報を確認してください。

根拠はキーのマスクと保存値の復元、連携設定の記録です。

送信できないときの切り分け ​

症状確認するところ
「AI連携」タブがないRag.Enabledがtrueか、設定が反映されているか
ファイルが出ないRag.OutputFilePath、書き込み権限、連携フォーマット、個別の「無効」と「全て無効化」
ファイルは出るが外部に登録されない接続設定のJSON、APIキー、Dataset ID / Vector Store ID、Endpointの解決結果とHTTPS条件
設定を保存できても送信に失敗する保存時の接続設定検査はJSONオブジェクトとして読めるかの検査。保存成功だけでAPI疎通は確認できない
「同期」を押せない・拒否される1件だけ選択しているか、設定が無効でないか、出力先が設定されているか
既存レコードが連携先にないAI連携設定の追加だけで全件登録されるわけではない。「同期」を実行したか
保存が終わったのに文書がまだ使えないジョブ・内部タスクの完了と、連携先のインデックス状態
削除したレコードが連携先に残るRag.DeleteEnabled、停止設定、削除処理の失敗ログ

システムログでは、TenantId・SiteId・AiProviderId・ReferenceIdで対象を絞り、PhaseとMessageを確認します。ファイル出力のログにはOutputFilePath・Body・Writeなどの段階が記録されます。レコード保存の成功だけで外部送信の成功とは判断せず、出力ファイルと連携先の文書の両方を確認してください。

根拠は保存時のJSON検査、出力エラーのログ項目です。

関連ページ ​

変更履歴

第1版RAG連携とClearScriptを解説し、既存記事をサイト内で完結させる