ai-agent-book 精选快照(<2MB 代码与文档,来自 github.com/bojieli/ai-agent-book)
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
"""Deterministic tools over synthetic DHIS2-style aggregate reports."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import csv
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
INTEGER_FIELDS = {
|
||||
"tests",
|
||||
"confirmed_cases",
|
||||
"deaths",
|
||||
"report_expected",
|
||||
"report_submitted",
|
||||
"stockout_days",
|
||||
}
|
||||
|
||||
|
||||
class ReportingEnvironment:
|
||||
"""Small, auditable tool environment backed by a CSV file."""
|
||||
|
||||
def __init__(self, data_path: str | Path) -> None:
|
||||
with Path(data_path).open(newline="", encoding="utf-8") as handle:
|
||||
self.rows = []
|
||||
for raw_row in csv.DictReader(handle):
|
||||
row: dict[str, Any] = dict(raw_row)
|
||||
for field in INTEGER_FIELDS:
|
||||
raw = row[field]
|
||||
text = str(raw).strip()
|
||||
if not text:
|
||||
row[field] = 0
|
||||
continue
|
||||
# Excel/CSV often writes whole counts as 10.0
|
||||
num = float(text)
|
||||
if not float(num).is_integer():
|
||||
raise ValueError(
|
||||
f"non-integer value for {field}: {raw!r}"
|
||||
)
|
||||
row[field] = int(num)
|
||||
self.rows.append(row)
|
||||
|
||||
def _select(self, **filters: str) -> list[dict[str, Any]]:
|
||||
rows = [
|
||||
row
|
||||
for row in self.rows
|
||||
if all(row.get(field) == value for field, value in filters.items())
|
||||
]
|
||||
if not rows:
|
||||
raise ValueError(f"No synthetic rows match {filters}")
|
||||
return rows
|
||||
|
||||
def calculate_test_positivity(self, org_unit_id: str, period: str) -> dict[str, Any]:
|
||||
rows = self._select(org_unit_id=org_unit_id, period=period)
|
||||
tests = sum(row["tests"] for row in rows)
|
||||
confirmed = sum(row["confirmed_cases"] for row in rows)
|
||||
positivity = round(100 * confirmed / tests, 2) if tests else None
|
||||
return {
|
||||
"tests": tests,
|
||||
"confirmed_cases": confirmed,
|
||||
"test_positivity_pct": positivity,
|
||||
"evidence": [row["row_id"] for row in rows],
|
||||
}
|
||||
|
||||
def calculate_reporting_completeness(
|
||||
self, parent_org_unit: str, period: str
|
||||
) -> dict[str, Any]:
|
||||
rows = self._select(parent_org_unit=parent_org_unit, period=period)
|
||||
expected = sum(row["report_expected"] for row in rows)
|
||||
submitted = sum(row["report_submitted"] for row in rows)
|
||||
completeness = round(100 * submitted / expected, 2) if expected else None
|
||||
return {
|
||||
"expected_reports": expected,
|
||||
"submitted_reports": submitted,
|
||||
"reporting_completeness_pct": completeness,
|
||||
"evidence": [row["row_id"] for row in rows],
|
||||
}
|
||||
|
||||
def compare_confirmed_cases(
|
||||
self, org_unit_id: str, start_period: str, end_period: str
|
||||
) -> dict[str, Any]:
|
||||
start_rows = self._select(org_unit_id=org_unit_id, period=start_period)
|
||||
end_rows = self._select(org_unit_id=org_unit_id, period=end_period)
|
||||
start_cases = sum(row["confirmed_cases"] for row in start_rows)
|
||||
end_cases = sum(row["confirmed_cases"] for row in end_rows)
|
||||
change = end_cases - start_cases
|
||||
percent_change = round(100 * change / start_cases, 2) if start_cases else None
|
||||
direction = "increase" if change > 0 else "decrease" if change < 0 else "no change"
|
||||
return {
|
||||
"start_cases": start_cases,
|
||||
"end_cases": end_cases,
|
||||
"absolute_change": change,
|
||||
"percent_change": percent_change,
|
||||
"direction": direction,
|
||||
"evidence": [row["row_id"] for row in start_rows + end_rows],
|
||||
}
|
||||
|
||||
def find_data_quality_issues(
|
||||
self, parent_org_unit: str, period: str
|
||||
) -> dict[str, Any]:
|
||||
rows = self._select(parent_org_unit=parent_org_unit, period=period)
|
||||
issues: list[dict[str, str]] = []
|
||||
for row in rows:
|
||||
if row["confirmed_cases"] > row["tests"]:
|
||||
issues.append({"row_id": row["row_id"], "code": "confirmed_exceeds_tests"})
|
||||
if row["stockout_days"] < 0:
|
||||
issues.append({"row_id": row["row_id"], "code": "negative_stockout_days"})
|
||||
if not row["report_submitted"] and any(
|
||||
row[field] for field in ("tests", "confirmed_cases", "deaths")
|
||||
):
|
||||
issues.append({"row_id": row["row_id"], "code": "data_in_unsubmitted_report"})
|
||||
return {
|
||||
"issue_count": len(issues),
|
||||
"issues": issues,
|
||||
"evidence": sorted({issue["row_id"] for issue in issues}),
|
||||
}
|
||||
|
||||
def review_stockouts(self, parent_org_unit: str, period: str) -> dict[str, Any]:
|
||||
rows = self._select(parent_org_unit=parent_org_unit, period=period)
|
||||
affected = [row for row in rows if row["stockout_days"] > 0]
|
||||
return {
|
||||
"facilities_with_stockouts": len(affected),
|
||||
"total_stockout_days": sum(row["stockout_days"] for row in affected),
|
||||
"facilities": [
|
||||
{
|
||||
"org_unit_id": row["org_unit_id"],
|
||||
"stockout_days": row["stockout_days"],
|
||||
}
|
||||
for row in affected
|
||||
],
|
||||
"evidence": [row["row_id"] for row in affected],
|
||||
}
|
||||
|
||||
def call(self, tool: str, arguments: dict[str, str] | None) -> dict[str, Any]:
|
||||
if arguments is None:
|
||||
arguments = {}
|
||||
allowed_tools = {
|
||||
"calculate_test_positivity": self.calculate_test_positivity,
|
||||
"calculate_reporting_completeness": self.calculate_reporting_completeness,
|
||||
"compare_confirmed_cases": self.compare_confirmed_cases,
|
||||
"find_data_quality_issues": self.find_data_quality_issues,
|
||||
"review_stockouts": self.review_stockouts,
|
||||
}
|
||||
try:
|
||||
function = allowed_tools[tool]
|
||||
except KeyError as exc:
|
||||
raise ValueError(f"Unknown reporting tool: {tool}") from exc
|
||||
return function(**arguments)
|
||||
Reference in New Issue
Block a user