langflow-ai / langflow

Langflow is a low-code app builder for RAG and multi-agent AI applications. It’s Python-based and agnostic to any model, API, or database.
http://www.langflow.org
MIT License
30.4k stars 3.83k forks source link

SSL Error querying qdrant vector db #3166

Closed peter-boucher closed 1 month ago

peter-boucher commented 2 months ago

Bug Description

When using the Qdrant module in a flow based on the template "Vector Store RAG" I am able to ingest my data into a qdrant instance running locally in docker. When running the RAG flow, querying the vector store fails with an SSL record layer failure message. Screenshot: image

Python error ResponseHandlingException: [SSL] record layer failure (_ssl.c:1000) /Users/peterboucher/projects/langflow/.venv/lib/python3.12/site-packages/pydantic/main.py:1059: PydanticDeprecatedSince20: Thefieldsattribute is deprecated, usemodel_fieldsinstead. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.8/migration/ warnings.warn(

Qdrant log: qdrant | 2024-08-02T13:34:38.637910Z ERROR actix_http::h1::dispatcher: stream error: request parse error: invalid Header provided

Reproduction

Prerequisite: docker container running qdrant vectorDB

dockerfile.yml

services:
  qdrant:
    image: qdrant/qdrant:latest
    restart: always
    container_name: qdrant
    ports:
      - 6333:6333
      - 6334:6334
    expose:
      - 6333
      - 6334
      - 6335
    volumes:
      - ./qdrant_data:/qdrant_data%
  1. Reproduce the flows pictured above (based on the template "Vector Store RAG"
  2. Using any PDF file as input. Run the lower ingestion flow, by clicking the play button on the last module Qdrant
  3. observe a collection is created in qdrant named 'langflow_demo'
  4. Run the upper RAG query flow by opening the Playground and typing a query related to the PDF content
  5. observe the error "[SSL] record layer failure"

Expected behavior

Expected a response from the model based on the ingested document in the vector store.

Who can help?

@carlosrcoelho

Operating System

MacOS Sonoma 14.5 (23F79)

Langflow Version

1.0.14

Python Version

3.12

Screenshot

image

Flow File

RAG Demo.json

dosubot[bot] commented 2 months ago

To resolve the SSL record layer failure when querying the Qdrant vector store in a flow based on the "Vector Store RAG" template, ensure that the location, api_key, and other relevant parameters are correctly provided when initializing the Qdrant client. Here is the relevant code snippet for initializing Qdrant:

def initialize_qdrant(class_object: Type[Qdrant], params: dict):
    if not docs_in_params(params):
        if "location" not in params and "api_key" not in params:
            raise ValueError("Location and API key must be provided in the params")
        from qdrant_client import QdrantClient

        client_params = {
            "location": params.pop("location"),
            "api_key": params.pop("api_key"),
            "https": params.pop("https", True),  # Ensure HTTPS is enabled
            "host": params.pop("host", None),
            "port": params.pop("port", 6333),
            "grpc_port": params.pop("grpc_port", 6334),
            "timeout": params.pop("timeout", None),
            "url": params.pop("url", None),
        }
        lc_params = {
            "collection_name": params.pop("collection_name"),
            "embeddings": params.pop("embedding"),
        }
        client = QdrantClient(**client_params)

        return class_object(client=client, **lc_params)

    return class_object.from_documents(**params)

Make sure that the location, api_key, and other parameters such as https, host, port, grpc_port, timeout, and url are correctly set in the params dictionary when calling this function. This should help in resolving the SSL record layer failure [1].

Additionally, ensure that the parameters are correctly set in the QdrantComponent class as shown below:

class QdrantComponent(CustomComponent):
    display_name = "Qdrant"
    description = "Construct Qdrant wrapper from a list of texts."

    def build_config(self):
        return {
            "documents": {"display_name": "Documents"},
            "embedding": {"display_name": "Embedding"},
            "api_key": {"display_name": "API Key", "password": True, "advanced": True},
            "collection_name": {"display_name": "Collection Name"},
            "content_payload_key": {"display_name": "Content Payload Key", "advanced": True},
            "distance_func": {"display_name": "Distance Function", "advanced": True},
            "grpc_port": {"display_name": "gRPC Port", "advanced": True},
            "host": {"display_name": "Host", "advanced": True},
            "https": {"display_name": "HTTPS", "advanced": True},
            "location": {"display_name": "Location", "advanced": True},
            "metadata_payload_key": {"display_name": "Metadata Payload Key", "advanced": True},
            "path": {"display_name": "Path", "advanced": True},
            "port": {"display_name": "Port", "advanced": True},
            "prefer_grpc": {"display_name": "Prefer gRPC", "advanced": True},
            "prefix": {"display_name": "Prefix", "advanced": True},
            "search_kwargs": {"display_name": "Search Kwargs", "advanced": True},
            "timeout": {"display_name": "Timeout", "advanced": True},
            "url": {"display_name": "URL", "advanced": True},
        }

    def build(
        self,
        embedding: Embeddings,
        collection_name: str,
        documents: Optional[Document] = None,
        api_key: Optional[str] = None,
        content_payload_key: str = "page_content",
        distance_func: str = "Cosine",
        grpc_port: int = 6334,
        https: bool = False,
        host: Optional[str] = None,
        location: Optional[str] = None,
        metadata_payload_key: str = "metadata",
        path: Optional[str] = None,
        port: Optional[int] = 6333,
        prefer_grpc: bool = False,
        prefix: Optional[str] = None,
        search_kwargs: Optional[NestedDict] = None,
        timeout: Optional[int] = None,
        url: Optional[str] = None,
    ) -> Union[VectorStore, Qdrant, BaseRetriever]:
        if documents is None:
            from qdrant_client import QdrantClient
            client = QdrantClient(
                location=location,
                url=host,
                port=port,
                grpc_port=grpc_port,
                https=https,
                prefix=prefix,
                timeout=timeout,
                prefer_grpc=prefer_grpc,
                metadata_payload_key=metadata_payload_key,
                content_payload_key=content_payload_key,
                api_key=api_key,
                collection_name=collection_name,
                host=host,
                path=path,
            )
            vs = Qdrant(
                client=client,
                collection_name=collection_name,
                embeddings=embedding,
            )
            return vs
        else:
            vs = Qdrant.from_documents(
                documents=documents,  # type: ignore
                embedding=embedding,
                api_key=api_key,
                collection_name=collection_name,
                content_payload_key=content_payload_key,
                distance_func=distance_func,
                grpc_port=grpc_port,
                host=host,
                https=https,
                location=location,
                metadata_payload_key=metadata_payload_key,
                path=path,
                port=port,
                prefer_grpc=prefer_grpc,
                prefix=prefix,
                search_kwargs=search_kwargs,
                timeout=timeout,
                url=url,
            )
        return vs

Ensure that all the necessary parameters are correctly set in the QdrantComponent class to avoid SSL record layer failures [2][3][4].

Additionally, check the docker-compose.yml file for configurations related to Traefik, which is used as a reverse proxy. These settings ensure that HTTPS is enabled, Let's Encrypt is used for SSL certificates, and HTTP requests are redirected to HTTPS:

- traefik.http.routers.${STACK_NAME?Variable not set}-proxy-https.tls=true
- traefik.http.routers.${STACK_NAME?Variable not set}-proxy-https.tls.certresolver=le
- traefik.http.middlewares.${STACK_NAME?Variable not set}-https-redirect.redirectscheme.scheme=https
- traefik.http.middlewares.${STACK_NAME?Variable not set}-https-redirect.redirectscheme.permanent=true

These configurations should help in resolving the SSL record layer failure [5].

To continue talking to Dosu, mention @dosu.

carlosrcoelho commented 1 month ago

@peter-boucher Ensure that the Qdrant server is running. You can start the Qdrant server with Docker using the following command: docker run -p 6333:6333 -p 6334:6334 qdrant/qdrant

carlosrcoelho commented 1 month ago

Thank you for your contribution! This issue will be closed. If you have any questions or encounter another problem, please open a new issue and we will be ready to assist you