O Clip-As Service é um serviço de alta escalabilidade de baixa latência para incorporar imagens e texto. Pode ser facilmente integrado como um microsserviço nas soluções de pesquisa neural.
⚡ Rápido : sirva modelos de clipe com Tensorrt, Onnx Runtime e Pytorch sem JIT com 800qps [*] . Fluxo duplex não bloqueador sob solicitações e respostas, projetado para grandes dados e tarefas de longa duração.
? ELÁSTICO : Escala horizontalmente para cima e para baixo vários modelos de clipe em GPU único, com balanceamento automático de carga.
? Fácil de usar : sem curva de aprendizado, design minimalista no cliente e no servidor. API intuitiva e consistente para incorporação de imagem e sentença.
? Moderno : Suporte ao cliente assíncrono. Alterne facilmente os protocolos GRPC, HTTP, WebSocket com TLS e compactação.
? Integração : Integração suave com o ecossistema de pesquisa neural, incluindo Jina e DocArray. Crie soluções cruzadas e multimodais em pouco tempo.
[*] Com a configuração padrão (réplica única, Pytorch no JIT) no 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 ) |
Existem quatro habilidades básicas de raciocínio visual: reconhecimento de objetos, contagem de objetos, reconhecimento de cores e compreensão da relação espacial. Vamos tentar alguns:
Você precisa instalar
jq
(um processador JSON) para prettificar os resultados.
Imagem | 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) " dá: | |
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) " dá: | |
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) " dá: |
O clipe como serviço consiste em dois pacotes Python clip-server
e clip-client
que podem ser instalados de forma independente . Ambos requerem 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] " |
Você também pode hospedar o servidor no Google Colab, aproveitando sua GPU/TPU gratuita.
pip install clip-client
Você pode executar uma verificação simples de conectividade após a instalação.
C/s | Comando | Espere saída |
---|---|---|
Servidor | python -m clip_server | ![]() |
Cliente | from clip_client import Client
c = Client ( 'grpc://0.0.0.0:23456' )
c . profile () | ![]() |
Você pode alterar 0.0.0.0
para o endereço IP da intranet ou público para testar a conectividade em relação à rede pública e privada.
python -m clip_server
. Lembre -se de seu endereço e porta. 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]
Os guias mais abrangentes do servidor e do cliente do cliente podem ser encontrados nos documentos.
Vamos criar uma pesquisa de texto para imagem usando clipe como serviço. Ou seja, um usuário pode inserir uma frase e o programa retorna imagens correspondentes. Usaremos totalmente o pacote de dados e docarray. Observe que o docarray está incluído no clip-client
como uma dependência a montante, para que você não precise instalá-lo separadamente.
Primeiro, carregamos imagens. Você pode simplesmente puxá -los de Jina Cloud:
from docarray import DocumentArray
da = DocumentArray . pull ( 'ttl-original' , show_progress = True , local_cache = True )
Como alternativa, você pode ir para o site oficial, descompactar e carregar imagens:
from docarray import DocumentArray
da = DocumentArray . from_files ([ 'left/*.jpg' , 'right/*.jpg' ])
O conjunto de dados contém 12.032 imagens, por isso pode demorar um pouco para puxar. Uma vez feito, você pode visualizá -lo e ter o primeiro gosto dessas imagens:
da . plot_image_sprites ()
Inicie o servidor com python -m clip_server
. Digamos que esteja em 0.0.0.0:51000
com o protocolo GRPC
(você obterá essas informações após a execução do servidor).
Crie um script do cliente Python:
from clip_client import Client
c = Client ( server = 'grpc://0.0.0.0:51000' )
da = c . encode ( da , show_progress = True )
Dependendo da sua rede de GPU e cliente-servidor, pode demorar um pouco para incorporar 12k imagens. No meu caso, levou cerca de dois minutos.
Se você está impaciente ou não tem uma GPU, esperar pode ser um inferno. Nesse caso, você pode simplesmente puxar nosso conjunto de dados de imagem pré-codificado:
from docarray import DocumentArray
da = DocumentArray . pull ( 'ttl-embedding' , show_progress = True , local_cache = True )
Vamos criar um aviso simples para permitir que um usuário digite a frase:
while True :
vec = c . encode ([ input ( 'sentence> ' )])
r = da . find ( query = vec , limit = 9 )
r [ 0 ]. plot_image_sprites ()
Agora você pode inserir frases arbitrárias em inglês e visualizar as 9 imagens correspondentes. A pesquisa é rápida e instintiva. Vamos nos divertir:
"Uma batata feliz" | "Uma super mal ai" | "Um cara gostando de seu hambúrguer" |
---|---|---|
"Professor Cat é muito sério" | "Um engenheiro do ego vive com os pais" | "Não haverá amanhã, então vamos comer prejudiciais" |
---|---|---|
Vamos salvar o resultado de incorporação para o nosso próximo exemplo:
da . save_binary ( 'ttl-image' )
Também podemos alternar a entrada e saída do último programa para obter pesquisa de imagem para texto. Precisamente, dada uma imagem de consulta, encontre a frase que melhor descreve a imagem.
Vamos usar todas as frases do livro "Orgulho e preconceito".
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 ()
)
Vejamos o que conseguimos:
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
Agora codifique essas 6.403 frases, pode levar 10 segundos ou menos, dependendo da sua GPU e rede:
from clip_client import Client
c = Client ( 'grpc://0.0.0.0:51000' )
r = c . encode ( da , show_progress = True )
Novamente, para pessoas impacientes ou não têm uma GPU, preparamos um conjunto de dados de texto pré-codificado:
from docarray import DocumentArray
da = DocumentArray . pull ( 'ttl-textual' , show_progress = True , local_cache = True )
Vamos carregar nossa imagem anteriormente armazenada incorporação, amostra aleatoriamente 10 documentos de imagem e, em seguida, encontre o vizinho Top-1 mais próximo de cada um.
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 )
Tempo divertido! Observe, diferentemente do exemplo anterior, aqui a entrada é uma imagem e a frase é a saída. Todas as frases vêm do livro "Orgulho e preconceito".
Além disso, havia verdade em sua aparência | Gardiner sorriu | Qual o nome dele | Na hora do chá, no entanto, a dose foi suficiente, e Sr. | Você não parece bem |
"Um jogador!" Ela chorou | Se você mencionar meu nome no sino, você será atendido | Não importa o cabelo da senhorita Lizzy | Elizabeth em breve será a esposa do Sr. | Eu os vi na noite anterior |
A partir de 0.3.0
o clipe como serviço adiciona um novo ponto de extremidade /rank
que re-classifica as correspondências cruzadas de acordo com sua probabilidade conjunta no modelo de clipe. Por exemplo, dado um documento de imagem com algumas partidas de frases predefinidas como abaixo:
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]]
Pode -se ver agora a photo of a television studio
é classificado no topo com o clip_score
SCORE em 0.992
. Na prática, pode-se usar esse endpoint para re-classificar o resultado correspondente de outro sistema de pesquisa, para melhorar a qualidade da pesquisa entre modais.
![]() | ![]() |
No projeto de fluxo Dall · E, o clipe é chamado para a classificação dos resultados gerados de Dall · e. Possui um executor envolto em cima do clip-client
, que chama .arank()
- a versão assíncrona 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 )
Intrigado? Isso está apenas arranhando a superfície do que o clipe como serviço é capaz. Leia nossos documentos para saber mais.
O clipe como serviço é apoiado por Jina AI e licenciado no Apache-2.0. Estamos contratando ativamente engenheiros de IA, engenheiros de solução para construir o próximo ecossistema de busca neural em código aberto.