Знакът на КАГАМИ КАГАМИ
kagami.bg/academy · lesson · machine-readable viewUPDATED 2026-10-03
IDENTITY
module
GX10-04-51 · Semantic video search with Cosmos-Embed1 and a local vector database
series
GX10 (local AI server class: NVIDIA GB10, e.g. ASUS Ascent GX10 / DGX Spark)
level
Advanced
duration
2-3 h
prerequisites
A GB10-class machine with DGX OS, Docker, Python 3.10+ with a PyTorch build that works on the machine (see lesson 04-21), a Hugging Face account, a folder of short video clips you are allowed to process
trust_label
UPDATED 2026-10-03 (content rebuilt against the Cosmos-Embed1 model card, the NVIDIA Open Model License page, the NVIDIA Cosmos Dataset Search repository, Docker Hub and PyPI) · NOT TESTED (no command was run on a GB10 machine) · NOT FULLY VERIFIED (PyTorch and OpenCV on Arm64, Cosmos-Embed1 on GB10, speed)
versions
Cosmos-Embed1-448p (model card, released 2025-06-15; 224p, 336p, 448p variants) · Qdrant image qdrant/qdrant:v1.19.1 (amd64 and arm64 on Docker Hub, checked 2026-10-03) · qdrant-client 1.19.1 (PyPI) · transformers (version not pinned by the model card)
language
human view: bg · english edition: /en/academy/gx10/ (same file name)
previous / next
GX10 series index / 04-52_Cosmos_Predict_World.html
PURPOSE

Search a collection of short video clips with plain English sentences. Cosmos-Embed1 (NVIDIA, joint video-text embedder for physical AI) turns clips and text queries into vectors in one shared space; Qdrant, running locally in Docker and reachable only from the machine itself, stores the clip vectors and returns the nearest clips by cosine similarity. Optional use: assemble a reviewed training set by running several queries and having a human check the results.

KEY CONCEPTS
COMMANDS / PATHS
CHECKLIST
NEXT MODULE

04-52 · Cosmos Predict 2.5: video from one image (04-52_Cosmos_Predict_World.html) · series index: kagami.bg/academy/gx10/ · offer: Quick experiment (kagami.bg/stalbata/)

SOURCES
TAGS
gx10nvidia-gb10cosmoscosmos-embed1video-searchqdrantembeddingsdockerphysical-ai
ОБНОВЕНО · 03.10.2026

Търсене във видео с Cosmos-Embed1 на GX10

Търсим в колекция от кратки клипове с обикновено изречение на английски, например „a car overtaking a white truck“, без етикети по файловете. Моделът Cosmos-Embed1 на NVIDIA превръща и клипове, и текст във вектори в общо пространство, а локална векторна база (Qdrant) намира най-близките клипове.

⏱ 2–3 чНапредналиGX10NVIDIA GB10 · 128 GB обща паметCosmos-Embed1 · Qdrant · Docker
Cosmos-Embed1 (моделът)🔒 локалноQdrant · Docker🔒 локално
🔄
ОБНОВЕНО · 03.10.2026 — какво
Урокът е преработен изцяло по официалните страници. Махнахме: Cosmos Tokenizer като „енкодер за вектори“, отделния текстов енкодер CLIP със „проектор“ без обучени тегла (така векторите на текста и на видеото не са в едно пространство и търсенето не работи), твърдението „под 5 ms при над 10 млн. вектора“ (не е измерено), qdrant/qdrant:latest и публикуването на портове към цялата мрежа, както и вътрешните адреси и пътища. Добавихме: Cosmos-Embed1 — модел на NVIDIA точно за търсене текст↔видео (общо пространство, 8 кадъра на клип), закачена версия на Qdrant (образ за amd64 и arm64, проверен в Docker Hub на 03.10.2026), нов програмен интерфейс query_points, предупреждение за trust_remote_code, лицензът на NVIDIA накратко и кутия за личните данни. Не даваме числа за скорост и размер на колекцията — не сме ги мерили.
⚠️
Какво не сме пускали сами
Нямахме машина от класа GB10. Командите и програмите са сверени с документацията, но нито една не е пускана от нас — затова няма етикет „ТЕСТВАНО“. Особено непроверени са: PyTorch и OpenCV на Arm64, работата на Cosmos-Embed1 на GB10 (в картата на модела BF16 е тестван на Ampere и Hopper; Blackwell е в списъка на съвместимите), скоростта и избраното качество на търсенето.

01Какво ще научиш

02Преди да започнеш

ВариантВходДължина на вектора
Cosmos-Embed1-224p8 кадъра · 224×224256
Cosmos-Embed1-336p8 кадъра · 336×336768
Cosmos-Embed1-448p8 кадъра · 448×448768
⚖️
Лицензът накратко (не е правен съвет)
Cosmos-Embed1 е под NVIDIA Open Model License (проверено на страницата на NVIDIA и в картата на модела на 03.10.2026). NVIDIA потвърждава: моделите са годни за търговска употреба, можеш да създаваш и разпространяваш производни модели, а NVIDIA не претендира за собственост върху резултатите. При разпространение на модел на Cosmos или на продукти и услуги, изградени от него, трябва да добавиш бележката „Built on NVIDIA Cosmos“, а към копие на модела — лиценза и бележката „Licensed by NVIDIA Corporation under the NVIDIA Open Model License“. Ако заобиколиш или изключиш технически ограничение или защита на модела без равностойна защита, правата ти по лиценза се прекратяват. Договорът се урежда от правото на САЩ (Делауер) и изисква спазване на законите за износ. Прочети пълния текст преди търговска употреба.
⚖️
Видеото с хора е лични данни
Клипове, на които се виждат разпознаваеми хора или регистрационни номера, са лични данни по GDPR и българското право. Основание, информиране, срок на съхранение и достъп зависят от обекта и целта. Препоръка: преди да индексираш реални записи, провери с юрист. Този урок е технически, не е правна консултация. За упражнението ползвай свои клипове без хора или измислени.

03Стъпки

  1. Схемата

    Всеки клип → 8 равномерно избрани кадъра → вектор от Cosmos-Embed1 → Qdrant. Заявката (изречение) → вектор от същия модел → Qdrant връща най-близките клипове по косинусово сходство. Защо едно пространство? Само когато текстът и видеото са научени заедно, близост на вектори означава близост на смисъл.

  2. Qdrant в Docker — затворен към мрежата

    Закачената версия е v1.19.1; образът е за amd64 и arm64 (Docker Hub, 03.10.2026). Портът е публикуван само към 127.0.0.1, защото Qdrant по подразбиране е без удостоверяване. Данните са в именуван том. gRPC портът (6334) не се публикува.

    bash
    docker run -d --name qdrant --restart unless-stopped \
      -p 127.0.0.1:6333:6333 \
      -v qdrant_storage:/qdrant/storage \
      qdrant/qdrant:v1.19.1
    
    curl -s http://localhost:6333/

    Очакваш кратък отговор с името и версията. От друг компютър стигаш до Qdrant през SSH тунел (като в урока за n8n): ssh -L 6333:localhost:6333 <потребител>@<адрес-на-машината>.

  3. Среда за Python

    Нужни са transformers, einops, OpenCV (само за четене на кадри) и клиентът на Qdrant. PyTorch се слага по начина, който работи на твоята машина (урок 04-21) — не сме го пускали.

    bash
    python3 -m venv .venv
    source .venv/bin/activate
    pip install transformers einops opencv-python-headless qdrant-client==1.19.1
  4. Вектор от клип и от изречение

    Кодът следва примера в картата на модела. Закачи ревизия (revision) на хранилището: trust_remote_code=True изпълнява код от хранилището на модела — прегледай го и фиксирай конкретен commit, който си прегледал. Векторите са нормализирани; дължината им (256 или 768) се взема от резултата, а не се пише на ръка.

    python · embed.py
    import cv2, numpy as np, torch
    from transformers import AutoModel, AutoProcessor
    
    MODEL = "nvidia/Cosmos-Embed1-448p"
    REV = "<commit>"   # закачи прегледан commit
    
    model = AutoModel.from_pretrained(MODEL, trust_remote_code=True, revision=REV)
    model = model.to("cuda", dtype=torch.bfloat16).eval()
    proc = AutoProcessor.from_pretrained(MODEL, trust_remote_code=True, revision=REV)
    
    def read_frames(path, n=8):
        cap = cv2.VideoCapture(path)
        total = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
        frames = []
        for i in np.linspace(0, total - 1, n, dtype=int):
            cap.set(cv2.CAP_PROP_POS_FRAMES, int(i))
            ok, f = cap.read()
            if not ok:
                cap.release()
                return None
            frames.append(cv2.cvtColor(f, cv2.COLOR_BGR2RGB))
        cap.release()
        return np.stack(frames)          # (T, H, W, C), uint8
    
    @torch.no_grad()
    def video_vec(path):
        fr = read_frames(path)
        if fr is None:
            return None
        batch = np.transpose(fr[None], (0, 1, 4, 2, 3))   # (B, T, C, H, W)
        inp = proc(videos=batch).to("cuda", dtype=torch.bfloat16)
        return model.get_video_embeddings(**inp).visual_proj[0].float().cpu().numpy()
    
    @torch.no_grad()
    def text_vec(query):
        inp = proc(text=[query]).to("cuda", dtype=torch.bfloat16)
        return model.get_text_embeddings(**inp).text_proj[0].float().cpu().numpy()

    Първото изпълнение тегли модела от Hugging Face. Ако страницата на модела иска съгласие с условията, приеми ги с твоя акаунт (hf auth login — токенът не се пише в скриптове).

  5. Индексиране в Qdrant

    В полезния товар (payload) пазим относително име на файла и по желание етикети — не пълни пътища и не лични данни.

    python · index.py
    from pathlib import Path
    from qdrant_client import QdrantClient
    from qdrant_client.models import Distance, VectorParams, PointStruct
    from embed import video_vec
    
    client = QdrantClient(url="http://localhost:6333")
    NAME = "clips"
    CLIPS = Path("clips")
    
    paths = sorted(CLIPS.glob("**/*.mp4"))
    first = next(v for v in (video_vec(str(p)) for p in paths) if v is not None)
    
    if not client.collection_exists(NAME):
        client.create_collection(
            collection_name=NAME,
            vectors_config=VectorParams(size=len(first), distance=Distance.COSINE),
        )
    
    points = []
    for i, p in enumerate(paths):
        v = video_vec(str(p))
        if v is None:
            print("пропуснат:", p.name)
            continue
        points.append(PointStruct(id=i, vector=v.tolist(),
                                  payload={"file": str(p.relative_to(CLIPS))}))
    client.upsert(collection_name=NAME, points=points)
    print("точки:", client.count(collection_name=NAME).count)

    За големи колекции вмъквай на партиди (например по няколкостотин точки) — оптималният размер не сме го мерили.

  6. Търсене с текст

    Заявката е кратко описание на действие или сцена на английски — моделът е обучен предимно с такива надписи (картата на модела предупреждава, че други формулировки може да съвпадат лошо). Оценката (score) е косинусово сходство; не слагай фиксиран праг — избери го по свои примери.

    python · search.py
    from qdrant_client import QdrantClient
    from embed import text_vec
    
    client = QdrantClient(url="http://localhost:6333")
    
    def search(query, k=10):
        res = client.query_points(
            collection_name="clips",
            query=text_vec(query).tolist(),
            limit=k,
            with_payload=True,
        )
        return [(h.score, h.payload["file"]) for h in res.points]
    
    for score, name in search("a car overtaking a white truck"):
        print(round(score, 3), name)

    Търсене „видео към видео“: вземи вектора на един клип (video_vec) и го подай като query — така намираш подобни клипове.

  7. Набор за преглед от няколко заявки

    За да съберем набор от различни сцени, пускаме няколко заявки и записваме най-добрите резултати в списък. Човек преглежда списъка — векторното търсене подрежда, но не гарантира, че клипът е точно това, което искаш.

    python · manifest.py
    import json
    from search import search
    
    QUERIES = {
        "overtaking": "a car overtaking a white truck",
        "night_road": "a vehicle driving on a wet road at night",
        "crossing": "a vehicle slowing down at a pedestrian crossing",
    }
    manifest = {name: [f for _, f in search(q, k=50)] for name, q in QUERIES.items()}
    with open("manifest_for_review.json", "w", encoding="utf-8") as f:
        json.dump(manifest, f, ensure_ascii=False, indent=2)
  8. Как да знаеш, че работи

    Направи си малък контролен набор: 20 клипа, за които знаеш какво показват, и 5 заявки с очаквани резултати. Виж в кои позиции излизат очакваните клипове (например дали са в първите 5). Само така ще разбереш дали 224p, 336p или 448p ти е достатъчен — в картата на NVIDIA има резултати върху свои набори, но не върху твоите данни.

    🌐
    Пълният референтен проект на NVIDIA
    NVIDIA публикува и цялостен проект „Cosmos Dataset Search“: услуга Cosmos-embed (NIM), векторна база Milvus с ускорение cuVS, S3-съвместимо хранилище, уеб интерфейс и Docker Compose или Helm. Не сме го пускали и не знаем изискванията му към GB10 — виж документацията в хранилището му. Уроците тук ползват по-малкия път: един модел и Qdrant.

04Проверка

Тест

1. Защо в урока няма отделен текстов енкодер (CLIP) за заявките?

2. Как е публикуван Qdrant в стъпка 2 и защо?

3. Какво изисква лицензът на NVIDIA при разпространение на продукт, изграден върху модел на Cosmos?

4. На какъв език пишеш заявките за най-добър резултат?

05Какво следва

06Източници

  1. Cosmos-Embed1-448p — картата на модела: варианти, вход и изход, лиценз, ограничения.
  2. NVIDIA Open Model License — пълният текст на лиценза.
  3. Cosmos Dataset Search (GitHub) — референтният проект на NVIDIA.
  4. Cosmos Dataset Search (NVIDIA) — страницата на проекта.
  5. Qdrant в Docker Hub — тагове и архитектури (arm64).
  6. qdrant-client (PyPI) — версия на клиента.
  7. Qdrant — документация.
  8. Regulation (EU) 2016/679 (GDPR) — Регламент за защита на личните данни.