From 2901794ed6753544997dad5984c22e6e456ee91e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 25 Jun 2026 20:58:50 +0000 Subject: [PATCH 01/15] chore(deps): update dependency langchain-core to v1 [security] --- pyproject.toml | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 2f730758..22c47000 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ authors = [ {name = "Google LLC", email = "googleapis-packages@google.com"} ] dependencies = [ - "langchain-core>=0.1.25, <1.0.0", + "langchain-core>=1.2.22, <1.2.23", "langchain-community>=0.0.18, <1.0.0", "google-cloud-spanner>=3.41.0, <4.0.0", "pydantic>=2.9.1, <3.0.0" diff --git a/requirements.txt b/requirements.txt index 02a1e008..61508874 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ google-cloud-spanner==3.55.0 -langchain-core==0.3.71 +langchain-core==1.2.22 langchain-community==0.3.27 pydantic==2.11.7 From 5ccb61650cf99b76c289061b200bb2fd4447afe0 Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Thu, 25 Jun 2026 14:01:11 -0700 Subject: [PATCH 02/15] Update pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 22c47000..aa652ecb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ authors = [ {name = "Google LLC", email = "googleapis-packages@google.com"} ] dependencies = [ - "langchain-core>=1.2.22, <1.2.23", + "langchain-core>=0.1.25, <2.0.0", "langchain-community>=0.0.18, <1.0.0", "google-cloud-spanner>=3.41.0, <4.0.0", "pydantic>=2.9.1, <3.0.0" From 8402507f6311a812f7cce44278d6a088b08e2fe0 Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Fri, 26 Jun 2026 08:58:28 -0700 Subject: [PATCH 03/15] refactor: migrate from community dep --- .flake8 | 4 + pyproject.toml | 3 +- requirements.txt | 3 +- src/langchain_google_spanner/__init__.py | 10 ++- src/langchain_google_spanner/graph_store.py | 85 ++++++++++++++++--- src/langchain_google_spanner/loader.py | 2 +- src/langchain_google_spanner/vector_store.py | 2 +- tests/integration/test_spanner_graph_qa.py | 8 +- .../test_spanner_graph_retriever.py | 8 +- tests/integration/test_spanner_graph_store.py | 9 +- .../integration/test_spanner_vector_store.py | 35 +++++--- 11 files changed, 133 insertions(+), 36 deletions(-) create mode 100644 .flake8 diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000..cc2b2432 --- /dev/null +++ b/.flake8 @@ -0,0 +1,4 @@ +[flake8] +max-line-length = 88 +extend-ignore = E203, W503, E501, E741, E731 +exclude = .git,.venv,.nox,build,dist diff --git a/pyproject.toml b/pyproject.toml index aa652ecb..8ac3a021 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,8 +9,7 @@ authors = [ {name = "Google LLC", email = "googleapis-packages@google.com"} ] dependencies = [ - "langchain-core>=0.1.25, <2.0.0", - "langchain-community>=0.0.18, <1.0.0", + "langchain-core>=0.3.0, <2.0.0", "google-cloud-spanner>=3.41.0, <4.0.0", "pydantic>=2.9.1, <3.0.0" ] diff --git a/requirements.txt b/requirements.txt index 61508874..461bccbd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ google-cloud-spanner==3.55.0 -langchain-core==1.2.22 -langchain-community==0.3.27 +langchain-core==0.3.86 pydantic==2.11.7 diff --git a/src/langchain_google_spanner/__init__.py b/src/langchain_google_spanner/__init__.py index 2b8b9c92..b6d3da75 100644 --- a/src/langchain_google_spanner/__init__.py +++ b/src/langchain_google_spanner/__init__.py @@ -18,7 +18,12 @@ SpannerGraphTextToGQLRetriever, SpannerGraphVectorContextRetriever, ) -from langchain_google_spanner.graph_store import SpannerGraphStore +from langchain_google_spanner.graph_store import ( + GraphDocument, + Node, + Relationship, + SpannerGraphStore, +) from langchain_google_spanner.vector_store import ( DistanceStrategy, QueryParameters, @@ -37,6 +42,9 @@ "SpannerDocumentSaver", "SpannerLoader", "SpannerGraphStore", + "GraphDocument", + "Node", + "Relationship", "SpannerGraphQAChain", "TableColumn", "SecondaryIndex", diff --git a/src/langchain_google_spanner/graph_store.py b/src/langchain_google_spanner/graph_store.py index 93b42ec0..0f913cc1 100644 --- a/src/langchain_google_spanner/graph_store.py +++ b/src/langchain_google_spanner/graph_store.py @@ -18,17 +18,80 @@ import re import string from abc import ABC, abstractmethod -from typing import Any, Dict, Generator, Iterable, List, Mapping, Optional, Tuple, Union +from typing import Any, Dict, Generator, Iterable, List, Optional, Tuple, Union from google.cloud import spanner from google.cloud.spanner_v1 import JsonObject, param_types -from langchain_community.graphs.graph_document import GraphDocument, Node, Relationship -from langchain_community.graphs.graph_store import GraphStore +from langchain_core.load.serializable import Serializable +from pydantic import Field +from langchain_core.documents import Document from requests.structures import CaseInsensitiveDict from .type_utils import TypeUtility from .version import __version__ + +class Node(Serializable): + """Represents a node in a graph with associated properties.""" + + id: Union[str, int] + type: str = "Node" + properties: Dict[str, Any] = Field(default_factory=dict) + + +class Relationship(Serializable): + """Represents a directed relationship between two nodes in a graph.""" + + source: Node + target: Node + type: str + properties: Dict[str, Any] = Field(default_factory=dict) + + +class GraphDocument(Serializable): + """Represents a graph document consisting of nodes and relationships.""" + + nodes: List[Node] + relationships: List[Relationship] + source: Document + + +class GraphStore(ABC): + """Abstract class for graph operations.""" + + @property + @abstractmethod + def get_schema(self) -> str: + """Get the schema of the graph database.""" + pass + + @property + @abstractmethod + def get_structured_schema(self) -> Dict[str, Any]: + """Get the structured schema of the graph database.""" + pass + + @abstractmethod + def refresh_schema(self) -> None: + """Refresh the graph schema information.""" + pass + + @abstractmethod + def query(self, query: str, params: dict = {}) -> List[Dict[str, Any]]: + """Query the graph.""" + pass + + @abstractmethod + def add_graph_documents( + self, + graph_documents: List[GraphDocument], + include_source: bool = False, + baseEntityLabel: bool = False, + ) -> None: + """Add graph documents to the graph.""" + pass + + MUTATION_BATCH_SIZE = 1000 DEFAULT_DDL_TIMEOUT = 300 NODE_KIND = "NODE" @@ -472,7 +535,7 @@ def from_dynamic_edges( def add_nodes( self, name: str, nodes: List[Node] - ) -> Generator[Tuple[str, Tuple[str], List[List[Any]]], None, None]: + ) -> Generator[Tuple[str, Tuple[str, ...], List[List[Any]]], None, None]: """Builds the data required to add a list of nodes to Spanner. Args: @@ -493,7 +556,7 @@ def add_nodes( # Group changes by columns: this avoids overwriting columns that aren't # specified. - rows_by_columns: Dict[Tuple[str], List[List[Any]]] = {} + rows_by_columns: Dict[Tuple[str, ...], List[List[Any]]] = {} for node in nodes: properties = node.properties.copy() properties[ElementSchema.NODE_KEY_COLUMN_NAME] = node.id @@ -521,7 +584,7 @@ def add_nodes( def add_edges( self, name: str, edges: List[Relationship] - ) -> Generator[Tuple[str, Tuple[str], List[List[Any]]], None, None]: + ) -> Generator[Tuple[str, Tuple[str, ...], List[List[Any]]], None, None]: """Builds the data required to add a list of edges to Spanner. Args: @@ -542,7 +605,7 @@ def add_edges( # Group changes by columns: this avoids overwriting columns that aren't # specified. - rows_by_columns: Dict[Tuple[str], List[List[Any]]] = {} + rows_by_columns: Dict[Tuple[str, ...], List[List[Any]]] = {} for edge in edges: properties = edge.properties.copy() properties[ElementSchema.NODE_KEY_COLUMN_NAME] = edge.source.id @@ -1140,7 +1203,7 @@ def _update_labels_and_properties(self, element_schema: ElementSchema) -> None: def add_nodes( self, name: str, nodes: List[Node] - ) -> Generator[Tuple[str, Tuple[str], List[List[Any]]], None, None]: + ) -> Generator[Tuple[str, Tuple[str, ...], List[List[Any]]], None, None]: """Builds the data required to add a list of nodes to Spanner. Args: @@ -1161,7 +1224,7 @@ def add_nodes( def add_edges( self, name: str, edges: List[Relationship] - ) -> Generator[Tuple[str, Tuple[str], List[List[Any]]], None, None]: + ) -> Generator[Tuple[str, Tuple[str, ...], List[List[Any]]], None, None]: """Builds the data required to add a list of edges to Spanner. Args: @@ -1210,7 +1273,7 @@ def apply_ddls(self, ddls: List[str], options: Dict[str, Any] = {}) -> None: @abstractmethod def insert_or_update( - self, table: str, columns: Tuple[str], values: List[List[Any]] + self, table: str, columns: Tuple[str, ...], values: List[List[Any]] ) -> None: """Insert or update the table. @@ -1269,7 +1332,7 @@ def apply_ddls(self, ddls: List[str], options: Dict[str, Any] = {}) -> None: return op.result(options.get("timeout", DEFAULT_DDL_TIMEOUT)) def insert_or_update( - self, table: str, columns: Tuple[str], values: List[List[Any]] + self, table: str, columns: Tuple[str, ...], values: List[List[Any]] ) -> None: for i in range(0, len(values), MUTATION_BATCH_SIZE): value_batch = values[i : i + MUTATION_BATCH_SIZE] diff --git a/src/langchain_google_spanner/loader.py b/src/langchain_google_spanner/loader.py index 5bc82860..9ffee3fa 100644 --- a/src/langchain_google_spanner/loader.py +++ b/src/langchain_google_spanner/loader.py @@ -19,7 +19,7 @@ from google.cloud.spanner import Client, KeySet # type: ignore from google.cloud.spanner_admin_database_v1.types import DatabaseDialect # type: ignore -from langchain_community.document_loaders.base import BaseLoader +from langchain_core.document_loaders import BaseLoader from langchain_core.documents import Document from .version import __version__ diff --git a/src/langchain_google_spanner/vector_store.py b/src/langchain_google_spanner/vector_store.py index 038b5f7e..57a42163 100644 --- a/src/langchain_google_spanner/vector_store.py +++ b/src/langchain_google_spanner/vector_store.py @@ -25,7 +25,7 @@ from google.cloud import spanner # type: ignore from google.cloud.spanner_admin_database_v1.types import DatabaseDialect from google.cloud.spanner_v1 import JsonObject, param_types -from langchain_community.vectorstores.utils import maximal_marginal_relevance +from langchain_core.vectorstores.utils import maximal_marginal_relevance from langchain_core.documents import Document from langchain_core.embeddings import Embeddings from langchain_core.vectorstores import VectorStore diff --git a/tests/integration/test_spanner_graph_qa.py b/tests/integration/test_spanner_graph_qa.py index a0778ef2..9c02be69 100644 --- a/tests/integration/test_spanner_graph_qa.py +++ b/tests/integration/test_spanner_graph_qa.py @@ -19,12 +19,16 @@ import pytest from google.cloud import spanner from langchain.evaluation import load_evaluator -from langchain_community.graphs.graph_document import GraphDocument, Node, Relationship +from langchain_google_spanner import ( + GraphDocument, + Node, + Relationship, + SpannerGraphStore, +) from langchain_core.documents import Document from langchain_google_vertexai import ChatVertexAI, VertexAIEmbeddings from langchain_google_spanner.graph_qa import SpannerGraphQAChain -from langchain_google_spanner.graph_store import SpannerGraphStore project_id = os.environ["PROJECT_ID"] instance_id = os.environ["INSTANCE_ID"] diff --git a/tests/integration/test_spanner_graph_retriever.py b/tests/integration/test_spanner_graph_retriever.py index b44d2d54..aa7ed2c7 100644 --- a/tests/integration/test_spanner_graph_retriever.py +++ b/tests/integration/test_spanner_graph_retriever.py @@ -18,7 +18,12 @@ import pytest from google.cloud import spanner -from langchain_community.graphs.graph_document import GraphDocument, Node, Relationship +from langchain_google_spanner import ( + GraphDocument, + Node, + Relationship, + SpannerGraphStore, +) from langchain_core.documents import Document from langchain_google_vertexai import ChatVertexAI, VertexAIEmbeddings @@ -26,7 +31,6 @@ SpannerGraphTextToGQLRetriever, SpannerGraphVectorContextRetriever, ) -from langchain_google_spanner.graph_store import SpannerGraphStore project_id = os.environ["PROJECT_ID"] instance_id = os.environ["INSTANCE_ID"] diff --git a/tests/integration/test_spanner_graph_store.py b/tests/integration/test_spanner_graph_store.py index 271dba30..06ddf052 100644 --- a/tests/integration/test_spanner_graph_store.py +++ b/tests/integration/test_spanner_graph_store.py @@ -22,10 +22,13 @@ import pytest from google.cloud.spanner import Client # type: ignore from google.cloud.spanner_v1 import JsonObject -from langchain_community.graphs.graph_document import GraphDocument, Node, Relationship from langchain_core.documents import Document - -from langchain_google_spanner import SpannerGraphStore +from langchain_google_spanner import ( + GraphDocument, + Node, + Relationship, + SpannerGraphStore, +) project_id = os.environ["PROJECT_ID"] instance_id = os.environ["INSTANCE_ID"] diff --git a/tests/integration/test_spanner_vector_store.py b/tests/integration/test_spanner_vector_store.py index 41bd4901..bfadeb8f 100644 --- a/tests/integration/test_spanner_vector_store.py +++ b/tests/integration/test_spanner_vector_store.py @@ -20,8 +20,10 @@ import pytest from google.cloud.spanner import Client # type: ignore -from langchain_community.document_loaders import RecursiveUrlLoader -from langchain_community.embeddings import FakeEmbeddings +from typing import Any, Iterator, List +from langchain_core.document_loaders import BaseLoader +from langchain_core.documents import Document +from langchain_core.embeddings import FakeEmbeddings from langchain_google_spanner.vector_store import ( # type: ignore DistanceStrategy, @@ -31,6 +33,23 @@ VectorSearchIndex, ) + +class FakeLoader(BaseLoader): + def __init__(self, *args: Any, **kwargs: Any) -> None: + pass + + def load(self) -> List[Document]: + return [ + Document( + page_content="Testing the langchain integration with spanner", + metadata={"title": "Hacker News: Article 1"}, + ) + ] + + def lazy_load(self) -> Iterator[Document]: + yield from self.load() + + project_id = os.environ["PROJECT_ID"] instance_id = os.environ["INSTANCE_ID"] google_database = os.environ["GOOGLE_DATABASE"] @@ -249,9 +268,7 @@ def setup_database(self, client): ], ) - loader = RecursiveUrlLoader( - "https://news.ycombinator.com/item?id=1", max_depth=1 - ) + loader = FakeLoader("https://news.ycombinator.com/item?id=1", max_depth=1) embeddings = FakeEmbeddings(size=3) @@ -461,9 +478,7 @@ def setup_database(self, client): ], ) - loader = RecursiveUrlLoader( - "https://news.ycombinator.com/item?id=1", max_depth=1 - ) + loader = FakeLoader("https://news.ycombinator.com/item?id=1", max_depth=1) embeddings = FakeEmbeddings(size=title_vector_size) def cleanup_db(): @@ -681,9 +696,7 @@ def setup_database(self, client): ], ) - loader = RecursiveUrlLoader( - "https://news.ycombinator.com/item?id=1", max_depth=1 - ) + loader = FakeLoader("https://news.ycombinator.com/item?id=1", max_depth=1) embeddings = FakeEmbeddings(size=3) yield loader, embeddings From 0eee600391d1fcc133a6d3c1f4be98a7989e456d Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Fri, 26 Jun 2026 09:32:19 -0700 Subject: [PATCH 04/15] fix --- pyproject.toml | 1 + requirements.txt | 3 ++- src/langchain_google_spanner/graph_qa.py | 2 +- src/langchain_google_spanner/graph_retriever.py | 2 +- src/langchain_google_spanner/graph_store.py | 2 +- src/langchain_google_spanner/vector_store.py | 2 +- tests/integration/test_spanner_graph_qa.py | 6 +++--- tests/integration/test_spanner_graph_retriever.py | 6 +++--- tests/integration/test_spanner_graph_store.py | 1 + tests/integration/test_spanner_vector_store.py | 3 +-- 10 files changed, 15 insertions(+), 13 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8ac3a021..aad45817 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,6 +10,7 @@ authors = [ ] dependencies = [ "langchain-core>=0.3.0, <2.0.0", + "langchain-classic>=1.0.8 <2.0.0", "google-cloud-spanner>=3.41.0, <4.0.0", "pydantic>=2.9.1, <3.0.0" ] diff --git a/requirements.txt b/requirements.txt index 461bccbd..3a376d45 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ google-cloud-spanner==3.55.0 -langchain-core==0.3.86 +langchain-core==1.4.8 +langchain-classic==1.0.8 pydantic==2.11.7 diff --git a/src/langchain_google_spanner/graph_qa.py b/src/langchain_google_spanner/graph_qa.py index d595f509..0563e72a 100644 --- a/src/langchain_google_spanner/graph_qa.py +++ b/src/langchain_google_spanner/graph_qa.py @@ -16,7 +16,7 @@ from typing import Any, Dict, List, Optional -from langchain.chains.base import Chain +from langchain_classic.chains.base import Chain from langchain_core.callbacks import CallbackManagerForChainRun from langchain_core.language_models import BaseLanguageModel from langchain_core.output_parsers import JsonOutputParser, StrOutputParser diff --git a/src/langchain_google_spanner/graph_retriever.py b/src/langchain_google_spanner/graph_retriever.py index 5bf502bc..fa2d911a 100644 --- a/src/langchain_google_spanner/graph_retriever.py +++ b/src/langchain_google_spanner/graph_retriever.py @@ -15,7 +15,6 @@ import json from typing import Any, List, Optional -from langchain.schema.retriever import BaseRetriever from langchain_core.callbacks import CallbackManagerForRetrieverRun from langchain_core.documents import Document from langchain_core.embeddings import Embeddings @@ -25,6 +24,7 @@ from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import FewShotPromptTemplate from langchain_core.prompts.prompt import PromptTemplate +from langchain_core.retrievers import BaseRetriever from langchain_core.runnables import RunnableSequence from langchain_core.vectorstores import InMemoryVectorStore from pydantic import Field diff --git a/src/langchain_google_spanner/graph_store.py b/src/langchain_google_spanner/graph_store.py index 0f913cc1..9c61620f 100644 --- a/src/langchain_google_spanner/graph_store.py +++ b/src/langchain_google_spanner/graph_store.py @@ -22,9 +22,9 @@ from google.cloud import spanner from google.cloud.spanner_v1 import JsonObject, param_types +from langchain_core.documents import Document from langchain_core.load.serializable import Serializable from pydantic import Field -from langchain_core.documents import Document from requests.structures import CaseInsensitiveDict from .type_utils import TypeUtility diff --git a/src/langchain_google_spanner/vector_store.py b/src/langchain_google_spanner/vector_store.py index 57a42163..b039e471 100644 --- a/src/langchain_google_spanner/vector_store.py +++ b/src/langchain_google_spanner/vector_store.py @@ -25,10 +25,10 @@ from google.cloud import spanner # type: ignore from google.cloud.spanner_admin_database_v1.types import DatabaseDialect from google.cloud.spanner_v1 import JsonObject, param_types -from langchain_core.vectorstores.utils import maximal_marginal_relevance from langchain_core.documents import Document from langchain_core.embeddings import Embeddings from langchain_core.vectorstores import VectorStore +from langchain_core.vectorstores.utils import maximal_marginal_relevance from .version import __version__ diff --git a/tests/integration/test_spanner_graph_qa.py b/tests/integration/test_spanner_graph_qa.py index 9c02be69..aec40328 100644 --- a/tests/integration/test_spanner_graph_qa.py +++ b/tests/integration/test_spanner_graph_qa.py @@ -19,15 +19,15 @@ import pytest from google.cloud import spanner from langchain.evaluation import load_evaluator +from langchain_core.documents import Document +from langchain_google_vertexai import ChatVertexAI, VertexAIEmbeddings + from langchain_google_spanner import ( GraphDocument, Node, Relationship, SpannerGraphStore, ) -from langchain_core.documents import Document -from langchain_google_vertexai import ChatVertexAI, VertexAIEmbeddings - from langchain_google_spanner.graph_qa import SpannerGraphQAChain project_id = os.environ["PROJECT_ID"] diff --git a/tests/integration/test_spanner_graph_retriever.py b/tests/integration/test_spanner_graph_retriever.py index aa7ed2c7..904c7774 100644 --- a/tests/integration/test_spanner_graph_retriever.py +++ b/tests/integration/test_spanner_graph_retriever.py @@ -18,15 +18,15 @@ import pytest from google.cloud import spanner +from langchain_core.documents import Document +from langchain_google_vertexai import ChatVertexAI, VertexAIEmbeddings + from langchain_google_spanner import ( GraphDocument, Node, Relationship, SpannerGraphStore, ) -from langchain_core.documents import Document -from langchain_google_vertexai import ChatVertexAI, VertexAIEmbeddings - from langchain_google_spanner.graph_retriever import ( SpannerGraphTextToGQLRetriever, SpannerGraphVectorContextRetriever, diff --git a/tests/integration/test_spanner_graph_store.py b/tests/integration/test_spanner_graph_store.py index 06ddf052..824c1349 100644 --- a/tests/integration/test_spanner_graph_store.py +++ b/tests/integration/test_spanner_graph_store.py @@ -23,6 +23,7 @@ from google.cloud.spanner import Client # type: ignore from google.cloud.spanner_v1 import JsonObject from langchain_core.documents import Document + from langchain_google_spanner import ( GraphDocument, Node, diff --git a/tests/integration/test_spanner_vector_store.py b/tests/integration/test_spanner_vector_store.py index bfadeb8f..7a4c9234 100644 --- a/tests/integration/test_spanner_vector_store.py +++ b/tests/integration/test_spanner_vector_store.py @@ -16,11 +16,10 @@ import os import sys import uuid -from typing import Dict +from typing import Any, Dict, Iterator, List import pytest from google.cloud.spanner import Client # type: ignore -from typing import Any, Iterator, List from langchain_core.document_loaders import BaseLoader from langchain_core.documents import Document from langchain_core.embeddings import FakeEmbeddings From 1f870f9c577603ac231cb6a1504474c058aaea9b Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Fri, 26 Jun 2026 09:34:59 -0700 Subject: [PATCH 05/15] fix --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index aad45817..d0c94a7f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ authors = [ ] dependencies = [ "langchain-core>=0.3.0, <2.0.0", - "langchain-classic>=1.0.8 <2.0.0", + "langchain-classic>=1.0.8, <2.0.0", "google-cloud-spanner>=3.41.0, <4.0.0", "pydantic>=2.9.1, <3.0.0" ] From 681e8da2f31fbf9537e098ca2d4afe41e324a63f Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Fri, 26 Jun 2026 09:51:20 -0700 Subject: [PATCH 06/15] fix --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d0c94a7f..707e386c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,7 +31,7 @@ version = {attr = "langchain_google_spanner.version.__version__"} [project.urls] Homepage = "https://github.com/googleapis/langchain-google-spanner-python" Repository = "https://github.com/googleapis/langchain-google-spanner-python.git" -"Bug Tracker" = "https://github.com/googleapis/langchain-google-spanner-python/issues" +"Bug Tracker" = "https://langchain-google-vertexaigithub.com/googleapis/langchain-google-spanner-python/issues" Changelog = "https://github.com/googleapis/langchain-google-spanner-python/blob/main/CHANGELOG.md" [project.optional-dependencies] @@ -50,7 +50,7 @@ test = [ "pytest==8.4.1", "pytest-asyncio==0.26.0", "pytest-cov==5.0.0", - "langchain_google_vertexai==2.0.27" + "langchain_google_vertexai==3.2.4" ] [build-system] From acaeefcdce9c484baff6961c0462592c5d8b22f5 Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Fri, 26 Jun 2026 10:13:42 -0700 Subject: [PATCH 07/15] fix --- pyproject.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 707e386c..fdee73a4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,7 +50,8 @@ test = [ "pytest==8.4.1", "pytest-asyncio==0.26.0", "pytest-cov==5.0.0", - "langchain_google_vertexai==3.2.4" + "langchain_google_vertexai==3.2.4", + "langchain"==1.3.11 ] [build-system] From 57199c5157d315819576a5f8c51254919379f6cc Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Fri, 26 Jun 2026 10:21:43 -0700 Subject: [PATCH 08/15] fix --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index fdee73a4..bea4568d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -51,7 +51,7 @@ test = [ "pytest-asyncio==0.26.0", "pytest-cov==5.0.0", "langchain_google_vertexai==3.2.4", - "langchain"==1.3.11 + "langchain==1.3.11" ] [build-system] From 7a9c18884b410ee6e99349785a9f4e3ca4368123 Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Fri, 26 Jun 2026 10:33:13 -0700 Subject: [PATCH 09/15] fix --- tests/integration/test_spanner_graph_qa.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/test_spanner_graph_qa.py b/tests/integration/test_spanner_graph_qa.py index aec40328..f0276f37 100644 --- a/tests/integration/test_spanner_graph_qa.py +++ b/tests/integration/test_spanner_graph_qa.py @@ -18,7 +18,7 @@ import pytest from google.cloud import spanner -from langchain.evaluation import load_evaluator +from langchain_classic.evaluation import load_evaluator from langchain_core.documents import Document from langchain_google_vertexai import ChatVertexAI, VertexAIEmbeddings From 93cdbb4741fdde564d345c81b945f71b47915eff Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Fri, 26 Jun 2026 10:51:16 -0700 Subject: [PATCH 10/15] add numpy --- .github/sync-repo-settings.yaml | 2 +- DEVELOPER.md | 6 +++--- README.rst | 2 +- integration.cloudbuild.yaml | 2 +- pyproject.toml | 15 ++++++++------- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/.github/sync-repo-settings.yaml b/.github/sync-repo-settings.yaml index 0dde89bb..85f03251 100644 --- a/.github/sync-repo-settings.yaml +++ b/.github/sync-repo-settings.yaml @@ -27,10 +27,10 @@ branchProtectionRules: requiredStatusCheckContexts: - "cla/google" - "lint" - - "integration-test-pr-py39 (langchain-spanner-testing)" - "integration-test-pr-py310 (langchain-spanner-testing)" - "integration-test-pr-py311 (langchain-spanner-testing)" - "integration-test-pr-py312 (langchain-spanner-testing)" + - "integration-test-pr-py313 (langchain-spanner-testing)" - "conventionalcommits.org" - "header-check" # - Add required status checks like presubmit tests diff --git a/DEVELOPER.md b/DEVELOPER.md index 24d33a9e..4eaa91f7 100644 --- a/DEVELOPER.md +++ b/DEVELOPER.md @@ -34,11 +34,11 @@ These tests are registered as required tests in `.github/sync-repo-settings.yaml #### Trigger Setup -Cloud Build triggers (for Python versions 3.9 to 3.11) were created with the following specs: +Cloud Build triggers (for Python versions 3.10 to 3.13) were created with the following specs: ```YAML name: integration-test-pr-py39 -description: Run integration tests on PR for Python 3.9 +description: Run integration tests on PR for Python 3.10 filename: integration.cloudbuild.yaml github: name: langchain-google-spanner-python @@ -55,7 +55,7 @@ substitutions: _INSTANCE_ID: _PG_DATABASE: _GOOGLE_DATABASE: - _VERSION: "3.9" + _VERSION: "3.10" ``` Use `gcloud builds triggers import --source=trigger.yaml` to create triggers via the command line diff --git a/README.rst b/README.rst index e4f78002..fd9d54f9 100644 --- a/README.rst +++ b/README.rst @@ -44,7 +44,7 @@ With `virtualenv`_, it’s possible to install this library without needing syst Supported Python Versions ^^^^^^^^^^^^^^^^^^^^^^^^^ -Python >= 3.9 +Python >= 3.10 Mac/Linux ^^^^^^^^^ diff --git a/integration.cloudbuild.yaml b/integration.cloudbuild.yaml index e27c8a02..bfe38fb9 100644 --- a/integration.cloudbuild.yaml +++ b/integration.cloudbuild.yaml @@ -38,7 +38,7 @@ substitutions: _INSTANCE_ID: test-instance _GOOGLE_DATABASE: test-gsql-db _PG_DATABASE: test-pgsql-db - _VERSION: "3.9" + _VERSION: "3.10" options: dynamicSubstitutions: true diff --git a/pyproject.toml b/pyproject.toml index bea4568d..36dccbe5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ dynamic = ["version"] description = "LangChain integrations for Google Cloud Spanner" readme = "README.rst" license = {file = "LICENSE"} -requires-python = ">=3.9" +requires-python = ">=3.10" authors = [ {name = "Google LLC", email = "googleapis-packages@google.com"} ] @@ -12,17 +12,19 @@ dependencies = [ "langchain-core>=0.3.0, <2.0.0", "langchain-classic>=1.0.8, <2.0.0", "google-cloud-spanner>=3.41.0, <4.0.0", - "pydantic>=2.9.1, <3.0.0" + "pydantic>=2.9.1, <3.0.0", + "numpy>=1.24.4, <3.0.0; python_version >= '3.11'", + "numpy>=1.24.4, <=2.2.6; python_version == '3.10'", ] classifiers = [ "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", ] [tool.setuptools.dynamic] @@ -50,8 +52,7 @@ test = [ "pytest==8.4.1", "pytest-asyncio==0.26.0", "pytest-cov==5.0.0", - "langchain_google_vertexai==3.2.4", - "langchain==1.3.11" + "langchain_google_vertexai==3.2.4" ] [build-system] @@ -59,13 +60,13 @@ requires = ["setuptools"] build-backend = "setuptools.build_meta" [tool.black] -target-version = ['py39'] +target-version = ['py310'] [tool.isort] profile = "black" [tool.mypy] -python_version = 3.9 +python_version = "3.10" warn_unused_configs = true exclude = [ From f69c239bfeb83ab2d793e668ee660b691f79c670 Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Fri, 26 Jun 2026 11:05:38 -0700 Subject: [PATCH 11/15] add numpy --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 36dccbe5..50a1c4cf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,7 +33,7 @@ version = {attr = "langchain_google_spanner.version.__version__"} [project.urls] Homepage = "https://github.com/googleapis/langchain-google-spanner-python" Repository = "https://github.com/googleapis/langchain-google-spanner-python.git" -"Bug Tracker" = "https://langchain-google-vertexaigithub.com/googleapis/langchain-google-spanner-python/issues" +"Bug Tracker" = "https://github.com/googleapis/langchain-google-spanner-python/issues" Changelog = "https://github.com/googleapis/langchain-google-spanner-python/blob/main/CHANGELOG.md" [project.optional-dependencies] From 01d288e386ba849876fbdbc354e36a1e0e48a027 Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Fri, 26 Jun 2026 11:12:59 -0700 Subject: [PATCH 12/15] update model --- docs/graph_qa_chain.ipynb | 2 +- docs/graph_rag.ipynb | 506 +++++++++--------- docs/graph_store.ipynb | 4 +- tests/integration/test_spanner_graph_qa.py | 2 +- .../test_spanner_graph_retriever.py | 2 +- 5 files changed, 258 insertions(+), 258 deletions(-) diff --git a/docs/graph_qa_chain.ipynb b/docs/graph_qa_chain.ipynb index af222656..71b89ac6 100644 --- a/docs/graph_qa_chain.ipynb +++ b/docs/graph_qa_chain.ipynb @@ -499,7 +499,7 @@ "from IPython.core.display import HTML\n", "\n", "# Initialize llm object\n", - "llm = ChatVertexAI(model=\"gemini-2.0-flash-001\", temperature=0)\n", + "llm = ChatVertexAI(model=\"gemini-3.1-flash-lite\", temperature=0)\n", "\n", "# Initialize GraphQAChain\n", "chain = SpannerGraphQAChain.from_llm(\n", diff --git a/docs/graph_rag.ipynb b/docs/graph_rag.ipynb index 60c8aef0..c08abe03 100644 --- a/docs/graph_rag.ipynb +++ b/docs/graph_rag.ipynb @@ -1,32 +1,10 @@ { - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.5" - }, - "colab": { - "provenance": [], - "toc_visible": true - } - }, "cells": [ { "cell_type": "markdown", + "metadata": { + "id": "7VBkjcqNNxEd" + }, "source": [ "# Google Spanner\n", "\n", @@ -37,13 +15,13 @@ "Learn more about the package on [GitHub](https://github.com/googleapis/langchain-google-spanner-python/).\n", "\n", "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/googleapis/langchain-google-spanner-python/blob/main/docs/graph_rag.ipynb)" - ], - "metadata": { - "id": "7VBkjcqNNxEd" - } + ] }, { "cell_type": "markdown", + "metadata": { + "id": "HEAGYTPgNydh" + }, "source": [ "## Before You Begin\n", "\n", @@ -53,91 +31,91 @@ " * [Enable the Cloud Spanner API](https://console.cloud.google.com/flows/enableapi?apiid=spanner.googleapis.com)\n", " * [Create a Spanner instance](https://cloud.google.com/spanner/docs/create-manage-instances)\n", " * [Create a Spanner database](https://cloud.google.com/spanner/docs/create-manage-databases)" - ], - "metadata": { - "id": "HEAGYTPgNydh" - } + ] }, { "cell_type": "markdown", + "metadata": { + "id": "cboPIg-yOcxS" + }, "source": [ "### πŸ¦œπŸ”— Library Installation\n", "The integration lives in its own `langchain-google-spanner` package, so we need to install it." - ], - "metadata": { - "id": "cboPIg-yOcxS" - } + ] }, { "cell_type": "code", - "source": [ - "%pip install --upgrade --quiet langchain-google-spanner langchain-google-vertexai langchain-experimental spanner-graph-notebook" - ], + "execution_count": null, "metadata": { "id": "AOWh6QKYVdDp" }, - "execution_count": null, - "outputs": [] + "outputs": [], + "source": [ + "%pip install --upgrade --quiet langchain-google-spanner langchain-google-vertexai langchain-experimental spanner-graph-notebook" + ] }, { "cell_type": "markdown", - "source": [], "metadata": { "id": "L06vBzPq7gz6" - } + }, + "source": [] }, { "cell_type": "markdown", - "source": [ - "**Colab only:** Uncomment the following cell to restart the kernel or use the button to restart the kernel. For Vertex AI Workbench you can restart the terminal using the button on top." - ], "metadata": { "id": "M7MqpDhkOiP-" - } + }, + "source": [ + "**Colab only:** Uncomment the following cell to restart the kernel or use the button to restart the kernel. For Vertex AI Workbench you can restart the terminal using the button on top." + ] }, { "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "xzgVZv0POj17" + }, + "outputs": [], "source": [ "## Automatically restart kernel after installs so that your environment can access the new packages\n", "import IPython\n", "\n", "app = IPython.Application.instance()\n", "app.kernel.do_shutdown(True)" - ], - "metadata": { - "id": "xzgVZv0POj17" - }, - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", + "metadata": { + "id": "zfIhwIryOls1" + }, "source": [ "### πŸ” Authentication\n", "Authenticate to Google Cloud as the IAM user logged into this notebook in order to access your Google Cloud Project.\n", "\n", "* If you are using Colab to run this notebook, use the cell below and continue.\n", "* If you are using Vertex AI Workbench, check out the setup instructions [here](https://github.com/GoogleCloudPlatform/generative-ai/tree/main/setup-env)." - ], - "metadata": { - "id": "zfIhwIryOls1" - } + ] }, { "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "EWOkHI7XOna2" + }, + "outputs": [], "source": [ "from google.colab import auth\n", "\n", "auth.authenticate_user()" - ], - "metadata": { - "id": "EWOkHI7XOna2" - }, - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", + "metadata": { + "id": "6xHXneICOpsB" + }, "source": [ "### ☁ Set Your Google Cloud Project\n", "Set your Google Cloud project so that you can leverage Google Cloud resources within this notebook.\n", @@ -147,13 +125,16 @@ "* Run `gcloud config list`.\n", "* Run `gcloud projects list`.\n", "* See the support page: [Locate the project ID](https://support.google.com/googleapi/answer/7014113)." - ], - "metadata": { - "id": "6xHXneICOpsB" - } + ] }, { "cell_type": "code", + "execution_count": null, + "metadata": { + "cellView": "form", + "id": "hF0481BGOsS8" + }, + "outputs": [], "source": [ "# @markdown Please fill in the value below with your Google Cloud project ID and then run the cell.\n", "\n", @@ -162,71 +143,68 @@ "# Set the project id\n", "!gcloud config set project {PROJECT_ID}\n", "%env GOOGLE_CLOUD_PROJECT={PROJECT_ID}" - ], - "metadata": { - "id": "hF0481BGOsS8", - "cellView": "form" - }, - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", + "metadata": { + "id": "4TiC0RbhOwUu" + }, "source": [ "### πŸ’‘ API Enablement\n", "The `langchain-google-spanner` package requires that you [enable the Spanner API](https://console.cloud.google.com/flows/enableapi?apiid=spanner.googleapis.com) in your Google Cloud Project." - ], - "metadata": { - "id": "4TiC0RbhOwUu" - } + ] }, { "cell_type": "code", - "source": [ - "# enable Spanner API\n", - "!gcloud services enable spanner.googleapis.com" - ], + "execution_count": null, "metadata": { "id": "9f3fJd5eOyRr" }, - "execution_count": null, - "outputs": [] + "outputs": [], + "source": [ + "# enable Spanner API\n", + "!gcloud services enable spanner.googleapis.com" + ] }, { "cell_type": "markdown", - "source": [ - "## Usage" - ], "metadata": { "id": "k5pxMMiMOzt7" - } + }, + "source": [ + "## Usage" + ] }, { "cell_type": "markdown", + "metadata": { + "id": "mtDbLU5sO2iA" + }, "source": [ "### Set Spanner database values\n", "Find your database values, in the [Spanner Instances page](https://console.cloud.google.com/spanner?_ga=2.223735448.2062268965.1707700487-2088871159.1707257687)." - ], - "metadata": { - "id": "mtDbLU5sO2iA" - } + ] }, { "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "C-I8VTIcO442" + }, + "outputs": [], "source": [ "# @title Set Your Values Here { display-mode: \"form\" }\n", "INSTANCE = \"my-instance\" # @param {type: \"string\"}\n", "DATABASE = \"my-database\" # @param {type: \"string\"}\n", "GRAPH_NAME = \"my_graph\" # @param {type: \"string\"}" - ], - "metadata": { - "id": "C-I8VTIcO442" - }, - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", + "metadata": { + "id": "kpAv-tpcO_iL" + }, "source": [ "### SpannerGraphStore\n", "\n", @@ -235,13 +213,15 @@ "1. a Spanner instance id;\n", "2. a Spanner database id belongs to the above instance id;\n", "3. a Spanner graph name used to create a graph in the above database." - ], - "metadata": { - "id": "kpAv-tpcO_iL" - } + ] }, { "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "u589YapWQFb8" + }, + "outputs": [], "source": [ "from langchain_google_spanner import SpannerGraphStore\n", "\n", @@ -250,25 +230,25 @@ " database_id=DATABASE,\n", " graph_name=GRAPH_NAME,\n", ")" - ], - "metadata": { - "id": "u589YapWQFb8" - }, - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", + "metadata": { + "id": "G7-Pe2ADQlNJ" + }, "source": [ "#### Add Graph Documents\n", "To add graph documents in the graph store." - ], - "metadata": { - "id": "G7-Pe2ADQlNJ" - } + ] }, { "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "Do7bCkyJagok" + }, + "outputs": [], "source": [ "# @title Load Documents\n", "import os\n", @@ -290,15 +270,15 @@ " os.path.join(path, directory), glob=\"**/*.txt\", loader_cls=TextLoader\n", " )\n", " document_lists.append(loader.load())" - ], - "metadata": { - "id": "Do7bCkyJagok" - }, - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "fP7XNu3aPl5c" + }, + "outputs": [], "source": [ "# @title Extract Nodes and Edges\n", "import copy\n", @@ -318,7 +298,7 @@ " print()\n", "\n", "\n", - "llm = ChatVertexAI(model=\"gemini-2.0-flash\", temperature=0)\n", + "llm = ChatVertexAI(model=\"gemini-3.1-flash-lite\", temperature=0)\n", "llm_transformer = LLMGraphTransformer(\n", " llm=llm,\n", " allowed_nodes=[\"Category\", \"Segment\", \"Tag\", \"Product\", \"Bundle\", \"Deal\"],\n", @@ -354,15 +334,15 @@ " )\n", "\n", "print_graph(graph_documents)" - ], - "metadata": { - "id": "fP7XNu3aPl5c" - }, - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "G9OAYF0spDTF" + }, + "outputs": [], "source": [ "# @title Post process extracted nodes and edges\n", "# Apply your domain knowledge to clean up and make desired fixes to the\n", @@ -450,15 +430,15 @@ "fix_directions(\"HAS_DEAL\", \"Deal\")\n", "fix_directions(\"IN_BUNDLE\", \"Bundle\")\n", "print_graph(graph_documents)" - ], - "metadata": { - "id": "G9OAYF0spDTF" - }, - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "lMXvOpRbZdau" + }, + "outputs": [], "source": [ "# @title Load data to Spanner Graph\n", "# Uncomment the line below, if you want to cleanup from\n", @@ -466,48 +446,48 @@ "# BeWARE - THIS COULD REMOVE DATA FROM YOUR DATABASE !!!\n", "graph_store.cleanup()\n", "graph_store.add_graph_documents(graph_documents)" - ], - "metadata": { - "id": "lMXvOpRbZdau" - }, - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", - "source": [ - "### Visualization" - ], "metadata": { "id": "28aMSrBbEvps" - } + }, + "source": [ + "### Visualization" + ] }, { "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "Xg14hrOhIL5e" + }, + "outputs": [], "source": [ "# @title Graph and Schema\n", "%%spanner_graph --project {PROJECT_ID} --instance {INSTANCE} --database {DATABASE}\n", "GRAPH my_graph #Change this to your graph name\n", "MATCH p = ()->()\n", "RETURN TO_JSON(p) AS path_json" - ], - "metadata": { - "id": "Xg14hrOhIL5e" - }, - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "markdown", - "source": [ - "## GraphRAG flow using Spanner Graph" - ], "metadata": { "id": "zsPxCSzXhuoB" - } + }, + "source": [ + "## GraphRAG flow using Spanner Graph" + ] }, { "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "19Amjrge71Ue" + }, + "outputs": [], "source": [ "# @title Question Answering Prompt\n", "from langchain_core.output_parsers import StrOutputParser\n", @@ -562,65 +542,25 @@ " input_variables=[\"question\", \"graph_schema\", \"context\"],\n", ")\n", "\n", - "llm = ChatVertexAI(model=\"gemini-2.0-flash\", temperature=0)\n", + "llm = ChatVertexAI(model=\"gemini-3.1-flash-lite\", temperature=0)\n", "\n", "chain = prompt | llm | StrOutputParser()" - ], - "metadata": { - "id": "19Amjrge71Ue" - }, - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "code", - "source": [ - "# @title GraphRAG using Vector Search and Graph Expansion\n", - "import textwrap\n", - "from langchain_google_spanner import SpannerGraphVectorContextRetriever\n", - "from langchain_google_vertexai import VertexAIEmbeddings\n", - "\n", - "\n", - "def use_node_vector_retriever(\n", - " question, graph_store, embedding_service, label_expr, expand_by_hops\n", - "):\n", - " retriever = SpannerGraphVectorContextRetriever.from_params(\n", - " graph_store=graph_store,\n", - " embedding_service=embedding_service,\n", - " label_expr=label_expr,\n", - " expand_by_hops=expand_by_hops,\n", - " top_k=1,\n", - " k=10,\n", - " )\n", - " context = format_docs(retriever.invoke(question))\n", - " return context\n", - "\n", - "\n", - "embedding_service = VertexAIEmbeddings(model_name=\"text-embedding-004\")\n", - "question = \"Give me recommendations for a beginner drone\"\n", - "context = use_node_vector_retriever(\n", - " question, graph_store, embedding_service, label_expr=\"Product\", expand_by_hops=1\n", - ")\n", - "\n", - "answer = chain.invoke(\n", - " {\"question\": question, \"graph_schema\": graph_store.get_schema, \"context\": context}\n", - ")\n", - "\n", - "print(\"\\n\\nAnswer:\\n\")\n", - "print(textwrap.fill(answer, width=80))" - ], + "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, - "outputId": "e7946a49-b470-4ded-8d77-28270a33d90f", - "id": "VK8e9vTK-nJz" + "id": "VK8e9vTK-nJz", + "outputId": "e7946a49-b470-4ded-8d77-28270a33d90f" }, - "execution_count": null, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "Context Retrieved: \n", "\n", @@ -788,32 +728,84 @@ "an accessory. The Skyhawk Zephyr 2.0 is an upgrade.\n" ] } + ], + "source": [ + "# @title GraphRAG using Vector Search and Graph Expansion\n", + "import textwrap\n", + "from langchain_google_spanner import SpannerGraphVectorContextRetriever\n", + "from langchain_google_vertexai import VertexAIEmbeddings\n", + "\n", + "\n", + "def use_node_vector_retriever(\n", + " question, graph_store, embedding_service, label_expr, expand_by_hops\n", + "):\n", + " retriever = SpannerGraphVectorContextRetriever.from_params(\n", + " graph_store=graph_store,\n", + " embedding_service=embedding_service,\n", + " label_expr=label_expr,\n", + " expand_by_hops=expand_by_hops,\n", + " top_k=1,\n", + " k=10,\n", + " )\n", + " context = format_docs(retriever.invoke(question))\n", + " return context\n", + "\n", + "\n", + "embedding_service = VertexAIEmbeddings(model_name=\"text-embedding-004\")\n", + "question = \"Give me recommendations for a beginner drone\"\n", + "context = use_node_vector_retriever(\n", + " question, graph_store, embedding_service, label_expr=\"Product\", expand_by_hops=1\n", + ")\n", + "\n", + "answer = chain.invoke(\n", + " {\"question\": question, \"graph_schema\": graph_store.get_schema, \"context\": context}\n", + ")\n", + "\n", + "print(\"\\n\\nAnswer:\\n\")\n", + "print(textwrap.fill(answer, width=80))" ] }, { "cell_type": "markdown", - "source": [ - "## Compare with Conventional RAG" - ], "metadata": { "id": "-FDDqobRE-8D" - } + }, + "source": [ + "## Compare with Conventional RAG" + ] }, { "cell_type": "code", + "execution_count": null, + "metadata": { + "cellView": "form", + "id": "YfRxVV8_PCSh" + }, + "outputs": [], "source": [ "# @title Define table name\n", "TABLE_NAME = \"my_table\" # @param {\"type\":\"string\"}" - ], - "metadata": { - "id": "YfRxVV8_PCSh", - "cellView": "form" - }, - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "urR34wZTFDr_", + "outputId": "13a8976e-92ec-4289-cf95-83b041b0e1a3" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Waiting for operation to complete...\n" + ] + } + ], "source": [ "# @title Setup and load data for vector search\n", "from langchain_google_spanner import SpannerVectorStore\n", @@ -851,27 +843,15 @@ "# Initialize table and load data\n", "embeddings = VertexAIEmbeddings(model_name=\"text-embedding-004\")\n", "load_data_for_vector_search(splits)" - ], - "metadata": { - "id": "urR34wZTFDr_", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "13a8976e-92ec-4289-cf95-83b041b0e1a3" - }, - "execution_count": null, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Waiting for operation to complete...\n" - ] - } ] }, { "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "vs9-lZiUIC07" + }, + "outputs": [], "source": [ "# @title Create a conventional RAG chain\n", "\n", @@ -922,24 +902,11 @@ " | llm\n", " | StrOutputParser()\n", ")" - ], - "metadata": { - "id": "vs9-lZiUIC07" - }, - "execution_count": null, - "outputs": [] + ] }, { "cell_type": "code", - "source": [ - "# @title Run conventional RAG chain\n", - "import textwrap\n", - "\n", - "question = \"I am looking for an beginner drone. Please give me some recommendations.\"\n", - "resp = rag_chain.invoke(question)\n", - "print(\"\\n\\nRag Response:\\n\")\n", - "print(textwrap.fill(resp, width=80))" - ], + "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -947,11 +914,10 @@ "id": "lkYxWBvvIn4K", "outputId": "6e0b259f-4a45-4662-bbf8-476294d85e0f" }, - "execution_count": null, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "Context Retrieved: \n", "\n", @@ -993,31 +959,65 @@ "construction. It also has a deal price of $109.99 (Original Price: $129.99).\n" ] } + ], + "source": [ + "# @title Run conventional RAG chain\n", + "import textwrap\n", + "\n", + "question = \"I am looking for an beginner drone. Please give me some recommendations.\"\n", + "resp = rag_chain.invoke(question)\n", + "print(\"\\n\\nRag Response:\\n\")\n", + "print(textwrap.fill(resp, width=80))" ] }, { "cell_type": "markdown", + "metadata": { + "id": "pM7TmfI0TEFy" + }, "source": [ "## Clean up the graph\n", "\n", "> USE IT WITH CAUTION!\n", "\n", "Clean up all the nodes/edges in your graph and remove your graph definition." - ], - "metadata": { - "id": "pM7TmfI0TEFy" - } + ] }, { "cell_type": "code", - "source": [ - "graph_store.cleanup()" - ], + "execution_count": null, "metadata": { "id": "UQWq4-sITOgl" }, - "execution_count": null, - "outputs": [] + "outputs": [], + "source": [ + "graph_store.cleanup()" + ] } - ] + ], + "metadata": { + "colab": { + "provenance": [], + "toc_visible": true + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.5" + } + }, + "nbformat": 4, + "nbformat_minor": 0 } diff --git a/docs/graph_store.ipynb b/docs/graph_store.ipynb index a2237711..e0207657 100644 --- a/docs/graph_store.ipynb +++ b/docs/graph_store.ipynb @@ -201,7 +201,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -225,7 +225,7 @@ "from langchain_experimental.graph_transformers import LLMGraphTransformer\n", "from langchain_google_vertexai.llms import VertexAI\n", "\n", - "llm = VertexAI(model_name=\"gemini-2.0-flash-001\")\n", + "llm = VertexAI(model_name=\"gemini-3.1-flash-lite\")\n", "llm_transformer = LLMGraphTransformer(\n", " llm=llm, allowed_nodes=[\"Person\", \"Company\", \"Product\"]\n", ")\n", diff --git a/tests/integration/test_spanner_graph_qa.py b/tests/integration/test_spanner_graph_qa.py index f0276f37..cba085b8 100644 --- a/tests/integration/test_spanner_graph_qa.py +++ b/tests/integration/test_spanner_graph_qa.py @@ -41,7 +41,7 @@ def random_string(num_char=3): def get_llm(): llm = ChatVertexAI( - model="gemini-2.0-flash-001", + model="gemini-3.1-flash-lite", temperature=0, ) return llm diff --git a/tests/integration/test_spanner_graph_retriever.py b/tests/integration/test_spanner_graph_retriever.py index 904c7774..3bff0ede 100644 --- a/tests/integration/test_spanner_graph_retriever.py +++ b/tests/integration/test_spanner_graph_retriever.py @@ -43,7 +43,7 @@ def random_string(num_char=3): def get_llm(): llm = ChatVertexAI( - model="gemini-2.0-flash-001", + model="gemini-3.1-flash-lite", temperature=0, ) return llm From f22c6d5dfb748fe52e3bb4f8d7d5df12a0ee23c2 Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Fri, 26 Jun 2026 12:20:57 -0700 Subject: [PATCH 13/15] add location --- tests/integration/test_spanner_graph_qa.py | 1 + tests/integration/test_spanner_graph_retriever.py | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/integration/test_spanner_graph_qa.py b/tests/integration/test_spanner_graph_qa.py index cba085b8..df09b57b 100644 --- a/tests/integration/test_spanner_graph_qa.py +++ b/tests/integration/test_spanner_graph_qa.py @@ -42,6 +42,7 @@ def random_string(num_char=3): def get_llm(): llm = ChatVertexAI( model="gemini-3.1-flash-lite", + location="global", temperature=0, ) return llm diff --git a/tests/integration/test_spanner_graph_retriever.py b/tests/integration/test_spanner_graph_retriever.py index 3bff0ede..732bdc1e 100644 --- a/tests/integration/test_spanner_graph_retriever.py +++ b/tests/integration/test_spanner_graph_retriever.py @@ -44,6 +44,7 @@ def random_string(num_char=3): def get_llm(): llm = ChatVertexAI( model="gemini-3.1-flash-lite", + location="global", temperature=0, ) return llm From 0129b0f58f719a05b26ecc3bf0f60410c0911fcc Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Fri, 26 Jun 2026 13:57:41 -0700 Subject: [PATCH 14/15] fix tests --- README.rst | 13 +++++----- docs/graph_rag.ipynb | 20 +++++++++------- docs/vector_store.ipynb | 8 +++---- pyproject.toml | 3 ++- samples/langchain_quick_start.ipynb | 24 +++++++++---------- tests/integration/test_spanner_graph_qa.py | 5 ++-- .../test_spanner_graph_retriever.py | 5 ++-- 7 files changed, 42 insertions(+), 36 deletions(-) diff --git a/README.rst b/README.rst index fd9d54f9..4c13ad0e 100644 --- a/README.rst +++ b/README.rst @@ -73,15 +73,15 @@ Use a vector store to store embedded data and perform vector search. .. code-block:: python - from langchain_google_spanner import SpannerVectorstore - from langchain.embeddings import VertexAIEmbeddings + from langchain_google_spanner import SpannerVectorStore + from langchain_google_genai import GoogleGenerativeAIEmbeddings - embeddings_service = VertexAIEmbeddings(model_name="textembedding-gecko@003") + embeddings_service = GoogleGenerativeAIEmbeddings(model="textembedding-gecko@003") vectorstore = SpannerVectorStore( instance_id="my-instance", database_id="my-database", table_name="my-table", - embeddings=embedding_service + embeddings=embeddings_service ) See the full `Vector Store`_ tutorial. @@ -207,7 +207,8 @@ Use ``SpannerGraphVectorContextRetriever`` to perform vector search on embedding .. code:: python from langchain_google_spanner import SpannerGraphStore, SpannerGraphVectorContextRetriever - from langchain_google_vertexai import ChatVertexAI, VertexAIEmbeddings + from langchain_google_vertexai import ChatVertexAI + from langchain_google_genai import GoogleGenerativeAIEmbeddings graph = SpannerGraphStore( @@ -215,7 +216,7 @@ Use ``SpannerGraphVectorContextRetriever`` to perform vector search on embedding database_id="my-database", graph_name="my_graph", ) - embedding_service = VertexAIEmbeddings(model_name="text-embedding-004") + embedding_service = GoogleGenerativeAIEmbeddings(model="gemini-embedding-2") retriever = SpannerGraphVectorContextRetriever.from_params( graph_store=graph, embedding_service=embedding_service, diff --git a/docs/graph_rag.ipynb b/docs/graph_rag.ipynb index c08abe03..811c83af 100644 --- a/docs/graph_rag.ipynb +++ b/docs/graph_rag.ipynb @@ -283,7 +283,8 @@ "# @title Extract Nodes and Edges\n", "import copy\n", "from langchain_experimental.graph_transformers import LLMGraphTransformer\n", - "from langchain_google_vertexai import ChatVertexAI, VertexAIEmbeddings\n", + "from langchain_google_vertexai import ChatVertexAI\n", + "from langchain_google_genai import GoogleGenerativeAIEmbeddings\n", "\n", "\n", "def print_graph(graph_documents):\n", @@ -325,7 +326,7 @@ " graph_documents.extend(llm_transformer.convert_to_graph_documents(document_list))\n", "\n", "# Add embeddings to the graph documents for Product nodes\n", - "embedding_service = VertexAIEmbeddings(model_name=\"text-embedding-004\")\n", + "embedding_service = GoogleGenerativeAIEmbeddings(model=\"gemini-embedding-2\")\n", "for graph_document in graph_documents:\n", " for node in graph_document.nodes:\n", " if \"features\" in node.properties:\n", @@ -492,7 +493,8 @@ "# @title Question Answering Prompt\n", "from langchain_core.output_parsers import StrOutputParser\n", "from langchain_core.prompts.prompt import PromptTemplate\n", - "from langchain_google_vertexai import ChatVertexAI, VertexAIEmbeddings\n", + "from langchain_google_vertexai import ChatVertexAI\n", + "from langchain_google_genai import GoogleGenerativeAIEmbeddings\n", "\n", "from IPython.display import Markdown\n", "import textwrap\n", @@ -733,7 +735,7 @@ "# @title GraphRAG using Vector Search and Graph Expansion\n", "import textwrap\n", "from langchain_google_spanner import SpannerGraphVectorContextRetriever\n", - "from langchain_google_vertexai import VertexAIEmbeddings\n", + "from langchain_google_genai import GoogleGenerativeAIEmbeddings\n", "\n", "\n", "def use_node_vector_retriever(\n", @@ -751,7 +753,7 @@ " return context\n", "\n", "\n", - "embedding_service = VertexAIEmbeddings(model_name=\"text-embedding-004\")\n", + "embedding_service = GoogleGenerativeAIEmbeddings(model=\"gemini-embedding-2\")\n", "question = \"Give me recommendations for a beginner drone\"\n", "context = use_node_vector_retriever(\n", " question, graph_store, embedding_service, label_expr=\"Product\", expand_by_hops=1\n", @@ -809,14 +811,14 @@ "source": [ "# @title Setup and load data for vector search\n", "from langchain_google_spanner import SpannerVectorStore\n", - "from langchain_google_vertexai import VertexAIEmbeddings\n", + "from langchain_google_genai import GoogleGenerativeAIEmbeddings\n", "from langchain_text_splitters import RecursiveCharacterTextSplitter\n", "\n", "import uuid\n", "\n", "\n", "def load_data_for_vector_search(splits):\n", - " embeddings = VertexAIEmbeddings(model_name=\"text-embedding-004\")\n", + " embeddings = GoogleGenerativeAIEmbeddings(model=\"gemini-embedding-2\")\n", "\n", " SpannerVectorStore.init_vector_store_table(\n", " instance_id=INSTANCE,\n", @@ -841,7 +843,7 @@ ")\n", "\n", "# Initialize table and load data\n", - "embeddings = VertexAIEmbeddings(model_name=\"text-embedding-004\")\n", + "embeddings = GoogleGenerativeAIEmbeddings(model=\"gemini-embedding-2\")\n", "load_data_for_vector_search(splits)" ] }, @@ -884,7 +886,7 @@ ")\n", "\n", "# Create a rag chain\n", - "embeddings = VertexAIEmbeddings(model_name=\"text-embedding-004\")\n", + "embeddings = GoogleGenerativeAIEmbeddings(model=\"gemini-embedding-2\")\n", "\n", "db = SpannerVectorStore(\n", " instance_id=INSTANCE,\n", diff --git a/docs/vector_store.ipynb b/docs/vector_store.ipynb index b5948543..52cd79cb 100644 --- a/docs/vector_store.ipynb +++ b/docs/vector_store.ipynb @@ -215,7 +215,7 @@ "### Create an embedding class instance\n", "\n", "You can use any [LangChain embeddings model](https://python.langchain.com/docs/integrations/text_embedding/).\n", - "You may need to enable Vertex AI API to use `VertexAIEmbeddings`. We recommend setting the embedding model's version for production, learn more about the [Text embeddings models](https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/text-embeddings)." + "You may need to enable Google Gen AI API or Vertex AI API to use `GoogleGenerativeAIEmbeddings`. We recommend setting the embedding model's version for production, learn more about the [Text embeddings models](https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/text-embeddings)." ] }, { @@ -234,10 +234,10 @@ "metadata": {}, "outputs": [], "source": [ - "from langchain_google_vertexai import VertexAIEmbeddings\n", + "from langchain_google_genai import GoogleGenerativeAIEmbeddings\n", "\n", - "embeddings = VertexAIEmbeddings(\n", - " model_name=\"textembedding-gecko@latest\", project=PROJECT_ID\n", + "embeddings = GoogleGenerativeAIEmbeddings(\n", + " model=\"textembedding-gecko@latest\", project=PROJECT_ID\n", ")" ] }, diff --git a/pyproject.toml b/pyproject.toml index 50a1c4cf..55a07abf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,7 +52,8 @@ test = [ "pytest==8.4.1", "pytest-asyncio==0.26.0", "pytest-cov==5.0.0", - "langchain_google_vertexai==3.2.4" + "langchain_google_vertexai==3.2.4", + "langchain-google-genai>=2.0.1" ] [build-system] diff --git a/samples/langchain_quick_start.ipynb b/samples/langchain_quick_start.ipynb index 0d9daed0..3f4799ac 100644 --- a/samples/langchain_quick_start.ipynb +++ b/samples/langchain_quick_start.ipynb @@ -878,7 +878,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": { "id": "Wo4-7EYCIFF9" }, @@ -896,11 +896,11 @@ } ], "source": [ - "from langchain_google_vertexai.embeddings import VertexAIEmbeddings\n", + "from langchain_google_genai import GoogleGenerativeAIEmbeddings\n", "\n", "# Initialize the embedding service. In this case we are using version 005 of Vertex AI's textembedding model. In general, it is good practice to specify the model version used.\n", - "embeddings_service = VertexAIEmbeddings(\n", - " model_name=\"text-embedding-005\", project=project_id\n", + "embeddings_service = GoogleGenerativeAIEmbeddings(\n", + " model=\"gemini-embedding-2\", project=project_id\n", ")\n", "\n", "\n", @@ -1066,7 +1066,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -1079,10 +1079,10 @@ } ], "source": [ - "from langchain_google_vertexai.embeddings import VertexAIEmbeddings\n", + "from langchain_google_genai import GoogleGenerativeAIEmbeddings\n", "\n", - "embeddings_service = VertexAIEmbeddings(\n", - " model_name=\"text-embedding-005\", project=project_id\n", + "embeddings_service = GoogleGenerativeAIEmbeddings(\n", + " model=\"gemini-embedding-2\", project=project_id\n", ")\n", "embedding_vector_size = 768\n", "vector_index_name = \"titles_index\"\n", @@ -1493,7 +1493,7 @@ }, { "cell_type": "code", - "execution_count": 40, + "execution_count": null, "metadata": { "id": "9ukjOO-sNQ8_" }, @@ -1526,7 +1526,7 @@ ], "source": [ "from langchain_google_vertexai import VertexAI\n", - "from langchain_google_vertexai.embeddings import VertexAIEmbeddings\n", + "from langchain_google_genai import GoogleGenerativeAIEmbeddings\n", "from langchain_core.messages import AIMessage, HumanMessage\n", "from langchain.chains import ConversationalRetrievalChain\n", "from langchain.memory import ConversationSummaryBufferMemory\n", @@ -1538,8 +1538,8 @@ ")\n", "\n", "# Intialize the embedding service\n", - "embeddings_service = VertexAIEmbeddings(\n", - " model_name=\"text-embedding-005\", project=project_id\n", + "embeddings_service = GoogleGenerativeAIEmbeddings(\n", + " model=\"gemini-embedding-2\", project=project_id\n", ")\n", "\n", "# Intialize the Vector Store\n", diff --git a/tests/integration/test_spanner_graph_qa.py b/tests/integration/test_spanner_graph_qa.py index df09b57b..f63546db 100644 --- a/tests/integration/test_spanner_graph_qa.py +++ b/tests/integration/test_spanner_graph_qa.py @@ -20,7 +20,8 @@ from google.cloud import spanner from langchain_classic.evaluation import load_evaluator from langchain_core.documents import Document -from langchain_google_vertexai import ChatVertexAI, VertexAIEmbeddings +from langchain_google_vertexai import ChatVertexAI +from langchain_google_genai import GoogleGenerativeAIEmbeddings from langchain_google_spanner import ( GraphDocument, @@ -51,7 +52,7 @@ def get_llm(): def get_evaluator(): return load_evaluator( "embedding_distance", - embeddings=VertexAIEmbeddings(model_name="text-embedding-004"), + embeddings=GoogleGenerativeAIEmbeddings(model="gemini-embedding-2"), ) diff --git a/tests/integration/test_spanner_graph_retriever.py b/tests/integration/test_spanner_graph_retriever.py index 732bdc1e..91856cc5 100644 --- a/tests/integration/test_spanner_graph_retriever.py +++ b/tests/integration/test_spanner_graph_retriever.py @@ -19,7 +19,8 @@ import pytest from google.cloud import spanner from langchain_core.documents import Document -from langchain_google_vertexai import ChatVertexAI, VertexAIEmbeddings +from langchain_google_vertexai import ChatVertexAI +from langchain_google_genai import GoogleGenerativeAIEmbeddings from langchain_google_spanner import ( GraphDocument, @@ -51,7 +52,7 @@ def get_llm(): def get_embedding(): - embeddings = VertexAIEmbeddings(model_name="text-embedding-004") + embeddings = GoogleGenerativeAIEmbeddings(model="gemini-embedding-2") return embeddings From 1057fdd8fc9228d0e7da550c96e98cbf5c5c0aa8 Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Fri, 26 Jun 2026 15:31:11 -0700 Subject: [PATCH 15/15] fix --- README.rst | 21 ++++++++++++------- docs/graph_qa_chain.ipynb | 8 +++---- docs/graph_rag.ipynb | 18 ++++++++-------- docs/vector_store.ipynb | 2 +- samples/langchain_quick_start.ipynb | 6 +++--- tests/integration/test_spanner_graph_qa.py | 9 ++++---- .../test_spanner_graph_retriever.py | 9 ++++---- 7 files changed, 41 insertions(+), 32 deletions(-) diff --git a/README.rst b/README.rst index 4c13ad0e..285626f7 100644 --- a/README.rst +++ b/README.rst @@ -76,7 +76,11 @@ Use a vector store to store embedded data and perform vector search. from langchain_google_spanner import SpannerVectorStore from langchain_google_genai import GoogleGenerativeAIEmbeddings - embeddings_service = GoogleGenerativeAIEmbeddings(model="textembedding-gecko@003") + embeddings_service = GoogleGenerativeAIEmbeddings( + model="textembedding-gecko@003", + project="my-project", + vertexai=True, + ) vectorstore = SpannerVectorStore( instance_id="my-instance", database_id="my-database", @@ -159,7 +163,7 @@ Use ``SpannerGraphQAChain`` for question answering over a graph stored in Spanne .. code:: python from langchain_google_spanner import SpannerGraphStore, SpannerGraphQAChain - from langchain_google_vertexai import ChatVertexAI + from langchain_google_genai import ChatGoogleGenerativeAI graph = SpannerGraphStore( @@ -167,7 +171,7 @@ Use ``SpannerGraphQAChain`` for question answering over a graph stored in Spanne database_id="my-database", graph_name="my_graph", ) - llm = ChatVertexAI() + llm = ChatGoogleGenerativeAI() chain = SpannerGraphQAChain.from_llm( llm, graph=graph, @@ -187,7 +191,7 @@ Use ``SpannerGraphTextToGQLRetriever`` to translate natural language question to .. code:: python from langchain_google_spanner import SpannerGraphStore, SpannerGraphTextToGQLRetriever - from langchain_google_vertexai import ChatVertexAI + from langchain_google_genai import ChatGoogleGenerativeAI graph = SpannerGraphStore( @@ -195,7 +199,7 @@ Use ``SpannerGraphTextToGQLRetriever`` to translate natural language question to database_id="my-database", graph_name="my_graph", ) - llm = ChatVertexAI() + llm = ChatGoogleGenerativeAI() retriever = SpannerGraphTextToGQLRetriever.from_params( graph_store=graph, llm=llm @@ -207,7 +211,6 @@ Use ``SpannerGraphVectorContextRetriever`` to perform vector search on embedding .. code:: python from langchain_google_spanner import SpannerGraphStore, SpannerGraphVectorContextRetriever - from langchain_google_vertexai import ChatVertexAI from langchain_google_genai import GoogleGenerativeAIEmbeddings @@ -216,7 +219,11 @@ Use ``SpannerGraphVectorContextRetriever`` to perform vector search on embedding database_id="my-database", graph_name="my_graph", ) - embedding_service = GoogleGenerativeAIEmbeddings(model="gemini-embedding-2") + embedding_service = GoogleGenerativeAIEmbeddings( + model="gemini-embedding-2", + project="my-project", + vertexai=True, + ) retriever = SpannerGraphVectorContextRetriever.from_params( graph_store=graph, embedding_service=embedding_service, diff --git a/docs/graph_qa_chain.ipynb b/docs/graph_qa_chain.ipynb index 71b89ac6..8d6f447e 100644 --- a/docs/graph_qa_chain.ipynb +++ b/docs/graph_qa_chain.ipynb @@ -273,7 +273,7 @@ "# @title Extract Nodes and Edges from text snippets\n", "from langchain_core.documents import Document\n", "from langchain_experimental.graph_transformers import LLMGraphTransformer\n", - "from langchain_google_vertexai import ChatVertexAI\n", + "from langchain_google_genai import ChatGoogleGenerativeAI\n", "from langchain_text_splitters import RecursiveCharacterTextSplitter\n", "\n", "text_snippets = [\n", @@ -333,7 +333,7 @@ "documents = [Document(page_content=t) for t in text_snippets]\n", "text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)\n", "splits = text_splitter.split_documents(documents)\n", - "llm = ChatVertexAI(model=\"gemini-1.5-flash\", temperature=0)\n", + "llm = ChatGoogleGenerativeAI(model=\"gemini-1.5-flash\", temperature=0)\n", "llm_transformer = LLMGraphTransformer(\n", " llm=llm,\n", " allowed_nodes=[\"College\", \"Deparatment\", \"Person\", \"Year\", \"Company\"],\n", @@ -495,11 +495,11 @@ "source": [ "from google.cloud import spanner\n", "from langchain_google_spanner import SpannerGraphQAChain\n", - "from langchain_google_vertexai import ChatVertexAI\n", + "from langchain_google_genai import ChatGoogleGenerativeAI\n", "from IPython.core.display import HTML\n", "\n", "# Initialize llm object\n", - "llm = ChatVertexAI(model=\"gemini-3.1-flash-lite\", temperature=0)\n", + "llm = ChatGoogleGenerativeAI(model=\"gemini-3.1-flash-lite\", temperature=0)\n", "\n", "# Initialize GraphQAChain\n", "chain = SpannerGraphQAChain.from_llm(\n", diff --git a/docs/graph_rag.ipynb b/docs/graph_rag.ipynb index 811c83af..34d213b5 100644 --- a/docs/graph_rag.ipynb +++ b/docs/graph_rag.ipynb @@ -283,7 +283,7 @@ "# @title Extract Nodes and Edges\n", "import copy\n", "from langchain_experimental.graph_transformers import LLMGraphTransformer\n", - "from langchain_google_vertexai import ChatVertexAI\n", + "from langchain_google_genai import ChatGoogleGenerativeAI\n", "from langchain_google_genai import GoogleGenerativeAIEmbeddings\n", "\n", "\n", @@ -299,7 +299,7 @@ " print()\n", "\n", "\n", - "llm = ChatVertexAI(model=\"gemini-3.1-flash-lite\", temperature=0)\n", + "llm = ChatGoogleGenerativeAI(model=\"gemini-3.1-flash-lite\", temperature=0)\n", "llm_transformer = LLMGraphTransformer(\n", " llm=llm,\n", " allowed_nodes=[\"Category\", \"Segment\", \"Tag\", \"Product\", \"Bundle\", \"Deal\"],\n", @@ -326,7 +326,7 @@ " graph_documents.extend(llm_transformer.convert_to_graph_documents(document_list))\n", "\n", "# Add embeddings to the graph documents for Product nodes\n", - "embedding_service = GoogleGenerativeAIEmbeddings(model=\"gemini-embedding-2\")\n", + "embedding_service = GoogleGenerativeAIEmbeddings(model=\"gemini-embedding-2\", project=PROJECT_ID, vertexai=True)\n", "for graph_document in graph_documents:\n", " for node in graph_document.nodes:\n", " if \"features\" in node.properties:\n", @@ -493,7 +493,7 @@ "# @title Question Answering Prompt\n", "from langchain_core.output_parsers import StrOutputParser\n", "from langchain_core.prompts.prompt import PromptTemplate\n", - "from langchain_google_vertexai import ChatVertexAI\n", + "from langchain_google_genai import ChatGoogleGenerativeAI\n", "from langchain_google_genai import GoogleGenerativeAIEmbeddings\n", "\n", "from IPython.display import Markdown\n", @@ -544,7 +544,7 @@ " input_variables=[\"question\", \"graph_schema\", \"context\"],\n", ")\n", "\n", - "llm = ChatVertexAI(model=\"gemini-3.1-flash-lite\", temperature=0)\n", + "llm = ChatGoogleGenerativeAI(model=\"gemini-3.1-flash-lite\", temperature=0)\n", "\n", "chain = prompt | llm | StrOutputParser()" ] @@ -753,7 +753,7 @@ " return context\n", "\n", "\n", - "embedding_service = GoogleGenerativeAIEmbeddings(model=\"gemini-embedding-2\")\n", + "embedding_service = GoogleGenerativeAIEmbeddings(model=\"gemini-embedding-2\", project=PROJECT_ID, vertexai=True)\n", "question = \"Give me recommendations for a beginner drone\"\n", "context = use_node_vector_retriever(\n", " question, graph_store, embedding_service, label_expr=\"Product\", expand_by_hops=1\n", @@ -818,7 +818,7 @@ "\n", "\n", "def load_data_for_vector_search(splits):\n", - " embeddings = GoogleGenerativeAIEmbeddings(model=\"gemini-embedding-2\")\n", + " embeddings = GoogleGenerativeAIEmbeddings(model=\"gemini-embedding-2\", project=PROJECT_ID, vertexai=True)\n", "\n", " SpannerVectorStore.init_vector_store_table(\n", " instance_id=INSTANCE,\n", @@ -843,7 +843,7 @@ ")\n", "\n", "# Initialize table and load data\n", - "embeddings = GoogleGenerativeAIEmbeddings(model=\"gemini-embedding-2\")\n", + "embeddings = GoogleGenerativeAIEmbeddings(model=\"gemini-embedding-2\", project=PROJECT_ID, vertexai=True)\n", "load_data_for_vector_search(splits)" ] }, @@ -886,7 +886,7 @@ ")\n", "\n", "# Create a rag chain\n", - "embeddings = GoogleGenerativeAIEmbeddings(model=\"gemini-embedding-2\")\n", + "embeddings = GoogleGenerativeAIEmbeddings(model=\"gemini-embedding-2\", project=PROJECT_ID, vertexai=True)\n", "\n", "db = SpannerVectorStore(\n", " instance_id=INSTANCE,\n", diff --git a/docs/vector_store.ipynb b/docs/vector_store.ipynb index 52cd79cb..dadb3946 100644 --- a/docs/vector_store.ipynb +++ b/docs/vector_store.ipynb @@ -237,7 +237,7 @@ "from langchain_google_genai import GoogleGenerativeAIEmbeddings\n", "\n", "embeddings = GoogleGenerativeAIEmbeddings(\n", - " model=\"textembedding-gecko@latest\", project=PROJECT_ID\n", + " model=\"textembedding-gecko@latest\", project=PROJECT_ID, vertexai=True\n", ")" ] }, diff --git a/samples/langchain_quick_start.ipynb b/samples/langchain_quick_start.ipynb index 3f4799ac..8bad96ed 100644 --- a/samples/langchain_quick_start.ipynb +++ b/samples/langchain_quick_start.ipynb @@ -900,7 +900,7 @@ "\n", "# Initialize the embedding service. In this case we are using version 005 of Vertex AI's textembedding model. In general, it is good practice to specify the model version used.\n", "embeddings_service = GoogleGenerativeAIEmbeddings(\n", - " model=\"gemini-embedding-2\", project=project_id\n", + " model=\"gemini-embedding-2\", project=project_id, vertexai=True\n", ")\n", "\n", "\n", @@ -1082,7 +1082,7 @@ "from langchain_google_genai import GoogleGenerativeAIEmbeddings\n", "\n", "embeddings_service = GoogleGenerativeAIEmbeddings(\n", - " model=\"gemini-embedding-2\", project=project_id\n", + " model=\"gemini-embedding-2\", project=project_id, vertexai=True\n", ")\n", "embedding_vector_size = 768\n", "vector_index_name = \"titles_index\"\n", @@ -1539,7 +1539,7 @@ "\n", "# Intialize the embedding service\n", "embeddings_service = GoogleGenerativeAIEmbeddings(\n", - " model=\"gemini-embedding-2\", project=project_id\n", + " model=\"gemini-embedding-2\", project=project_id, vertexai=True\n", ")\n", "\n", "# Intialize the Vector Store\n", diff --git a/tests/integration/test_spanner_graph_qa.py b/tests/integration/test_spanner_graph_qa.py index f63546db..2ed4fd1f 100644 --- a/tests/integration/test_spanner_graph_qa.py +++ b/tests/integration/test_spanner_graph_qa.py @@ -20,8 +20,7 @@ from google.cloud import spanner from langchain_classic.evaluation import load_evaluator from langchain_core.documents import Document -from langchain_google_vertexai import ChatVertexAI -from langchain_google_genai import GoogleGenerativeAIEmbeddings +from langchain_google_genai import ChatGoogleGenerativeAI, GoogleGenerativeAIEmbeddings from langchain_google_spanner import ( GraphDocument, @@ -41,7 +40,7 @@ def random_string(num_char=3): def get_llm(): - llm = ChatVertexAI( + llm = ChatGoogleGenerativeAI( model="gemini-3.1-flash-lite", location="global", temperature=0, @@ -52,7 +51,9 @@ def get_llm(): def get_evaluator(): return load_evaluator( "embedding_distance", - embeddings=GoogleGenerativeAIEmbeddings(model="gemini-embedding-2"), + embeddings=GoogleGenerativeAIEmbeddings( + model="gemini-embedding-2", project=project_id, vertexai=True + ), ) diff --git a/tests/integration/test_spanner_graph_retriever.py b/tests/integration/test_spanner_graph_retriever.py index 91856cc5..e3951f64 100644 --- a/tests/integration/test_spanner_graph_retriever.py +++ b/tests/integration/test_spanner_graph_retriever.py @@ -19,8 +19,7 @@ import pytest from google.cloud import spanner from langchain_core.documents import Document -from langchain_google_vertexai import ChatVertexAI -from langchain_google_genai import GoogleGenerativeAIEmbeddings +from langchain_google_genai import ChatGoogleGenerativeAI, GoogleGenerativeAIEmbeddings from langchain_google_spanner import ( GraphDocument, @@ -43,7 +42,7 @@ def random_string(num_char=3): def get_llm(): - llm = ChatVertexAI( + llm = ChatGoogleGenerativeAI( model="gemini-3.1-flash-lite", location="global", temperature=0, @@ -52,7 +51,9 @@ def get_llm(): def get_embedding(): - embeddings = GoogleGenerativeAIEmbeddings(model="gemini-embedding-2") + embeddings = GoogleGenerativeAIEmbeddings( + model="gemini-embedding-2", project=project_id, vertexai=True + ) return embeddings