Создайте мультимодальный поиск 3D-ассетов с Tripo и Zilliz Cloud
Генерация 3D с помощью ИИ сделала создание ассетов намного быстрее. С Tripo, генератором 3D-моделей на основе ИИ, команды могут генерировать 3D-модели из текстовых запросов, изображений или эскизов, а затем использовать их в разработке игр, электронной коммерции, маркетинге, концепт-дизайне и внутренних креативных пайплайнах.
Такая скорость создает новую проблему: ассеты быстро накапливаются.
Несколькими сгенерированными моделями легко управлять вручную. Несколькими тысячами — нет. Дизайнеры могут заново генерировать объекты, которые уже существуют. Игровые команды могут потерять из виду вариации персонажей, реквизита и окружения. Маркетинговые команды могут тратить больше времени на поиск подходящего ассета, чем на его адаптацию для кампании.
В этом руководстве показано, как превратить эти сгенерированные ассеты в каталог с возможностью поиска. Tripo — это слой создания 3D, а Zilliz Cloud — слой поиска: полностью управляемый сервис векторной базы данных от создателей Milvus, который хранит эмбеддинги и метаданные, поддерживает поиск по сходству с низкой задержкой и позволяет объединять векторный поиск со структурированными фильтрами.
В этом рабочем процессе каждая запись ассета содержит предварительный рендер, структурированные метаданные и один мультимодальный эмбеддинг. После индексации ассетов пользователи могут искать по тексту, по изображению или одновременно по тексту и изображению.
Что вы создадите
Библиотека в этом руководстве рассматривает каждый 3D-ассет как элемент каталога с возможностью поиска. 3D-сетка остается там, где ее хранит ваш пайплайн ассетов. Запись для поиска содержит предварительный рендер ассета, метаданные, ссылки на хранилище и эмбеддинг.
В этой демонстрации используются три типа локальных данных:
| Локальные данные | Что они содержат |
|---|---|
| milvus_dataset.csv | Метаданные по каждому ассету: категория, стиль, тип объекта, цвет, сценарий использования, имя файла, информация о проекте |
| milvus_render_images/ | Предварительные рендеры ассетов Tripo. Именно по ним выполняется поиск и именно они возвращаются |
| milvus_input_images/ | Референсные изображения, использованные для генерации image-to-3D. Хранятся как метаданные и дополнительные референсы для запросов |
Базовый рабочий процесс выглядит так:
3D-ассет, сгенерированный Tripo
↓
Изображение предварительного рендера + метаданные
↓
Мультимодальный эмбеддинг
↓
Коллекция Zilliz Cloud
↓
Поиск по тексту, изображению или тексту + изображению
↓
Возврат совпавших изображений рендера и метаданных
Эта настройка поддерживает распространенные паттерны поиска для креативных задач:
- Поиск по концепту, например blue fantasy sword.
- Поиск по типу объекта, стилю, цвету или сценарию использования.
- Использование референсного изображения, когда слова слишком расплывчаты.
- Объединение референсного изображения с текстом для направления результата.
- Фильтрация по структурированным полям, таким как категория, проект, оператор, стиль или режим генерации.
В результате получается не просто папка с более удачными именами файлов. Это каталог ассетов, по которому можно выполнять запросы.
Почему предварительные рендеры и метаданные важны
3D-модель сложно искать напрямую. В производственном пайплайне модель обычно сопровождается несколькими связанными фрагментами информации:
- сгенерированная сетка или исходный файл;
- одно или несколько изображений предварительного рендера;
- необязательное входное или референсное изображение;
- подпись или промпт;
- сгенерированные теги;
- поля проекта, владельца или оператора;
- метаданные о стиле, категории, цвете, типе объекта и сценарии использования;
- URL-адреса или ключи хранилища, указывающие обратно на ассет.
В этом руководстве предварительный рендер — это визуальный объект, для которого мы создаем эмбеддинг. Это хорошо работает, потому что предварительные рендеры передают форму, материал, цвет и визуальный стиль в формате, который мультимодальная модель эмбеддингов может понять.
Предварительный рендер — это объект, который видит модель эмбеддингов, поэтому качество ассета напрямую влияет на качество поиска. Геометрическая точность — сохраненные формы, грани и элементы декора — дает модели структурный сигнал. Текстуры высокого разрешения — отчетливые материалы, точный цвет, детали поверхности — дают ей сигнал о материале и цвете. Без обоих факторов эмбеддинги сглаживаются: кожаная сумка и холщовая сумка выглядят для модели одинаково, и поиск перестает быть полезным.
Метаданные дают вам второй уровень контроля: вы можете выполнять семантический поиск и при этом применять точные фильтры. Одна запись ассета может выглядеть так:
caption: fantasy sword with blue gemstone
llm_object: sword
llm_category: weapon
llm_style: fantasy
llm_color: blue, silver
llm_use_case: game asset
generation_mode: image-to-3D
render_image_file: fantasy_sword.webp
input_image_file: sword_reference.webp
Эта комбинация делает библиотеку полезной в реальных рабочих процессах. Например, художник по игровым ассетам может искать женского персонажа и ограничить набор результатов игровыми ассетами. Маркетолог может искать realistic leather bag и фильтровать по проекту. Команда e-commerce может искать по категории и материалу, не полагаясь на точные имена файлов.
Примечание о формате изображений
В этой демонстрации рендеры и референсные изображения хранятся как .webp для экономии места. API для эмбеддингов может быть надежнее с входными PNG или JPEG, в зависимости от модели и маршрута провайдера. Если вы видите ошибки ввода изображений, конвертируйте WebP-превью в PNG или JPEG перед созданием эмбеддингов.
Инструменты в этом пайплайне
Этот туториал соединяет две системы: одну, которая создает 3D-ассеты, и одну, которая делает их доступными для поиска.
Tripo: слой создания
Tripo — это AI 3D model generator, построенный на модели с более чем 20 миллиардами параметров. Его основной продукт, Tripo Studio, охватывает полный процесс создания ассетов в одном рабочем пространстве — от ввода текста, изображения или скетча до доработки меша, генерации текстур, риггинга, анимации и экспорта. Стандартный меш генерируется за две–пять секунд, и это одна из причин, почему библиотеки ассетов растут достаточно быстро, чтобы им понадобился поисковый пайплайн, который строится в этом туториале.
Три возможности особенно важны здесь:
- Генерация Image-to-3D model сохраняет геометрическую структуру — сложные формы, острые грани, украшения, детали поверхности — благодаря чему сгенерированные модели остаются близкими к исходному референсу.
- HD Model еще сильнее повышает эту точность, поддерживая до двух миллионов граней для ассетов, которые выдерживают рендеринг крупным планом, визуализацию продукта или 3D-печать.
- Texture Generation с разрешением до 8K добавляет точную передачу цвета, четкое различение материалов (металл, кожа, ткань, дерево) и мелкодетализированные особенности поверхности, такие как следы износа, зернистость и микротекстуры.
Вместе они дают каждому ассету достаточно геометрических и материальных сигналов, чтобы сформировать осмысленный мультимодальный эмбеддинг — и здесь вступает в дело сторона извлечения.
Zilliz Cloud: слой извлечения
Zilliz Cloud — это полностью управляемая платформа Vector Lakebase, созданная разработчиками Milvus, самой широко используемой open-source векторной базы данных (45 000+ звезд на GitHub, 100M+ загрузок Docker, 10 000+ организаций в продакшене). В ее основе лежит векторная база данных промышленного уровня, обеспечивающая поиск с задержкой менее миллисекунды в масштабе 100 миллиардов. В этом туториале она выполняет три задачи:
- Хранение эмбеддингов — мультимодальный вектор каждого ассета хранится вместе с его структурированными метаданными в одной коллекции.
- Поиск по сходству — текстовые, графические или комбинированные запросы преобразуются в эмбеддинги в том же векторном пространстве и сопоставляются с сохраненными превью рендеров.
- Извлечение с фильтрацией — точные фильтры по категории, стилю, сценарию использования или проекту накладываются поверх семантического поиска в одном запросе, что превращает набор векторов в каталог, по которому можно выполнять запросы.
Предварительные требования
Перед началом подготовьте следующее:
- Аккаунт и кластер Zilliz Cloud. Бесплатного кластера достаточно для этого руководства. Зарегистрируйтесь, создайте кластер и скопируйте его endpoint и token.
- API-ключ OpenRouter для мультимодальной модели эмбеддингов, используемой ниже.
- Python 3.10 или более поздней версии.
- Python SDK Milvus. См. руководство по установке PyMilvus, если вы с ним не знакомы.
- Набор ассетов, сгенерированных Tripo, включая изображения предварительного рендера и метаданные.
- Необязательные референсные изображения, используемые для генерации image-to-3D.
Пример кода ниже предполагает скрипт с именем tripo_rag.py, но ту же логику можно перенести в ваш собственный сервис загрузки данных, backend управления ассетами или внутренний инструмент.
Шаг 1: Подготовьте данные ассетов, сгенерированных Tripo
Начните с ассетов, сгенерированных в Tripo. Для каждого ассета экспортируйте или сохраните как минимум одно изображение предварительного рендера. Если ассет был создан на основе референсного изображения, сохраните и это референсное изображение. Оно может быть полезно для отладки, предварительного просмотра результатов поиска или создания будущих режимов поиска.
Каждая строка в вашем metadata CSV должна представлять один ассет. Как минимум, включите:
- уникальный ID ассета;
- имя файла изображения предварительного рендера или ключ хранилища;
- подпись или prompt генерации;
- поля category, object, style, color и use-case, если доступны;
- поля project или owner, если вашей команде требуется контроль доступа или фильтрация на уровне workspace;
- URL или место хранения исходного ассета.
Более богатые метаданные дадут вам лучшие фильтры позже. Вектор помогает находить визуально и семантически похожие ассеты. Метаданные помогают сузить набор результатов до ассетов, которые действительно пригодны для текущего проекта.
Шаг 2: Создайте коллекцию Zilliz Cloud
Каждая запись в коллекции представляет один ассет Tripo. Структурированные поля хранят метаданные. Поле multimodal_vector хранит эмбеддинг для предварительного рендера.
Примеры ниже используют 3072-мерный вектор и сходство COSINE. Сохраняйте размерность согласованной с моделью эмбеддингов, которую вы используете.
schema = MilvusClient.create_schema(
auto_id=False,
enable_dynamic_field=False
)
schema.add_field("id", DataType.INT64, is_primary=True)
schema.add_field("project_id", DataType.VARCHAR, max_length=64)
schema.add_field("operator_id", DataType.VARCHAR, max_length=64)
schema.add_field("caption", DataType.VARCHAR, max_length=2048)
schema.add_field("llm_keyword", DataType.VARCHAR, max_length=512)
schema.add_field("llm_object", DataType.VARCHAR, max_length=512)
schema.add_field("llm_category", DataType.VARCHAR, max_length=128)
schema.add_field("llm_style", DataType.VARCHAR, max_length=128)
schema.add_field("llm_color", DataType.VARCHAR, max_length=256)
schema.add_field("llm_use_case", DataType.VARCHAR, max_length=128)
schema.add_field("generation_mode", DataType.VARCHAR, max_length=32)
schema.add_field("url", DataType.VARCHAR, max_length=512)
schema.add_field("input_image_file", DataType.VARCHAR, max_length=256)
schema.add_field("input_image_key", DataType.VARCHAR, max_length=512)
schema.add_field("render_image_file", DataType.VARCHAR, max_length=256)
schema.add_field("render_image_key", DataType.VARCHAR, max_length=512)
schema.add_field(VECTOR_FIELD, DataType.FLOAT_VECTOR, dim=VECTOR_DIM)
Затем создайте векторный индекс:
index_params = MilvusClient.prepare_index_params()
index_params.add_index(
field_name=VECTOR_FIELD,
index_type="AUTOINDEX",
metric_type="COSINE",
)
Если ваш скрипт оборачивает настройку в команду, выполните:
python3 tripo_rag.py create-collection
После завершения команды откройте консоль Zilliz Cloud и проверьте список коллекций.
Нажмите на коллекцию, чтобы проверить статус, схему, загруженные сущности и конфигурацию векторного поля.
Краткое примечание об индексе: AUTOINDEX упрощает руководство, поскольку вам не нужно вручную настраивать параметры индекса перед импортом данных. Тип метрики COSINE соответствует нормализованным эмбеддингам, используемым на следующем шаге.
Шаг 3: Сгенерируйте мультимодальные эмбеддинги для изображений рендеров
Далее сгенерируйте эмбеддинг для каждого превью рендера.
Демо отправляет изображение превью в модель эмбеддингов через OpenRouter. Изображение кодируется как base64 data URL, а возвращаемый вектор L2-нормализуется перед вставкой в Zilliz Cloud.
def data_url_for_image(path: Path) -> str:
mime_type = mimetypes.guess_type(path.name)[0] or "image/webp"
data = base64.b64encode(path.read_bytes()).decode("ascii")
return f"data:{mime_type};base64,{data}"
def embed_content(self, content: list[dict]) -> list[float]:
body = {
"model": "google/gemini-embedding-2-preview",
"input": [{"content": content}],
"encoding_format": "float",
}
response = requests.post(
"https://openrouter.ai/api/v1/embeddings",
headers=self._headers(),
json=body,
timeout=120,
)
vector = response.json()["data"][0]["embedding"]
return l2_normalize(vector)
def embed_image(self, image_path: Path) -> list[float]:
return self.embed_content(
[
{
"type": "image_url",
"image_url": {
"url": data_url_for_image(image_path)
},
}
]
)
Для реального конвейера загрузки кэшируйте эмбеддинги. Вызов внешнего API эмбеддингов для каждого импорта выполняется медленно, а повторные попытки могут сделать повторные тестовые запуски дорогими.
python3 tripo_rag.py build-cache
Кэш также делает поведение импорта детерминированным. Вы можете перестроить коллекцию, протестировать изменения схемы или повторно запустить импорт без повторного создания эмбеддингов для каждого превью рендера.
Шаг 4: Импортируйте записи ассетов в Zilliz Cloud
После того как кэш готов, преобразуйте каждую строку CSV в одну сущность для Zilliz Cloud.
Каждая сущность должна включать структурированные поля и кэшированный мультимодальный вектор:
def row_to_entity(row_index: int, row: dict, cached_item: dict) -> dict:
return {
"id": row_index,
"project_id": row.get("project_id", ""),
"operator_id": row.get("operator_id", ""),
"caption": row.get("caption", ""),
"llm_keyword": row.get("llm_keyword", ""),
"llm_object": row.get("llm_object", ""),
"llm_category": row.get("llm_category", ""),
"llm_style": row.get("llm_style", ""),
"llm_color": row.get("llm_color", ""),
"llm_use_case": row.get("llm_use_case", ""),
"generation_mode": generation_mode(row),
"url": row.get("url", ""),
"input_image_file": row.get("input_image_file", ""),
"input_image_key": row.get("input_image_key", ""),
"render_image_file": row.get("render_image_file", ""),
"render_image_key": row.get("render_image_key", ""),
VECTOR_FIELD: cached_item[VECTOR_FIELD],
}
Затем импортируйте набор данных и проверьте статистику коллекции:
python3 tripo_rag.py import-data
python3 tripo_rag.py stats
Откройте вкладку Data в консоли Zilliz Cloud, чтобы подтвердить, что записи ассетов были вставлены. Вы должны увидеть поля метаданных, ссылки на изображения рендеров и векторное поле для каждой сущности.
Теперь ассеты Tripo являются доступными для поиска сущностями в векторной базе данных, а не разрозненными локальными файлами.
Шаг 5: Поиск по тексту, изображению или обоим
Поиск выполняется в трех режимах, все через одну и ту же мультимодальную модель и по одному и тому же полю multimodal_vector.
| Режим | Когда использовать | Пример |
|---|---|---|
| Текст | Вы можете описать, что хотите | blue fantasy sword |
| Изображение | У вас есть референс, и вы хотите похожие ассеты | загрузить стилизованный рендер щита |
| Текст + изображение | Вы хотите задать намерение и визуальный ориентир | изображение меча + fantasy sword with blue gemstone |
Запрос встраивается в то же векторное пространство, что и превью рендеров ассетов. Затем Zilliz Cloud выполняет поиск по векторному полю и возвращает ближайшие ассеты с их метаданными.
def search(args) -> None:
if not args.text and not args.image:
raise SystemExit("Provide --text, --image, or both.")
embedding_client = OpenRouterEmbeddingClient(
require_env("OPENROUTER_API_KEY")
)
client = connect_client()
if args.text and args.image:
vector = embedding_client.embed_text_image(
args.text,
Path(args.image)
)
elif args.image:
vector = embedding_client.embed_image(Path(args.image))
else:
vector = embedding_client.embed_text(args.text)
results = client.search(
collection_name=args.collection,
data=[vector],
anns_field=VECTOR_FIELD,
filter=filter_expr(args),
limit=args.top_k,
output_fields=[
"project_id",
"caption",
"llm_keyword",
"llm_object",
"llm_category",
"llm_style",
"llm_color",
"llm_use_case",
"generation_mode",
"render_image_file",
"render_image_key",
"input_image_file",
"url",
],
search_params={"metric_type": "COSINE"},
)
for rank, hit in enumerate(results[0], start=1):
entity = hit["entity"]
print(
json.dumps(
{
"rank": rank,
"score": hit["distance"],
**entity,
},
ensure_ascii=False,
indent=2,
)
)
Поскольку каждый результат включает и оценку сходства, и метаданные, ваш фронтенд может отображать превью изображения, подпись, категорию, стиль, вариант использования и исходный URL ассета в одной карточке результата.
Поиск не ограничен чистым векторным сходством. Поскольку каждый ассет содержит структурированные метаданные, вы можете добавлять фильтры к семантическому запросу в одном запросе. Например, искать female, но ограничить набор результатов условием llm_use_case == "game asset". Именно это делает коллекцию настоящим каталогом, а не кучей векторов.
Пример 1: Текстовый поиск с фильтром по варианту использования
Предположим, игровой команде нужны ассеты, похожие на персонажей. Вы можете искать female и ограничить результаты вариантом использования game asset:
python3 tripo_rag.py search \
--text "female" \
--use-case "game asset" \
--top-k 12
Это возвращает наиболее близкие ассеты из подмножества game-asset, что полезнее, чем искать по всей библиотеке и вручную игнорировать нерелевантные продуктовые, окруженческие или маркетинговые ассеты.
Пример 2: Поиск по тексту плюс референсному изображению
Одного текста часто слишком мало для визуальной работы. Запрос вроде fantasy sword with blue gemstone сообщает системе, что вы хотите, но референсное изображение фиксирует форму, композицию и визуальное направление.
python3 tripo_rag.py search \
--text "fantasy sword with blue gemstone" \
--image ./examples/sword_reference.png \
--top-k 12
Этот режим полезен, когда автор начинает с визуального референса, но хочет направить поиск несколькими словами. Референсное изображение передает визуальное сходство. Текст уточняет намерение.
Что это дает в реальном пайплайне ассетов
Как только библиотека становится доступной для поиска, команды могут использовать сгенерированные 3D-ассеты скорее как переиспользуемый производственный инвентарь.
Игровая команда может отслеживать вариации пропсов и персонажей в разных проектах. Команда электронной коммерции может организовывать ассеты, похожие на товары, по категории, материалу и стилю. Маркетинговая команда может поддерживать утвержденную библиотеку переиспользуемых визуальных материалов. Команда creative ops может выстраивать рабочие процессы ревью вокруг владельцев, ID проектов и URL ассетов, вместо того чтобы полагаться на имена папок.
Важный сдвиг прост: генерация создает ассет, но поиск делает ассет переиспользуемым.
Заключение
AI-генерация 3D упрощает производство большего количества ассетов, чем способна обработать ручная структура папок. Следующее узкое место — извлечение: найти нужный ассет, понять, откуда он взялся, и переиспользовать его в нужном проекте.
В этом руководстве показан один способ решить эту задачу. Генерируйте ассеты с помощью Tripo, храните превью рендеров и метаданные в Zilliz Cloud, встраивайте каждое превью с помощью мультимодальной модели и выполняйте поиск по коллекции с использованием текста, изображения или обоих вариантов. Тот же паттерн можно начать применять на небольшом локальном датасете и масштабировать до производственного каталога ассетов по мере расширения вашей библиотеки.
Именно это направление также лежит в основе Zilliz Vector Lakebase: хранить мультимодальные AI-данные, эмбеддинги, метаданные и пути обслуживания в единой доступной для поиска основе, чтобы команды могли переходить от генерации к извлечению и переиспользованию без перестройки слоя данных каждый раз.
Чтобы попробовать самостоятельно, зарегистрируйтесь в Zilliz Cloud, создайте бесплатный кластер, сгенерируйте небольшую партию ассетов с помощью Tripo и выполните пайплайн от начала до конца. Когда первые результаты поиска будут выглядеть правильно, подключите вывод к вашему внутреннему браузеру ассетов или творческому инструменту.
Примеры ассетов Tripo
Ассеты ниже были сгенерированы в Tripo Studio с использованием функций, описанных в этом руководстве.
Генерация текстур 8K
Генерация текстур 8K сохраняет точность цветопередачи и различает материалы поверхностей, такие как металл, кожа, ткань и дерево, вплоть до следов износа и микротекстур.
HD Model
HD Model поддерживает до двух миллионов граней, сохраняя сложные формы, острые края и мелкие особенности поверхности для рендеринга, визуализации и 3D-печати.
Читать далее

What Is a Vector Lakebase?
A Vector Lakebase is a unified, lake-native data architecture for AI that combines vector-database-grade serving with open lake storage, reusable lake-level indexes, and a shared semantic layer.

We spent 8 years making vector databases faster. Then we stopped.
Rarely queried embeddings still need to stay searchable. See how Vector Lakebase enables on-demand vector search without always-on compute costs.

Announcing the General Availability of Zilliz Cloud BYOC on Google Cloud Platform
Zilliz Cloud BYOC on GCP offers enterprise vector search with full data sovereignty and seamless integration.




