💡 何がTxtai 4.0で新しいですか



この記事はチュートリアルシリーズの一部ですtxtai , AI動力セマンティック検索プラットフォーム
txtai データを変換し、AIで動く意味の検索アプリケーションを構築するために、機械学習ワークフローを実行します.
Txtai 4.0は、主要な機能強化の数をもたらします、最も重要な機能Txtaiの完全な文書内容とテキスト権利を保存すること.この記事は、すべての変更を例でカバーします.

依存関係のインストール
インストールtxtai すべての依存関係.
pip install txtai

コンテンツストレージ
今までTxtaiでは、一度テキストをベクトル化された、もはや入力テキストにトレースすることは可能ではなかった.ドキュメントIDとベクトルのみが格納されました.結果はidとスコアからなる.外部データストアとのマッチを解決するのは開発者の責任でした.
TXTAI 4.0は主要なパラダイムシフトをもたらします.コンテンツは現在、埋め込みベクトルと一緒に格納することができます.これはTxtaiでエキサイティングな可能性の数を開きます!
以下の古典的なTxtaiの例を見てみましょう.
from txtai.embeddings import Embeddings

data = ["US tops 5 million confirmed virus cases",
        "Canada's last fully intact ice shelf has suddenly collapsed, forming a Manhattan-sized iceberg",
        "Beijing mobilises invasion craft along coast as Taiwan tensions escalate",
        "The National Park Service warns against sacrificing slower friends in a bear attack",
        "Maine man wins $1M from $25 lottery ticket",
        "Make huge profits without work, earn up to $100,000 a day"]

# Create embeddings index with content enabled. The default behavior is to only store indexed vectors.
embeddings = Embeddings({"path": "sentence-transformers/nli-mpnet-base-v2", "content": True, "objects": True})

# Create an index for the list of text
embeddings.index([(uid, text, None) for uid, text in enumerate(data)])

print("%-20s %s" % ("Query", "Best Match"))
print("-" * 50)

# Run an embeddings search for each query
for query in ("feel good story", "climate change", "public health story", "war", "wildlife", "asia", "lucky", "dishonest junk"):
    # Extract text field from result
    text = embeddings.search(query, 1)[0]["text"]

    # Print text
    print("%-20s %s" % (query, text))
Query                Best Match
--------------------------------------------------
feel good story      Maine man wins $1M from $25 lottery ticket
climate change       Canada's last fully intact ice shelf has suddenly collapsed, forming a Manhattan-sized iceberg
public health story  US tops 5 million confirmed virus cases
war                  Beijing mobilises invasion craft along coast as Taiwan tensions escalate
wildlife             The National Park Service warns against sacrificing slower friends in a bear attack
asia                 Beijing mobilises invasion craft along coast as Taiwan tensions escalate
lucky                Maine man wins $1M from $25 lottery ticket
dishonest junk       Make huge profits without work, earn up to $100,000 a day
上記の唯一の変更は、コンテンツフラグをtrueに設定することです.これにより、インデックスと一緒にテキストとメタデータの内容を格納できます.テキストがクエリ結果から右に引っ張られる方法に注意してください!

SQLクエリ
コンテンツが有効になっている場合は、全体の辞書が格納され、クエリすることができます.類似性クエリに加えて、TXTIはSQLクエリを受け入れます.これにより、データベースバックエンドに格納された類似インデックスとコンテンツの両方を使用してクエリを組み合わせます.
# Create an index for the list of text
embeddings.index([(uid, {"text": text, "length": len(text)}, None) for uid, text in enumerate(data)])

# Filter by score
print(embeddings.search("select text, score from txtai where similar('hiking danger') and score >= 0.15"))

# Filter by metadata field 'length'
print(embeddings.search("select text, length, score from txtai where similar('feel good story') and score >= 0.05 and length >= 40"))

# Run aggregate queries
print(embeddings.search("select count(*), min(length), max(length), sum(length) from txtai"))
print()
for x in embeddings.search("select count(*), min(length), max(length), sum(length), text, score from txtai group by text limit 10"):
  print(x)
[{'text': 'The National Park Service warns against sacrificing slower friends in a bear attack', 'score': 0.3151373267173767}]
[{'text': 'Maine man wins $1M from $25 lottery ticket', 'length': 42, 'score': 0.08329004049301147}]
[{'count(*)': 6, 'min(length)': 39, 'max(length)': 94, 'sum(length)': 387}]

{'count(*)': 1, 'min(length)': 72, 'max(length)': 72, 'sum(length)': 72, 'text': 'Beijing mobilises invasion craft along coast as Taiwan tensions escalate', 'score': None}
{'count(*)': 1, 'min(length)': 94, 'max(length)': 94, 'sum(length)': 94, 'text': "Canada's last fully intact ice shelf has suddenly collapsed, forming a Manhattan-sized iceberg", 'score': None}
{'count(*)': 1, 'min(length)': 42, 'max(length)': 42, 'sum(length)': 42, 'text': 'Maine man wins $1M from $25 lottery ticket', 'score': None}
{'count(*)': 1, 'min(length)': 57, 'max(length)': 57, 'sum(length)': 57, 'text': 'Make huge profits without work, earn up to $100,000 a day', 'score': None}
{'count(*)': 1, 'min(length)': 83, 'max(length)': 83, 'sum(length)': 83, 'text': 'The National Park Service warns against sacrificing slower friends in a bear attack', 'score': None}
{'count(*)': 1, 'min(length)': 39, 'max(length)': 39, 'sum(length)': 39, 'text': 'US tops 5 million confirmed virus cases', 'score': None}
上の例では、テキストの長さを簡単に追加します.Txtai 4.0から始まると、インデックスメソッドはデータフィールドに辞書を受け取ります.
番目のクエリは、類似のクエリ句と共にメタデータフィールド長にフィルター処理されます.これは、最高の結果を識別するために伝統的なフィルタリングで類似性検索の大きな混合を与えます.

オブジェクトストレージ
メタデータに加えて、バイナリコンテンツもドキュメントと関連付けることができます.次の例では、イメージをダウンロードし、関連付けられたテキストと共にそれを埋め込みインデックスにアップロードします.
import urllib

from IPython.display import Image

# Get an image
request = urllib.request.urlopen("https://raw.githubusercontent.com/neuml/txtai/master/demo.gif")

# Upsert new record having both text and an object
embeddings.upsert([("txtai", {"text": "txtai executes machine-learning workflows to transform data and build AI-powered semantic search applications.", "object": request.read()}, None)])

# Query txtai for the most similar result to "machine learning" and get associated object
result = embeddings.search("select object from txtai where similar('machine learning') limit 1")[0]["object"]

# Display image
Image(result.getvalue(), width=600)


インデックス
コンテンツが格納されているので、インデックスの埋め込みは、異なる構成設定で再構築できます.
# Print index info before (info() is also new!)
embeddings.info()

# Reindex
embeddings.reindex({"path": "sentence-transformers/paraphrase-MiniLM-L3-v2"})

print("------")

# Print index info after
embeddings.info()
{
  "backend": "faiss",
  "build": {
    "create": "2022-01-05T01:44:13Z",
    "python": "3.7.12",
    "settings": {
      "components": "IDMap,Flat"
    },
    "system": "Linux (x86_64)",
    "txtai": "4.0.0"
  },
  "content": "sqlite",
  "dimensions": 768,
  "objects": true,
  "offset": 7,
  "path": "sentence-transformers/nli-mpnet-base-v2"
}
------
{
  "backend": "faiss",
  "build": {
    "create": "2022-01-05T01:44:19Z",
    "python": "3.7.12",
    "settings": {
      "components": "IDMap,Flat"
    },
    "system": "Linux (x86_64)",
    "txtai": "4.0.0"
  },
  "content": "sqlite",
  "dimensions": 384,
  "objects": true,
  "offset": 7,
  "path": "sentence-transformers/paraphrase-MiniLM-L3-v2"
}

インデックス圧縮
txtai通常、インデックスファイルをディレクトリに保存します.4.0では、圧縮インデックスを保存することが可能です.インデックスをtarに圧縮できます.GZタール.bz 2、tar.xzとzip.Txtai圧縮ファイルを読み込むことができますし、ディレクトリとして扱います.
圧縮インデックスは、バックアップ戦略および/またはプライマリストレージメカニズムとして使用できます.
# Save index as tar.xz
embeddings.save("index.tar.xz")
!tar -tvJf index.tar.xz
!echo
!xz -l index.tar.xz
!echo

# Reload index
embeddings.load("index.tar.xz")

# Test search
embeddings.search("lucky guy", 1)
drwx------ root/root         0 2022-01-05 01:44 ./
-rw-r--r-- root/root       290 2022-01-05 01:44 ./config
-rw-r--r-- root/root     77824 2022-01-05 01:44 ./documents
-rw-r--r-- root/root     10898 2022-01-05 01:44 ./embeddings

Strms  Blocks   Compressed Uncompressed  Ratio  Check   Filename
    1       1     45.8 KiB    100.0 KiB  0.458  CRC64   index.tar.xz

[{'id': '4',
  'score': 0.3691234290599823,
  'text': 'Maine man wins $1M from $25 lottery ticket'}]
圧縮比に注意してください.保存されたデータの種類によっては、これはかなりの可能性があります.

外部ベクトルモデル
Txtaiサポートベクトルを生成するHugging Face Transformers , PyTorch , ONNX and Word Vector モデル.
このリリースでは、外部モデルを使用して事前に計算されたベクトルのサポートを追加します.外部モデルは、API、カスタムライブラリおよび/またはデータをベクトル化する別の方法かもしれません.これにより,埋込みベクトルの構築において高い計算コストを与えられる.組み込みの生成は、GPUを持つサーバ群に外部委託されたり、統合されたりすることができ、インデックスサーバをより低いリソースマシン上で実行することができます.
以下の例はHugging Face Inference API 埋め込みベクターを構築するにはロードしますexact model as in the first example と同じ結果を生成します.
import numpy as np
import requests
import time

def transform(text):
  if isinstance(text, tuple):
    text = text[1]

  response = requests.post("https://api-inference.huggingface.co/pipeline/feature-extraction/sentence-transformers/nli-mpnet-base-v2",
                           json={"inputs": text})

  return np.array(response.json(), dtype=np.float32)

# Batch encode data
vectors = transform(data)

# Index data using vectors from Inference API
embeddings = Embeddings({"method": "external", "transform": transform, "content": True})
embeddings.index([(x, {"object": vectors[x], "row": row}, None) for x, row in enumerate(data)])

print("%-20s %s" % ("Query", "Best Match"))
print("-" * 50)

# Run an embeddings search for each query
for query in ("feel good story", "climate change", "public health story", "war", "wildlife", "asia", "lucky", "dishonest junk"):
    # Extract text field from result
    text = embeddings.search(f"select id, row as text, score from txtai where similar('{query}')", 1)[0]["text"]

    # Print text
    print("%-20s %s" % (query, text))
Query                Best Match
--------------------------------------------------
feel good story      Maine man wins $1M from $25 lottery ticket
climate change       Canada's last fully intact ice shelf has suddenly collapsed, forming a Manhattan-sized iceberg
public health story  US tops 5 million confirmed virus cases
war                  Beijing mobilises invasion craft along coast as Taiwan tensions escalate
wildlife             The National Park Service warns against sacrificing slower friends in a bear attack
asia                 Beijing mobilises invasion craft along coast as Taiwan tensions escalate
lucky                Maine man wins $1M from $25 lottery ticket
dishonest junk       Make huge profits without work, earn up to $100,000 a day
次の使用例spaCy ベクトルを構築し、Txtaiにそれらをロードします.このモデルを持つベクトルは,精度を犠牲にして生成するのが非常に速い.
pip install spacy --upgrade
python -m spacy download en_core_web_md
import spacy

# Load spacy
nlp = spacy.load("en_core_web_md")

def transform(document):
    return nlp(document[1]).vector

# Index data with spacy pipeline
embeddings = Embeddings({"method": "external", "transform": transform, "content": True})
embeddings.index([(x, {"object": nlp(row).vector, "row": row}, None) for x, row in enumerate(data)])

# Run search
print(embeddings.search("select id, row as text, score from txtai where similar('hiking danger')", 1))
[{'id': '3', 'text': 'The National Park Service warns against sacrificing slower friends in a bear attack', 'score': 0.5822835564613342}]

ラッピング
この記事はTxtaiの簡単な概観を与えた.Txtai 4.0は2022年1月初めにリリースされますが、Txtaiがソースからインストールされている場合は上記のすべての変更をテストできます.
詳細については、次のリンクを参照してください.
  • 4.0 Milestone on GitHub
  • Documentation for txtai
  • Full list of examples