Files
playbook/antigravity-awesome-skills/skills/weaviate/scripts/example_data.py
T
2026-06-29 16:09:10 +00:00

946 lines
34 KiB
Python

#!/usr/bin/env python3
# /// script
# dependencies = [
# "weaviate-client==4.19.2",
# "weaviate-agents==1.2.0",
# "typer==0.21.0",
# "datasets>=4.5.0",
# ]
# ///
"""
Download an example dataset from the Hugging Face dataset hub.
Usage:
uv run example_data.py --domain "domain_name" --nrows "number_of_rows" --vectorizer "vectorizer_name"
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 sys
import typer
import weaviate
from weaviate.client import WeaviateClient
import re
from weaviate.classes.config import Property, DataType, Configure
from datasets import load_dataset
from datetime import datetime, timezone
# Import shared connection utilities (local to this skill)
from weaviate_conn import get_client
app = typer.Typer()
# Vectorizer string to config mapping
VECTORIZER_MAP = {
"text2vec_weaviate": lambda: Configure.Vectors.text2vec_weaviate(),
"text2vec_openai": lambda: Configure.Vectors.text2vec_openai(),
"text2vec_cohere": lambda: Configure.Vectors.text2vec_cohere(),
"text2vec_huggingface": lambda: Configure.Vectors.text2vec_huggingface(),
"text2vec_google_gemini": lambda: Configure.Vectors.text2vec_google_gemini(),
"text2vec_jinaai": lambda: Configure.Vectors.text2vec_jinaai(),
"text2vec_voyageai": lambda: Configure.Vectors.text2vec_voyageai(),
"text2vec_model2vec": lambda: Configure.Vectors.text2vec_model2vec(),
"text2vec_transformers": lambda: Configure.Vectors.text2vec_transformers(),
"text2vec_ollama": lambda: Configure.Vectors.text2vec_ollama(),
"multi2vec_clip": lambda: Configure.Vectors.multi2vec_clip(),
"multi2vec_bind": lambda: Configure.Vectors.multi2vec_bind(),
"none": lambda: Configure.Vectors.self_provided(),
}
def _get_sentences(document: str) -> tuple[list[str], list[tuple[int, int]]]:
"""
Split document into sentences based on sentence_boundaries.
Maintains original order and preserves boundaries in chunks.
Returns sentences and their character spans (start, end) in the original document.
"""
sentence_boundaries: list[str] = [".", "?", "!"]
if not sentence_boundaries or not document:
return ([document], [(0, len(document))]) if document else ([], [])
escaped_boundaries = [re.escape(boundary) for boundary in sentence_boundaries]
pattern = r"(?<=" + "|".join(escaped_boundaries) + r")\s+"
sentences = []
spans = []
current_pos = 0
for match in re.finditer(pattern, document):
sentence_end = match.start()
sentence = document[current_pos:sentence_end].strip()
if sentence:
sentences.append(sentence)
spans.append((current_pos, sentence_end))
current_pos = match.end()
remaining = document[current_pos:].strip()
if remaining:
sentences.append(remaining)
spans.append((current_pos, len(document)))
filtered_sentences = []
filtered_spans = []
for sentence, span in zip(sentences, spans):
if sentence:
filtered_sentences.append(sentence)
filtered_spans.append(span)
return (
(filtered_sentences, filtered_spans)
if filtered_sentences
else ([document], [(0, len(document))])
)
def chunk_by_sentences(
document: str,
num_sentences: int,
overlap_sentences: int = 1,
) -> tuple[list[str], list[tuple[int, int]]]:
"""
Given a document (string), return the sentences as chunks and span annotations (start and end indices of chunks).
"""
if overlap_sentences >= num_sentences:
print(
f"Warning: overlap_sentences ({overlap_sentences}) is greater than num_sentences ({num_sentences}). Setting overlap to {num_sentences - 1}"
)
overlap_sentences = num_sentences - 1
sentences = _get_sentences(document)
span_annotations = []
chunks = []
i = 0
while i < len(sentences[0]):
# Get chunk of num_sentences sentences
chunk_sentences = sentences[1][i : i + num_sentences]
if not chunk_sentences:
break
# Get start and end char positions
start_char = chunk_sentences[0][0]
end_char = chunk_sentences[-1][1]
# Add chunk and its span annotation
chunks.append(document[start_char:end_char])
span_annotations.append((start_char, end_char))
# Move forward but account for overlap
i += num_sentences - overlap_sentences
return chunks, span_annotations
def create_ai_arxiv_collection(
client: WeaviateClient, vectorizer: str = "text2vec_weaviate", nrows: int = 1000
):
# check existence of collection
if client.collections.exists("AI_Arxiv"):
print(
f"Collection 'AI_Arxiv' already exists. Cannot create. Returning.",
file=sys.stderr,
)
return
print(f"Creating collection 'AI_Arxiv'...", file=sys.stderr)
collection = client.collections.create(
"AI_Arxiv",
description="AI and machine learning research papers from arXiv, chunked by sentences for semantic search.",
properties=[
Property(
name="paper_id",
data_type=DataType.TEXT,
index_searchable=False,
description="Unique arXiv paper identifier (e.g., '2301.07041')",
),
Property(
name="title",
data_type=DataType.TEXT,
description="Title of the research paper",
),
Property(
name="summary",
data_type=DataType.TEXT,
description="Abstract or summary of the research paper",
),
Property(
name="source",
data_type=DataType.TEXT,
index_searchable=False,
description="URL or source link to the original arXiv paper",
),
Property(
name="authors",
data_type=DataType.TEXT,
description="Comma-separated list of paper authors",
),
Property(
name="categories",
data_type=DataType.TEXT,
description="arXiv subject categories (e.g., 'cs.LG', 'stat.ML')",
),
Property(
name="comment",
data_type=DataType.TEXT,
description="Additional comments or notes from the authors",
),
Property(
name="primary_category",
data_type=DataType.TEXT,
description="Primary arXiv subject category for the paper",
),
Property(
name="published",
data_type=DataType.DATE,
index_range_filters=True,
description="Date the paper was first published on arXiv",
),
Property(
name="updated",
data_type=DataType.DATE,
index_range_filters=True,
description="Date the paper was last updated on arXiv",
),
Property(
name="chunk",
data_type=DataType.TEXT,
description="Text chunk from the paper body used for semantic search",
),
Property(
name="chunk_start",
data_type=DataType.NUMBER,
index_range_filters=True,
description="Character offset where this chunk starts in the original document",
),
Property(
name="chunk_end",
data_type=DataType.NUMBER,
index_range_filters=True,
description="Character offset where this chunk ends in the original document",
),
],
vector_config=VECTORIZER_MAP[vectorizer](),
inverted_index_config=Configure.inverted_index(index_null_state=True),
)
dataset = load_dataset("jamescalam/ai-arxiv2", split="train", keep_in_memory=True)
nrows = nrows or len(dataset)
with collection.batch.fixed_size(batch_size=100) as batch:
for i in range(min(nrows, len(dataset))):
item = dataset[i]
if i % int(min(nrows, len(dataset)) / 10) == 0:
print(
f"Importing {i}/{min(nrows, len(dataset))} objects... (AI_Arxiv)",
file=sys.stderr,
)
if item and isinstance(item, dict):
chunks, span_annotations = chunk_by_sentences(
document=item["content"], num_sentences=15, overlap_sentences=0
)
del item["content"]
item["paper_id"] = item["id"]
del item["id"]
del item["references"]
item["published"] = (
datetime.strptime("20231126", "%Y%m%d").replace(tzinfo=timezone.utc)
if item["published"]
else None
)
item["updated"] = (
datetime.strptime("20231126", "%Y%m%d").replace(tzinfo=timezone.utc)
if item["updated"]
else None
)
for chunk, span in zip(chunks, span_annotations):
item["chunk"] = chunk
item["chunk_start"] = span[0]
item["chunk_end"] = span[1]
batch.add_object(properties=item)
if batch.number_errors > 10:
print(
"Batch import stopped due to excessive errors. Returning.",
file=sys.stderr,
)
break
failed_objects = collection.batch.failed_objects
if failed_objects:
print(
f"Number of failed imports: {len(failed_objects)}",
file=sys.stderr,
)
print(f"First failed object: {failed_objects[0]}", file=sys.stderr)
return
print(
f"Created collection 'AI_Arxiv' with {len(collection)} objects.",
file=sys.stderr,
)
def create_income_tax_returns_collection(
client: WeaviateClient, vectorizer: str = "text2vec_weaviate", nrows: int = 1000
):
# check existence of collection
if client.collections.exists("Income_Tax_Returns"):
print(
f"Collection 'Income_Tax_Returns' already exists. Cannot create. Returning.",
file=sys.stderr,
)
return
print(f"Creating collection 'Income_Tax_Returns'...", file=sys.stderr)
collection = client.collections.create(
"Income_Tax_Returns",
description="Indian income tax return filings with taxpayer details, financials, and filing metadata.",
properties=[
Property(
name="pan",
data_type=DataType.TEXT,
index_searchable=False,
description="Permanent Account Number (PAN) — unique tax identifier for the taxpayer",
),
Property(
name="acknowledgement_number",
data_type=DataType.TEXT,
index_searchable=False,
description="Government-issued acknowledgement number for the filed return",
),
Property(
name="name",
data_type=DataType.TEXT,
description="Full legal name of the taxpayer",
),
Property(
name="address",
data_type=DataType.TEXT,
index_searchable=False,
description="Street address of the taxpayer",
),
Property(
name="area",
data_type=DataType.TEXT,
description="Area or locality name within the city",
),
Property(
name="city", data_type=DataType.TEXT, description="City of residence"
),
Property(
name="state",
data_type=DataType.TEXT,
description="State or province of residence",
),
Property(
name="pincode",
data_type=DataType.NUMBER,
index_range_filters=True,
description="Postal PIN code for the taxpayer's address",
),
Property(
name="state_code",
data_type=DataType.TEXT,
description="Two-character state code",
),
Property(
name="country_code",
data_type=DataType.TEXT,
description="ISO two-character country code (e.g., 'IN' for India)",
),
Property(
name="entity",
data_type=DataType.TEXT,
description="Type of taxpayer entity (e.g., 'Individual', 'Company', 'HUF')",
),
Property(
name="form",
data_type=DataType.TEXT,
description="Tax form type used for filing (e.g., 'ITR-1', 'ITR-2')",
),
Property(
name="assessment_year_start",
data_type=DataType.DATE,
index_range_filters=True,
description="Start date of the tax assessment year",
),
Property(
name="assessment_year_end",
data_type=DataType.DATE,
index_range_filters=True,
description="End date of the tax assessment year",
),
Property(
name="filing_datetime",
data_type=DataType.DATE,
index_range_filters=True,
description="Date and time when the return was filed",
),
Property(
name="late_filing",
data_type=DataType.BOOL,
description="Whether the return was filed after the due date",
),
Property(
name="signatory",
data_type=DataType.TEXT,
description="Name of the authorized signatory on the return",
),
Property(
name="loss",
data_type=DataType.NUMBER,
index_range_filters=True,
description="Total loss amount in Indian Rupees (INR)",
),
Property(
name="income",
data_type=DataType.NUMBER,
index_range_filters=True,
description="Total taxable income in Indian Rupees (INR)",
),
Property(
name="tax",
data_type=DataType.NUMBER,
index_range_filters=True,
description="Total tax payable in Indian Rupees (INR)",
),
Property(
name="cess",
data_type=DataType.NUMBER,
index_range_filters=True,
description="Health and education cess amount in Indian Rupees (INR)",
),
Property(
name="interest",
data_type=DataType.NUMBER,
index_range_filters=True,
description="Interest payable or receivable in Indian Rupees (INR)",
),
Property(
name="total_payable",
data_type=DataType.NUMBER,
index_range_filters=True,
description="Total amount payable including tax, cess, and interest in Indian Rupees (INR)",
),
],
vector_config=VECTORIZER_MAP[vectorizer](),
inverted_index_config=Configure.inverted_index(index_null_state=True),
)
dataset = load_dataset(
"AgamiAI/Indian-Income-Tax-Returns", split="train", keep_in_memory=True
)
nrows = nrows or len(dataset)
with collection.batch.fixed_size(batch_size=100) as batch:
for i in range(min(nrows, len(dataset))):
item = dataset[i]
if i % int(min(nrows, len(dataset)) / 10) == 0:
print(
f"Importing {i}/{min(nrows, len(dataset))} objects... (Income_Tax_Returns)",
file=sys.stderr,
)
if item and isinstance(item, dict):
batch.add_object(
properties={
"pan": item["pan"],
"acknowledgement_number": item["acknowledgement_number"],
"name": item["name"],
"address": item["address"],
"area": item["area"],
"city": item["city"],
"state": item["state"],
"pincode": item["pincode"],
"state_code": item["state_code"],
"country_code": item["country_code"],
"entity": item["entity"],
"form": item["form"],
"assessment_year_start": datetime.strptime(
item["assessment_year"][:4], "%Y"
).replace(tzinfo=timezone.utc),
"assessment_year_end": datetime.strptime(
item["assessment_year"][5:], "%y"
).replace(tzinfo=timezone.utc),
"filing_datetime": datetime.strptime(
item["filing_time"], "%d-%b-%Y %H:%M:%S"
).replace(tzinfo=timezone.utc),
"late_filing": item["late_filing"],
"signatory": item["signatory"],
"loss": (
item["financials"]["loss"]
if "loss" in item["financials"]
else None
),
"income": (
item["financials"]["income"]
if "income" in item["financials"]
else None
),
"tax": (
item["financials"]["tax"]
if "tax" in item["financials"]
else None
),
"cess": (
item["financials"]["cess"]
if "cess" in item["financials"]
else None
),
"interest": (
item["financials"]["interest"]
if "interest" in item["financials"]
else None
),
"total_payable": (
item["financials"]["total_payable"]
if "total_payable" in item["financials"]
else None
),
}
)
if batch.number_errors > 10:
print(
"Batch import stopped due to excessive errors. Returning.",
file=sys.stderr,
)
break
failed_objects = collection.batch.failed_objects
if failed_objects:
print(
f"Number of failed imports: {len(failed_objects)}",
file=sys.stderr,
)
print(f"First failed object: {failed_objects[0]}", file=sys.stderr)
return
print(
f"Created collection 'Income_Tax_Returns' with {len(collection)} objects.",
file=sys.stderr,
)
def create_product_catalog_collection(
client: WeaviateClient, vectorizer: str = "text2vec_weaviate", nrows: int = 1000
):
# check existence of collection
if client.collections.exists("Product_Catalog"):
print(
f"Collection 'Product_Catalog' already exists. Cannot create. Returning.",
file=sys.stderr,
)
return
print(f"Creating collection 'Product_Catalog'...", file=sys.stderr)
collection = client.collections.create(
"Product_Catalog",
description="E-commerce product catalog with pricing, brand, weight, and three-level category hierarchy.",
properties=[
Property(
name="product_name",
data_type=DataType.TEXT,
description="Name or title of the product",
),
Property(
name="size",
data_type=DataType.TEXT,
description="Size specification of the product (e.g., 'Small', '250g', '1L')",
),
Property(
name="pack_type",
data_type=DataType.TEXT,
description="Type of packaging (e.g., 'Box', 'Bag', 'Bottle')",
),
Property(
name="organic_status",
data_type=DataType.TEXT,
description="Organic certification status of the product (e.g., 'Organic', 'Conventional')",
),
Property(
name="weight_kg",
data_type=DataType.NUMBER,
index_range_filters=True,
description="Product weight in kilograms",
),
Property(
name="brand",
data_type=DataType.TEXT,
description="Brand name of the product",
),
Property(
name="price_usd",
data_type=DataType.NUMBER,
index_range_filters=True,
description="Product price in US dollars (USD)",
),
Property(
name="category",
data_type=DataType.TEXT,
description="Top-level product category (L1)",
),
Property(
name="subcategory",
data_type=DataType.TEXT,
description="Second-level product subcategory (L2)",
),
Property(
name="subsubcategory",
data_type=DataType.TEXT,
description="Third-level product subcategory (L3)",
),
],
vector_config=VECTORIZER_MAP[vectorizer](),
inverted_index_config=Configure.inverted_index(index_null_state=True),
)
dataset = load_dataset(
"pkghf/ecom-product-catalog", split="train", keep_in_memory=True
)
nrows = nrows or len(dataset)
with collection.batch.fixed_size(batch_size=100) as batch:
for i in range(min(nrows, len(dataset))):
item = dataset[i]
if i % int(min(nrows, len(dataset)) / 10) == 0:
print(
f"Importing {i}/{min(nrows, len(dataset))} objects... (Product_Catalog)",
file=sys.stderr,
)
if item and isinstance(item, dict):
batch.add_object(
properties={
"product_name": item["product_name"],
"size": item["size"],
"pack_type": item["pack_type"],
"organic_status": item["organic_status"],
"weight_kg": item["weight_kg"],
"brand": item["brand"],
"price_usd": item["price_usd"],
"category": item["L1"],
"subcategory": item["L2"],
"subsubcategory": item["L3"],
}
)
if batch.number_errors > 10:
print(
"Batch import stopped due to excessive errors. Returning.",
file=sys.stderr,
)
break
failed_objects = collection.batch.failed_objects
if failed_objects:
print(
f"Number of failed imports: {len(failed_objects)}",
file=sys.stderr,
)
print(f"First failed object: {failed_objects[0]}", file=sys.stderr)
return
print(
f"Created collection 'Product_Catalog' with {len(collection)} objects.",
file=sys.stderr,
)
def duration_to_days(duration_str: str) -> float | None:
"""Convert a duration string like '4 weeks', '2-4 weeks', '14 days' to a number of days.
For ranges like '2-4 weeks', returns the average (3 weeks = 21 days).
"""
unit_to_days = {
"day": 1,
"days": 1,
"week": 7,
"weeks": 7,
"month": 30,
"months": 30,
"year": 365,
"years": 365,
}
match = re.match(
r"(\d+)(?:\s*-\s*(\d+))?\s+(days?|weeks?|months?|years?)",
duration_str.strip(),
re.IGNORECASE,
)
if not match:
return None
low = float(match.group(1))
high = float(match.group(2)) if match.group(2) else low
unit = match.group(3).lower()
avg = (low + high) / 2
return avg * unit_to_days[unit]
def create_hair_medical_collection(
client: WeaviateClient, vectorizer: str = "text2vec_weaviate", nrows: int = 1000
):
# check existence of collection
if client.collections.exists("Hair_Medical"):
print(
f"Collection 'Hair_Medical' already exists. Cannot create. Returning.",
file=sys.stderr,
)
return
print(f"Creating collection 'Hair_Medical'...", file=sys.stderr)
collection = client.collections.create(
"Hair_Medical",
description="Hair disease diagnoses with associated symptoms, medications, side effects, severity, and treatment duration.",
properties=[
Property(
name="side_effects",
data_type=DataType.TEXT,
description="Known side effects of the prescribed medication",
),
Property(
name="avg_duration_days",
data_type=DataType.NUMBER,
index_range_filters=True,
description="Average treatment duration in days",
),
Property(
name="symptoms",
data_type=DataType.TEXT,
description="Symptoms associated with the hair disease",
),
Property(
name="medication_description",
data_type=DataType.TEXT,
description="Description and mechanism of action of the medication",
),
Property(
name="hair_disease",
data_type=DataType.TEXT,
description="Name of the hair disease or condition being treated",
),
Property(
name="medication",
data_type=DataType.TEXT,
description="Name of the prescribed medication",
),
Property(
name="disease_description",
data_type=DataType.TEXT,
description="Detailed description of the hair disease or condition",
),
Property(
name="disease_severity",
data_type=DataType.TEXT,
description="Severity level of the disease (e.g., 'Mild', 'Moderate', 'Severe')",
),
],
vector_config=VECTORIZER_MAP[vectorizer](),
inverted_index_config=Configure.inverted_index(index_null_state=True),
)
dataset = load_dataset("Amod/hair_medical_sit", split="train", keep_in_memory=True)
nrows = nrows or len(dataset)
with collection.batch.fixed_size(batch_size=100) as batch:
for i in range(min(nrows, len(dataset))):
item = dataset[i]
if i % int(min(nrows, len(dataset)) / 10) == 0:
print(
f"Importing {i}/{min(nrows, len(dataset))} objects... (Hair_Medical)",
file=sys.stderr,
)
if item and isinstance(item, dict):
batch.add_object(
properties={
"side_effects": item["Side Effects"],
"avg_duration_days": duration_to_days(item["Duration"]),
"symptoms": item["Symptoms"],
"medication_description": item["Medication Description"],
"hair_disease": item["Hair Disease"],
"medication": item["Medication"],
"disease_description": item["Disease Description"],
"disease_severity": item[" Severity of Disease"],
}
)
if batch.number_errors > 10:
print(
"Batch import stopped due to excessive errors. Returning.",
file=sys.stderr,
)
break
failed_objects = collection.batch.failed_objects
if failed_objects:
print(
f"Number of failed imports: {len(failed_objects)}",
file=sys.stderr,
)
print(f"First failed object: {failed_objects[0]}", file=sys.stderr)
return
print(
f"Created collection 'Hair_Medical' with {len(collection)} objects.",
file=sys.stderr,
)
def create_helpdesk_tickets_collection(
client: WeaviateClient, vectorizer: str = "text2vec_weaviate", nrows: int = 1000
):
# check existence of collection
if client.collections.exists("IT_Support_Tickets"):
print(
f"Collection 'IT_Support_Tickets' already exists. Cannot create. Returning.",
file=sys.stderr,
)
return
print(f"Creating collection 'IT_Support_Tickets'...", file=sys.stderr)
collection = client.collections.create(
"IT_Support_Tickets",
description="Synthetic IT helpdesk support tickets with subject, description, priority, category, and requester details.",
properties=[
Property(
name="ticket_id",
data_type=DataType.TEXT,
index_searchable=False,
description="Unique identifier for the support ticket",
),
Property(
name="subject",
data_type=DataType.TEXT,
description="Short subject line summarizing the IT issue",
),
Property(
name="description",
data_type=DataType.TEXT,
description="Detailed description of the IT support issue reported by the requester",
),
Property(
name="priority",
data_type=DataType.TEXT,
description="Priority level of the ticket (e.g., 'Low', 'Medium', 'High', 'Critical')",
),
Property(
name="category",
data_type=DataType.TEXT,
description="Category of the IT issue (e.g., 'Hardware', 'Software', 'Network', 'Access')",
),
Property(
name="createdAt",
data_type=DataType.DATE,
index_range_filters=True,
description="Date and time when the ticket was created",
),
Property(
name="requesterEmail",
data_type=DataType.TEXT,
description="Email address of the person who submitted the ticket",
),
],
vector_config=VECTORIZER_MAP[vectorizer](),
inverted_index_config=Configure.inverted_index(index_null_state=True),
)
dataset = load_dataset(
"Console-AI/IT-helpdesk-synthetic-tickets", split="train", keep_in_memory=True
)
nrows = nrows or len(dataset)
with collection.batch.fixed_size(batch_size=100) as batch:
for i in range(min(nrows, len(dataset))):
item = dataset[i]
if i % int(min(nrows, len(dataset)) / 10) == 0:
print(
f"Importing {i}/{min(nrows, len(dataset))} objects... (IT_Support_Tickets)",
file=sys.stderr,
)
if item and isinstance(item, dict):
batch.add_object(
properties={
"ticket_id": item["id"],
"subject": item["subject"],
"description": item["description"],
"priority": item["priority"],
"category": item["category"],
"createdAt": datetime.strptime(
item["createdAt"], "%Y-%m-%dT%H:%M:%S.%fZ"
).replace(tzinfo=timezone.utc),
"requesterEmail": item["requesterEmail"],
}
)
if batch.number_errors > 10:
print(
"Batch import stopped due to excessive errors. Returning.",
file=sys.stderr,
)
break
failed_objects = collection.batch.failed_objects
if failed_objects:
print(
f"Number of failed imports: {len(failed_objects)}",
file=sys.stderr,
)
print(f"First failed object: {failed_objects[0]}", file=sys.stderr)
return
print(
f"Created collection 'IT_Support_Tickets' with {len(collection)} objects.",
file=sys.stderr,
)
@app.command()
def main(
domain: str = typer.Option("academic", "--domain", "-d"),
nrows: int = typer.Option(None, "--nrows", "-n"),
vectorizer: str = typer.Option(
"text2vec_weaviate",
"--vectorizer",
"-v",
help=f"Vectorizer to use. Options: {', '.join(VECTORIZER_MAP.keys())}",
),
):
"""Download an example dataset from the Hugging Face dataset hub."""
with get_client() as client:
if domain == "academic":
create_ai_arxiv_collection(client, vectorizer, nrows)
elif domain == "finance":
create_income_tax_returns_collection(client, vectorizer, nrows)
elif domain == "ecommerce":
create_product_catalog_collection(client, vectorizer, nrows)
elif domain == "medical":
create_hair_medical_collection(client, vectorizer, nrows)
elif domain == "customer_support":
create_helpdesk_tickets_collection(client, vectorizer, nrows)
else:
print(f"Domain '{domain}' not supported. Returning.", file=sys.stderr)
raise typer.Exit(1)
if __name__ == "__main__":
app()