すべてのプロダクト
Search
ドキュメントセンター

OpenSearch:マルチモーダルデータの解析とベクトル化

最終更新日:Jun 05, 2026

AI Search Open Platform 上にエンドツーエンドのマルチモーダルデータ前処理パイプラインを構築し、ドキュメントと画像を解析し、コンテンツをチャンキングして、テキスト埋め込みを生成します。

ユースケース

マルチモーダルデータ前処理パイプラインは、ドキュメント解析、画像解析、ドキュメントチャンキング、テキスト埋め込み、スパーステキスト埋め込みの 5 つのサービスを通じて、非構造化ドキュメントと画像を処理します。すべてのサービスは、AI Search Open Platform API を介して呼び出します。料金は実際の使用量に基づきます。

前提条件

  • AI Search Open Platform が有効化されていること。サービスの有効化

  • API エンドポイントと API キーが用意されていること。サービスエンドポイントの照会API キーの管理

    サービスは、インターネット経由または VPC 経由で呼び出すことができます。クロスリージョンの VPC 呼び出しは、China (Shanghai)、China (Hangzhou)、China (Shenzhen)、China (Beijing)、China (Zhangjiakou)、China (Qingdao) リージョンでサポートしています。

マルチモーダルデータ前処理パイプラインの構築

説明

使いやすさを考慮し、AI Search Open Platform では以下の 4 種類の開発フレームワークを提供しています。

  • Java SDK

  • Python SDK

  • 既に LangChain 開発フレームワークを使用している場合は、LangChain を選択します。

  • 既に LlamaIndex 開発フレームワークを使用している場合は、LlamaIndex を選択します。

ステップ 1:サービスの選択とコードのダウンロード

この手順では、Python SDK を使用してマルチモーダルデータ前処理パイプラインを構築します。

  1. AI Search Open Platform コンソールにログインします。

  2. China (Shanghai) リージョンを選択し、AI 検索オープンプラットフォーム に切り替えてから、ターゲットのワークスペースに切り替えます。

    説明
    • 現在、AI Search Open Platform は、中国 (上海) およびドイツ (フランクフルト) リージョンでのみ利用可能です。

    • 中国 (杭州)、中国 (深圳)、中国 (北京)、中国 (張家口)、および中国 (青島) リージョンのユーザーは、VPC エンドポイントを使用してリージョン間で AI Search Open Platform サービスを呼び出すことができます。

  3. 左側のナビゲーションペインで、シナリオセンター を選択します。[マルチモーダルデータの前処理 - データの解析とベクトル化] を見つけて、進む をクリックします。

  4. ドロップダウンリストから、必要なサービスを選択します。各サービスの詳細情報は 詳細 ページで確認できます。

    説明
    • 各サービスにはサービス ID (service_id) が必要です。たとえば、ドキュメント解析サービスの ID は ops-document-analyze-001 です。

    • 生成されたコード内の service_id は、サービスを切り替えると自動的に更新されます。コードをダウンロードした後に手動で service_id を変更することもできます。

    段階

    説明

    ドキュメント内容解析

    ドキュメント内容解析サービス (ops-document-analyze-001) :非構造化ドキュメント (テキスト、表、画像) からタイトルや段落などの論理構造を抽出し、構造化されたコンテンツを返します。

    画像内容解析

    • 画像内容理解サービス (ops-image-analyze-vlm-001) :マルチモーダル LLM を使用して画像コンテンツを解析し、テキストを認識して、画像の検索や質疑応答に利用します。

    • 画像テキスト認識サービス (ops-image-analyze-ocr-001) :OCR を使用して画像内のテキストを認識し、検索や質疑応答に利用します。

    ドキュメントチャンキング

    ドキュメントチャンキングサービス (ops-document-split-001) :HTML、Markdown、TXT 形式の構造化データを段落、セマンティクス、またはカスタムルールに従って分割します。また、リッチテキストからコード、画像、表を抽出します。

    テキスト埋め込み

    • OpenSearch テキスト埋め込みサービス-001 (ops-text-embedding-001) :40 以上の言語をサポート。最大入力:300 トークン。出力:1,536 次元ベクトル。

    • OpenSearch 一般テキスト埋め込みサービス-002 (ops-text-embedding-002) :100 以上の言語をサポート。最大入力:8,192 トークン。出力:1,024 次元ベクトル。

    • OpenSearch テキスト埋め込みサービス-中国語-001 (ops-text-embedding-zh-001) :中国語専用。最大入力:1,024 トークン。出力:768 次元ベクトル。

    • OpenSearch テキスト埋め込みサービス-英語-001 (ops-text-embedding-en-001) :英語専用。最大入力:512 トークン。出力:768 次元ベクトル。

    スパーステキスト埋め込み

    テキストをスパースベクトル表現に変換します。スパースベクトルはストレージ要件が少なく、キーワードと用語の頻度を捉えます。密ベクトルと組み合わせてハイブリッド検索を行うことで、検索精度を向上させます。

    OpenSearch スパーステキスト埋め込みサービス (ops-text-sparse-embedding-001) :100 以上の言語をサポート。最大入力:8,192 トークン。

サービスを選択した後、設定完了、コード照会へ をクリックしてコードを表示し、ダウンロードします。次の表は、データ前処理パイプラインのランタイム フローを説明しています。

関数

説明

ドキュメントと画像の解析、ドキュメントのチャンキング、テキスト埋め込みなど、ドキュメントの処理を行います。

document_pipeline_execute メイン関数がパイプライン全体を実行します。この関数は、ドキュメントの URL または Base64 エンコードされた文字列を受け取ります。

  1. ドキュメント解析 API画像解析 API を使用してドキュメントと画像を解析します。

    • 非同期ドキュメント解析 API を呼び出して、ドキュメントの URL または Base64 エンコードされたファイルからコンテンツを抽出します。

    • 非同期画像解析 API を呼び出して、画像の URL または Base64 エンコードされたファイルからコンテンツを抽出します。

  2. ドキュメントチャンキング API を使用してドキュメントをチャンキングします。

    • ドキュメントチャンキング API を呼び出して、指定された戦略に従って解析済みドキュメントを分割します。

    • document_split 関数はドキュメントを分割し、リッチテキストコンテンツを解析します。

  3. テキスト埋め込み APIスパーステキスト埋め込み API を使用してテキスト埋め込みを生成します。

    • テキスト埋め込み API を呼び出して、チャンキングされたデータを密ベクトルに変換します。

    • スパーステキスト埋め込み API を呼び出して、チャンキングされたデータをスパースベクトルに変換し、その結果を検索エンジンの検索用に書き込みます。

コード照会[ドキュメントの解析とベクトル化] を選択し、コードのコピー または ファイルのダウンロード をクリックして、コードをローカルに保存します。

ステップ 2:環境の設定とパイプラインのテスト

コードをダウンロードした後、次のパラメーターを設定します。

カテゴリ

パラメーター

説明

AI Search Open Platform

api_key

認証用の API キー。API キーの管理

aisearch_endpoint

API エンドポイント。サービスエンドポイントの照会

説明

http:// プレフィックスを削除してください。

API は、インターネット経由または VPC 経由で呼び出すことができます。

workspace_name

AI Search Open Platform のワークスペース名。

service_id

サービス ID。 service_id_config を使用してサービス ID を設定します。

# AI Search Open Platform の設定
api_key = "xxx"
aisearch_endpoint = "xxx.platform-cn-shanghai.opensearch.aliyuncs.com"
workspace_name = "default"
# サービス ID の設定
service_id_config = {"document_analyze": "ops-document-analyze-001", "split": "ops-document-split-001", "text_embedding": "ops-text-embedding-001"}

Python 3.8.1 以降でコードを実行して、結果を確認します。

ドキュメント 「AI Search Open Platform の概要」 を前処理した際のサンプル出力:

C:\Users\issuser\PycharmProjects\pythonProject630Demo\.venv\Scripts\python.exe C:\Users\issuser\PycharmProjects\pythonProject3\.venv\Lib\site-packages\alibabacloud_searchplat2...
document_analyze task_id:f6dd92de-01e4-46a2-96c4-b80e7b120239
document_analyze done
document-split done, chunks count: 6 rich text count:9
image analyze :https://img.alicdn.com/imgextra/i2/O1CN01bYc1m81RrcSAyOjMu_!!6000000002165-54-tps-60-60.apng
https://img.alicdn.com/imgextra/i2/O1CN01bYc1m81RrcSAyOjMu_!!6000000002165-54-tps-60-60.apng is  unanalysable.
image analyze :https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/3873436171/p802381.png
image analyze :https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/0517992271/p821030.png
image analyze ://gw.alicdn.com/tfs/TB16xwdSXXXXXa.aXXXXXXXXXXX-65-70.gif
https://gw.alicdn.com/tfs/TB16xwdSXXXXXa.aXXXXXXXXXXX-65-70.gif is  unanalysable.
image analyze ://img.alicdn.com/tfs/TB1..50QpXXXXX7XpXXXXXXXXXX-40-40.png
image analyze :https://img.alicdn.com/tfs/TB1UdKEM6TpK1RjSZKPXXa3UpXa-256-256.png
image analyze :https://img.alicdn.com/tfs/TB1A0dINW6qK1RjSZFmXXX0PFXa-258-258.jpg
image analyze ://gw.alicdn.com/tfs/TB16xwdSXXXXXa.aXXXXXXXXXXX-65-70.gif
https://gw.alicdn.com/tfs/TB16xwdSXXXXXa.aXXXXXXXXXXX-65-70.gif is  unanalysable.
image analyze ://img.alicdn.com/tfs/TB1..50QpXXXXX7XpXXXXXXXXXX-40-40.png
text-embedding done.
Process finished with exit code 0

完全なパイプラインコード:

# マルチモーダルデータ処理パイプライン
# 要件:
# Python バージョン: 3.8.1 以降
# パッケージ要件:
# pip install alibabacloud_searchplat20240529
# AI Search Open Platform の設定
aisearch_endpoint = "xxx.platform-cn-shanghai.opensearch.aliyuncs.com"
api_key = "OS-xxx"
workspace_name = "default"
service_id_config = {"document_analyze": "ops-document-analyze-001",
                     "split": "ops-document-split-001",
                     "text_embedding": "ops-text-embedding-001",
                     "text_sparse_embedding": "ops-text-sparse-embedding-001",
                     "image_analyze": "ops-image-analyze-ocr-001"}
# 入力ドキュメントの URL。 サンプルドキュメントは AI Search Open Platform の概要です。
document_url = "https://www.alibabacloud.com/help/zh/open-search/search-platform/product-overview/introduction-to-search-platform?spm=a2c4g.11186623.0.0.7ab93526WDzQ8z"
import asyncio
from operator import attrgetter
from typing import List
from Tea.exceptions import TeaException, RetryError
from alibabacloud_tea_openapi.models import Config
from alibabacloud_searchplat20240529.client import Client
from alibabacloud_searchplat20240529.models import GetDocumentSplitRequest, CreateDocumentAnalyzeTaskRequest, \
    CreateDocumentAnalyzeTaskRequestDocument, GetDocumentAnalyzeTaskStatusRequest, \
    GetDocumentSplitRequestDocument, GetTextEmbeddingRequest, GetTextEmbeddingResponseBodyResultEmbeddings, \
    GetTextSparseEmbeddingRequest, GetTextSparseEmbeddingResponseBodyResultSparseEmbeddings, \
    GetImageAnalyzeTaskStatusResponse, CreateImageAnalyzeTaskRequest, GetImageAnalyzeTaskStatusRequest, \
    CreateImageAnalyzeTaskRequestDocument, CreateImageAnalyzeTaskResponse
async def poll_doc_analyze_task_result(ops_client, task_id, service_id, interval=5):
    while True:
        request = GetDocumentAnalyzeTaskStatusRequest(task_id=task_id)
        response = await ops_client.get_document_analyze_task_status_async(workspace_name, service_id, request)
        status = response.body.result.status
        if status == "PENDING":
            await asyncio.sleep(interval)
        elif status == "SUCCESS":
            return response
        else:
            print("error: " + response.body.result.error)
            raise Exception("document analyze task failed")
def is_analyzable_url(url:str):
    if not url:
        return False
    image_extensions = {'.jpg', '.jpeg', '.png', '.bmp', '.tiff'}
    return url.lower().endswith(tuple(image_extensions))
async def image_analyze(ops_client, url):
    try:
        print("image analyze :" + url)
        if url.startswith("//"):
            url = "https:" + url
        if not is_analyzable_url(url):
            print(url + " is  unanalysable.")
            return url
        image_analyze_service_id = service_id_config["image_analyze"]
        document = CreateImageAnalyzeTaskRequestDocument(
            url=url,
        )
        request = CreateImageAnalyzeTaskRequest(document=document)
        response: CreateImageAnalyzeTaskResponse = ops_client.create_image_analyze_task(workspace_name, image_analyze_service_id, request)
        task_id = response.body.result.task_id
        while True:
            request = GetImageAnalyzeTaskStatusRequest(task_id=task_id)
            response: GetImageAnalyzeTaskStatusResponse = ops_client.get_image_analyze_task_status(workspace_name, image_analyze_service_id, request)
            status = response.body.result.status
            if status == "PENDING":
                await asyncio.sleep(5)
            elif status == "SUCCESS":
                return url + response.body.result.data.content
            else:
                print("image analyze error: " + response.body.result.error)
                return url
    except Exception as e:
        print(f"image analyze Exception : {e}")
def chunk_list(lst, chunk_size):
    for i in range(0, len(lst), chunk_size):
        yield lst[i:i + chunk_size]
async def document_pipeline_execute(document_url: str = None, document_base64: str = None, file_name: str = None):
    # AI Search Open Platform クライアントを作成します。
    config = Config(bearer_token=api_key,endpoint=aisearch_endpoint,protocol="http")
    ops_client = Client(config=config)
    # ステップ 1: ドキュメント/画像の解析
    document_analyze_request = CreateDocumentAnalyzeTaskRequest(document=CreateDocumentAnalyzeTaskRequestDocument(url=document_url, content=document_base64,file_name=file_name, file_type='html'))
    document_analyze_response = await ops_client.create_document_analyze_task_async(workspace_name=workspace_name,service_id=service_id_config["document_analyze"],request=document_analyze_request)
    print("document_analyze task_id:" + document_analyze_response.body.result.task_id)
    extraction_result = await poll_doc_analyze_task_result(ops_client, document_analyze_response.body.result.task_id, service_id_config["document_analyze"])
    print("document_analyze done")
    document_content = extraction_result.body.result.data.content
    content_type = extraction_result.body.result.data.content_type
    # ステップ 2: ドキュメントのチャンキング
    document_split_request = GetDocumentSplitRequest(
        GetDocumentSplitRequestDocument(content=document_content, content_type=content_type))
    document_split_result = await ops_client.get_document_split_async(workspace_name, service_id_config["split"],
                                                                      document_split_request)
    print("document-split done, chunks count: " + str(len(document_split_result.body.result.chunks))
          + " rich text count:" + str(len(document_split_result.body.result.rich_texts)))
    # ステップ 3: テキストの埋め込み
    # チャンキング結果を抽出します。 画像チャンクの場合、画像解析サービスがテキストコンテンツを抽出します。
    doc_list = ([{"id": chunk.meta.get("id"), "content": chunk.content} for chunk in document_split_result.body.result.chunks]
                + [{"id": chunk.meta.get("id"), "content": chunk.content} for chunk in document_split_result.body.result.rich_texts if chunk.meta.get("type") != "image"]
                + [{"id": chunk.meta.get("id"), "content": await image_analyze(ops_client,chunk.content)} for chunk in document_split_result.body.result.rich_texts if chunk.meta.get("type") == "image"]
                )
    # 1 回のリクエストで最大 32 個の埋め込みを計算できます。
    chunk_size = 32  
    all_text_embeddings: List[GetTextEmbeddingResponseBodyResultEmbeddings] = []
    for chunk in chunk_list([text["content"] for text in doc_list], chunk_size):
        response = await ops_client.get_text_embedding_async(workspace_name,service_id_config["text_embedding"],GetTextEmbeddingRequest(chunk))
        all_text_embeddings.extend(response.body.result.embeddings)
    all_text_sparse_embeddings: List[GetTextSparseEmbeddingResponseBodyResultSparseEmbeddings] = []
    for chunk in chunk_list([text["content"] for text in doc_list], chunk_size):
        response = await ops_client.get_text_sparse_embedding_async(workspace_name,service_id_config["text_sparse_embedding"],GetTextSparseEmbeddingRequest(chunk,input_type="document",return_token=True))
        all_text_sparse_embeddings.extend(response.body.result.sparse_embeddings)
    for i in range(len(doc_list)):
        doc_list[i]["embedding"] = all_text_embeddings[i].embedding
        doc_list[i]["sparse_embedding"] = all_text_sparse_embeddings[i].embedding
    print("text-embedding done.")
if __name__ == "__main__":
    # 非同期タスクを実行します。
    #    import nest_asyncio # Jupyter Notebook で実行する場合は、次の 2 行のコメントを解除してください。
    #    nest_asyncio.apply() # Jupyter Notebook で実行する場合は、次の 2 行のコメントを解除してください。
    asyncio.run(document_pipeline_execute(document_url))
    # asyncio.run(document_pipeline_execute(document_base64="eHh4eHh4eHg...", file_name="attention.pdf")) # 別の呼び出し方法