<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: David Myriel</title>
    <description>The latest articles on DEV Community by David Myriel (@davidmyriel).</description>
    <link>https://dev.to/davidmyriel</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1279937%2F7ed63d14-11bc-4b8b-abdb-eda2eead7c94.png</url>
      <title>DEV Community: David Myriel</title>
      <link>https://dev.to/davidmyriel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davidmyriel"/>
    <language>en</language>
    <item>
      <title>Blog-Reading Chatbot with GPT-4o</title>
      <dc:creator>David Myriel</dc:creator>
      <pubDate>Tue, 14 May 2024 16:31:49 +0000</pubDate>
      <link>https://dev.to/qdrant/blog-reading-chatbot-with-gpt-4o-2kha</link>
      <guid>https://dev.to/qdrant/blog-reading-chatbot-with-gpt-4o-2kha</guid>
      <description>&lt;p&gt;In this tutorial, you will build a RAG system that combines blog content ingestion with the capabilities of semantic search. &lt;strong&gt;OpenAI’s GPT-4o LLM&lt;/strong&gt; is powerful, but scaling its use requires us to supply context systematically.&lt;/p&gt;

&lt;p&gt;RAG enhances the LLM’s generation of answers by retrieving relevant documents to aid the question-answering process. This setup showcases the integration of advanced search and AI language processing to improve information retrieval and generation tasks.&lt;/p&gt;

&lt;p&gt;A notebook for this tutorial is available on &lt;a href="https://github.com/qdrant/examples/blob/master/langchain-lcel-rag/Langchain-LCEL-RAG-Demo.ipynb" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data Privacy and Sovereignty:&lt;/strong&gt; RAG applications often rely on sensitive or proprietary internal data. Running the entire stack within your own environment becomes crucial for maintaining control over this data. Qdrant Hybrid Cloud deployed on &lt;a href="https://www.scaleway.com/en/" rel="noopener noreferrer"&gt;Scaleway&lt;/a&gt; addresses this need perfectly, offering a secure, scalable platform that still leverages the full potential of RAG. Scaleway offers serverless &lt;a href="https://www.scaleway.com/en/serverless-functions/" rel="noopener noreferrer"&gt;Functions&lt;/a&gt; and serverless &lt;a href="https://www.scaleway.com/en/serverless-jobs/" rel="noopener noreferrer"&gt;Jobs&lt;/a&gt;, both of which are ideal for embedding creation in large-scale RAG cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Components
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cloud Host:&lt;/strong&gt; Scaleway on managed Kubernetes for compatibility with Qdrant Hybrid Cloud.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vector Database:&lt;/strong&gt; Qdrant Hybrid Cloud as the vector search engine for retrieval.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LLM:&lt;/strong&gt; GPT-4o, developed by OpenAI is utilized as the generator for producing answers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Framework:&lt;/strong&gt; &lt;a href="https://www.langchain.com/" rel="noopener noreferrer"&gt;LangChain&lt;/a&gt; for extensive RAG capabilities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm7hhu9s71ye9gabatk6f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm7hhu9s71ye9gabatk6f.png" alt="Architecture diagram" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&amp;gt; Langchain &lt;a href="https://python.langchain.com/v0.1/docs/integrations/chat/" rel="noopener noreferrer"&gt;supports a wide range of LLMs&lt;/a&gt;, and GPT-4o is used as the main generator in this tutorial. You can easily swap it out for your preferred model that might be launched on your premises to complete the fully private setup. For the sake of simplicity, we used the OpenAI APIs, but LangChain makes the transition seamless.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying Qdrant Hybrid Cloud on Scaleway
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.scaleway.com/en/kubernetes-kapsule/" rel="noopener noreferrer"&gt;Scaleway Kapsule&lt;/a&gt; and &lt;a href="https://www.scaleway.com/en/kubernetes-kosmos/" rel="noopener noreferrer"&gt;Kosmos&lt;/a&gt; are managed Kubernetes services from Scaleway. They abstract away the complexities of managing and operating a Kubernetes cluster. &lt;/p&gt;

&lt;p&gt;The primary difference being, Kapsule clusters are composed solely of Scaleway Instances. Whereas, a Kosmos cluster is a managed multi-cloud Kubernetes engine that allows you to connect instances from any cloud provider to a single managed Control-Plane.&lt;/p&gt;

&lt;p&gt;To start using managed Kubernetes on Scaleway, follow the &lt;a href="https://qdrant.tech/documentation/hybrid-cloud/platform-deployment-options/#scaleway" rel="noopener noreferrer"&gt;platform-specific documentation.&lt;/a&gt;&lt;br&gt;
Once your Kubernetes clusters are up, &lt;a href="https://qdrant.tech/documentation/hybrid-cloud/" rel="noopener noreferrer"&gt;you can begin deploying Qdrant Hybrid Cloud.&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;To prepare the environment for working with Qdrant and related libraries, it’s necessary to install all required Python packages. This can be done using Poetry, a tool for dependency management and packaging in Python. The code snippet imports various libraries essential for the tasks ahead, including bs4 for parsing HTML and XML documents, langchain and its community extensions for working with language models and document loaders, and Qdrant for vector storage and retrieval. These imports lay the groundwork for utilizing Qdrant alongside other tools for natural language processing and machine learning tasks.&lt;/p&gt;

&lt;p&gt;Qdrant will be running on a specific URL and access will be restricted by the API key. Make sure to store them both as environment variables as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export QDRANT_URL="https://qdrant.example.com"
export QDRANT_API_KEY="your-api-key"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Optional: Whenever you use LangChain, you can also &lt;a href="https://docs.smith.langchain.com/" rel="noopener noreferrer"&gt;configure LangSmith&lt;/a&gt;, which will help us trace, monitor and debug LangChain applications. You can sign up for LangSmith &lt;a href="https://smith.langchain.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export LANGCHAIN_TRACING_V2=true
export LANGCHAIN_API_KEY="your-api-key"
export LANGCHAIN_PROJECT="your-project"  # if not specified, defaults to "default"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Now you can get started:

import getpass
import os

import bs4
from langchain import hub
from langchain_community.document_loaders import WebBaseLoader
from langchain_qdrant import Qdrant
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set up the OpenAI API key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;os.environ["OPENAI_API_KEY"] = getpass.getpass()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Initialize the language model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
llm = ChatOpenAI(model="gpt-4o")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is here that we configure both the Embeddings and LLM. You can replace this with your own models using Ollama or other services. Scaleway has some great L4 GPU Instances you can use for compute here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Download and parse data
&lt;/h2&gt;

&lt;p&gt;To begin working with blog post contents, the process involves loading and parsing the HTML content. This is achieved using &lt;code&gt;urllib&lt;/code&gt; and &lt;code&gt;BeautifulSoup&lt;/code&gt;, which are tools designed for such tasks. After the content is loaded and parsed, it is indexed using Qdrant, a powerful tool for managing and querying vector data. The code snippet demonstrates how to load, chunk, and index the contents of a blog post by specifying the URL of the blog and the specific HTML elements to parse. This step is crucial for preparing the data for further processing and analysis with Qdrant.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Load, chunk and index the contents of the blog.
loader = WebBaseLoader(
    web_paths=("https://lilianweng.github.io/posts/2023-06-23-agent/",),
    bs_kwargs=dict(
        parse_only=bs4.SoupStrainer(
            class_=("post-content", "post-title", "post-header")
        )
    ),
)
docs = loader.load()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Chunking data
&lt;/h3&gt;

&lt;p&gt;When dealing with large documents, such as a blog post exceeding 42,000 characters, it’s crucial to manage the data efficiently for processing. Many models have a limited context window and struggle with long inputs, making it difficult to extract or find relevant information. To overcome this, the document is divided into smaller chunks. This approach enhances the model’s ability to process and retrieve the most pertinent sections of the document effectively.&lt;/p&gt;

&lt;p&gt;In this scenario, the document is split into chunks using the &lt;code&gt;RecursiveCharacterTextSplitter&lt;/code&gt; with a specified chunk size and overlap. This method ensures that no critical information is lost between chunks. Following the splitting, these chunks are then indexed into Qdrant—a vector database for efficient similarity search and storage of embeddings. The &lt;code&gt;Qdrant.from_documents&lt;/code&gt; function is utilized for indexing, with documents being the split chunks and embeddings generated through &lt;code&gt;OpenAIEmbeddings&lt;/code&gt;. The entire process is facilitated within an in-memory database, signifying that the operations are performed without the need for persistent storage, and the collection is named “lilianweng” for reference.&lt;/p&gt;

&lt;p&gt;This chunking and indexing strategy significantly improves the management and retrieval of information from large documents, making it a practical solution for handling extensive texts in data processing workflows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)

vectorstore = Qdrant.from_documents(
    documents=splits, embedding=OpenAIEmbeddings(), location=":memory:", collection_name="lilianweng"
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Retrieve and generate content
&lt;/h2&gt;

&lt;p&gt;The vectorstore is used as a retriever to fetch relevant documents based on vector similarity. The hub.pull("rlm/rag-prompt") function is used to pull a specific prompt from a repository, which is designed to work with retrieved documents and a question to generate a response.&lt;/p&gt;

&lt;p&gt;The format_docs function formats the retrieved documents into a single string, preparing them for further processing. This formatted string, along with a question, is passed through a chain of operations. Firstly, the context (formatted documents) and the question are processed by the retriever and the prompt. Then, the result is fed into a large language model (llm) for content generation. Finally, the output is parsed into a string format using StrOutputParser().&lt;/p&gt;

&lt;p&gt;This chain of operations demonstrates a sophisticated approach to information retrieval and content generation, leveraging both the semantic understanding capabilities of vector search and the generative prowess of large language models.&lt;/p&gt;

&lt;p&gt;Now, retrieve and generate data using relevant snippets from the blogL&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;retriever = vectorstore.as_retriever()
prompt = hub.pull("rlm/rag-prompt")


def format_docs(docs):
    return "\n\n".join(doc.page_content for doc in docs)


rag_chain = (
    {"context": retriever | format_docs, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Invoking the RAG Chain
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rag_chain.invoke("What is Task Decomposition?")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Next steps:
&lt;/h2&gt;

&lt;p&gt;We built a solid foundation for a simple chatbot, but there is still a lot to do. If you want to make the system production-ready, you should consider implementing the mechanism into your existing stack. We recommend&lt;/p&gt;

&lt;p&gt;Our vector database can easily be hosted on &lt;a href="https://www.scaleway.com/" rel="noopener noreferrer"&gt;Scaleway&lt;/a&gt;, our trusted &lt;a href="https://qdrant.tech/documentation/hybrid-cloud/" rel="noopener noreferrer"&gt;Qdrant Hybrid Cloud&lt;/a&gt; partner. This means that Qdrant can be run from your Scaleway region, but the database itself can still be managed from within Qdrant Cloud’s interface. Both products have been tested for compatibility and scalability, and we recommend their &lt;a href="https://www.scaleway.com/en/kubernetes-kapsule/" rel="noopener noreferrer"&gt;managed Kubernetes&lt;/a&gt; service. Their French deployment regions e.g. France are excellent for network latency and data sovereignty. For hosted GPUs, try &lt;a href="https://www.scaleway.com/en/l4-gpu-instance/" rel="noopener noreferrer"&gt;rendering with L4 GPU instance&lt;/a&gt;s.&lt;/p&gt;

&lt;p&gt;If you have any questions, feel free to ask on our &lt;a href="https://dev.toDiscord%20community"&gt;Discord community&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Qdrant 1.8.0 - Major Performance Enhancements</title>
      <dc:creator>David Myriel</dc:creator>
      <pubDate>Fri, 08 Mar 2024 16:41:12 +0000</pubDate>
      <link>https://dev.to/qdrant/qdrant-180-major-performance-enhancements-384o</link>
      <guid>https://dev.to/qdrant/qdrant-180-major-performance-enhancements-384o</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/qdrant/qdrant/releases/tag/v1.8.0" rel="noopener noreferrer"&gt;Qdrant 1.8.0 is out!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This time around, we have focused on Qdrant's internals. Our goal was to optimize performance, so that your existing setup can run faster and save on compute. Here is what we've been up to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Faster sparse vectors:&lt;/strong&gt; Hybrid search is up to 16x faster now!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CPU resource management:&lt;/strong&gt; You can allocate CPU threads for faster indexing. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better indexing performance:&lt;/strong&gt; We optimized text indexing on the backend.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Faster search with sparse vectors
&lt;/h2&gt;

&lt;p&gt;Search throughput is now up to 16 times faster for sparse vectors. If you are &lt;a href="https://dev.to/articles/sparse-vectors/"&gt;using Qdrant for hybrid search&lt;/a&gt;, this means that you can now handle up to sixteen times as many queries. This improvement comes from extensive backend optimizations aimed at increasing efficiency and capacity. &lt;/p&gt;

&lt;p&gt;What this means for your setup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Query speed:&lt;/strong&gt; The time it takes to run a search query has been significantly reduced. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search capacity:&lt;/strong&gt; Qdrant can now handle a much larger volume of search requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User experience:&lt;/strong&gt; Results will appear faster, leading to a smoother experience for the user.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability:&lt;/strong&gt; You can easily accomodate rapidly growing users or an expanding dataset.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Sparse vectors benchmark
&lt;/h3&gt;

&lt;p&gt;Performance results are publicly available for you to test. Qdrant's R&amp;amp;D developed a dedicated &lt;a href="https://github.com/qdrant/sparse-vectors-benchmark" rel="noopener noreferrer"&gt;open-source benchmarking tool&lt;/a&gt; just to test sparse vector performance.&lt;/p&gt;

&lt;p&gt;A real-life simulation of sparse vector queries was run against the &lt;a href="https://big-ann-benchmarks.com/neurips23.html" rel="noopener noreferrer"&gt;NeurIPS 2023 dataset&lt;/a&gt;. All tests were done on an 8 CPU machine on Azure. &lt;/p&gt;

&lt;p&gt;Latency (y-axis) has dropped significantly for queries. You can see the before/after here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9kgj248oqlxs4i4wvvmy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9kgj248oqlxs4i4wvvmy.png" alt="dropping latency" width="800" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 1:&lt;/strong&gt; Dropping latency in sparse vector search queries across versions 1.7-1.8.&lt;/p&gt;

&lt;p&gt;The colors within both scatter plots show the frequency of results. The red dots show that the highest concentration is around 2200ms (before) and 135ms (after). This tells us that latency for sparse vectors queries dropped by about a factor of 16. Therefore, the time it takes to retrieve an answer with Qdrant is that much shorter. &lt;/p&gt;

&lt;p&gt;This performance increase can have a dramatic effect on hybrid search implementations. &lt;a href="https://dev.to/articles/sparse-vectors/"&gt;Read more about how to set this up.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;FYI, sparse vectors were released in &lt;a href="///articles/qdrant-1.7.x/#sparse-vectors"&gt;Qdrant v.1.7.0&lt;/a&gt;. They are stored using a different index, so first &lt;a href="https://dev.to/documentation/concepts/indexing/#sparse-vector-index"&gt;check out the documentation&lt;/a&gt; if you want to try an implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  CPU resource management
&lt;/h2&gt;

&lt;p&gt;Indexing is Qdrant’s most resource-intensive process. Now you can account for this by allocating compute use specifically to indexing. You can assign a number CPU resources towards indexing and leave the rest for search. As a result, indexes will build faster, and search quality will remain unaffected.&lt;/p&gt;

&lt;p&gt;This isn't mandatory, as Qdrant is by default tuned to strike the right balance between indexing and search. However, if you wish to define specific CPU usage, you will need to do so from &lt;code&gt;config.yaml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This version introduces a &lt;code&gt;optimizer_cpu_budget&lt;/code&gt; parameter to control the maximum number of CPUs used for indexing. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Read more about &lt;code&gt;config.yaml&lt;/code&gt; in the &lt;a href="https://dev.to/documentation/guides/configuration/"&gt;configuration file&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# CPU budget, how many CPUs (threads) to allocate for an optimization job.&lt;/span&gt;
&lt;span class="na"&gt;optimizer_cpu_budget&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If left at 0, Qdrant will keep 1 or more CPUs unallocated - depending on CPU size.&lt;/li&gt;
&lt;li&gt;If the setting is positive, Qdrant will use this exact number of CPUs for indexing.&lt;/li&gt;
&lt;li&gt;If the setting is negative, Qdrant will subtract this number of CPUs from the available CPUs for indexing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For most users, the default &lt;code&gt;optimizer_cpu_budget&lt;/code&gt; setting will work well. We only recommend you use this if your indexing load is significant.&lt;/p&gt;

&lt;p&gt;Our backend leverages dynamic CPU saturation to increase indexing speed. For that reason, the impact on search query performance ends up being minimal. Ultimately, you will be able to strike a the best possible balance between indexing times and search performance.&lt;/p&gt;

&lt;p&gt;This configuration can be done at any time, but it requires a restart of Qdrant. Changing it affects both existing and new collections. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This feature is not configurable on &lt;a href="https://qdrant.to/cloud" rel="noopener noreferrer"&gt;Qdrant Cloud&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Better indexing for text data
&lt;/h2&gt;

&lt;p&gt;In order to minimize your RAM expenditure, we have developed a new way to index specific types of data. Please keep in mind that this is a backend improvement, and you won't need to configure anything. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Going forward, if you are indexing immutable text fields, we estimate a 10% reduction in RAM loads. Our benchmark result is based on a system that uses 64GB of RAM. If you are using less RAM, this reduction might be higher than 10%.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Immutable text fields are static and do not change once they are added to Qdrant. These entries usually represent some type of an attribute, description or a tag. Vectors associated with them can be indexed more efficiently, since you don’t need to re-index them anymore. Conversely, mutable fields are dynamic and can be modified after their initial creation. Please keep in mind that they will continue to require additional RAM.&lt;/p&gt;

&lt;p&gt;This approach ensures stability in the vector search index, with faster and more consistent operations. We achieved this by setting up a field index which helps minimize what is stored. To improve search performance we have also optimized the way we load documents for searches with a text field index. Now our backend loads documents mostly sequentially and in increasing order.&lt;/p&gt;

&lt;h2&gt;
  
  
  Minor improvements and new features
&lt;/h2&gt;

&lt;p&gt;Beyond these enhancements, &lt;a href="https://github.com/qdrant/qdrant/releases/tag/v1.8.0" rel="noopener noreferrer"&gt;Qdrant v1.8.0&lt;/a&gt; adds and improves on several smaller features:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Order points by payload:&lt;/strong&gt; In addition to searching for semantic results, you might want to retrieve results by specific metadata (such as price). You can now use Scroll API to &lt;a href="https://dev.to/documentation/concepts/points/#order-points-by-payload-key"&gt;order points by payload key&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Datetime support:&lt;/strong&gt; We have implemented &lt;a href="https://dev.to/documentation/concepts/filtering/#datetime-range"&gt;datetime support for the payload index&lt;/a&gt;. Prior to this, if you wanted to search for a specific datetime range, you would have had to convert dates to UNIX timestamps. (&lt;a href="https://github.com/qdrant/qdrant/issues/3320" rel="noopener noreferrer"&gt;PR#3320&lt;/a&gt;) &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check collection existence:&lt;/strong&gt; You can check whether a collection exists via the &lt;code&gt;/exists&lt;/code&gt; endpoint to the &lt;code&gt;/collections/{collection_name}&lt;/code&gt;. You will get a true/false response. (&lt;a href="https://github.com/qdrant/qdrant/pull/3472" rel="noopener noreferrer"&gt;PR#3472&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Find points&lt;/strong&gt; whose payloads match more than the minimal amount of conditions. We included the &lt;code&gt;min_should&lt;/code&gt; match feature for a condition to be &lt;code&gt;true&lt;/code&gt; (&lt;a href="https://github.com/qdrant/qdrant/pull/3466/" rel="noopener noreferrer"&gt;PR#3331&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modify nested fields:&lt;/strong&gt; We have improved the &lt;code&gt;set_payload&lt;/code&gt; API, adding the ability to update nested fields (&lt;a href="https://github.com/qdrant/qdrant/pull/3548" rel="noopener noreferrer"&gt;PR#3548&lt;/a&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Release notes
&lt;/h2&gt;

&lt;p&gt;For more information, see &lt;a href="https://github.com/qdrant/qdrant/releases/tag/v1.8.0" rel="noopener noreferrer"&gt;our release notes&lt;/a&gt;. &lt;br&gt;
Qdrant is an open source project. We welcome your contributions; raise &lt;a href="https://github.com/qdrant/qdrant/issues" rel="noopener noreferrer"&gt;issues&lt;/a&gt;, or contribute via &lt;a href="https://github.com/qdrant/qdrant/pulls" rel="noopener noreferrer"&gt;pull requests&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>vectordatabase</category>
      <category>devops</category>
      <category>news</category>
      <category>database</category>
    </item>
    <item>
      <title>RAG is Dead. Long Live RAG!</title>
      <dc:creator>David Myriel</dc:creator>
      <pubDate>Wed, 28 Feb 2024 21:44:14 +0000</pubDate>
      <link>https://dev.to/qdrant/rag-is-dead-long-live-rag-5k8</link>
      <guid>https://dev.to/qdrant/rag-is-dead-long-live-rag-5k8</guid>
      <description>&lt;p&gt;When Anthropic came out with a context window of 100K tokens, they said: “&lt;em&gt;Vector search is dead. LLMs are getting more accurate and won’t need RAG anymore.&lt;/em&gt;”&lt;/p&gt;

&lt;p&gt;Google’s Gemini 1.5 now offers a context window of 10 million tokens. &lt;a href="https://storage.googleapis.com/deepmind-media/gemini/gemini_v1_5_report.pdf" rel="noopener noreferrer"&gt;Their supporting paper&lt;/a&gt; claims victory over accuracy issues, even when applying Greg Kamradt’s &lt;a href="https://twitter.com/GregKamradt/status/1722386725635580292" rel="noopener noreferrer"&gt;NIAH methodology&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;It’s over. RAG must be completely obsolete now. Right?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;No.&lt;/p&gt;

&lt;p&gt;Larger context windows are never the solution. Let me repeat. Never. They require more computational resources and lead to slower processing times. &lt;/p&gt;

&lt;p&gt;The community is already stress testing Gemini 1.5: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftait4tne3qsw6yl3hzch.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftait4tne3qsw6yl3hzch.png" alt="rag-is-dead-1.png" width="800" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is not surprising. LLMs require massive amounts of compute and memory to run. To cite Grant, running such a model by itself “would deplete a small coal mine to generate each completion”. Also, who is waiting 30 seconds for a response?&lt;/p&gt;

&lt;h2&gt;
  
  
  Context stuffing is not the solution
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Relying on context is expensive, and it doesn’t improve response quality in real-world applications. Retrieval based on vector search offers much higher precision.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you solely rely on an LLM to perfect retrieval and precision, you are doing it wrong. &lt;/p&gt;

&lt;p&gt;A large context window makes it harder to focus on relevant information. This increases the risk of errors or hallucinations in its responses. &lt;/p&gt;

&lt;p&gt;Google found Gemini 1.5 significantly more accurate than GPT-4 at shorter context lengths and “a very small decrease in recall towards 1M tokens”. The recall is still below 0.8.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fefu8rcww1dvr3hakh4pm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fefu8rcww1dvr3hakh4pm.png" alt="rag-is-dead-2" width="800" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We don’t think 60-80% is good enough. The LLM might retrieve enough relevant facts in its context window, but it still loses up to 40% of the available information.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The whole point of vector search is to circumvent this process by efficiently picking the information your app needs to generate the best response. A vector database keeps the compute load low and the query response fast. You don’t need to wait for the LLM at all.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Qdrant’s benchmark results are strongly in favor of accuracy and efficiency. We recommend that you consider them before deciding that an LLM is enough. Take a look at our &lt;a href="https://qdrant.tech/benchmarks/" rel="noopener noreferrer"&gt;open-source benchmark reports&lt;/a&gt; and &lt;a href="https://github.com/qdrant/vector-db-benchmark" rel="noopener noreferrer"&gt;try out the tests&lt;/a&gt; yourself. &lt;/p&gt;

&lt;h2&gt;
  
  
  Vector search in compound systems
&lt;/h2&gt;

&lt;p&gt;The future of AI lies in careful system engineering. As per &lt;a href="https://bair.berkeley.edu/blog/2024/02/18/compound-ai-systems/" rel="noopener noreferrer"&gt;Zaharia et al.&lt;/a&gt;, results from Databricks find that “60% of LLM applications use some form of RAG, while 30% use multi-step chains.” &lt;/p&gt;

&lt;p&gt;Even Gemini 1.5 demonstrates the need for a complex strategy. When looking at &lt;a href="https://storage.googleapis.com/deepmind-media/gemini/gemini_v1_5_report.pdf" rel="noopener noreferrer"&gt;Google’s MMLU Benchmark&lt;/a&gt;, the model was called 32 times to reach a score of 90.0% accuracy. This shows us that even a basic compound arrangement is superior to monolithic models. &lt;/p&gt;

&lt;p&gt;As a retrieval system, a vector database perfectly fits the need for compound systems. Introducing them into your design opens the possibilities for superior applications of LLMs. It is superior because it’s faster, more accurate, and much cheaper to run. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The key advantage of RAG is that it allows an LLM to pull in real-time information from up-to-date internal and external knowledge sources, making it more dynamic and adaptable to new information. - Oliver Molander, CEO of IMAGINAI&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Qdrant scales to enterprise RAG scenarios
&lt;/h2&gt;

&lt;p&gt;People still don’t understand the economic benefit of vector databases. Why would a large corporate AI system need a stand-alone vector db like Qdrant? In our minds, this is the most important question. Let’s pretend that LLMs cease struggling with context thresholds altogether. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How much would all of this cost?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;If you are running a RAG solution in an enterprise environment with petabytes of private data, your compute bill will be unimaginable. Let's assume 1 cent per 1K input tokens (which is the current GPT-4 Turbo pricing). Whatever you are doing, every time you go 100 thousand tokens deep, it will cost you $1. &lt;/p&gt;

&lt;p&gt;That’s a buck a question. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;According to our estimations, vector search queries are &lt;strong&gt;at least&lt;/strong&gt; 100 million times cheaper than queries made by LLMs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Conversely, the only up-front investment with vector databases is the indexing (which requires more compute). After this step, everything else is a breeze. Once setup, Qdrant easily scales via &lt;a href="https://qdrant.tech/articles/multitenancy/" rel="noopener noreferrer"&gt;features like Multitenancy and Sharding&lt;/a&gt;. This lets you scale up your reliance on the vector retrieval process and minimize your use of the compute-heavy LLMs. As an optimization  measure, Qdrant is irreplaceable. &lt;/p&gt;

&lt;p&gt;Julien Simon from HuggingFace says it best:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;RAG is not a workaround for limited context size. For mission-critical enterprise use cases, RAG is a way to leverage high-value, proprietary company knowledge that will never be found in public datasets used for LLM training. At the moment, the best place to index and query this knowledge is some sort of vector index. In addition, RAG downgrades the LLM to a writing assistant. Since built-in knowledge becomes much less important, a nice small 7B open-source model usually does the trick at a fraction of the cost of a huge generic model.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Long Live RAG
&lt;/h2&gt;

&lt;p&gt;As LLMs continue to require enormous computing power, users will need to leverage vector search and RAG.&lt;/p&gt;

&lt;p&gt;Our customers remind us of this fact every day. As a product, our vector database is highly scalable and business-friendly. We develop our features strategically to follow our company’s Unix philosophy. &lt;/p&gt;

&lt;p&gt;We want to keep Qdrant compact, efficient and with a focused purpose. This purpose is to empower our customers to use it however they see fit. &lt;/p&gt;

&lt;p&gt;When large enterprises release their generative AI into production, they need to keep costs under control, while retaining the best possible quality of responses. Qdrant has the tools to do just that. &lt;/p&gt;

&lt;p&gt;Whether through &lt;a href="https://qdrant.tech/articles/vector-similarity-beyond-search/" rel="noopener noreferrer"&gt;RAG, Semantic Search, Dissimilarity Search, Recommendations or Multimodality&lt;/a&gt; - Qdrant will continue to journey on.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>machinelearning</category>
      <category>programming</category>
    </item>
    <item>
      <title>Best Practices for Massive-Scale Deployments: Multitenancy and Custom Sharding</title>
      <dc:creator>David Myriel</dc:creator>
      <pubDate>Tue, 13 Feb 2024 14:53:58 +0000</pubDate>
      <link>https://dev.to/qdrant/best-practices-for-massive-scale-deployments-multitenancy-and-custom-sharding-1mjb</link>
      <guid>https://dev.to/qdrant/best-practices-for-massive-scale-deployments-multitenancy-and-custom-sharding-1mjb</guid>
      <description>&lt;p&gt;We are seeing the topics of &lt;a href="https://qdrant.tech/documentation/guides/multiple-partitions/" rel="noopener noreferrer"&gt;multitenancy&lt;/a&gt; and &lt;a href="https://qdrant.tech/documentation/guides/distributed_deployment/#sharding" rel="noopener noreferrer"&gt;distributed deployment&lt;/a&gt; pop-up daily on our &lt;a href="https://qdrant.to/discord" rel="noopener noreferrer"&gt;Discord support channel&lt;/a&gt;. This tells us that many of you are looking to scale Qdrant along with the rest of your machine learning setup. &lt;/p&gt;

&lt;p&gt;Whether you are building a bank fraud-detection system, RAG for e-commerce, or services for the federal government - you will need to leverage a multitenant architecture to scale your product.&lt;br&gt;
In the world of SaaS and enterprise apps, this setup is the norm. It will considerably increase your application's performance and lower your hosting costs. &lt;/p&gt;

&lt;p&gt;We have developed two major features just for this. &lt;strong&gt;You can now scale a single Qdrant cluster and support all of your customers worldwide.&lt;/strong&gt; Under &lt;a href="https://qdrant.tech/documentation/guides/multiple-partitions/" rel="noopener noreferrer"&gt;multitenancy&lt;/a&gt;, each customer's data is completely isolated and only accessible by them. At times, if this data is location-sensitive, Qdrant also gives you the option to divide your cluster by region or other criteria that further secure your customer's access. This is called &lt;a href="https://qdrant.tech/documentation/guides/distributed_deployment/#user-defined-sharding" rel="noopener noreferrer"&gt;custom sharding&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Combining these two will result in an efficiently-partitioned architecture that further leverages the convenience of a single Qdrant cluster. This article will briefly explain the benefits and show how you can get started using both features.&lt;/p&gt;
&lt;h2&gt;
  
  
  One collection, many tenants
&lt;/h2&gt;

&lt;p&gt;When working with Qdrant, you can upsert all your data to a single collection, and then partition each vector via its payload. This means that all your users are leveraging the power of a single Qdrant cluster, but their data is still isolated within the collection. Let's take a look at a two-tenant collection:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 1:&lt;/strong&gt; Each individual vector is assigned a specific payload that denotes which tenant it belongs to. This is how a large number of different tenants can share a single Qdrant collection.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6gcrk4ylh7wvhbtivvx1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6gcrk4ylh7wvhbtivvx1.png" alt="Qdrant Multitenanc" width="800" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Qdrant is built to excel in a single collection with a vast number of tenants. You should only create multiple collections when your data is not homogenous or if users' vectors are created by different embedding models. Creating too many collections may result in resource overhead and cause dependencies. This can increase costs and affect overall performance. &lt;/p&gt;
&lt;h2&gt;
  
  
  Sharding your database
&lt;/h2&gt;

&lt;p&gt;With Qdrant, you can also specify a shard for each vector individually. This feature is useful if you want to &lt;a href="https://qdrant.tech/documentation/guides/distributed_deployment/#sharding" rel="noopener noreferrer"&gt;control where your data is kept in the cluster&lt;/a&gt;. For example, one set of vectors can be assigned to one shard on its own node, while another set can be on a completely different node.&lt;/p&gt;

&lt;p&gt;During vector search, your operations will be able to hit only the subset of shards they actually need. In massive-scale deployments, &lt;strong&gt;this can significantly improve the performance of operations that do not require the whole collection to be scanned&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This works in the other direction as well. Whenever you search for something, you can specify a shard or several shards and Qdrant will know where to find them. It will avoid asking all machines in your cluster for results. This will minimize overhead and maximize performance. &lt;/p&gt;
&lt;h3&gt;
  
  
  Common use cases
&lt;/h3&gt;

&lt;p&gt;A clear use-case for this feature is managing a multitenant collection, where each tenant (let it be a user or organization) is assumed to be segregated, so they can have their data stored in separate shards. Sharding solves the problem of region-based data placement, whereby certain data needs to be kept within specific locations. To do this, however, you will need to &lt;a href="https://qdrant.tech/documentation/guides/distributed_deployment/#moving-shards" rel="noopener noreferrer"&gt;move your shards between nodes&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 2:&lt;/strong&gt; Users can both upsert and query shards that are relevant to them, all within the same collection. Regional sharding can help avoid cross-continental traffic. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffgsrslrna13ukfu45bzk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffgsrslrna13ukfu45bzk.png" alt="Qdrant Multitenancy" width="800" height="196"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Custom sharding also gives you precise control over other use cases. A time-based data placement means that data streams can index shards that represent latest updates. If you organize your shards by date, you can have great control over the recency of retrieved data. This is relevant for social media platforms, which greatly rely on time-sensitive data. &lt;/p&gt;
&lt;h2&gt;
  
  
  Before I go any further.....how secure is my user data?
&lt;/h2&gt;

&lt;p&gt;By design, Qdrant offers three levels of isolation. We initially introduced collection-based isolation, but your scaled setup has to move beyond this level. In this scenario, you will leverage payload-based isolation (from multitenancy) and resource-based isolation (from sharding). The ultimate goal is to have a single collection, where you can manipulate and customize placement of shards inside your cluster more precisely and avoid any kind of overhead. The diagram below shows the arrangement of your data within a two-tier isolation arrangement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 3:&lt;/strong&gt; Users can query the collection based on two filters: the &lt;code&gt;group_id&lt;/code&gt; and the individual &lt;code&gt;shard_key_selector&lt;/code&gt;. This gives your data two additional levels of isolation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flliib0gkmdnh57r9mezn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flliib0gkmdnh57r9mezn.png" alt="Qdrant Multitenancy" width="800" height="328"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Create custom shards for a single collection
&lt;/h2&gt;

&lt;p&gt;When creating a collection, you will need to configure user-defined sharding. This lets you control the shard placement of your data, so that operations can hit only the subset of shards they actually need. In big clusters, this can significantly improve the performance of operations, since you won't need to go through the entire collection to retrieve data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;collection_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{tenant_data}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;shard_number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;sharding_method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ShardingMethod&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CUSTOM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;# ... other collection parameters
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_shard_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{tenant_data}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;canada&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_shard_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{tenant_data}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;germany&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, your cluster is divided between Germany and Canada. Canadian and German law differ when it comes to international data transfer. Let's say you are creating a RAG application that supports the healthcare industry. Your Canadian customer data will have to be clearly separated for compliance purposes from your German customer. &lt;/p&gt;

&lt;p&gt;Even though it is part of the same collection, data from each shard is isolated from other shards and can be retrieved as such. For additional examples on shards and retrieval, consult &lt;a href="https://qdrant.tech/documentation/guides/distributed_deployment/" rel="noopener noreferrer"&gt;Distributed Deployments&lt;/a&gt; documentation and &lt;a href="https://python-client.qdrant.tech" rel="noopener noreferrer"&gt;Qdrant Client specification&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure a multitenant setup for users
&lt;/h2&gt;

&lt;p&gt;Let's continue and start adding data. As you upsert your vectors to your new collection, you can add a &lt;code&gt;group_id&lt;/code&gt; field to each vector. If you do this, Qdrant will assign each vector to its respective group. &lt;/p&gt;

&lt;p&gt;Additionally, each vector can now be allocated to a shard. You can specify the &lt;code&gt;shard_key_selector&lt;/code&gt; for each individual vector. In this example, you are upserting data belonging to &lt;code&gt;tenant_1&lt;/code&gt; to the Canadian region.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upsert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;collection_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{tenant_data}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;PointStruct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;group_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tenant_1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; 
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;PointStruct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;group_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tenant_1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;shard_key_selector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;canada&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep in mind that the data for each &lt;code&gt;group_id&lt;/code&gt; is isolated. In the example below, &lt;code&gt;tenant_1&lt;/code&gt; vectors are kept separate from &lt;code&gt;tenant_2&lt;/code&gt;. The first tenant will be able to access their data in the Canadian portion of the cluster. However, as shown below &lt;code&gt;tenant_2&lt;/code&gt;might only be able to retrieve information hosted in Germany.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upsert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;collection_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{tenant_data}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;PointStruct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;group_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tenant_2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.9&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;shard_key_selector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;germany&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Retrieve data via filters
&lt;/h2&gt;

&lt;p&gt;The access control setup is completed as you specify the criteria for data retrieval. When searching for vectors, you need to use a &lt;code&gt;query_filter&lt;/code&gt; along with &lt;code&gt;group_id&lt;/code&gt; to filter vectors for each user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;collection_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{tenant_data}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;query_filter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;must&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;FieldCondition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;group_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;MatchValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tenant_1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;query_vector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.9&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Performance considerations
&lt;/h2&gt;

&lt;p&gt;The speed of indexation may become a bottleneck if you are adding large amounts of data in this way, as each user's vector will be indexed into the same collection. To avoid this bottleneck, consider &lt;em&gt;bypassing the construction of a global vector index&lt;/em&gt; for the entire collection and building it only for individual groups instead.&lt;/p&gt;

&lt;p&gt;By adopting this strategy, Qdrant will index vectors for each user independently, significantly accelerating the process.&lt;/p&gt;

&lt;p&gt;To implement this approach, you should:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set &lt;code&gt;payload_m&lt;/code&gt; in the HNSW configuration to a non-zero value, such as 16.&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;m&lt;/code&gt; in hnsw config to 0. This will disable building global index for the whole collection.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;qdrant_client&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;QdrantClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;QdrantClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;localhost&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6333&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;collection_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{tenant_data}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;vectors_config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;VectorParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;768&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Distance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COSINE&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;hnsw_config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;HnswConfigDiff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;payload_m&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Create keyword payload index for &lt;code&gt;group_id&lt;/code&gt; field.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_payload_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;collection_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{tenant_data}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;field_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;group_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;field_schema&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PayloadSchemaType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;KEYWORD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: Keep in mind that global requests (without the &lt;code&gt;group_id&lt;/code&gt; filter) will be slower since they will necessitate scanning all groups to identify the nearest neighbors.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;p&gt;Qdrant is ready to support a massive-scale architecture for your machine learning project. If you want to see whether our vector database is right for you, try the &lt;a href="https://qdrant.tech/documentation/quick-start/" rel="noopener noreferrer"&gt;quickstart tutorial&lt;/a&gt; or read our &lt;a href="https://qdrant.tech/documentation/" rel="noopener noreferrer"&gt;docs and tutorials&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To spin up a free instance of Qdrant, sign up for &lt;a href="https://qdrant.to/cloud" rel="noopener noreferrer"&gt;Qdrant Cloud&lt;/a&gt; - no strings attached.&lt;/p&gt;

&lt;p&gt;Get support or share ideas in our &lt;a href="https://qdrant.to/discord" rel="noopener noreferrer"&gt;Discord&lt;/a&gt; community. This is where we talk about vector search theory, publish examples and demos and discuss vector database setups.&lt;/p&gt;

</description>
      <category>vectordatabase</category>
      <category>devops</category>
      <category>database</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
