Skip to content

Commit e50bf2d

Browse files
authored
fix: Moss integration bug with QueryOptions (#20815)
* fix: moss querying fix + update * fix: moss querying fix + update * fix: moss querying fix + update * fix: pytest issue * fixing coverage test
1 parent 3d94303 commit e50bf2d

File tree

5 files changed

+220
-53
lines changed

5 files changed

+220
-53
lines changed

docs/examples/tools/moss_agent.ipynb renamed to docs/examples/tools/moss_with_llamaindex.ipynb

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,9 @@
55
"id": "3e37307f",
66
"metadata": {},
77
"source": [
8-
"# Moss Tool Example\n",
8+
"# Moss + LlamaIndex\n",
99
"\n",
10-
"This notebook demonstrates how to use the `MossToolSpec` with LlamaIndex.\n",
11-
"\n",
12-
"## Installation\n",
13-
"\n",
14-
"First, you need to install the package (and LlamaIndex core if not present)."
10+
"[Moss](https://moss.dev) is a search runtime for voice agents, copilots, and multimodal apps. Sub-10ms lookups, zero infrastructure. Built in Rust and WebAssembly. Moss runs search inside your agent runtime. Sub-10ms lookups, always-current data, without rebuilding your infra."
1511
]
1612
},
1713
{
@@ -31,7 +27,7 @@
3127
"source": [
3228
"## Setup\n",
3329
"\n",
34-
"Import the necessary classes and initialize the Moss client."
30+
"Import the necessary classes and initialize the Moss client with your project credentials. We'll configure query options to tune the search behavior (`top_k` for result count, `alpha` for the semantic/keyword blend)."
3531
]
3632
},
3733
{
@@ -75,7 +71,7 @@
7571
"source": [
7672
"## Indexing Data\n",
7773
"\n",
78-
"Let's add some sample data to our index."
74+
"Create sample documents with `DocumentInfo` (each with `id`, `text`, and `metadata`). Then call `index_docs()` to build the Moss index — this creates or replaces the index with your documents and makes them searchable."
7975
]
8076
},
8177
{
@@ -110,7 +106,7 @@
110106
"source": [
111107
"## Using with an Agent\n",
112108
"\n",
113-
"Now we can wrap the tool for use with a LlamaIndex agent."
109+
"Now we'll expose the Moss tool's methods (`query`, `list_indexes`, `delete_index`) to a `ReActAgent`. The agent will autonomously decide which tool to call based on the user's question and the search results it retrieves."
114110
]
115111
},
116112
{
Lines changed: 45 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,80 @@
11
import asyncio
22
import os
33
from typing import List
4-
4+
from dotenv import load_dotenv
5+
load_dotenv()
56
from llama_index.core.agent import ReActAgent
67
from llama_index.llms.openai import OpenAI
78
from llama_index.tools.moss import MossToolSpec, QueryOptions
89
from inferedge_moss import MossClient, DocumentInfo
910

1011

1112
async def main():
12-
print("--- Moss Tool with ReAct Agent Example ---\n")
13-
1413
# 1. Initialize Client
15-
# Ensure you have your environment variables set or pass credentials directly.
16-
MOSS_PROJECT_KEY = os.getenv('MOSS_PROJECT_KEY')
17-
MOSS_PROJECT_ID = os.getenv('MOSS_PROJECT_ID')
14+
MOSS_PROJECT_KEY = os.getenv("MOSS_PROJECT_KEY")
15+
MOSS_PROJECT_ID = os.getenv("MOSS_PROJECT_ID")
1816
client = MossClient(project_id=MOSS_PROJECT_ID, project_key=MOSS_PROJECT_KEY)
19-
# 2. Configure query settings - Instantiate QueryOptions (Optional)
20-
# If skipped, the tool will use its own defaults.
21-
query_options = QueryOptions(top_k=12, alpha=0.9)
17+
18+
# 2. Configure query settings (optional — defaults: top_k=5, alpha=0.5, model_id="moss-minilm")
19+
query_options = QueryOptions(top_k=5, alpha=0.5, model_id="moss-minilm")
20+
2221
# 3. Initialize Tool
23-
print("Initializing MossToolSpec...")
2422
moss_tool = MossToolSpec(
2523
client=client,
26-
index_name="knowledge_base",
27-
query_options=query_options
24+
index_name="knowledge_base_new",
25+
query_options=query_options,
2826
)
2927

30-
# 4. Index Documents (Optional step)
31-
print("\n[Step 4] Indexing Documents...")
32-
docs = [
28+
# 4. List existing indexes before indexing
29+
print("\n[Step 4] Listing existing indexes...")
30+
print(await moss_tool.list_indexes())
31+
32+
# 5. Index Documents
33+
print("\n[Step 5] Indexing Documents...")
34+
docs: List[DocumentInfo] = [
3335
DocumentInfo(
36+
id="123",
3437
text="LlamaIndex is a data framework for LLM-based applications.",
35-
metadata={"source": "docs", "category": "framework"}
38+
metadata={"source": "docs", "category": "framework"},
3639
),
3740
DocumentInfo(
41+
id="124",
3842
text="Moss is a real-time semantic search engine optimized for speed.",
39-
metadata={"source": "moss_website", "category": "engine"}
43+
metadata={"source": "moss_website", "category": "engine"},
4044
),
4145
]
4246
await moss_tool.index_docs(docs)
4347
print(f"Indexed {len(docs)} documents.")
4448

45-
# 5. Create an agent (Using OpenAI llm for demonstration)
46-
print("\n[Step 5] Creating Agent...")
47-
os.environ['OPENAI_API_KEY'] = os.getenv('OPENAI_API_KEY', 'your-key-here')
48-
llm = OpenAI()
49-
agent = ReActAgent.from_tools(
50-
moss_tool.to_tool_list(),
49+
# 6. List indexes again to confirm creation
50+
print("\n[Step 6] Listing indexes after indexing...")
51+
print(await moss_tool.list_indexes())
52+
53+
# 7. Create agent with all exposed tools (query, list_indexes, delete_index)
54+
print("\n[Step 7] Creating Agent...")
55+
llm = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
56+
agent = ReActAgent(
57+
tools=moss_tool.to_tool_list(),
5158
llm=llm,
52-
verbose=True
59+
verbose=True,
5360
)
5461

55-
# 6. Run Agent
56-
print("\n[Step 6] Querying...")
57-
# This query would trigger the tool usage in a real scenario
58-
response = await agent.achat("What is Moss?")
62+
# 8. Run Agent — natural language query triggers the query tool
63+
print("\n[Step 8] Querying via Agent...")
64+
response = await agent.run(user_msg="What is Moss?")
5965
print("\nAgent Response:")
6066
print(response)
6167

68+
# 9. Run Agent — ask it to list available indexes
69+
print("\n[Step 9] Listing indexes via Agent...")
70+
response = await agent.run(user_msg="What indexes are available?")
71+
print("\nAgent Response:")
72+
print(response)
73+
74+
# 10. Clean up — delete the index directly (not via agent to avoid accidental deletion)
75+
print("\n[Step 10] Cleaning up...")
76+
print(await moss_tool.delete_index("knowledge_base"))
77+
6278

6379
if __name__ == "__main__":
64-
# Ensure we catch ImportError for better user experience if run without deps
65-
try:
66-
asyncio.run(main())
67-
except ImportError as e:
68-
print(f"Error: {e}")
69-
print("Please install required dependencies: pip install llama-index-tools-moss llama-index-core llama-index-llms-openai inferedge-moss")
70-
except Exception as e:
71-
print(f"An error occurred: {e}")
80+
asyncio.run(main())

llama-index-integrations/tools/llama-index-tools-moss/llama_index/tools/moss/base.py

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from dataclasses import dataclass
55
from llama_index.core.tools.tool_spec.base import BaseToolSpec
66
from inferedge_moss import MossClient, DocumentInfo
7+
from inferedge_moss import QueryOptions as MossQueryOptions
78

89

910
@dataclass
@@ -14,7 +15,7 @@ class QueryOptions:
1415
Attributes:
1516
top_k (int): Number of results to return from queries. Defaults to 5.
1617
alpha (float): Hybrid search weight (0.0=keyword, 1.0=semantic). Defaults to 0.5.
17-
model_id (str): The model ID to use for embeddings. Defaults to "moss-minilm".
18+
model_id (str): The embedding model ID used when creating the index. Defaults to "moss-minilm".
1819
1920
"""
2021

@@ -31,7 +32,7 @@ class MossToolSpec(BaseToolSpec):
3132
and query for relevant information.
3233
"""
3334

34-
spec_functions: tuple[str, ...] = ("query",)
35+
spec_functions: tuple[str, ...] = ("query", "list_indexes", "delete_index")
3536

3637
def __init__(
3738
self,
@@ -58,10 +59,10 @@ def __init__(
5859

5960
self.top_k: int = opt.top_k
6061
self.alpha: float = opt.alpha
62+
self.model_id: str = opt.model_id
6163
self.client: MossClient = client
6264
self.index_name: str = index_name
6365
self._index_loaded: bool = False
64-
self.model_id: str = opt.model_id
6566

6667
async def index_docs(self, docs: List[DocumentInfo]) -> None:
6768
await self.client.create_index(self.index_name, docs, model_id=self.model_id)
@@ -93,7 +94,7 @@ async def query(self, query: str) -> str:
9394
await self._load_index()
9495

9596
results = await self.client.query(
96-
self.index_name, query, self.top_k, self.alpha
97+
self.index_name, query, MossQueryOptions(top_k=self.top_k, alpha=self.alpha)
9798
)
9899
answer = f"Search results for: '{query}'\n\n"
99100

@@ -111,3 +112,40 @@ async def query(self, query: str) -> str:
111112
answer += "-" * 20 + "\n\n"
112113

113114
return answer
115+
116+
async def list_indexes(self) -> str:
117+
"""
118+
List all available indexes in the Moss project.
119+
120+
Use this tool to discover what indexes exist before querying or managing them.
121+
122+
Returns:
123+
str: A formatted list of all index names in the project.
124+
125+
"""
126+
indexes = await self.client.list_indexes()
127+
if not indexes:
128+
return "No indexes found."
129+
130+
result = "Available indexes:\n"
131+
for idx in indexes:
132+
result += f" - {idx.name} (docs: {idx.doc_count}, status: {idx.status})\n"
133+
return result
134+
135+
async def delete_index(self, index_name: str) -> str:
136+
"""
137+
Delete an index from the Moss project.
138+
139+
Use this tool to remove an index and all its documents when it is no longer needed.
140+
141+
Args:
142+
index_name (str): The name of the index to delete.
143+
144+
Returns:
145+
str: A confirmation message indicating the index was deleted.
146+
147+
"""
148+
await self.client.delete_index(index_name)
149+
if index_name == self.index_name:
150+
self._index_loaded = False
151+
return f"Index '{index_name}' has been deleted."

llama-index-integrations/tools/llama-index-tools-moss/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "llama-index-tools-moss"
7-
version = "0.1.0"
7+
version = "0.2.0"
88
description = "llama-index tools moss integration"
99
authors = [{name = "Roaim Khan", email = "roaimkhan459@gmail.com"}]
1010
requires-python = ">=3.9,<4.0"

0 commit comments

Comments
 (0)