grasys blog

GenAI Processorsを触ってみる 1/4 ~ Content APIについて ~

はじめまして!エンジニアのUemaです。

今回は、AIパイプラインをシンプルに書けるように設計された、Google DeepMind の新しいオープンソース Python ライブラリである「GenAI Processors」をGet Startedやexampleを参考にしながら触ってみたいと思います。

シンプルに書けるとはいえ、ライブラリの構成要素やコンセプトなどを理解しないと混乱するため、それらもまとめてみました。

4部構成となっていて、今回はPart1となっています。

Part1は、GenAI Processorsで扱われるコンテンツの構成要素が実装されているContent APIについて、まとめてみました。

GenAI Processorsとは

AIパイプラインを構築でき、効率的な並列コンテンツ処理を可能にする軽量の Python ライブラリです。

テキスト、音声、画像といった複数のデータ形式(マルチモーダル)を組み合わせ、リアルタイムで処理するような複雑なアプリケーションの開発を効率化することに特化しています。

Content API

Content API Colab より

GenAI Processorsライブラリには、content_api というモジュールがあります。これは、ProcessorPart ProcessorContent と言ったGenAI Processorsで扱われるコンテンツの構成要素が実装されています。また、Utilityも実装されています。

テキスト、画像、音声といったマルチモーダルなデータを一貫した処理で扱えるようになっています。コンテンツを分類したりルーティングしたりするためのmimetypesubstream_nameなどのメタデータを添付することもできます。

この2つの要素は知っておくとGenAI Processorsライブラリの理解につながると思います。

ProcessorPart

ProcessorPart は、プロセッサが扱うコンテンツの最小単位です。様々なPythonの型から ProcessorPart オブジェクトを作成できるため、テキスト、画像、音声、Pythonのdataclassのデータを格納できます。

ProcessorPartのAttributeは下記をご覧ください。

https://colab.research.google.com/github/google-gemini/genai-processors/blob/main/notebooks/content_api_intro.ipynb#scrollTo=cAXSW37sZCj9

import dataclasses

import dataclasses_json
import requests
from genai_processors.content_api import ProcessorPart


print("########## テキストから")

text_data = "テキストパートです"
text_part = ProcessorPart(text_data)

print(f"ProcessorPart: {text_part}")
print(f"MIMEタイプ: {text_part.mimetype}")  # 'text/plain'として自動的に推論されます
print(f"テキストコンテンツ: '{text_part.text}'")



print("\n########## 画像(bytes)から")

def generate_gdm_logo_bytes() -> bytes:
    """generate_gdm_logo_bytes"""
    # The URL of the DeepMind logo image
    image_url = "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6a/DeepMind_new_logo.svg/2560px-DeepMind_new_logo.svg.png"
    headers = {"User-Agent": "genai_processors Colab"}
    response = requests.get(image_url, headers=headers, timeout=60)
    response.raise_for_status()
    return response.content

gdm_png_bytes = generate_gdm_logo_bytes()

image_bytes_part = ProcessorPart(gdm_png_bytes, mimetype="image/png")  # bytesの場合、mimetypeを指定

print(f"ProcessorPart: {image_bytes_part}")
print(f"MIMEタイプ: {image_bytes_part.mimetype}")
try:
    txt = image_bytes_part.text
except ValueError:
    print("textはありません")



print("\n########## dataclassから")

@dataclasses_json.dataclass_json  # JSONシリアライゼーションに重要
@dataclasses.dataclass
class MyStructuredData:
    id: int
    name: str
    tags: list[str]

my_data_instance = MyStructuredData(
    id=101,
    name="Alpha",
    tags=["important", "beta"],
)

dataclass_part = ProcessorPart.from_dataclass(
    dataclass=my_data_instance,
    role="system_event",
    metadata={"source": "internal_module"},
)

print(f"ProcessorPart: {dataclass_part}")
print(f"MIMEタイプ: {dataclass_part.mimetype}")
print(f"テキストコンテンツ (JSON): {dataclass_part.text}")

下記を参考に ProcessorPart オブジェクトを生成しました。詳細な使い方やその他の ProcessorPart のサンプルが気になる場合は下記を参照してください。

https://colab.research.google.com/github/google-gemini/genai-processors/blob/main/notebooks/content_api_intro.ipynb#scrollTo=Y_xs5YKoZCj8

ProcessorContent

ProcessorContent は、1つ以上の ProcessorPart オブジェクトが集まったコレクションです。これは、会話のやり取りを表現したり、マルチモーダルの入力のコレクションによく使用されます。

コンストラクタに、ProcessorPart オブジェクト、ProcessorPart に変換できるデータ、ProcessorPart オブジェクトのリストを渡すことで ProcessorContent オブジェクトを作成できます。

ProcessorContent は、ProcessorPartのリストのように振る舞うため、for文でイテレートしたり、.items() メソッドを使うことで、mimetypeとProcessorPartオブジェクトを取得できます。

from genai_processors.content_api import ProcessorContent, ProcessorPart, is_text


def generate_gdm_logo_bytes() -> bytes:
    """generate_gdm_logo_bytes"""
    # 「ProcessorPart」のサンプルコード参照


print("########## Content 1")

content1 = ProcessorContent(
    "これが最初のテキストパートです。",
    ProcessorPart(generate_gdm_logo_bytes(), mimetype="image/png", role="user"),
    "そして最後のテキストパートです。",
)

for part in content1:  # ProcessorContentは直接イテレートできます
    content_data = f"テキスト: {part.text}" if is_text(part.mimetype) else "[バイナリデータ]"
    print(f"  - mimetype: {part.mimetype}:, {content_data}")
print(f"Content 1の長さ: {len(content1)}")


print("\n########## Content 2")

# ProcessorPartオブジェクトのリストから
parts_list = [
    ProcessorPart("猫について", role="user"),
    ProcessorPart("猫は魅力的な生き物です!", role="model"),
]
content2 = ProcessorContent(parts_list)

for mime, part_obj in content2.items():  # .items()は(mimetype, ProcessorPart)を返す
    print(f"  - ロール: {part_obj.role}, mimetype: {mime}, テキスト: {part_obj.text}")
print(f"Content 2の長さ: {len(content2)}")

Utility: as_text()

content_api.as_text() は、ProcessorContent にあるmimetypeがtext/plainであるProcessorPart のテキストを連結します。

from genai_processors.content_api import ProcessorContent, ProcessorPart, as_text


def generate_gdm_logo_bytes() -> bytes:
    """generate_gdm_logo_bytes"""
    # 「ProcessorPart」のサンプルコード参照


print("########## as_text")
multimodal_content = ProcessorContent(
    ProcessorPart("最初のテキストがあります。", substream_name="other"),
    ProcessorPart(generate_gdm_logo_bytes(), mimetype="image/png"),  # これはas_textによって無視されます
    "続いてさらにテキストがあります。",
)

all_text = as_text(multimodal_content)
print(f"multimodal_contentから連結されたテキスト:\n{all_text}")

other_text_only = as_text(multimodal_content, substream_name="other")
print(f"'other'substreamからのテキスト:\n{other_text_only}")

content_api モジュールには、as_text() 以外にもUtilityはあるので気になる場合はソースコードを確認してみてください。

おわりに

テキスト、音声、画像などを格納して、マルチモーダルなデータを一貫した処理を行えるようにしたのはすごいと思いました。

GenAI ProcessorsのExampleを見ても、ProcessorPartProcessorContent がどの様なオブジェクトなのかわからなかったのですが、Content APIのGet Startedを見たり、動かしてみたりして理解することができたと思います。

次回は、Processorについてです。

参考

こちらのリンクからシリーズ記事を一覧で見られます。よろしければこちらもご覧ください!
『GenAI Processorsを触ってみる』シリーズ一覧


採用情報
お問い合わせ