136 lines
4.7 KiB
Python
136 lines
4.7 KiB
Python
#!/usr/bin/env python3
|
|
# /// script
|
|
# dependencies = [
|
|
# "weaviate-client==4.19.2",
|
|
# "weaviate-agents==1.2.0",
|
|
# "typer==0.21.0",
|
|
# ]
|
|
# ///
|
|
"""
|
|
Query Weaviate using Query Agent in Search mode.
|
|
|
|
Usage:
|
|
uv run search.py --query "your query" --collections "Collection1,Collection2" [--limit 10] [--json]
|
|
|
|
Environment Variables:
|
|
WEAVIATE_URL: Weaviate Cloud cluster URL
|
|
WEAVIATE_API_KEY: API key for authentication
|
|
+ Any provider API keys (OPENAI_API_KEY, COHERE_API_KEY, etc.) - auto-detected
|
|
"""
|
|
|
|
import json
|
|
import sys
|
|
|
|
import typer
|
|
import weaviate
|
|
from weaviate.agents.query import QueryAgent
|
|
|
|
# Import shared connection utilities (local to this skill)
|
|
from weaviate_conn import get_client
|
|
|
|
app = typer.Typer()
|
|
|
|
|
|
def parse_collections(collections_str: str) -> list[str]:
|
|
"""Parse comma-separated collection names."""
|
|
collections = [c.strip() for c in collections_str.split(",") if c.strip()]
|
|
if not collections:
|
|
print("Error: At least one collection name required", file=sys.stderr)
|
|
raise typer.Exit(1)
|
|
return collections
|
|
|
|
|
|
@app.command()
|
|
def main(
|
|
query: str = typer.Option(
|
|
..., "--query", "-q", help="Natural language search query"
|
|
),
|
|
collections: str = typer.Option(
|
|
..., "--collections", "-c", help="Comma-separated collection names"
|
|
),
|
|
limit: int = typer.Option(10, "--limit", "-l", help="Maximum results to return"),
|
|
json_output: bool = typer.Option(False, "--json", help="Output in JSON format"),
|
|
):
|
|
"""Query Weaviate using Query Agent in Search mode (retrieves raw objects)."""
|
|
collection_list = parse_collections(collections)
|
|
|
|
try:
|
|
with get_client() as client:
|
|
agent = QueryAgent(client=client, collections=collection_list)
|
|
|
|
print("Searching...", file=sys.stderr)
|
|
response = agent.search(query, limit=limit)
|
|
print("Done.", file=sys.stderr)
|
|
|
|
# Extract objects from search results
|
|
objects = []
|
|
if hasattr(response, "search_results") and response.search_results:
|
|
search_results = response.search_results
|
|
if hasattr(search_results, "objects") and search_results.objects:
|
|
for obj in search_results.objects:
|
|
obj_data = {
|
|
"uuid": str(getattr(obj, "uuid", "")),
|
|
"collection": getattr(obj, "collection", None),
|
|
"properties": dict(getattr(obj, "properties", {})),
|
|
}
|
|
objects.append(obj_data)
|
|
|
|
result = {
|
|
"query": query,
|
|
"collections": collection_list,
|
|
"limit": limit,
|
|
"objects": objects,
|
|
"object_count": len(objects),
|
|
}
|
|
|
|
if json_output:
|
|
print(json.dumps(result, indent=2, default=str))
|
|
else:
|
|
print(f"## Search Results\n")
|
|
print(f"**Query:** {query}")
|
|
print(f"**Collections:** {', '.join(collection_list)}")
|
|
print(f"**Found:** {len(objects)} objects\n")
|
|
|
|
if objects:
|
|
# Collect all property keys
|
|
all_props = set()
|
|
for obj in objects:
|
|
all_props.update(obj.get("properties", {}).keys())
|
|
sorted_props = sorted(list(all_props))
|
|
|
|
headers = ["#", "UUID", "Collection"] + sorted_props
|
|
header_row = "| " + " | ".join(headers) + " |"
|
|
separator_row = "| " + " | ".join(["---"] * len(headers)) + " |"
|
|
|
|
print(header_row)
|
|
print(separator_row)
|
|
|
|
for idx, obj in enumerate(objects, 1):
|
|
row_data = [
|
|
str(idx),
|
|
str(obj.get("uuid", "N/A")),
|
|
str(obj.get("collection", "N/A")),
|
|
]
|
|
|
|
props = obj.get("properties", {})
|
|
for prop in sorted_props:
|
|
val = props.get(prop, "-")
|
|
val_str = str(val).replace("\n", " ").replace("|", "\\|")
|
|
row_data.append(val_str)
|
|
|
|
print("| " + " | ".join(row_data) + " |")
|
|
print()
|
|
else:
|
|
print("No objects found matching the query.\n")
|
|
|
|
except weaviate.exceptions.WeaviateConnectionError as e:
|
|
print(f"Error: Connection failed - {e}", file=sys.stderr)
|
|
raise typer.Exit(1)
|
|
except Exception as e:
|
|
print(f"Error: {e}", file=sys.stderr)
|
|
raise typer.Exit(1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
app()
|