From bea72bac3e26fbb2b03de93f596168c455c73d23 Mon Sep 17 00:00:00 2001 From: dishaprakash <57954147+dishaprakash@users.noreply.github.com> Date: Fri, 12 Sep 2025 01:12:58 +0000 Subject: [PATCH 1/5] docs: add hybrid search documentation to PGVectorStore (#32549) Adding documentation for Hybrid Search in the PGVectorStore Notebook --------- Co-authored-by: Mason Daugherty --- .../vectorstores/pgvectorstore.ipynb | 258 +++++++++++++++++- 1 file changed, 256 insertions(+), 2 deletions(-) diff --git a/docs/docs/integrations/vectorstores/pgvectorstore.ipynb b/docs/docs/integrations/vectorstores/pgvectorstore.ipynb index da9847a32c5..d38e845a283 100644 --- a/docs/docs/integrations/vectorstores/pgvectorstore.ipynb +++ b/docs/docs/integrations/vectorstores/pgvectorstore.ipynb @@ -496,7 +496,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Create a custom Vector Store\n", + "## Create a custom Vector Store\n", "\n", "Customize the vectorstore with special column names or with custom metadata columns.\n", "\n", @@ -617,7 +617,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Create a Vector Store using existing table\n", + "## Create a Vector Store using existing table\n", "\n", "A Vector Store can be built up on an existing table.\n", "\n", @@ -713,6 +713,260 @@ "1. For new records, added via `VectorStore` embeddings are automatically generated." ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Hybrid Search with PGVectorStore\n", + "\n", + "A Hybrid Search combines multiple lookup strategies to provide more comprehensive and relevant search results. Specifically, it leverages both dense embedding vector search (for semantic similarity) and TSV (Text Search Vector) based keyword search (for lexical matching). This approach is particularly powerful for applications requiring efficient searching through customized text and metadata, especially when a specialized embedding model isn't feasible or necessary.\n", + "\n", + "By integrating both semantic and lexical capabilities, hybrid search helps overcome the limitations of each individual method:\n", + "* **Semantic Search**: Excellent for understanding the meaning of a query, even if the exact keywords aren't present. However, it can sometimes miss highly relevant documents that contain the precise keywords but have a slightly different semantic context.\n", + "* **Keyword Search**: Highly effective for finding documents with exact keyword matches and is generally fast. Its weakness lies in its inability to understand synonyms, misspellings, or conceptual relationships." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Hybrid Search Config\n", + "\n", + "You can take advantage of hybrid search with PGVectorStore using the `HybridSearchConfig`.\n", + "\n", + "With a `HybridSearchConfig` provided, the `PGVectorStore` class can efficiently manage a hybrid search vector store using PostgreSQL as the backend, automatically handling the creation and population of the necessary TSV columns when possible." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Building the config\n", + "\n", + "Here are the parameters to the hybrid search config:\n", + "* **tsv_column:** The column name for TSV column. Default: `_tsv`\n", + "* **tsv_lang:** Value representing a supported language. Default: `pg_catalog.english`\n", + "* **fts_query:** If provided, this would be used for secondary retrieval instead of user provided query.\n", + "* **fusion_function:** Determines how the results are to be merged, default is equal weighted sum ranking.\n", + "* **fusion_function_parameters:** Parameters for the fusion function\n", + "* **primary_top_k:** Max results fetched for primary retrieval. Default: `4`\n", + "* **secondary_top_k:** Max results fetched for secondary retrieval. Default: `4`\n", + "* **index_name:** Name of the index built on the `tsv_column`\n", + "* **index_type:** GIN or GIST. Default: `GIN`" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here is an example `HybridSearchConfig`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from langchain_postgres.v2.hybrid_search_config import (\n", + " HybridSearchConfig,\n", + " reciprocal_rank_fusion,\n", + ")\n", + "\n", + "hybrid_search_config = HybridSearchConfig(\n", + " tsv_column=\"hybrid_description\",\n", + " tsv_lang=\"pg_catalog.english\",\n", + " fusion_function=reciprocal_rank_fusion,\n", + " fusion_function_parameters={\n", + " \"rrf_k\": 60,\n", + " \"fetch_top_k\": 10,\n", + " },\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Note:** In this case, we have mentioned the fusion function to be a `reciprocal rank fusion` but you can also use the `weighted_sum_ranking`.\n", + "\n", + "Make sure to use the right fusion function parameters\n", + "\n", + "`reciprocal_rank_fusion`:\n", + "* rrf_k: The RRF parameter k. Defaults to 60\n", + "* fetch_top_k: The number of documents to fetch after merging the results. Defaults to 4\n", + "\n", + "`weighted_sum_ranking`:\n", + "* primary_results_weight: The weight for the primary source's scores. Defaults to 0.5\n", + "* secondary_results_weight: The weight for the secondary source's scores. Defaults to 0.5\n", + "* fetch_top_k: The number of documents to fetch after merging the results. Defaults to 4\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Usage\n", + "\n", + "Let's assume we are using the previously mentioned table [`products`](#create-a-vector-store-using-existing-table), which stores product details for an eComm venture.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### With a new hybrid search table\n", + "To create a new postgres table with the tsv column, specify the hybrid search config during the initialization of the vector store.\n", + "\n", + "In this case, all the similarity searches will make use of hybrid search." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from langchain_postgres import PGVectorStore\n", + "\n", + "TABLE_NAME = \"hybrid_search_products\"\n", + "\n", + "await pg_engine.ainit_vectorstore_table(\n", + " table_name=TABLE_NAME,\n", + " # schema_name=SCHEMA_NAME,\n", + " vector_size=VECTOR_SIZE,\n", + " id_column=\"product_id\",\n", + " content_column=\"description\",\n", + " embedding_column=\"embed\",\n", + " metadata_columns=[\"name\", \"category\", \"price_usd\", \"quantity\", \"sku\", \"image_url\"],\n", + " metadata_json_column=\"metadata\",\n", + " hybrid_search_config=hybrid_search_config,\n", + " store_metadata=True,\n", + ")\n", + "\n", + "vs_hybrid = await PGVectorStore.create(\n", + " pg_engine,\n", + " table_name=TABLE_NAME,\n", + " # schema_name=SCHEMA_NAME,\n", + " embedding_service=embedding,\n", + " # Connect to existing VectorStore by customizing below column names\n", + " id_column=\"product_id\",\n", + " content_column=\"description\",\n", + " embedding_column=\"embed\",\n", + " metadata_columns=[\"name\", \"category\", \"price_usd\", \"quantity\", \"sku\", \"image_url\"],\n", + " metadata_json_column=\"metadata\",\n", + " hybrid_search_config=hybrid_search_config,\n", + ")\n", + "\n", + "# Fetch documents from the previously created store to fetch product documents\n", + "docs = await custom_store.asimilarity_search(\"products\", k=5)\n", + "# Add data normally to the hybrid search vector store, which will also add the tsv values in tsv_column\n", + "await vs_hybrid.aadd_documents(docs)\n", + "\n", + "# Use hybrid search\n", + "hybrid_docs = await vs_hybrid.asimilarity_search(\"products\", k=5)\n", + "print(hybrid_docs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### With a pre-existing table\n", + "\n", + "If a hybrid search config is **NOT** provided during `init_vectorstore_table` while creating a table, the table will not contain a tsv_column. In this case you can still take advantage of hybrid search using the `HybridSearchConfig`.\n", + "\n", + "The specified TSV column is not present but the TSV vectors are created dynamically on-the-go for hybrid search." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from langchain_postgres import PGVectorStore\n", + "\n", + "# Set the existing table name\n", + "TABLE_NAME = \"products\"\n", + "# SCHEMA_NAME = \"my_schema\"\n", + "\n", + "hybrid_search_config = HybridSearchConfig(\n", + " tsv_lang=\"pg_catalog.english\",\n", + " fusion_function=reciprocal_rank_fusion,\n", + " fusion_function_parameters={\n", + " \"rrf_k\": 60,\n", + " \"fetch_top_k\": 10,\n", + " },\n", + ")\n", + "\n", + "# Initialize PGVectorStore with the hybrid search config\n", + "custom_hybrid_store = await PGVectorStore.create(\n", + " pg_engine,\n", + " table_name=TABLE_NAME,\n", + " # schema_name=SCHEMA_NAME,\n", + " embedding_service=embedding,\n", + " # Connect to existing VectorStore by customizing below column names\n", + " id_column=\"product_id\",\n", + " content_column=\"description\",\n", + " embedding_column=\"embed\",\n", + " metadata_columns=[\"name\", \"category\", \"price_usd\", \"quantity\", \"sku\", \"image_url\"],\n", + " metadata_json_column=\"metadata\",\n", + " hybrid_search_config=hybrid_search_config,\n", + ")\n", + "\n", + "# Use hybrid search\n", + "hybrid_docs = await custom_hybrid_store.asimilarity_search(\"products\", k=5)\n", + "print(hybrid_docs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this case, all the similarity searches will make use of hybrid search." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Applying Hybrid Search to Specific Queries\n", + "\n", + "To use hybrid search only for certain queries, omit the configuration during initialization and pass it directly to the search method when needed.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Use hybrid search\n", + "hybrid_docs = await custom_store.asimilarity_search(\n", + " \"products\", k=5, hybrid_search_config=hybrid_search_config\n", + ")\n", + "print(hybrid_docs)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Hybrid Search Index\n", + "\n", + "Optionally, if you have created a Postgres table with a tsv_column, you can create an index." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "await vs_hybrid.aapply_hybrid_search_index()" + ] + }, { "cell_type": "markdown", "metadata": {}, From 91286b0b275453ce70498fa123b611afdd83616d Mon Sep 17 00:00:00 2001 From: "open-swe[bot]" <215916821+open-swe[bot]@users.noreply.github.com> Date: Thu, 11 Sep 2025 21:53:35 -0400 Subject: [PATCH 2/5] chore(infra): issue template updates (#32910) Fixes: #32909 --------- Co-authored-by: Mason Daugherty --- .github/ISSUE_TEMPLATE/bug-report.yml | 13 +- .github/ISSUE_TEMPLATE/config.yml | 4 +- .github/ISSUE_TEMPLATE/feature-request.yml | 118 +++++++++++++++++ .github/ISSUE_TEMPLATE/task.yml | 143 +++++++++++++++++++++ 4 files changed, 272 insertions(+), 6 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/feature-request.yml create mode 100644 .github/ISSUE_TEMPLATE/task.yml diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index 039fe97d51a..2d617d495ef 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -1,6 +1,7 @@ name: "\U0001F41B Bug Report" description: Report a bug in LangChain. To report a security issue, please instead use the security option below. For questions, please use the LangChain forum. labels: ["bug"] +type: bug body: - type: markdown attributes: @@ -13,9 +14,7 @@ body: if there's another way to solve your problem: * [LangChain Forum](https://forum.langchain.com/), - * [LangChain Github Issues](https://github.com/langchain-ai/langchain/issues?q=is%3Aissue), - * [LangChain documentation with the integrated search](https://python.langchain.com/docs/get_started/introduction), - * [LangChain how-to guides](https://python.langchain.com/docs/how_to/), + * [LangChain documentation with the integrated search](https://docs.langchain.com/oss/python/langchain/overview), * [API Reference](https://python.langchain.com/api_reference/), * [LangChain ChatBot](https://chat.langchain.com/) * [GitHub search](https://github.com/langchain-ai/langchain), @@ -25,7 +24,7 @@ body: label: Checked other resources description: Please confirm and check all the following options. options: - - label: This is a bug, not a usage question. For questions, please use the LangChain Forum (https://forum.langchain.com/). + - label: This is a bug, not a usage question. required: true - label: I added a clear and descriptive title that summarizes this issue. required: true @@ -35,6 +34,8 @@ body: required: true - label: The bug is not resolved by updating to the latest stable version of LangChain (or the specific integration package). required: true + - label: This is not related to the langchain-community package. + required: true - label: I read what a minimal reproducible example is (https://stackoverflow.com/help/minimal-reproducible-example). required: true - label: I posted a self-contained, minimal, reproducible example. A maintainer can copy it and run it AS IS. @@ -118,3 +119,7 @@ body: python -m langchain_core.sys_info validations: required: true + + + + diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index c17d356634a..fd62bf94353 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,9 +1,9 @@ blank_issues_enabled: false version: 2.1 contact_links: - - name: Documentation + - name: 📚 Documentation url: https://github.com/langchain-ai/docs/issues/new?template=langchain.yml about: Report an issue related to the LangChain documentation - - name: LangChain Forum + - name: 💬 LangChain Forum url: https://forum.langchain.com/ about: General community discussions and support diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml new file mode 100644 index 00000000000..067cc9621b3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request.yml @@ -0,0 +1,118 @@ +name: "✨ Feature Request" +description: Request a new feature or enhancement for LangChain. For questions, please use the LangChain forum. +labels: ["feature request"] +type: feature +body: + - type: markdown + attributes: + value: | + Thank you for taking the time to request a new feature. + + Use this to request NEW FEATURES or ENHANCEMENTS in LangChain. For bug reports, please use the bug report template. For usage questions and general design questions, please use the [LangChain Forum](https://forum.langchain.com/). + + Relevant links to check before filing a feature request to see if your request has already been made or + if there's another way to achieve what you want: + + * [LangChain Forum](https://forum.langchain.com/), + * [LangChain documentation with the integrated search](https://docs.langchain.com/oss/python/langchain/overview), + * [API Reference](https://python.langchain.com/api_reference/), + * [LangChain ChatBot](https://chat.langchain.com/) + * [GitHub search](https://github.com/langchain-ai/langchain), + - type: checkboxes + id: checks + attributes: + label: Checked other resources + description: Please confirm and check all the following options. + options: + - label: This is a feature request, not a bug report or usage question. + required: true + - label: I added a clear and descriptive title that summarizes the feature request. + required: true + - label: I used the GitHub search to find a similar feature request and didn't find it. + required: true + - label: I checked the LangChain documentation and API reference to see if this feature already exists. + required: true + - label: This is not related to the langchain-community package. + required: true + - type: textarea + id: feature-description + validations: + required: true + attributes: + label: Feature Description + description: | + Please provide a clear and concise description of the feature you would like to see added to LangChain. + + What specific functionality are you requesting? Be as detailed as possible. + placeholder: | + I would like LangChain to support... + + This feature would allow users to... + - type: textarea + id: use-case + validations: + required: true + attributes: + label: Use Case + description: | + Describe the specific use case or problem this feature would solve. + + Why do you need this feature? What problem does it solve for you or other users? + placeholder: | + I'm trying to build an application that... + + Currently, I have to work around this by... + + This feature would help me/users to... + - type: textarea + id: proposed-solution + validations: + required: false + attributes: + label: Proposed Solution + description: | + If you have ideas about how this feature could be implemented, please describe them here. + + This is optional but can be helpful for maintainers to understand your vision. + placeholder: | + I think this could be implemented by... + + The API could look like... + + ```python + # Example of how the feature might work + ``` + - type: textarea + id: alternatives + validations: + required: false + attributes: + label: Alternatives Considered + description: | + Have you considered any alternative solutions or workarounds? + + What other approaches have you tried or considered? + placeholder: | + I've tried using... + + Alternative approaches I considered: + 1. ... + 2. ... + + But these don't work because... + - type: textarea + id: additional-context + validations: + required: false + attributes: + label: Additional Context + description: | + Add any other context, screenshots, examples, or references that would help explain your feature request. + placeholder: | + Related issues: #... + + Similar features in other libraries: + - ... + + Additional context or examples: + - ... diff --git a/.github/ISSUE_TEMPLATE/task.yml b/.github/ISSUE_TEMPLATE/task.yml new file mode 100644 index 00000000000..d738d94da5c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/task.yml @@ -0,0 +1,143 @@ +name: "📋 Task" +description: Create a task for project management and tracking by LangChain maintainers. If you are not a maintainer, please use other templates or the forum. +labels: ["task"] +type: task +body: + - type: markdown + attributes: + value: | + Thanks for creating a task to help organize LangChain development! 🚀 + + This template is for **maintainer tasks** such as project management, development planning, refactoring, documentation updates, and other organizational work. + + If you are not a LangChain maintainer or were not asked directly by a maintainer to create a task, then please start the conversation on the [LangChain Forum](https://forum.langchain.com/) instead or use the appropriate bug report or feature request templates. + + You are a LangChain maintainer if you maintain any of the packages inside of the LangChain repository + or are a regular contributor to LangChain with previous merged pull requests. + - type: checkboxes + id: maintainer + attributes: + label: Maintainer task + description: Confirm that you are allowed to create a task here. + options: + - label: I am a LangChain maintainer, or was asked directly by a LangChain maintainer to create a task here. + required: true + - type: dropdown + id: task-type + attributes: + label: Task Type + description: What type of task is this? + options: + - Project Management + - Documentation + - Refactoring + - Testing + - CI/CD + - Release Management + - Code Cleanup + - Performance Optimization + - Security + - Other + validations: + required: true + - type: dropdown + id: priority + attributes: + label: Priority + description: What is the priority level of this task? + options: + - Low + - Medium + - High + - Critical + validations: + required: true + - type: textarea + id: task-description + attributes: + label: Task Description + description: | + Provide a clear and detailed description of the task. + + What needs to be done? Be specific about the scope and requirements. + placeholder: | + This task involves... + + The goal is to... + + Specific requirements: + - ... + - ... + validations: + required: true + - type: textarea + id: acceptance-criteria + attributes: + label: Acceptance Criteria + description: | + Define the criteria that must be met for this task to be considered complete. + + What are the specific deliverables or outcomes expected? + placeholder: | + This task will be complete when: + - [ ] ... + - [ ] ... + - [ ] ... + validations: + required: true + - type: textarea + id: context + attributes: + label: Context and Background + description: | + Provide any relevant context, background information, or links to related issues/PRs. + + Why is this task needed? What problem does it solve? + placeholder: | + Background: + - ... + + Related issues/PRs: + - #... + + Additional context: + - ... + validations: + required: false + - type: textarea + id: implementation-notes + attributes: + label: Implementation Notes + description: | + Any specific implementation details, constraints, or considerations for this task. + + Are there any technical requirements or limitations to be aware of? + placeholder: | + Technical considerations: + - ... + + Constraints: + - ... + + Suggested approach: + - ... + validations: + required: false + - type: textarea + id: dependencies + attributes: + label: Dependencies + description: | + List any dependencies or blockers for this task. + + Are there other tasks, issues, or external factors that need to be completed first? + placeholder: | + This task depends on: + - [ ] Issue #... + - [ ] PR #... + - [ ] External dependency: ... + + Blocked by: + - ... + validations: + required: false From 31f641a11ff84108e6c25c63f8dc71df80afd027 Mon Sep 17 00:00:00 2001 From: Mason Daugherty Date: Thu, 11 Sep 2025 22:00:44 -0400 Subject: [PATCH 3/5] chore(infra): issue template updates (#32911) --- .github/ISSUE_TEMPLATE/privileged.yml | 7 +--- .github/ISSUE_TEMPLATE/task.yml | 58 ++------------------------- 2 files changed, 4 insertions(+), 61 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/privileged.yml b/.github/ISSUE_TEMPLATE/privileged.yml index 8950090d6d2..7bc320a22a4 100644 --- a/.github/ISSUE_TEMPLATE/privileged.yml +++ b/.github/ISSUE_TEMPLATE/privileged.yml @@ -4,12 +4,7 @@ body: - type: markdown attributes: value: | - Thanks for your interest in LangChain! 🚀 - - If you are not a LangChain maintainer or were not asked directly by a maintainer to create an issue, then please start the conversation on the [LangChain Forum](https://forum.langchain.com/) instead. - - You are a LangChain maintainer if you maintain any of the packages inside of the LangChain repository - or are a regular contributor to LangChain with previous merged pull requests. + If you are not a LangChain maintainer, employee, or were not asked directly by a maintainer to create an issue, then please start the conversation on the [LangChain Forum](https://forum.langchain.com/) instead. - type: checkboxes id: privileged attributes: diff --git a/.github/ISSUE_TEMPLATE/task.yml b/.github/ISSUE_TEMPLATE/task.yml index d738d94da5c..fb958a04da4 100644 --- a/.github/ISSUE_TEMPLATE/task.yml +++ b/.github/ISSUE_TEMPLATE/task.yml @@ -1,19 +1,16 @@ name: "📋 Task" description: Create a task for project management and tracking by LangChain maintainers. If you are not a maintainer, please use other templates or the forum. -labels: ["task"] +labels: ["task", "infra"] type: task body: - type: markdown attributes: value: | - Thanks for creating a task to help organize LangChain development! 🚀 + Thanks for creating a task to help organize LangChain development. This template is for **maintainer tasks** such as project management, development planning, refactoring, documentation updates, and other organizational work. - If you are not a LangChain maintainer or were not asked directly by a maintainer to create a task, then please start the conversation on the [LangChain Forum](https://forum.langchain.com/) instead or use the appropriate bug report or feature request templates. - - You are a LangChain maintainer if you maintain any of the packages inside of the LangChain repository - or are a regular contributor to LangChain with previous merged pull requests. + If you are not a LangChain maintainer or were not asked directly by a maintainer to create a task, then please start the conversation on the [LangChain Forum](https://forum.langchain.com/) instead or use the appropriate bug report or feature request templates on the previous page. - type: checkboxes id: maintainer attributes: @@ -22,36 +19,6 @@ body: options: - label: I am a LangChain maintainer, or was asked directly by a LangChain maintainer to create a task here. required: true - - type: dropdown - id: task-type - attributes: - label: Task Type - description: What type of task is this? - options: - - Project Management - - Documentation - - Refactoring - - Testing - - CI/CD - - Release Management - - Code Cleanup - - Performance Optimization - - Security - - Other - validations: - required: true - - type: dropdown - id: priority - attributes: - label: Priority - description: What is the priority level of this task? - options: - - Low - - Medium - - High - - Critical - validations: - required: true - type: textarea id: task-description attributes: @@ -104,25 +71,6 @@ body: - ... validations: required: false - - type: textarea - id: implementation-notes - attributes: - label: Implementation Notes - description: | - Any specific implementation details, constraints, or considerations for this task. - - Are there any technical requirements or limitations to be aware of? - placeholder: | - Technical considerations: - - ... - - Constraints: - - ... - - Suggested approach: - - ... - validations: - required: false - type: textarea id: dependencies attributes: From 338d3d2795e37c4e9b45c5a672c7bf6fa7a7a074 Mon Sep 17 00:00:00 2001 From: Mason Daugherty Date: Thu, 11 Sep 2025 22:02:14 -0400 Subject: [PATCH 4/5] chore: remove `infra` tag from task issue template (#32912) --- .github/ISSUE_TEMPLATE/task.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/task.yml b/.github/ISSUE_TEMPLATE/task.yml index fb958a04da4..e055813a029 100644 --- a/.github/ISSUE_TEMPLATE/task.yml +++ b/.github/ISSUE_TEMPLATE/task.yml @@ -1,6 +1,6 @@ name: "📋 Task" description: Create a task for project management and tracking by LangChain maintainers. If you are not a maintainer, please use other templates or the forum. -labels: ["task", "infra"] +labels: ["task"] type: task body: - type: markdown From 649d8a8223034348e517bd2af143720074fa9790 Mon Sep 17 00:00:00 2001 From: Mason Daugherty Date: Thu, 11 Sep 2025 23:19:55 -0400 Subject: [PATCH 5/5] test(anthropic): enable VCR for web fetch test (#32913) The API issues have been resolved; no longer xfailing --- .../tests/cassettes/test_web_fetch.yaml.gz | Bin 0 -> 51123 bytes .../tests/integration_tests/test_chat_models.py | 7 ++++--- 2 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 libs/partners/anthropic/tests/cassettes/test_web_fetch.yaml.gz diff --git a/libs/partners/anthropic/tests/cassettes/test_web_fetch.yaml.gz b/libs/partners/anthropic/tests/cassettes/test_web_fetch.yaml.gz new file mode 100644 index 0000000000000000000000000000000000000000..56db91c639ce8d856f4cee28010cab642d75233c GIT binary patch literal 51123 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 None: ) -# @pytest.mark.vcr -@pytest.mark.xfail(reason="Citations broken in Anthropic API; all other features work") +@pytest.mark.vcr def test_web_fetch() -> None: """Note: this is a beta feature. @@ -999,7 +998,9 @@ def test_web_fetch() -> None: citation_response = llm_with_citations.invoke([citation_message]) citation_results = [ - block for block in citation_response.content if isinstance(block, dict) + block + for block in citation_response.content + if isinstance(block, dict) and block.get("type") == "web_fetch_tool_result" ] assert len(citation_results) == 1 # Since max_uses=1 citation_result = citation_results[0]