地方エンジニアの学習日記

興味ある技術の雑なメモだったりを書いてくブログ。たまに日記とガジェット紹介。

【LLM】ChromaDBとは

www.trychroma.com

ChromaDBは、ベクトルデータを効率的に保存し、検索するためのオープンソースのベクトルデータベースです。特に、機械学習モデルや自然言語処理NLP)で生成される高次元ベクトルを扱うために最適化されています。ChromaDBは、ドキュメントやテキストなどのデータをベクトル形式で保存し、それらのデータ間の類似性検索(Nearest Neighbor Search)を行うことに特化しています。(Chromeに似ていてtypoしそうってこの文章を打ちながら思いましたw)

特徴は以下です。

  • ベクトルの高速検索
    • ChromaDBは、大量の高次元ベクトルに対する類似度検索を効率的に行うために最適化されています。これにより、BERTやGPTなどのモデルで生成されたベクトルを使って、類似するデータを迅速に検索できます。
  • スケーラビリティ: ChromaDBは、大規模なベクトルデータにも対応しており、スケーラブルな形でデータを保存、検索することができます。分散アーキテクチャを採用しているため、クラウド環境や分散システムでの利用も可能です。
  • シンプルなAPI
    • ChromaDBはPythonライブラリとして提供されており、簡単なAPIを使ってデータの挿入や検索を行えます。データサイエンティストやエンジニアが直感的に使える設計です。
    • Goから使うことも一応は可能っぽいです

GitHub - amikos-tech/chroma-go: The Go client for Chroma vector database

  • 多様な検索メソッドのサポート
    • 類似度検索において、L2距離、コサイン類似度など、さまざまな計量手法をサポートしています。ユーザーは、用途に応じて適切な検索手法を選択することができます。

ChromaDBの利用

ChromaDBはクラサバで動かすモードがあるようです。ChromaDBサーバーの起動とかが必要で面倒なのでとりあえずインメモリーの方で動かしてみます。 (とはいえDockerイメージも公開されてるのでシュッと試すことはできそう)

import chromadb

# ChromaDBクライアントの初期化
client = chromadb.Client()

# コレクション(テーブルに相当)を作成
collection = client.create_collection("my_collection")

# サンプルデータ(文とその対応するベクトル)
documents = ["I love machine learning", "Natural language processing is fascinating", "ChromaDB makes vector search easy"]
embeddings = [
    [0.1, 0.2, 0.3],  # 仮のベクトル(実際にはモデルから取得)
    [0.2, 0.1, 0.4],
    [0.4, 0.5, 0.1]
]

# データをコレクションに挿入
collection.add(
    documents=documents,
    embeddings=embeddings,
    ids=["doc1", "doc2", "doc3"]
)

# 類似するベクトルの検索
query_vector = [0.1, 0.2, 0.3]  # クエリとして使用するベクトル
results = collection.query(query_embeddings=[query_vector], n_results=2)

# 検索結果の表示
print("Similar documents:", results["documents"])

【LLM】Embeddingとは

Embedding(エンベディング)とは、情報をコンパクトな数値ベクトル(多くの場合は高次元ベクトル)に変換する技術を指します。主に機械学習自然言語処理の分野で使用され、文章や単語、画像、その他のデータを数値の形で表現することで、コンピュータがそれらを処理しやすくする。ベクトルとかは高校とか大学でもやって気がするけど苦手な分野なので正直難しそうという印象しかない。

atmarkit.itmedia.co.jp

Embeddingのフロー

データ収集と前処理
語彙の作成
単語の数値化
モデルに渡してEmbeddingベクトルを生成
Embeddingベクトルの利用

こんな流れになる。ベクトルデータ自体はどこかに保存するのでそこで出てくるのがベクトルデータベースというやつ。ベクトル検索 SQLite 拡張のsqlite-vecとかPostgreSQLの拡張のpgvectorというのがある。

github.com

github.com

Embeddingのモデル

Embeddingのモデルとは、単語や文章、画像などのデータを数値ベクトルに変換するためのアルゴリズムニューラルネットワークモデルを指します。このモデルは、データ間の意味的・特徴的な関係を捉えるために、ベクトル空間にデータを配置することを目指します。ここでは、特に自然言語処理における代表的なEmbeddingモデルをいくつか見てみます。

Word2Vec

Word2Vecは、自然言語処理で広く使われる単語埋め込みモデルです。Googleによって開発され、2つの主要なアーキテクチャ(CBOWとSkip-Gram)を使用して単語の埋め込みベクトルを学習します。

ja.wikipedia.org

BERT

Googleが開発したトランスフォーマーベースのモデルで、双方向のコンテキスト情報を利用して文脈に基づく単語の埋め込みを学習します。BERTは文全体の意味や単語の前後関係を理解するため、より高度な言語理解が可能とのこと。

ja.wikipedia.org

(Transformerとは、主に自然言語処理NLP)において利用される強力なニューラルネットワークアーキテクチャです。2017年にGoogleによって発表された論文「Attention is All You Need」で初めて紹介され、その後、多くのNLPモデルやタスクにおいて基盤となる技術となっている。)

触ってみる

BERTとpgvectorを使ってベクトルデータ化してデータに突っ込んでみるというのをやってみます

# pgvectorをインストール
psql -c "CREATE EXTENSION IF NOT EXISTS vector;"

pipでライブラリを持ってくる

$ pip install transformers torch psycopg2 numpy

BERTで文をベクトル化する

from transformers import BertTokenizer, BertModel
import torch
import numpy as np

# BERTモデルとトークナイザーをロード
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertModel.from_pretrained('bert-base-uncased')

def encode_text(text):
    # テキストをトークナイズし、BERTでベクトル化
    inputs = tokenizer(text, return_tensors="pt")
    with torch.no_grad():
        outputs = model(**inputs)
    
    # 文全体のベクトルとして[CLS]トークンのベクトルを取得
    cls_embedding = outputs.last_hidden_state[0][0].numpy()
    
    return cls_embedding

# サンプルの文をベクトル化
text = "I love natural language processing"
vector = encode_text(text)
print(f"Vector for the text: {vector}")

ベクトルを保存

import psycopg2
import numpy as np

conn = psycopg2.connect(
    dbname="your_db_name", 
    user="your_username", 
    password="your_password", 
    host="your_host", 
    port="your_port"
)
cur = conn.cursor()
cur.execute("""
CREATE TABLE IF NOT EXISTS text_embeddings (
    id SERIAL PRIMARY KEY,
    text TEXT,
    embedding VECTOR(768)
);
""")
conn.commit()

def insert_embedding(text, vector):
    # ベクトルをPostgreSQLに挿入
    cur.execute("INSERT INTO text_embeddings (text, embedding) VALUES (%s, %s)", (text, vector.tolist()))
    conn.commit()

# サンプルの文とベクトルを挿入
insert_embedding(text, vector)

# 挿入結果の確認
cur.execute("SELECT * FROM text_embeddings;")
rows = cur.fetchall()
for row in rows:
    print(row)

cur.close()
conn.close()

検索もできる

def search_similar_vectors(vector, top_k=5):
    cur = conn.cursor()
    cur.execute("""
    SELECT text, embedding 
    FROM text_embeddings 
    ORDER BY embedding <-> %s 
    LIMIT %s;
    """, (vector.tolist(), top_k))
    
    results = cur.fetchall()
    cur.close()
    return results

# 検索実行
similar_texts = search_similar_vectors(vector)
print(f"Similar texts: {similar_texts}")

【LLM】RAGってなんだ?ってなったので調べた

最近よくきくRAGがなんなのかよくわかっていないので調べたメモ

www.hicareer.jp

最初聞いた時はこっちを思い浮かべたがググっても全く出てこないので取り残されている


目次

RAGとは

生成AIの文脈での「RAG」は、Retrieval-Augmented Generation(検索強化生成)を指します。これは、生成AIモデルが外部データベースや知識ベースから情報を「検索」し、その情報を基に「生成」するアプローチです。この手法を使うことで、モデルがより正確かつ最新の情報を活用した文章生成が可能になります。

RAGの仕組み

  • 検索フェーズ(Retrieval)
    • モデルは、ユーザーの質問や要求に基づき、関連性のある文書や情報をデータベースや知識ベースから検索します。これにより、モデルは外部の豊富な情報源にアクセスし、単なる事前訓練された知識以上の内容を得られるようになります。
  • 生成フェーズ(Generation)
    • 検索された情報を活用し、それを基にユーザーの質問に答えたり、新しいテキストを生成します。生成されたテキストは、検索したデータを考慮しているため、より正確で最新の情報に基づくものになります。

RAGの特徴

  • 検索(Retrieval)と生成(Generation)の統合
    • RAGは、外部の知識ベースやデータベースから情報を「検索」し、その結果を基にテキストを「生成」するプロセスを組み合わせています。このため、モデルが自身の訓練データにない新しい情報にもアクセスでき、最新の知識を活用してテキスト生成を行えます。
  • 高精度な生成
    • 従来の生成モデル(GPTなど)は事前に学習した情報だけに基づいて回答しますが、RAGでは検索された外部データを基にテキストを生成するため、より具体的で正確な情報に基づいた応答を生成できることが特徴です。特に、最新の情報や専門的な知識が必要な場合に有効です。
  • 柔軟性
    • RAGは、複数の情報源にアクセスしてデータを取得できるため、異なるドメインやトピックに柔軟に対応可能です。例えば、技術文書、ニュース、製品情報など、さまざまなタイプのデータベースを利用することで、多様なユーザーのニーズに応じた回答を提供できます。
  • 動的な知識利用
    • RAGは、事前に学習した静的な知識に加えて、検索結果を動的に活用します。これにより、モデルが常に最新の情報を利用でき、時間の経過とともに古くなる情報に依存しない生成が可能です。特に変化の激しい領域(技術、ニュースなど)で有効です。
  • パフォーマンスとリアルタイム性
    • 検索フェーズを含むため、外部データの取得に若干の時間がかかることがありますが、その代わりに正確性や関連性の高い情報を生成できます。応答時間を少し犠牲にする代わりに、より信頼性の高い結果を得るというトレードオフがあります。
  • 多様な情報源の利用
    • RAGは、事前に用意された特定の知識ベースやデータベースだけでなく、ウェブ全体の情報、カスタマイズされた企業内データ、または特定の専門的データベースを利用することも可能です。これにより、利用するデータの幅広さが大きな強みとなります。
  • モデルのサイズ依存性の軽減
    • 従来の大規模生成モデルは、巨大な訓練データを必要とするため、トレーニングコストが高い傾向があります。しかし、RAGでは必要に応じて外部データベースから情報を検索してくるため、モデル自体が極端に大きくなくても十分に高性能な結果を生成できます。

staffing.archetyp.jp

メリデメ

RAGの利点

  • 正確性の向上
    • モデルの事前訓練データだけに依存せず、外部の最新情報にアクセスすることで、事実誤認のリスクを軽減できます。
  • 柔軟性
    • 様々なデータソースから情報を取得できるため、特定分野の質問にも対応しやすくなります。
  • 知識の最新化
    • 生成AIは通常、訓練時点までの情報しか持ちませんが、RAGを使うことで、リアルタイムに最新の情報を反映した生成が可能です。

RAGの欠点

  • 検索精度に依存
    • RAGは検索された情報に基づいてテキストを生成しますが、検索フェーズで不正確または不適切な情報が選ばれた場合、生成された結果も正確性を欠く可能性があります。つまり、検索アルゴリズムの性能や、データベース内の情報の質に強く依存します。
  • 速度の遅さ
    • 外部データベースへの検索や取得プロセスが追加されるため、純粋な生成モデルよりも応答速度が遅くなることがあります。検索に時間がかかると、特にリアルタイム性が求められるアプリケーションではパフォーマンスの問題が生じることがあります。
  • 情報の信頼性
    • 検索した情報の信頼性が問題になることがあります。RAGモデルが使用する外部データベースや知識ベースの情報が正確であるとは限りません。もし不正確な情報を取得した場合、生成されるテキストも誤ったものになる可能性があります。特に、外部ソースに誤情報や古い情報が含まれている場合にはリスクが高くなります。
  • メモリと計算資源の負荷
    • RAGモデルは、生成フェーズと検索フェーズの両方を実行する必要があるため、通常の生成モデルよりもメモリや計算資源を多く必要とします。特に大規模なデータベースに対する検索と複雑な生成を行う場合、計算コストが高くなりがちです。
  • データソースの依存
    • RAGモデルは外部データベースに依存しているため、そのデータソースが利用できなくなる、更新されない、または内容が不十分な場合には、生成の質が著しく低下する可能性があります。データソースの選定や管理が適切に行われていないと、モデルの性能に悪影響を及ぼします。

実際の応用

  • チャットボット
    • ユーザーの質問に対して、外部データベースから情報を検索し、その情報を基に回答を生成する。
  • ドキュメント作成支援
    • 例えば技術文書やリサーチレポートの作成時、関連する文献や資料を検索し、その内容を反映した文章生成が行える。

kuroco.app

RAGの実装

qiita.com

ただ動かすだけならサッとできそう。精度みたいなのを気にした途端に難しくなりそうという感じ。

qiita.com

Amazon Bedrock

business.ntt-east.co.jp

AWS が提供する完全マネージド型の生成AIサービスです。開発者が簡単に大規模な生成AIモデルを利用してアプリケーションを構築、トレーニング、デプロイできるように設計されています。特に、自然言語処理NLP)、テキスト生成、画像生成などの生成AIモデルを活用するためのプラットフォームです。

ai-market.jp

ファインチューニングとの違い

leapwell.co.jp

つらつらと書こうと思っていたがこの例えばすごくしっくりきた。マニュアルを渡しただけの人とOJTとかで教育した人。どっちが良いかはトレードオフが多くあるようでまだまだ研究段階らしい。

その他の用語とか

  • LLM
    • Large Language Modelの略
    • 大規模なデータセットでトレーニングされた自然言語処理NLP)モデルのことを指す
    • 特徴
    • ローカルLLM
      • ユーザーが自身のローカル環境(オンプレミスや個人のコンピュータ、データセンターなど)で実行することを指す
      • データプライバシーの向上やコストの削減あたりに繋がってくる
  • LangChain
  • Embedding
    • データを数値ベクトルに変換する手法
    • 自然言語処理NLP)や機械学習において、テキストや画像、音声などの非数値データを数値形式に変換するために使われる
  • ベクトルデータベース
    • データを数値ベクトルとして保存し、そのベクトル間の距離や類似性に基づいてデータを効率的に検索・管理するためのデータベース
  • 学習
    • 教師あり学習
      • 機械学習の一種で、入力データ(特徴)とそれに対応する正解ラベル(出力)を使ってモデルを学習させる手法
      • 学習時に正解ラベルが与えられるため、モデルは入力と出力の関係を学習し、新しいデータが与えられた際にその関係を基に予測や分類を行う
    • 教師なし学習
      • ラベルのないデータを使って、データ内のパターンや構造を見つけ出す機械学習の手法
      • データセットには正解ラベル(ターゲット)が与えられず、モデルはデータの潜在的な規則性や関係性を発見することを目的とする
  • ニューラルネットワーク
    • 生物の脳神経回路を模倣した計算モデルで、機械学習の一種
    • 複雑なパターンの認識やデータの予測に優れており、近年ではディープラーニングの基礎として、多くの分野で活用されている

参考

【PostgreSQL】物理レプリケーションとは

www.fujitsu.com

PostgreSQLの物理レプリケーションは、データベースの物理的なデータ(つまり、ディスク上のバイナリファイル)を基にデータベース全体を複製し、データベースの可用性やデータの冗長性を確保する方法です。これは、マスターサーバー(プライマリ)からスレーブサーバー(スタンバイ)にWAL(Write-Ahead Log)を送信し、それをリプレイしてスタンバイサーバーをプライマリと同じ状態に保つ仕組みです。

物理レプリケーションの概要

WAL (Write-Ahead Log) の利用: PostgreSQLは、すべてのデータ変更をWALに記録します。物理レプリケーションでは、プライマリサーバー上のWALがスタンバイサーバーにストリームされ、スタンバイ側でリプレイされます。これにより、スタンバイサーバーがプライマリサーバーの状態と同期されます。

同期レプリケーションと非同期レプリケーション: 物理レプリケーションには、同期と非同期の2種類のモードがあります。

非同期レプリケーション: WALの変更がプライマリサーバーからスタンバイサーバーに送られますが、プライマリはスタンバイがその変更を受け取るのを待たずに次の処理を続行します。この方式は高いパフォーマンスが得られますが、スタンバイがプライマリに追いつく前に障害が発生するとデータが失われる可能性があります。

同期レプリケーション: プライマリサーバーがトランザクションをコミットする前に、スタンバイサーバーがその変更を確実に受け取ったことを確認します。これにより、データの一貫性が高まりますが、遅延が増加する可能性があります。

スタンバイサーバーの役割: スタンバイサーバーは通常、プライマリサーバーのフェイルオーバー目的で使用されます。プライマリが障害を起こした場合、スタンバイサーバーをプライマリサーバーに昇格させることができます。この操作は手動または自動で行うことができます。

スタンバイサーバーを作成する際、プライマリサーバーのデータ全体を物理的にコピーします(ベースバックアップ)。 スタンバイサーバーはその後、プライマリサーバーからWALを受け取り、リプレイしてデータを最新の状態に保ちます。 ホットスタンバイ: 物理レプリケーションを使用する場合、スタンバイサーバーはリードオンリークエリを受け付けることが可能です。この設定を「ホットスタンバイ」と呼び、スタンバイサーバーをバックアップ目的だけでなく、リードクエリを分散させるためにも使用できます。

高可用性: プライマリサーバーがダウンした場合、スタンバイサーバーにフェイルオーバーすることで、ダウンタイムを最小限に抑えられます。

データの整合性: 同期レプリケーションを使うことで、データの整合性が確保され、スタンバイサーバーがプライマリサーバーと完全に同期された状態で維持されます。

負荷分散: ホットスタンバイを使用することで、リードオンリークエリをスタンバイサーバーで処理し、プライマリサーバーの負荷を軽減できます。

  • 物理レプリケーションの欠点 データ転送量の増加: WALのストリーミングにより、ネットワーク帯域が消費されます。トランザクションの量が多い場合、WALが頻繁に転送されるため、ネットワーク負荷が高くなる可能性があります。

スタンバイサーバーのディスク消費: スタンバイサーバーもプライマリサーバーと同じ量のディスクスペースを消費します。WALの履歴も保存されるため、ディスク容量の管理が重要です。

まとめ

PostgreSQLの物理レプリケーションは、WALを使ってプライマリサーバーとスタンバイサーバーのデータを同期し、フェイルオーバーや負荷分散、高可用性を実現するための重要な仕組みです。データの一貫性と冗長性を確保しつつ、運用の効率を向上させるために、多くの企業で利用されています。