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

This commit is contained in:
2026-08-20 13:12:50 +00:00
commit b119135836
10275 changed files with 3284984 additions and 0 deletions
+313
View File
@@ -0,0 +1,313 @@
"""Reference and real-model agents for the Experiment 9-9 task stream."""
from __future__ import annotations
from dataclasses import dataclass
import hashlib
import json
import os
import re
import time
from typing import Any, Dict
BASELINE_ACTIONS = {
"refund": "issue_full_refund",
"identity": "change_without_verification",
"baggage": "answer_unknown",
}
@dataclass
class MemoryEntry:
value: str
version: int
class ReferenceAgent:
"""Controllable arms used only to unit-test the model-external harness."""
def __init__(self, profile: str = "evolving"):
if profile not in {"evolving", "append_only", "static"}:
raise ValueError(f"unknown profile: {profile}")
self.profile = profile
self.memory: Dict[str, MemoryEntry] = {}
self.token_cost = 0
self.time_ms = 0
def act(self, task: Dict[str, Any]) -> Dict[str, Any]:
entry = self.memory.get(task["rule_id"])
used_memory = entry is not None and self.profile != "static"
action = entry.value if used_memory else BASELINE_ACTIONS[task["family"]]
tokens = 70 if used_memory else 120
elapsed = 450 if used_memory else 900
self.token_cost += tokens
self.time_ms += elapsed
return {
"action": action,
"used_memory": used_memory,
"memory_available": entry is not None,
"active_memory_value": entry.value if entry else None,
"memory_version": entry.version if used_memory else None,
"tokens": tokens,
"prompt_tokens": tokens,
"completion_tokens": 0,
"provider_reported_cost_usd": None,
"time_ms": elapsed,
"response_id": None,
}
def observe(self, task: Dict[str, Any]) -> Dict[str, Any]:
signal = task.get("learning_signal")
if not signal or self.profile == "static":
return {
"updated": False, "candidate_proposed": False, "candidate_valid": None,
"tokens": 0, "time_ms": 0, "event_order_valid": True,
}
rule_id = task["rule_id"]
current = self.memory.get(rule_id)
can_write = current is None or (
self.profile == "evolving" and int(signal["version"]) > current.version
)
if can_write:
self.memory[rule_id] = MemoryEntry(signal["value"], int(signal["version"]))
self.token_cost += 25
self.time_ms += 50
return {
"updated": can_write,
"candidate_proposed": True,
"candidate_valid": signal["value"] == task["expected_action"],
"tokens": 25 if can_write else 0,
"time_ms": 50 if can_write else 0,
"event_order_valid": True,
}
@property
def storage_bytes(self) -> int:
return sum(len(key) + len(entry.value) + 8 for key, entry in self.memory.items())
class OpenAILongitudinalAgent:
"""A real LLM policy running one of the three external-memory arms.
The model makes every task decision. The arm-specific update operation is
deliberately model-external, is invoked only after ``act``, and never sees
a task's expected action before that action has been recorded.
"""
ACTIONS = tuple(sorted(set(BASELINE_ACTIONS.values()) | {
"offer_tax_only_refund", "verify_identity_first",
"answer_20kg", "answer_23kg", "ask_for_clarification",
}))
def __init__(
self,
model: str | None = None,
*,
arm: str = "evolving",
provider: str = "ark",
seed: int = 0,
run_id: str = "run",
):
if arm not in {"static", "append_only", "evolving"}:
raise ValueError(f"unknown arm: {arm}")
try:
from openai import OpenAI
except ImportError as error:
raise RuntimeError("Install dependencies with: pip install -r requirements.txt") from error
if provider == "ark":
key, base, key_env = os.getenv("ARK_API_KEY"), "https://ark.cn-beijing.volces.com/api/v3", "ARK_API_KEY"
default_model = os.getenv("ARK_MODEL", "doubao-seed-1-6-250615")
elif provider == "openrouter":
key, base, key_env = os.getenv("OPENROUTER_API_KEY"), "https://openrouter.ai/api/v1", "OPENROUTER_API_KEY"
default_model = "openai/gpt-4o-mini"
else:
key, base, key_env = os.getenv("OPENAI_API_KEY"), None, "OPENAI_API_KEY"
default_model = "gpt-4o-mini"
if not key:
raise RuntimeError(f"{key_env} is required for provider {provider}")
self.client = OpenAI(api_key=key, base_url=base) if base else OpenAI(api_key=key)
self.arm = arm
self.profile = f"llm_{arm}"
self.provider = provider
self.model = model or default_model
self.seed = seed
self.run_id = run_id
self.key_env = key_env
self.endpoint = (base or "https://api.openai.com/v1") + "/chat/completions"
self.memory: Dict[str, MemoryEntry] = {}
self.history: list[dict[str, Any]] = []
self.receipts: list[dict[str, Any]] = []
self.token_cost = 0
self.prompt_tokens = 0
self.completion_tokens = 0
self.time_ms = 0
self.provider_reported_cost_usd = 0.0
self.provider_cost_observations = 0
self._call_index = 0
self._last_action_finished_ns = 0
@staticmethod
def _parse(text: str) -> Dict[str, Any]:
cleaned = re.sub(r"^```(?:json)?\s*|\s*```$", "", text.strip(), flags=re.IGNORECASE)
try:
return json.loads(cleaned)
except json.JSONDecodeError:
match = re.search(r"\{.*\}", cleaned, re.DOTALL)
return json.loads(match.group(0)) if match else {}
def _memory_view(self) -> list[dict[str, Any]]:
return [
{"rule_id": key, "version": entry.version, "required_action": entry.value, "active": True}
for key, entry in sorted(self.memory.items())
]
def act(self, task: Dict[str, Any]) -> Dict[str, Any]:
memory = self._memory_view()
# Only the input-side task fields are serialized. In particular,
# expected_action and learning_signal stay in the evaluator.
task_view = {key: task[key] for key in ("id", "phase", "family", "rule_id", "input")}
prompt = f"""Act as an airline policy executor in a longitudinal experiment.
Company rules in this experiment are arbitrary. Never infer an unstored rule
from general knowledge. If ACTIVE_MEMORY has the exact task rule_id, return its
required_action exactly. Otherwise use the family baseline exactly:
{json.dumps(BASELINE_ACTIONS, sort_keys=True)}
Choose exactly one action from:
{json.dumps(self.ACTIONS)}
Return JSON only:
{{"action":"one vocabulary value","used_rule_id":"exact rule id or null","used_version":"integer or null"}}
ACTIVE_MEMORY:
{json.dumps(memory, ensure_ascii=False, sort_keys=True)}
TASK_INPUT:
{json.dumps(task_view, ensure_ascii=False, sort_keys=True)}
"""
call_seed = self.seed + self._call_index
request = {
"model": self.model,
"messages": [{"role": "user", "content": prompt}],
"temperature": 0,
"seed": call_seed,
"max_tokens": 160,
"response_format": {"type": "json_object"},
}
started_ns = time.time_ns()
started = time.perf_counter()
response = self.client.chat.completions.create(**request)
elapsed = max(1, round((time.perf_counter() - started) * 1000))
finished_ns = time.time_ns()
raw = response.model_dump(mode="json", exclude_none=True)
payload = self._parse(response.choices[0].message.content or "")
action = payload.get("action", "invalid_output")
if action not in self.ACTIONS:
action = "invalid_output"
usage = raw.get("usage") or {}
prompt_tokens = int(usage.get("prompt_tokens") or 0)
completion_tokens = int(usage.get("completion_tokens") or 0)
tokens = int(usage.get("total_tokens") or prompt_tokens + completion_tokens)
native_cost = usage.get("cost")
self.token_cost += tokens
self.prompt_tokens += prompt_tokens
self.completion_tokens += completion_tokens
self.time_ms += elapsed
if native_cost is not None:
self.provider_reported_cost_usd += float(native_cost)
self.provider_cost_observations += 1
entry = self.memory.get(task["rule_id"])
used_memory = (
entry is not None
and payload.get("used_rule_id") == task["rule_id"]
and int(payload.get("used_version") or -1) == entry.version
)
receipt = {
"run_id": self.run_id,
"arm": self.arm,
"task_id": task["id"],
"call_index": self._call_index,
"seed": call_seed,
"backend": {
"provider": self.provider,
"model": self.model,
"endpoint": self.endpoint,
"credential_env": self.key_env,
"credential_value_recorded": False,
},
"request": request,
"response": raw,
"request_sha256": hashlib.sha256(json.dumps(request, sort_keys=True).encode()).hexdigest(),
"response_sha256": hashlib.sha256(json.dumps(raw, sort_keys=True).encode()).hexdigest(),
"started_ns": started_ns,
"finished_ns": finished_ns,
"elapsed_ms": elapsed,
}
self.receipts.append(receipt)
self._call_index += 1
self._last_action_finished_ns = finished_ns
return {
"action": action,
"used_memory": used_memory,
"memory_available": entry is not None,
"active_memory_value": entry.value if entry else None,
"memory_version": entry.version if used_memory else None,
"tokens": tokens,
"prompt_tokens": prompt_tokens,
"completion_tokens": completion_tokens,
"provider_reported_cost_usd": float(native_cost) if native_cost is not None else None,
"time_ms": elapsed,
"response_id": raw.get("id"),
}
def observe(self, task: Dict[str, Any]) -> Dict[str, Any]:
observed_ns = time.time_ns()
signal = task.get("learning_signal")
if not signal or self.arm == "static":
return {
"updated": False,
"candidate_proposed": False,
"candidate_valid": None,
"tokens": 0,
"time_ms": 0,
"event_order_valid": observed_ns >= self._last_action_finished_ns,
}
entry = MemoryEntry(str(signal["value"]), int(signal["version"]))
current = self.memory.get(task["rule_id"])
if self.arm == "append_only":
# Keep every observation, including a conflicting v2, but never
# resolve or replace the first active version.
updated = current is None
else:
updated = current is None or entry.version > current.version
if updated:
if current is not None:
for item in self.history:
if item["rule_id"] == task["rule_id"] and item.get("active"):
item["active"] = False
item["status"] = "superseded"
self.memory[task["rule_id"]] = entry
self.history.append({
"rule_id": task["rule_id"],
"version": entry.version,
"value": entry.value,
"active": updated,
"status": "active" if updated else ("unresolved_conflict" if current and entry.version > current.version else "duplicate"),
"observed_after_task": task["id"],
"observed_ns": observed_ns,
})
return {
"updated": updated,
"candidate_proposed": True,
"candidate_valid": entry.value == task["expected_action"],
"tokens": 0,
"time_ms": 0,
"event_order_valid": observed_ns >= self._last_action_finished_ns,
}
@property
def storage_bytes(self) -> int:
if self.arm == "static":
return 0
return len(json.dumps(self.history, ensure_ascii=False, sort_keys=True).encode("utf-8"))