ChromaDB

ChromaDB ChromaDB

Bancos de dados vetoriaislink image 60

Vimos na postagem embeddings que os embeddings são uma forma de representar palavras em um espaço vetorial. Nesta postagem, veremos como podemos armazenar esses embeddings em bancos de dados vetoriais e como podemos fazer consultas a eles.

Este caderno foi traduzido automaticamente para torná-lo acessível a mais pessoas, por favor me avise se você vir algum erro de digitação..

Quando temos uma consulta, podemos criar a incorporação da consulta, pesquisar no banco de dados de vetores as incorporações que mais se aproximam da consulta e retornar os documentos que correspondem a essas incorporações ou uma explicação desses documentos.

banco de dados vetorial

Ou seja, vamos gerar um banco de dados de informações, vamos criar embeddings dessas informações e vamos armazená-las em um banco de dados vetorial. Então, quando um usuário fizer uma consulta, converteremos a consulta em embeddings, pesquisaremos no banco de dados os embeddings com a maior similaridade e retornaremos os documentos que correspondem a esses embeddings.

Além dos documentos, outras informações podem ser armazenadas no banco de dados, que chamaremos de metadados. Por exemplo, se estivermos trabalhando com um conjunto de itens de notícias, podemos armazenar o título, a data, o autor etc. do item de notícias.

Cromalink image 61

Nesta postagem, vamos analisar o crhoma, pois ele é o banco de dados de vetores mais usado, como pode ser visto neste relatório langchain state of ai 2023.

Vectorstores mais usados](https://blog.langchain.dev/content/images/size/w1000/2023/12/Top-vectorstores--1-.png)

Instalaçãolink image 62

Portanto, para instalar o chroma com o conda, você precisa fazer o seguinte

conda install conda-forge::chromadb
      ```
      
      Ou se você quiser instalar com o pip
      
      ````bash
      pip install chromadb
      ```
      

Uso rápidolink image 63

Para uma aplicação rápida, primeiro importamos o chroma

	
import chromadb
Copy

Em seguida, criamos um cliente chroma.

	
import chromadb
chroma_client = chromadb.Client()
Copy

Criamos uma coleção. Uma coleção é o local onde as incorporações, as incorporações e os metadados serão armazenados.

	
import chromadb
chroma_client = chromadb.Client()
collection = chroma_client.create_collection(name="my_collection")
Copy

Como você pode ver, é exibida uma mensagem indicando que nenhuma função de embeddings foi introduzida e, portanto, o padrão será all-MiniLM-L6-v2, que é semelhante ao modelo paraphrase-MiniLM-L6-v2 que usamos na postagem embeddings.

Falaremos mais sobre isso mais tarde, mas podemos escolher como gerar os embeddings.

Agora, adicionamos documentos, IDs e metadados à coleção.

	
import chromadb
chroma_client = chromadb.Client()
collection = chroma_client.create_collection(name="my_collection")
collection.add(
documents=["This is a python docs", "This is JavaScript docs"],
metadatas=[{"source": "Python source"}, {"source": "JavaScript source"}],
ids=["id1", "id2"]
)
Copy

Agora podemos fazer uma consulta

	
import chromadb
chroma_client = chromadb.Client()
collection = chroma_client.create_collection(name="my_collection")
collection.add(
documents=["This is a python docs", "This is JavaScript docs"],
metadatas=[{"source": "Python source"}, {"source": "JavaScript source"}],
ids=["id1", "id2"]
)
results = collection.query(
query_texts=["This is a query of Python"],
n_results=2
)
Copy
	
import chromadb
chroma_client = chromadb.Client()
collection = chroma_client.create_collection(name="my_collection")
collection.add(
documents=["This is a python docs", "This is JavaScript docs"],
metadatas=[{"source": "Python source"}, {"source": "JavaScript source"}],
ids=["id1", "id2"]
)
results = collection.query(
query_texts=["This is a query of Python"],
n_results=2
)
results
Copy
	
{'ids': [['id1', 'id2']],
'distances': [[0.6205940246582031, 1.4631636142730713]],
'metadatas': [[{'source': 'Python source'}, {'source': 'JavaScript source'}]],
'embeddings': None,
'documents': [['This is a python docs', 'This is JavaScript docs']],
'uris': None,
'data': None}

Como podemos ver, a distância para id1 é menor do que a distância para id2, portanto, parece que o documento 1 é mais adequado para responder à consulta.

Bancos de dados persistenteslink image 64

O banco de dados que criamos anteriormente é temporário e, assim que fecharmos o notebook, ele desaparecerá. Portanto, para criar um banco de dados persistente, é necessário passar para o chroma o caminho onde ele será salvo.

Primeiro, vamos criar a pasta onde salvaremos o banco de dados

	
from pathlib import Path
chroma_path = Path("chromadb")
chroma_path.mkdir(exist_ok=True)
Copy

Agora, criamos um cliente na pasta que criamos.

	
from pathlib import Path
chroma_path = Path("chromadb")
chroma_path.mkdir(exist_ok=True)
chroma_client_persistent = chromadb.PersistentClient(path = str(chroma_path))
Copy

Coleçõeslink image 65

Criar coleçõeslink image 66

Ao criar uma coleção, um nome deve ser especificado. O nome deve ter as seguintes considerações:

  • O comprimento do nome deve ter entre 3 e 63 caracteres.
  • O nome deve começar e terminar com uma letra minúscula ou dígito e pode conter pontos finais, hífens e sublinhados no meio.
  • O nome não deve conter dois dois pontos consecutivos.
  • O nome não deve ser um endereço IP válido.

Também podemos atribuir a ele uma função de incorporação. Se não for atribuída uma função, o padrão será a função all-MiniLM-L6-v2.

	
from pathlib import Path
chroma_path = Path("chromadb")
chroma_path.mkdir(exist_ok=True)
chroma_client_persistent = chromadb.PersistentClient(path = str(chroma_path))
collection = chroma_client.create_collection(name="my_other_collection")
Copy

Como você pode ver, uma segunda coleção foi criada para o mesmo cliente chroma_client, portanto, para um único cliente, podemos ter várias coleções.

Recuperar coleçõeslink image 67

Se quisermos recuperar uma coleção de um cliente, podemos fazer isso com o método get_collection.

	
from pathlib import Path
chroma_path = Path("chromadb")
chroma_path.mkdir(exist_ok=True)
chroma_client_persistent = chromadb.PersistentClient(path = str(chroma_path))
collection = chroma_client.create_collection(name="my_other_collection")
collection = chroma_client.get_collection(name = "my_collection")
Copy

Recuperar ou criar coleçõeslink image 68

Podemos obter coleções e, se elas não existirem, criá-las com o método get_or_create_collection.

	
from pathlib import Path
chroma_path = Path("chromadb")
chroma_path.mkdir(exist_ok=True)
chroma_client_persistent = chromadb.PersistentClient(path = str(chroma_path))
collection = chroma_client.create_collection(name="my_other_collection")
collection = chroma_client.get_collection(name = "my_collection")
collection = chroma_client.get_or_create_collection(name = "my_tird_collection")
Copy

Excluir coleçõeslink image 69

Podemos excluir uma coleção com o método delete_collection.

	
from pathlib import Path
chroma_path = Path("chromadb")
chroma_path.mkdir(exist_ok=True)
chroma_client_persistent = chromadb.PersistentClient(path = str(chroma_path))
collection = chroma_client.create_collection(name="my_other_collection")
collection = chroma_client.get_collection(name = "my_collection")
collection = chroma_client.get_or_create_collection(name = "my_tird_collection")
chroma_client.delete_collection(name="my_tird_collection")
Copy

Obter itens de coleçõeslink image 70

Podemos obter os primeiros 10 itens da coleção com o método peek.

	
from pathlib import Path
chroma_path = Path("chromadb")
chroma_path.mkdir(exist_ok=True)
chroma_client_persistent = chromadb.PersistentClient(path = str(chroma_path))
collection = chroma_client.create_collection(name="my_other_collection")
collection = chroma_client.get_collection(name = "my_collection")
collection = chroma_client.get_or_create_collection(name = "my_tird_collection")
chroma_client.delete_collection(name="my_tird_collection")
collection = chroma_client.get_collection(name = "my_collection")
collection.peek()
Copy
	
{'ids': ['id1', 'id2'],
'embeddings': [[-0.06924048811197281,
0.061624377965927124,
-0.090973399579525,
0.013923337683081627,
0.006247623357921839,
-0.1078396588563919,
-0.012472339905798435,
0.03485661745071411,
-0.06300634145736694,
-0.00880391988903284,
0.06879935413599014,
0.0564003586769104,
0.07040536403656006,
-0.020754728466272354,
-0.04048658534884453,
-0.006666888482868671,
-0.0953674241900444,
0.049781784415245056,
0.021780474111437798,
-0.06344643980264664,
0.06119797006249428,
0.0834411084651947,
-0.034758951514959335,
0.0029120452236384153,
...
-0.013378280214965343]],
'metadatas': [{'source': 'Python source'}, {'source': 'JavaScript source'}],
'documents': ['This is a python docs', 'This is JavaScript docs'],
'uris': None,
'data': None}

Nesse caso, apenas dois foram obtidos, porque nossa coleção tem apenas dois documentos.

Se você quiser obter outro número de itens, poderá especificá-lo com o argumento limit.

	
collection.peek(limit=1)
Copy
	
{'ids': ['id1'],
'embeddings': [[-0.06924048811197281,
0.061624377965927124,
-0.090973399579525,
0.013923337683081627,
0.006247623357921839,
-0.1078396588563919,
-0.012472339905798435,
0.03485661745071411,
-0.06300634145736694,
-0.00880391988903284,
0.06879935413599014,
0.0564003586769104,
0.07040536403656006,
-0.020754728466272354,
-0.04048658534884453,
-0.006666888482868671,
-0.0953674241900444,
0.049781784415245056,
0.021780474111437798,
-0.06344643980264664,
0.06119797006249428,
0.0834411084651947,
-0.034758951514959335,
0.0029120452236384153,
...
0.012315398082137108]],
'metadatas': [{'source': 'Python source'}],
'documents': ['This is a python docs'],
'uris': None,
'data': None}

Obter o número total de itens nas coleçõeslink image 71

Podemos obter o número total de itens na coleção com o método count.

	
collection.count()
Copy
	
2

Alterar a função de similaridadelink image 72

Anteriormente, quando fizemos uma consulta, obtivemos a similaridade dos embeddings com nossa consulta, porque, por padrão, em uma coleção, a função de distância é usada, mas podemos especificar qual função de similaridade queremos usar. As possibilidades são

  • L2 ao quadrado (l2)
  • Produto interno (ip)
  • Similaridade de cosseno (cosine)

Na postagem [Measurement of similarity between embeddings] (http://maximofn.com/embeddings-similarity/), vimos a similaridade L2 e cosseno, caso queira saber mais sobre elas.

Portanto, podemos criar coleções com outra função de similaridade com o argumento metadata={"hnsw:space": <function>}.

	
collection = chroma_client.create_collection(name="colection_cosine", metadata={"hnsw:space": "cosine"})
Copy

Adicionar dados à coleçãolink image 73

Adicionar documentoslink image 74

Vamos examinar os dados que temos na coleção novamente com o método peek.

	
collection = chroma_client.create_collection(name="colection_cosine", metadata={"hnsw:space": "cosine"})
collection.peek()
Copy
	
{'ids': [],
'embeddings': [],
'metadatas': [],
'documents': [],
'uris': None,
'data': None}

Como podemos ver, ela está vazia, porque a última coleção que criamos foi a função de similaridade cosine, mas não adicionamos dados a ela. Vamos ver como é isso, obtendo o nome da coleção

	
collection.name
Copy
	
'colection_cosine'

Assim, trazemos de volta a primeira coleção que criamos e para a qual inserimos dados.

	
collection = chroma_client.get_collection(name = "my_collection")
Copy

Agora podemos adicionar dados à coleção com o método add.

	
collection = chroma_client.get_collection(name = "my_collection")
collection.add(
documents=["This is a Mojo docs", "This is Rust docs"],
metadatas=[{"source": "Mojo source"}, {"source": "Rust source"}],
ids=["id3", "id4"]
)
Copy

Como você pode ver, os IDs são consecutivos e não têm o mesmo valor de antes, pois osIDs precisam ser exclusivos.

Se tentarmos adicionar dados repetindo IDs, ele indicará que já existem dados com esses IDs.

	
collection = chroma_client.get_collection(name = "my_collection")
collection.add(
documents=["This is a Mojo docs", "This is Rust docs"],
metadatas=[{"source": "Mojo source"}, {"source": "Rust source"}],
ids=["id3", "id4"]
)
collection.add(
documents=["This is a Pytorch docs", "This is TensorRT docs"],
metadatas=[{"source": "Pytorch source"}, {"source": "TensorRT source"}],
ids=["id3", "id4"]
)
Copy
	
Add of existing embedding ID: id3
Add of existing embedding ID: id4
Insert of existing embedding ID: id3
Insert of existing embedding ID: id4

Não foi possível adicionar os documentos do Pytorch e do TensorRT.

Vamos dar uma olhada nos dados de coleta

	
collection.peek()
Copy
	
{'ids': ['id1', 'id2', 'id3', 'id4'],
'embeddings': [[-0.06924048811197281,
0.061624377965927124,
-0.090973399579525,
0.013923337683081627,
0.006247623357921839,
-0.1078396588563919,
-0.012472339905798435,
0.03485661745071411,
-0.06300634145736694,
-0.00880391988903284,
0.06879935413599014,
0.0564003586769104,
0.07040536403656006,
-0.020754728466272354,
-0.04048658534884453,
-0.006666888482868671,
-0.0953674241900444,
0.049781784415245056,
0.021780474111437798,
-0.06344643980264664,
0.06119797006249428,
0.0834411084651947,
-0.034758951514959335,
0.0029120452236384153,
...
{'source': 'JavaScript source'},
{'source': 'Mojo source'},
{'source': 'Rust source'}],
'documents': ['This is a python docs',
'This is JavaScript docs',
'This is a Mojo docs',
'This is Rust docs'],
'uris': None,
'data': None}

Como pode ser visto, os conteúdos originais de ID3 e ID4 foram mantidos.

Adicionar incorporaçõeslink image 75

Podemos adicionar embeddings diretamente sem adicionar documentos. No entanto, isso não faz muito sentido, pois se adicionarmos apenas embeddings, quando quisermos fazer uma consulta, não haverá documentos para recuperar.

Obtemos algumas incorporações para criar outras com as mesmas dimensões.

	
embedding1 = collection.peek(1)['embeddings']
len(embedding1), len(embedding1[0])
Copy
	
(1, 384)

Criamos novas incorporações com todos eles para sabermos quais foram criados.

	
new_embedding = [1] * len(embedding1[0])
new_embedding = [new_embedding]
len(new_embedding), len(new_embedding[0])
Copy
	
(1, 384)

Agora adicionamos os novos embeddings

	
collection.add(
embeddings=new_embedding,
metadatas=[{"source": "Only embeddings"}],
ids=["id5"]
)
Copy

Vamos dar uma olhada nos dados de coleta

	
collection.add(
embeddings=new_embedding,
metadatas=[{"source": "Only embeddings"}],
ids=["id5"]
)
collection.peek()['embeddings'][-1]
Copy
	
[1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
...,
1.0,
1.0,
1.0,
1.0,
1.0]

O último elemento da condição tem as incorporações que adicionamos.

Observação: Se tentarmos adicionar bordados com um tamanho diferente dos que já estão na coleção, ocorrerá um erro.

	
new_embedding_differetn_size = [1] * (len(embedding1[0])-1)
new_embedding_differetn_size = [new_embedding_differetn_size]
len(new_embedding_differetn_size), len(new_embedding_differetn_size[0])
Copy
	
(1, 383)

Como você pode ver, a dimensão de incorporação é 383, em vez de 384.

	
collection.add(
embeddings=new_embedding_differetn_size,
metadatas=[{"source": "New embeddings different size"}],
ids=["id6"]
)
Copy
	
---------------------------------------------------------------------------
InvalidDimensionException Traceback (most recent call last)
Cell In[28], line 1
----> 1 collection.add(
2 embeddings=new_embedding_differetn_size,
3 metadatas=[{"source": "New embeddings different size"}],
4 ids=["id6"]
5 )
File ~/miniforge3/envs/crhomadb/lib/python3.11/site-packages/chromadb/api/models/Collection.py:168, in Collection.add(self, ids, embeddings, metadatas, documents, images, uris)
163 raise ValueError(
164 "You must set a data loader on the collection if loading from URIs."
165 )
166 embeddings = self._embed(self._data_loader(uris))
--> 168 self._client._add(ids, self.id, embeddings, metadatas, documents, uris)
File ~/miniforge3/envs/crhomadb/lib/python3.11/site-packages/chromadb/telemetry/opentelemetry/__init__.py:127, in trace_method.<locals>.decorator.<locals>.wrapper(*args, **kwargs)
125 global tracer, granularity
126 if trace_granularity < granularity:
--> 127 return f(*args, **kwargs)
128 if not tracer:
129 return f(*args, **kwargs)
File ~/miniforge3/envs/crhomadb/lib/python3.11/site-packages/chromadb/api/segment.py:375, in SegmentAPI._add(self, ids, collection_id, embeddings, metadatas, documents, uris)
365 records_to_submit = []
366 for r in _records(
367 t.Operation.ADD,
368 ids=ids,
(...)
373 uris=uris,
374 ):
--> 375 self._validate_embedding_record(coll, r)
376 records_to_submit.append(r)
377 self._producer.submit_embeddings(coll["topic"], records_to_submit)
File ~/miniforge3/envs/crhomadb/lib/python3.11/site-packages/chromadb/telemetry/opentelemetry/__init__.py:127, in trace_method.<locals>.decorator.<locals>.wrapper(*args, **kwargs)
125 global tracer, granularity
126 if trace_granularity < granularity:
--> 127 return f(*args, **kwargs)
128 if not tracer:
129 return f(*args, **kwargs)
File ~/miniforge3/envs/crhomadb/lib/python3.11/site-packages/chromadb/api/segment.py:799, in SegmentAPI._validate_embedding_record(self, collection, record)
797 add_attributes_to_current_span({"collection_id": str(collection["id"])})
798 if record["embedding"]:
--> 799 self._validate_dimension(collection, len(record["embedding"]), update=True)
File ~/miniforge3/envs/crhomadb/lib/python3.11/site-packages/chromadb/telemetry/opentelemetry/__init__.py:127, in trace_method.<locals>.decorator.<locals>.wrapper(*args, **kwargs)
125 global tracer, granularity
126 if trace_granularity < granularity:
--> 127 return f(*args, **kwargs)
128 if not tracer:
129 return f(*args, **kwargs)
File ~/miniforge3/envs/crhomadb/lib/python3.11/site-packages/chromadb/api/segment.py:814, in SegmentAPI._validate_dimension(self, collection, dim, update)
812 self._collection_cache[id]["dimension"] = dim
813 elif collection["dimension"] != dim:
--> 814 raise InvalidDimensionException(
815 f"Embedding dimension {dim} does not match collection dimensionality {collection['dimension']}"
816 )
817 else:
818 return
InvalidDimensionException: Embedding dimension 383 does not match collection dimensionality 384

Adicionar documentos e embeddingslink image 76

O Chroma também permite adicionar documentos e embeddings ao mesmo tempo. Portanto, se isso for feito, ele não criará os embeddings do documento.

	
collection.add(
documents=["This is a Pytorch docs"],
embeddings=new_embedding,
metadatas=[{"source": "Pytorch source"}],
ids=["id6"]
)
Copy

Se observarmos os embeddings do último elemento da coleção, veremos que eles são os que adicionamos.

	
collection.add(
documents=["This is a Pytorch docs"],
embeddings=new_embedding,
metadatas=[{"source": "Pytorch source"}],
ids=["id6"]
)
collection.peek()['embeddings'][-1]
Copy
	
[1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
...,
1.0,
1.0,
1.0,
1.0,
1.0]

Consultaslink image 77

Consultas por documentoslink image 78

Para fazer uma consulta, usamos o método query. Com o parâmetro n_results, podemos especificar quantos resultados queremos obter.

	
collection.query(
query_texts=["python"],
n_results=1,
)
Copy
	
{'ids': [['id1']],
'distances': [[0.5389559268951416]],
'metadatas': [[{'source': 'Python source'}]],
'embeddings': None,
'documents': [['This is a python docs']],
'uris': None,
'data': None}

Se, em vez de n_results = 1, definirmos um valor maior, ele retornará mais resultados.

collection.query(
          query_texts=["python"],
          n_results=10,
      )
      
Number of requested results 10 is greater than number of elements in index 6, updating n_results = 6
      
Out[100]:
{'ids': [['id1', 'id2', 'id4', 'id3', 'id5', 'id6']],
       'distances': [[0.5389559268951416,
         1.5743632316589355,
         1.578398585319519,
         1.59961998462677,
         384.56890869140625,
         384.56890869140625]],
       'metadatas': [[{'source': 'Python source'},
         {'source': 'JavaScript source'},
         {'source': 'Rust source'},
         {'source': 'Mojo source'},
         {'source': 'Only embeddings'},
         {'source': 'Pytorch source'}]],
       'embeddings': None,
       'documents': [['This is a python docs',
         'This is JavaScript docs',
         'This is Rust docs',
         'This is a Mojo docs',
         None,
         'This is a Pytorch docs']],
       'uris': None,
       'data': None}

Podemos filtrar por um valor de metadados com o argumento where.

collection.query(
          query_texts=["python"],
          n_results=10,
          where={"source": "Python source"}
      )
      
Number of requested results 10 is greater than number of elements in index 6, updating n_results = 6
      
Out[100]:
{'ids': [['id1']],
       'distances': [[0.5389559268951416]],
       'metadatas': [[{'source': 'Python source'}]],
       'embeddings': None,
       'documents': [['This is a python docs']],
       'uris': None,
       'data': None}

Podemos ver que apenas um resultado já foi retornado

Também podemos filtrar pelo conteúdo do documento com o argumento where_document.

collection.query(
          query_texts=["python"],
          n_results=10,
          where_document={"$contains": "python"}
      )
      
Number of requested results 10 is greater than number of elements in index 6, updating n_results = 6
      
Out[100]:
{'ids': [['id1']],
       'distances': [[0.5389559268951416]],
       'metadatas': [[{'source': 'Python source'}]],
       'embeddings': None,
       'documents': [['This is a python docs']],
       'uris': None,
       'data': None}

Mais tarde, falaremos mais sobre as possibilidades que temos aqui

Quando fazemos uma consulta, podemos dizer quais dados queremos que sejam retornados, por exemplo, apenas os embeddings, apenas os metadados ou vários dados, especificando-os em uma lista usando o argumento include.

collection.query(
          query_texts=["python"],
          n_results=10,
          include=["documents", "distances"]
      )
      
Number of requested results 10 is greater than number of elements in index 6, updating n_results = 6
      
Out[100]:
{'ids': [['id1', 'id2', 'id4', 'id3', 'id5', 'id6']],
       'distances': [[0.5389559268951416,
         1.5743632316589355,
         1.578398585319519,
         1.59961998462677,
         384.56890869140625,
         384.56890869140625]],
       'metadatas': None,
       'embeddings': None,
       'documents': [['This is a python docs',
         'This is JavaScript docs',
         'This is Rust docs',
         'This is a Mojo docs',
         None,
         'This is a Pytorch docs']],
       'uris': None,
       'data': None}

Vemos que metadatas agora é None.

Várias consultas ao mesmo tempolink image 79

Podemos consultar a coleção várias vezes ao mesmo tempo, passando uma lista para o parâmetro query_texts.

	
collection.query(
query_texts=["python"],
n_results=10,
)
collection.query(
query_texts=["python"],
n_results=10,
where={"source": "Python source"}
)
collection.query(
query_texts=["python"],
n_results=10,
where_document={"$contains": "python"}
)
collection.query(
query_texts=["python"],
n_results=10,
include=["documents", "distances"]
)
collection.query(
query_texts=["programming language", "high level", "multi propuse"],
n_results=1,
)
Copy
	
Number of requested results 10 is greater than number of elements in index 6, updating n_results = 6
Number of requested results 10 is greater than number of elements in index 6, updating n_results = 6
Number of requested results 10 is greater than number of elements in index 6, updating n_results = 6
Number of requested results 10 is greater than number of elements in index 6, updating n_results = 6
{'ids': [['id1'], ['id1'], ['id3']],
'distances': [[1.152251958847046], [1.654376745223999], [1.6786067485809326]],
'metadatas': [[{'source': 'Python source'}],
[{'source': 'Python source'}],
[{'source': 'Mojo source'}]],
'embeddings': None,
'documents': [['This is a python docs'],
['This is a python docs'],
['This is a Mojo docs']],
'uris': None,
'data': None}

Para cada consulta, ele retornou um resultado

Isso é muito útil quando o banco de dados está hospedado em um servidor e somos cobrados por cada consulta que fazemos. Portanto, em vez de fazer uma consulta para cada pergunta que temos, fazemos uma consulta com todas as perguntas que temos.

Consultas para incorporaçõeslink image 80

Quando consultamos os documentos, o que o chroma faz é calcular a incorporação dos textos de consulta e procurar os documentos que mais se assemelham a essa incorporação. Mas se já tivermos a incorporação, podemos fazer a consulta diretamente com a incorporação.

Primeiro, vamos obter a incorporação de uma consulta com a mesma função de incorporação das coleções.

	
query_texts = ["python language"]
query_embeddings = collection._embedding_function(query_texts)
query_embeddings
Copy
	
[[-0.04816831275820732,
0.014662696048617363,
-0.031021444126963615,
0.008308809250593185,
-0.07176128774881363,
-0.10355626791715622,
0.06690476089715958,
0.04229631647467613,
-0.03681119903922081,
-0.04993892088532448,
0.03186540678143501,
0.015252595767378807,
0.0642094686627388,
0.018130118027329445,
0.016300885006785393,
-0.028082313016057014,
-0.03994889184832573,
0.023195551708340645,
0.004547565709799528,
-0.11764183640480042,
0.019792592152953148,
0.0496944822371006,
-0.013253907673060894,
0.03610404208302498,
0.030529780313372612,
-0.01815914921462536,
-0.009753326885402203,
0.03412770479917526,
0.03020440600812435,
...
0.02079579420387745,
-0.00972712505608797,
0.13462257385253906,
0.15277136862277985,
-0.028574923053383827]]

Agora podemos fazer a consulta com a incorporação

	
collection.query(
query_embeddings=query_embeddings,
n_results=1,
)
Copy
	
{'ids': [['id1']],
'distances': [[0.6297433376312256]],
'metadatas': [[{'source': 'Python source'}]],
'embeddings': None,
'documents': [['This is a python docs']],
'uris': None,
'data': None}

Como antes, podemos obter mais resultados aumentando o valor do parâmetro n_results e podemos filtrar com os parâmetros where e where_document. Também podemos fazer várias consultas ao mesmo tempo e especificar quais dados queremos retornar com o parâmetro include.

Observação: se tentarmos fazer uma consulta com uma incorporação de uma dimensão diferente das que já estão na coleção, receberemos um erro.

Recuperar documentos por ID.link image 81

Se soubermos o ID de um documento, poderemos recuperar o documento com o método get.

	
collection.get(
ids=["id1"],
)
Copy
	
{'ids': ['id1'],
'embeddings': None,
'metadatas': [{'source': 'Python source'}],
'documents': ['This is a python docs'],
'uris': None,
'data': None}

Também é possível recuperar vários documentos de uma só vez.

	
collection.get(
ids=["id1", "id2", "id3"],
)
Copy
	
{'ids': ['id1', 'id2', 'id3'],
'embeddings': None,
'metadatas': [{'source': 'Python source'},
{'source': 'JavaScript source'},
{'source': 'Mojo source'}],
'documents': ['This is a python docs',
'This is JavaScript docs',
'This is a Mojo docs'],
'uris': None,
'data': None}

Como antes, podemos filtrar com os argumentos where e where_document. Também podemos fazer várias consultas ao mesmo tempo e especificar quais dados queremos retornar com o parâmetro include.

Filtragemlink image 82

Como vimos, você pode filtrar por metadados com o parâmetro where e pelo conteúdo do documento com o parâmetro where_document.

Filtragem por metadadoslink image 83

Como os metadados entrarão em mim como um dicionário

collection.add(
          documents=["This is a python docs", "This is JavaScript docs"],
          metadatas=[{"source": "Python source"}, {"source": "JavaScript source"}],
          ids=["id1", "id2"]
      )
      ```
      
      A primeira coisa que temos de fazer é indicar a chave dos metadados pelos quais queremos filtrar. Em seguida, temos de colocar um operador e o valor
      
      ````python
      {
          "metadata_field": {
              <Operador>: <Valor>.
          }
      }
      ```
      

Os valores possíveis do oerador são

$eq - igual a (string, int, float) $ne - não é igual a (string, int, float) $gt - maior que (int, float) $gte - maior ou igual a (int, float) $lt - menor que (int, float) $lte - menor que ou igual a (int, float)

Vamos dar uma olhada em uma consulta

	
collection.query(
query_texts=["python"],
n_results=1,
where=
{
"source":
{
"$eq": "Python source"
}
}
)
Copy
	
{'ids': [['id1']],
'distances': [[0.5389559268951416]],
'metadatas': [[{'source': 'Python source'}]],
'embeddings': None,
'documents': [['This is a python docs']],
'uris': None,
'data': None}

Se não colocarmos o operador, o padrão será $eq, ou seja, isto

{
          "metadata_field": {
              <"$eq">: <Value>.
          }
      }
      ```
      
      É o mesmo que isto
      
      ````python
      {
          "metadata_field": <Value>.
      }
      ```
      

Observação**: O Chroma só pesquisará dados que tenham os metadados source; por exemplo, se você pesquisar where={"version": {"$ne": 1}}, ele só retornará dados que tenham uma chave version em seus metadados e que não sejam 1.

Filtragem por conteúdo do documentolink image 84

Ao filtrar pelo conteúdo do documento, temos duas chaves possíveis: $contains e $not_contains.

Por exemplo, procuramos dados na coleção em que a palavra "python" aparece em seu documento.

collection.query(
          query_texts=["python"],
          n_results=10,
          where_document={"$contains": "python"}
      )
      
Number of requested results 10 is greater than number of elements in index 6, updating n_results = 6
      
Out[100]:
{'ids': [['id1']],
       'distances': [[0.5389559268951416]],
       'metadatas': [[{'source': 'Python source'}]],
       'embeddings': None,
       'documents': [['This is a python docs']],
       'uris': None,
       'data': None}

E todos os dados na coleção em que a palavra python não aparece em seu documento

collection.query(
          query_texts=["python"],
          n_results=10,
          where_document={"$not_contains": "python"}
      )
      
Number of requested results 10 is greater than number of elements in index 6, updating n_results = 6
      
Out[100]:
{'ids': [['id2', 'id4', 'id3', 'id6']],
       'distances': [[1.5743632316589355,
         1.578398585319519,
         1.59961998462677,
         384.56890869140625]],
       'metadatas': [[{'source': 'JavaScript source'},
         {'source': 'Rust source'},
         {'source': 'Mojo source'},
         {'source': 'Pytorch source'}]],
       'embeddings': None,
       'documents': [['This is JavaScript docs',
         'This is Rust docs',
         'This is a Mojo docs',
         'This is a Pytorch docs']],
       'uris': None,
       'data': None}

Também podemos usar os operadores lógicos $and e $or para fazer consultas mais complexas.

{
          "$e": [
              {
                  <Operador>: <Valor>.
              },
              {
                  <Operador>: <Valor>.
              }
      
      }
      ```
      
      ````python
      {
          "$or": [
              {
                  <Operador>: <Valor>.
              },
              {
                  <Operador>: <Valor>.
              }
      
      }
      ```
      

Por exemplo, pesquisamos todos os documentos que contêm as palavras python e docs.

collection.query(
          query_texts=["python"],
          n_results=10,
          where_document=
          {
              "$and": [
                  {"$contains": "python"},
                  {"$contains": "docs"},
              ],
          },
      )
      
Number of requested results 10 is greater than number of elements in index 6, updating n_results = 6
      
Out[100]:
{'ids': [['id1']],
       'distances': [[0.5389559268951416]],
       'metadatas': [[{'source': 'Python source'}]],
       'embeddings': None,
       'documents': [['This is a python docs']],
       'uris': None,
       'data': None}

Atualizar dadoslink image 85

Qualquer item de dados pode ser atualizado com o método update.

	
collection.query(
query_texts=["python"],
n_results=10,
where_document={"$contains": "python"}
)
collection.query(
query_texts=["python"],
n_results=10,
where_document={"$not_contains": "python"}
)
collection.query(
query_texts=["python"],
n_results=10,
where_document=
{
"$and": [
{"$contains": "python"},
{"$contains": "docs"},
],
},
)
collection.update(
ids=["id1"],
documents=["This is a updated Python docs"]
)
Copy

Vamos ver se ela foi atualizada

collection.query(
          query_texts=["python"],
          n_results=10,
          where_document={"$contains": "Python"}
      )
      
Number of requested results 10 is greater than number of elements in index 6, updating n_results = 6
      
Out[100]:
{'ids': [['id1']],
       'distances': [[0.8247963190078735]],
       'metadatas': [[{'source': 'Python source'}]],
       'embeddings': None,
       'documents': [['This is a updated Python docs']],
       'uris': None,
       'data': None}

Observação: se você tentar atualizar um ID que não existe, ocorrerá um erro.

Observação: se você tentar atualizar uma incorporação com outra incorporação de tamanho diferente, ocorrerá um erro.

Atualizar ou adicionar dadoslink image 86

Com o método upsert, podemos atualizar um dado se ele já existir ou adicioná-lo se ele não existir.

	
collection.query(
query_texts=["python"],
n_results=10,
where_document={"$contains": "python"}
)
collection.query(
query_texts=["python"],
n_results=10,
where_document={"$not_contains": "python"}
)
collection.query(
query_texts=["python"],
n_results=10,
where_document=
{
"$and": [
{"$contains": "python"},
{"$contains": "docs"},
],
},
)
collection.update(
ids=["id1"],
documents=["This is a updated Python docs"]
)
collection.query(
query_texts=["python"],
n_results=10,
where_document={"$contains": "Python"}
)
collection.upsert(
ids=["id6"],
documents=["This is a Pytorch docs"],
metadatas=[{"source": "Pytorch source"}],
)
Copy

Vamos ver se ele foi adicionado à coleção

	
collection.query(
query_texts=["python"],
n_results=10,
where_document={"$contains": "python"}
)
collection.query(
query_texts=["python"],
n_results=10,
where_document={"$not_contains": "python"}
)
collection.query(
query_texts=["python"],
n_results=10,
where_document=
{
"$and": [
{"$contains": "python"},
{"$contains": "docs"},
],
},
)
collection.update(
ids=["id1"],
documents=["This is a updated Python docs"]
)
collection.query(
query_texts=["python"],
n_results=10,
where_document={"$contains": "Python"}
)
collection.upsert(
ids=["id6"],
documents=["This is a Pytorch docs"],
metadatas=[{"source": "Pytorch source"}],
)
collection.peek()
Copy
	
Number of requested results 10 is greater than number of elements in index 6, updating n_results = 6
Number of requested results 10 is greater than number of elements in index 6, updating n_results = 6
Number of requested results 10 is greater than number of elements in index 6, updating n_results = 6
Number of requested results 10 is greater than number of elements in index 6, updating n_results = 6
{'ids': ['id1', 'id2', 'id3', 'id4', 'id5', 'id6'],
'embeddings': [[-0.08374718576669693,
0.01027572900056839,
-0.04819200187921524,
0.01758415624499321,
0.013158757239580154,
-0.11435151100158691,
-0.024248722940683365,
-0.01319972239434719,
-0.09626100957393646,
-0.010561048053205013,
0.09369225800037384,
0.06017905846238136,
0.031283188611269,
0.014855983667075634,
-0.0015984248602762818,
0.023238031193614006,
-0.04709107056260109,
-0.007838696241378784,
0.012870412319898605,
-0.028354981914162636,
-0.007653804495930672,
0.09018168598413467,
0.060235824435949326,
0.0005205210763961077,
...
0.014388148672878742]],
'metadatas': [{'source': 'Python source'},
{'source': 'JavaScript source'},
{'source': 'Mojo source'},
{'source': 'Rust source'},
{'source': 'Only embeddings'},
{'source': 'Pytorch source'}],
'documents': ['This is a updated Python docs',
'This is JavaScript docs',
'This is a Mojo docs',
'This is Rust docs',
None,
'This is a Pytorch docs'],
'uris': None,
'data': None}

Vemos que sim

Excluir dadoslink image 87

Podemos excluir dados de uma coleção com o método delete.

Removeremos os dados com ID id5, que é o que adicionamos com sua incorporação de todos os dados

	
collection.delete(
ids=["id5"]
)
Copy

Vamos ver se ele foi removido

	
collection.delete(
ids=["id5"]
)
collection.peek()
Copy
	
{'ids': ['id1', 'id2', 'id3', 'id4', 'id6'],
'embeddings': [[-0.08374718576669693,
0.01027572900056839,
-0.04819200187921524,
0.01758415624499321,
0.013158757239580154,
-0.11435151100158691,
-0.024248722940683365,
-0.01319972239434719,
-0.09626100957393646,
-0.010561048053205013,
0.09369225800037384,
0.06017905846238136,
0.031283188611269,
0.014855983667075634,
-0.0015984248602762818,
0.023238031193614006,
-0.04709107056260109,
-0.007838696241378784,
0.012870412319898605,
-0.028354981914162636,
-0.007653804495930672,
0.09018168598413467,
0.060235824435949326,
0.0005205210763961077,
...
0.07033486664295197,
0.014388148672878742]],
'metadatas': [{'source': 'Python source'},
{'source': 'JavaScript source'},
{'source': 'Mojo source'},
{'source': 'Rust source'},
{'source': 'Pytorch source'}],
'documents': ['This is a updated Python docs',
'This is JavaScript docs',
'This is a Mojo docs',
'This is Rust docs',
'This is a Pytorch docs'],
'uris': None,
'data': None}

Vemos que não é mais

Embeddingslink image 88

Conforme mencionado acima, podemos usar diferentes funções de embeddings e, se nenhuma for especificada, ele usará all-MiniLM-L6-v2. Na página chroma embeddings documentation, podemos ver as diferentes funções de embeddings que podemos usar. Como isso pode mudar e algumas delas são pagas e exigem uma chave de API, explicaremos apenas como usar as do HuggingFace.

Primeiro, definimos a função de incorporação

	
import chromadb.utils.embedding_functions as embedding_functions
huggingface_ef = embedding_functions.HuggingFaceEmbeddingFunction(
api_key="YOUR_API_KEY",
model_name="sentence-transformers/all-mpnet-base-v2"
)
Copy

No meu caso, utilizo o sentence-transformers/all-mpnet-base-v2, que é o mais baixado dos sentence-transformers no momento em que escrevo esta postagem.

Para adicionar agora a função de incorporação à coleção, precisamos adicionar o argumento metadata={"embedding": <function>}.

	
import chromadb.utils.embedding_functions as embedding_functions
huggingface_ef = embedding_functions.HuggingFaceEmbeddingFunction(
api_key="YOUR_API_KEY",
model_name="sentence-transformers/all-mpnet-base-v2"
)
collection = chroma_client.create_collection(
name="colection_huggingface",
embedding_function=huggingface_ef
)
Copy

Podemos verificar se adicionamos a nova função de incorporação calculando as incorporações de uma palavra.

	
import chromadb.utils.embedding_functions as embedding_functions
huggingface_ef = embedding_functions.HuggingFaceEmbeddingFunction(
api_key="YOUR_API_KEY",
model_name="sentence-transformers/all-mpnet-base-v2"
)
collection = chroma_client.create_collection(
name="colection_huggingface",
embedding_function=huggingface_ef
)
embedding = collection._embedding_function(["python"])
len(embedding), len(embedding[0])
Copy
	
(1, 768)

O comprimento da incorporação é de 768

Se agora calcularmos a incorporação com a função de incorporação da coleção anterior

	
collection = chroma_client.get_collection(name = "my_collection")
Copy
	
collection = chroma_client.get_collection(name = "my_collection")
embedding = collection._embedding_function(["python"])
len(embedding), len(embedding[0])
Copy
	
(1, 384)

Vemos que agora o comprimento da incorporação é 384, ou seja, usamos uma nova função de incorporação antes.

Multimodalidadelink image 89

Podemos adicionar embeddings de imagem, pois o chroma tem o OpenCLIP incorporado. O OpenCLIP é uma implementação de código aberto do CLIP (Contrastive Language-Image Pre-Training), que é uma rede neural OpenAI capaz de fornecer uma descrição de uma imagem.

Para usar o OpenCLIP, temos que instalá-lo com o pip

pip install open-clip-torch
      ```
      

Depois de instalado, podemos usá-lo para criar embeddings da seguinte imagem

chroma db - python mixture

Eu o tenho em meu caminho local ../images/chromadb_dalle3.webp.

	
from chromadb.utils.embedding_functions import OpenCLIPEmbeddingFunction
embedding_function = OpenCLIPEmbeddingFunction()
image = "../images/chromadb_dalle3.webp"
embedding = embedding_function(image)
len(embedding), len(embedding[0])
Copy
	
(30, 512)

Como podemos ver, ele cria uma incorporação de tamanho 30x512.

O Chroma também vem com um carregador de imagens.

	
from chromadb.utils.data_loaders import ImageLoader
data_loader = ImageLoader()
data = data_loader._load_image(image)
type(data), data.shape
Copy
	
(numpy.ndarray, (1024, 1024, 3))

Portanto, podemos criar uma coleção multimodal com essa função de incorporação e o carregador de imagens.

	
collection = chroma_client.create_collection(
name="multimodal_collection",
embedding_function=embedding_function,
data_loader=data_loader
)
Copy

E podemos adicionar os embeddings das imagens a ele.

	
collection = chroma_client.create_collection(
name="multimodal_collection",
embedding_function=embedding_function,
data_loader=data_loader
)
collection.add(
ids=['id1'],
images=[image]
)
Copy

Vamos ver o que ele salvou

	
collection = chroma_client.create_collection(
name="multimodal_collection",
embedding_function=embedding_function,
data_loader=data_loader
)
collection.add(
ids=['id1'],
images=[image]
)
collection.peek()
Copy
	
{'ids': ['id1'],
'embeddings': [[-0.014372998848557472,
0.0063015008345246315,
-0.03794914484024048,
-0.028725482523441315,
-0.014304812066257,
-0.04323698952794075,
0.008670451119542122,
-0.016066772863268852,
-0.02365742437541485,
0.07881983369588852,
0.022775636985898018,
0.004407387692481279,
0.058205753564834595,
-0.02389293536543846,
-0.027586588636040688,
0.05778728798031807,
-0.2631031572818756,
0.044124454259872437,
0.010588622651994228,
-0.035578884184360504,
-0.041719693690538406,
-0.0033654430881142616,
-0.04731074720621109,
-0.0019943572115153074,
...
0.04397008568048477,
0.04396628588438034]],
'metadatas': [None],
'documents': [None],
'uris': None,
'data': None}

O Chroma não armazena as imagens, apenas os embeddings, portanto, para não perder a relação entre os embeddings e as imagens, podemos salvar o caminho para as imagens nos metadados. Vamos usar o método update para adicionar o caminho à imagem

	
collection.update(
ids=['id1'],
images=[image],
metadatas=[{"source": image}]
)
Copy

Se voltarmos e olharmos para o que a coleção tem reservado

	
collection.update(
ids=['id1'],
images=[image],
metadatas=[{"source": image}]
)
collection.peek()
Copy
	
{'ids': ['id1'],
'embeddings': [[-0.014372998848557472,
0.0063015008345246315,
-0.03794914484024048,
-0.028725482523441315,
-0.014304812066257,
-0.04323698952794075,
0.008670451119542122,
-0.016066772863268852,
-0.02365742437541485,
0.07881983369588852,
0.022775636985898018,
0.004407387692481279,
0.058205753564834595,
-0.02389293536543846,
-0.027586588636040688,
0.05778728798031807,
-0.2631031572818756,
0.044124454259872437,
0.010588622651994228,
-0.035578884184360504,
-0.041719693690538406,
-0.0033654430881142616,
-0.04731074720621109,
-0.0019943572115153074,
...
0.04397008568048477,
0.04396628588438034]],
'metadatas': [{'source': '../images/chromadb_dalle3.webp'}],
'documents': [None],
'uris': None,
'data': None}

Como a coleção é multimodal, podemos adicionar documentos a ela como antes.

	
collection.add(
ids=['id2', 'id3'],
documents=["This is a python docs", "This is JavaScript docs"],
metadatas=[{"source": "Python source"}, {"source": "JavaScript source"}]
)
collection.peek()
Copy
	
{'ids': ['id1', 'id2', 'id3'],
'embeddings': [[-0.014372998848557472,
0.0063015008345246315,
-0.03794914484024048,
-0.028725482523441315,
-0.014304812066257,
-0.04323698952794075,
0.008670451119542122,
-0.016066772863268852,
-0.02365742437541485,
0.07881983369588852,
0.022775636985898018,
0.004407387692481279,
0.058205753564834595,
-0.02389293536543846,
-0.027586588636040688,
0.05778728798031807,
-0.2631031572818756,
0.044124454259872437,
0.010588622651994228,
-0.035578884184360504,
-0.041719693690538406,
-0.0033654430881142616,
-0.04731074720621109,
-0.0019943572115153074,
...
-0.061795610934495926,
-0.02433035336434841]],
'metadatas': [{'source': '../images/chromadb_dalle3.webp'},
{'source': 'Python source'},
{'source': 'JavaScript source'}],
'documents': [None, 'This is a python docs', 'This is JavaScript docs'],
'uris': None,
'data': None}

Por fim, podemos fazer consultas com texto

collection.query(
          query_texts=["persona trabajando en una mesa"],
      )
      
WARNING:chromadb.segment.impl.vector.local_hnsw:Number of requested results 10 is greater than number of elements in index 3, updating n_results = 3
      
Out[59]:
{'ids': [['id2', 'id1', 'id3']],
       'distances': [[1.1276676654815674, 1.1777206659317017, 1.2047353982925415]],
       'metadatas': [[{'source': 'Python source'},
         {'source': '../images/chromadb_dalle3.webp'},
         {'source': 'JavaScript source'}]],
       'embeddings': None,
       'documents': [['This is a python docs', None, 'This is JavaScript docs']],
       'uris': None,
       'data': None}

Com o texto, não obtivemos a imagem como o primeiro resultado, se eu seguir a documentação do python

Mas também podemos criá-las com imagens. Neste caso, vou fazer isso com esta imagem

chroma logo

query_image = "https://pub-fb664c455eca46a2ba762a065ac900f7.r2.dev/chromadb_elegant.webp"
      collection.query(
          query_images=[query_image],
      )
      
WARNING:chromadb.segment.impl.vector.local_hnsw:Number of requested results 10 is greater than number of elements in index 3, updating n_results = 3
      
Out[60]:
{'ids': [['id1', 'id2', 'id3']],
       'distances': [[0.6684874296188354, 0.9450105428695679, 1.0639115571975708]],
       'metadatas': [[{'source': '../images/chromadb_dalle3.webp'},
         {'source': 'Python source'},
         {'source': 'JavaScript source'}]],
       'embeddings': None,
       'documents': [[None, 'This is a python docs', 'This is JavaScript docs']],
       'uris': None,
       'data': None}

Agora, ele apresenta como primeiro resultado a imagem que salvamos

Continuar lendo

DoLa – Decoding by Contrasting Layers Improves Factuality in Large Language Models

DoLa – Decoding by Contrasting Layers Improves Factuality in Large Language Models

Você já conversou com um LLM e ele lhe respondeu algo que parece ter bebido café de máquina a noite toda? 😂 Isso é o que chamamos de alucinação no mundo dos LLMs! Mas não se preocupe, pois não é que seu modelo de linguagem esteja louco (embora às vezes possa parecer isso 🤪). A verdade é que os LLMs podem ser um pouco... criativos quando se trata de gerar texto. Mas graças ao DoLa, um método que usa camadas de contraste para melhorar a viabilidade dos LLMs, podemos evitar que nossos modelos de linguagem se transformem em escritores de ficção científica 😂. Nesta publicação, explicarei como o DoLa funciona e mostrarei um exemplo de código para que você possa entender melhor como tornar seus LLMs mais confiáveis e menos propensos a inventar histórias. Vamos salvar nossos LLMs da loucura e torná-los mais úteis! 🚀

Últimos posts -->

Você viu esses projetos?

Subtify

Subtify Subtify

Gerador de legendas para vídeos no idioma que você desejar. Além disso, coloca uma legenda de cor diferente para cada pessoa

Ver todos os projetos -->

Quer aplicar IA no seu projeto? Entre em contato!

Quer melhorar com essas dicas?

Últimos tips -->

Use isso localmente

Os espaços do Hugging Face nos permitem executar modelos com demos muito simples, mas e se a demo quebrar? Ou se o usuário a deletar? Por isso, criei contêineres docker com alguns espaços interessantes, para poder usá-los localmente, aconteça o que acontecer. Na verdade, se você clicar em qualquer botão de visualização de projeto, ele pode levá-lo a um espaço que não funciona.

Ver todos os contêineres -->

Quer aplicar IA no seu projeto? Entre em contato!

Você quer treinar seu modelo com esses datasets?

short-jokes-dataset

Dataset com piadas em inglês

opus100

Dataset com traduções de inglês para espanhol

netflix_titles

Dataset com filmes e séries da Netflix

Ver mais datasets -->