AI取込
一言でいうと
Astar の「転記を根絶する」中核機能。PDF・画像・スキャン文書を OCR にかけ、AI にテーブルのスキーマへ抽出させ、確認を経てテーブルのレコードとして書き込むパイプライン。単発の変換ではなく、ステップの列(OCR アンカリング → 抽出 → 検証 → ギャップ検出 → レコード挿入)として実装された明示的なワークフローで、途中経過は SSE で配信される。
主要ドメイン概念
| 概念 | 役割 |
|---|---|
| Organize Job | 1回の取込実行。対象文書・出力テーブル・状態を持つ |
AiExtractorPort | AI へ抽出を依頼するポート。実装は AI チャット基盤(AIChatServiceAdapter)を再利用する |
| Fund Flow Candidate | 護 (mamoru) の入出金明細のような「候補レコード」。マージ・重複排除の対象になる |
| Gap(ギャップ) | 抽出結果のうち、必須項目が埋まらなかった箇所。ユーザーへの確認を促す |
| triage-capture | 「AIに渡す」フォルダに投げ込まれた文書を自動で仕分けする automation スキル |
Backend 構造
core/organize/ は api/domain/infrastructure の直下に加えて、責務ごとのサブパッケージ(workflow・extraction・pack・learning・interview・citation・convert・videoevidence・publicaccess・review)を持つ、モジュール内モジュールの構成になっている。
api/controller/OrganizeController: Organize Job の起動 (POST/ idempotency key 対応)・進捗取得・リトライ・レコードマージ・ファンドフロー候補の取得を公開するworkflow/domain/service/: パイプライン本体。OrganizeWorkflowRunnerがステップ列を順に実行する。ステップはResolveDocumentsStep→OcrAnchorStep→ExtractSingleDocumentStep/ExtractMultiTableDocumentStep→ValidateExtractionStep→GapDetectionStep→InsertRecordsStep/InsertMultiTableRecordsStep→FinalizeSingleTableJobStepのように、明示的な Step クラスとして分解されている(単一テーブル抽出と複数テーブル抽出で別系統のステップを持つ)extraction/domain/:AiExtractorPort(AI 抽出のポート)、ExtractionRouter、PromptGeneratorService(抽出プロンプト生成)、ExtractionResponseParser/ExtractionValidatorPort(AI 応答の検証)、ExtractionCorrectionLoop(検証エラー時の再試行)citation/domain/service/SourceReferenceService・OcrAlignmentService: 抽出値が元文書のどこに書かれていたかを紐付ける「根拠出典」機能learning/domain/service/LearnedCorrectionService: ユーザーが手動修正した内容を学習し、次回の抽出精度を上げるpack/: 抽出結果を既存の書式(フォーマットパック)に流し込んで文書生成する(PackPipelineService等)review/domain/service/:PassbookBalanceCheckService(通帳残高整合性チェック)、FundFlowCandidateQueryService/FundFlowCandidateStatusService(入出金候補の一覧・状態管理)、RecordMergeService/RecordDeduplicationService(重複レコードのマージ)infrastructure/listener/:OrganizeWorkspaceBootstrapListener・OrganizeTemplateBackfillListener(ワークスペース作成時の初期化系リスナー)- 進捗配信は
workflow/api/controller/OrganizeJobEventController+OrganizeSseEmitterFactoryが SSE で行う
Frontend 構造
app/modules/organize/ は規約の4分類に services・validators・utils を加えた構成。
components/:pack/(フォーマットパック UI)、convert/(変換 UI)、workspace/(取込先ワークスペース選択)composables/: Organize Job の起動・進捗購読・結果確認のロジック
listener駆動と triage-capture
AI 取込は「ユーザーが明示的に取込ボタンを押す」経路(OrganizeController.startOrganize)に加えて、automation の triage-capture スキル経由でも起動する。事務所メンバーが、テンプレート適用などの明示操作で triage-capture 自動化を追加した「AIに渡す」フォルダへ文書を投げ込むと、document.created イベントが AutomationRuleEventDispatcher によって dispatch され、スキルが文書を読んで適切な業務テーブルへ振り分ける。新規テナントへ実行ルールを自動投入する経路はない。
triage-capture の自動実行は本来、AI メンバーを紐付けない AUTO document イベントとして拒否されるはずの経路(validateSkillRequiresAiMember)だが、document.* イベントに限り event.actorUserId(=文書を投げ込んだ本人)の権限で実行される特例になっている。EVENT_SYSTEM_USER への昇格は発生しない。フィルタも /*/AIに渡す/* という直下限定パターンで、** にすると「AIに渡す」フォルダ自身の作成イベントにまで誤爆するため意図的に一段階に絞られている——このパターンを新しい automation ルールのひな形にする際は、フィルタの階層をそのままコピーしないこと。