chore: import upstream snapshot with attribution
Test Suites / Build CI Environment (push) Has been cancelled
Test Suites / Basic Tests (push) Has been cancelled
Test Suites / End-to-End Tests (push) Has been cancelled
Test Suites / CLI Tests (push) Has been cancelled
Test Suites / Slow End-to-End Tests (push) Has been cancelled
Test Suites / Graph Database Tests (push) Has been cancelled
Test Suites / Vector DB Tests (push) Has been cancelled
Test Suites / Temporal Graph Test (push) Has been cancelled
Test Suites / Search Test on Different DBs (push) Has been cancelled
Test Suites / Example Tests (push) Has been cancelled
Test Suites / Notebook Tests (push) Has been cancelled
Test Suites / OS and Python Tests Ubuntu (push) Has been cancelled
Test Suites / OS and Python Tests Extended (push) Has been cancelled
Test Suites / LLM Test Suite (push) Has been cancelled
Test Suites / S3 File Storage Test (push) Has been cancelled
Test Suites / Run Integration Tests (push) Has been cancelled
Test Suites / MCP Tests (push) Has been cancelled
Test Suites / Docker Compose Test (push) Has been cancelled
Test Suites / Docker CI test (push) Has been cancelled
Test Suites / Relational DB Migration Tests (push) Has been cancelled
Test Suites / Distributed Cognee Test (push) Has been cancelled
Test Suites / DB Examples Tests (push) Has been cancelled
Test Suites / Test Completion Status (push) Has been cancelled
Test Suites / Claude Code Review (push) Has been cancelled
Test Suites / basic checks (push) Has been cancelled
build | Build and Push Cognee MCP Docker Image to dockerhub / docker-build-and-push (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
build | Build and Push Docker Image to dockerhub / docker-build-and-push (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges Core Functionality (3.11) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges Core Functionality (3.12) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges with Different Graph Databases (kuzu, kuzu) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges with Different Graph Databases (neo4j, neo4j) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges Examples (push) Has been cancelled
Weighted Edges Tests / Code Quality for Weighted Edges (push) Has been cancelled
Test Suites / Build CI Environment (push) Has been cancelled
Test Suites / Basic Tests (push) Has been cancelled
Test Suites / End-to-End Tests (push) Has been cancelled
Test Suites / CLI Tests (push) Has been cancelled
Test Suites / Slow End-to-End Tests (push) Has been cancelled
Test Suites / Graph Database Tests (push) Has been cancelled
Test Suites / Vector DB Tests (push) Has been cancelled
Test Suites / Temporal Graph Test (push) Has been cancelled
Test Suites / Search Test on Different DBs (push) Has been cancelled
Test Suites / Example Tests (push) Has been cancelled
Test Suites / Notebook Tests (push) Has been cancelled
Test Suites / OS and Python Tests Ubuntu (push) Has been cancelled
Test Suites / OS and Python Tests Extended (push) Has been cancelled
Test Suites / LLM Test Suite (push) Has been cancelled
Test Suites / S3 File Storage Test (push) Has been cancelled
Test Suites / Run Integration Tests (push) Has been cancelled
Test Suites / MCP Tests (push) Has been cancelled
Test Suites / Docker Compose Test (push) Has been cancelled
Test Suites / Docker CI test (push) Has been cancelled
Test Suites / Relational DB Migration Tests (push) Has been cancelled
Test Suites / Distributed Cognee Test (push) Has been cancelled
Test Suites / DB Examples Tests (push) Has been cancelled
Test Suites / Test Completion Status (push) Has been cancelled
Test Suites / Claude Code Review (push) Has been cancelled
Test Suites / basic checks (push) Has been cancelled
build | Build and Push Cognee MCP Docker Image to dockerhub / docker-build-and-push (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
build | Build and Push Docker Image to dockerhub / docker-build-and-push (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges Core Functionality (3.11) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges Core Functionality (3.12) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges with Different Graph Databases (kuzu, kuzu) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges with Different Graph Databases (neo4j, neo4j) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges Examples (push) Has been cancelled
Weighted Edges Tests / Code Quality for Weighted Edges (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
"""Demo: the Semantic Memory Map.
|
||||
|
||||
Runs a real cognee pipeline (add → cognify) and renders the knowledge graph
|
||||
with ``visualize_graph``. The resulting HTML has a **Semantic** tab that lays
|
||||
the graph out by *meaning*: every node is placed at the 2-D projection of its
|
||||
embedding, so semantically similar nodes cluster together — a view the classic
|
||||
topology layout can't show.
|
||||
|
||||
Nothing here patches the HTML. The semantic tab is produced by the production
|
||||
render path itself:
|
||||
|
||||
fetch_node_embeddings (join graph nodes to their stored vectors)
|
||||
-> semantic_layout.compute_positions (PCA, pinned)
|
||||
-> compute_clusters (k-means + nearest neighbors)
|
||||
-> cognee_network_visualization (token substitution)
|
||||
|
||||
Requirements: an LLM + embedding key in the environment (e.g. ``LLM_API_KEY``),
|
||||
exactly as ``cognify`` already needs. With no embeddings the tab simply shows a
|
||||
friendly empty state — the classic render never breaks.
|
||||
|
||||
Run:
|
||||
python examples/python/semantic_memory_map.py
|
||||
Then open the printed HTML and click the **Semantic** tab (or append
|
||||
``#semantic`` to deep-link straight to it).
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
import cognee
|
||||
from cognee.api.v1.visualize.visualize import visualize_graph
|
||||
|
||||
DEST = os.path.join(os.path.expanduser("~"), "semantic_memory_map.html")
|
||||
|
||||
# A few short, deliberately multi-topic passages so distinct clusters emerge:
|
||||
# computing pioneers, jazz, and ocean science.
|
||||
TEXT = """
|
||||
Ada Lovelace worked with Charles Babbage on the Analytical Engine in London.
|
||||
Alan Turing formalized computation and broke ciphers at Bletchley Park.
|
||||
Grace Hopper built the first compiler and worked on the Harvard Mark I.
|
||||
|
||||
Miles Davis recorded Kind of Blue, a landmark modal jazz album, in New York.
|
||||
John Coltrane played saxophone with the Miles Davis Quintet before A Love Supreme.
|
||||
Bill Evans, the pianist on Kind of Blue, shaped its impressionistic harmony.
|
||||
|
||||
Marine biologists study coral reefs, which host a quarter of all ocean species.
|
||||
Rising sea temperatures cause coral bleaching, threatening reef ecosystems.
|
||||
Phytoplankton in the ocean produce a large share of the planet's oxygen.
|
||||
"""
|
||||
|
||||
|
||||
async def main():
|
||||
await cognee.prune.prune_data()
|
||||
await cognee.prune.prune_system(metadata=True)
|
||||
|
||||
await cognee.add(TEXT)
|
||||
await cognee.cognify()
|
||||
|
||||
html = await visualize_graph(destination_file_path=DEST)
|
||||
|
||||
has_semantic = 'data-view="semantic"' in html
|
||||
has_positions = "window._semanticPositions = null" not in html
|
||||
print(f"\nSaved: {DEST}")
|
||||
print(f"Semantic tab present: {has_semantic}")
|
||||
print(f"Semantic positions set: {has_positions}")
|
||||
print("\nOpen the file and click the Semantic tab (or append #semantic to the URL).")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,177 @@
|
||||
"""Truth-Subspace Reranking — runnable demo.
|
||||
|
||||
What it shows
|
||||
-------------
|
||||
A finished "session" teaches the system a preference (here: the user cares about
|
||||
*coffee*, not tea). We distill that into deterministic centroid slots, project
|
||||
every corpus chunk onto those slots, and store the per-chunk coordinates on the
|
||||
graph node. At query time the HYBRID retriever reads current-epoch coordinates
|
||||
and nudges ranking toward the learned preference.
|
||||
|
||||
The demo retrieves the SAME ambiguous query twice — once with truth weighting OFF
|
||||
(exact baseline) and once ON — and prints a side-by-side rank diff so you can see
|
||||
the coffee chunks rise.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
- An LLM + embeddings provider configured (e.g. LLM_API_KEY in your .env). cognify
|
||||
and retrieval call the embedding/LLM APIs.
|
||||
|
||||
Run it
|
||||
------
|
||||
python examples/python/truth_subspace_reranking_demo.py
|
||||
|
||||
It uses a dedicated dataset ("truth_subspace_demo") and does NOT prune, so it will
|
||||
not touch your other cognee data. Re-running is safe (adds are content-addressed,
|
||||
the subspace build is a full recompute).
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Run against THIS checkout of cognee even if a different copy is pip-installed,
|
||||
# so the truth-subspace code in this working tree is the one that executes.
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")))
|
||||
|
||||
import cognee
|
||||
from cognee.context_global_variables import set_database_global_context_variables
|
||||
from cognee.modules.data.methods import get_authorized_existing_datasets
|
||||
from cognee.modules.retrieval.hybrid.results import payload, result_id
|
||||
from cognee.modules.retrieval.hybrid_retriever import HybridRetriever
|
||||
from cognee.modules.truth_subspace.build import build_truth_subspace
|
||||
from cognee.modules.users.methods import get_default_user
|
||||
|
||||
DATASET = "truth_subspace_demo"
|
||||
CORPUS_NODE_SET = ["beverages"]
|
||||
LESSONS_NODE_SET = ["session_learnings"] # the node set build_truth_subspace reads learnings from
|
||||
|
||||
# A small two-theme corpus. Each short doc becomes its own chunk.
|
||||
CORPUS = [
|
||||
"Espresso is brewed by forcing hot water through finely ground coffee under high pressure.",
|
||||
"A pour-over coffee drips a slow stream of hot water over a paper filter of ground coffee.",
|
||||
"Cold brew coffee steeps coarse coffee grounds in cold water for twelve hours or more.",
|
||||
"A French press steeps coffee grounds in hot water, then a metal plunger separates them.",
|
||||
"Green tea is brewed with water below boiling to avoid a bitter, astringent flavor.",
|
||||
"Black tea is steeped in fully boiling water for three to five minutes before serving.",
|
||||
"Herbal tisanes are caffeine-free infusions of dried herbs, flowers, and dried fruit.",
|
||||
"Matcha is a powdered green tea whisked into hot water with a bamboo whisk until frothy.",
|
||||
]
|
||||
|
||||
# What a finished session "learned" about the user. These fill the truth centroid
|
||||
# slots. They are about coffee, so coffee chunks align more strongly.
|
||||
LESSONS = [
|
||||
"The user is a dedicated coffee drinker who cares about espresso extraction and pour-over technique.",
|
||||
"We learned the user wants coffee brewing recommendations specifically, and is not interested in tea.",
|
||||
"For this user, coffee details — grind size, water temperature, and bloom time — matter most.",
|
||||
]
|
||||
|
||||
QUERY = "How should I prepare my morning drink at home?"
|
||||
|
||||
# Number of chunks to rank.
|
||||
TOP_K = len(CORPUS)
|
||||
|
||||
|
||||
def _theme(text: str) -> str:
|
||||
coffee = ("coffee", "espresso", "pour-over", "french press", "cold brew")
|
||||
return "☕ coffee" if any(w in text.lower() for w in coffee) else "🍵 tea "
|
||||
|
||||
|
||||
def _snippet(text: str, width: int = 62) -> str:
|
||||
text = " ".join(text.split())
|
||||
return text if len(text) <= width else text[: width - 1] + "…"
|
||||
|
||||
|
||||
async def ranked_chunks(dataset_obj, query: str, use_truth_weight: bool):
|
||||
"""Return the hybrid retriever's ranked chunk dicts, within the dataset's DB context."""
|
||||
async with set_database_global_context_variables(dataset_obj.id, dataset_obj.owner_id):
|
||||
retriever = HybridRetriever(
|
||||
chunks_top_k=TOP_K,
|
||||
entities_top_k=0, # focus the demo on chunk-lane reranking
|
||||
facts_top_k=0,
|
||||
node_name=CORPUS_NODE_SET, # rank only the corpus, not the lesson chunks
|
||||
use_truth_weight=use_truth_weight,
|
||||
)
|
||||
objects = await retriever.get_retrieved_objects(query=query)
|
||||
return objects.get("chunks", [])
|
||||
|
||||
|
||||
def _text(chunk) -> str:
|
||||
return payload(chunk).get("text", "")
|
||||
|
||||
|
||||
def print_ranking(title: str, chunks: list):
|
||||
print(f"\n{title}")
|
||||
print(" " + "-" * 74)
|
||||
for i, chunk in enumerate(chunks, 1):
|
||||
text = _text(chunk)
|
||||
print(f" {i:>2}. {_theme(text)} {_snippet(text)}")
|
||||
|
||||
|
||||
def print_diff(baseline: list, truthful: list):
|
||||
base_rank = {result_id(c): i for i, c in enumerate(baseline, 1)}
|
||||
print("\nRANK CHANGE WITH TRUTH WEIGHTING ON (vs baseline)")
|
||||
print(" " + "-" * 74)
|
||||
for new_rank, chunk in enumerate(truthful, 1):
|
||||
cid = result_id(chunk)
|
||||
old = base_rank.get(cid)
|
||||
if old is None:
|
||||
delta = " new"
|
||||
elif old > new_rank:
|
||||
delta = f" ↑{old - new_rank}"
|
||||
elif old < new_rank:
|
||||
delta = f" ↓{new_rank - old}"
|
||||
else:
|
||||
delta = " ="
|
||||
text = _text(chunk)
|
||||
print(f" {new_rank:>2}. {_theme(text)} {_snippet(text, 52)}{delta}")
|
||||
|
||||
|
||||
async def main():
|
||||
print("=" * 78)
|
||||
print("Truth-Subspace Reranking demo")
|
||||
print("=" * 78)
|
||||
|
||||
# 1) Ingest the corpus and build the knowledge graph.
|
||||
print(f"\n[1/5] Adding {len(CORPUS)} corpus docs and cognifying (dataset='{DATASET}')…")
|
||||
await cognee.add(CORPUS, dataset_name=DATASET, node_set=CORPUS_NODE_SET)
|
||||
await cognee.cognify(datasets=[DATASET])
|
||||
|
||||
user = await get_default_user()
|
||||
datasets = await get_authorized_existing_datasets([DATASET], "write", user)
|
||||
dataset_obj = datasets[0]
|
||||
|
||||
# 2) Baseline ranking — truth weighting OFF (exact current behavior).
|
||||
print(f"\n[2/5] Baseline retrieval (truth weighting OFF) for:\n “{QUERY}”")
|
||||
baseline = await ranked_chunks(dataset_obj, QUERY, use_truth_weight=False)
|
||||
print_ranking("BASELINE RANKING", baseline)
|
||||
|
||||
# 3) A finished session's learnings → seed the session_learnings node set.
|
||||
print(f"\n[3/5] Recording {len(LESSONS)} session learnings (favoring coffee)…")
|
||||
await cognee.add(LESSONS, dataset_name=DATASET, node_set=LESSONS_NODE_SET)
|
||||
await cognee.cognify(datasets=[DATASET])
|
||||
|
||||
# 4) Build the truth subspace: lesson centroids -> coords on every corpus chunk.
|
||||
print("\n[4/5] Building the truth subspace (build_truth_subspace)…")
|
||||
result = await build_truth_subspace(dataset=DATASET, session_ids=None, user=user)
|
||||
print(f" centroid_slots={result['anchors']} nodes_scored={result['nodes_scored']}")
|
||||
if result["anchors"] == 0 or result["nodes_scored"] == 0:
|
||||
print(" ⚠ No centroid slots or no scored nodes — truth weighting will be a no-op.")
|
||||
|
||||
# 5) Truth-weighted ranking — same query, truth weighting ON.
|
||||
print("\n[5/5] Retrieval with truth weighting ON for the same query…")
|
||||
truthful = await ranked_chunks(dataset_obj, QUERY, use_truth_weight=True)
|
||||
print_ranking("TRUTH-WEIGHTED RANKING", truthful)
|
||||
|
||||
print_diff(baseline, truthful)
|
||||
|
||||
base_top = _theme(_text(baseline[0])) if baseline else "?"
|
||||
truth_top = _theme(_text(truthful[0])) if truthful else "?"
|
||||
print("\n" + "=" * 78)
|
||||
print(f"Top result moved from {base_top.strip()} → {truth_top.strip()}")
|
||||
print("The learned coffee preference reshaped retrieval ordering. ✔")
|
||||
print("=" * 78)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user