File size: 5,700 Bytes
fe766f7 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | """
Advanced GSQL Queries for GraphRAG Novelties
=============================================
Queries that run inside TigerGraph for PPR, paths, and community detection.
Install once via: graph.install_advanced_queries()
"""
# ββ Personalized PageRank (CatRAG-inspired) ββββββββββββββ
PPR_QUERY = """
CREATE OR REPLACE QUERY pprFromSeeds(
SET<STRING> seedEntityIds,
FLOAT damping,
INT maxIter
) FOR GRAPH {graphname} {{
TYPEDEF TUPLE<STRING entity_id, STRING name, DOUBLE score> EntityPPR;
HeapAccum<EntityPPR>(50, score DESC) @@topEntities;
SumAccum<DOUBLE> @score;
SumAccum<DOUBLE> @newScore;
SumAccum<INT> @outDegree;
# Initialize
AllEntities = {{Entity.*}};
AllEntities = SELECT e FROM AllEntities:e
ACCUM e.@outDegree += 1;
Seeds = SELECT e FROM AllEntities:e
WHERE e.entity_id IN seedEntityIds
ACCUM e.@score += 1.0 / seedEntityIds.size();
# Power iteration
FOREACH iter IN RANGE[1, maxIter] DO
AllEntities = SELECT e FROM AllEntities:e -(RELATED_TO:rel)- Entity:nbr
ACCUM
DOUBLE contribution = CASE WHEN nbr.@outDegree > 0
THEN nbr.@score * damping * rel.weight / nbr.@outDegree
ELSE 0.0 END,
e.@newScore += contribution
POST-ACCUM
e.@score = e.@newScore + CASE WHEN e.entity_id IN seedEntityIds
THEN (1.0 - damping) / seedEntityIds.size()
ELSE 0.0 END,
e.@newScore = 0;
END;
# Collect top entities by PPR score
AllEntities = SELECT e FROM AllEntities:e
WHERE e.@score > 0.001
ACCUM @@topEntities += EntityPPR(e.entity_id, e.name, e.@score);
PRINT @@topEntities;
}}
INSTALL QUERY pprFromSeeds
"""
# ββ Shortest Path Between Entity Pairs βββββββββββββββββββ
SHORTEST_PATH_QUERY = """
CREATE OR REPLACE QUERY findReasoningPaths(
STRING sourceId,
STRING targetId,
INT maxDepth
) FOR GRAPH {graphname} {{
ListAccum<STRING> @pathTrace;
SetAccum<STRING> @@visitedNodes;
ListAccum<STRING> @@pathDescriptions;
Source = {{Entity.*}};
Source = SELECT e FROM Source:e WHERE e.entity_id == sourceId
ACCUM e.@pathTrace += e.name;
FOREACH depth IN RANGE[1, maxDepth] DO
Source = SELECT nbr FROM Source:e -(RELATED_TO:rel)- Entity:nbr
WHERE nbr.entity_id NOT IN @@visitedNodes
ACCUM
nbr.@pathTrace += e.@pathTrace,
nbr.@pathTrace += (" -[" + rel.relation_type + "]-> " + nbr.name),
@@visitedNodes += nbr.entity_id;
# Check if target reached
Target = SELECT e FROM Source:e WHERE e.entity_id == targetId
ACCUM @@pathDescriptions += e.@pathTrace;
END;
PRINT @@pathDescriptions;
}}
INSTALL QUERY findReasoningPaths
"""
# ββ Spreading Activation βββββββββββββββββββββββββββββββββ
SPREADING_ACTIVATION_QUERY = """
CREATE OR REPLACE QUERY spreadingActivation(
SET<STRING> seedEntityIds,
FLOAT decayFactor,
INT maxSteps,
FLOAT threshold
) FOR GRAPH {graphname} {{
TYPEDEF TUPLE<STRING entity_id, STRING name, DOUBLE activation> ActivatedEntity;
HeapAccum<ActivatedEntity>(100, activation DESC) @@activated;
SumAccum<DOUBLE> @activation;
SumAccum<DOUBLE> @newActivation;
# Initialize seeds
Seeds = {{Entity.*}};
Seeds = SELECT e FROM Seeds:e
WHERE e.entity_id IN seedEntityIds
ACCUM e.@activation += 1.0;
# Propagate
FOREACH step IN RANGE[1, maxSteps] DO
ActiveNodes = SELECT e FROM Seeds:e -(RELATED_TO:rel)- Entity:nbr
WHERE e.@activation > threshold
ACCUM
DOUBLE spread = e.@activation * rel.weight * decayFactor,
nbr.@newActivation += CASE WHEN spread > threshold THEN spread ELSE 0.0 END
POST-ACCUM
e.@activation = e.@newActivation,
e.@newActivation = 0;
END;
# Collect all activated entities
AllEntities = {{Entity.*}};
AllEntities = SELECT e FROM AllEntities:e
WHERE e.@activation > threshold
ACCUM @@activated += ActivatedEntity(e.entity_id, e.name, e.@activation);
PRINT @@activated;
}}
INSTALL QUERY spreadingActivation
"""
# ββ Get Entity Neighborhood for Community Detection ββββββ
ENTITY_NEIGHBORHOOD_QUERY = """
CREATE OR REPLACE QUERY getEntityNeighborhood(
SET<STRING> entityIds,
INT hops
) FOR GRAPH {graphname} {{
SetAccum<STRING> @@nodeIds;
SetAccum<STRING> @@edgeDescriptions;
SumAccum<INT> @@nodeCount;
SumAccum<INT> @@edgeCount;
Seeds = {{Entity.*}};
Seeds = SELECT e FROM Seeds:e WHERE e.entity_id IN entityIds
ACCUM @@nodeIds += e.entity_id, @@nodeCount += 1;
FOREACH hop IN RANGE[1, hops] DO
Seeds = SELECT nbr FROM Seeds:e -(RELATED_TO:rel)- Entity:nbr
WHERE nbr.entity_id NOT IN @@nodeIds
ACCUM
@@nodeIds += nbr.entity_id,
@@nodeCount += 1,
@@edgeCount += 1,
@@edgeDescriptions += (e.name + "|" + rel.relation_type + "|" + nbr.name + "|" + to_string(rel.weight));
END;
PRINT @@nodeIds, @@edgeDescriptions, @@nodeCount, @@edgeCount;
}}
INSTALL QUERY getEntityNeighborhood
"""
ALL_ADVANCED_QUERIES = {
"pprFromSeeds": PPR_QUERY,
"findReasoningPaths": SHORTEST_PATH_QUERY,
"spreadingActivation": SPREADING_ACTIVATION_QUERY,
"getEntityNeighborhood": ENTITY_NEIGHBORHOOD_QUERY,
}
|