Qdrant Vector Search Tool
Visão Geral
Seção intitulada “Visão Geral”A ferramenta Qdrant Vector Search permite adicionar capacidades de busca semântica aos seus agentes CrewAI utilizando o Qdrant, um mecanismo de busca por similaridade vetorial. Com essa ferramenta, seus agentes podem pesquisar em documentos armazenados em uma coleção Qdrant usando similaridade semântica.
Instalação
Seção intitulada “Instalação”Instale os pacotes necessários:
uv add qdrant-clientUso Básico
Seção intitulada “Uso Básico”Veja um exemplo mínimo de como utilizar a ferramenta:
from crewai import Agentfrom crewai_tools import QdrantVectorSearchTool, QdrantConfig
# Inicialize a ferramenta com QdrantConfigqdrant_tool = QdrantVectorSearchTool( qdrant_config=QdrantConfig( qdrant_url="your_qdrant_url", qdrant_api_key="your_qdrant_api_key", collection_name="your_collection" ))
# Crie um agente que utiliza a ferramentaagent = Agent( role="Research Assistant", goal="Find relevant information in documents", tools=[qdrant_tool])
# A ferramenta usará automaticamente embeddings da OpenAI# e retornará os 3 resultados mais relevantes com pontuação > 0.35Exemplo Completo e Funcional
Seção intitulada “Exemplo Completo e Funcional”Veja um exemplo completo mostrando como:
- Extrair texto de um PDF
- Gerar embeddings usando OpenAI
- Armazenar no Qdrant
- Criar um fluxo de trabalho RAG agente CrewAI para busca semântica
import osimport uuidimport pdfplumberfrom openai import OpenAIfrom dotenv import load_dotenvfrom crewai import Agent, Task, Crew, Process, LLMfrom crewai_tools import QdrantVectorSearchToolfrom qdrant_client import QdrantClientfrom qdrant_client.models import PointStruct, Distance, VectorParams
# Carregar variáveis de ambienteload_dotenv()
# Inicializar cliente OpenAIclient = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
# Extrair texto do PDFdef extract_text_from_pdf(pdf_path): text = [] with pdfplumber.open(pdf_path) as pdf: for page in pdf.pages: page_text = page.extract_text() if page_text: text.append(page_text.strip()) return text
# Gerar embeddings da OpenAIdef get_openai_embedding(text): response = client.embeddings.create( input=text, model="text-embedding-3-large" ) return response.data[0].embedding
# Armazenar texto e embeddings no Qdrantdef load_pdf_to_qdrant(pdf_path, qdrant, collection_name): # Extrair texto do PDF text_chunks = extract_text_from_pdf(pdf_path)
# Criar coleção no Qdrant if qdrant.collection_exists(collection_name): qdrant.delete_collection(collection_name) qdrant.create_collection( collection_name=collection_name, vectors_config=VectorParams(size=3072, distance=Distance.COSINE) )
# Armazenar embeddings points = [] for chunk in text_chunks: embedding = get_openai_embedding(chunk) points.append(PointStruct( id=str(uuid.uuid4()), vector=embedding, payload={"text": chunk} )) qdrant.upsert(collection_name=collection_name, points=points)
# Inicializar cliente Qdrant e carregar dadosqdrant = QdrantClient( url=os.getenv("QDRANT_URL"), api_key=os.getenv("QDRANT_API_KEY"))collection_name = "example_collection"pdf_path = "path/to/your/document.pdf"load_pdf_to_qdrant(pdf_path, qdrant, collection_name)
# Inicializar ferramenta de busca Qdrantfrom crewai_tools import QdrantConfig
qdrant_tool = QdrantVectorSearchTool( qdrant_config=QdrantConfig( qdrant_url=os.getenv("QDRANT_URL"), qdrant_api_key=os.getenv("QDRANT_API_KEY"), collection_name=collection_name, limit=3, score_threshold=0.35 ))
# Criar agentes CrewAIsearch_agent = Agent( role="Senior Semantic Search Agent", goal="Find and analyze documents based on semantic search", backstory="""You are an expert research assistant who can find relevant information using semantic search in a Qdrant database.""", tools=[qdrant_tool], verbose=True)
answer_agent = Agent( role="Senior Answer Assistant", goal="Generate answers to questions based on the context provided", backstory="""You are an expert answer assistant who can generate answers to questions based on the context provided.""", tools=[qdrant_tool], verbose=True)
# Definir tarefassearch_task = Task( description="""Search for relevant documents about the {query}. Your final answer should include: - The relevant information found - The similarity scores of the results - The metadata of the relevant documents""", agent=search_agent)
answer_task = Task( description="""Given the context and metadata of relevant documents, generate a final answer based on the context.""", agent=answer_agent)
# Executar fluxo CrewAIcrew = Crew( agents=[search_agent, answer_agent], tasks=[search_task, answer_task], process=Process.sequential, verbose=True)
result = crew.kickoff( inputs={"query": "What is the role of X in the document?"})print(result)Parâmetros da Ferramenta
Seção intitulada “Parâmetros da Ferramenta”Parâmetros Obrigatórios
Seção intitulada “Parâmetros Obrigatórios”qdrant_config(QdrantConfig): Objeto de configuração contendo todas as configurações do Qdrant
Parâmetros do QdrantConfig
Seção intitulada “Parâmetros do QdrantConfig”qdrant_url(str): URL do seu servidor Qdrantqdrant_api_key(str, opcional): Chave de API para autenticação com o Qdrantcollection_name(str): Nome da coleção Qdrant a ser pesquisadalimit(int): Número máximo de resultados a serem retornados (padrão: 3)score_threshold(float): Limite mínimo de similaridade (padrão: 0.35)filter(Any, opcional): Instância de Filter do Qdrant para filtragem avançada (padrão: None)
Parâmetros Opcionais da Ferramenta
Seção intitulada “Parâmetros Opcionais da Ferramenta”custom_embedding_fn(Callable[[str], list[float]]): Função personalizada para vetorização de textosqdrant_package(str): Caminho base do pacote Qdrant (padrão: “qdrant_client”)client(Any): Cliente Qdrant pré-inicializado (opcional)
Filtragem Avançada
Seção intitulada “Filtragem Avançada”A ferramenta QdrantVectorSearchTool oferece recursos poderosos de filtragem para refinar os resultados da busca:
Filtragem Dinâmica
Seção intitulada “Filtragem Dinâmica”Use os parâmetros filter_by e filter_value na sua busca para filtrar resultados dinamicamente:
# O agente usará esses parâmetros ao chamar a ferramenta# O schema da ferramenta aceita filter_by e filter_value# Exemplo: busca com filtro de categoria# Os resultados serão filtrados onde categoria == "tecnologia"Filtros Pré-definidos com QdrantConfig
Seção intitulada “Filtros Pré-definidos com QdrantConfig”Para filtragens complexas, use instâncias de Filter do Qdrant na sua configuração:
from qdrant_client.http import models as qmodelsfrom crewai_tools import QdrantVectorSearchTool, QdrantConfig
# Criar um filtro para condições específicaspreset_filter = qmodels.Filter( must=[ qmodels.FieldCondition( key="categoria", match=qmodels.MatchValue(value="pesquisa") ), qmodels.FieldCondition( key="ano", match=qmodels.MatchValue(value=2024) ) ])
# Inicializar ferramenta com filtro pré-definidoqdrant_tool = QdrantVectorSearchTool( qdrant_config=QdrantConfig( qdrant_url="your_url", qdrant_api_key="your_key", collection_name="your_collection", filter=preset_filter # Filtro pré-definido aplicado a todas as buscas ))Combinando Filtros
Seção intitulada “Combinando Filtros”A ferramenta combina automaticamente os filtros pré-definidos do QdrantConfig com os filtros dinâmicos de filter_by e filter_value:
# Se QdrantConfig tem um filtro pré-definido para categoria="pesquisa"# E a busca usa filter_by="ano", filter_value=2024# Ambos os filtros serão combinados (lógica AND)Parâmetros de Busca
Seção intitulada “Parâmetros de Busca”A ferramenta aceita estes parâmetros em seu schema:
query(str): Consulta de busca para encontrar documentos similaresfilter_by(str, opcional): Campo de metadado para filtrarfilter_value(Any, opcional): Valor para filtrar
Formato de Retorno
Seção intitulada “Formato de Retorno”A ferramenta retorna resultados no formato JSON:
[ { "metadata": { // Todos os metadados armazenados junto com o documento }, "context": "O conteúdo textual real do documento", "distance": 0.95 // Pontuação de similaridade }]Embedding Padrão
Seção intitulada “Embedding Padrão”Por padrão, a ferramenta utiliza o modelo text-embedding-3-large da OpenAI para vetorização. Isso requer:
- Chave de API da OpenAI definida na variável de ambiente:
OPENAI_API_KEY
Embeddings Personalizados
Seção intitulada “Embeddings Personalizados”Em vez de utilizar o modelo padrão de embeddings, você pode utilizar sua própria função de embeddings nos casos em que:
- Deseja usar um modelo de embeddings diferente (ex: Cohere, HuggingFace, modelos Ollama)
- Precisa reduzir custos utilizando modelos de código aberto
- Tem requisitos específicos quanto à dimensão dos vetores ou à qualidade dos embeddings
- Deseja utilizar embeddings específicos para determinado domínio (ex: textos médicos ou jurídicos)
Veja um exemplo utilizando um modelo HuggingFace:
from transformers import AutoTokenizer, AutoModelimport torch
# Carregar modelo e tokenizertokenizer = AutoTokenizer.from_pretrained('sentence-transformers/all-MiniLM-L6-v2')model = AutoModel.from_pretrained('sentence-transformers/all-MiniLM-L6-v2')
def custom_embeddings(text: str) -> list[float]: # Tokenizar e obter saídas do modelo inputs = tokenizer(text, return_tensors="pt", padding=True, truncation=True) outputs = model(**inputs)
# Usar mean pooling para obter o embedding do texto embeddings = outputs.last_hidden_state.mean(dim=1)
# Converter para lista de floats e retornar return embeddings[0].tolist()
# Usar embeddings personalizados com a ferramentafrom crewai_tools import QdrantConfig
tool = QdrantVectorSearchTool( qdrant_config=QdrantConfig( qdrant_url="your_url", qdrant_api_key="your_key", collection_name="your_collection" ), custom_embedding_fn=custom_embeddings # Passe sua função personalizada)Tratamento de Erros
Seção intitulada “Tratamento de Erros”A ferramenta trata os seguintes erros específicos:
- Lança ImportError se
qdrant-clientnão estiver instalado (com opção de instalar automaticamente) - Lança ValueError se
QDRANT_URLnão estiver definido - Solicita instalação de
qdrant-clientse estiver ausente utilizandouv add qdrant-client
Variáveis de Ambiente
Seção intitulada “Variáveis de Ambiente”Variáveis de ambiente obrigatórias:
export QDRANT_URL="your_qdrant_url" # Se não for informado no construtorexport QDRANT_API_KEY="your_api_key" # Se não for informado no construtorexport OPENAI_API_KEY="your_openai_key" # Se estiver usando embeddings padrão