From afc27e38414e9d0529598aab5e8708a30c8e08bf Mon Sep 17 00:00:00 2001 From: thierrypdamiba Date: Tue, 3 Mar 2026 05:19:51 -0800 Subject: [PATCH] fix collaborator query excluding all papers, improve graph insights prompt * stop excluding qdrant-retrieved pmids from collaborator search since the goal is finding people, not new papers * tell the LLM to report empty tool results instead of hiding them * revert the neo4j result filtering so all tool outputs reach the summarizer --- .../services/hybrid_service/neo4j_query.py | 12 ++++++------ .../hybrid_service/prompts/hybrid_prompts.py | 6 ++---- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/biomedical_graphrag/application/services/hybrid_service/neo4j_query.py b/src/biomedical_graphrag/application/services/hybrid_service/neo4j_query.py index 610e680..bf17cba 100644 --- a/src/biomedical_graphrag/application/services/hybrid_service/neo4j_query.py +++ b/src/biomedical_graphrag/application/services/hybrid_service/neo4j_query.py @@ -63,9 +63,11 @@ def get_collaborators_with_topics( """ Get collaborators for an author filtered by MeSH topics. Uses case-insensitive CONTAINS matching for flexibility. - Optionally excludes papers already retrieved by Qdrant. + Note: exclude_pmids is accepted but intentionally not applied here. + Collaborator networks should be computed across all shared papers, + including those already retrieved by Qdrant, since the goal is to + surface people (not new papers). """ - exclude_pmids = exclude_pmids or [] if require_all: topic_clauses = "\n".join( f"MATCH (p)-[:HAS_MESH_TERM]->(m{i}:MeshTerm) WHERE toLower(m{i}.term) CONTAINS toLower($topic_{i})" @@ -74,21 +76,19 @@ def get_collaborators_with_topics( cypher = f""" MATCH (a1:Author)-[:WROTE]->(p:Paper)<-[:WROTE]-(a2:Author) WHERE toLower(a1.name) CONTAINS toLower($author_name) AND a1 <> a2 - AND NOT p.pmid IN $exclude_pmids WITH DISTINCT a2, p {topic_clauses} RETURN DISTINCT a2.name as collaborator, COUNT(DISTINCT p) as papers ORDER BY papers DESC LIMIT 10 """ - params: dict[str, Any] = {"author_name": author_name, "exclude_pmids": exclude_pmids} + params: dict[str, Any] = {"author_name": author_name} for i, topic in enumerate(topics): params[f"topic_{i}"] = topic else: cypher = """ MATCH (a1:Author)-[:WROTE]->(p:Paper)<-[:WROTE]-(a2:Author) WHERE toLower(a1.name) CONTAINS toLower($author_name) AND a1 <> a2 - AND NOT p.pmid IN $exclude_pmids WITH DISTINCT a2, p MATCH (p)-[:HAS_MESH_TERM]->(m:MeshTerm) WHERE ANY(topic IN $topics WHERE toLower(m.term) CONTAINS toLower(topic)) @@ -98,7 +98,7 @@ def get_collaborators_with_topics( ORDER BY papers DESC LIMIT 10 """ - params = {"author_name": author_name, "topics": topics, "exclude_pmids": exclude_pmids} + params = {"author_name": author_name, "topics": topics} return self.query(cypher, params) def get_related_papers_by_mesh( diff --git a/src/biomedical_graphrag/application/services/hybrid_service/prompts/hybrid_prompts.py b/src/biomedical_graphrag/application/services/hybrid_service/prompts/hybrid_prompts.py index eb0c4b6..5eacef6 100644 --- a/src/biomedical_graphrag/application/services/hybrid_service/prompts/hybrid_prompts.py +++ b/src/biomedical_graphrag/application/services/hybrid_service/prompts/hybrid_prompts.py @@ -86,7 +86,7 @@ - Always cite PMIDs inline like (PMID: 12345678) - Be precise and factual, no speculation - Keep each section focused and concise -- Write Graph Insights for EVERY non-empty Neo4j tool result. Only skip Graph Insights entirely if ALL Neo4j tools returned empty arrays. +- Write Graph Insights for EVERY Neo4j tool that was called. For tools that returned results, summarize what was found. For tools that returned empty, briefly note what was searched and that no matches were found (e.g. "No collaborators found for Author X on these topics"). This helps the researcher understand what the graph does and does not contain. - Do NOT mention "Qdrant" or "Neo4j" by name. Refer to them as "retrieved literature" and "knowledge graph" User Question: @@ -124,11 +124,9 @@ def fusion_summary_prompt( Returns: The fusion summary prompt. """ - # Filter out empty tool results so the LLM focuses on what actually returned data - filtered_neo4j = {k: v for k, v in neo4j_results.items() if v} return FUSION_SUMMARY_PROMPT.format( question=question, qdrant_context=_format_qdrant_points(qdrant_results), - neo4j_results=json.dumps(filtered_neo4j, indent=2) if filtered_neo4j else "No graph results.", + neo4j_results=json.dumps(neo4j_results, indent=2), limit=limit, )