From 0f7394cef2a6983d131a28958d0f389466781302 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 May 2026 22:11:36 +0000 Subject: [PATCH 1/7] chore(deps): bump google-cloud-aiplatform from 1.97.0 to 1.133.0 Bumps [google-cloud-aiplatform](https://github.com/googleapis/python-aiplatform) from 1.97.0 to 1.133.0. - [Release notes](https://github.com/googleapis/python-aiplatform/releases) - [Changelog](https://github.com/googleapis/python-aiplatform/blob/main/CHANGELOG.md) - [Commits](https://github.com/googleapis/python-aiplatform/compare/v1.97.0...v1.133.0) --- updated-dependencies: - dependency-name: google-cloud-aiplatform dependency-version: 1.133.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- samples/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/requirements.txt b/samples/requirements.txt index 55ca38fb..a7feb5db 100644 --- a/samples/requirements.txt +++ b/samples/requirements.txt @@ -1,4 +1,4 @@ -google-cloud-aiplatform[reasoningengine,langchain]==1.97.0 +google-cloud-aiplatform[reasoningengine,langchain]==1.133.0 google-cloud-resource-manager==1.15.0 langchain-community==0.3.31 langchain-google-alloydb-pg==0.13.0 From 7ca0835cc5434bd193b186d5809f9fcca95ca165 Mon Sep 17 00:00:00 2001 From: Twisha Bansal <58483338+twishabansal@users.noreply.github.com> Date: Fri, 29 May 2026 13:13:57 +0530 Subject: [PATCH 2/7] Refactor query method parameters and documentation Refactor query method to accept keyword arguments and improve documentation. --- .../retriever_agent_with_history_template.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/samples/langchain_on_vertexai/retriever_agent_with_history_template.py b/samples/langchain_on_vertexai/retriever_agent_with_history_template.py index e2eea8d6..4e9bbf72 100644 --- a/samples/langchain_on_vertexai/retriever_agent_with_history_template.py +++ b/samples/langchain_on_vertexai/retriever_agent_with_history_template.py @@ -135,19 +135,20 @@ def set_up(self): history_messages_key="chat_history", ) - def query(self, input: str, session_id: str, **kwargs: Any) -> str: + def query(self, **kwargs: Any) -> Any: """Query the application. Args: - input: The user query. - session_id: The user's session id. + **kwargs: Keyword arguments forwarded from the reasoning engine. + Expects ``input`` (the user query) and ``session_id`` + (the user's session id). Returns: - The LLM response dictionary. + The LLM response. """ response = self.agent.invoke( - {"input": input}, - config={"configurable": {"session_id": session_id}}, + {"input": kwargs["input"]}, + config={"configurable": {"session_id": kwargs["session_id"]}}, ) return response["output"] From cfdbc15a20546248bda5281dd0fb3b18e2557959 Mon Sep 17 00:00:00 2001 From: Twisha Bansal <58483338+twishabansal@users.noreply.github.com> Date: Fri, 29 May 2026 13:14:14 +0530 Subject: [PATCH 3/7] Refactor AlloyDBAgent to AlloyDBRetriever --- .../retriever_agent_with_history_template.py | 119 +++++++----------- 1 file changed, 44 insertions(+), 75 deletions(-) diff --git a/samples/langchain_on_vertexai/retriever_agent_with_history_template.py b/samples/langchain_on_vertexai/retriever_agent_with_history_template.py index 4e9bbf72..55854736 100644 --- a/samples/langchain_on_vertexai/retriever_agent_with_history_template.py +++ b/samples/langchain_on_vertexai/retriever_agent_with_history_template.py @@ -16,7 +16,6 @@ import vertexai # type: ignore from config import ( - CHAT_TABLE_NAME, CLUSTER, DATABASE, INSTANCE, @@ -27,26 +26,20 @@ TABLE_NAME, USER, ) -from langchain import hub -from langchain.agents import AgentExecutor, create_react_agent -from langchain.tools.retriever import create_retriever_tool -from langchain_core.runnables.history import RunnableWithMessageHistory -from langchain_google_vertexai import ChatVertexAI, VertexAIEmbeddings +from langchain.chains.combine_documents import create_stuff_documents_chain +from langchain.chains.retrieval import create_retrieval_chain +from langchain_core.prompts import ChatPromptTemplate +from langchain_google_vertexai import VertexAI, VertexAIEmbeddings from vertexai.preview import reasoning_engines # type: ignore -from langchain_google_alloydb_pg import ( - AlloyDBChatMessageHistory, - AlloyDBEngine, - AlloyDBVectorStore, -) +from langchain_google_alloydb_pg import AlloyDBEngine, AlloyDBVectorStore -# This sample requires a vector store table and a chat message table -# Create these tables using `AlloyDBEngine` methods -# `init_vectorstore_table()` and `init_chat_history_table()` -# or create and load the tables using `create_embeddings.py` +# This sample requires a vector store table +# Create these tables using `AlloyDBEngine` method `init_vectorstore_table()` +# or create and load the table using `create_embeddings.py` -class AlloyDBAgent(reasoning_engines.Queryable): +class AlloyDBRetriever(reasoning_engines.Queryable): def __init__( self, model: str, @@ -56,11 +49,8 @@ def __init__( instance: str, database: str, table: str, - chat_table: str, user: Optional[str] = None, password: Optional[str] = None, - tool_name: str = "search_movies", - tool_description: str = "Searches and returns movies.", ): self.model_name = model self.project = project @@ -69,18 +59,34 @@ def __init__( self.instance = instance self.database = database self.table = table - self.chat_table = chat_table self.user = user self.password = password - self.tool_name = tool_name - self.tool_description = tool_description def set_up(self): """All unpickle-able logic should go here. In general, add any logic that requires a network or database connection. """ - # Initialize the vector store + # Create a chain to handle the processing of relevant documents + system_prompt = ( + "You are an assistant for question-answering tasks. " + "Use the following pieces of retrieved context to answer " + "the question. If you don't know the answer, say that you " + "don't know. Use three sentences maximum and keep the " + "answer concise." + "\n\n" + "{context}" + ) + prompt = ChatPromptTemplate.from_messages( + [ + ("system", system_prompt), + ("human", "{input}"), + ] + ) + llm = VertexAI(model_name=self.model_name, project=self.project) + combine_docs_chain = create_stuff_documents_chain(llm, prompt) + + # Initialize the vector store and retriever engine = AlloyDBEngine.from_instance( self.project, self.region, @@ -99,62 +105,28 @@ def set_up(self): ) retriever = vector_store.as_retriever() - # Create a tool to do retrieval of documents - tool = create_retriever_tool( - retriever, - self.tool_name, - self.tool_description, - ) - tools = [tool] - - # Initialize the LLM and prompt - llm = ChatVertexAI(model_name=self.model_name, project=self.project) - base_prompt = hub.pull("langchain-ai/react-agent-template") - instructions = ( - "You are an assistant for question-answering tasks. " - "Use the following pieces of retrieved context to answer " - "the question. If you don't know the answer, say that you " - "don't know. Use three sentences maximum and keep the " - "answer concise." - ) - prompt = base_prompt.partial(instructions=instructions) - - # Create an agent - agent = create_react_agent(llm, tools, prompt) - agent_executor = AgentExecutor( - agent=agent, tools=tools, handle_parsing_errors=True - ) - - # Initialize a Runnable that manages chat message history for the agent - self.agent = RunnableWithMessageHistory( - agent_executor, - lambda session_id: AlloyDBChatMessageHistory.create_sync( - engine=engine, session_id=session_id, table_name=self.chat_table - ), - input_messages_key="input", - history_messages_key="chat_history", - ) + # Create a retrieval chain to fetch relevant documents and pass them to + # an LLM to generate a response + self.chain = create_retrieval_chain(retriever, combine_docs_chain) def query(self, **kwargs: Any) -> Any: """Query the application. Args: **kwargs: Keyword arguments forwarded from the reasoning engine. - Expects ``input`` (the user query) and ``session_id`` - (the user's session id). + Expects an ``input`` key containing the user query. Returns: The LLM response. """ - response = self.agent.invoke( - {"input": kwargs["input"]}, - config={"configurable": {"session_id": kwargs["session_id"]}}, - ) - return response["output"] + # Define the runtime logic that serves user queries + response = self.chain.invoke({"input": kwargs["input"]}) + return response["answer"] # Uncomment to test locally -# app = AlloyDBAgent( + +# app = AlloyDBRetriever( # model="gemini-2.0-flash-001", # project=PROJECT_ID, # region=REGION, @@ -162,22 +134,20 @@ def query(self, **kwargs: Any) -> Any: # instance=INSTANCE, # database=DATABASE, # table=TABLE_NAME, -# chat_table=CHAT_TABLE_NAME, # user=USER, -# password=PASSWORD +# password=PASSWORD, # ) - # app.set_up() -# print(app.query(input="What movies are about engineers?", session_id="abc123")) +# print(app.query(input="movies about engineers")) # Initialize VertexAI vertexai.init(project=PROJECT_ID, location="us-central1", staging_bucket=STAGING_BUCKET) # Deploy to VertexAI -DISPLAY_NAME = os.getenv("DISPLAY_NAME") or "AlloyDBAgent" +DISPLAY_NAME = os.getenv("DISPLAY_NAME") or "AlloyDBRetriever" remote_app = reasoning_engines.ReasoningEngine.create( - AlloyDBAgent( + AlloyDBRetriever( model="gemini-2.0-flash-001", project=PROJECT_ID, region=REGION, @@ -185,10 +155,9 @@ def query(self, **kwargs: Any) -> Any: instance=INSTANCE, database=DATABASE, table=TABLE_NAME, - chat_table=CHAT_TABLE_NAME, # To use IAM authentication, remove user and password and ensure # the Reasoning Engine Agent service account is a database user - # with access to vector store and chat tables + # with access to the vector store table user=USER, password=PASSWORD, ), @@ -198,4 +167,4 @@ def query(self, **kwargs: Any) -> Any: extra_packages=["config.py"], ) -print(remote_app.query(input="movies about engineers", session_id="abc123")) # type: ignore +print(remote_app.query(input="movies about engineers")) # type: ignore From b94efa215adfc59fc8a3933f566c8911502a4f48 Mon Sep 17 00:00:00 2001 From: Twisha Bansal <58483338+twishabansal@users.noreply.github.com> Date: Fri, 29 May 2026 13:17:15 +0530 Subject: [PATCH 4/7] Update retriever_agent_with_history_template.py --- .../retriever_agent_with_history_template.py | 119 +++++++++++------- 1 file changed, 75 insertions(+), 44 deletions(-) diff --git a/samples/langchain_on_vertexai/retriever_agent_with_history_template.py b/samples/langchain_on_vertexai/retriever_agent_with_history_template.py index 55854736..4e9bbf72 100644 --- a/samples/langchain_on_vertexai/retriever_agent_with_history_template.py +++ b/samples/langchain_on_vertexai/retriever_agent_with_history_template.py @@ -16,6 +16,7 @@ import vertexai # type: ignore from config import ( + CHAT_TABLE_NAME, CLUSTER, DATABASE, INSTANCE, @@ -26,20 +27,26 @@ TABLE_NAME, USER, ) -from langchain.chains.combine_documents import create_stuff_documents_chain -from langchain.chains.retrieval import create_retrieval_chain -from langchain_core.prompts import ChatPromptTemplate -from langchain_google_vertexai import VertexAI, VertexAIEmbeddings +from langchain import hub +from langchain.agents import AgentExecutor, create_react_agent +from langchain.tools.retriever import create_retriever_tool +from langchain_core.runnables.history import RunnableWithMessageHistory +from langchain_google_vertexai import ChatVertexAI, VertexAIEmbeddings from vertexai.preview import reasoning_engines # type: ignore -from langchain_google_alloydb_pg import AlloyDBEngine, AlloyDBVectorStore +from langchain_google_alloydb_pg import ( + AlloyDBChatMessageHistory, + AlloyDBEngine, + AlloyDBVectorStore, +) -# This sample requires a vector store table -# Create these tables using `AlloyDBEngine` method `init_vectorstore_table()` -# or create and load the table using `create_embeddings.py` +# This sample requires a vector store table and a chat message table +# Create these tables using `AlloyDBEngine` methods +# `init_vectorstore_table()` and `init_chat_history_table()` +# or create and load the tables using `create_embeddings.py` -class AlloyDBRetriever(reasoning_engines.Queryable): +class AlloyDBAgent(reasoning_engines.Queryable): def __init__( self, model: str, @@ -49,8 +56,11 @@ def __init__( instance: str, database: str, table: str, + chat_table: str, user: Optional[str] = None, password: Optional[str] = None, + tool_name: str = "search_movies", + tool_description: str = "Searches and returns movies.", ): self.model_name = model self.project = project @@ -59,34 +69,18 @@ def __init__( self.instance = instance self.database = database self.table = table + self.chat_table = chat_table self.user = user self.password = password + self.tool_name = tool_name + self.tool_description = tool_description def set_up(self): """All unpickle-able logic should go here. In general, add any logic that requires a network or database connection. """ - # Create a chain to handle the processing of relevant documents - system_prompt = ( - "You are an assistant for question-answering tasks. " - "Use the following pieces of retrieved context to answer " - "the question. If you don't know the answer, say that you " - "don't know. Use three sentences maximum and keep the " - "answer concise." - "\n\n" - "{context}" - ) - prompt = ChatPromptTemplate.from_messages( - [ - ("system", system_prompt), - ("human", "{input}"), - ] - ) - llm = VertexAI(model_name=self.model_name, project=self.project) - combine_docs_chain = create_stuff_documents_chain(llm, prompt) - - # Initialize the vector store and retriever + # Initialize the vector store engine = AlloyDBEngine.from_instance( self.project, self.region, @@ -105,28 +99,62 @@ def set_up(self): ) retriever = vector_store.as_retriever() - # Create a retrieval chain to fetch relevant documents and pass them to - # an LLM to generate a response - self.chain = create_retrieval_chain(retriever, combine_docs_chain) + # Create a tool to do retrieval of documents + tool = create_retriever_tool( + retriever, + self.tool_name, + self.tool_description, + ) + tools = [tool] + + # Initialize the LLM and prompt + llm = ChatVertexAI(model_name=self.model_name, project=self.project) + base_prompt = hub.pull("langchain-ai/react-agent-template") + instructions = ( + "You are an assistant for question-answering tasks. " + "Use the following pieces of retrieved context to answer " + "the question. If you don't know the answer, say that you " + "don't know. Use three sentences maximum and keep the " + "answer concise." + ) + prompt = base_prompt.partial(instructions=instructions) + + # Create an agent + agent = create_react_agent(llm, tools, prompt) + agent_executor = AgentExecutor( + agent=agent, tools=tools, handle_parsing_errors=True + ) + + # Initialize a Runnable that manages chat message history for the agent + self.agent = RunnableWithMessageHistory( + agent_executor, + lambda session_id: AlloyDBChatMessageHistory.create_sync( + engine=engine, session_id=session_id, table_name=self.chat_table + ), + input_messages_key="input", + history_messages_key="chat_history", + ) def query(self, **kwargs: Any) -> Any: """Query the application. Args: **kwargs: Keyword arguments forwarded from the reasoning engine. - Expects an ``input`` key containing the user query. + Expects ``input`` (the user query) and ``session_id`` + (the user's session id). Returns: The LLM response. """ - # Define the runtime logic that serves user queries - response = self.chain.invoke({"input": kwargs["input"]}) - return response["answer"] + response = self.agent.invoke( + {"input": kwargs["input"]}, + config={"configurable": {"session_id": kwargs["session_id"]}}, + ) + return response["output"] # Uncomment to test locally - -# app = AlloyDBRetriever( +# app = AlloyDBAgent( # model="gemini-2.0-flash-001", # project=PROJECT_ID, # region=REGION, @@ -134,20 +162,22 @@ def query(self, **kwargs: Any) -> Any: # instance=INSTANCE, # database=DATABASE, # table=TABLE_NAME, +# chat_table=CHAT_TABLE_NAME, # user=USER, -# password=PASSWORD, +# password=PASSWORD # ) + # app.set_up() -# print(app.query(input="movies about engineers")) +# print(app.query(input="What movies are about engineers?", session_id="abc123")) # Initialize VertexAI vertexai.init(project=PROJECT_ID, location="us-central1", staging_bucket=STAGING_BUCKET) # Deploy to VertexAI -DISPLAY_NAME = os.getenv("DISPLAY_NAME") or "AlloyDBRetriever" +DISPLAY_NAME = os.getenv("DISPLAY_NAME") or "AlloyDBAgent" remote_app = reasoning_engines.ReasoningEngine.create( - AlloyDBRetriever( + AlloyDBAgent( model="gemini-2.0-flash-001", project=PROJECT_ID, region=REGION, @@ -155,9 +185,10 @@ def query(self, **kwargs: Any) -> Any: instance=INSTANCE, database=DATABASE, table=TABLE_NAME, + chat_table=CHAT_TABLE_NAME, # To use IAM authentication, remove user and password and ensure # the Reasoning Engine Agent service account is a database user - # with access to the vector store table + # with access to vector store and chat tables user=USER, password=PASSWORD, ), @@ -167,4 +198,4 @@ def query(self, **kwargs: Any) -> Any: extra_packages=["config.py"], ) -print(remote_app.query(input="movies about engineers")) # type: ignore +print(remote_app.query(input="movies about engineers", session_id="abc123")) # type: ignore From 59f9f2dfe1caa68b05f611e3c4ea87d63af69b5c Mon Sep 17 00:00:00 2001 From: Twisha Bansal <58483338+twishabansal@users.noreply.github.com> Date: Fri, 29 May 2026 13:18:09 +0530 Subject: [PATCH 5/7] Update retriever_chain_template.py --- .../langchain_on_vertexai/retriever_chain_template.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/samples/langchain_on_vertexai/retriever_chain_template.py b/samples/langchain_on_vertexai/retriever_chain_template.py index 905c41dd..55854736 100644 --- a/samples/langchain_on_vertexai/retriever_chain_template.py +++ b/samples/langchain_on_vertexai/retriever_chain_template.py @@ -109,18 +109,18 @@ def set_up(self): # an LLM to generate a response self.chain = create_retrieval_chain(retriever, combine_docs_chain) - def query(self, input: str, **kwargs: Any) -> str: + def query(self, **kwargs: Any) -> Any: """Query the application. Args: - input: The user query. - **kwargs: Additional arguments for Protocol compliance. + **kwargs: Keyword arguments forwarded from the reasoning engine. + Expects an ``input`` key containing the user query. Returns: - The LLM response dictionary. + The LLM response. """ # Define the runtime logic that serves user queries - response = self.chain.invoke({"input": input}) + response = self.chain.invoke({"input": kwargs["input"]}) return response["answer"] From d650f83d8ffb44743707f150299b55e1f0fc1ebe Mon Sep 17 00:00:00 2001 From: Twisha Bansal Date: Fri, 29 May 2026 13:29:53 +0530 Subject: [PATCH 6/7] put arg type ignore at the right place --- .../prebuilt_langchain_agent_template.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/langchain_on_vertexai/prebuilt_langchain_agent_template.py b/samples/langchain_on_vertexai/prebuilt_langchain_agent_template.py index f4a14675..6dbffc33 100644 --- a/samples/langchain_on_vertexai/prebuilt_langchain_agent_template.py +++ b/samples/langchain_on_vertexai/prebuilt_langchain_agent_template.py @@ -92,7 +92,7 @@ def similarity_search(query: str) -> list[Document]: DISPLAY_NAME = os.getenv("DISPLAY_NAME") or "PrebuiltAgent" remote_app = reasoning_engines.ReasoningEngine.create( - reasoning_engines.LangchainAgent( + reasoning_engines.LangchainAgent( # type: ignore[arg-type] model="gemini-2.0-flash-001", tools=[similarity_search], # type: ignore[list-item] model_kwargs={ @@ -103,6 +103,6 @@ def similarity_search(query: str) -> list[Document]: display_name="PrebuiltAgent", sys_version="3.11", extra_packages=["config.py"], -) # type: ignore[arg-type] +) print(remote_app.query(input="movies about engineers")) # type: ignore[attr-defined] From 5625132f1518afdfdaf7e4b1cea0eae2ea3cbad3 Mon Sep 17 00:00:00 2001 From: Twisha Bansal Date: Fri, 29 May 2026 14:24:39 +0530 Subject: [PATCH 7/7] update samples for new versions --- .../retriever_agent_with_history_template.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/samples/langchain_on_vertexai/retriever_agent_with_history_template.py b/samples/langchain_on_vertexai/retriever_agent_with_history_template.py index 4e9bbf72..ff4de53b 100644 --- a/samples/langchain_on_vertexai/retriever_agent_with_history_template.py +++ b/samples/langchain_on_vertexai/retriever_agent_with_history_template.py @@ -27,11 +27,11 @@ TABLE_NAME, USER, ) -from langchain import hub from langchain.agents import AgentExecutor, create_react_agent from langchain.tools.retriever import create_retriever_tool from langchain_core.runnables.history import RunnableWithMessageHistory from langchain_google_vertexai import ChatVertexAI, VertexAIEmbeddings +from langsmith import Client from vertexai.preview import reasoning_engines # type: ignore from langchain_google_alloydb_pg import ( @@ -109,7 +109,12 @@ def set_up(self): # Initialize the LLM and prompt llm = ChatVertexAI(model_name=self.model_name, project=self.project) - base_prompt = hub.pull("langchain-ai/react-agent-template") + # ``react-agent-template`` is an official, trusted LangChain prompt. + # langsmith disables pulling public prompts by default, so explicitly + # acknowledge the source with ``dangerously_pull_public_prompt``. + base_prompt = Client().pull_prompt( + "langchain-ai/react-agent-template", dangerously_pull_public_prompt=True + ) instructions = ( "You are an assistant for question-answering tasks. " "Use the following pieces of retrieved context to answer "