I den här bloggen kommer vi att bygga live-bildsökning och fråga den med naturligt språk. Till exempel kan du söka efter "en elefant", eller ett "söt djur" med en lista över bilder som input.
Vi kommer att använda multimodal inbäddningsmodell för att förstå och inbäddning av bilden, och bygga en vektorindex för effektiv återvinning. Vi kommer att använda CocoIndex för att bygga indexeringsflödet, det är en ultra-presterande realtidsdatatransformationsramverk. Under körning kan du lägga till nya filer till mappen och det bara bearbetar ändrade filer och kommer att indexeras inom en minut.
Det skulle betyda mycket för oss om du kunde släppa en stjärna påCocoIndex på GitHubOm denna tutorial är till hjälp.
tekniker
CocoIndex
CocoIndexär en ultra-presterande realtidsdatatransformationsram för AI.
Klipp ViT-L/14
Klipp ViT-L/14är en kraftfull vision-språkmodell som kan förstå både bilder och texter. Den är utbildad för att anpassa visuella och textuella representationer i ett delat inbäddningsutrymme, vilket gör den perfekt för vår bildsökning.
I vårt projekt använder vi CLIP för att:
- Generera inbäddningar av bilderna direkt
- Konvertera naturliga språk sökfrågor till samma inbäddningsutrymme
- Aktivera semantisk sökning genom att jämföra frågeinbäddningar med rubrikinbäddningar
Qdrant
Qdrantär en högpresterande vektordatabas. Vi använder den för att lagra och fråga in inbäddningarna.
snabba
snabbaär en modern, snabb (högpresterande), webbram för att bygga API med Python 3.7+ baserat på standard Python typ tips.
Förutsättningar
- Installera Postgres. CocoIndex använder Postgres för att hålla reda på data linje för incrementell bearbetning.
- Installation av Qdrant.
Definiera indexering flöde
Flödesdesign
Flödesdiagrammet illustrerar hur vi kommer att bearbeta vår kodbas:
- Läs bildfiler från det lokala filsystemet
- Använd CLIP för att förstå och bädda in bilden
- Spara inbäddningarna i en vektordatabas för hämtning
1 Inkludera bilderna
@cocoindex.flow_def(name="ImageObjectEmbedding")
def image_object_embedding_flow(flow_builder: cocoindex.FlowBuilder, data_scope: cocoindex.DataScope):
data_scope["images"] = flow_builder.add_source(
cocoindex.sources.LocalFile(path="img", included_patterns=["*.jpg", "*.jpeg", "*.png"], binary=True),
refresh_interval=datetime.timedelta(minutes=1) # Poll for changes every 1 minute
)
img_embeddings = data_scope.add_collector()
flow_builder.add_source
kommer att skapa en tabell med underfält (filename
ochcontent
) kan vi hänvisa till denDokumentationFör mer detaljer.
Bearbeta varje bild och samla in informationen.
2.1 Infoga bilden med CLIP
@functools.cache
def get_clip_model() -> tuple[CLIPModel, CLIPProcessor]:
model = CLIPModel.from_pretrained(CLIP_MODEL_NAME)
processor = CLIPProcessor.from_pretrained(CLIP_MODEL_NAME)
return model, processor
den@functools.cache
I det här fallet säkerställer det att vi bara laddar CLIP-modellen och processorn en gång.
@cocoindex.op.function(cache=True, behavior_version=1, gpu=True)
def embed_image(img_bytes: bytes) -> cocoindex.Vector[cocoindex.Float32, Literal[384]]:
"""
Convert image to embedding using CLIP model.
"""
model, processor = get_clip_model()
image = Image.open(io.BytesIO(img_bytes)).convert("RGB")
inputs = processor(images=image, return_tensors="pt")
with torch.no_grad():
features = model.get_image_features(**inputs)
return features[0].tolist()
embed_image
är en anpassad funktion som använder CLIP-modellen för att konvertera en bild till en vektorinbäddning. Den accepterar bilddata i byteformat och returnerar en lista över flytande punktsnummer som representerar bildens inbäddning.
Funktionen stöder caching genomcache
parameter. När den är aktiverad lagrar utföraren funktionens resultat för återanvändning under vidare bearbetning, vilket är särskilt användbart för beräkningsintensiva operationer.Dokumentation.
Sedan kommer vi att bearbeta varje bild och samla in informationen.
with data_scope["images"].row() as img:
img["embedding"] = img["content"].transform(embed_image)
img_embeddings.collect(
id=cocoindex.GeneratedField.UUID,
filename=img["filename"],
embedding=img["embedding"],
)
2.3 Samla in inbäddningarna
Exportera inbäddningarna till ett bord i Qdrant.
img_embeddings.export(
"img_embeddings",
cocoindex.storages.Qdrant(
collection_name="image_search",
grpc_url=QDRANT_GRPC_URL,
),
primary_key_fields=["id"],
setup_by_user=True,
)
Sök efter index
Bädda in frågan med CLIP, som kartlägger både text och bilder i samma inbäddningsutrymme, vilket möjliggör cross-modal likhetssökning.
def embed_query(text: str) -> list[float]:
model, processor = get_clip_model()
inputs = processor(text=[text], return_tensors="pt", padding=True)
with torch.no_grad():
features = model.get_text_features(**inputs)
return features[0].tolist()
Definiera en FastAPI Endpoint/search
som utför semantisk bildsökning.
@app.get("/search")
def search(q: str = Query(..., description="Search query"), limit: int = Query(5, description="Number of results")):
# Get the embedding for the query
query_embedding = embed_query(q)
# Search in Qdrant
search_results = app.state.qdrant_client.search(
collection_name="image_search",
query_vector=("embedding", query_embedding),
limit=limit
)
Detta söker Qdrant-vektordatabasen för liknande inbäddningar. Returnerar toppenlimit
Resultatet
# Format results
out = []
for result in search_results:
out.append({
"filename": result.payload["filename"],
"score": result.score
})
return {"results": out}
Denna slutpunkt möjliggör semantisk bildsökning där användare kan hitta bilder genom att beskriva dem i naturligt språk, snarare än med exakta nyckelord matcher.
Ansökan
Snabbt eld
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Serve images from the 'img' directory at /img
app.mount("/img", StaticFiles(directory="img"), name="img")
FastAPI applikationsinstallation med CORS middleware och statisk fil som serverar appen är konfigurerad till:
- Tillåta korsförfrågningar från alla ursprung
- Servera statiska bildfiler från 'img' katalogen
- Hantera API-ändpunkter för bild sökfunktionalitet
@app.on_event("startup")
def startup_event():
load_dotenv()
cocoindex.init()
# Initialize Qdrant client
app.state.qdrant_client = QdrantClient(
url=QDRANT_GRPC_URL,
prefer_grpc=True
)
app.state.live_updater = cocoindex.FlowLiveUpdater(image_object_embedding_flow)
app.state.live_updater.start()
Starthändelsehanteraren initialiserar applikationen när den startar först.
- load_dotenv(): Ladda miljövariabler från en .env-fil, som är användbar för konfiguration som API-nycklar och URL-adresser
- cocoindex.init(): Initialiserar CocoIndex-ramverket och ställer in nödvändiga komponenter och konfigurationer
- Qdrant Client Setup:
- Creates a new
QdrantClient
instance - Configures it to use the gRPC URL specified in environment variables
- Enables gRPC preference for better performance
- Stores the client in the FastAPI app state for access across requests
- Creates a new
- Live Updater Setup:
- Creates a
FlowLiveUpdater
instance for theimage_object_embedding_flow
- This enables real-time updates to the image search index
- Starts the live updater to begin monitoring for changes
- Creates a
Denna initialisering säkerställer att alla nödvändiga komponenter är korrekt konfigurerade och körs när programmet startar.
Fronten
Du kan kontrollera frontend-kodenhärVi har avsiktligt hållit det enkelt och minimalistiskt att fokusera på bildsökningsfunktionaliteten.
Dags att ha kul!
-
Create a collection in Qdrant
curl -X PUT 'http://localhost:6333/collections/image_search' \ -H 'Content-Type: application/json' \ -d '{ "vectors": { "embedding": { "size": 768, "distance": "Cosine" } } }'
-
Setup indexing flow
cocoindex setup main.py
It is setup with a live updater, so you can add new files to the folder and it will be indexed within a minute.
-
Run backend
uvicorn main:app --reload --host 0.0.0.0 --port 8000
-
Run frontend
cd frontend npm install npm run dev
Gå tillhttp://localhost:5174För att söka.
Lägg till en ny bild iimg
Folders, till exempel dettaSöt sköldpaddaVänta en minut för att den nya bilden ska bearbetas och indexeras.
Om du vill övervaka indexeringsprocessen kan du se den i CocoInsightcocoindex server -ci main.py
.
Finally - we are constantly improving, and more features and examples are coming soon. If you love this article, please give us a star ⭐ at GitHub to help us grow. Thanks for reading!
GitHub