opencode-skills-collection 3.1.10 → 3.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled-skills/.antigravity-install-manifest.json +8 -1
- package/bundled-skills/browser-testing-with-devtools/SKILL.md +334 -0
- package/bundled-skills/docs/integrations/jetski-cortex.md +3 -3
- package/bundled-skills/docs/integrations/jetski-gemini-loader/README.md +1 -1
- package/bundled-skills/docs/maintainers/repo-growth-seo.md +3 -3
- package/bundled-skills/docs/maintainers/skills-update-guide.md +1 -1
- package/bundled-skills/docs/sources/sources.md +4 -0
- package/bundled-skills/docs/users/bundles.md +1 -1
- package/bundled-skills/docs/users/claude-code-skills.md +1 -1
- package/bundled-skills/docs/users/gemini-cli-skills.md +1 -1
- package/bundled-skills/docs/users/getting-started.md +1 -1
- package/bundled-skills/docs/users/kiro-integration.md +1 -1
- package/bundled-skills/docs/users/usage.md +4 -4
- package/bundled-skills/docs/users/visual-guide.md +4 -4
- package/bundled-skills/drizzle-migration-conflict/SKILL.md +179 -0
- package/bundled-skills/drizzle-migration-conflict/references/ci-policy.md +87 -0
- package/bundled-skills/drizzle-migration-conflict/references/conflict-resolution.md +163 -0
- package/bundled-skills/drizzle-migration-conflict/references/report-template.md +69 -0
- package/bundled-skills/drizzle-migration-conflict/references/sources.md +51 -0
- package/bundled-skills/drizzle-migration-conflict/scripts/check_drizzle_migrations.py +721 -0
- package/bundled-skills/frontend-lighthouse/SKILL.md +348 -0
- package/bundled-skills/pre-release-review/SKILL.md +198 -0
- package/bundled-skills/pre-release-review/references/checklist.md +104 -0
- package/bundled-skills/pre-release-review/references/report-template.md +91 -0
- package/bundled-skills/re-create/SKILL.md +251 -0
- package/bundled-skills/weaviate/SKILL.md +132 -0
- package/bundled-skills/weaviate/references/ask.md +36 -0
- package/bundled-skills/weaviate/references/create_collection.md +152 -0
- package/bundled-skills/weaviate/references/environment_requirements.md +34 -0
- package/bundled-skills/weaviate/references/example_data.md +24 -0
- package/bundled-skills/weaviate/references/explore_collection.md +50 -0
- package/bundled-skills/weaviate/references/fetch_filter.md +88 -0
- package/bundled-skills/weaviate/references/get_collection.md +32 -0
- package/bundled-skills/weaviate/references/hybrid_search.md +47 -0
- package/bundled-skills/weaviate/references/import_data.md +160 -0
- package/bundled-skills/weaviate/references/keyword_search.md +38 -0
- package/bundled-skills/weaviate/references/list_collections.md +31 -0
- package/bundled-skills/weaviate/references/query_search.md +38 -0
- package/bundled-skills/weaviate/references/semantic_search.md +46 -0
- package/bundled-skills/weaviate/scripts/ask.py +106 -0
- package/bundled-skills/weaviate/scripts/create_collection.py +359 -0
- package/bundled-skills/weaviate/scripts/example_data.py +945 -0
- package/bundled-skills/weaviate/scripts/explore_collection.py +295 -0
- package/bundled-skills/weaviate/scripts/fetch_filter.py +261 -0
- package/bundled-skills/weaviate/scripts/get_collection.py +122 -0
- package/bundled-skills/weaviate/scripts/hybrid_search.py +157 -0
- package/bundled-skills/weaviate/scripts/import.py +701 -0
- package/bundled-skills/weaviate/scripts/keyword_search.py +142 -0
- package/bundled-skills/weaviate/scripts/list_collections.py +77 -0
- package/bundled-skills/weaviate/scripts/query_search.py +135 -0
- package/bundled-skills/weaviate/scripts/semantic_search.py +139 -0
- package/bundled-skills/weaviate/scripts/weaviate_conn.py +231 -0
- package/bundled-skills/weaviate-cookbooks/SKILL.md +67 -0
- package/bundled-skills/weaviate-cookbooks/references/advanced_rag.md +274 -0
- package/bundled-skills/weaviate-cookbooks/references/agentic_rag.md +360 -0
- package/bundled-skills/weaviate-cookbooks/references/async_client.md +428 -0
- package/bundled-skills/weaviate-cookbooks/references/basic_agent.md +270 -0
- package/bundled-skills/weaviate-cookbooks/references/basic_rag.md +219 -0
- package/bundled-skills/weaviate-cookbooks/references/data_explorer.md +336 -0
- package/bundled-skills/weaviate-cookbooks/references/environment_requirements.md +78 -0
- package/bundled-skills/weaviate-cookbooks/references/frontend_interface.md +104 -0
- package/bundled-skills/weaviate-cookbooks/references/pdf_multimodal_rag.md +635 -0
- package/bundled-skills/weaviate-cookbooks/references/project_setup.md +75 -0
- package/bundled-skills/weaviate-cookbooks/references/query_agent_chatbot.md +163 -0
- package/package.json +1 -1
- package/skills_index.json +156 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# /// script
|
|
3
|
+
# dependencies = [
|
|
4
|
+
# "weaviate-client==4.19.2",
|
|
5
|
+
# "typer==0.21.0",
|
|
6
|
+
# ]
|
|
7
|
+
# ///
|
|
8
|
+
"""
|
|
9
|
+
Keyword (BM25) search on a Weaviate collection.
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
uv run keyword_search.py --query "your query" --collection "CollectionName" [--limit 10] [--json]
|
|
13
|
+
|
|
14
|
+
Environment Variables:
|
|
15
|
+
WEAVIATE_URL: Weaviate Cloud cluster URL
|
|
16
|
+
WEAVIATE_API_KEY: API key for authentication
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import json
|
|
20
|
+
import sys
|
|
21
|
+
|
|
22
|
+
import typer
|
|
23
|
+
import weaviate
|
|
24
|
+
from weaviate.classes.query import MetadataQuery
|
|
25
|
+
|
|
26
|
+
# Import shared connection utilities (local to this skill)
|
|
27
|
+
from weaviate_conn import get_client
|
|
28
|
+
|
|
29
|
+
app = typer.Typer()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def parse_properties(properties_str: str | None) -> list[str] | None:
|
|
33
|
+
"""Parse comma-separated property names with optional boost."""
|
|
34
|
+
if not properties_str:
|
|
35
|
+
return None
|
|
36
|
+
return [p.strip() for p in properties_str.split(",") if p.strip()]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@app.command()
|
|
40
|
+
def main(
|
|
41
|
+
query: str = typer.Option(..., "--query", "-q", help="Keyword search query"),
|
|
42
|
+
collection: str = typer.Option(..., "--collection", "-c", help="Collection name"),
|
|
43
|
+
limit: int = typer.Option(10, "--limit", "-l", help="Maximum results to return"),
|
|
44
|
+
properties: str = typer.Option(
|
|
45
|
+
None,
|
|
46
|
+
"--properties",
|
|
47
|
+
"-p",
|
|
48
|
+
help="Properties to search with optional boost (e.g., 'title^2,content')",
|
|
49
|
+
),
|
|
50
|
+
json_output: bool = typer.Option(False, "--json", help="Output in JSON format"),
|
|
51
|
+
):
|
|
52
|
+
"""Perform keyword (BM25) search on a Weaviate collection."""
|
|
53
|
+
query_properties = parse_properties(properties)
|
|
54
|
+
|
|
55
|
+
try:
|
|
56
|
+
with get_client() as client:
|
|
57
|
+
if not client.collections.exists(collection):
|
|
58
|
+
print(f"Error: Collection '{collection}' not found.", file=sys.stderr)
|
|
59
|
+
raise typer.Exit(1)
|
|
60
|
+
|
|
61
|
+
coll = client.collections.use(collection)
|
|
62
|
+
|
|
63
|
+
print("Searching...", file=sys.stderr)
|
|
64
|
+
response = coll.query.bm25(
|
|
65
|
+
query=query,
|
|
66
|
+
limit=limit,
|
|
67
|
+
query_properties=query_properties,
|
|
68
|
+
return_metadata=MetadataQuery(score=True),
|
|
69
|
+
)
|
|
70
|
+
print("Done.", file=sys.stderr)
|
|
71
|
+
|
|
72
|
+
objects = []
|
|
73
|
+
for obj in response.objects:
|
|
74
|
+
obj_data = {
|
|
75
|
+
"uuid": str(obj.uuid),
|
|
76
|
+
"properties": dict(obj.properties),
|
|
77
|
+
"score": obj.metadata.score if obj.metadata else None,
|
|
78
|
+
}
|
|
79
|
+
objects.append(obj_data)
|
|
80
|
+
|
|
81
|
+
result = {
|
|
82
|
+
"query": query,
|
|
83
|
+
"collection": collection,
|
|
84
|
+
"limit": limit,
|
|
85
|
+
"query_properties": query_properties,
|
|
86
|
+
"objects": objects,
|
|
87
|
+
"object_count": len(objects),
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if json_output:
|
|
91
|
+
print(json.dumps(result, indent=2, default=str))
|
|
92
|
+
else:
|
|
93
|
+
print(f"## Keyword Search Results\n")
|
|
94
|
+
print(f"**Query:** {query}")
|
|
95
|
+
print(f"**Collection:** {collection}")
|
|
96
|
+
if query_properties:
|
|
97
|
+
print(f"**Properties:** {', '.join(query_properties)}")
|
|
98
|
+
print(f"**Found:** {len(objects)} objects\n")
|
|
99
|
+
|
|
100
|
+
if objects:
|
|
101
|
+
all_props = set()
|
|
102
|
+
for obj in objects:
|
|
103
|
+
all_props.update(obj.get("properties", {}).keys())
|
|
104
|
+
sorted_props = sorted(list(all_props))
|
|
105
|
+
|
|
106
|
+
headers = ["#", "UUID", "Score"] + sorted_props
|
|
107
|
+
header_row = "| " + " | ".join(headers) + " |"
|
|
108
|
+
separator_row = "| " + " | ".join(["---"] * len(headers)) + " |"
|
|
109
|
+
|
|
110
|
+
print(header_row)
|
|
111
|
+
print(separator_row)
|
|
112
|
+
|
|
113
|
+
for idx, obj in enumerate(objects, 1):
|
|
114
|
+
score = obj.get("score")
|
|
115
|
+
score_str = f"{score:.4f}" if score is not None else "N/A"
|
|
116
|
+
row_data = [
|
|
117
|
+
str(idx),
|
|
118
|
+
str(obj.get("uuid", "N/A")),
|
|
119
|
+
score_str,
|
|
120
|
+
]
|
|
121
|
+
|
|
122
|
+
props = obj.get("properties", {})
|
|
123
|
+
for prop in sorted_props:
|
|
124
|
+
val = props.get(prop, "-")
|
|
125
|
+
val_str = str(val).replace("\n", " ").replace("|", "\\|")
|
|
126
|
+
row_data.append(val_str)
|
|
127
|
+
|
|
128
|
+
print("| " + " | ".join(row_data) + " |")
|
|
129
|
+
print()
|
|
130
|
+
else:
|
|
131
|
+
print("No objects found matching the query.\n")
|
|
132
|
+
|
|
133
|
+
except weaviate.exceptions.WeaviateConnectionError as e:
|
|
134
|
+
print(f"Error: Connection failed - {e}", file=sys.stderr)
|
|
135
|
+
raise typer.Exit(1)
|
|
136
|
+
except Exception as e:
|
|
137
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
138
|
+
raise typer.Exit(1)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
if __name__ == "__main__":
|
|
142
|
+
app()
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# /// script
|
|
3
|
+
# dependencies = [
|
|
4
|
+
# "weaviate-client==4.19.2",
|
|
5
|
+
# "typer==0.21.0",
|
|
6
|
+
# ]
|
|
7
|
+
# ///
|
|
8
|
+
"""
|
|
9
|
+
List all Weaviate collections.
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
uv run list_collections.py [--json]
|
|
13
|
+
|
|
14
|
+
Environment Variables:
|
|
15
|
+
WEAVIATE_URL: Weaviate Cloud cluster URL
|
|
16
|
+
WEAVIATE_API_KEY: API key for authentication
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import json
|
|
20
|
+
import sys
|
|
21
|
+
|
|
22
|
+
import typer
|
|
23
|
+
import weaviate
|
|
24
|
+
|
|
25
|
+
# Import shared connection utilities (local to this skill)
|
|
26
|
+
from weaviate_conn import get_client
|
|
27
|
+
|
|
28
|
+
app = typer.Typer()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@app.command()
|
|
32
|
+
def main(
|
|
33
|
+
json_output: bool = typer.Option(False, "--json", help="Output in JSON format"),
|
|
34
|
+
):
|
|
35
|
+
"""List all Weaviate collections."""
|
|
36
|
+
try:
|
|
37
|
+
with get_client() as client:
|
|
38
|
+
print("Fetching collections...", file=sys.stderr)
|
|
39
|
+
collections = client.collections.list_all(simple=False)
|
|
40
|
+
print(f"Found {len(collections)} collections.", file=sys.stderr)
|
|
41
|
+
|
|
42
|
+
if json_output:
|
|
43
|
+
result = []
|
|
44
|
+
for name, config in collections.items():
|
|
45
|
+
result.append(
|
|
46
|
+
{
|
|
47
|
+
"name": name,
|
|
48
|
+
"description": config.description,
|
|
49
|
+
"properties": [
|
|
50
|
+
{"name": p.name, "data_type": str(p.data_type)}
|
|
51
|
+
for p in config.properties
|
|
52
|
+
],
|
|
53
|
+
}
|
|
54
|
+
)
|
|
55
|
+
print(json.dumps(result, indent=2, default=str))
|
|
56
|
+
else:
|
|
57
|
+
if not collections:
|
|
58
|
+
print("No collections found.")
|
|
59
|
+
else:
|
|
60
|
+
print("## Collections\n")
|
|
61
|
+
print("| Name | Description | Properties |")
|
|
62
|
+
print("|------|-------------|------------|")
|
|
63
|
+
for name, config in collections.items():
|
|
64
|
+
props = ", ".join([p.name for p in config.properties])
|
|
65
|
+
desc = config.description or "N/A"
|
|
66
|
+
print(f"| {name} | {desc} | {props} |")
|
|
67
|
+
|
|
68
|
+
except weaviate.exceptions.WeaviateConnectionError as e:
|
|
69
|
+
print(f"Error: Connection failed - {e}", file=sys.stderr)
|
|
70
|
+
raise typer.Exit(1)
|
|
71
|
+
except Exception as e:
|
|
72
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
73
|
+
raise typer.Exit(1)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
if __name__ == "__main__":
|
|
77
|
+
app()
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# /// script
|
|
3
|
+
# dependencies = [
|
|
4
|
+
# "weaviate-client==4.19.2",
|
|
5
|
+
# "weaviate-agents==1.2.0",
|
|
6
|
+
# "typer==0.21.0",
|
|
7
|
+
# ]
|
|
8
|
+
# ///
|
|
9
|
+
"""
|
|
10
|
+
Query Weaviate using Query Agent in Search mode.
|
|
11
|
+
|
|
12
|
+
Usage:
|
|
13
|
+
uv run search.py --query "your query" --collections "Collection1,Collection2" [--limit 10] [--json]
|
|
14
|
+
|
|
15
|
+
Environment Variables:
|
|
16
|
+
WEAVIATE_URL: Weaviate Cloud cluster URL
|
|
17
|
+
WEAVIATE_API_KEY: API key for authentication
|
|
18
|
+
+ Any provider API keys (OPENAI_API_KEY, COHERE_API_KEY, etc.) - auto-detected
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
import json
|
|
22
|
+
import sys
|
|
23
|
+
|
|
24
|
+
import typer
|
|
25
|
+
import weaviate
|
|
26
|
+
from weaviate.agents.query import QueryAgent
|
|
27
|
+
|
|
28
|
+
# Import shared connection utilities (local to this skill)
|
|
29
|
+
from weaviate_conn import get_client
|
|
30
|
+
|
|
31
|
+
app = typer.Typer()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def parse_collections(collections_str: str) -> list[str]:
|
|
35
|
+
"""Parse comma-separated collection names."""
|
|
36
|
+
collections = [c.strip() for c in collections_str.split(",") if c.strip()]
|
|
37
|
+
if not collections:
|
|
38
|
+
print("Error: At least one collection name required", file=sys.stderr)
|
|
39
|
+
raise typer.Exit(1)
|
|
40
|
+
return collections
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@app.command()
|
|
44
|
+
def main(
|
|
45
|
+
query: str = typer.Option(
|
|
46
|
+
..., "--query", "-q", help="Natural language search query"
|
|
47
|
+
),
|
|
48
|
+
collections: str = typer.Option(
|
|
49
|
+
..., "--collections", "-c", help="Comma-separated collection names"
|
|
50
|
+
),
|
|
51
|
+
limit: int = typer.Option(10, "--limit", "-l", help="Maximum results to return"),
|
|
52
|
+
json_output: bool = typer.Option(False, "--json", help="Output in JSON format"),
|
|
53
|
+
):
|
|
54
|
+
"""Query Weaviate using Query Agent in Search mode (retrieves raw objects)."""
|
|
55
|
+
collection_list = parse_collections(collections)
|
|
56
|
+
|
|
57
|
+
try:
|
|
58
|
+
with get_client() as client:
|
|
59
|
+
agent = QueryAgent(client=client, collections=collection_list)
|
|
60
|
+
|
|
61
|
+
print("Searching...", file=sys.stderr)
|
|
62
|
+
response = agent.search(query, limit=limit)
|
|
63
|
+
print("Done.", file=sys.stderr)
|
|
64
|
+
|
|
65
|
+
# Extract objects from search results
|
|
66
|
+
objects = []
|
|
67
|
+
if hasattr(response, "search_results") and response.search_results:
|
|
68
|
+
search_results = response.search_results
|
|
69
|
+
if hasattr(search_results, "objects") and search_results.objects:
|
|
70
|
+
for obj in search_results.objects:
|
|
71
|
+
obj_data = {
|
|
72
|
+
"uuid": str(getattr(obj, "uuid", "")),
|
|
73
|
+
"collection": getattr(obj, "collection", None),
|
|
74
|
+
"properties": dict(getattr(obj, "properties", {})),
|
|
75
|
+
}
|
|
76
|
+
objects.append(obj_data)
|
|
77
|
+
|
|
78
|
+
result = {
|
|
79
|
+
"query": query,
|
|
80
|
+
"collections": collection_list,
|
|
81
|
+
"limit": limit,
|
|
82
|
+
"objects": objects,
|
|
83
|
+
"object_count": len(objects),
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if json_output:
|
|
87
|
+
print(json.dumps(result, indent=2, default=str))
|
|
88
|
+
else:
|
|
89
|
+
print(f"## Search Results\n")
|
|
90
|
+
print(f"**Query:** {query}")
|
|
91
|
+
print(f"**Collections:** {', '.join(collection_list)}")
|
|
92
|
+
print(f"**Found:** {len(objects)} objects\n")
|
|
93
|
+
|
|
94
|
+
if objects:
|
|
95
|
+
# Collect all property keys
|
|
96
|
+
all_props = set()
|
|
97
|
+
for obj in objects:
|
|
98
|
+
all_props.update(obj.get("properties", {}).keys())
|
|
99
|
+
sorted_props = sorted(list(all_props))
|
|
100
|
+
|
|
101
|
+
headers = ["#", "UUID", "Collection"] + sorted_props
|
|
102
|
+
header_row = "| " + " | ".join(headers) + " |"
|
|
103
|
+
separator_row = "| " + " | ".join(["---"] * len(headers)) + " |"
|
|
104
|
+
|
|
105
|
+
print(header_row)
|
|
106
|
+
print(separator_row)
|
|
107
|
+
|
|
108
|
+
for idx, obj in enumerate(objects, 1):
|
|
109
|
+
row_data = [
|
|
110
|
+
str(idx),
|
|
111
|
+
str(obj.get("uuid", "N/A")),
|
|
112
|
+
str(obj.get("collection", "N/A")),
|
|
113
|
+
]
|
|
114
|
+
|
|
115
|
+
props = obj.get("properties", {})
|
|
116
|
+
for prop in sorted_props:
|
|
117
|
+
val = props.get(prop, "-")
|
|
118
|
+
val_str = str(val).replace("\n", " ").replace("|", "\\|")
|
|
119
|
+
row_data.append(val_str)
|
|
120
|
+
|
|
121
|
+
print("| " + " | ".join(row_data) + " |")
|
|
122
|
+
print()
|
|
123
|
+
else:
|
|
124
|
+
print("No objects found matching the query.\n")
|
|
125
|
+
|
|
126
|
+
except weaviate.exceptions.WeaviateConnectionError as e:
|
|
127
|
+
print(f"Error: Connection failed - {e}", file=sys.stderr)
|
|
128
|
+
raise typer.Exit(1)
|
|
129
|
+
except Exception as e:
|
|
130
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
131
|
+
raise typer.Exit(1)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
if __name__ == "__main__":
|
|
135
|
+
app()
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# /// script
|
|
3
|
+
# dependencies = [
|
|
4
|
+
# "weaviate-client==4.19.2",
|
|
5
|
+
# "typer==0.21.0",
|
|
6
|
+
# ]
|
|
7
|
+
# ///
|
|
8
|
+
"""
|
|
9
|
+
Semantic (vector) search on a Weaviate collection.
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
uv run semantic_search.py --query "your query" --collection "CollectionName" [--limit 10] [--json]
|
|
13
|
+
|
|
14
|
+
Environment Variables:
|
|
15
|
+
WEAVIATE_URL: Weaviate Cloud cluster URL
|
|
16
|
+
WEAVIATE_API_KEY: API key for authentication
|
|
17
|
+
+ Any provider API keys (OPENAI_API_KEY, COHERE_API_KEY, etc.) - auto-detected
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import json
|
|
21
|
+
import sys
|
|
22
|
+
|
|
23
|
+
import typer
|
|
24
|
+
import weaviate
|
|
25
|
+
from weaviate.classes.query import MetadataQuery
|
|
26
|
+
|
|
27
|
+
# Import shared connection utilities (local to this skill)
|
|
28
|
+
from weaviate_conn import get_client
|
|
29
|
+
|
|
30
|
+
app = typer.Typer()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@app.command()
|
|
34
|
+
def main(
|
|
35
|
+
query: str = typer.Option(..., "--query", "-q", help="Search query text"),
|
|
36
|
+
collection: str = typer.Option(..., "--collection", "-c", help="Collection name"),
|
|
37
|
+
limit: int = typer.Option(10, "--limit", "-l", help="Maximum results to return"),
|
|
38
|
+
distance: float = typer.Option(
|
|
39
|
+
None, "--distance", "-d", help="Maximum distance threshold"
|
|
40
|
+
),
|
|
41
|
+
target_vector: str = typer.Option(
|
|
42
|
+
None,
|
|
43
|
+
"--target-vector",
|
|
44
|
+
"-t",
|
|
45
|
+
help="Target vector name for named vector collections",
|
|
46
|
+
),
|
|
47
|
+
json_output: bool = typer.Option(False, "--json", help="Output in JSON format"),
|
|
48
|
+
):
|
|
49
|
+
"""Perform semantic (vector similarity) search on a Weaviate collection."""
|
|
50
|
+
try:
|
|
51
|
+
with get_client() as client:
|
|
52
|
+
if not client.collections.exists(collection):
|
|
53
|
+
print(f"Error: Collection '{collection}' not found.", file=sys.stderr)
|
|
54
|
+
raise typer.Exit(1)
|
|
55
|
+
|
|
56
|
+
coll = client.collections.use(collection)
|
|
57
|
+
|
|
58
|
+
print("Searching...", file=sys.stderr)
|
|
59
|
+
response = coll.query.near_text(
|
|
60
|
+
query=query,
|
|
61
|
+
limit=limit,
|
|
62
|
+
distance=distance,
|
|
63
|
+
target_vector=target_vector,
|
|
64
|
+
return_metadata=MetadataQuery(distance=True),
|
|
65
|
+
)
|
|
66
|
+
print("Done.", file=sys.stderr)
|
|
67
|
+
|
|
68
|
+
objects = []
|
|
69
|
+
for obj in response.objects:
|
|
70
|
+
obj_data = {
|
|
71
|
+
"uuid": str(obj.uuid),
|
|
72
|
+
"properties": dict(obj.properties),
|
|
73
|
+
"distance": obj.metadata.distance if obj.metadata else None,
|
|
74
|
+
}
|
|
75
|
+
objects.append(obj_data)
|
|
76
|
+
|
|
77
|
+
result = {
|
|
78
|
+
"query": query,
|
|
79
|
+
"collection": collection,
|
|
80
|
+
"limit": limit,
|
|
81
|
+
"distance_threshold": distance,
|
|
82
|
+
"target_vector": target_vector,
|
|
83
|
+
"objects": objects,
|
|
84
|
+
"object_count": len(objects),
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if json_output:
|
|
88
|
+
print(json.dumps(result, indent=2, default=str))
|
|
89
|
+
else:
|
|
90
|
+
print(f"## Semantic Search Results\n")
|
|
91
|
+
print(f"**Query:** {query}")
|
|
92
|
+
print(f"**Collection:** {collection}")
|
|
93
|
+
if distance:
|
|
94
|
+
print(f"**Max Distance:** {distance}")
|
|
95
|
+
print(f"**Found:** {len(objects)} objects\n")
|
|
96
|
+
|
|
97
|
+
if objects:
|
|
98
|
+
all_props = set()
|
|
99
|
+
for obj in objects:
|
|
100
|
+
all_props.update(obj.get("properties", {}).keys())
|
|
101
|
+
sorted_props = sorted(list(all_props))
|
|
102
|
+
|
|
103
|
+
headers = ["#", "UUID", "Distance"] + sorted_props
|
|
104
|
+
header_row = "| " + " | ".join(headers) + " |"
|
|
105
|
+
separator_row = "| " + " | ".join(["---"] * len(headers)) + " |"
|
|
106
|
+
|
|
107
|
+
print(header_row)
|
|
108
|
+
print(separator_row)
|
|
109
|
+
|
|
110
|
+
for idx, obj in enumerate(objects, 1):
|
|
111
|
+
dist = obj.get("distance")
|
|
112
|
+
dist_str = f"{dist:.4f}" if dist is not None else "N/A"
|
|
113
|
+
row_data = [
|
|
114
|
+
str(idx),
|
|
115
|
+
str(obj.get("uuid", "N/A")),
|
|
116
|
+
dist_str,
|
|
117
|
+
]
|
|
118
|
+
|
|
119
|
+
props = obj.get("properties", {})
|
|
120
|
+
for prop in sorted_props:
|
|
121
|
+
val = props.get(prop, "-")
|
|
122
|
+
val_str = str(val).replace("\n", " ").replace("|", "\\|")
|
|
123
|
+
row_data.append(val_str)
|
|
124
|
+
|
|
125
|
+
print("| " + " | ".join(row_data) + " |")
|
|
126
|
+
print()
|
|
127
|
+
else:
|
|
128
|
+
print("No objects found matching the query.\n")
|
|
129
|
+
|
|
130
|
+
except weaviate.exceptions.WeaviateConnectionError as e:
|
|
131
|
+
print(f"Error: Connection failed - {e}", file=sys.stderr)
|
|
132
|
+
raise typer.Exit(1)
|
|
133
|
+
except Exception as e:
|
|
134
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
135
|
+
raise typer.Exit(1)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
if __name__ == "__main__":
|
|
139
|
+
app()
|