🔢

ベクトル埋め込みと検索のプロトタイプについて

に公開

背景

本番環境でQdrant、Chroma、Faiss、PineconeなどのベクトルDBの導入を前提として、まずは、Azure OpenAI埋め込みとドキュメント検索のチュートリアルを参考にしながら、ローカル環境でCopilotに生成してもらったMarkdownファイルを使って、それに対応するベクトルデータの扱いが理解できるように、特定のJSONファイルに保存し、そのJSONファイルからベクトル検索を試しました。

対象読者

  • ベクトルの基本概念を理解している方
  • RAG導入を検討している方

環境

項目 バージョン
OS Windows 11 Pro
ランタイム Python: 3.13.2
主要ライブラリ langchain 0.3.25、numpy 2.3.0、openai 1.85.0、python-dotenv 1.1.0、tiktoken 0.9.0
モデル Azure OpenAI text-embedding-3-small

参照:Azure OpenAIテキスト埋め込みモデル

事前準備

今度研究のため、markdown_filesというフォルダーの以下、10件のmarkdownファイルをCopilotに生成してもらいました。その10件は以下のようです。

  1. AIエージェントの構築.md
  2. AIエージェントの種類.md
  3. AIとは.md
  4. エクササイズのメリット.md
  5. プログラミング言語.md
  6. 学校とは.md
  7. 最先端技術.md
  8. 新幹線.md
  9. 世界遺産とは.md
  10. 日本の有名な観光地.md

※ それぞれファイルの内容は、こちらの記事に乗せるとすごく長くなりますので、こちらには省略させていただきます。

プロジェクトの全体像

登録

  1. Markdown形式のサンプルデータをローカルフォルダーから取得します。
  2. 次に、各ページのデータを取得し、見出しごとにセクションの分割をします。
  3. 各セクションの見出しや本文は、ベクトル化の前に、指定されたチャンクサイズごとに分割しています。
  4. 分割されたチャンクごとにベクトル化を行います。
  5. 見出しや本文のテキストデータと、それに対応するベクトルデータを、モックDBとしてJSON形式でローカルファイルに保存します。

検索

  1. モックDBから、データを読み込みます。
  2. ユーザーの入力クエリと既存データとのコサイン類似度を計算します。
  3. 計算されたコサイン類似度の値の中、上位の結果を抽出します。
  4. その検索結果をJSONファイルとして保存します。

プロジェクト構造

./
├── markdown_files #Copilotに生成してもらったmarkdownファイルのフォルダー
├── .env #環境変数の設定ファイル
├── extract_top.py #上位結果の抽出
├── generate_json_file.py #モックDB生成
├── json_generator.py #JSONデータ生成
├── md_file_handler.py #サンプルデータ取得
├── requirements.txt #必須のパッケージ
├── section_handler.py #セクションごと分割
├── split_markdown.py #mdファイルの分割
├── split_text.py #チャンクの分割
├── token_check.py #トークン数の計算
├── vector_embed.py #ベクトル埋め込み
└── vector_similarity.py #コサイン類似度の計算

手順

1. pythonパッケージのインストール

  • スクリプトと同じ階層に、依存パッケージを記載した requirements.txt ファイルを用意しました。
  • requirements.txtファイルの中は以下のようです。
requirements.txt
langchain
numpy
openai
python-dotenv
tiktoken
  • 下記のコマンドを実行することで、requirements.txtに記載された依存パッケージをインストールできます。
pip install -r requirements.txt
  • ローカルでインストールされた全てのpythonパッケージをpip listコマンドで確認出来ます。
C:\Users\...\...> pip list
Package                  Version
...
langchain                0.3.25
numpy                    2.3.0
openai                   1.85.0
python-dotenv            1.1.0
tiktoken                 0.9.0

※2025年6月10日現在※

2. .envの設定

AZURE_OPENAI_API_KEY = '' # テキストモデルのAPIキー
AZURE_OPENAI_ENDPOINT = '' # Azure OpenAIのエンドポイント

登録用のサンプルコード

前述のプロジェクト構造の中、登録用のスクリプトは以下のようです。

  1. md_file_handler.py
  2. split_markdown.py
  3. section_handler.py
  4. split_text.py
  5. vector_embed.py
  6. token_check.py
  7. json_generatior.py
  8. generate_json_file.py「※ mainメソッドが存在する」

① ファイル読み込み

ローカルフォルダーから複数のMarkdownファイルを読み込むスクリプトです。

md_file_handler.py
import os

def read_files_as_list(folder_path) -> list[str]:
    """
    指定されたフォルダー内のすべてのファイルを読み込み、その内容を文字列のリストとして返します。
    Args:
        folder_path (str): 読み込むファイルが含まれるフォルダーのパス
    Returns:
        file_contents (list[str]): 各要素がファイル内容の文字列であるリスト
    """
    file_contents = []
    
    # フォルダーが存在するかを確認する
    if not os.path.exists(folder_path):
        print(f"フォルダーは見つかりません: {folder_path}")
        return file_contents

    for filename in os.listdir(folder_path):
        file_path = os.path.join(folder_path, filename)

        if os.path.isfile(file_path):
            with open(file_path, 'r', encoding='utf-8') as file:
                content = file.read()
                file_contents.append(content)

    return file_contents

② セクションの分割

マークダウンファイルを見出し単位で分割するスクリプトです。

split_markdown.py
from langchain_text_splitters import MarkdownHeaderTextSplitter
from langchain.schema import Document

def split(file: str) -> list[Document]:
   """マークダウンファイルを見出し単位で分割する
    Args:
        file: マークダウンファイル
    Returns:
        documents: 分割されたドキュメント配列
    """ 
   # セクションを分ける見出しの定義
   headers_to_split_on = [("#", "header1"), ("##", "header2"), ("###", "header3")]

   # Markdown見出しの分割設定
   markdown_splitter = MarkdownHeaderTextSplitter(headers_to_split_on=headers_to_split_on)

   # Markdownファイルの分割
   documents = markdown_splitter.split_text(file)
   
   return documents

ドキュメントを見出し単位のセクションごとに分割するスクリプトです。

section_handler.py
from langchain.schema import Document

import json_generatior

def split_sections(docs: list[Document]) -> list[dict]:
    """ドキュメントをセクションごとに分割する
    Args:
        docs: 分割するドキュメントのリスト
    Returns:
        section_list: セクションごとに分割されたドキュメントのリスト
    """
    header1_text = None
    header2_text = None
    header3_text = None
    page_content_text = None

    header1 = None
    header2 = None
    header3 = None
    page_content = None

    section_list = []

    for doc in docs:
        # print(doc.page_content)
        if doc.metadata.get("header1"):
            header1_text = doc.metadata["header1"]
        if doc.metadata.get("header2"):
            header2_text = doc.metadata["header2"]
        if doc.metadata.get("header3"):
            header3_text = doc.metadata["header3"]
        if doc.page_content:
            page_content_text = doc.page_content

        if (page_content_text) or (not page_content_text.startswith("---")):
            if header1_text is not None:
                header1 = json_generatior.create(header1_text)

            if header2_text is not None:
                header2 = json_generatior.create(header2_text)

            if header3_text is not None:
                header3 = json_generatior.create(header3_text)

            if page_content_text is not None:
                page_content = json_generatior.create(page_content_text)

            section = {
                "header1": header1,
                "header2": header2,
                "header3": header3,
                "pageContent": page_content,
            }
            section_list.append(section)
    return section_list

③ チャンク区切り

テキストを指定のチャンクサイズと重複設定で分割するスクリプトです。

split_text.py
from langchain_text_splitters import RecursiveCharacterTextSplitter

def split(text, chunk_size=1000, chunk_overlap=200):
    """
    入力テキストを指定したサイズで重複しながら分割します。
    Args:
        text (str): 分割する入力テキスト
        chunk_size (int, オプション): 各チャンクの最大サイズ。デフォルトは1000
        chunk_overlap (int, オプション): 連続するチャンク間の重複文字数。デフォルトは200
    Returns:
        out: 分割されたテキストチャンクのリスト
    """
    # チャンクサイズの設定
    splitter = RecursiveCharacterTextSplitter(chunk_size=chunk_size, chunk_overlap=chunk_overlap)
    # チャンクサイズ設定による文書分割の処理
    return splitter.split_text(text)

④ ベクトル化

入力テキストのベクトル埋め込みを生成するスクリプトです。

vector_embed.py
from openai import AzureOpenAI
from dotenv import load_dotenv

# .envファイルをロードする
load_dotenv()

client = AzureOpenAI(
    api_key = os.getenv("AZURE_OPENAI_API_KEY"),
    api_version = '2024-10-21', # https://learn.microsoft.com/ja-jp/azure/ai-services/openai/supported-languages?tabs=dotnet-secure%2Csecure%2Cpython-secure%2Ccommand&pivots=programming-language-python#azure-openai-api-version-support
    azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")
)

def create_embeddings(text: str | list[str], model="text-embedding-3-small") -> list[float]:
    """
    指定されたモデルを使用して、入力テキストの埋め込みを生成します。
    Args:
        text (str | list[str]): テキストまたはテキストのリスト
        model (str, オプション): 埋め込みモデル名(デフォルトは "text-embedding-3-small")
    Returns:
        list[float]: 埋め込みベクトル
    """ 
    return client.embeddings.create(
        input=text,
        model=model
    ).data[0].embedding

トークン数の確認「任意」

入力テキストのトークン数を計算するスクリプトです。トークン数は、あるメーターデータとして保存していますが、必須ではありません。

token_check.py
import tiktoken

# トークナイザーの設定
# "cl100k_base"は、text-embedding-3-large、GPT-4、GPT-3.5 などのOpenAIモデルで使用されているトークナイザー
tokenizer = tiktoken.get_encoding("cl100k_base")

def calculate_token_length(input_text: str) -> int:
    """入力テキストのトークン数を計算する
    Args:
        input_text: 入力テキスト
    Returns:
        len(tokens): トークン数
    """ 
    # トークン化する
    tokens = tokenizer.encode(input_text)
   
    # トークン数を渡す
    return len(tokens)

⑤ JSON形式でローカルファイルに保存

各見出しや本文などのテキスト、トークン数、ベクトル埋め込み配列を辞書型またはJSON形式で整理するスクリプトです。

json_generatior.py
import split_text
import token_check
import vector_embed

def create(text: str) -> dict:
    """ローカルに保存するためのJSONデータを生成する
    Args:
        text: テキスト
    Returns:
        テキスト、トークン数、ベクトル埋め込み配列のJSONデータ
    """
    # トークン数の確認
    token_length = token_check.calculate_token_length(text)

    # テキストをチャンクに分ける
    text_chunks = split_text.split(text)

    # テキストとトークン数のJSONデータ
    result = {
        "text": text,
        "tokenLength": token_length,
        "embeddingsArray": [
            vector_embed.create_embeddings(chunk) for chunk in text_chunks
        ],
    }
    return result

モックDBの生成プログラム

上記の①から⑤のステップをまとめ、Markdownファイルの読み込みから、各見出しや本文などのテキスト、トークン数、ベクトル埋め込み配列JSON形式で整理し、指定したファイルパスに保存するスクリプトです。

generate_json_file.py
import json
import os
from dotenv import load_dotenv
import time

import md_file_handler
import section_handler
import split_markdown

# .envファイルをロードする
load_dotenv()

# ファイルパースの設定
file_path = os.path.join(os.getcwd(), "MKDB_20250612", "sections.json")


def main():
    """
    マークダウンファイルを読み込み、セクションごとに分割し、結果をJSONファイルとして保存する処理を行います。
    この関数は以下の手順を実行します:
    1. "markdown_files" ディレクトリからすべてのマークダウンファイルを読み込む。
    2. 各ファイルをセクションごとに分割する。
    3. 処理の実行時間を計測・表示する。
    4. 得られたセクションを指定したファイルパスにJSON形式で保存する。
    依存関係:
        - md_file_handler: マークダウンファイルの読み込み用モジュール
        - split_markdown: マークダウン内容の分割用モジュール
        - section_handler: 分割したドキュメントからセクションを抽出するモジュール
        - os, time, json: 標準Pythonライブラリ
    注意:
        変数 `file_path` やインポートしたモジュールはコード内で定義されている必要があります。
    """

    files = md_file_handler.read_files_as_list("markdown_files")
    sections = []
    start_time = time.time()
    # 各ファイルを分割してセクションを取得する
    for file in files: 
        print(f"インデックス: {files.index(file)}")
        # ファイルを分割してセクションを取得
        splitted_docs = split_markdown.split(file)
        sections.extend(section_handler.split_sections(splitted_docs, files.index(file)))
    end_time = time.time()
    execution_time = end_time - start_time
    print(f"登録実行時間: {execution_time:.4f} 秒")

    os.makedirs(os.path.dirname(file_path), exist_ok=True)

    with open(file_path, "w", encoding="utf-8") as file:
        json.dump(sections, file, ensure_ascii=False, indent=4)


if __name__ == "__main__":
    main()


登録結果

  • MKDB_20250612のフォルダーの以下でsections.jsonとうファイルが生成されました。
  • 実行時間148.9533 秒かかりました。

各項目の形式

生成されたJSONファイルの各項目の形式は以下のようです。

{
    "pg_id": 数字型のページid,
    "header1": {
        "text": "...",
        "tokenLength": トークン数,
        "embeddings": [...]   
    },
    "header2": null,
    "header3": null,
    "pageContent": {
        "text": "...",
        "tokenLength": トークン数,
        "embeddings": [...]  
}            

生成されたJSONファイルを垣間見ると

sections.json
[
    {
        "pg_id": 0,
        "header1": {
            "text": "AI とは?—人工知能の基礎とその可能性",
            "tokenLength": 18,
            "embeddingsArray": [
                [
                    -0.0068137021735310555,
                    0.004677916411310434,
                    ...
                ]
            ]
        },
        "header2": {
            "text": "はじめに",
            "tokenLength": 4,
            "embeddingsArray": [
                [
                    0.007865370251238346,
                    -0.0275938231498003,
                    ...
                ]
            ]
        },
        "header3": null,
        "pageContent": {
            "text": "AI(人工知能)は、近年急速に発展し、私たちの生活や仕事のあらゆる場面に影響を与えています。しかし、「AI とは何か?」と聞かれると、明確に答えるのは意外と難しいかもしれません。本記事では、AI の基本的な概念から、種類、活用例、そして今後の展望までをわかりやすく解説します。  \n---",
            "tokenLength": 139,
            "embeddingsArray": [
                [
                    -0.017028581351041794,
                    -0.01099900621920824,
                    ...
                ]
            ]
        },
    },
    {
        "pg_id": 0,
        "header1": {
            "text": "AI とは?—人工知能の基礎とその可能性",
            "tokenLength": 18,
            "embeddingsArray": [
                [
                    -0.0068137021735310555,
                    0.004677916411310434,
                    ...
                ]
            ]
        },
        "header2": {
            "text": "AI の定義",
            "tokenLength": 5,
            "embeddingsArray": [
                [
                    -0.017520831897854805,
                    0.022861799225211143,
                    ...
                ]
            ]
        },
        "header3": null,
        "pageContent": {
            "text": "**人工知能(Artificial Intelligence, AI)**とは、人間のように「学習」「推論」「判断」「問題解決」などの知的な活動をコンピュータに行わせる技術のことです。AI は、単なるプログラムとは異なり、経験から学び、状況に応じて柔軟に対応する能力を持ちます。  \n---",
            "tokenLength": 129,
            "embeddingsArray": [
                [
                    -0.0035273318644613028,
                    -0.008726497180759907,...
                ]
            ]
        },
    },
    ...
]       

検索用のサンプルコード

前述のプロジェクト構造の中、検索用のスクリプトは以下のようです。

  1. vector_similarity.py
  2. vector_embed.py
  3. extract_top.py「※ mainメソッドが存在する」

コサイン類似度の計算

ユーザークエリのベクトルとベクトル埋め込みリストの各要素とのコサイン類似度を計算して返すスクリプトです。

vector_similarity.py
import numpy as np

def cosine_similarity(a: list[float], b: list[float]):
    """コサイン類似度を計算して返す"""
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))


def calculate_similarities(user_query_embedding: list[float], embeddings_list: list[list[float]])-> list[float]:
    """ユーザークエリのベクトルとベクトル埋め込みリストの各要素とのコサイン類似度を計算して返す
    Args:
        user_query_embedding (list[float]): クエリのベクトル埋め込み
        embeddings_list (list[list[float]]): ベクトル埋め込みリスト
    Returns:
        similarity_values (list[float]):コサイン類似度のリスト
    """
    similarity_values = []
    for embeddings in embeddings_list:
        similarity_value = cosine_similarity(user_query_embedding, embeddings)
        similarity_values.append(similarity_value)
    return similarity_values

検索実行のスクリプト

セクション情報を含むJSONデータを処理し、クエリと各セクションの見出し・本文のベクトル埋め込み間のコサイン類似度を計算し、上位の結果を抽出するメインスクリプトです。
スクリプト内で、以下の処理を行いました。

  1. モックDBの生成プログラムで生成されたMKDB_20250612以下のsections.jsonを読み込む。
  2. ユーザークエリとして、「よく使うプログラミング言語」を引数として渡す。
  3. そのクエリをベクトル化する。
  4. そのクエリのベクトル埋め込みとheader1, header2, header3, pageContentのベクトル埋め込み間のコサイン類似度を計算します。
  5. 最も高い類似度スコアと該当するセクション種別を特定する。
  6. 類似度確認した全結果の保存ファイルをMKDB_20250612/resultsの下でよく使うプログラミング言語-all.jsonというファイル名にする。
  7. 類似度確認した上位5件の結果の保存ファイルをMKDB_20250612/topの下でよく使うプログラミング言語-top_5.jsonというファイル名にする。
extract_top.py
import json
import os
import time

import vector_embed
import vector_similarity

# ファイルパスの定義
file_path = os.path.join(os.getcwd(), "MKDB_20250612", "sections.json")

# 類似度確認した全結果ファイル
all_results_path = os.path.join(
    os.getcwd(), "MKDB_20250612/results", "merits of exercise-all.json"
)

# 類似度確認した上位5件の結果ファイル
top_file_path = os.path.join(
    os.getcwd(), "MKDB_20250612/top", "merits of exercise-top_5.json"
)


def get_which_cosine(value):
    """
    インデックス値から対応するコサイン類似度の変数名を返す関数。
    Args:
        value (int): インデックス(0, 1, 2, 3 のいずれか)。
    Returns:
        str: インデックスに対応するコサイン変数名("pg_cos", "h1_cos", "h2_cos", "h3_cos")。
    Raises:
        ValueError: 入力値が想定外の場合に発生。
    """

    match value:
        case 0:
            return "pg_cos"
        case 1:
            return "h1_cos"
        case 2:
            return "h2_cos"
        case 3:
            return "h3_cos"
        case _:
            raise ValueError("インデックス値が不正です(0〜3のみ有効)")


def main():
    """
    セクション情報を含むJSONデータを処理し、クエリと各セクションの見出し・本文のベクトル埋め込み間のコサイン類似度を計算し、上位の結果を抽出するメイン関数
    ワークフロー:
    1. 指定されたJSONファイルが存在するか確認し、内容を読み込む。
    2. 各セクションごとに以下を実施:
        - クエリとheader1, header2, header3, pageContentのベクトル埋め込みとのコサイン類似度を計算する。
        - 最も高い類似度スコアとその該当セクション種別を特定する。
        - 類似度スコアや関連テキストを含む結果を収集する。
    3. 全結果を類似度順にソートし、上位5件を抽出する。
    4. 全結果と上位5件の結果をそれぞれJSONファイルに保存する。
    5. 検索処理の実行時間を表示する。
    必要なもの:
    - `file_path`: 入力JSONファイルのパス
    - `all_results_path`: 全結果保存先パス
    - `top_file_path`: 上位5件保存先パス
    - `vector_embed.create_embeddings`: ベクトル生成関数
    - `vector_similarity.calculate_similarities`: コサイン類似度計算関数
    - `get_which_cosine`: インデックスからセクション種別を返す関数
    - 必要なインポート: os, json, time, カスタムモジュール等
    """

    # ファイルが存在するか確認
    if os.path.exists(file_path):
        with open(file_path, "r", encoding="utf-8") as file:
            sections = json.load(file)

    results = []

    query = "merits of exercise"
    

    h1_cs = []
    h2_cs = []
    h3_cs = []
    pg_cs = []

    query_embed_start_time = time.time()
    # ユーザークエリのベクトル化
    query_embedding = vector_embed.create_embeddings(query)

    query_embed_end_time = time.time()
    query_embed__time = query_embed_end_time - query_embed_start_time
    
    print(f"クエリ埋め込みの実行時間: {query_embed__time:.4f} 秒")
    
    start_time = time.time()
    for section in sections:
        print(f"ページID: {json.dumps(section['pg_id'], indent=4)}")
        header1 = section["header1"]
        header2 = section["header2"]
        header3 = section["header3"]
        page_content = section["pageContent"]

        # 見出しごとのコサイン類似度計算
        if header1 is not None:
            h1_cs = vector_similarity.calculate_similarities(
                query_embedding, header1["embeddingsArray"]
            )
        if header2 is not None:
            h2_cs = vector_similarity.calculate_similarities(
                query_embedding, header2["embeddingsArray"]
            )
        if header3 is not None:
            h3_cs = vector_similarity.calculate_similarities(
                query_embedding, header3["embeddingsArray"]
            )

        pg_cs = vector_similarity.calculate_similarities(
            query_embedding, page_content["embeddingsArray"]
        )

        cos_similarities = [pg_cs]
        if header1 is not None:
            cos_similarities.append(h1_cs)
        if header2 is not None:
            cos_similarities.append(h2_cs)
        if header3 is not None:
            cos_similarities.append(h3_cs)

        largest_list = []
        for i in cos_similarities:
            # 例:[[0.4562, 0.1236],[0.478, 0.155], [0.623, 0.721]]
            if len(i) == 1:
                largest_list.append(i[0])
            else:
                largest_list.append(max(i))
        largest_one = max(largest_list)
        index_of_largest = largest_list.index(largest_one)
        which_cos = get_which_cosine(index_of_largest)

        result = {
            "pg_id": section["pg_id"],
            "largestSimilarity": largest_one,
            "whichCos": which_cos,
            "header1": header1["text"] if header1 is not None else None,
            "h1_cs": h1_cs,
            "header2": header2["text"] if header2 is not None else None,
            "h2_cs": h2_cs,
            "header3": header3["text"] if header3 is not None else None,
            "h3_cs": h3_cs,
            "pageContent": section["pageContent"]["text"],
            "pg_cs": pg_cs,
        }
        results.append(result)

    # コサイン類似度が高い上位5件
    top_5 = sorted(results, key=lambda x: x["largestSimilarity"], reverse=True)[:5]
    
    end_time = time.time()
    execution_time = end_time - start_time

    print(f"検索実行時間: {execution_time:.4f} 秒")

    # 全結果を保存
    os.makedirs(os.path.dirname(all_results_path), exist_ok=True)
    with open(all_results_path, "w", encoding="utf-8") as file:
        json.dump(results, file, ensure_ascii=False, indent=4)

    # 上位5件を保存
    os.makedirs(os.path.dirname(top_file_path), exist_ok=True)
    with open(top_file_path, "w", encoding="utf-8") as file:
        json.dump(top_5, file, ensure_ascii=False, indent=4)


if __name__ == "__main__":
    main()

検索結果

  • 全結果のためは、MKDB_20250612/resultsの下でよく使うプログラミング言語-all.jsonとうファイルが生成されました。
  • 上位5件の結果のためは、MKDB_20250612/topの下でよく使うプログラミング言語-top_5.jsonとうファイルが生成されました。
  • クエリの埋め込み1.2344 秒かかりました。
  • 検索実行時間0.1075 秒でした。
  • 事前準備でCopilotに生成してもらった10件のMarkdownファイルの中、抽出された上位5件は、5番目のプログラミング言語.mdファイルからのを観察できます。

全結果のJSONファイルを垣間見ると

よく使うプログラミング言語-all.json
[
    {
        "pg_id": 0,
        "largestSimilarity": 0.21868106244565133,
        "whichCos": "h1_cos",
        "header1": "AI とは?—人工知能の基礎とその可能性",
        "h1_cs": [
            0.21868106244565133
        ],
        "header2": "はじめに",
        "h2_cs": [
            0.16903663413144063
        ],
        "header3": null,
        "h3_cs": [],
        "pageContent": "AI(人工知能)は、近年急速に発展し、私たちの生活や仕事のあらゆる場面に影響を与えています。しかし、「AI とは何か?」と聞かれると、明確に答えるのは意外と難しいかもしれません。本記事では、AI の基本的な概念から、種類、活用例、そして今後の展望までをわかりやすく解説します。  \n---",
        "pg_cs": [
            0.1897110790449392
        ]
    },
    {
        "pg_id": 0,
        "largestSimilarity": 0.2588618422776396,
        "whichCos": "h2_cos",
        "header1": "AI とは?—人工知能の基礎とその可能性",
        "h1_cs": [
            0.21868106244565133
        ],
        "header2": "AI の定義",
        "h2_cs": [
            0.2588618422776396
        ],
        "header3": null,
        "h3_cs": [],
        "pageContent": "**人工知能(Artificial Intelligence, AI)**とは、人間のように「学習」「推論」「判断」「問題解決」などの知的な活動をコンピュータに行わせる技術のことです。AI は、単なるプログラムとは異なり、経験から学び、状況に応じて柔軟に対応する能力を持ちます。  \n---",
        "pg_cs": [
            0.20983305205117078
        ]
    },
    {
        "pg_id": 0,
        "largestSimilarity": 0.27154733821715543,
        "whichCos": "h2_cos",
        "header1": "AI とは?—人工知能の基礎とその可能性",
        "h1_cs": [
            0.21868106244565133
        ],
        "header2": "AI の種類",
        "h2_cs": [
            0.27154733821715543
        ],
        "header3": null,
        "h3_cs": [],
        "pageContent": "AI は大きく分けて以下の 3 つのタイプに分類されます。",
        "pg_cs": [
            0.12400079765648551
        ]
    },
    ...
]

上位5件の結果のJSONファイルの中身

よく使うプログラミング言語-top_5.json
[
    {
        "pg_id": 4,
        "largestSimilarity": 0.7125444247296953,
        "whichCos": "h1_cos",
        "header1": "プログラミング言語とは",
        "h1_cs": [
            0.7125444247296953
        ],
        "header2": null,
        "h2_cs": [
            0.15642984265459162
        ],
        "header3": null,
        "h3_cs": [
            0.22195831263399685
        ],
        "pageContent": "プログラミング言語は、コンピュータに命令を与えるための言語です。人間が理解しやすい形式で記述し、それをコンピュータが実行可能な形に変換することで、さまざまなソフトウェアやアプリケーションが動作します。  \n---",
        "pg_cs": [
            0.6123948439743047
        ]
    },
    {
        "pg_id": 4,
        "largestSimilarity": 0.7125205977444146,
        "whichCos": "h1_cos",
        "header1": "プログラミング言語とは",
        "h1_cs": [
            0.7125205977444146
        ],
        "header2": "💡 プログラミング言語の目的",
        "h2_cs": [
            0.6909023515228951
        ],
        "header3": null,
        "h3_cs": [
            0.22195831263399685
        ],
        "pageContent": "プログラミング言語は以下のような目的で使用されます:  \n- **ソフトウェア開発**:アプリケーションやゲーム、Web サービスなどを作成。\n- **データ処理**:大量のデータを分析・処理。\n- **自動化**:繰り返し作業の効率化。\n- **教育・研究**:アルゴリズムや論理的思考の学習。  \n---",
        "pg_cs": [
            0.6327993719253637
        ]
    },
    {
        "pg_id": 4,
        "largestSimilarity": 0.7125205977444146,
        "whichCos": "h1_cos",
        "header1": "プログラミング言語とは",
        "h1_cs": [
            0.7125205977444146
        ],
        "header2": "🧩 主なプログラミング言語と特徴",
        "h2_cs": [
            0.6978904572319633
        ],
        "header3": null,
        "h3_cs": [
            0.22195831263399685
        ],
        "pageContent": "| 言語名     | 特徴                                            | 主な用途                     |\n| ---------- | ----------------------------------------------- | ---------------------------- |\n| Python     | シンプルで読みやすい文法。豊富なライブラリ。    | データ分析、AI、Web 開発     |\n| JavaScript | Web ブラウザ上で動作。動的な Web ページを作成。 | フロントエンド開発           |\n| Java       | オブジェクト指向。クロスプラットフォーム対応。  | 業務システム、Android アプリ |\n| C/C++      | 高速でハードウェアに近い制御が可能。            | 組み込み開発、ゲーム開発     |\n| Ruby       | 書きやすく、初心者に優しい。                    | Web アプリ(Ruby on Rails)  |\n| Go         | シンプルで高速な並行処理が得意。                | サーバーサイド、クラウド開発 |  \n---",
        "pg_cs": [
            0.622680059016323
        ]
    },
    {
        "pg_id": 4,
        "largestSimilarity": 0.7125205977444146,
        "whichCos": "h1_cos",
        "header1": "プログラミング言語とは",
        "h1_cs": [
            0.7125205977444146
        ],
        "header2": "🛠️ プログラミング言語の分類",
        "h2_cs": [
            0.6435157725796018
        ],
        "header3": null,
        "h3_cs": [
            0.22195831263399685
        ],
        "pageContent": "プログラミング言語は、いくつかの観点で分類されます:  \n- **コンパイル型 vs インタプリタ型**  \n- コンパイル型:C, C++(事前に機械語に変換)\n- インタプリタ型:Python, JavaScript(逐次実行)  \n- **手続き型 vs オブジェクト指向型**  \n- 手続き型:C(命令の順序で処理)\n- オブジェクト指向型:Java, Python(データと処理を一体化)  \n- **静的型付け vs 動的型付け**\n- 静的型付け:Java, C++(変数の型を明示)\n- 動的型付け:Python, Ruby(実行時に型が決定)  \n---",
        "pg_cs": [
            0.5930413541604844
        ]
    },
    {
        "pg_id": 4,
        "largestSimilarity": 0.7125205977444146,
        "whichCos": "h1_cos",
        "header1": "プログラミング言語とは",
        "h1_cs": [
            0.7125205977444146
        ],
        "header2": "🚀 プログラミング言語の選び方",
        "h2_cs": [
            0.697364453864034
        ],
        "header3": null,
        "h3_cs": [
            0.22195831263399685
        ],
        "pageContent": "目的や用途に応じて、適切な言語を選ぶことが重要です:  \n- **初心者向け**:Python, Scratch\n- **Web 開発**:HTML/CSS + JavaScript + フレームワーク(React, Vue など)\n- **モバイルアプリ**:Swift(iOS)、Kotlin(Android)\n- **ゲーム開発**:C++, C#, Unity  \n---",
        "pg_cs": [
            0.5452092767061049
        ]
    }
]

まとめ & 次のステップ

  • 今度のプロジェクトでは、ベクトルDBを使わずに、ローカルでの登録と検索を行いました。登録と検索実行時間はそれぞれ148.9533 秒0.1075 秒でした。
  • 次は、同じデータを使い、Qdrant、Chroma、Faiss、Pinecone、それぞれのベクトルDBの登録、取得、検索などの結果を比較してみます。

参考リンク

セリオ株式会社 テックブログ

Discussion