{ "cells": [ { "cell_type": "markdown", "id": "79ffcbff", "metadata": {}, "source": [ "# 01 — Quickstart: Connect & First Query\n", "\n", "This notebook assumes you already have the Fractal RAG stack running\n", "(either the [local docker-compose stack](../local-setup.md) on `localhost:8080`\n", "or the [K3s deployment](../hosted-vm.md) on `localhost:30080`) and that\n", "`fractal-rag ingest` has loaded at least the `docs` and `notebooks` sources.\n", "\n", "By the end of this notebook you'll have:\n", "\n", "1. Connected to Weaviate with the same Settings the CLI uses.\n", "2. Confirmed the schema and concept ontology are loaded.\n", "3. Run a hybrid search and inspected one full artifact." ] }, { "cell_type": "code", "execution_count": null, "id": "2190429b", "metadata": {}, "outputs": [], "source": [ "# If you used docker-compose locally, uncomment these:\n", "# import os\n", "# os.environ['FRACTAL_RAG_WEAVIATE_HTTP_PORT'] = '8080'\n", "# os.environ['FRACTAL_RAG_WEAVIATE_GRPC_PORT'] = '50051'\n", "\n", "from fractal_rag.client import client_session\n", "from fractal_rag.config import get_settings\n", "\n", "settings = get_settings(refresh=True)\n", "print(f'Targeting Weaviate at {settings.weaviate_http_host}:{settings.weaviate_http_port}')" ] }, { "cell_type": "markdown", "id": "86e3df5c", "metadata": {}, "source": [ "## Sanity check\n", "\n", "Make sure both collections exist and have objects." ] }, { "cell_type": "code", "execution_count": null, "id": "69ea2dd8", "metadata": {}, "outputs": [], "source": [ "from fractal_rag.client import client_session\n", "\n", "with client_session() as client:\n", " for name in (settings.artifact_collection, settings.concept_collection):\n", " if not client.collections.exists(name):\n", " print(f'{name}: MISSING')\n", " continue\n", " coll = client.collections.get(name)\n", " total = coll.aggregate.over_all(total_count=True).total_count\n", " print(f'{name}: {total} objects')" ] }, { "cell_type": "markdown", "id": "d126a1f3", "metadata": {}, "source": [ "## Browse the concept ontology\n", "\n", "The `Concept` collection holds 32 hand-curated entries. Listing them is the fastest way to orient yourself." ] }, { "cell_type": "code", "execution_count": null, "id": "d23cd9dd", "metadata": {}, "outputs": [], "source": [ "with client_session() as client:\n", " concept = client.collections.get(settings.concept_collection)\n", " response = concept.query.fetch_objects(limit=50)\n", " for o in response.objects:\n", " p = o.properties\n", " print(f\"- {p['name']} ({len(p.get('aliases') or [])} aliases) - domains: {p.get('domain')}\")" ] }, { "cell_type": "markdown", "id": "0eaf29b3", "metadata": {}, "source": [ "## Your first hybrid search\n", "\n", "`coll.query.hybrid(...)` mixes BM25 keyword scoring with vector similarity. `target_vector` picks **which** of the named vectors to compare against. Try `content_vec` (the body), `title_vec` (just the title), or `summary_vec` (the short summary)." ] }, { "cell_type": "code", "execution_count": null, "id": "67575694", "metadata": {}, "outputs": [], "source": [ "from weaviate.classes.query import MetadataQuery\n", "\n", "QUERY = 'Hausdorff dimension of the Cantor set'\n", "\n", "with client_session() as client:\n", " art = client.collections.get(settings.artifact_collection)\n", " response = art.query.hybrid(\n", " query=QUERY,\n", " limit=5,\n", " target_vector='content_vec',\n", " return_metadata=MetadataQuery(distance=True),\n", " )\n", "\n", "for o in response.objects:\n", " p = o.properties\n", " d = getattr(o.metadata, 'distance', None)\n", " print(f\"[{d:.3f}] {p.get('source_type')} {p.get('title')[:80]}\")" ] }, { "cell_type": "markdown", "id": "fea8ca2c", "metadata": {}, "source": [ "## Pull the full content of a hit\n", "\n", "The hybrid response only returns the headline fields. If you want to read the actual chunk content, fetch by UUID." ] }, { "cell_type": "code", "execution_count": null, "id": "20488545", "metadata": {}, "outputs": [], "source": [ "best = response.objects[0]\n", "with client_session() as client:\n", " art = client.collections.get(settings.artifact_collection)\n", " full = art.query.fetch_object_by_id(str(best.uuid))\n", "\n", "print(f\"TITLE : {full.properties.get('title')}\")\n", "print(f\"URI : {full.properties.get('source_uri')}\")\n", "print(f\"SUMMARY : {full.properties.get('summary')}\")\n", "print('CONTENT (first 800 chars):')\n", "print(full.properties.get('content', '')[:800])" ] }, { "cell_type": "markdown", "id": "845d7631", "metadata": {}, "source": [ "## Next steps\n", "\n", "- Try [02 — Hybrid search patterns](02_hybrid_search.ipynb) for `target_vector` tradeoffs, `alpha` tuning, and filters.\n", "- Or skip to [03 — Concept ontology](03_concept_ontology.ipynb) to walk the Concept side-collection and its cross-refs." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "name": "python3" } }, "nbformat": 4, "nbformat_minor": 5 }