
チュートリアル
Twelve Labs と Milvus を使用したマルチモーダル検索拡張生成(RAG)アプリケーションの構築

リシケシュ・ヤダフ
このチュートリアルでは、Fashion AIチャットアプリケーションの構築手順を解説します。このアプリケーションは、Twelve LabsのEmbed API(Marengo 2.7)とMilvusを使用することで、テキスト、画像、動画ベースの商品検索を可能にし、さらにGPT-3.5を活用したRAG(検索拡張生成)システムによって、取得したマルチモーダル埋め込みから会話形式のファッション提案を生成します。
このチュートリアルでは、Fashion AIチャットアプリケーションの構築手順を解説します。このアプリケーションは、Twelve LabsのEmbed API(Marengo 2.7)とMilvusを使用することで、テキスト、画像、動画ベースの商品検索を可能にし、さらにGPT-3.5を活用したRAG(検索拡張生成)システムによって、取得したマルチモーダル埋め込みから会話形式のファッション提案を生成します。

この記事の内容
No headings found on page
ニュースレターに登録する
ニュースレターに登録する
ビデオ理解に関する最新の技術進歩、チュートリアル、業界の動向をお届けします
ビデオ理解に関する最新の技術進歩、チュートリアル、業界の動向をお届けします
AIを活用してビデオを検索、分析、探索します。
2025/01/22
13分
記事へのリンクをコピー
はじめに
言葉だけでなく視覚的な好みまで理解してくれる専属のファッションアドバイザーが、24時間365日いつでも利用できたらどうなるか、考えたことはありますか?気に入ったコーディネートの写真を見せるだけで、AIが瞬時に似たスタイルの提案をしてくれたり、憧れのルックを言葉で伝えるだけで、それにマッチするコーディネートの提案を受け取ったりすることを想像してみてください 👚
当社のFashion AIアシスタントアプリケーションは、次世代の製品発見(プロダクトディスカバリー)のために構築されています。このチュートリアルでは、マルチモーダルな検索と対話型AIを組み合わせた、当社の高度なファッション推薦システムについて説明します。このシステムは、 TwelveLabs EmbedのMarengo-retrieval-2.7モデルを使用して、テキストとビデオコンテンツの両方から埋め込み(embeddings)を生成し、異なるデータタイプ間でのシームレスな検索を可能にします。
このアプリケーションは、効率的な類似性検索を行うためのベクトルデータベースとして Milvusを使用し、自然言語処理のためにOpenAIのgpt-3.5を統合しています。テキストと画像両方の入力からファッションに関するクエリを処理し、関連する製品説明と正確なビデオタイムスタンプを見つけ出し、ユーザーが探しているアイテムがビデオ内のどこに登場するかを正確に示します。
この強力な組み合わせにより、テキストとビジュアルの両方のクエリを理解し、マルチモーダルなコンテンツで強化された文脈に沿った回答を提供するシステムが構築されます。
このアプリケーションがどのように機能するのか、そして TwelveLabs Python SDKおよび Milvus Python SDKを使用して同様のソリューションをどのように構築できるかを見ていきましょう。
アプリケーションのデモはこちらからお試しいただけます: Fashion AI Chat App。
コードにアクセスしてアプリを直接試してみたい場合は、こちらの Replit Templateをご利用いただけます。
前提条件
Twelve Labs Playgroundに登録して、APIキーを生成します。
設定ガイドに従って、Milvusサーバーのインストールとセットアップを行います。
このアプリケーションのリポジトリは Fashion AI Chat Applicationにあります。
Python、Streamlit、CSSについて、ある程度の知識があらかじめ必要となります。

アプリケーションの仕組み
ここでは、アプリケーションの動作の概要と、そのコンポーネントがどのように相互作用するかを示します。

このアプリケーションには、3つの主な機能があります:
埋め込みの生成とMilvusベクトルデータベースへの挿入
クエリ画像からビデオセグメントへの検索
マルチモーダル検索(テキストおよびビデオセグメント)のための、対話型Retrieval Augmented Generation (RAG)
このチュートリアルアプリケーションでは、Twelve Labs Embed - Marengo-retrieval-2.7を使用して、製品カタログデータをベクトルデータベースに格納する方法を示します。テキストとビデオコンテンツの両方に該当する埋め込みは、同一のMilvusベクトルデータベースのコレクションに保存されます。わかりやすさと再利用性を考慮して、Twelve Labsの埋め込み関数は各ユーティリティ関数内で定義されています。
アプリケーションを期待通りに動作させるには、埋め込みデータをコレクションに挿入する必要があります。または、このアプリケーションで使用されているこちらの提供サンプルデータを参照することもできます。
準備手順
Twelve Labs PlaygroundからAPIキーを取得し、環境変数に設定します。
GitHubからプロジェクトをクローンするか、 Replit Templateを使用します。事前に定義された仮想環境が付属しているため、Replitテンプレートの使用をお勧めします。セットアップ時にはシークレットファイルを追加することを忘れずに、 Replit のシークレットキーに関するドキュメントを参照してください。
Twelve Labs、Milvus接続、およびLLMモデル用のOpenAI APIキーを含む
.envファイルを作成します。
Milvusベクトルデータベースの認証情報にはZilliz Cloudを使用した設定を行っていますが、他の接続方法については 設定ガイドでも確認できます。
TWELVELABS_API_KEY="your_twelvelabs_key" COLLECTION_NAME="your_collection_name" URL="your_milvus_url" TOKEN="your_milvus_token" OPENAI_API_KEY="your_openai_key"
これらの手順が完了したら、開発を始める準備は完了です!
ファッションチャットアプリケーションの実装解説
このチュートリアルでは、最小限のフロントエンドを備えたStreamlitアプリケーションを作成します。ディレクトリ構造を見てみましょう:
├── pages/ │ ├── add_product_page.py │ └── visual_search.py ├── .gitignore ├── app.py └── utils.py └── requirements.txt
Streamlit アプリケーションの作成
セットアップが完了したところで、Streamlitアプリケーションを構築していきましょう。
仮想環境の作成に必要なすべての依存関係は、こちらで確認できます: requirements.txt
Pythonの仮想環境を作成し、次のコマンドを使用してアプリケーションの環境をセットアップします:
pip install -r requirements.txt
ユーティリティ関数の定義
このセクションでは、中心となるロジックと実装が含まれている utility.pyについて説明します。各サブセクションを詳しく処理していきましょう:
1 - 接続のセットアップ
最初のステップでは、環境変数をロードし、LLMアクセスのためのOpenAI、コレクション管理のためのMilvus、そしてTwelve Labsの初期化のための接続を確立します。
# Load environment variables COLLECTION_NAME = os.getenv('COLLECTION_NAME') URL = os.getenv('URL') TOKEN = os.getenv('TOKEN') TWELVELABS_API_KEY = os.getenv('TWELVELABS_API_KEY') # Initialize connections openai_client = OpenAI() connections.connect(uri=URL, token=TOKEN) collection = Collection(COLLECTION_NAME) collection.load() twelvelabs_client = TwelveLabs(api_key=TWELVELABS_API_KEY)
2 - Twelve Labs Embed API を使用した埋め込みの生成
このセクションでは、マルチモーダル検索用の Marengo-retrieval-2.7 モデルを搭載したTwelve Labs SDKを使用した埋め込み生成について説明します。このソリューションは、効率的な検索埋め込みを作成するために、テキストとビデオの処理を統合しています。
# Generate text and segmented video embeddings for a product def generate_embedding(product_info): try: st.write("Starting embedding generation process...") st.write(f"Processing product: {product_info['title']}") # Initialize the Twelve Labs client twelvelabs_client = TwelveLabs(api_key=TWELVELABS_API_KEY) st.write("TwelveLabs client initialized successfully") st.write("Attempting to generate text embedding...") # Formatting the Text Data of Product Catalogue text = f"product type: {product_info['title']}. " \ f"product description: {product_info['desc']}. " \ f"product category: fashion apparel." st.write(f"Generating embedding for text: {text}") # Generating the Text Embeddings text_embedding = twelvelabs_client.embed.create( model_name="Marengo-retrieval-2.7", text=text ).text_embedding.segments[0].embeddings_float st.write("Text embedding generated successfully") # Create and wait for video embedding task st.write("Creating video embedding task...") video_task = twelvelabs_client.embed.task.create( model_name="Marengo-retrieval-2.7", video_url=product_info['video_url'], video_clip_length=6 ) def on_task_update(task): st.write(f"Video processing status: {task.status}") st.write("Waiting for video processing to complete...") video_task.wait_for_done(sleep_interval=2, callback=on_task_update) # Retrieve segmented video embeddings video_task = video_task.retrieve() if not video_task.video_embedding or not video_task.video_embedding.segments: raise Exception("Failed to retrieve video embeddings") video_segments = video_task.video_embedding.segments st.write(f"Retrieved {len(video_segments)} video segments") video_embeddings = [] for segment in video_segments: video_embeddings.append({ 'embedding': segment.embeddings_float, 'metadata': { 'scope': 'clip', 'start_time': segment.start_offset_sec, 'end_time': segment.end_offset_sec, 'video_url': product_info['video_url'] } }) return { 'text_embedding': text_embedding, 'video_embeddings': video_embeddings }, None except Exception as e: st.error("Error in embedding generation") st.error(f"Error message: {str(e)}") return None, str(e)
このプロセスは、一貫性があり意味のある埋め込みを保証するために、テキストを構造化およびフォーマットすることから始まります。次に動画の埋め込みが行われ、ステータスの監視や進捗の追跡が処理されます。各ビデオセグメントは6秒に設定されています(video_clip_length=6)。
メタデータの追跡は、トレーサビリティを維持し、正確なビデオセグメントおよびテキスト検索を可能にするために不可欠です。その後、結果はMilvusベクトルデータベースのコレクションに格納されます。
3 - Milvus ベクトルデータベースへの埋め込みの挿入
ベクトルデータベースは、高次元の埋め込みデータを効率的に保存、検索することができます。このセクションでは、適切なメタデータ管理およびエラーハンドリングを行いつつ、テキストとビデオ両方の埋め込みをMilvusベクトルデータベースに挿入する方法を説明します。
# Insert text and all video segment embeddings into Milvus Collection def insert_embeddings(embeddings_data, product_info): try: metadata = { "product_id": product_info['product_id'], "title": product_info['title'], "description": product_info['desc'], "video_url": product_info['video_url'], "link": product_info['link'] } # Insert text embedding text_entry = { "id": int(uuid.uuid4().int & (1<<63)-1), "vector": embeddings_data['text_embedding'], "metadata": metadata, "embedding_type": "text" } collection.insert([text_entry]) st.write("Text embedding inserted successfully") # Insert each video segment embedding for video_segment in embeddings_data['video_embeddings']: video_entry = { "id": int(uuid.uuid4().int & (1<<63)-1), "vector": video_segment['embedding'], "metadata": {**metadata, **video_segment['metadata']}, "embedding_type": "video" } collection.insert([video_entry]) st.write(f"Inserted {len(embeddings_data['video_embeddings'])} video segment embeddings") return True except Exception as e: st.error(f"Error inserting embeddings: {str(e)}") return False
ID、ベクトル、メタデータを定義した後、同じコレクション空間内で異なるフォーマットに対応できるようにするために embedding_type を指定します。その後、データは collection.insert メソッドを使用して挿入されます。
4 - 画像から動画を検索するためのセマンティック検索の実装
画像クエリによるセマンティック検索により、類似するビデオコンテンツを探すことができます。この実装は、Twelve Labsの埋め込み機能とMilvusのベクトル検索を組み合わせています。ユーティリティ関数であるsearched_similar_videosがどのように機能するかを以下に示します:

まず、システムは製品画像をロードして読み込み、類似する製品が含まれるビデオセグメントを探します。次にTwelve Labsの埋め込み(embed)が画像を埋め込みに変換し、Milvusコレクションに格納された動画埋め込みに対してセマンティック検索を実行します。
# Load and Read Query Image image_path = "path/to/your/image.jpg" with open(image_path, 'rb') as f: image_file = f.read() # Intializing of client and Generation of Image Emebedding twelvelabs_client = TwelveLabs(api_key=TWELVELABS_API_KEY) image_embedding = twelvelabs_client.embed.create( model_name="Marengo-retrieval-2.7", image_file=image_file ).image_embedding.segments[0].embeddings_float
検索には、速度と精度のバランスを取るために、コサイン類似度とクラスターパラメータが使用されます。collection.search が embedding_type == 'video' やその他のパラメータとともに実行されると、指定された数の製品ビデオセグメントを検索(リトリーブ)します。
search_params = { "metric_type": "COSINE", "params": { "nprobe": 1024, "ef": 64 } } # Search relevant video segments results = collection.search( data=[image_embedding], anns_field="vector", param=search_params, limit=2, expr="embedding_type == 'video'", output_fields=["metadata"] )
システムは結果を処理し、明確にするために類似度のスコアを割合(%)に変換し、メタデータを構造化された辞書形式に整理します。
search_results = [] for hits in results: for hit in hits: metadata = hit.metadata # Convert score from [-1,1] to [0,100] range similarity = round((hit.score + 1) * 50, 2) similarity = max(0, min(100, similarity)) search_results.append({ 'Title': metadata.get('title', ''), 'Description': metadata.get('description', ''), 'Link': metadata.get('link', ''), 'Start Time': f"{metadata.get('start_time', 0):.1f}s", 'End Time': f"{metadata.get('end_time', 0):.1f}s", 'Video URL': metadata.get('video_url', ''), 'Similarity': f"{similarity}%", 'Raw Score': hit.score }) # Sort by similarity score in descending order search_results.sort(key=lambda x: float(x['Similarity'].rstrip('%')), reverse=True)
ソートされた結果は、画面に表示することができます。UIの実装はvision_searchで確認できます。
5 - RAG (Retrieval Augmented Generation) システムの開発
このセクションでは、ファッションアシスタントの文脈における質問応答に焦点を当て、マルチモーダル検索とLLM (gpt-3.5) を組み合わせて文脈に即した回答を作成します。効果的なパーソナライズ化のために、メタデータを持つテキストおよび動画データからのマルチモーダル検索を重視しています。get_rag_response関数がRAG機能を実装しています。

プロセスは、Twelve Labsの埋め込みでMarengo-retrieval-2.7エンジンを使用してユーザーの質問と文脈をテキスト埋め込みに変換し、データベース全体に対するセマンティック検索を可能にすることから始まります。
# Sample question question_with_context = f"fashion product: Suggest me black dresses for a party" # Generate embedding for the question question_embedding = twelvelabs_client.embed.create( model_name="Marengo-retrieval-2.7", text=question_with_context ).text_embedding.segments[0].embeddings_float
セマンティック検索のパラメータを設定した後、システムはテキストと動画セグメントに対して別々にコレクション検索を実行します。動画セグメント検索では、テキストクエリに最も関連するセグメントを見つけ出し、ユーザーに包括的な探索オプションを提供します。
expr メソッドにより検索条件が絞り込まれ、テキスト検索と動画検索で異なるリミット値が適用されます。典型的な検索では、メタデータを持つ2つのテキスト製品と3つの関連ビデオセグメントを検索します。
# Configure search parameters search_params = { "metric_type": "COSINE", "params": { "nprobe": 1024, "ef": 64 } } # Search for relevant text embeddings text_results = collection.search( data=[question_embedding], anns_field="vector", param=search_params, limit=2, # Get top 2 text matches expr="embedding_type == 'text'", output_fields=["metadata"] ) # Search for relevant video segments video_results = collection.search( data=[question_embedding], anns_field="vector", param=search_params, limit=3, # Get top 3 video segments expr="embedding_type == 'video'", output_fields=["metadata"] )
結果の処理中、システムは各セグメントからメタデータを抽出し、類似度のスコアを割合(%)に変換し、製品の詳細を構造化された辞書形式に整理します。
# Process text results text_docs = [] for hits in text_results: for hit in hits: metadata = hit.metadata similarity = round((hit.score + 1) * 50, 2) similarity = max(0, min(100, similarity)) text_docs.append({ "title": metadata.get('title', 'Untitled'), "description": metadata.get('description', 'No description available'), "product_id": metadata.get('product_id', ''), "video_url": metadata.get('video_url', ''), "link": metadata.get('link', ''), "similarity": similarity, "raw_score": hit.score, "type": "text" }) # Process video results video_docs = [] for hits in video_results: for hit in hits: metadata = hit.metadata similarity = round((hit.score + 1) * 50, 2) similarity = max(0, min(100, similarity)) video_docs.append({ "title": metadata.get('title', 'Untitled'), "description": metadata.get('description', 'No description available'), "product_id": metadata.get('product_id', ''), "video_url": metadata.get('video_url', ''), "link": metadata.get('link', ''), "similarity": similarity, "raw_score": hit.score, "start_time": metadata.get('start_time', 0), "end_time": metadata.get('end_time', 0), "type": "video" })
関連する情報を収集した後、システムはRetrieval Augmented Generation(検索拡張生成)のステップに進みます。検索されたコンテキスト(文脈情報)は、効率的なLLM処理のために構造化されます。
システムは、システムプロンプトとユーザープロンプトの両方を定義します。システムプロンプトはファッションアドバイザーとしての役割を確立し、ユーザープロンプトはユーザーのクエリとデータベースから取得したコンテキストを組み合わせます。コンテキスト取得が失敗した場合のエラーハンドリングも含まれています。
# Handle case when no results found if not text_docs and not video_docs: response_data = { "response": "I couldn't find any matching products. Try describing what you're looking for differently.", "metadata": None } else: # Create context from text results for LLM text_context = "\n\n".join([ f"Product: {doc['title']}\nDescription: {doc['description']}\nLink: {doc['link']}" for doc in text_docs ]) # Prepare messages for OpenAI messages = [ { "role": "system", "content": """You are a professional fashion advisor and AI shopping assistant. Organize your response in the following format: First, provide a brief, direct answer to the user's query Then, describe any relevant products found that match their request, including: - Product name and key features - Why this product matches their needs - Style suggestions for how to wear or use the item Finally, provide any additional style advice or recommendations Keep your response engaging and natural while maintaining this clear structure. Focus on being helpful and specific rather than promotional.""" }, { "role": "user", "content": f"""Query: {question} Available Products: {text_context} Please provide fashion advice and product recommendations based on these options.""" } ] # Get response from OpenAI chat_response = openai_client.chat.completions.create( model="gpt-3.5-turbo", messages=messages, temperature=0.5, max_tokens=500 ) # Format final response response_data = { "response": chat_response.choices[0].message.content, "metadata": { "sources": text_docs + video_docs, "total_sources": len(text_docs) + len(video_docs), "text_sources": len(text_docs), "video_sources": len(video_docs) } }
text_context には検索された情報が含まれます。gpt-3.5-turbo を使用して、システムはシステムプロンプトで指定されたように、説明、提案、ユーザー向けのガイダンスを含む応答を生成します。その応答は、アクセスしやすい辞書構造にフォーマットされます。UI実装の詳細については、appを参照してください。
デモアプリケーション
このデモは、データベース挿入の簡略化、効率的なマルチモーダル検索の有効化、そしてユーザーのための検索機能の向上の3つの主な目的を持ったパーツに分かれています。
データベースへのテキストおよびビデオ埋め込みの生成と挿入
LLMとのチャット対話を通じたマルチモーダルデータの検索
関連するビデオセグメントを見つけるための、製品画像ベースの検索
製品データカタログには、製品ID、テキスト、説明、リンク、およびビデオURLなどのフィールドが含まれます。テキストデータは埋め込みに変換され、その他のデータはメタデータとして保存されます。動画セグメントについて、システムは動画URLを処理します。すべての埋め込みは単一のコレクションに保存されます。

マルチモーダル検索の例として、「メンズの黒いTシャツを探しています」というクエリがあります。

セマンティックビデオ検索では、黒いTシャツの画像をクエリとして使用し、上位2件の結果を表示する場合のようになります。

チュートリアルを応用するためのその他のアイデア
アプリケーションの仕組みと開発プロセスを理解することは、ユーザーのニーズを捉えた革新的な製品を作成するのに役立ちます。ビデオコンテンツクリエイター向けの応用可能なユースケースを提案します:
🛍️ Eコマース:テキストおよび画像クエリを用いた商品検索とおすすめ機能の強化
🎵 音楽ディスカバリー:オーディオクリップやユーザーの好みに基づいて、似た曲、アーティスト、またはジャンルを検索
🎥 インテリジェント動画検索エンジン:視覚および音声コンテンツに基づいて動画を検索し、コンテンツクリエイター、ジャーナリスト、研究者を支援
🗺️ パーソナライズされた旅行プランナー:ユーザーの好み、レビュー、目的地のデータに基づいて旅行の旅程を作成
📚 教育リソース管理:ドキュメント、プレゼンテーション、ビデオなどの学習教材を、学習内容のニーズに基づいて整理して検索
結論
このチュートリアルでは、Twelve LabsとMilvusベクトルデータベースによって駆動する埋め込みを介した、マルチモーダル検索プロセスの実装を示しました。この実装は、視覚とテキストデータの両方を処理するスケーラブルなアプリケーションを構築する方法を開発者に示しています。チュートリアルにお付き合いいただきありがとうございました。ユーザーエクスペリエンスの向上やさまざまな課題を解決するためのご意見やアイデアを歓迎します。
追加リソース
埋め込み生成エンジンであるMarengo-retrieval-2.7についてさらに詳しく。Twelve Labsをさらに探索し、ビデオコンテンツ解析への理解を深めるには、以下のリソースを確認してください:
Discord コミュニティ:開発者や熱心なファンが集まる活気あるコミュニティに参加して、アイデアを議論したり、質問したり、プロジェクトをシェアしましょう。Twelve Labs Discordに参加する
サンプルアプリケーション:次のプロジェクトのインスピレーションを得たり、新しい実装テクニックを学ぶためのさまざまなサンプルアプリケーションを探索できます
チュートリアルの探索:包括的なチュートリアルを通じて、Twelve Labsの実力をさらに深く知ることができます
これらのリソースを活用して知識を広げ、Twelve Labsのシステムビデオ理解テクノロジーを使用した革新的なアプリケーションを作成することをお勧めします。
はじめに
言葉だけでなく視覚的な好みまで理解してくれる専属のファッションアドバイザーが、24時間365日いつでも利用できたらどうなるか、考えたことはありますか?気に入ったコーディネートの写真を見せるだけで、AIが瞬時に似たスタイルの提案をしてくれたり、憧れのルックを言葉で伝えるだけで、それにマッチするコーディネートの提案を受け取ったりすることを想像してみてください 👚
当社のFashion AIアシスタントアプリケーションは、次世代の製品発見(プロダクトディスカバリー)のために構築されています。このチュートリアルでは、マルチモーダルな検索と対話型AIを組み合わせた、当社の高度なファッション推薦システムについて説明します。このシステムは、 TwelveLabs EmbedのMarengo-retrieval-2.7モデルを使用して、テキストとビデオコンテンツの両方から埋め込み(embeddings)を生成し、異なるデータタイプ間でのシームレスな検索を可能にします。
このアプリケーションは、効率的な類似性検索を行うためのベクトルデータベースとして Milvusを使用し、自然言語処理のためにOpenAIのgpt-3.5を統合しています。テキストと画像両方の入力からファッションに関するクエリを処理し、関連する製品説明と正確なビデオタイムスタンプを見つけ出し、ユーザーが探しているアイテムがビデオ内のどこに登場するかを正確に示します。
この強力な組み合わせにより、テキストとビジュアルの両方のクエリを理解し、マルチモーダルなコンテンツで強化された文脈に沿った回答を提供するシステムが構築されます。
このアプリケーションがどのように機能するのか、そして TwelveLabs Python SDKおよび Milvus Python SDKを使用して同様のソリューションをどのように構築できるかを見ていきましょう。
アプリケーションのデモはこちらからお試しいただけます: Fashion AI Chat App。
コードにアクセスしてアプリを直接試してみたい場合は、こちらの Replit Templateをご利用いただけます。
前提条件
Twelve Labs Playgroundに登録して、APIキーを生成します。
設定ガイドに従って、Milvusサーバーのインストールとセットアップを行います。
このアプリケーションのリポジトリは Fashion AI Chat Applicationにあります。
Python、Streamlit、CSSについて、ある程度の知識があらかじめ必要となります。

アプリケーションの仕組み
ここでは、アプリケーションの動作の概要と、そのコンポーネントがどのように相互作用するかを示します。

このアプリケーションには、3つの主な機能があります:
埋め込みの生成とMilvusベクトルデータベースへの挿入
クエリ画像からビデオセグメントへの検索
マルチモーダル検索(テキストおよびビデオセグメント)のための、対話型Retrieval Augmented Generation (RAG)
このチュートリアルアプリケーションでは、Twelve Labs Embed - Marengo-retrieval-2.7を使用して、製品カタログデータをベクトルデータベースに格納する方法を示します。テキストとビデオコンテンツの両方に該当する埋め込みは、同一のMilvusベクトルデータベースのコレクションに保存されます。わかりやすさと再利用性を考慮して、Twelve Labsの埋め込み関数は各ユーティリティ関数内で定義されています。
アプリケーションを期待通りに動作させるには、埋め込みデータをコレクションに挿入する必要があります。または、このアプリケーションで使用されているこちらの提供サンプルデータを参照することもできます。
準備手順
Twelve Labs PlaygroundからAPIキーを取得し、環境変数に設定します。
GitHubからプロジェクトをクローンするか、 Replit Templateを使用します。事前に定義された仮想環境が付属しているため、Replitテンプレートの使用をお勧めします。セットアップ時にはシークレットファイルを追加することを忘れずに、 Replit のシークレットキーに関するドキュメントを参照してください。
Twelve Labs、Milvus接続、およびLLMモデル用のOpenAI APIキーを含む
.envファイルを作成します。
Milvusベクトルデータベースの認証情報にはZilliz Cloudを使用した設定を行っていますが、他の接続方法については 設定ガイドでも確認できます。
TWELVELABS_API_KEY="your_twelvelabs_key" COLLECTION_NAME="your_collection_name" URL="your_milvus_url" TOKEN="your_milvus_token" OPENAI_API_KEY="your_openai_key"
これらの手順が完了したら、開発を始める準備は完了です!
ファッションチャットアプリケーションの実装解説
このチュートリアルでは、最小限のフロントエンドを備えたStreamlitアプリケーションを作成します。ディレクトリ構造を見てみましょう:
├── pages/ │ ├── add_product_page.py │ └── visual_search.py ├── .gitignore ├── app.py └── utils.py └── requirements.txt
Streamlit アプリケーションの作成
セットアップが完了したところで、Streamlitアプリケーションを構築していきましょう。
仮想環境の作成に必要なすべての依存関係は、こちらで確認できます: requirements.txt
Pythonの仮想環境を作成し、次のコマンドを使用してアプリケーションの環境をセットアップします:
pip install -r requirements.txt
ユーティリティ関数の定義
このセクションでは、中心となるロジックと実装が含まれている utility.pyについて説明します。各サブセクションを詳しく処理していきましょう:
1 - 接続のセットアップ
最初のステップでは、環境変数をロードし、LLMアクセスのためのOpenAI、コレクション管理のためのMilvus、そしてTwelve Labsの初期化のための接続を確立します。
# Load environment variables COLLECTION_NAME = os.getenv('COLLECTION_NAME') URL = os.getenv('URL') TOKEN = os.getenv('TOKEN') TWELVELABS_API_KEY = os.getenv('TWELVELABS_API_KEY') # Initialize connections openai_client = OpenAI() connections.connect(uri=URL, token=TOKEN) collection = Collection(COLLECTION_NAME) collection.load() twelvelabs_client = TwelveLabs(api_key=TWELVELABS_API_KEY)
2 - Twelve Labs Embed API を使用した埋め込みの生成
このセクションでは、マルチモーダル検索用の Marengo-retrieval-2.7 モデルを搭載したTwelve Labs SDKを使用した埋め込み生成について説明します。このソリューションは、効率的な検索埋め込みを作成するために、テキストとビデオの処理を統合しています。
# Generate text and segmented video embeddings for a product def generate_embedding(product_info): try: st.write("Starting embedding generation process...") st.write(f"Processing product: {product_info['title']}") # Initialize the Twelve Labs client twelvelabs_client = TwelveLabs(api_key=TWELVELABS_API_KEY) st.write("TwelveLabs client initialized successfully") st.write("Attempting to generate text embedding...") # Formatting the Text Data of Product Catalogue text = f"product type: {product_info['title']}. " \ f"product description: {product_info['desc']}. " \ f"product category: fashion apparel." st.write(f"Generating embedding for text: {text}") # Generating the Text Embeddings text_embedding = twelvelabs_client.embed.create( model_name="Marengo-retrieval-2.7", text=text ).text_embedding.segments[0].embeddings_float st.write("Text embedding generated successfully") # Create and wait for video embedding task st.write("Creating video embedding task...") video_task = twelvelabs_client.embed.task.create( model_name="Marengo-retrieval-2.7", video_url=product_info['video_url'], video_clip_length=6 ) def on_task_update(task): st.write(f"Video processing status: {task.status}") st.write("Waiting for video processing to complete...") video_task.wait_for_done(sleep_interval=2, callback=on_task_update) # Retrieve segmented video embeddings video_task = video_task.retrieve() if not video_task.video_embedding or not video_task.video_embedding.segments: raise Exception("Failed to retrieve video embeddings") video_segments = video_task.video_embedding.segments st.write(f"Retrieved {len(video_segments)} video segments") video_embeddings = [] for segment in video_segments: video_embeddings.append({ 'embedding': segment.embeddings_float, 'metadata': { 'scope': 'clip', 'start_time': segment.start_offset_sec, 'end_time': segment.end_offset_sec, 'video_url': product_info['video_url'] } }) return { 'text_embedding': text_embedding, 'video_embeddings': video_embeddings }, None except Exception as e: st.error("Error in embedding generation") st.error(f"Error message: {str(e)}") return None, str(e)
このプロセスは、一貫性があり意味のある埋め込みを保証するために、テキストを構造化およびフォーマットすることから始まります。次に動画の埋め込みが行われ、ステータスの監視や進捗の追跡が処理されます。各ビデオセグメントは6秒に設定されています(video_clip_length=6)。
メタデータの追跡は、トレーサビリティを維持し、正確なビデオセグメントおよびテキスト検索を可能にするために不可欠です。その後、結果はMilvusベクトルデータベースのコレクションに格納されます。
3 - Milvus ベクトルデータベースへの埋め込みの挿入
ベクトルデータベースは、高次元の埋め込みデータを効率的に保存、検索することができます。このセクションでは、適切なメタデータ管理およびエラーハンドリングを行いつつ、テキストとビデオ両方の埋め込みをMilvusベクトルデータベースに挿入する方法を説明します。
# Insert text and all video segment embeddings into Milvus Collection def insert_embeddings(embeddings_data, product_info): try: metadata = { "product_id": product_info['product_id'], "title": product_info['title'], "description": product_info['desc'], "video_url": product_info['video_url'], "link": product_info['link'] } # Insert text embedding text_entry = { "id": int(uuid.uuid4().int & (1<<63)-1), "vector": embeddings_data['text_embedding'], "metadata": metadata, "embedding_type": "text" } collection.insert([text_entry]) st.write("Text embedding inserted successfully") # Insert each video segment embedding for video_segment in embeddings_data['video_embeddings']: video_entry = { "id": int(uuid.uuid4().int & (1<<63)-1), "vector": video_segment['embedding'], "metadata": {**metadata, **video_segment['metadata']}, "embedding_type": "video" } collection.insert([video_entry]) st.write(f"Inserted {len(embeddings_data['video_embeddings'])} video segment embeddings") return True except Exception as e: st.error(f"Error inserting embeddings: {str(e)}") return False
ID、ベクトル、メタデータを定義した後、同じコレクション空間内で異なるフォーマットに対応できるようにするために embedding_type を指定します。その後、データは collection.insert メソッドを使用して挿入されます。
4 - 画像から動画を検索するためのセマンティック検索の実装
画像クエリによるセマンティック検索により、類似するビデオコンテンツを探すことができます。この実装は、Twelve Labsの埋め込み機能とMilvusのベクトル検索を組み合わせています。ユーティリティ関数であるsearched_similar_videosがどのように機能するかを以下に示します:

まず、システムは製品画像をロードして読み込み、類似する製品が含まれるビデオセグメントを探します。次にTwelve Labsの埋め込み(embed)が画像を埋め込みに変換し、Milvusコレクションに格納された動画埋め込みに対してセマンティック検索を実行します。
# Load and Read Query Image image_path = "path/to/your/image.jpg" with open(image_path, 'rb') as f: image_file = f.read() # Intializing of client and Generation of Image Emebedding twelvelabs_client = TwelveLabs(api_key=TWELVELABS_API_KEY) image_embedding = twelvelabs_client.embed.create( model_name="Marengo-retrieval-2.7", image_file=image_file ).image_embedding.segments[0].embeddings_float
検索には、速度と精度のバランスを取るために、コサイン類似度とクラスターパラメータが使用されます。collection.search が embedding_type == 'video' やその他のパラメータとともに実行されると、指定された数の製品ビデオセグメントを検索(リトリーブ)します。
search_params = { "metric_type": "COSINE", "params": { "nprobe": 1024, "ef": 64 } } # Search relevant video segments results = collection.search( data=[image_embedding], anns_field="vector", param=search_params, limit=2, expr="embedding_type == 'video'", output_fields=["metadata"] )
システムは結果を処理し、明確にするために類似度のスコアを割合(%)に変換し、メタデータを構造化された辞書形式に整理します。
search_results = [] for hits in results: for hit in hits: metadata = hit.metadata # Convert score from [-1,1] to [0,100] range similarity = round((hit.score + 1) * 50, 2) similarity = max(0, min(100, similarity)) search_results.append({ 'Title': metadata.get('title', ''), 'Description': metadata.get('description', ''), 'Link': metadata.get('link', ''), 'Start Time': f"{metadata.get('start_time', 0):.1f}s", 'End Time': f"{metadata.get('end_time', 0):.1f}s", 'Video URL': metadata.get('video_url', ''), 'Similarity': f"{similarity}%", 'Raw Score': hit.score }) # Sort by similarity score in descending order search_results.sort(key=lambda x: float(x['Similarity'].rstrip('%')), reverse=True)
ソートされた結果は、画面に表示することができます。UIの実装はvision_searchで確認できます。
5 - RAG (Retrieval Augmented Generation) システムの開発
このセクションでは、ファッションアシスタントの文脈における質問応答に焦点を当て、マルチモーダル検索とLLM (gpt-3.5) を組み合わせて文脈に即した回答を作成します。効果的なパーソナライズ化のために、メタデータを持つテキストおよび動画データからのマルチモーダル検索を重視しています。get_rag_response関数がRAG機能を実装しています。

プロセスは、Twelve Labsの埋め込みでMarengo-retrieval-2.7エンジンを使用してユーザーの質問と文脈をテキスト埋め込みに変換し、データベース全体に対するセマンティック検索を可能にすることから始まります。
# Sample question question_with_context = f"fashion product: Suggest me black dresses for a party" # Generate embedding for the question question_embedding = twelvelabs_client.embed.create( model_name="Marengo-retrieval-2.7", text=question_with_context ).text_embedding.segments[0].embeddings_float
セマンティック検索のパラメータを設定した後、システムはテキストと動画セグメントに対して別々にコレクション検索を実行します。動画セグメント検索では、テキストクエリに最も関連するセグメントを見つけ出し、ユーザーに包括的な探索オプションを提供します。
expr メソッドにより検索条件が絞り込まれ、テキスト検索と動画検索で異なるリミット値が適用されます。典型的な検索では、メタデータを持つ2つのテキスト製品と3つの関連ビデオセグメントを検索します。
# Configure search parameters search_params = { "metric_type": "COSINE", "params": { "nprobe": 1024, "ef": 64 } } # Search for relevant text embeddings text_results = collection.search( data=[question_embedding], anns_field="vector", param=search_params, limit=2, # Get top 2 text matches expr="embedding_type == 'text'", output_fields=["metadata"] ) # Search for relevant video segments video_results = collection.search( data=[question_embedding], anns_field="vector", param=search_params, limit=3, # Get top 3 video segments expr="embedding_type == 'video'", output_fields=["metadata"] )
結果の処理中、システムは各セグメントからメタデータを抽出し、類似度のスコアを割合(%)に変換し、製品の詳細を構造化された辞書形式に整理します。
# Process text results text_docs = [] for hits in text_results: for hit in hits: metadata = hit.metadata similarity = round((hit.score + 1) * 50, 2) similarity = max(0, min(100, similarity)) text_docs.append({ "title": metadata.get('title', 'Untitled'), "description": metadata.get('description', 'No description available'), "product_id": metadata.get('product_id', ''), "video_url": metadata.get('video_url', ''), "link": metadata.get('link', ''), "similarity": similarity, "raw_score": hit.score, "type": "text" }) # Process video results video_docs = [] for hits in video_results: for hit in hits: metadata = hit.metadata similarity = round((hit.score + 1) * 50, 2) similarity = max(0, min(100, similarity)) video_docs.append({ "title": metadata.get('title', 'Untitled'), "description": metadata.get('description', 'No description available'), "product_id": metadata.get('product_id', ''), "video_url": metadata.get('video_url', ''), "link": metadata.get('link', ''), "similarity": similarity, "raw_score": hit.score, "start_time": metadata.get('start_time', 0), "end_time": metadata.get('end_time', 0), "type": "video" })
関連する情報を収集した後、システムはRetrieval Augmented Generation(検索拡張生成)のステップに進みます。検索されたコンテキスト(文脈情報)は、効率的なLLM処理のために構造化されます。
システムは、システムプロンプトとユーザープロンプトの両方を定義します。システムプロンプトはファッションアドバイザーとしての役割を確立し、ユーザープロンプトはユーザーのクエリとデータベースから取得したコンテキストを組み合わせます。コンテキスト取得が失敗した場合のエラーハンドリングも含まれています。
# Handle case when no results found if not text_docs and not video_docs: response_data = { "response": "I couldn't find any matching products. Try describing what you're looking for differently.", "metadata": None } else: # Create context from text results for LLM text_context = "\n\n".join([ f"Product: {doc['title']}\nDescription: {doc['description']}\nLink: {doc['link']}" for doc in text_docs ]) # Prepare messages for OpenAI messages = [ { "role": "system", "content": """You are a professional fashion advisor and AI shopping assistant. Organize your response in the following format: First, provide a brief, direct answer to the user's query Then, describe any relevant products found that match their request, including: - Product name and key features - Why this product matches their needs - Style suggestions for how to wear or use the item Finally, provide any additional style advice or recommendations Keep your response engaging and natural while maintaining this clear structure. Focus on being helpful and specific rather than promotional.""" }, { "role": "user", "content": f"""Query: {question} Available Products: {text_context} Please provide fashion advice and product recommendations based on these options.""" } ] # Get response from OpenAI chat_response = openai_client.chat.completions.create( model="gpt-3.5-turbo", messages=messages, temperature=0.5, max_tokens=500 ) # Format final response response_data = { "response": chat_response.choices[0].message.content, "metadata": { "sources": text_docs + video_docs, "total_sources": len(text_docs) + len(video_docs), "text_sources": len(text_docs), "video_sources": len(video_docs) } }
text_context には検索された情報が含まれます。gpt-3.5-turbo を使用して、システムはシステムプロンプトで指定されたように、説明、提案、ユーザー向けのガイダンスを含む応答を生成します。その応答は、アクセスしやすい辞書構造にフォーマットされます。UI実装の詳細については、appを参照してください。
デモアプリケーション
このデモは、データベース挿入の簡略化、効率的なマルチモーダル検索の有効化、そしてユーザーのための検索機能の向上の3つの主な目的を持ったパーツに分かれています。
データベースへのテキストおよびビデオ埋め込みの生成と挿入
LLMとのチャット対話を通じたマルチモーダルデータの検索
関連するビデオセグメントを見つけるための、製品画像ベースの検索
製品データカタログには、製品ID、テキスト、説明、リンク、およびビデオURLなどのフィールドが含まれます。テキストデータは埋め込みに変換され、その他のデータはメタデータとして保存されます。動画セグメントについて、システムは動画URLを処理します。すべての埋め込みは単一のコレクションに保存されます。

マルチモーダル検索の例として、「メンズの黒いTシャツを探しています」というクエリがあります。

セマンティックビデオ検索では、黒いTシャツの画像をクエリとして使用し、上位2件の結果を表示する場合のようになります。

チュートリアルを応用するためのその他のアイデア
アプリケーションの仕組みと開発プロセスを理解することは、ユーザーのニーズを捉えた革新的な製品を作成するのに役立ちます。ビデオコンテンツクリエイター向けの応用可能なユースケースを提案します:
🛍️ Eコマース:テキストおよび画像クエリを用いた商品検索とおすすめ機能の強化
🎵 音楽ディスカバリー:オーディオクリップやユーザーの好みに基づいて、似た曲、アーティスト、またはジャンルを検索
🎥 インテリジェント動画検索エンジン:視覚および音声コンテンツに基づいて動画を検索し、コンテンツクリエイター、ジャーナリスト、研究者を支援
🗺️ パーソナライズされた旅行プランナー:ユーザーの好み、レビュー、目的地のデータに基づいて旅行の旅程を作成
📚 教育リソース管理:ドキュメント、プレゼンテーション、ビデオなどの学習教材を、学習内容のニーズに基づいて整理して検索
結論
このチュートリアルでは、Twelve LabsとMilvusベクトルデータベースによって駆動する埋め込みを介した、マルチモーダル検索プロセスの実装を示しました。この実装は、視覚とテキストデータの両方を処理するスケーラブルなアプリケーションを構築する方法を開発者に示しています。チュートリアルにお付き合いいただきありがとうございました。ユーザーエクスペリエンスの向上やさまざまな課題を解決するためのご意見やアイデアを歓迎します。
追加リソース
埋め込み生成エンジンであるMarengo-retrieval-2.7についてさらに詳しく。Twelve Labsをさらに探索し、ビデオコンテンツ解析への理解を深めるには、以下のリソースを確認してください:
Discord コミュニティ:開発者や熱心なファンが集まる活気あるコミュニティに参加して、アイデアを議論したり、質問したり、プロジェクトをシェアしましょう。Twelve Labs Discordに参加する
サンプルアプリケーション:次のプロジェクトのインスピレーションを得たり、新しい実装テクニックを学ぶためのさまざまなサンプルアプリケーションを探索できます
チュートリアルの探索:包括的なチュートリアルを通じて、Twelve Labsの実力をさらに深く知ることができます
これらのリソースを活用して知識を広げ、Twelve Labsのシステムビデオ理解テクノロジーを使用した革新的なアプリケーションを作成することをお勧めします。
はじめに
言葉だけでなく視覚的な好みまで理解してくれる専属のファッションアドバイザーが、24時間365日いつでも利用できたらどうなるか、考えたことはありますか?気に入ったコーディネートの写真を見せるだけで、AIが瞬時に似たスタイルの提案をしてくれたり、憧れのルックを言葉で伝えるだけで、それにマッチするコーディネートの提案を受け取ったりすることを想像してみてください 👚
当社のFashion AIアシスタントアプリケーションは、次世代の製品発見(プロダクトディスカバリー)のために構築されています。このチュートリアルでは、マルチモーダルな検索と対話型AIを組み合わせた、当社の高度なファッション推薦システムについて説明します。このシステムは、 TwelveLabs EmbedのMarengo-retrieval-2.7モデルを使用して、テキストとビデオコンテンツの両方から埋め込み(embeddings)を生成し、異なるデータタイプ間でのシームレスな検索を可能にします。
このアプリケーションは、効率的な類似性検索を行うためのベクトルデータベースとして Milvusを使用し、自然言語処理のためにOpenAIのgpt-3.5を統合しています。テキストと画像両方の入力からファッションに関するクエリを処理し、関連する製品説明と正確なビデオタイムスタンプを見つけ出し、ユーザーが探しているアイテムがビデオ内のどこに登場するかを正確に示します。
この強力な組み合わせにより、テキストとビジュアルの両方のクエリを理解し、マルチモーダルなコンテンツで強化された文脈に沿った回答を提供するシステムが構築されます。
このアプリケーションがどのように機能するのか、そして TwelveLabs Python SDKおよび Milvus Python SDKを使用して同様のソリューションをどのように構築できるかを見ていきましょう。
アプリケーションのデモはこちらからお試しいただけます: Fashion AI Chat App。
コードにアクセスしてアプリを直接試してみたい場合は、こちらの Replit Templateをご利用いただけます。
前提条件
Twelve Labs Playgroundに登録して、APIキーを生成します。
設定ガイドに従って、Milvusサーバーのインストールとセットアップを行います。
このアプリケーションのリポジトリは Fashion AI Chat Applicationにあります。
Python、Streamlit、CSSについて、ある程度の知識があらかじめ必要となります。

アプリケーションの仕組み
ここでは、アプリケーションの動作の概要と、そのコンポーネントがどのように相互作用するかを示します。

このアプリケーションには、3つの主な機能があります:
埋め込みの生成とMilvusベクトルデータベースへの挿入
クエリ画像からビデオセグメントへの検索
マルチモーダル検索(テキストおよびビデオセグメント)のための、対話型Retrieval Augmented Generation (RAG)
このチュートリアルアプリケーションでは、Twelve Labs Embed - Marengo-retrieval-2.7を使用して、製品カタログデータをベクトルデータベースに格納する方法を示します。テキストとビデオコンテンツの両方に該当する埋め込みは、同一のMilvusベクトルデータベースのコレクションに保存されます。わかりやすさと再利用性を考慮して、Twelve Labsの埋め込み関数は各ユーティリティ関数内で定義されています。
アプリケーションを期待通りに動作させるには、埋め込みデータをコレクションに挿入する必要があります。または、このアプリケーションで使用されているこちらの提供サンプルデータを参照することもできます。
準備手順
Twelve Labs PlaygroundからAPIキーを取得し、環境変数に設定します。
GitHubからプロジェクトをクローンするか、 Replit Templateを使用します。事前に定義された仮想環境が付属しているため、Replitテンプレートの使用をお勧めします。セットアップ時にはシークレットファイルを追加することを忘れずに、 Replit のシークレットキーに関するドキュメントを参照してください。
Twelve Labs、Milvus接続、およびLLMモデル用のOpenAI APIキーを含む
.envファイルを作成します。
Milvusベクトルデータベースの認証情報にはZilliz Cloudを使用した設定を行っていますが、他の接続方法については 設定ガイドでも確認できます。
TWELVELABS_API_KEY="your_twelvelabs_key" COLLECTION_NAME="your_collection_name" URL="your_milvus_url" TOKEN="your_milvus_token" OPENAI_API_KEY="your_openai_key"
これらの手順が完了したら、開発を始める準備は完了です!
ファッションチャットアプリケーションの実装解説
このチュートリアルでは、最小限のフロントエンドを備えたStreamlitアプリケーションを作成します。ディレクトリ構造を見てみましょう:
├── pages/ │ ├── add_product_page.py │ └── visual_search.py ├── .gitignore ├── app.py └── utils.py └── requirements.txt
Streamlit アプリケーションの作成
セットアップが完了したところで、Streamlitアプリケーションを構築していきましょう。
仮想環境の作成に必要なすべての依存関係は、こちらで確認できます: requirements.txt
Pythonの仮想環境を作成し、次のコマンドを使用してアプリケーションの環境をセットアップします:
pip install -r requirements.txt
ユーティリティ関数の定義
このセクションでは、中心となるロジックと実装が含まれている utility.pyについて説明します。各サブセクションを詳しく処理していきましょう:
1 - 接続のセットアップ
最初のステップでは、環境変数をロードし、LLMアクセスのためのOpenAI、コレクション管理のためのMilvus、そしてTwelve Labsの初期化のための接続を確立します。
# Load environment variables COLLECTION_NAME = os.getenv('COLLECTION_NAME') URL = os.getenv('URL') TOKEN = os.getenv('TOKEN') TWELVELABS_API_KEY = os.getenv('TWELVELABS_API_KEY') # Initialize connections openai_client = OpenAI() connections.connect(uri=URL, token=TOKEN) collection = Collection(COLLECTION_NAME) collection.load() twelvelabs_client = TwelveLabs(api_key=TWELVELABS_API_KEY)
2 - Twelve Labs Embed API を使用した埋め込みの生成
このセクションでは、マルチモーダル検索用の Marengo-retrieval-2.7 モデルを搭載したTwelve Labs SDKを使用した埋め込み生成について説明します。このソリューションは、効率的な検索埋め込みを作成するために、テキストとビデオの処理を統合しています。
# Generate text and segmented video embeddings for a product def generate_embedding(product_info): try: st.write("Starting embedding generation process...") st.write(f"Processing product: {product_info['title']}") # Initialize the Twelve Labs client twelvelabs_client = TwelveLabs(api_key=TWELVELABS_API_KEY) st.write("TwelveLabs client initialized successfully") st.write("Attempting to generate text embedding...") # Formatting the Text Data of Product Catalogue text = f"product type: {product_info['title']}. " \ f"product description: {product_info['desc']}. " \ f"product category: fashion apparel." st.write(f"Generating embedding for text: {text}") # Generating the Text Embeddings text_embedding = twelvelabs_client.embed.create( model_name="Marengo-retrieval-2.7", text=text ).text_embedding.segments[0].embeddings_float st.write("Text embedding generated successfully") # Create and wait for video embedding task st.write("Creating video embedding task...") video_task = twelvelabs_client.embed.task.create( model_name="Marengo-retrieval-2.7", video_url=product_info['video_url'], video_clip_length=6 ) def on_task_update(task): st.write(f"Video processing status: {task.status}") st.write("Waiting for video processing to complete...") video_task.wait_for_done(sleep_interval=2, callback=on_task_update) # Retrieve segmented video embeddings video_task = video_task.retrieve() if not video_task.video_embedding or not video_task.video_embedding.segments: raise Exception("Failed to retrieve video embeddings") video_segments = video_task.video_embedding.segments st.write(f"Retrieved {len(video_segments)} video segments") video_embeddings = [] for segment in video_segments: video_embeddings.append({ 'embedding': segment.embeddings_float, 'metadata': { 'scope': 'clip', 'start_time': segment.start_offset_sec, 'end_time': segment.end_offset_sec, 'video_url': product_info['video_url'] } }) return { 'text_embedding': text_embedding, 'video_embeddings': video_embeddings }, None except Exception as e: st.error("Error in embedding generation") st.error(f"Error message: {str(e)}") return None, str(e)
このプロセスは、一貫性があり意味のある埋め込みを保証するために、テキストを構造化およびフォーマットすることから始まります。次に動画の埋め込みが行われ、ステータスの監視や進捗の追跡が処理されます。各ビデオセグメントは6秒に設定されています(video_clip_length=6)。
メタデータの追跡は、トレーサビリティを維持し、正確なビデオセグメントおよびテキスト検索を可能にするために不可欠です。その後、結果はMilvusベクトルデータベースのコレクションに格納されます。
3 - Milvus ベクトルデータベースへの埋め込みの挿入
ベクトルデータベースは、高次元の埋め込みデータを効率的に保存、検索することができます。このセクションでは、適切なメタデータ管理およびエラーハンドリングを行いつつ、テキストとビデオ両方の埋め込みをMilvusベクトルデータベースに挿入する方法を説明します。
# Insert text and all video segment embeddings into Milvus Collection def insert_embeddings(embeddings_data, product_info): try: metadata = { "product_id": product_info['product_id'], "title": product_info['title'], "description": product_info['desc'], "video_url": product_info['video_url'], "link": product_info['link'] } # Insert text embedding text_entry = { "id": int(uuid.uuid4().int & (1<<63)-1), "vector": embeddings_data['text_embedding'], "metadata": metadata, "embedding_type": "text" } collection.insert([text_entry]) st.write("Text embedding inserted successfully") # Insert each video segment embedding for video_segment in embeddings_data['video_embeddings']: video_entry = { "id": int(uuid.uuid4().int & (1<<63)-1), "vector": video_segment['embedding'], "metadata": {**metadata, **video_segment['metadata']}, "embedding_type": "video" } collection.insert([video_entry]) st.write(f"Inserted {len(embeddings_data['video_embeddings'])} video segment embeddings") return True except Exception as e: st.error(f"Error inserting embeddings: {str(e)}") return False
ID、ベクトル、メタデータを定義した後、同じコレクション空間内で異なるフォーマットに対応できるようにするために embedding_type を指定します。その後、データは collection.insert メソッドを使用して挿入されます。
4 - 画像から動画を検索するためのセマンティック検索の実装
画像クエリによるセマンティック検索により、類似するビデオコンテンツを探すことができます。この実装は、Twelve Labsの埋め込み機能とMilvusのベクトル検索を組み合わせています。ユーティリティ関数であるsearched_similar_videosがどのように機能するかを以下に示します:

まず、システムは製品画像をロードして読み込み、類似する製品が含まれるビデオセグメントを探します。次にTwelve Labsの埋め込み(embed)が画像を埋め込みに変換し、Milvusコレクションに格納された動画埋め込みに対してセマンティック検索を実行します。
# Load and Read Query Image image_path = "path/to/your/image.jpg" with open(image_path, 'rb') as f: image_file = f.read() # Intializing of client and Generation of Image Emebedding twelvelabs_client = TwelveLabs(api_key=TWELVELABS_API_KEY) image_embedding = twelvelabs_client.embed.create( model_name="Marengo-retrieval-2.7", image_file=image_file ).image_embedding.segments[0].embeddings_float
検索には、速度と精度のバランスを取るために、コサイン類似度とクラスターパラメータが使用されます。collection.search が embedding_type == 'video' やその他のパラメータとともに実行されると、指定された数の製品ビデオセグメントを検索(リトリーブ)します。
search_params = { "metric_type": "COSINE", "params": { "nprobe": 1024, "ef": 64 } } # Search relevant video segments results = collection.search( data=[image_embedding], anns_field="vector", param=search_params, limit=2, expr="embedding_type == 'video'", output_fields=["metadata"] )
システムは結果を処理し、明確にするために類似度のスコアを割合(%)に変換し、メタデータを構造化された辞書形式に整理します。
search_results = [] for hits in results: for hit in hits: metadata = hit.metadata # Convert score from [-1,1] to [0,100] range similarity = round((hit.score + 1) * 50, 2) similarity = max(0, min(100, similarity)) search_results.append({ 'Title': metadata.get('title', ''), 'Description': metadata.get('description', ''), 'Link': metadata.get('link', ''), 'Start Time': f"{metadata.get('start_time', 0):.1f}s", 'End Time': f"{metadata.get('end_time', 0):.1f}s", 'Video URL': metadata.get('video_url', ''), 'Similarity': f"{similarity}%", 'Raw Score': hit.score }) # Sort by similarity score in descending order search_results.sort(key=lambda x: float(x['Similarity'].rstrip('%')), reverse=True)
ソートされた結果は、画面に表示することができます。UIの実装はvision_searchで確認できます。
5 - RAG (Retrieval Augmented Generation) システムの開発
このセクションでは、ファッションアシスタントの文脈における質問応答に焦点を当て、マルチモーダル検索とLLM (gpt-3.5) を組み合わせて文脈に即した回答を作成します。効果的なパーソナライズ化のために、メタデータを持つテキストおよび動画データからのマルチモーダル検索を重視しています。get_rag_response関数がRAG機能を実装しています。

プロセスは、Twelve Labsの埋め込みでMarengo-retrieval-2.7エンジンを使用してユーザーの質問と文脈をテキスト埋め込みに変換し、データベース全体に対するセマンティック検索を可能にすることから始まります。
# Sample question question_with_context = f"fashion product: Suggest me black dresses for a party" # Generate embedding for the question question_embedding = twelvelabs_client.embed.create( model_name="Marengo-retrieval-2.7", text=question_with_context ).text_embedding.segments[0].embeddings_float
セマンティック検索のパラメータを設定した後、システムはテキストと動画セグメントに対して別々にコレクション検索を実行します。動画セグメント検索では、テキストクエリに最も関連するセグメントを見つけ出し、ユーザーに包括的な探索オプションを提供します。
expr メソッドにより検索条件が絞り込まれ、テキスト検索と動画検索で異なるリミット値が適用されます。典型的な検索では、メタデータを持つ2つのテキスト製品と3つの関連ビデオセグメントを検索します。
# Configure search parameters search_params = { "metric_type": "COSINE", "params": { "nprobe": 1024, "ef": 64 } } # Search for relevant text embeddings text_results = collection.search( data=[question_embedding], anns_field="vector", param=search_params, limit=2, # Get top 2 text matches expr="embedding_type == 'text'", output_fields=["metadata"] ) # Search for relevant video segments video_results = collection.search( data=[question_embedding], anns_field="vector", param=search_params, limit=3, # Get top 3 video segments expr="embedding_type == 'video'", output_fields=["metadata"] )
結果の処理中、システムは各セグメントからメタデータを抽出し、類似度のスコアを割合(%)に変換し、製品の詳細を構造化された辞書形式に整理します。
# Process text results text_docs = [] for hits in text_results: for hit in hits: metadata = hit.metadata similarity = round((hit.score + 1) * 50, 2) similarity = max(0, min(100, similarity)) text_docs.append({ "title": metadata.get('title', 'Untitled'), "description": metadata.get('description', 'No description available'), "product_id": metadata.get('product_id', ''), "video_url": metadata.get('video_url', ''), "link": metadata.get('link', ''), "similarity": similarity, "raw_score": hit.score, "type": "text" }) # Process video results video_docs = [] for hits in video_results: for hit in hits: metadata = hit.metadata similarity = round((hit.score + 1) * 50, 2) similarity = max(0, min(100, similarity)) video_docs.append({ "title": metadata.get('title', 'Untitled'), "description": metadata.get('description', 'No description available'), "product_id": metadata.get('product_id', ''), "video_url": metadata.get('video_url', ''), "link": metadata.get('link', ''), "similarity": similarity, "raw_score": hit.score, "start_time": metadata.get('start_time', 0), "end_time": metadata.get('end_time', 0), "type": "video" })
関連する情報を収集した後、システムはRetrieval Augmented Generation(検索拡張生成)のステップに進みます。検索されたコンテキスト(文脈情報)は、効率的なLLM処理のために構造化されます。
システムは、システムプロンプトとユーザープロンプトの両方を定義します。システムプロンプトはファッションアドバイザーとしての役割を確立し、ユーザープロンプトはユーザーのクエリとデータベースから取得したコンテキストを組み合わせます。コンテキスト取得が失敗した場合のエラーハンドリングも含まれています。
# Handle case when no results found if not text_docs and not video_docs: response_data = { "response": "I couldn't find any matching products. Try describing what you're looking for differently.", "metadata": None } else: # Create context from text results for LLM text_context = "\n\n".join([ f"Product: {doc['title']}\nDescription: {doc['description']}\nLink: {doc['link']}" for doc in text_docs ]) # Prepare messages for OpenAI messages = [ { "role": "system", "content": """You are a professional fashion advisor and AI shopping assistant. Organize your response in the following format: First, provide a brief, direct answer to the user's query Then, describe any relevant products found that match their request, including: - Product name and key features - Why this product matches their needs - Style suggestions for how to wear or use the item Finally, provide any additional style advice or recommendations Keep your response engaging and natural while maintaining this clear structure. Focus on being helpful and specific rather than promotional.""" }, { "role": "user", "content": f"""Query: {question} Available Products: {text_context} Please provide fashion advice and product recommendations based on these options.""" } ] # Get response from OpenAI chat_response = openai_client.chat.completions.create( model="gpt-3.5-turbo", messages=messages, temperature=0.5, max_tokens=500 ) # Format final response response_data = { "response": chat_response.choices[0].message.content, "metadata": { "sources": text_docs + video_docs, "total_sources": len(text_docs) + len(video_docs), "text_sources": len(text_docs), "video_sources": len(video_docs) } }
text_context には検索された情報が含まれます。gpt-3.5-turbo を使用して、システムはシステムプロンプトで指定されたように、説明、提案、ユーザー向けのガイダンスを含む応答を生成します。その応答は、アクセスしやすい辞書構造にフォーマットされます。UI実装の詳細については、appを参照してください。
デモアプリケーション
このデモは、データベース挿入の簡略化、効率的なマルチモーダル検索の有効化、そしてユーザーのための検索機能の向上の3つの主な目的を持ったパーツに分かれています。
データベースへのテキストおよびビデオ埋め込みの生成と挿入
LLMとのチャット対話を通じたマルチモーダルデータの検索
関連するビデオセグメントを見つけるための、製品画像ベースの検索
製品データカタログには、製品ID、テキスト、説明、リンク、およびビデオURLなどのフィールドが含まれます。テキストデータは埋め込みに変換され、その他のデータはメタデータとして保存されます。動画セグメントについて、システムは動画URLを処理します。すべての埋め込みは単一のコレクションに保存されます。

マルチモーダル検索の例として、「メンズの黒いTシャツを探しています」というクエリがあります。

セマンティックビデオ検索では、黒いTシャツの画像をクエリとして使用し、上位2件の結果を表示する場合のようになります。

チュートリアルを応用するためのその他のアイデア
アプリケーションの仕組みと開発プロセスを理解することは、ユーザーのニーズを捉えた革新的な製品を作成するのに役立ちます。ビデオコンテンツクリエイター向けの応用可能なユースケースを提案します:
🛍️ Eコマース:テキストおよび画像クエリを用いた商品検索とおすすめ機能の強化
🎵 音楽ディスカバリー:オーディオクリップやユーザーの好みに基づいて、似た曲、アーティスト、またはジャンルを検索
🎥 インテリジェント動画検索エンジン:視覚および音声コンテンツに基づいて動画を検索し、コンテンツクリエイター、ジャーナリスト、研究者を支援
🗺️ パーソナライズされた旅行プランナー:ユーザーの好み、レビュー、目的地のデータに基づいて旅行の旅程を作成
📚 教育リソース管理:ドキュメント、プレゼンテーション、ビデオなどの学習教材を、学習内容のニーズに基づいて整理して検索
結論
このチュートリアルでは、Twelve LabsとMilvusベクトルデータベースによって駆動する埋め込みを介した、マルチモーダル検索プロセスの実装を示しました。この実装は、視覚とテキストデータの両方を処理するスケーラブルなアプリケーションを構築する方法を開発者に示しています。チュートリアルにお付き合いいただきありがとうございました。ユーザーエクスペリエンスの向上やさまざまな課題を解決するためのご意見やアイデアを歓迎します。
追加リソース
埋め込み生成エンジンであるMarengo-retrieval-2.7についてさらに詳しく。Twelve Labsをさらに探索し、ビデオコンテンツ解析への理解を深めるには、以下のリソースを確認してください:
Discord コミュニティ:開発者や熱心なファンが集まる活気あるコミュニティに参加して、アイデアを議論したり、質問したり、プロジェクトをシェアしましょう。Twelve Labs Discordに参加する
サンプルアプリケーション:次のプロジェクトのインスピレーションを得たり、新しい実装テクニックを学ぶためのさまざまなサンプルアプリケーションを探索できます
チュートリアルの探索:包括的なチュートリアルを通じて、Twelve Labsの実力をさらに深く知ることができます
これらのリソースを活用して知識を広げ、Twelve Labsのシステムビデオ理解テクノロジーを使用した革新的なアプリケーションを作成することをお勧めします。




