Skip to content

Commit 949a888

Browse files
committed
feat: Add Milvus vector store integration for RAG
Add Milvus as a vector database option for knowledge base RAG workflows. This follows the existing Spanner integration pattern with BaseToolset, providing data ingestion, similarity search, and a ready-to-use toolset for LLM agents. - MilvusVectorStoreSettings / MilvusToolSettings (Pydantic config) - MilvusVectorStore: setup, add_contents, search, close - MilvusTool: FunctionTool subclass injecting vector_store param - MilvusToolset: BaseToolset providing similarity_search tool - Registered MILVUS_TOOLSET / MILVUS_VECTOR_STORE as experimental features - Added pymilvus>=2.5.0 to test, extensions, and new milvus extras - 30 unit tests (all passing) - Sample milvus_rag_agent under contributing/samples/
1 parent 483c5ba commit 949a888

File tree

16 files changed

+1416
-0
lines changed

16 files changed

+1416
-0
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Milvus RAG Agent Sample
2+
3+
This sample demonstrates how to build a knowledge base agent using
4+
[Milvus](https://milvus.io/) as the vector database for
5+
retrieval-augmented generation (RAG) with Google ADK.
6+
7+
## Prerequisites
8+
9+
1. A running Milvus instance, or use Milvus Lite (local file path).
10+
2. A Google GenAI API key for embedding generation.
11+
3. Install dependencies:
12+
13+
```bash
14+
pip install "google-adk[milvus]"
15+
```
16+
17+
## Setup
18+
19+
### Environment Variables
20+
21+
```bash
22+
export GOOGLE_API_KEY="your-google-api-key"
23+
export MILVUS_URI="http://localhost:19530" # or ./milvus.db for Milvus Lite
24+
export MILVUS_COLLECTION="knowledge_base"
25+
# Optional: export MILVUS_TOKEN="your-token" # for Zilliz Cloud
26+
```
27+
28+
### Data Ingestion
29+
30+
Before running the agent, you need to populate the Milvus collection
31+
with your knowledge base data:
32+
33+
```python
34+
from google.adk.tools.milvus.milvus_vector_store import MilvusVectorStore
35+
from google.adk.tools.milvus.settings import MilvusToolSettings
36+
from google.adk.tools.milvus.settings import MilvusVectorStoreSettings
37+
from google.genai import Client
38+
39+
# Define your embedding function (example using Google GenAI).
40+
genai_client = Client()
41+
42+
def embedding_fn(texts):
43+
resp = genai_client.models.embed_content(
44+
model="text-embedding-004", contents=texts)
45+
return [list(e.values) for e in resp.embeddings]
46+
47+
settings = MilvusToolSettings(
48+
vector_store_settings=MilvusVectorStoreSettings(
49+
uri="http://localhost:19530",
50+
collection_name="knowledge_base",
51+
dimension=768,
52+
),
53+
)
54+
55+
store = MilvusVectorStore(settings=settings, embedding_fn=embedding_fn)
56+
store.setup()
57+
store.add_contents([
58+
"Your document text here...",
59+
"Another document...",
60+
])
61+
```
62+
63+
## Run
64+
65+
```bash
66+
adk run contributing/samples/milvus_rag_agent
67+
```
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright 2026 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from . import agent
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# Copyright 2026 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Sample Milvus RAG Agent.
16+
17+
This sample demonstrates how to build a knowledge base agent using Milvus
18+
as the vector database for retrieval-augmented generation (RAG).
19+
20+
Prerequisites:
21+
1. A running Milvus instance (or use Milvus Lite with a local file path).
22+
2. A Google GenAI API key set in the GOOGLE_API_KEY environment variable.
23+
3. Install dependencies: pip install "google-adk[milvus]"
24+
25+
Usage:
26+
adk run contributing/samples/milvus_rag_agent
27+
"""
28+
29+
import os
30+
31+
from dotenv import load_dotenv
32+
from google.adk.agents.llm_agent import LlmAgent
33+
from google.adk.tools.milvus.milvus_toolset import MilvusToolset
34+
from google.adk.tools.milvus.settings import MilvusToolSettings
35+
from google.adk.tools.milvus.settings import MilvusVectorStoreSettings
36+
from google.genai import Client
37+
38+
load_dotenv()
39+
40+
# --- Embedding function using Google GenAI ---
41+
genai_client = Client()
42+
43+
44+
def embedding_fn(texts: list[str]) -> list[list[float]]:
45+
response = genai_client.models.embed_content(
46+
model="text-embedding-004",
47+
contents=texts,
48+
)
49+
return [list(e.values) for e in response.embeddings]
50+
51+
52+
# --- Milvus vector store settings ---
53+
# Replace these with your own Milvus connection and collection settings.
54+
vector_store_settings = MilvusVectorStoreSettings(
55+
# Use a remote Milvus instance or a local Milvus Lite file path.
56+
uri=os.environ.get("MILVUS_URI", "http://localhost:19530"),
57+
token=os.environ.get("MILVUS_TOKEN", None),
58+
collection_name=os.environ.get("MILVUS_COLLECTION", "knowledge_base"),
59+
dimension=768,
60+
metric_type="COSINE",
61+
top_k=5,
62+
)
63+
64+
# --- Milvus toolset ---
65+
milvus_toolset = MilvusToolset(
66+
milvus_tool_settings=MilvusToolSettings(
67+
vector_store_settings=vector_store_settings,
68+
),
69+
embedding_fn=embedding_fn,
70+
tool_filter=["similarity_search"],
71+
)
72+
73+
# --- Agent definition ---
74+
root_agent = LlmAgent(
75+
model="gemini-2.5-flash",
76+
name="milvus_knowledge_agent",
77+
description="Agent that answers questions using a Milvus knowledge base.",
78+
instruction="""
79+
You are a helpful assistant with access to a knowledge base.
80+
1. Always use the `similarity_search` tool to find relevant information.
81+
2. Present the search results naturally in your response.
82+
3. If no results are found, say you don't know.
83+
""",
84+
tools=[milvus_toolset],
85+
)

pyproject.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ test = [
127127
"litellm>=1.75.5, <1.80.17", # For LiteLLM tests
128128
"llama-index-readers-file>=0.4.0", # For retrieval tests
129129
"openai>=1.100.2", # For LiteLLM
130+
"pymilvus>=2.5.0", # For Milvus vector store tests
130131
"opentelemetry-instrumentation-google-genai>=0.3b0, <1.0.0",
131132
"pypika>=0.50.0", # For crewai->chromadb dependency
132133
"pytest-asyncio>=0.25.0",
@@ -159,11 +160,16 @@ extensions = [
159160
"litellm>=1.75.5, <1.80.17", # For LiteLlm class. Currently has OpenAI limitations. TODO: once LiteLlm fix it
160161
"llama-index-readers-file>=0.4.0", # For retrieval using LlamaIndex.
161162
"llama-index-embeddings-google-genai>=0.3.0", # For files retrieval using LlamaIndex.
163+
"pymilvus>=2.5.0", # For Milvus vector store integration.
162164
"lxml>=5.3.0", # For load_web_page tool.
163165
"pypika>=0.50.0", # For crewai->chromadb dependency
164166
"toolbox-adk>=0.5.7, <0.6.0", # For tools.toolbox_toolset.ToolboxToolset
165167
]
166168

169+
milvus = [
170+
"pymilvus>=2.5.0",
171+
]
172+
167173
otel-gcp = ["opentelemetry-instrumentation-google-genai>=0.6b0, <1.0.0"]
168174

169175
toolbox = ["toolbox-adk>=0.5.7, <0.6.0"]

src/google/adk/features/_feature_registry.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ class FeatureName(str, Enum):
3838
GOOGLE_CREDENTIALS_CONFIG = "GOOGLE_CREDENTIALS_CONFIG"
3939
GOOGLE_TOOL = "GOOGLE_TOOL"
4040
JSON_SCHEMA_FOR_FUNC_DECL = "JSON_SCHEMA_FOR_FUNC_DECL"
41+
MILVUS_TOOLSET = "MILVUS_TOOLSET"
42+
MILVUS_VECTOR_STORE = "MILVUS_VECTOR_STORE"
4143
PROGRESSIVE_SSE_STREAMING = "PROGRESSIVE_SSE_STREAMING"
4244
PUBSUB_TOOL_CONFIG = "PUBSUB_TOOL_CONFIG"
4345
PUBSUB_TOOLSET = "PUBSUB_TOOLSET"
@@ -114,6 +116,12 @@ class FeatureConfig:
114116
FeatureName.JSON_SCHEMA_FOR_FUNC_DECL: FeatureConfig(
115117
FeatureStage.WIP, default_on=False
116118
),
119+
FeatureName.MILVUS_TOOLSET: FeatureConfig(
120+
FeatureStage.EXPERIMENTAL, default_on=True
121+
),
122+
FeatureName.MILVUS_VECTOR_STORE: FeatureConfig(
123+
FeatureStage.EXPERIMENTAL, default_on=True
124+
),
117125
FeatureName.PROGRESSIVE_SSE_STREAMING: FeatureConfig(
118126
FeatureStage.EXPERIMENTAL, default_on=True
119127
),
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Copyright 2026 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Milvus Tools (Experimental).
16+
17+
Milvus Tools provide vector similarity search capabilities using Milvus
18+
as the vector database backend. This module offers:
19+
20+
1. A MilvusToolset for easy integration with ADK agents.
21+
2. A MilvusVectorStore utility for collection management and data ingestion.
22+
3. Support for any third-party embedding function (Google GenAI, OpenAI, etc.).
23+
"""
24+
25+
from .milvus_toolset import MilvusToolset
26+
27+
__all__ = [
28+
"MilvusToolset",
29+
]
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Copyright 2026 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""MilvusTool wraps a function and injects the MilvusVectorStore instance."""
16+
17+
from __future__ import annotations
18+
19+
import inspect
20+
from typing import Any
21+
from typing import Callable
22+
23+
from typing_extensions import override
24+
25+
from ..function_tool import FunctionTool
26+
from ..tool_context import ToolContext
27+
from .milvus_vector_store import MilvusVectorStore
28+
29+
30+
class MilvusTool(FunctionTool):
31+
"""A FunctionTool that injects MilvusVectorStore into the wrapped function.
32+
33+
The ``vector_store`` parameter is hidden from the LLM function
34+
declaration and automatically injected at runtime.
35+
"""
36+
37+
def __init__(
38+
self,
39+
func: Callable[..., Any],
40+
*,
41+
vector_store: MilvusVectorStore,
42+
):
43+
super().__init__(func=func)
44+
self._ignore_params.append("vector_store")
45+
self._vector_store = vector_store
46+
47+
@override
48+
async def run_async(
49+
self, *, args: dict[str, Any], tool_context: ToolContext
50+
) -> Any:
51+
args_to_call = args.copy()
52+
signature = inspect.signature(self.func)
53+
if "vector_store" in signature.parameters:
54+
args_to_call["vector_store"] = self._vector_store
55+
return await super().run_async(args=args_to_call, tool_context=tool_context)

0 commit comments

Comments
 (0)