"""Production graph-to-answer context adapter; no benchmark or oracle dependencies.""" from tools.answers.context_policy import joined_candidates def graph_context(result: dict) -> dict: """Remove storage/profile metadata that cannot answer the actual question. Uses only actual retrieval output and query intent, never gold annotations. Values/subjects/source paths are copied without inventing or rewriting facts. """ facts = [] intent = result["constraints"] shared_year_query = intent.get("mentions_shared") and intent.get("mentions_academic_year") work_listing = ( intent.get("mentions_work_listing", False) or shared_year_query or ( intent.get("mentions_title") and any( row.get("fact_type") in {"person_thesis", "person_work"} and not row.get("title") for row in result["facts"] ) ) ) academic_records = [] for row in [*result["facts"], *result.get("supporting_facts", [])]: kind = row.get("fact_type", "") if kind.startswith("shared_"): field = { "shared_keyword": "keyword", "shared_category": "category", "shared_document_author": "document_author", }.get(kind) if field: for side in ["left", "right"]: facts.append( { "person": row[f"{side}_person"], field: row[field], "document_path": row.get(f"{side}_document_path"), "source_url": row.get(f"{side}_source_url"), } ) continue if not row.get("person"): continue allowed = { "person", "document_path", "source_url", "keyword", "category", "document_author", } if intent["mentions_title"] or work_listing: allowed.add("title") if ( intent["mentions_title"] or intent["mentions_academic_year"] or intent["years"] or work_listing ): allowed.add("year") if intent["mentions_start_year"]: allowed.add("start_year") fact = {k: v for k, v in row.items() if k in allowed and v is not None} if (intent.get("thesis_types") or intent.get("work_types")) and kind in { "person_thesis", "person_work", }: work_type = row.get("thesis_type") or row.get("work_type") if work_type: fact["work_type"] = work_type if work_listing and kind in {"person_thesis", "person_work"}: # Stable source record identity distinguishes two untitled projects # by the same person in the same year. Never use Neo4j element IDs. fact.update( record_id=row.get("thesis_id") or row.get("work_id"), work_type=row.get("thesis_type") or row.get("work_type"), work_label=row.get("heading"), title=row.get("title"), ) fact = {k: v for k, v in fact.items() if v is not None or k == "title"} if fact not in academic_records: academic_records.append(fact) if fact not in facts: facts.append(fact) sources = result.get("sources") if sources is None: sources = [ {k: d[k] for k in ["document_path", "source_url"] if d.get(k)} for d in result.get("documents", []) ] context = { "status": result["status"], "reason": result["reason"], "facts": facts, "sources": sources, "aggregation": result["aggregation"], "complete": result.get("complete"), "truncated": result.get("truncated", False), "truncation_reasons": result.get("truncation_reasons", []), "index_version": result.get("index_version"), } context["answer_candidates"] = joined_candidates(facts, intent) context["question"] = result.get("resolved_query") or result.get("query", "") context["requested_years"] = ( intent.get("years", []) if not intent.get("mentions_start_year") else [] ) context["requested_work_types"] = [ *intent.get("thesis_types", []), *intent.get("work_types", []), ] context["clarification"] = result.get("clarification") context["requested_people"] = list( dict.fromkeys( row["name"] for row in result.get("resolved_entities", []) if row.get("kind") == "Person" and row.get("name") ) ) shared_values = {} for fact in facts: for field in ["keyword", "category", "document_author"]: if intent.get("mentions_shared") and fact.get(field) is not None: shared_values.setdefault((field, fact[field]), set()).add(fact["person"]) people = context["requested_people"] context["shared_properties"] = [ {"field": field, "value": value, "people": people} for (field, value), witnesses in shared_values.items() if len(people) >= 2 and set(people) <= witnesses ] comparison = result.get("academic_year_comparison") or next( (row for row in result["facts"] if row.get("fact_type") == "academic_year_comparison"), None ) if comparison is not None: context["academic_year_comparison"] = comparison if work_listing: context["required_academic_records"] = academic_records return context