パートナーシップ

高度なビデオ理解アプリケーションの構築:マルチモーダルAIに向けたTwelve Labs Embed APIとLanceDBの統合

ジェームズ・リー、マニッシュ・マヘシュワリ

開発者は、Twelve LabsのEmbed APIとLanceDBを統合してMarengoによるマルチモーダルビデオ埋め込みを作成し、それらをサーバーレスのベクトルデータベースに保存して、テキスト入力を使用してクエリを実行することにより、セマンティックなビデオ検索アプリケーションを構築できます。ビデオコンテンツに関する質問に答えるためのRAGワークフローの例も含まれています。

開発者は、Twelve LabsのEmbed APIとLanceDBを統合してMarengoによるマルチモーダルビデオ埋め込みを作成し、それらをサーバーレスのベクトルデータベースに保存して、テキスト入力を使用してクエリを実行することにより、セマンティックなビデオ検索アプリケーションを構築できます。ビデオコンテンツに関する質問に答えるためのRAGワークフローの例も含まれています。

この記事の内容

No headings found on page

ニュースレターに登録する

ニュースレターに登録する

ビデオ理解に関する最新の技術進歩、チュートリアル、業界の動向をお届けします

ビデオ理解に関する最新の技術進歩、チュートリアル、業界の動向をお届けします

AIを活用してビデオを検索、分析、探索します。

2024/08/14

12分

記事へのリンクをコピー

TLDR: Twelve LabsのEmbed APIとLanceDBを統合し、ビデオの理解と検索のための高度なAIアプリケーションを構築する方法を学びます。このガイドでは、環境のセットアップやビデオ埋め込みの生成から、それらを効率的に保存・クエリする方法まで、すべてを網羅しています。このチュートリアルでコラボレーションしてくれたLanceDBチームのJasmine Wang氏とAyush Chaurasia氏に深く感謝いたします。

はじめに

高度なビデオ理解と検索のために、Twelve LabsのEmbed APILanceDBを統合するこのチュートリアルへようこそ。このガイドでは、これら2つの強力なテクノロジーを活用して、ビデオコンテンツをかつてない精度と効率で処理および分析できるAIアプリケーションを作成する方法を実演します。

Twelve LabsのEmbed APIは、ビデオコンテンツの本質を捉える豊富なマルチモーダル埋め込みを生成し、LanceDBは、これらの高次元ベクトルを大規模に保存、インデックス登録、およびクエリすることに優れたサーバーレスベクトルデータベースです。これらのテクノロジーを組み合わせることで、セマンティックビデオ検索エンジン、コンテンツベースの推奨システム、ビデオストリームにおける異常検知などのアプリケーションを作成できます。

セットアップとインストール

コア機能に飛び込む前に、環境をセットアップし、必要なライブラリをインストールしましょう。

必要なライブラリのインストール

まず、Twelve Labs SDKとLanceDBをインストールします。ノートブックのセルで次のコマンドを実行します。

!pip install twelvelabs lancedb

このコマンドは両方のライブラリをインストールし、Twelve Labsのビデオ処理機能とLanceDBのベクトル保存およびクエリ機能へのアクセスを提供します。

Twelve Labsでの認証

次に、Twelve Labs APIの認証をセットアップする必要があります。APIキーを安全に保存するために環境変数を使用します。

from twelvelabs import TwelveLabs
import os

# Retrieve the API key from environment variables
TWELVE_LABS_API_KEY = os.getenv('TWELVE_LABS_API_KEY')

# Initialize the Twelve Labs client
twelvelabs_client = TwelveLabs(api_key=TWELVE_LABS_API_KEY)

注: このコードを実行する前に、実際のAPIキーを使用して TWELVE_LABS_API_KEY 環境変数を設定していることを確認してください。

export TWELVE_LABS_API_KEY='your_api_key_here'

LanceDBの初期化

次に、LanceDBへの接続を初期化しましょう。

import lancedb
import pyarrow as pa

# Create or connect to a LanceDB database
db = lancedb.connect("my_video_embeddings_db")

# Define the schema for your video embeddings
schema = pa.schema(
    [
        pa.field("video_id", pa.string()),
        pa.field("embedding", pa.list_(pa.float32(), 1024)),
        pa.field("start_time", pa.float32()),
        pa.field("end_time", pa.float32()),
        pa.field("video_url", pa.string())
    ]
)

# Create a table for storing video embeddings
table = db.create_table("video_embeddings", schema=schema, mode="overwrite")

このコードは、新しいLanceDBデータベースを作成し(または既存のデータベースに接続し)、ビデオ埋め込みを保存するための専用テーブルをセットアップします。

  • pyarrowライブラリをインポートし、pa.schemaを使用してlancedbライブラリが想定する形式でスキーマを定義します。Pydanticを使用してスキーマを定義することもできます。

  • テーブルのスキーマを定義します。これには以下が含まれます:

    • video_id: 各埋め込みの一意の識別子

    • embedding: ビデオセグメントのベクトル表現(1024はTwelve Labs Embed APIによって提供されるビデオ埋め込みの次元数です)

    • start_time および end_time: ビデオセグメントの時間情報

    • video_url: ビデオのソース

  • create_table メソッドは、テーブル名、定義されたスキーマ、およびテーブルがすでに存在する場合に再作成するためのモード「overwrite」を指定して呼び出されます。

Twelve Labs Embed APIを使用したビデオ埋め込みの生成

このセクションでは、Twelve Labs Embed APIを使用して、ビデオコンテンツからマルチモーダル埋め込みを生成します。これらの埋め込みは、視覚的要素、音声、時間情報など、ビデオの豊かなコンテキストを捉えます。

まず、指定されたビデオURLの埋め込みを生成する関数を定義しましょう。

from twelvelabs.models.embed import EmbeddingsTask

def generate_embedding(video_url: str) -> tuple[List[Dict[str, Any]], Any]:
    """Generate embeddings for a given video URL."""
    task = twelvelabs_client.embed.task.create(
        engine_name="Marengo-retrieval-2.6",
        video_url=video_url
    )
    
    def on_task_update(task: EmbeddingsTask):
        print(f"  Status={task.status}")

    task.wait_for_done(sleep_interval=2, callback=on_task_update)
    task_result = twelvelabs_client.embed.task.retrieve(task.id)

    embeddings = [{
        'embedding': v.embedding.float,
        'start_offset_sec': v.start_offset_sec,
        'end_offset_sec': v.end_offset_sec,
        'embedding_scope': v.embedding_scope
    } for v in task_result.video_embeddings]
    
    return embeddings, task_result

この関数は、埋め込みタスクを作成し、その進行状況を監視して、完了すると結果を取得します。埋め込みのリストを、その時間情報およびスコープとともに返します。

次に、この関数を使用してサンプルビデオの埋め込みを生成してみましょう。

# Example usage
video_url = "https://example.com/your-video.mp4"

# Generate embeddings for the video
embeddings, task_result = generate_embedding(video_url)

print(f"Generated {len(embeddings)} embeddings for the video")
for i, emb in enumerate(embeddings):
    print(f"Embedding {i+1}:")
    print(f"  Scope: {emb['embedding_scope']}")
    print(f"  Time range: {emb['start_offset_sec']} - {emb['end_offset_sec']} seconds")
    print(f"  Embedding vector (first 5 values): {emb['embedding'][:5]}")
    print()

このコードスニペットは、ビデオの埋め込みを生成し、結果を確認する方法を示しています。各埋め込みはビデオのセグメントを表し、そのマルチモーダルな特性を捉えています。

埋め込みについて理解する:

  1. 埋め込みベクトル: ビデオセグメントの内容を高次元で表現したもので、視覚、音声、コンテキスト情報を捉えます。

  2. 時間範囲: 埋め込みによって表されるビデオセグメントの開始時間と終了時間。

  3. 埋め込みスコープ: 埋め込みのタイプを示します(例:フルビデオ埋め込みの場合は「video」)。

LanceDBへの埋め込みの保存

Twelve LabsのEmbed APIを使用してビデオ埋め込みを生成した後の次の重要なステップは、これらの埋め込みをLanceDBに効率的に保存することです。これにより、迅速な検索が可能になり、類似性検索やコンテンツ推奨などのさまざまな下流のタスクが可能になります。

ビデオ埋め込みをLanceDBに保存するプロセスを見ていきましょう:

import uuid

def insert_embeddings(embeddings: List[Dict[str, Any]], video_url: str) -> None:
    """Insert embeddings into the database."""
    data_to_insert = [{
        "id": str(uuid.uuid4()),
        "embedding": emb['embedding'],
        "start_time": emb['start_offset_sec'],
        "end_time": emb['end_offset_sec'],
        "video_url": video_url
    } for emb in embeddings]
    
    table.add(data_to_insert)
    print(f"Inserted {len(data_to_insert)} embeddings for video: {video_url}")

# Use the function to insert the embeddings we generated earlier
insert_embeddings(embeddings, video_url)

# Verify the insertion
print(f"Total embeddings in the table: {len(table)}")

このコードが何を行うのかを分解してみましょう:

  1. 生成された埋め込みとビデオURLを受け取り、それらをLanceDBへの挿入用にフォーマットしてテーブルに追加する関数insert_embeddingsを作成します。

  2. この関数を使用して、前のステップで生成した埋め込みを挿入します。

  3. 最後に、テーブル内の埋め込みの総数を確認して、挿入を検証します。

このアプローチにより、埋め込みベクトルだけでなく、時間情報やソースビデオのURLなどの重要なメタデータも保存できます。この追加情報は、ワークフローの後半のステップでの検索やコンテキスト化に役立ちます。

埋め込みのクエリと検索

ビデオ埋め込みをLanceDBに保存したので、その強力なクエリ機能を活用して類似性検索を実行し、関連するビデオセグメントを取得できます。これは、セマンティックビデオ検索、コンテンツ推奨、または検索拡張生成(RAG)システムなどのアプリケーションを構築する際の重要なステップです。

LanceDBから埋め込みをクエリして取得する方法を探ってみましょう:

def similarity_search(query_embedding: List[float], k: int = 5) -> List[Dict[str, Any]]:
    """Perform a similarity search on the embeddings table."""
    return table.search(query_embedding).limit(k).to_list()

def get_text_embedding(text_query: str) -> List[float]:
    """Generate a text embedding for a given text query."""
    return twelvelabs_client.embed.text(text_query).embedding.float

# Example usage: Text-based search
text_query = "A person explaining machine learning concepts"
query_embedding = get_text_embedding(text_query)
search_results = similarity_search(query_embedding)

print(f"Top 5 results for query: '{text_query}'")
for i, result in enumerate(search_results):
    print(f"Result {i+1}:")
    print(f"  Video URL: {result['video_url']}")
    print(f"  Segment: {result['start_time']} - {result['end_time']} seconds")
    print(f"  Similarity Score: {result['_distance']}")
    print()

def get_video_segment(video_url: str, start_time: float, end_time: float) -> str:
    """Retrieve a video segment URL from a video URL using start and end times."""
    return f"{video_url}?start={start_time}&end={end_time}"

# Retrieve specific video segment for the top result
top_result = search_results[0]
video_segment = get_video_segment(top_result['video_url'], 
                                  top_result['start_time'], 
                                  top_result['end_time'])
print(f"Link to top result video segment: {video_segment}")

このコードの主要なコンポーネントを分解してみましょう:

  1. 類似性検索関数: クエリ埋め込みを受け取り、LanceDBテーブルから最も類似したk個の埋め込みを返すsimilarity_search関数を定義します。

  2. テキストから埋め込みへの変換: get_text_embedding関数は、Twelve LabsのEmbed APIを使用してテキストクエリを埋め込みに変換する方法を示しています。これにより、ビデオコンテンツに対してテキストベースの検索を実行できます。

  3. クエリプロセス

    • テキストクエリから始めます。

    • それを埋め込みに変換します。

    • LanceDBで類似性検索を実行します。

    • ビデオURL、セグメントのタイムスタンプ、類似性スコアなど、上位の結果を取得して表示します。

  4. ビデオセグメントの取得: 検索結果に基づいて特定のビデオセグメントへのリンクまたは参照を生成する方法を示すプレースホルダー関数get_video_segmentを含めています。

実際のアプリケーションでは、次のようなより高度なフィルタリングオプションを追加することをお勧めします:

# Example of filtering results by metadata
filtered_results = table.search(query_embedding).where("start_time > 10 AND end_time < 60").limit(5).to_list()

これにより、埋め込みベースの類似性検索と従来のメタデータフィルタリングを組み合わせて、より正確な結果を得ることができます。

RAGワークフローとの統合

ビデオ埋め込みシステムを検索拡張生成(RAG)ワークフローに統合する簡単な例を以下に示します:

from transformers import AutoTokenizer, AutoModelForSeq2SeqLMv

# Constants
MODEL_NAME = "google/flan-t5-base"
MAX_QUERY_TOKENS = 77

# Initialize model, tokenizer, and database
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
model = AutoModelForSeq2SeqLM.from_pretrained(MODEL_NAME)

def generate_response(prompt: str, max_length: int = 100) -> str:
    """Generate a response using FLAN-T5 model."""
    inputs = tokenizer(prompt, return_tensors="pt", max_length=512, truncation=True)
    outputs = model.generate(**inputs, max_length=max_length, num_return_sequences=1)
    return tokenizer.decode(outputs[0], skip_special_tokens=True)

def retrieve_relevant_segments(query: str, k: int = 3) -> list:
    """Retrieve relevant video segments based on the query."""
    truncated_query = ' '.join(query.split()[:MAX_QUERY_TOKENS])
    query_embedding = get_text_embedding(truncated_query)
    return similarity_search(query_embedding, k)

def create_context(results: list) -> str:
    """Create context from retrieved video segments."""
    return "\n".join(
        f"Video segment from {result['start_time']} to {result['end_time']} seconds: {result['video_url']}"
        for result in results
    )

def rag_workflow(user_query: str) -> str:
    """Execute the RAG (Retrieval-Augmented Generation) workflow."""
    relevant_segments = retrieve_relevant_segments(user_query)
    context = create_context(relevant_segments)
    
    prompt = f"""Context:
{context}

User Query: {user_query}

Based on the context provided about the video segments, please answer the user's query:"""
    
    return generate_response(prompt)

# Example usage
user_query = "What is the purpose of the video?"
rag_response = rag_workflow(user_query)
print("User Query:", user_query)
print("\nRAG Response:", rag_response)

このコードは、当社のビデオ埋め込みシステムを統合した基本的なRAGワークフローを示しています:

  1. まず、開発者が簡単にアクセスできるオープンソースのLLMであるFLAN-T5モデルを設定することから始めます。

  2. retrieve_relevant_segments関数は、以前に定義した類似性検索を使用して、ユーザーのクエリに関連するビデオセグメントを見つけます。

  3. create_contextは、取得したビデオセグメント情報をコンテキスト文字列にフォーマットします。

  4. rag_workflow関数がすべてをまとめます:

    • ユーザーのクエリに基づいて関連するビデオセグメントを取得します。

    • これらのセグメントからコンテキストを作成します。

    • コンテキストとユーザーのクエリを組み合わせたプロンプトを構築します。

    • FLAN-T5モデルを使用して、この充実したプロンプトに基づいて応答を生成します。

  5. 最後に、ビデオ内の機械学習の概念に関するクエリの例を使用して、ワークフローを示します。

このRAGシステムにより、言語モデルは、インデックスに登録したビデオコンテンツを活用することで、より情報に基づいたコンテキストに沿った応答を提供できます。これは、ビデオの要約の作成、ビデオコンテンツに関する特定の質問への回答、およびビデオ素材に基づくインサイトや説明の提供などのアプリケーションに特に強力です(Twelve Labs Generate APIで実現できることと同様です)。

パフォーマンスに関する考慮事項とベストプラクティス

Twelve LabsのEmbed APIとLanceDBを使用する場合、次のベストプラクティスを推奨します:

  • APIの使用を最適化するために、大規模なビデオデータセットの埋め込みリクエストをバッチ処理することを検討してください。

  • クエリのパフォーマンスを監視し、類似性検索の結果数(k)を調整して、精度と速度のバランスを取ります。

  • 多数のビデオを処理する場合は、API呼び出しとデータベースクエリを減らすために、頻繁にアクセスされる埋め込みのキャッシュ戦略を実装することを検討してください。

本番環境については、他にも以下の考慮事項があります:

  • API呼び出しとデータベース操作のエラー処理と再試行を実装します。

  • システム全体の応答性を向上させるために、埋め込み生成とデータベース挿入の非同期処理を検討してください。

  • 向上した精度とパフォーマンスの恩恵を受けるために、Twelve LabsがMarengoの新しいバージョンをリリースするたびに、埋め込みを定期的に更新してください。

結論と次のステップ

このチュートリアルでは、Twelve LabsのEmbed APIをLanceDBと統合して、強力なビデオ理解および検索システムを作成する方法を実演しました。埋め込みの生成、保存、クエリ、およびセマンティック検索やRAGワークフローなどの実用的なアプリケーションについて説明しました。この統合は、高度なビデオベースのAIアプリケーションを構築するための無数の可能性を開きます。

さらにプロジェクトを強化するために、以下を検討してください:

付録

参考およびさらなる探索のために:

  1. 完全なColabノートブック

  2. Twelve Labs APIドキュメント

  3. LanceDBドキュメント

皆さんが何を作るのか楽しみにしています!Twelve LabsおよびLanceDBのコミュニティで、プロジェクトや経験を共有してください。ハッピーコーディング!

TLDR: Twelve LabsのEmbed APIとLanceDBを統合し、ビデオの理解と検索のための高度なAIアプリケーションを構築する方法を学びます。このガイドでは、環境のセットアップやビデオ埋め込みの生成から、それらを効率的に保存・クエリする方法まで、すべてを網羅しています。このチュートリアルでコラボレーションしてくれたLanceDBチームのJasmine Wang氏とAyush Chaurasia氏に深く感謝いたします。

はじめに

高度なビデオ理解と検索のために、Twelve LabsのEmbed APILanceDBを統合するこのチュートリアルへようこそ。このガイドでは、これら2つの強力なテクノロジーを活用して、ビデオコンテンツをかつてない精度と効率で処理および分析できるAIアプリケーションを作成する方法を実演します。

Twelve LabsのEmbed APIは、ビデオコンテンツの本質を捉える豊富なマルチモーダル埋め込みを生成し、LanceDBは、これらの高次元ベクトルを大規模に保存、インデックス登録、およびクエリすることに優れたサーバーレスベクトルデータベースです。これらのテクノロジーを組み合わせることで、セマンティックビデオ検索エンジン、コンテンツベースの推奨システム、ビデオストリームにおける異常検知などのアプリケーションを作成できます。

セットアップとインストール

コア機能に飛び込む前に、環境をセットアップし、必要なライブラリをインストールしましょう。

必要なライブラリのインストール

まず、Twelve Labs SDKとLanceDBをインストールします。ノートブックのセルで次のコマンドを実行します。

!pip install twelvelabs lancedb

このコマンドは両方のライブラリをインストールし、Twelve Labsのビデオ処理機能とLanceDBのベクトル保存およびクエリ機能へのアクセスを提供します。

Twelve Labsでの認証

次に、Twelve Labs APIの認証をセットアップする必要があります。APIキーを安全に保存するために環境変数を使用します。

from twelvelabs import TwelveLabs
import os

# Retrieve the API key from environment variables
TWELVE_LABS_API_KEY = os.getenv('TWELVE_LABS_API_KEY')

# Initialize the Twelve Labs client
twelvelabs_client = TwelveLabs(api_key=TWELVE_LABS_API_KEY)

注: このコードを実行する前に、実際のAPIキーを使用して TWELVE_LABS_API_KEY 環境変数を設定していることを確認してください。

export TWELVE_LABS_API_KEY='your_api_key_here'

LanceDBの初期化

次に、LanceDBへの接続を初期化しましょう。

import lancedb
import pyarrow as pa

# Create or connect to a LanceDB database
db = lancedb.connect("my_video_embeddings_db")

# Define the schema for your video embeddings
schema = pa.schema(
    [
        pa.field("video_id", pa.string()),
        pa.field("embedding", pa.list_(pa.float32(), 1024)),
        pa.field("start_time", pa.float32()),
        pa.field("end_time", pa.float32()),
        pa.field("video_url", pa.string())
    ]
)

# Create a table for storing video embeddings
table = db.create_table("video_embeddings", schema=schema, mode="overwrite")

このコードは、新しいLanceDBデータベースを作成し(または既存のデータベースに接続し)、ビデオ埋め込みを保存するための専用テーブルをセットアップします。

  • pyarrowライブラリをインポートし、pa.schemaを使用してlancedbライブラリが想定する形式でスキーマを定義します。Pydanticを使用してスキーマを定義することもできます。

  • テーブルのスキーマを定義します。これには以下が含まれます:

    • video_id: 各埋め込みの一意の識別子

    • embedding: ビデオセグメントのベクトル表現(1024はTwelve Labs Embed APIによって提供されるビデオ埋め込みの次元数です)

    • start_time および end_time: ビデオセグメントの時間情報

    • video_url: ビデオのソース

  • create_table メソッドは、テーブル名、定義されたスキーマ、およびテーブルがすでに存在する場合に再作成するためのモード「overwrite」を指定して呼び出されます。

Twelve Labs Embed APIを使用したビデオ埋め込みの生成

このセクションでは、Twelve Labs Embed APIを使用して、ビデオコンテンツからマルチモーダル埋め込みを生成します。これらの埋め込みは、視覚的要素、音声、時間情報など、ビデオの豊かなコンテキストを捉えます。

まず、指定されたビデオURLの埋め込みを生成する関数を定義しましょう。

from twelvelabs.models.embed import EmbeddingsTask

def generate_embedding(video_url: str) -> tuple[List[Dict[str, Any]], Any]:
    """Generate embeddings for a given video URL."""
    task = twelvelabs_client.embed.task.create(
        engine_name="Marengo-retrieval-2.6",
        video_url=video_url
    )
    
    def on_task_update(task: EmbeddingsTask):
        print(f"  Status={task.status}")

    task.wait_for_done(sleep_interval=2, callback=on_task_update)
    task_result = twelvelabs_client.embed.task.retrieve(task.id)

    embeddings = [{
        'embedding': v.embedding.float,
        'start_offset_sec': v.start_offset_sec,
        'end_offset_sec': v.end_offset_sec,
        'embedding_scope': v.embedding_scope
    } for v in task_result.video_embeddings]
    
    return embeddings, task_result

この関数は、埋め込みタスクを作成し、その進行状況を監視して、完了すると結果を取得します。埋め込みのリストを、その時間情報およびスコープとともに返します。

次に、この関数を使用してサンプルビデオの埋め込みを生成してみましょう。

# Example usage
video_url = "https://example.com/your-video.mp4"

# Generate embeddings for the video
embeddings, task_result = generate_embedding(video_url)

print(f"Generated {len(embeddings)} embeddings for the video")
for i, emb in enumerate(embeddings):
    print(f"Embedding {i+1}:")
    print(f"  Scope: {emb['embedding_scope']}")
    print(f"  Time range: {emb['start_offset_sec']} - {emb['end_offset_sec']} seconds")
    print(f"  Embedding vector (first 5 values): {emb['embedding'][:5]}")
    print()

このコードスニペットは、ビデオの埋め込みを生成し、結果を確認する方法を示しています。各埋め込みはビデオのセグメントを表し、そのマルチモーダルな特性を捉えています。

埋め込みについて理解する:

  1. 埋め込みベクトル: ビデオセグメントの内容を高次元で表現したもので、視覚、音声、コンテキスト情報を捉えます。

  2. 時間範囲: 埋め込みによって表されるビデオセグメントの開始時間と終了時間。

  3. 埋め込みスコープ: 埋め込みのタイプを示します(例:フルビデオ埋め込みの場合は「video」)。

LanceDBへの埋め込みの保存

Twelve LabsのEmbed APIを使用してビデオ埋め込みを生成した後の次の重要なステップは、これらの埋め込みをLanceDBに効率的に保存することです。これにより、迅速な検索が可能になり、類似性検索やコンテンツ推奨などのさまざまな下流のタスクが可能になります。

ビデオ埋め込みをLanceDBに保存するプロセスを見ていきましょう:

import uuid

def insert_embeddings(embeddings: List[Dict[str, Any]], video_url: str) -> None:
    """Insert embeddings into the database."""
    data_to_insert = [{
        "id": str(uuid.uuid4()),
        "embedding": emb['embedding'],
        "start_time": emb['start_offset_sec'],
        "end_time": emb['end_offset_sec'],
        "video_url": video_url
    } for emb in embeddings]
    
    table.add(data_to_insert)
    print(f"Inserted {len(data_to_insert)} embeddings for video: {video_url}")

# Use the function to insert the embeddings we generated earlier
insert_embeddings(embeddings, video_url)

# Verify the insertion
print(f"Total embeddings in the table: {len(table)}")

このコードが何を行うのかを分解してみましょう:

  1. 生成された埋め込みとビデオURLを受け取り、それらをLanceDBへの挿入用にフォーマットしてテーブルに追加する関数insert_embeddingsを作成します。

  2. この関数を使用して、前のステップで生成した埋め込みを挿入します。

  3. 最後に、テーブル内の埋め込みの総数を確認して、挿入を検証します。

このアプローチにより、埋め込みベクトルだけでなく、時間情報やソースビデオのURLなどの重要なメタデータも保存できます。この追加情報は、ワークフローの後半のステップでの検索やコンテキスト化に役立ちます。

埋め込みのクエリと検索

ビデオ埋め込みをLanceDBに保存したので、その強力なクエリ機能を活用して類似性検索を実行し、関連するビデオセグメントを取得できます。これは、セマンティックビデオ検索、コンテンツ推奨、または検索拡張生成(RAG)システムなどのアプリケーションを構築する際の重要なステップです。

LanceDBから埋め込みをクエリして取得する方法を探ってみましょう:

def similarity_search(query_embedding: List[float], k: int = 5) -> List[Dict[str, Any]]:
    """Perform a similarity search on the embeddings table."""
    return table.search(query_embedding).limit(k).to_list()

def get_text_embedding(text_query: str) -> List[float]:
    """Generate a text embedding for a given text query."""
    return twelvelabs_client.embed.text(text_query).embedding.float

# Example usage: Text-based search
text_query = "A person explaining machine learning concepts"
query_embedding = get_text_embedding(text_query)
search_results = similarity_search(query_embedding)

print(f"Top 5 results for query: '{text_query}'")
for i, result in enumerate(search_results):
    print(f"Result {i+1}:")
    print(f"  Video URL: {result['video_url']}")
    print(f"  Segment: {result['start_time']} - {result['end_time']} seconds")
    print(f"  Similarity Score: {result['_distance']}")
    print()

def get_video_segment(video_url: str, start_time: float, end_time: float) -> str:
    """Retrieve a video segment URL from a video URL using start and end times."""
    return f"{video_url}?start={start_time}&end={end_time}"

# Retrieve specific video segment for the top result
top_result = search_results[0]
video_segment = get_video_segment(top_result['video_url'], 
                                  top_result['start_time'], 
                                  top_result['end_time'])
print(f"Link to top result video segment: {video_segment}")

このコードの主要なコンポーネントを分解してみましょう:

  1. 類似性検索関数: クエリ埋め込みを受け取り、LanceDBテーブルから最も類似したk個の埋め込みを返すsimilarity_search関数を定義します。

  2. テキストから埋め込みへの変換: get_text_embedding関数は、Twelve LabsのEmbed APIを使用してテキストクエリを埋め込みに変換する方法を示しています。これにより、ビデオコンテンツに対してテキストベースの検索を実行できます。

  3. クエリプロセス

    • テキストクエリから始めます。

    • それを埋め込みに変換します。

    • LanceDBで類似性検索を実行します。

    • ビデオURL、セグメントのタイムスタンプ、類似性スコアなど、上位の結果を取得して表示します。

  4. ビデオセグメントの取得: 検索結果に基づいて特定のビデオセグメントへのリンクまたは参照を生成する方法を示すプレースホルダー関数get_video_segmentを含めています。

実際のアプリケーションでは、次のようなより高度なフィルタリングオプションを追加することをお勧めします:

# Example of filtering results by metadata
filtered_results = table.search(query_embedding).where("start_time > 10 AND end_time < 60").limit(5).to_list()

これにより、埋め込みベースの類似性検索と従来のメタデータフィルタリングを組み合わせて、より正確な結果を得ることができます。

RAGワークフローとの統合

ビデオ埋め込みシステムを検索拡張生成(RAG)ワークフローに統合する簡単な例を以下に示します:

from transformers import AutoTokenizer, AutoModelForSeq2SeqLMv

# Constants
MODEL_NAME = "google/flan-t5-base"
MAX_QUERY_TOKENS = 77

# Initialize model, tokenizer, and database
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
model = AutoModelForSeq2SeqLM.from_pretrained(MODEL_NAME)

def generate_response(prompt: str, max_length: int = 100) -> str:
    """Generate a response using FLAN-T5 model."""
    inputs = tokenizer(prompt, return_tensors="pt", max_length=512, truncation=True)
    outputs = model.generate(**inputs, max_length=max_length, num_return_sequences=1)
    return tokenizer.decode(outputs[0], skip_special_tokens=True)

def retrieve_relevant_segments(query: str, k: int = 3) -> list:
    """Retrieve relevant video segments based on the query."""
    truncated_query = ' '.join(query.split()[:MAX_QUERY_TOKENS])
    query_embedding = get_text_embedding(truncated_query)
    return similarity_search(query_embedding, k)

def create_context(results: list) -> str:
    """Create context from retrieved video segments."""
    return "\n".join(
        f"Video segment from {result['start_time']} to {result['end_time']} seconds: {result['video_url']}"
        for result in results
    )

def rag_workflow(user_query: str) -> str:
    """Execute the RAG (Retrieval-Augmented Generation) workflow."""
    relevant_segments = retrieve_relevant_segments(user_query)
    context = create_context(relevant_segments)
    
    prompt = f"""Context:
{context}

User Query: {user_query}

Based on the context provided about the video segments, please answer the user's query:"""
    
    return generate_response(prompt)

# Example usage
user_query = "What is the purpose of the video?"
rag_response = rag_workflow(user_query)
print("User Query:", user_query)
print("\nRAG Response:", rag_response)

このコードは、当社のビデオ埋め込みシステムを統合した基本的なRAGワークフローを示しています:

  1. まず、開発者が簡単にアクセスできるオープンソースのLLMであるFLAN-T5モデルを設定することから始めます。

  2. retrieve_relevant_segments関数は、以前に定義した類似性検索を使用して、ユーザーのクエリに関連するビデオセグメントを見つけます。

  3. create_contextは、取得したビデオセグメント情報をコンテキスト文字列にフォーマットします。

  4. rag_workflow関数がすべてをまとめます:

    • ユーザーのクエリに基づいて関連するビデオセグメントを取得します。

    • これらのセグメントからコンテキストを作成します。

    • コンテキストとユーザーのクエリを組み合わせたプロンプトを構築します。

    • FLAN-T5モデルを使用して、この充実したプロンプトに基づいて応答を生成します。

  5. 最後に、ビデオ内の機械学習の概念に関するクエリの例を使用して、ワークフローを示します。

このRAGシステムにより、言語モデルは、インデックスに登録したビデオコンテンツを活用することで、より情報に基づいたコンテキストに沿った応答を提供できます。これは、ビデオの要約の作成、ビデオコンテンツに関する特定の質問への回答、およびビデオ素材に基づくインサイトや説明の提供などのアプリケーションに特に強力です(Twelve Labs Generate APIで実現できることと同様です)。

パフォーマンスに関する考慮事項とベストプラクティス

Twelve LabsのEmbed APIとLanceDBを使用する場合、次のベストプラクティスを推奨します:

  • APIの使用を最適化するために、大規模なビデオデータセットの埋め込みリクエストをバッチ処理することを検討してください。

  • クエリのパフォーマンスを監視し、類似性検索の結果数(k)を調整して、精度と速度のバランスを取ります。

  • 多数のビデオを処理する場合は、API呼び出しとデータベースクエリを減らすために、頻繁にアクセスされる埋め込みのキャッシュ戦略を実装することを検討してください。

本番環境については、他にも以下の考慮事項があります:

  • API呼び出しとデータベース操作のエラー処理と再試行を実装します。

  • システム全体の応答性を向上させるために、埋め込み生成とデータベース挿入の非同期処理を検討してください。

  • 向上した精度とパフォーマンスの恩恵を受けるために、Twelve LabsがMarengoの新しいバージョンをリリースするたびに、埋め込みを定期的に更新してください。

結論と次のステップ

このチュートリアルでは、Twelve LabsのEmbed APIをLanceDBと統合して、強力なビデオ理解および検索システムを作成する方法を実演しました。埋め込みの生成、保存、クエリ、およびセマンティック検索やRAGワークフローなどの実用的なアプリケーションについて説明しました。この統合は、高度なビデオベースのAIアプリケーションを構築するための無数の可能性を開きます。

さらにプロジェクトを強化するために、以下を検討してください:

付録

参考およびさらなる探索のために:

  1. 完全なColabノートブック

  2. Twelve Labs APIドキュメント

  3. LanceDBドキュメント

皆さんが何を作るのか楽しみにしています!Twelve LabsおよびLanceDBのコミュニティで、プロジェクトや経験を共有してください。ハッピーコーディング!

TLDR: Twelve LabsのEmbed APIとLanceDBを統合し、ビデオの理解と検索のための高度なAIアプリケーションを構築する方法を学びます。このガイドでは、環境のセットアップやビデオ埋め込みの生成から、それらを効率的に保存・クエリする方法まで、すべてを網羅しています。このチュートリアルでコラボレーションしてくれたLanceDBチームのJasmine Wang氏とAyush Chaurasia氏に深く感謝いたします。

はじめに

高度なビデオ理解と検索のために、Twelve LabsのEmbed APILanceDBを統合するこのチュートリアルへようこそ。このガイドでは、これら2つの強力なテクノロジーを活用して、ビデオコンテンツをかつてない精度と効率で処理および分析できるAIアプリケーションを作成する方法を実演します。

Twelve LabsのEmbed APIは、ビデオコンテンツの本質を捉える豊富なマルチモーダル埋め込みを生成し、LanceDBは、これらの高次元ベクトルを大規模に保存、インデックス登録、およびクエリすることに優れたサーバーレスベクトルデータベースです。これらのテクノロジーを組み合わせることで、セマンティックビデオ検索エンジン、コンテンツベースの推奨システム、ビデオストリームにおける異常検知などのアプリケーションを作成できます。

セットアップとインストール

コア機能に飛び込む前に、環境をセットアップし、必要なライブラリをインストールしましょう。

必要なライブラリのインストール

まず、Twelve Labs SDKとLanceDBをインストールします。ノートブックのセルで次のコマンドを実行します。

!pip install twelvelabs lancedb

このコマンドは両方のライブラリをインストールし、Twelve Labsのビデオ処理機能とLanceDBのベクトル保存およびクエリ機能へのアクセスを提供します。

Twelve Labsでの認証

次に、Twelve Labs APIの認証をセットアップする必要があります。APIキーを安全に保存するために環境変数を使用します。

from twelvelabs import TwelveLabs
import os

# Retrieve the API key from environment variables
TWELVE_LABS_API_KEY = os.getenv('TWELVE_LABS_API_KEY')

# Initialize the Twelve Labs client
twelvelabs_client = TwelveLabs(api_key=TWELVE_LABS_API_KEY)

注: このコードを実行する前に、実際のAPIキーを使用して TWELVE_LABS_API_KEY 環境変数を設定していることを確認してください。

export TWELVE_LABS_API_KEY='your_api_key_here'

LanceDBの初期化

次に、LanceDBへの接続を初期化しましょう。

import lancedb
import pyarrow as pa

# Create or connect to a LanceDB database
db = lancedb.connect("my_video_embeddings_db")

# Define the schema for your video embeddings
schema = pa.schema(
    [
        pa.field("video_id", pa.string()),
        pa.field("embedding", pa.list_(pa.float32(), 1024)),
        pa.field("start_time", pa.float32()),
        pa.field("end_time", pa.float32()),
        pa.field("video_url", pa.string())
    ]
)

# Create a table for storing video embeddings
table = db.create_table("video_embeddings", schema=schema, mode="overwrite")

このコードは、新しいLanceDBデータベースを作成し(または既存のデータベースに接続し)、ビデオ埋め込みを保存するための専用テーブルをセットアップします。

  • pyarrowライブラリをインポートし、pa.schemaを使用してlancedbライブラリが想定する形式でスキーマを定義します。Pydanticを使用してスキーマを定義することもできます。

  • テーブルのスキーマを定義します。これには以下が含まれます:

    • video_id: 各埋め込みの一意の識別子

    • embedding: ビデオセグメントのベクトル表現(1024はTwelve Labs Embed APIによって提供されるビデオ埋め込みの次元数です)

    • start_time および end_time: ビデオセグメントの時間情報

    • video_url: ビデオのソース

  • create_table メソッドは、テーブル名、定義されたスキーマ、およびテーブルがすでに存在する場合に再作成するためのモード「overwrite」を指定して呼び出されます。

Twelve Labs Embed APIを使用したビデオ埋め込みの生成

このセクションでは、Twelve Labs Embed APIを使用して、ビデオコンテンツからマルチモーダル埋め込みを生成します。これらの埋め込みは、視覚的要素、音声、時間情報など、ビデオの豊かなコンテキストを捉えます。

まず、指定されたビデオURLの埋め込みを生成する関数を定義しましょう。

from twelvelabs.models.embed import EmbeddingsTask

def generate_embedding(video_url: str) -> tuple[List[Dict[str, Any]], Any]:
    """Generate embeddings for a given video URL."""
    task = twelvelabs_client.embed.task.create(
        engine_name="Marengo-retrieval-2.6",
        video_url=video_url
    )
    
    def on_task_update(task: EmbeddingsTask):
        print(f"  Status={task.status}")

    task.wait_for_done(sleep_interval=2, callback=on_task_update)
    task_result = twelvelabs_client.embed.task.retrieve(task.id)

    embeddings = [{
        'embedding': v.embedding.float,
        'start_offset_sec': v.start_offset_sec,
        'end_offset_sec': v.end_offset_sec,
        'embedding_scope': v.embedding_scope
    } for v in task_result.video_embeddings]
    
    return embeddings, task_result

この関数は、埋め込みタスクを作成し、その進行状況を監視して、完了すると結果を取得します。埋め込みのリストを、その時間情報およびスコープとともに返します。

次に、この関数を使用してサンプルビデオの埋め込みを生成してみましょう。

# Example usage
video_url = "https://example.com/your-video.mp4"

# Generate embeddings for the video
embeddings, task_result = generate_embedding(video_url)

print(f"Generated {len(embeddings)} embeddings for the video")
for i, emb in enumerate(embeddings):
    print(f"Embedding {i+1}:")
    print(f"  Scope: {emb['embedding_scope']}")
    print(f"  Time range: {emb['start_offset_sec']} - {emb['end_offset_sec']} seconds")
    print(f"  Embedding vector (first 5 values): {emb['embedding'][:5]}")
    print()

このコードスニペットは、ビデオの埋め込みを生成し、結果を確認する方法を示しています。各埋め込みはビデオのセグメントを表し、そのマルチモーダルな特性を捉えています。

埋め込みについて理解する:

  1. 埋め込みベクトル: ビデオセグメントの内容を高次元で表現したもので、視覚、音声、コンテキスト情報を捉えます。

  2. 時間範囲: 埋め込みによって表されるビデオセグメントの開始時間と終了時間。

  3. 埋め込みスコープ: 埋め込みのタイプを示します(例:フルビデオ埋め込みの場合は「video」)。

LanceDBへの埋め込みの保存

Twelve LabsのEmbed APIを使用してビデオ埋め込みを生成した後の次の重要なステップは、これらの埋め込みをLanceDBに効率的に保存することです。これにより、迅速な検索が可能になり、類似性検索やコンテンツ推奨などのさまざまな下流のタスクが可能になります。

ビデオ埋め込みをLanceDBに保存するプロセスを見ていきましょう:

import uuid

def insert_embeddings(embeddings: List[Dict[str, Any]], video_url: str) -> None:
    """Insert embeddings into the database."""
    data_to_insert = [{
        "id": str(uuid.uuid4()),
        "embedding": emb['embedding'],
        "start_time": emb['start_offset_sec'],
        "end_time": emb['end_offset_sec'],
        "video_url": video_url
    } for emb in embeddings]
    
    table.add(data_to_insert)
    print(f"Inserted {len(data_to_insert)} embeddings for video: {video_url}")

# Use the function to insert the embeddings we generated earlier
insert_embeddings(embeddings, video_url)

# Verify the insertion
print(f"Total embeddings in the table: {len(table)}")

このコードが何を行うのかを分解してみましょう:

  1. 生成された埋め込みとビデオURLを受け取り、それらをLanceDBへの挿入用にフォーマットしてテーブルに追加する関数insert_embeddingsを作成します。

  2. この関数を使用して、前のステップで生成した埋め込みを挿入します。

  3. 最後に、テーブル内の埋め込みの総数を確認して、挿入を検証します。

このアプローチにより、埋め込みベクトルだけでなく、時間情報やソースビデオのURLなどの重要なメタデータも保存できます。この追加情報は、ワークフローの後半のステップでの検索やコンテキスト化に役立ちます。

埋め込みのクエリと検索

ビデオ埋め込みをLanceDBに保存したので、その強力なクエリ機能を活用して類似性検索を実行し、関連するビデオセグメントを取得できます。これは、セマンティックビデオ検索、コンテンツ推奨、または検索拡張生成(RAG)システムなどのアプリケーションを構築する際の重要なステップです。

LanceDBから埋め込みをクエリして取得する方法を探ってみましょう:

def similarity_search(query_embedding: List[float], k: int = 5) -> List[Dict[str, Any]]:
    """Perform a similarity search on the embeddings table."""
    return table.search(query_embedding).limit(k).to_list()

def get_text_embedding(text_query: str) -> List[float]:
    """Generate a text embedding for a given text query."""
    return twelvelabs_client.embed.text(text_query).embedding.float

# Example usage: Text-based search
text_query = "A person explaining machine learning concepts"
query_embedding = get_text_embedding(text_query)
search_results = similarity_search(query_embedding)

print(f"Top 5 results for query: '{text_query}'")
for i, result in enumerate(search_results):
    print(f"Result {i+1}:")
    print(f"  Video URL: {result['video_url']}")
    print(f"  Segment: {result['start_time']} - {result['end_time']} seconds")
    print(f"  Similarity Score: {result['_distance']}")
    print()

def get_video_segment(video_url: str, start_time: float, end_time: float) -> str:
    """Retrieve a video segment URL from a video URL using start and end times."""
    return f"{video_url}?start={start_time}&end={end_time}"

# Retrieve specific video segment for the top result
top_result = search_results[0]
video_segment = get_video_segment(top_result['video_url'], 
                                  top_result['start_time'], 
                                  top_result['end_time'])
print(f"Link to top result video segment: {video_segment}")

このコードの主要なコンポーネントを分解してみましょう:

  1. 類似性検索関数: クエリ埋め込みを受け取り、LanceDBテーブルから最も類似したk個の埋め込みを返すsimilarity_search関数を定義します。

  2. テキストから埋め込みへの変換: get_text_embedding関数は、Twelve LabsのEmbed APIを使用してテキストクエリを埋め込みに変換する方法を示しています。これにより、ビデオコンテンツに対してテキストベースの検索を実行できます。

  3. クエリプロセス

    • テキストクエリから始めます。

    • それを埋め込みに変換します。

    • LanceDBで類似性検索を実行します。

    • ビデオURL、セグメントのタイムスタンプ、類似性スコアなど、上位の結果を取得して表示します。

  4. ビデオセグメントの取得: 検索結果に基づいて特定のビデオセグメントへのリンクまたは参照を生成する方法を示すプレースホルダー関数get_video_segmentを含めています。

実際のアプリケーションでは、次のようなより高度なフィルタリングオプションを追加することをお勧めします:

# Example of filtering results by metadata
filtered_results = table.search(query_embedding).where("start_time > 10 AND end_time < 60").limit(5).to_list()

これにより、埋め込みベースの類似性検索と従来のメタデータフィルタリングを組み合わせて、より正確な結果を得ることができます。

RAGワークフローとの統合

ビデオ埋め込みシステムを検索拡張生成(RAG)ワークフローに統合する簡単な例を以下に示します:

from transformers import AutoTokenizer, AutoModelForSeq2SeqLMv

# Constants
MODEL_NAME = "google/flan-t5-base"
MAX_QUERY_TOKENS = 77

# Initialize model, tokenizer, and database
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
model = AutoModelForSeq2SeqLM.from_pretrained(MODEL_NAME)

def generate_response(prompt: str, max_length: int = 100) -> str:
    """Generate a response using FLAN-T5 model."""
    inputs = tokenizer(prompt, return_tensors="pt", max_length=512, truncation=True)
    outputs = model.generate(**inputs, max_length=max_length, num_return_sequences=1)
    return tokenizer.decode(outputs[0], skip_special_tokens=True)

def retrieve_relevant_segments(query: str, k: int = 3) -> list:
    """Retrieve relevant video segments based on the query."""
    truncated_query = ' '.join(query.split()[:MAX_QUERY_TOKENS])
    query_embedding = get_text_embedding(truncated_query)
    return similarity_search(query_embedding, k)

def create_context(results: list) -> str:
    """Create context from retrieved video segments."""
    return "\n".join(
        f"Video segment from {result['start_time']} to {result['end_time']} seconds: {result['video_url']}"
        for result in results
    )

def rag_workflow(user_query: str) -> str:
    """Execute the RAG (Retrieval-Augmented Generation) workflow."""
    relevant_segments = retrieve_relevant_segments(user_query)
    context = create_context(relevant_segments)
    
    prompt = f"""Context:
{context}

User Query: {user_query}

Based on the context provided about the video segments, please answer the user's query:"""
    
    return generate_response(prompt)

# Example usage
user_query = "What is the purpose of the video?"
rag_response = rag_workflow(user_query)
print("User Query:", user_query)
print("\nRAG Response:", rag_response)

このコードは、当社のビデオ埋め込みシステムを統合した基本的なRAGワークフローを示しています:

  1. まず、開発者が簡単にアクセスできるオープンソースのLLMであるFLAN-T5モデルを設定することから始めます。

  2. retrieve_relevant_segments関数は、以前に定義した類似性検索を使用して、ユーザーのクエリに関連するビデオセグメントを見つけます。

  3. create_contextは、取得したビデオセグメント情報をコンテキスト文字列にフォーマットします。

  4. rag_workflow関数がすべてをまとめます:

    • ユーザーのクエリに基づいて関連するビデオセグメントを取得します。

    • これらのセグメントからコンテキストを作成します。

    • コンテキストとユーザーのクエリを組み合わせたプロンプトを構築します。

    • FLAN-T5モデルを使用して、この充実したプロンプトに基づいて応答を生成します。

  5. 最後に、ビデオ内の機械学習の概念に関するクエリの例を使用して、ワークフローを示します。

このRAGシステムにより、言語モデルは、インデックスに登録したビデオコンテンツを活用することで、より情報に基づいたコンテキストに沿った応答を提供できます。これは、ビデオの要約の作成、ビデオコンテンツに関する特定の質問への回答、およびビデオ素材に基づくインサイトや説明の提供などのアプリケーションに特に強力です(Twelve Labs Generate APIで実現できることと同様です)。

パフォーマンスに関する考慮事項とベストプラクティス

Twelve LabsのEmbed APIとLanceDBを使用する場合、次のベストプラクティスを推奨します:

  • APIの使用を最適化するために、大規模なビデオデータセットの埋め込みリクエストをバッチ処理することを検討してください。

  • クエリのパフォーマンスを監視し、類似性検索の結果数(k)を調整して、精度と速度のバランスを取ります。

  • 多数のビデオを処理する場合は、API呼び出しとデータベースクエリを減らすために、頻繁にアクセスされる埋め込みのキャッシュ戦略を実装することを検討してください。

本番環境については、他にも以下の考慮事項があります:

  • API呼び出しとデータベース操作のエラー処理と再試行を実装します。

  • システム全体の応答性を向上させるために、埋め込み生成とデータベース挿入の非同期処理を検討してください。

  • 向上した精度とパフォーマンスの恩恵を受けるために、Twelve LabsがMarengoの新しいバージョンをリリースするたびに、埋め込みを定期的に更新してください。

結論と次のステップ

このチュートリアルでは、Twelve LabsのEmbed APIをLanceDBと統合して、強力なビデオ理解および検索システムを作成する方法を実演しました。埋め込みの生成、保存、クエリ、およびセマンティック検索やRAGワークフローなどの実用的なアプリケーションについて説明しました。この統合は、高度なビデオベースのAIアプリケーションを構築するための無数の可能性を開きます。

さらにプロジェクトを強化するために、以下を検討してください:

付録

参考およびさらなる探索のために:

  1. 完全なColabノートブック

  2. Twelve Labs APIドキュメント

  3. LanceDBドキュメント

皆さんが何を作るのか楽しみにしています!Twelve LabsおよびLanceDBのコミュニティで、プロジェクトや経験を共有してください。ハッピーコーディング!