From 469625c0a3b8bc2b857ca47a1afd84f4ff630d65 Mon Sep 17 00:00:00 2001 From: David Oplatka Date: Sun, 28 Jul 2024 07:02:23 -0700 Subject: [PATCH] feat: new Vectara RAG Component (#2733) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * First implementation of LangWatch tracer * Remove dependency from backend base internal and add langwatch docs * Bump langwatch to v0.1.4 * Fix missing log parameter on method * Move docs to the right folder * chore: update lock * Add Vectara RAG component and docs * [autofix.ci] apply automated fixes * refactor: update VectaraRAG component to the new component standard * fix: update VectaraRagComponent filter parameter Update the filter parameter in the VectaraRagComponent class to use the correct variable name 'self.filter' instead of 'filter'. This ensures that the correct filter value is passed to the VectaraQueryConfig object. * fix: add condition to set_cache_coro in Graph class Add a condition to the `set_cache_coro` function call in the `Graph` class. The condition checks if the `cache` variable is true and the `flow_id` is not empty before calling the function. This ensures that the cache is set only when both conditions are met, improving the efficiency of the code. --------- Co-authored-by: Rogério Chaves Co-authored-by: Gabriel Luiz Freitas Almeida Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- docs/docs/Components/components-rag.md | 31 +++++ .../Integrations/integrations-langwatch.mdx | 46 +++++++ poetry.lock | 21 ++- .../components/vectorstores/vectara_rag.py | 127 ++++++++++++++++++ src/backend/base/langflow/graph/graph/base.py | 2 +- .../base/langflow/services/tracing/base.py | 1 + src/backend/base/poetry.lock | 11 -- 7 files changed, 222 insertions(+), 17 deletions(-) create mode 100644 docs/docs/Components/components-rag.md create mode 100644 docs/docs/Integrations/integrations-langwatch.mdx create mode 100644 src/backend/base/langflow/components/vectorstores/vectara_rag.py diff --git a/docs/docs/Components/components-rag.md b/docs/docs/Components/components-rag.md new file mode 100644 index 000000000..d39eef27c --- /dev/null +++ b/docs/docs/Components/components-rag.md @@ -0,0 +1,31 @@ +--- +title: RAG +sidebar_position: 9 +slug: /components-rag +--- + +RAG (Retrieval-Augmented Generation) components process a user query by retrieving relevant documents and generating a concise summary that addresses the user's question. + + +### Vectara + + + `Vectara` performs RAG using a Vectara corpus, including document retrieval, reranking results, and summary generation. + + + **Parameters:** + + - **Vectara Customer ID:** Customer ID. + - **Vectara Corpus ID:** Corpus ID. + - **Vectara API Key:** API key. + - **Search Query:** User query. + - **Lexical Interpolation:** How much to weigh lexical vs. embedding scores. + - **Metadata Filters:** Filters to narrow down the search documents and parts. + - **Reranker Type:** How to rerank the retrieved results. + - **Number of Results to Rerank:** Maximum reranked results. + - **Diversity Bias:** How much to diversify retrieved results (only for MMR reranker). + - **Max Results to Summarize:** Maximum search results to provide to summarizer. + - **Response Language:** The language code (use ISO 639-1 or 639-3 codes) of the summary. + - **Prompt Name:** The summarizer prompt. + + For more information, consult the [Vectara documentation](https://docs.vectara.com/docs) diff --git a/docs/docs/Integrations/integrations-langwatch.mdx b/docs/docs/Integrations/integrations-langwatch.mdx new file mode 100644 index 000000000..8060ad480 --- /dev/null +++ b/docs/docs/Integrations/integrations-langwatch.mdx @@ -0,0 +1,46 @@ +import Admonition from "@theme/Admonition"; +import ThemedImage from "@theme/ThemedImage"; +import useBaseUrl from "@docusaurus/useBaseUrl"; +import ZoomableImage from "/src/theme/ZoomableImage.js"; + +# LangWatch + +LangWatch is an all-in-one LLMOps platform for monitoring, observability, analytics, evaluations and alerting for getting user insights and improve your LLM workflows. + +To integrate with Langflow, just add your LangWatch API as a Langflow environment variable and you are good to go! + +## Step-by-step Configuration + +1. Obtain your LangWatch API key from https://app.langwatch.com/ +2. Add the following key to Langflow .env file: + +```bash +LANGWATCH_API_KEY="your-api-key" +``` + +or export it in your terminal: + +```bash +export LANGWATCH_API_KEY="your-api-key" +``` + +3. Restart Langflow using `langflow run --env-file .env` +4. Run any project and check the LangWatch dashboard for monitoring and observability. + + + + diff --git a/poetry.lock b/poetry.lock index 0ab430b5f..64d52e6cd 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1332,6 +1332,17 @@ files = [ {file = "coolname-2.2.0.tar.gz", hash = "sha256:6c5d5731759104479e7ca195a9b64f7900ac5bead40183c09323c7d0be9e75c7"}, ] +[[package]] +name = "coolname" +version = "2.2.0" +description = "Random name and slug generator" +optional = false +python-versions = "*" +files = [ + {file = "coolname-2.2.0-py2.py3-none-any.whl", hash = "sha256:4d1563186cfaf71b394d5df4c744f8c41303b6846413645e31d31915cdeb13e8"}, + {file = "coolname-2.2.0.tar.gz", hash = "sha256:6c5d5731759104479e7ca195a9b64f7900ac5bead40183c09323c7d0be9e75c7"}, +] + [[package]] name = "couchbase" version = "4.3.0" @@ -2707,8 +2718,8 @@ files = [ [package.dependencies] cffi = {version = ">=1.12.2", markers = "platform_python_implementation == \"CPython\" and sys_platform == \"win32\""} greenlet = [ - {version = ">=3.0rc3", markers = "platform_python_implementation == \"CPython\" and python_version >= \"3.11\""}, {version = ">=2.0.0", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.11\""}, + {version = ">=3.0rc3", markers = "platform_python_implementation == \"CPython\" and python_version >= \"3.11\""}, ] "zope.event" = "*" "zope.interface" = "*" @@ -2867,12 +2878,12 @@ files = [ google-auth = ">=2.14.1,<3.0.dev0" googleapis-common-protos = ">=1.56.2,<2.0.dev0" grpcio = [ - {version = ">=1.49.1,<2.0dev", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, {version = ">=1.33.2,<2.0dev", optional = true, markers = "python_version < \"3.11\" and extra == \"grpc\""}, + {version = ">=1.49.1,<2.0dev", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, ] grpcio-status = [ - {version = ">=1.49.1,<2.0.dev0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, {version = ">=1.33.2,<2.0.dev0", optional = true, markers = "python_version < \"3.11\" and extra == \"grpc\""}, + {version = ">=1.49.1,<2.0.dev0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""}, ] proto-plus = ">=1.22.3,<2.0.0dev" protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" @@ -5220,8 +5231,8 @@ psutil = ">=5.9.1" pywin32 = {version = "*", markers = "platform_system == \"Windows\""} pyzmq = ">=25.0.0" requests = [ - {version = ">=2.32.2", markers = "python_version > \"3.11\""}, {version = ">=2.26.0", markers = "python_version <= \"3.11\""}, + {version = ">=2.32.2", markers = "python_version > \"3.11\""}, ] tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.11\""} @@ -6826,9 +6837,9 @@ files = [ [package.dependencies] numpy = [ - {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, {version = ">=1.22.4", markers = "python_version < \"3.11\""}, {version = ">=1.23.2", markers = "python_version == \"3.11\""}, + {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, ] python-dateutil = ">=2.8.2" pytz = ">=2020.1" diff --git a/src/backend/base/langflow/components/vectorstores/vectara_rag.py b/src/backend/base/langflow/components/vectorstores/vectara_rag.py new file mode 100644 index 000000000..10ea8c192 --- /dev/null +++ b/src/backend/base/langflow/components/vectorstores/vectara_rag.py @@ -0,0 +1,127 @@ +from langflow.custom import Component +from langflow.field_typing.range_spec import RangeSpec +from langflow.io import DropdownInput, FloatInput, IntInput, MessageTextInput, Output +from langflow.schema.message import Message + + +class VectaraRagComponent(Component): + display_name = "Vectara RAG" + description = "Vectara's full end to end RAG" + documentation = "https://docs.vectara.com/docs" + icon = "Vectara" + name = "VectaraRAG" + SUMMARIZER_PROMPTS = [ + "vectara-summary-ext-24-05-sml", + "vectara-summary-ext-24-05-med-omni", + "vectara-summary-ext-24-05-large", + "vectara-summary-ext-24-05-med", + "vectara-summary-ext-v1.3.0", + ] + + RERANKER_TYPES = ["mmr", "rerank_multilingual_v1", "none"] + + field_order = ["vectara_customer_id", "vectara_corpus_id", "vectara_api_key", "search_query", "reranker"] + # return { + # "vectara_customer_id": {"display_name": "Vectara Customer ID", "field_type": "str", "required": True}, + # "vectara_corpus_id": {"display_name": "Vectara Corpus ID", "field_type": "str", "required": True}, + # "vectara_api_key": {"display_name": "Vectara API Key", "field_type": "str", "required": True}, + # "search_query": {"display_name": "Search Query", "field_type": "str", "info": "The query to receive an answer on.", "required": True}, + # "lexical_interpolation": {"display_name": "Hybrid Search Factor", "field_type": "float", "value": 0.005, "info": "How much to weigh lexical scores compared to the embedding score. 0 means lexical search is not used at all, and 1 means only lexical search is used.", "advanced": True}, + # "filter": {"display_name": "Metadata Filters", "field_type": "str", "value": '', "info": "The filter string to narrow the search to according to metadata attributes.", "advanced": True}, + # "reranker": {"display_name": "Reranker Type", "options": RERANKER_TYPES, "value": RERANKER_TYPES[0], "info": "How to rerank the retrieved search results."}, + # "reranker_k": {"display_name": "Number of Results to Rerank", "field_type": "int", "value": 50, "advanced": True}, + # "diversity_bias": {"display_name": "Diversity Bias", "field_type": "float", "value": 0.2, "info": "Ranges from 0 to 1, with higher values indicating greater diversity (only applies to MMR reranker).", "advanced": True}, + # "max_results": {"display_name": "Max Results to Summarize", "field_type": "int", "value": 7, "info": "The maximum number of search results to be available to the prompt.", "advanced": True}, + # "response_lang": {"display_name": "Response Language", "field_type": "str", "value": "eng", "info": "Use the ISO 639-1 or 639-3 language code or auto to automatically detect the language.", "advanced": True}, + # "prompt": {"display_name": "Prompt Name", "options": SUMMARIZER_PROMPTS, "value": SUMMARIZER_PROMPTS[0], "info": "Only vectara-summary-ext-24-05-sml is for Growth customers; all other prompts are for Scale customers only.", "advanced": True} + # } + + inputs = [ + MessageTextInput(name="search_query", display_name="Search Query", info="The query to receive an answer on."), + FloatInput( + name="lexical_interpolation", + display_name="Hybrid Search Factor", + range_spec=RangeSpec(min=0.005, max=0.1, step=0.005), + value=0.005, + info="How much to weigh lexical scores compared to the embedding score. 0 means lexical search is not used at all, and 1 means only lexical search is used.", + ), + MessageTextInput( + name="filter", + display_name="Metadata Filters", + value="", + info="The filter string to narrow the search to according to metadata attributes.", + ), + DropdownInput( + name="reranker", + display_name="Reranker Type", + options=RERANKER_TYPES, + value=RERANKER_TYPES[0], + info="How to rerank the retrieved search results.", + ), + IntInput( + name="reranker_k", + display_name="Number of Results to Rerank", + value=50, + range_spec=RangeSpec(min=1, max=100, step=1), + ), + FloatInput( + name="diversity_bias", + display_name="Diversity Bias", + value=0.2, + range_spec=RangeSpec(min=0, max=1, step=0.01), + info="Ranges from 0 to 1, with higher values indicating greater diversity (only applies to MMR reranker).", + ), + IntInput( + name="max_results", + display_name="Max Results to Summarize", + value=7, + range_spec=RangeSpec(min=1, max=100, step=1), + ), + DropdownInput( + name="response_lang", + display_name="Response Language", + options=["auto", "eng", "deu", "fra", "ita", "nld", "por", "rus", "spa", "zho"], + value="eng", + info="Use the ISO 639-1 or 639-3 language code or auto to automatically detect the language.", + ), + DropdownInput( + name="prompt", + display_name="Prompt Name", + options=SUMMARIZER_PROMPTS, + value=SUMMARIZER_PROMPTS[0], + info="Only vectara-summary-ext-24-05-sml is for Growth customers; all other prompts are for Scale customers only.", + ), + ] + + outputs = [ + Output(name="answer", display_name="Answer", method="generate_response"), + ] + + def generate_response( + self, + ) -> Message: + text_output = "" + + try: + from langchain_community.vectorstores import Vectara + from langchain_community.vectorstores.vectara import RerankConfig, SummaryConfig, VectaraQueryConfig + except ImportError: + raise ImportError("Could not import Vectara. Please install it with `pip install langchain-community`.") + + vectara = Vectara(self.vectara_customer_id, self.vectara_corpus_id, self.vectara_api_key) + rerank_config = RerankConfig(self.reranker, self.reranker_k, self.diversity_bias) + summary_config = SummaryConfig( + is_enabled=True, max_results=self.max_results, response_lang=self.response_lang, prompt_name=self.prompt + ) + config = VectaraQueryConfig( + lambda_val=self.lexical_interpolation, + filter=self.filter, + summary_config=summary_config, + rerank_config=rerank_config, + ) + rag = vectara.as_rag(config) + response = rag.invoke(self.search_query) + + text_output = response["answer"] + + return Message(text=text_output) diff --git a/src/backend/base/langflow/graph/graph/base.py b/src/backend/base/langflow/graph/graph/base.py index 903eb9674..76516c14b 100644 --- a/src/backend/base/langflow/graph/graph/base.py +++ b/src/backend/base/langflow/graph/graph/base.py @@ -1013,7 +1013,7 @@ class Graph: next_runnable_vertices.remove(v_id) else: self.run_manager.add_to_vertices_being_run(next_v_id) - if cache: + if cache and self.flow_id: set_cache_coro = partial(get_chat_service().set_cache, key=self.flow_id) await set_cache_coro(self, lock) return next_runnable_vertices diff --git a/src/backend/base/langflow/services/tracing/base.py b/src/backend/base/langflow/services/tracing/base.py index 5da28f744..3d2c06cef 100644 --- a/src/backend/base/langflow/services/tracing/base.py +++ b/src/backend/base/langflow/services/tracing/base.py @@ -1,6 +1,7 @@ from abc import ABC, abstractmethod from typing import TYPE_CHECKING, Any, Dict, Optional from uuid import UUID + from langflow.services.tracing.schema import Log if TYPE_CHECKING: diff --git a/src/backend/base/poetry.lock b/src/backend/base/poetry.lock index 6d8026116..67f031f3a 100644 --- a/src/backend/base/poetry.lock +++ b/src/backend/base/poetry.lock @@ -1850,17 +1850,6 @@ files = [ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] -[[package]] -name = "nanoid" -version = "2.0.0" -description = "A tiny, secure, URL-friendly, unique string ID generator for Python" -optional = false -python-versions = "*" -files = [ - {file = "nanoid-2.0.0-py3-none-any.whl", hash = "sha256:90aefa650e328cffb0893bbd4c236cfd44c48bc1f2d0b525ecc53c3187b653bb"}, - {file = "nanoid-2.0.0.tar.gz", hash = "sha256:5a80cad5e9c6e9ae3a41fa2fb34ae189f7cb420b2a5d8f82bd9d23466e4efa68"}, -] - [[package]] name = "nest-asyncio" version = "1.6.0"