Spaces:
Sleeping
Sleeping
File size: 5,647 Bytes
bfcc872 | 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 175 176 177 178 179 180 181 182 183 | """
Citation and sourcing utilities to reduce hallucinations.
When presenting grant information, we cite the source data:
- Grant ID and title
- Specific fields (funding_max, deadline, etc.)
- Field source (from grant record or extracted)
This helps users verify information and trust the system.
"""
from typing import Dict, Any, List, Optional
from datetime import datetime
def cite_grant_fact(grant: Dict[str, Any], field: str, value: Any) -> str:
"""
Create a citation for a fact about a grant.
Args:
grant: The grant record dict
field: Field name (e.g., "funding_max", "close_date")
value: The value to cite
Returns:
Formatted citation like "£50,000 [Source: Grant ID #2315]"
"""
grant_id = grant.get("id") or grant.get("competition_id") or "unknown"
# Special formatting for currency
if field in ("funding_max", "funding_min", "total_pot") and isinstance(value, (int, float)):
return f"£{value:,.0f} [Source: Grant ID #{grant_id}]"
# Special formatting for dates
if field in ("close_date", "open_date", "deadline") and value:
return f"{value} [Source: Grant ID #{grant_id}]"
# Default formatting
if value is None:
return "Not specified"
return f"{value} [Source: Grant ID #{grant_id}]"
def format_grant_with_citations(grant: Dict[str, Any]) -> Dict[str, Any]:
"""
Format a grant record with citations on key fields.
Args:
grant: The grant record
Returns:
Dict with cited versions of key fields
"""
grant_id = grant.get("id") or grant.get("competition_id") or "unknown"
title = grant.get("title", "(untitled)")
cited = {
"id": grant_id,
"title": title,
"url": grant.get("url", ""),
}
# Cite monetary fields
if grant.get("funding_max"):
cited["funding_max"] = cite_grant_fact(grant, "funding_max", grant["funding_max"])
if grant.get("funding_min"):
cited["funding_min"] = cite_grant_fact(grant, "funding_min", grant["funding_min"])
if grant.get("total_pot"):
cited["total_pot"] = cite_grant_fact(grant, "total_pot", grant["total_pot"])
# Cite dates
if grant.get("close_date"):
cited["close_date"] = cite_grant_fact(grant, "close_date", grant["close_date"])
if grant.get("open_date"):
cited["open_date"] = cite_grant_fact(grant, "open_date", grant["open_date"])
return cited
def build_citation_summary(grant: Dict[str, Any]) -> str:
"""
Build a markdown summary of grant with citations.
Args:
grant: The grant record
Returns:
Markdown formatted summary with citations
"""
grant_id = grant.get("id") or grant.get("competition_id") or "unknown"
title = grant.get("title", "(untitled)")
url = grant.get("url", "")
lines = [
f"## {title}",
f"**Grant ID:** #{grant_id}",
"",
]
if url:
lines.append(f"**Official Link:** {url}")
lines.append("")
# Funding details with citations
if grant.get("funding_max") or grant.get("funding_min"):
min_fund = grant.get("funding_min")
max_fund = grant.get("funding_max")
if min_fund and max_fund:
funding_str = f"£{min_fund:,.0f} – £{max_fund:,.0f}"
elif max_fund:
funding_str = f"up to £{max_fund:,.0f}"
elif min_fund:
funding_str = f"from £{min_fund:,.0f}"
else:
funding_str = "See official page"
lines.append(f"**Funding per project:** {funding_str} [Source: Grant ID #{grant_id}]")
if grant.get("total_pot"):
lines.append(f"**Total available:** £{grant['total_pot']:,.0f} [Source: Grant ID #{grant_id}]")
lines.append("")
# Dates with citations
if grant.get("open_date") or grant.get("close_date"):
close = grant.get("close_date") or grant.get("deadline")
if close:
lines.append(f"**Deadline:** {close} [Source: Grant ID #{grant_id}]")
if grant.get("open_date"):
lines.append(f"**Opens:** {grant['open_date']} [Source: Grant ID #{grant_id}]")
lines.append("")
# Duration with citation
if grant.get("duration_min") or grant.get("duration_max"):
min_dur = grant.get("duration_min")
max_dur = grant.get("duration_max")
if min_dur and max_dur:
duration_str = f"{min_dur}–{max_dur} months"
elif max_dur:
duration_str = f"up to {max_dur} months"
elif min_dur:
duration_str = f"from {min_dur} months"
else:
duration_str = "Variable"
lines.append(f"**Project duration:** {duration_str} [Source: Grant ID #{grant_id}]")
return "\n".join(lines)
def validate_fact_availability(grant: Dict[str, Any], fact_type: str) -> bool:
"""
Check if a fact exists in the grant data before citing it.
Args:
grant: The grant record
fact_type: Type of fact ("funding", "deadline", "duration", "scope", "eligibility")
Returns:
True if the fact is available to cite
Raises assertion/warning if fact is missing
"""
fact_fields = {
"funding": ["funding_max", "funding_min", "total_pot"],
"deadline": ["close_date", "deadline"],
"duration": ["duration_min", "duration_max"],
"scope": ["scope", "scope_raw", "sections"],
"eligibility": ["eligibility", "eligibility_raw"],
}
required_fields = fact_fields.get(fact_type, [])
for field in required_fields:
if grant.get(field):
return True
return False
|