
Clip-as-Service est un service de grande échec à faible latence pour l'intégration d'images et de texte. Il peut être facilement intégré en microservice dans des solutions de recherche neuronales.
⚡ Rapide : servez des modèles de clip avec Tensorrt, ONNX Runtime et Pytorch avec Jit avec 800qps [*] . Streaming duplex non bloquant sur les demandes et les réponses, conçu pour les grandes données et les tâches de longue durée.
? Élastique : évoluer horizontalement de haut en bas de multiples modèles de clip sur un seul GPU, avec un équilibrage automatique de charge.
? Facile à utiliser : pas de courbe d'apprentissage, conception minimaliste sur le client et le serveur. API intuitive et cohérente pour l'intégration d'images et de phrases.
? Moderne : support client asynchrone. Basculer facilement entre les protocoles GRPC, HTTP, WebSocket avec TLS et compression.
? Intégration : intégration en douceur avec l'écosystème de recherche neuronale, y compris Jina et DocArray. Construisez des solutions croisées et multimodales en un rien de temps.
[*] Avec configation par défaut (réplique unique, pytorch no jit) sur geforce rtx 3090.
| via https? | via grpc? ⚡⚡ |
curl
-X POST https:// < your-inference-address > -http.wolf.jina.ai/post
-H ' Content-Type: application/json '
-H ' Authorization: <your access token> '
-d ' {"data":[{"text": "First do it"},
{"text": "then do it right"},
{"text": "then do it better"},
{"uri": "https://picsum.photos/200"}],
"execEndpoint":"/"} ' | # pip install clip-client
from clip_client import Client
c = Client (
'grpcs://<your-inference-address>-grpc.wolf.jina.ai' ,
credential = { 'Authorization' : '<your access token>' },
)
r = c . encode (
[
'First do it' ,
'then do it right' ,
'then do it better' ,
'https://picsum.photos/200' ,
]
)
print ( r ) |
Il existe quatre compétences de raisonnement visuel de base: la reconnaissance des objets, le comptage des objets, la reconnaissance des couleurs et la compréhension des relations spatiales. Essayons certains:
Vous devez installer
jq(un processeur JSON) pour briser les résultats.
| Image | via https? |
curl
-X POST https:// < your-inference-address > -http.wolf.jina.ai/post
-H ' Content-Type: application/json '
-H ' Authorization: <your access token> '
-d ' {"data":[{"uri": "https://picsum.photos/id/1/300/300",
"matches": [{"text": "there is a woman in the photo"},
{"text": "there is a man in the photo"}]}],
"execEndpoint":"/rank"} '
| jq " .data[].matches[] | (.text, .scores.clip_score.value) "Donne: | |
curl
-X POST https:// < your-inference-address > -http.wolf.jina.ai/post
-H ' Content-Type: application/json '
-H ' Authorization: <your access token> '
-d ' {"data":[{"uri": "https://picsum.photos/id/133/300/300",
"matches": [
{"text": "the blue car is on the left, the red car is on the right"},
{"text": "the blue car is on the right, the red car is on the left"},
{"text": "the blue car is on top of the red car"},
{"text": "the blue car is below the red car"}]}],
"execEndpoint":"/rank"} '
| jq " .data[].matches[] | (.text, .scores.clip_score.value) "Donne: | |
curl
-X POST https:// < your-inference-address > -http.wolf.jina.ai/post
-H ' Content-Type: application/json '
-H ' Authorization: <your access token> '
-d ' {"data":[{"uri": "https://picsum.photos/id/102/300/300",
"matches": [{"text": "this is a photo of one berry"},
{"text": "this is a photo of two berries"},
{"text": "this is a photo of three berries"},
{"text": "this is a photo of four berries"},
{"text": "this is a photo of five berries"},
{"text": "this is a photo of six berries"}]}],
"execEndpoint":"/rank"} '
| jq " .data[].matches[] | (.text, .scores.clip_score.value) "Donne: |
Clip-as-Service se compose de deux packages Python clip-server et clip-client qui peuvent être installés indépendamment . Les deux nécessitent Python 3.7+.
| Pytorch Runtime ⚡ | ONNX Runtime ⚡⚡ | Tensorrt Runtime ⚡⚡⚡ |
pip install clip-server | pip install " clip-server[onnx] " | pip install nvidia-pyindex
pip install " clip-server[tensorrt] " |
Vous pouvez également héberger le serveur sur Google Colab, en tirant parti de son GPU / TPU gratuit.
pip install clip-clientVous pouvez exécuter une vérification de connectivité simple après l'installation.
| C / s | Commande | Attendez-vous à la sortie |
|---|---|---|
| Serveur | python -m clip_server | ![]() |
| Client | from clip_client import Client
c = Client ( 'grpc://0.0.0.0:23456' )
c . profile () | ![]() |
Vous pouvez modifier 0.0.0.0 pour l'adresse IP Intranet ou publique pour tester la connectivité sur le réseau privé et public.
python -m clip_server . N'oubliez pas son adresse et son port. from clip_client import Client
c = Client ( 'grpc://0.0.0.0:51000' ) r = c . encode ([ 'First do it' , 'then do it right' , 'then do it better' ])
print ( r . shape ) # [3, 512] r = c . encode ([ 'apple.png' , # local image
'https://clip-as-service.jina.ai/_static/favicon.png' , # remote image
'data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7' ]) # in image URI
print ( r . shape ) # [3, 512]Des guides plus complets du serveur et de l'utilisateur client peuvent être trouvés dans les documents.
Créons une recherche de texte à l'image à l'aide de clip-asservit. À savoir, un utilisateur peut saisir une phrase et le programme renvoie des images correspondantes. Nous utiliserons l'ensemble de données et le package DocArray totalement. Notez que DocArray est inclus dans clip-client en tant que dépendance en amont, vous n'avez donc pas besoin de l'installer séparément.
Nous chargeons d'abord des images. Vous pouvez simplement les tirer de Jina Cloud:
from docarray import DocumentArray
da = DocumentArray . pull ( 'ttl-original' , show_progress = True , local_cache = True )Alternativement, vous pouvez aller totalement ressembler à un site Web officiel, décompresser et charger des images:
from docarray import DocumentArray
da = DocumentArray . from_files ([ 'left/*.jpg' , 'right/*.jpg' ])L'ensemble de données contient 12 032 images, il peut donc prendre un certain temps pour tirer. Une fois terminé, vous pouvez le visualiser et obtenir le premier goût de ces images:
da . plot_image_sprites ()
Démarrez le serveur avec python -m clip_server . Disons que c'est à 0.0.0.0:51000 avec le protocole GRPC (vous obtiendrez ces informations après l'exécution du serveur).
Créer un script client Python:
from clip_client import Client
c = Client ( server = 'grpc://0.0.0.0:51000' )
da = c . encode ( da , show_progress = True )Selon votre GPU et votre réseau client-serveur, il peut prendre un certain temps pour intégrer des images 12k. Dans mon cas, cela a pris environ deux minutes.
Si vous êtes impatient ou que vous n'avez pas de GPU, l'attente peut être l'enfer. Dans ce cas, vous pouvez simplement extraire notre ensemble de données d'image pré-codé:
from docarray import DocumentArray
da = DocumentArray . pull ( 'ttl-embedding' , show_progress = True , local_cache = True )Créons une simple invite pour permettre à un utilisateur de taper la phrase:
while True :
vec = c . encode ([ input ( 'sentence> ' )])
r = da . find ( query = vec , limit = 9 )
r [ 0 ]. plot_image_sprites ()Vous pouvez maintenant saisir des phrases en anglais arbitraires et afficher les 9 premières images correspondantes. La recherche est rapide et instinctive. Amuisons-nous:
| "Une pomme de terre heureuse" | "une super maléfique AI" | "Un gars appréciant son hamburger" |
|---|---|---|
|
|
|
| "Le professeur Cat est très sérieux" | "Un ingénieur de l'ego vit avec le parent" | "Il n'y aura pas de lendemain alors mange malsain" |
|---|---|---|
|
|
|
Enregistrons le résultat d'intégration pour notre prochain exemple:
da . save_binary ( 'ttl-image' )Nous pouvons également changer l'entrée et la sortie du dernier programme pour obtenir la recherche d'image à texte. Précisément, étant donné une image de requête, trouvez la phrase qui décrit le mieux l'image.
Utilisons toutes les phrases du livre "Pride and Prejudice".
from docarray import Document , DocumentArray
d = Document ( uri = 'https://www.gutenberg.org/files/1342/1342-0.txt' ). load_uri_to_text ()
da = DocumentArray (
Document ( text = s . strip ()) for s in d . text . replace ( ' r n ' , '' ). split ( '.' ) if s . strip ()
)Regardons ce que nous avons eu:
da . summary () Documents Summary
Length 6403
Homogenous Documents True
Common Attributes ('id', 'text')
Attributes Summary
Attribute Data type #Unique values Has empty value
──────────────────────────────────────────────────────────
id ('str',) 6403 False
text ('str',) 6030 False
Encode maintenant ces 6 403 phrases, cela peut prendre 10 secondes ou moins selon votre GPU et votre réseau:
from clip_client import Client
c = Client ( 'grpc://0.0.0.0:51000' )
r = c . encode ( da , show_progress = True )Encore une fois, pour les personnes impatientes ou qui n'ont pas de GPU, nous avons préparé un ensemble de données de texte précodé:
from docarray import DocumentArray
da = DocumentArray . pull ( 'ttl-textual' , show_progress = True , local_cache = True )Chargez notre introduction à l'image précédemment stockée, goûtez au hasard 10 documents d'image, puis trouvons le voisin le plus proche de chacun de chacun.
from docarray import DocumentArray
img_da = DocumentArray . load_binary ( 'ttl-image' )
for d in img_da . sample ( 10 ):
print ( da . find ( d . embedding , limit = 1 )[ 0 ]. text )Temps amusant! Remarque, contrairement à l'exemple précédent, ici l'entrée est une image et la phrase est la sortie. Toutes les phrases proviennent du livre "Pride and Prejudice".
|
|
|
|
|
| D'ailleurs, il y avait du vrai dans son apparence | Gardiner sourit | Quel est son prénom | À l'heure du thé, cependant, la dose avait été suffisante, et M. | Tu n'as pas bien l'air |
|
|
|
|
|
| "Un jeu!" Elle a pleuré | Si vous mentionnez mon nom à la cloche, vous serez pris en compte | Tant pis, cheveux de Mlle Lizzy | Elizabeth sera bientôt l'épouse de M. | Je les ai vus la veille |
À partir de 0.3.0 Clip-as-Service ajoute un nouveau point de terminaison /rank qui recrut les correspondances intermodales en fonction de leur vraisemblance conjointe dans le modèle de clip. Par exemple, étant donné un document d'image avec quelques correspondances de phrases prédéfinies comme ci-dessous:
from clip_client import Client
from docarray import Document
c = Client ( server = 'grpc://0.0.0.0:51000' )
r = c . rank (
[
Document (
uri = '.github/README-img/rerank.png' ,
matches = [
Document ( text = f'a photo of a { p } ' )
for p in (
'control room' ,
'lecture room' ,
'conference room' ,
'podium indoor' ,
'television studio' ,
)
],
)
]
)
print ( r [ '@m' , [ 'text' , 'scores__clip_score__value' ]]) [['a photo of a television studio', 'a photo of a conference room', 'a photo of a lecture room', 'a photo of a control room', 'a photo of a podium indoor'],
[0.9920725226402283, 0.006038925610482693, 0.0009973491542041302, 0.00078492151806131, 0.00010626466246321797]]
On peut voir maintenant a photo of a television studio est classé en haut avec un score clip_score à 0.992 . En pratique, on peut utiliser ce point de terminaison pour ré-classez le résultat correspondant d'un autre système de recherche, pour améliorer la qualité de recherche intermodale.
![]() | ![]() |
Dans le projet de flux de Dall · e, le clip est appelé pour classer les résultats générés de Dall · e. Il a un exécuteur testamentaire en haut de clip-client , qui appelle .arank() - la version asynchrone de .rank() :
from clip_client import Client
from jina import Executor , requests , DocumentArray
class ReRank ( Executor ):
def __init__ ( self , clip_server : str , ** kwargs ):
super (). __init__ ( ** kwargs )
self . _client = Client ( server = clip_server )
@ requests ( on = '/' )
async def rerank ( self , docs : DocumentArray , ** kwargs ):
return await self . _client . arank ( docs )
Intrigué? Cela ne fait que gratter la surface de ce dont le clip est capable. Lisez nos documents pour en savoir plus.
Clip-as-Service est soutenu par Jina AI et sous licence sous Apache-2.0. Nous embauchons activement des ingénieurs d'IA, des ingénieurs de solution pour construire le prochain écosystème de recherche neuronale en open source.