Files
playbook/antigravity-awesome-skills/skills/weaviate-cookbooks/references/basic_rag.md
T
2026-06-29 16:09:10 +00:00

6.2 KiB

Basic RAG Cookbook

Build basic RAG functionality with Weaviate. For advanced strategies, see here.

Docs to reference if needed:

Core Rules

  • Use a virtual environment via venv
  • Use uv for Python project/dependency management.
  • Do not manually author pyproject.toml or uv.lock; let uv generate/update them.
  • Use this install set: uv add weaviate-client python-dotenv dspy
  • Customise this cookbook to the users specification, ask them for details if not given.

Assume the user has data already to be used, do not create data unless asked to.

Env Rules

Mandatory:

  • WEAVIATE_URL
  • WEAVIATE_API_KEY

External provider keys:

  • Fill only keys actually used by the target Weaviate collection setup.

Weaviate Client

import os
from weaviate import connect_to_weaviate_cloud

client = connect_to_weaviate_cloud(
    cluster_url=os.getenv("WEAVIATE_URL", ""),
    auth_credentials=os.getenv("WEAVIATE_API_KEY", ""),
    headers={
        "X-OpenAI-Api-Key": os.getenv("OPENAI_API_KEY")
    },
)

If the user's collections require vectorizer provider keys, set the matching keys listed in environment_requirements.md.

Clients must be closed after completion. Wrap in try/finally blocks with client.close() (and client.connect() to reconnect if needed).

Multi-tenancy

Multi-tenancy should be checked via

config = await collection.config.get()
config.multi_tenancy_config.enabled # bool

e.g.


base_collection = client.collections.use(collection_name)

config = collection.config.get()
if config.multi_tenancy_config.enabled:
    collection = base_collection.with_tenant("<tenant_name>")
else:
    collection = base_collection

Tenant names can be obtained via

all_tenants = list(collection.tenants.get().keys())

Basic Retrieval

Use collections via

collection = client.collections.use("<collection_name>")

Weaviate can use vector, keyword or hybrid search.

collection.query.near_text # semantic (text)
collection.query.bm25 # keyword
collection.query.hybrid # blend of keyword and semantic

It can also do image search

collection.query.near_image(
    near_image = ... # base 64 representation of image or Path object to image
)

Key Code Blocks

RAG should have 4 pieces of core functionality:

  1. Pre-retrieval
  2. Retrieval
  3. Post-retrieval
  4. Generation

These should all be separate functions and combined into a single function, leaving scope for later editing or for the user themselves to modify it, to keep it understandable.

Pre-retrieval

Transform the user question into a vector-database style (list of) query(ies). Basic RAG will provide no extra query transformations.

def query_transformation(query: str) -> list[str]:
    return [query]

Retrieval

def retrieve(
    query: str, 
    limit: int = 10,  # optional
    filters = [] # optional
    # additional arguments if required can go here and passed down to the search strategy
) -> list[dict]:
    
    # import client logic here

    collection = client.collections.use("<collection_name>")

    response = collection.query.near_text( # or hybrid, bm25, near_image
        query=query,
        limit=limit,
        filters=filters if filters else None
    )
    
    return [
        {
            **obj.properties,
            "uuid": obj.uuid
        } 
        for obj in response.objects
    ]

Post-Retrieval

Modify the output of retrieve. Basic RAG will provide no extra post-processing. But you can consider adding uniqueness checks, formatting to remove properties, or more.

def process_retrieval_results(objects: list[dict]) -> list[dict]:
    return objects

Generation

This step depends on your LLM framework, see below. Using DSPy:

import dspy
def generate(query: str, context: list[dict]) -> str:
    lm = dspy.LM("<model_name>") # e.g. gpt-5.2, gpt-5-mini, claude-sonnet-4-5, etc.
    answer = dspy.Predict("context, query -> answer") # inputs: context, query. outputs: answer
    pred = answer(context=context, query=query, lm=lm)
    return pred.answer # answer is then an attribute of pred

User-specific Customisations

If not specified ask the user about these points before implementing their respective strategies:

LLM Framework

You can use DSPy (works with all LiteLLM providers) or LiteLLM itself.

Alternatively, users can use a single model provider. What model provider will they use?

These may require additional installs.

Collections

Do collections already exist and what are they called? Does the user want to query multiple collections or just a single one? Does it need to be customisable?

What format is the data, images or text or something else? What vectoriser is the collection set up as? What API keys are needed?

Search strategy

Does the user want semantic, keyword or hybrid search?

Hybrid search has an alpha parameter, controlling tradeoff between keyword and semantic weights. alpha=1 is pure semantic, alpha=0 is pure keyword.

Troubleshooting

  • Weaviate startup host errors: ensure WEAVIATE_URL is full https://... URL.
  • For any other issues, refer to the official library/package documentation and use web search extensively for troubleshooting.

Done Criteria

  • Create test scripts to check each function works independently with test data. Tear down tests after completion, or create a proper test suite with pytest (requires install)
  • User has completed specification of the app.