Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions examples/python/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
MOSS_PROJECT_ID=your_project_id
MOSS_PROJECT_KEY=your_project_key
COHERE_API_KEY=your_cohere_api_key
3 changes: 2 additions & 1 deletion examples/python/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
moss>=1.0.0
-e sdks/python/sdk
cohere>=5.0.0
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
python-dotenv
openai
75 changes: 75 additions & 0 deletions examples/python/reranking_sample.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import asyncio
import json
import os

from dotenv import load_dotenv
from moss import MossClient, DocumentInfo, QueryOptions, RerankOptions

load_dotenv()

INDEX_NAME = "rerank-demo-full"


async def setup_index(client):
"""Delete old index, create fresh one with all FAQ data."""
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the delete old index step missing ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

darn, I think I removed it for a test and then forgot to add, let me do it real quick

faqs_path = os.path.join(os.path.dirname(__file__), "faqs.json")
with open(faqs_path, "r") as f:
faqs = json.load(f)

docs = [
DocumentInfo(
id=faq["id"],
text=faq["text"],
metadata={k: str(v) for k, v in faq.get("metadata", {}).items()},
)
for faq in faqs
]

print(f"Setting up index '{INDEX_NAME}'")
try:
await client.delete_index(INDEX_NAME)
print("Deleted old index.")
except Exception:
pass

await client.create_index(INDEX_NAME, docs)
print("Index created.")

await client.load_index(INDEX_NAME)
print("Index loaded.\n")


async def main():
client = MossClient(os.getenv("MOSS_PROJECT_ID"), os.getenv("MOSS_PROJECT_KEY"))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you please create .env.example

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


await setup_index(client)

print("Without Reranking")
results = await client.query(
INDEX_NAME,
"How to get discount?",
QueryOptions(top_k=5, alpha=0.8),
)
for i, doc in enumerate(results.docs):
print(f" {i + 1}. [{doc.score:.3f}] {doc.text[:100]}...")

print("\nWith Cohere Reranking")
results = await client.query(
INDEX_NAME,
"How to get discount?",
QueryOptions(
top_k=10,
alpha=0.8,
rerank=RerankOptions(
provider="cohere",
api_key=os.getenv("COHERE_API_KEY"),
top_n=5,
),
),
)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would reranking definition return type searchresult ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes it would be of this type

for i, doc in enumerate(results.docs):
print(f" {i + 1}. [{doc.score:.3f}] {doc.text[:100]}...")


if __name__ == "__main__":
asyncio.run(main())
4 changes: 4 additions & 0 deletions sdks/python/sdk/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ dependencies = [
]

[project.optional-dependencies]
cohere = [
"cohere>=5.0.0",
]
dev = [
"cohere>=5.0.0",
"pytest>=8.4.2",
"pytest-asyncio>=1.2.0",
"tox>=4.0.0",
Expand Down
126 changes: 64 additions & 62 deletions sdks/python/sdk/src/moss/__init__.py
Original file line number Diff line number Diff line change
@@ -1,62 +1,64 @@
"""
Moss Semantic Search SDK

Powerful Python SDK for semantic search using state-of-the-art embedding models.

Example:
```python
from moss import MossClient, DocumentInfo

client = MossClient('your-project-id', 'your-project-key')

docs = [DocumentInfo(id="1", text="Example document")]

result = await client.create_index('my-index', docs, 'moss-minilm')

await client.load_index('my-index')
results = await client.query('my-index', 'search query')
```
"""

from moss_core import (
DocumentInfo,
GetDocumentsOptions,
IndexInfo,
IndexStatus,
IndexStatusValues,
ModelRef,
MutationOptions,
MutationResult,
JobStatus,
JobPhase,
JobProgress,
JobStatusResponse,
QueryOptions,
QueryResultDocumentInfo,
SearchResult,
)

from .client.moss_client import MossClient

__version__ = "1.0.0b19"

__all__ = [
"MossClient",
# Core data types
"DocumentInfo",
"GetDocumentsOptions",
"IndexInfo",
"SearchResult",
"QueryResultDocumentInfo",
"ModelRef",
"IndexStatus",
"IndexStatusValues",
"QueryOptions",
# Mutation types
"MutationResult",
"MutationOptions",
"JobStatus",
"JobPhase",
"JobProgress",
"JobStatusResponse",
]
"""
Moss Semantic Search SDK

Powerful Python SDK for semantic search using state-of-the-art embedding models.

Example:
```python
from moss import MossClient, DocumentInfo

client = MossClient('your-project-id', 'your-project-key')

docs = [DocumentInfo(id="1", text="Example document")]

result = await client.create_index('my-index', docs, 'moss-minilm')

await client.load_index('my-index')
results = await client.query('my-index', 'search query')
```
"""

from moss_core import (
DocumentInfo,
GetDocumentsOptions,
IndexInfo,
IndexStatus,
IndexStatusValues,
ModelRef,
MutationOptions,
MutationResult,
JobStatus,
JobPhase,
JobProgress,
JobStatusResponse,
QueryResultDocumentInfo,
SearchResult,
)

from .client.models import QueryOptions, RerankOptions
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: QueryOptions replaced from Rust class to Python dataclass — backward compatibility

The PR replaces QueryOptions imported from moss_core (a Rust-backed class) with a new Python @dataclass in models.py:39-54. This is a significant type change. However, it is safe because MossClient never passes the QueryOptions object directly to Rust functions — it always extracts individual fields via getattr() (e.g., moss_client.py:230-238). All existing callers (test_hot_reload.py, test_cloud_fallback.py, test_search.py, examples, packages) use from moss import QueryOptions and construct it with keyword arguments like QueryOptions(top_k=5), which works identically with the new dataclass since it's a superset of the old fields.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

from .client.moss_client import MossClient

__version__ = "1.0.0b19"

__all__ = [
"MossClient",
# Core data types
"DocumentInfo",
"GetDocumentsOptions",
"IndexInfo",
"SearchResult",
"QueryResultDocumentInfo",
"ModelRef",
"IndexStatus",
"IndexStatusValues",
"QueryOptions",
# Mutation types
"MutationResult",
"MutationOptions",
"JobStatus",
"JobPhase",
"JobProgress",
"JobStatusResponse",
# Reranking
"RerankOptions",
]
Loading
Loading