文字列テンソル¶
OpenVINO テンソルは、浮動小数点や整数などの数値データだけでなく、1 つまたは複数の文字列のテキスト情報も保持できます。これは文字列テンソルと呼ばれ、トークナイザーやデトークナイザーなどのテキスト処理モデルの入力として渡したり、出力として取得できます。
このセクションでは、文字列テンソルを処理する基本的な API について説明しますが、文字列テンソルと OpenVINO トークナイザーの両方を活用する実践的な例は GenAI サンプルにあります。
表現¶
文字列テンソルは C++ および Python API でサポートされ、ov::element::string
に等しい element_type
パラメーターを持つ ov::Tensor
クラスのインスタンスとして表されます。文字列テンソルの各要素は、空の文字列を含む任意の長さの文字列であり、同じテンソル内の他の要素とは独立して設定できます。
使用される API (C++ または Python) に応じて、テンソル要素にアクセスする文字列を表すベースのデータタイプは異なります。
C++ では、std::string が使用されます
Python では、
numpy.str_
/numpy.bytes_
が設定された Numpy 配列が、ベースとなる C++ コンテンツの読み取り専用コピーとして使用されます。
ベースとなる std::string
にはそのような制限がないため、文字列テンソルの実装は文字列エンコードの制限を意味するものではありません。すべての有効な UTF-8 文字を表すことができますが、UTF-8 エンコード標準以外のその他のバイト・シーケンスも表現できます。ユーザーは、エンコードされた UTF-8 シンボルとしてテンソルコンテンツにアクセスして任意のバイト・シーケンスを処理する場合、特に注意する必要があります。
文字列表現は、float
や int
データタイプより洗練されているため、文字列オブジェクトを適切に構築および破棄しない限り、文字列テンソル表現に使用されるメモリーを処理できません。また、数値データとは異なり、C++ と Python は同じメモリーレイアウトを共有しないため、2 つの API 間でテンソルコンテンツが即座に共有されることはありません。Python は、C++ コアに std::string
オブジェクトの配列として割り当て保持されるデータの numpy 互換のビューのみを提供します。
開発者は、文字列テンソルを使用してコードを作成するときにこれらの制限を考慮し、コンテンツを生のバイトまたは Python のデータのビューとして扱うことを避けなければなりません。
文字列テンソルの作成¶
以下は、3 つの要素が事前に設定された小さな 1D テンソルを作成する例です。
import openvino as ov
tensor = ov.Tensor(['text', 'more text', 'even more text'])
#include <vector>
#include <string>
#include <openvino/openvino.hpp>
std::vector<std::string> strings = {"text", "more text", "even more text"};
ov::Tensor tensor(ov::element::string, ov::Shape{strings.size()}, &strings[0]);
この例は、数値情報を持つテンソルと同様に、事前に割り当てられた要素配列へのポインターを提供することで、C++ の既存のメモリー上にテンソル・オブジェクトを作成できることを示しています。ここでは、3 つの std::string オブジェクトで構成される、std::vector のインスタンスがメモリーを保持するために使用されてます。したがって、C++ の例の tensor
オブジェクトは strings
ベクトルと同じメモリーを共有します。
ov::Tensor
は、ポインターで初期化される場合、空の文字列であっても、利用可能な std::string
コンストラクターの 1 つを呼び出して作成された有効な std::string
オブジェクトを含む事前に初期化されたメモリーを必要とすることに注意してください。初期化されていないメモリーがこの ov::Tensor
コンストラクターに渡されると、未定義の動作になります。
上記の Python バージョンでは、通常の文字列リストが初期化子として使用されます。C++ とは対照的に、メモリー共有は利用できず、初期化リストの文字列は、tensor
オブジェクト下に個別に割り当てられたストレージにコピーされます。
初期化子は、プレーンな Python 文字列リストのほか、Unicode またはバイト文字列で初期化された、numpy
配列にすることができます。
import numpy as np
tensor = ov.Tensor(np.array(['text', 'more text', 'even more text']))
tensor = ov.Tensor(np.array([b'text', b'more text', b'even more text']))
初期化文字列なして ov::Tensor
が作成された場合、指定された形状と要素の空の文字列のテンソルが作成されます。
tensor = ov.Tensor(dtype=str, shape=[3])
ov::Tensor tensor(ov::element::string, ov::Shape{3});
ov::Tensor
は、必要な数の std::string
オブジェクトを割り当てて初期化します。
要素のアクセス¶
次のコードは、上記で構築された 1D 文字列テンソルのすべての要素を出力します。C++ コードでは、同じ .data
テンプレート・メソッドが他のデータタイプにも使用され、文字列データにアクセスするには、std::string
タイプで呼び出す必要があります。Python では、数値データの data
フィールドの代わりに、専用の std_data
と byte_data
フィールドが使用されます。
data = tensor.str_data # use tensor.byte_data instead to access encoded strings as `bytes`
for i in range(tensor.get_size()):
print(data[i])
#include <iostream>
std::string* data = tensor.data<std::string>();
for(size_t i = 0; i < tensor.get_size(); ++i)
std::cout << data[i] << '\n';
Python の場合、tensor.str_data
(または tensor.bytes_data
) で取得されるオブジェクトは、numpy.str_
要素 (または対応する numpy.bytes_
) を含む numpy 配列です。これは、tensor
オブジェクトのベースとなるデータのコピーであり、テンソルコンテンツの変更には使用できません。新しい値を設定するには、次のように、テンソルコンテンツ全体をリストまたは numpy
配列として設定する必要があります。
Python とは対照的に、C++ で tensor.data<std::string>()
を使用すると、ベースになるデータストレージへのポインターが返され、それをテンソル要素の変更に使用できます
# Unicode strings:
tensor.str_data = ['one', 'two', 'three']
# Do NOT use tensor.str_data[i] to set a new value, it won't update the tensor content
# Encoded strings:
tensor.bytes_data = [b'one', b'two', b'three']
# Do NOT use tensor.bytes_data[i] to set a new value, it won't update the tensor content
std::string new_content[] = {"one", "two", "three"};
std::string* data = tensor.data<std::string>();
for(size_t i = 0; i < tensor.get_size(); ++i)
data[i] = new_content[i];
Python で文字列テンソルの要素を読み取りまたは設定する場合、ベースになるバイト・シーケンスが有効な UTF-8 エンコード文字列を形成することが判明しているのであれば、str
オブジェクト (または numpy 配列で使用される場合は numpy.str_
) を使用することを推奨します。それ以外の場合、UTF-8 標準だけではなく、任意のバイト・シーケンスが許可される場合、代わりに bytes
文字列 (またはそれに応じて numpy.bytes_
) を使用します。
str_data
を介してテンソルコンテンツにアクセスすると、暗黙的に UTF-8 デコードが適用されます。バイトストリームの一部が有効な Unicode シンボルとして表現できない場合、無効な Unicode ストリームでのエラーを通知するため置換記号が使用されます。
関連情報¶
推論をアプリケーションに統合する基本的な手順について学びます。
OpenVINO トークナイザーを使用して、大規模言語モデルの前処理および後処理としてテキスト情報を操作する文字列テンソルを使用するモデルを作成します。
GenAI サンプルをチェックして、実際のアプリケーションで文字列テンソルがどのように使用されるか確認してください。