diff --git a/cognee/infrastructure/databases/graph/kuzu/adapter.py b/cognee/infrastructure/databases/graph/kuzu/adapter.py index 12c15fb81..95174ec0e 100644 --- a/cognee/infrastructure/databases/graph/kuzu/adapter.py +++ b/cognee/infrastructure/databases/graph/kuzu/adapter.py @@ -1654,3 +1654,41 @@ class KuzuAdapter(GraphDBInterface): id_list = [row[0] for row in rows] return id_list + + async def apply_feedback_weight( + self, + node_ids: List[str], + weight: float, + ) -> None: + """ + Increment `feedback_weight` inside r.properties JSON for edges where + relationship_name = 'used_graph_element_to_answer'. + + """ + # Step 1: fetch matching edges + query = """ + MATCH (n:Node)-[r:EDGE]->() + WHERE n.id IN $node_ids AND r.relationship_name = 'used_graph_element_to_answer' + RETURN r.properties, n.id + """ + results = await self.query(query, {"node_ids": node_ids}) + + # Step 2: update JSON client-side + updates = [] + for props_json, source_id in results: + try: + props = json.loads(props_json) if props_json else {} + except json.JSONDecodeError: + props = {} + + props["feedback_weight"] = props.get("feedback_weight", 0) + weight + updates.append((source_id, json.dumps(props))) + + # Step 3: write back + for node_id, new_props in updates: + update_query = """ + MATCH (n:Node)-[r:EDGE]->() + WHERE n.id = $node_id AND r.relationship_name = 'used_graph_element_to_answer' + SET r.properties = $props + """ + await self.query(update_query, {"node_id": node_id, "props": new_props}) diff --git a/cognee/infrastructure/databases/graph/neo4j_driver/adapter.py b/cognee/infrastructure/databases/graph/neo4j_driver/adapter.py index 589848dc9..3ff9cb5be 100644 --- a/cognee/infrastructure/databases/graph/neo4j_driver/adapter.py +++ b/cognee/infrastructure/databases/graph/neo4j_driver/adapter.py @@ -1345,3 +1345,29 @@ class Neo4jAdapter(GraphDBInterface): id_list = [row["id"] for row in rows if "id" in row] return id_list + + async def apply_feedback_weight( + self, + node_ids: List[str], + weight: float, + ) -> None: + """ + Increment `feedback_weight` on relationships `:used_graph_element_to_answer` + outgoing from nodes whose `id` is in `node_ids`. + + Args: + node_ids: List of node IDs to match. + weight: Amount to add to `r.feedback_weight` (can be negative). + + Side effects: + Updates relationship property `feedback_weight`, defaulting missing values to 0. + """ + query = """ + MATCH (n)-[r]->() + WHERE n.id IN $node_ids AND r.relationship_name = 'used_graph_element_to_answer' + SET r.feedback_weight = coalesce(r.feedback_weight, 0) + $weight + """ + await self.query( + query, + params={"weight": float(weight), "node_ids": list(node_ids)}, + ) diff --git a/cognee/modules/retrieval/graph_completion_retriever.py b/cognee/modules/retrieval/graph_completion_retriever.py index c831d8550..fb3cf4885 100644 --- a/cognee/modules/retrieval/graph_completion_retriever.py +++ b/cognee/modules/retrieval/graph_completion_retriever.py @@ -248,6 +248,7 @@ class GraphCompletionRetriever(BaseRetriever): "source_node_id": source_id, "target_node_id": target_id_1, "ontology_valid": False, + "feedback_weight": 0, }, ) ) @@ -262,6 +263,7 @@ class GraphCompletionRetriever(BaseRetriever): "source_node_id": source_id, "target_node_id": target_id_2, "ontology_valid": False, + "feedback_weight": 0, }, ) ) diff --git a/cognee/modules/retrieval/user_qa_feedback.py b/cognee/modules/retrieval/user_qa_feedback.py index 45b5b0ec0..55c59518a 100644 --- a/cognee/modules/retrieval/user_qa_feedback.py +++ b/cognee/modules/retrieval/user_qa_feedback.py @@ -51,6 +51,7 @@ class UserQAFeedback(BaseFeedback): relationships = [] relationship_name = "gives_feedback_to" + to_node_ids = [] for interaction_id in last_interaction_ids: target_id_1 = feedback_id @@ -70,9 +71,16 @@ class UserQAFeedback(BaseFeedback): }, ) ) + to_node_ids.append(str(target_id_2)) + if len(relationships) > 0: graph_engine = await get_graph_engine() await graph_engine.add_edges(relationships) + await graph_engine.apply_feedback_weight( + node_ids=to_node_ids, + weight=feedback_sentiment.score + ) + return [feedback_text]