|
# retoor <retoor@molodetz.nl>
|
|
|
|
from __future__ import annotations
|
|
|
|
import html
|
|
import json
|
|
import logging
|
|
from datetime import datetime, timezone
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def _findings(report: dict) -> list[dict]:
|
|
return report.get("findings") or []
|
|
|
|
|
|
def _sources(report: dict) -> list[dict]:
|
|
return report.get("sources") or []
|
|
|
|
|
|
def _gaps(report: dict) -> list[str]:
|
|
return report.get("gaps") or []
|
|
|
|
|
|
def to_markdown(report: dict) -> str:
|
|
query = report.get("query", "")
|
|
lines: list[str] = [f"# DeepSearch report: {query}", ""]
|
|
lines.append(
|
|
f"- Score: {report.get('score', 0)} "
|
|
f"Confidence: {report.get('confidence', 0)} "
|
|
f"Source diversity: {report.get('source_diversity', 0)}"
|
|
)
|
|
lines.append(
|
|
f"- Pages crawled: {report.get('page_count', 0)} "
|
|
f"Chunks indexed: {report.get('chunk_count', 0)}"
|
|
)
|
|
generated = report.get("generated_at") or datetime.now(timezone.utc).isoformat()
|
|
lines.append(f"- Generated: {generated}")
|
|
lines.append("")
|
|
summary = report.get("summary", "")
|
|
if summary:
|
|
lines.extend(["## Summary", "", summary, ""])
|
|
findings = _findings(report)
|
|
if findings:
|
|
lines.append("## Findings")
|
|
lines.append("")
|
|
for finding in findings:
|
|
title = finding.get("title", "")
|
|
detail = finding.get("detail", "")
|
|
confidence = finding.get("confidence", 0)
|
|
lines.append(f"### {title}")
|
|
lines.append("")
|
|
lines.append(detail)
|
|
citations = finding.get("citations") or []
|
|
if citations:
|
|
lines.append("")
|
|
lines.append("Sources: " + ", ".join(str(c) for c in citations))
|
|
lines.append(f"\nConfidence: {confidence}")
|
|
lines.append("")
|
|
gaps = _gaps(report)
|
|
if gaps:
|
|
lines.append("## Open gaps")
|
|
lines.append("")
|
|
for gap in gaps:
|
|
lines.append(f"- {gap}")
|
|
lines.append("")
|
|
sources = _sources(report)
|
|
if sources:
|
|
lines.append("## Sources")
|
|
lines.append("")
|
|
for index, source in enumerate(sources, start=1):
|
|
title = source.get("title") or source.get("url", "")
|
|
url = source.get("url", "")
|
|
lines.append(f"{index}. [{title}]({url})")
|
|
lines.append("")
|
|
return "\n".join(lines)
|
|
|
|
|
|
def to_json(report: dict) -> str:
|
|
return json.dumps(report, ensure_ascii=False, indent=2)
|
|
|
|
|
|
def _html_document(report: dict) -> str:
|
|
query = html.escape(report.get("query", ""))
|
|
parts: list[str] = [
|
|
"<html><head><meta charset='utf-8'><style>",
|
|
"body{font-family:Arial,Helvetica,sans-serif;color:#1b2330;margin:40px;}",
|
|
"h1{font-size:22px;}h2{font-size:17px;margin-top:24px;}h3{font-size:14px;}",
|
|
".meta{color:#566;font-size:12px;}a{color:#2d6cdf;}",
|
|
"</style></head><body>",
|
|
f"<h1>DeepSearch report: {query}</h1>",
|
|
"<p class='meta'>"
|
|
f"Score {report.get('score', 0)} | Confidence {report.get('confidence', 0)} | "
|
|
f"Diversity {report.get('source_diversity', 0)} | "
|
|
f"Pages {report.get('page_count', 0)} | Chunks {report.get('chunk_count', 0)}"
|
|
"</p>",
|
|
]
|
|
summary = report.get("summary", "")
|
|
if summary:
|
|
parts.append("<h2>Summary</h2>")
|
|
parts.append(f"<p>{html.escape(summary)}</p>")
|
|
findings = _findings(report)
|
|
if findings:
|
|
parts.append("<h2>Findings</h2>")
|
|
for finding in findings:
|
|
parts.append(f"<h3>{html.escape(finding.get('title', ''))}</h3>")
|
|
parts.append(f"<p>{html.escape(finding.get('detail', ''))}</p>")
|
|
parts.append(
|
|
f"<p class='meta'>Confidence {finding.get('confidence', 0)}</p>"
|
|
)
|
|
gaps = _gaps(report)
|
|
if gaps:
|
|
parts.append("<h2>Open gaps</h2><ul>")
|
|
for gap in gaps:
|
|
parts.append(f"<li>{html.escape(gap)}</li>")
|
|
parts.append("</ul>")
|
|
sources = _sources(report)
|
|
if sources:
|
|
parts.append("<h2>Sources</h2><ol>")
|
|
for source in sources:
|
|
url = html.escape(source.get("url", ""))
|
|
title = html.escape(source.get("title") or source.get("url", ""))
|
|
parts.append(f"<li><a href='{url}'>{title}</a></li>")
|
|
parts.append("</ol>")
|
|
parts.append("</body></html>")
|
|
return "".join(parts)
|
|
|
|
|
|
def to_pdf(report: dict) -> bytes:
|
|
from weasyprint import HTML
|
|
|
|
return HTML(string=_html_document(report)).write_pdf()
|