<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>http://www.anwsome.com//api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Admin</id>
	<title>程序员技术小站 - 用户贡献 [zh-cn]</title>
	<link rel="self" type="application/atom+xml" href="http://www.anwsome.com//api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Admin"/>
	<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php/%E7%89%B9%E6%AE%8A:%E7%94%A8%E6%88%B7%E8%B4%A1%E7%8C%AE/Admin"/>
	<updated>2026-04-15T00:28:47Z</updated>
	<subtitle>用户贡献</subtitle>
	<generator>MediaWiki 1.45.1</generator>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E6%9E%84%E5%BB%BA%E8%87%AA%E5%B7%B1%E7%9A%84Harness%E7%B3%BB%E7%BB%9F--%E5%9F%BA%E4%BA%8EKimi2.5%E5%A4%A7%E6%A8%A1%E5%9E%8B&amp;diff=122</id>
		<title>构建自己的Harness系统--基于Kimi2.5大模型</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E6%9E%84%E5%BB%BA%E8%87%AA%E5%B7%B1%E7%9A%84Harness%E7%B3%BB%E7%BB%9F--%E5%9F%BA%E4%BA%8EKimi2.5%E5%A4%A7%E6%A8%A1%E5%9E%8B&amp;diff=122"/>
		<updated>2026-04-08T05:04:50Z</updated>

		<summary type="html">&lt;p&gt;Admin：​创建页面，内容为“本文基于前文的Harness系统原理介绍，实现了基于Kimi2.5大模型的简单agent模型，重点在于学习和了解Harness的系统的实现原理。同时也做到了国内大模型的开箱即用。&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt; #!/usr/bin/env python3 # Harness: all mechanisms combined -- the complete cockpit for the model. &amp;quot;&amp;quot;&amp;quot; s_full.py - Full Reference Agent  Capstone implementation combining every mechanism from s01-s11. Session s…”&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;本文基于前文的Harness系统原理介绍，实现了基于Kimi2.5大模型的简单agent模型，重点在于学习和了解Harness的系统的实现原理。同时也做到了国内大模型的开箱即用。&amp;lt;syntaxhighlight lang=&amp;quot;python3&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python3&lt;br /&gt;
# Harness: all mechanisms combined -- the complete cockpit for the model.&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
s_full.py - Full Reference Agent&lt;br /&gt;
&lt;br /&gt;
Capstone implementation combining every mechanism from s01-s11.&lt;br /&gt;
Session s12 (task-aware worktree isolation) is taught separately.&lt;br /&gt;
NOT a teaching session -- this is the &amp;quot;put it all together&amp;quot; reference.&lt;br /&gt;
&lt;br /&gt;
    +------------------------------------------------------------------+&lt;br /&gt;
    |                        FULL AGENT                                 |&lt;br /&gt;
    |                                                                   |&lt;br /&gt;
    |  System prompt (s05 skills, task-first + optional todo nag)      |&lt;br /&gt;
    |                                                                   |&lt;br /&gt;
    |  Before each LLM call:                                            |&lt;br /&gt;
    |  +--------------------+  +------------------+  +--------------+  |&lt;br /&gt;
    |  | Microcompact (s06) |  | Drain bg (s08)   |  | Check inbox  |  |&lt;br /&gt;
    |  | Auto-compact (s06) |  | notifications    |  | (s09)        |  |&lt;br /&gt;
    |  +--------------------+  +------------------+  +--------------+  |&lt;br /&gt;
    |                                                                   |&lt;br /&gt;
    |  Tool dispatch (s02 pattern):                                     |&lt;br /&gt;
    |  +--------+----------+----------+---------+-----------+          |&lt;br /&gt;
    |  | bash   | read     | write    | edit    | TodoWrite |          |&lt;br /&gt;
    |  | task   | load_sk  | compress | bg_run  | bg_check  |          |&lt;br /&gt;
    |  | t_crt  | t_get    | t_upd    | t_list  | spawn_tm  |          |&lt;br /&gt;
    |  | list_tm| send_msg | rd_inbox | bcast   | shutdown  |          |&lt;br /&gt;
    |  | plan   | idle     | claim    |         |           |          |&lt;br /&gt;
    |  +--------+----------+----------+---------+-----------+          |&lt;br /&gt;
    |                                                                   |&lt;br /&gt;
    |  Subagent (s04):  spawn -&amp;gt; work -&amp;gt; return summary                 |&lt;br /&gt;
    |  Teammate (s09):  spawn -&amp;gt; work -&amp;gt; idle -&amp;gt; auto-claim (s11)      |&lt;br /&gt;
    |  Shutdown (s10):  request_id handshake                            |&lt;br /&gt;
    |  Plan gate (s10): submit -&amp;gt; approve/reject                        |&lt;br /&gt;
    +------------------------------------------------------------------+&lt;br /&gt;
&lt;br /&gt;
    REPL commands: /compact /tasks /team /inbox&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
import json&lt;br /&gt;
import os&lt;br /&gt;
import re&lt;br /&gt;
import subprocess&lt;br /&gt;
import threading&lt;br /&gt;
import time&lt;br /&gt;
import uuid&lt;br /&gt;
from pathlib import Path&lt;br /&gt;
from queue import Queue&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
from openai import OpenAI&lt;br /&gt;
&lt;br /&gt;
WORKDIR = Path.cwd()&lt;br /&gt;
client = OpenAI(&lt;br /&gt;
    api_key = &amp;quot;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&amp;quot;,&lt;br /&gt;
    base_url = &amp;quot;https://api.moonshot.cn/v1&amp;quot;,&lt;br /&gt;
)&lt;br /&gt;
# https://api.moonshot.c&lt;br /&gt;
MODEL = &amp;quot;kimi-k2.5&amp;quot;&lt;br /&gt;
&lt;br /&gt;
TEAM_DIR = WORKDIR / &amp;quot;.team&amp;quot;&lt;br /&gt;
INBOX_DIR = TEAM_DIR / &amp;quot;inbox&amp;quot;&lt;br /&gt;
TASKS_DIR = WORKDIR / &amp;quot;.tasks&amp;quot;&lt;br /&gt;
SKILLS_DIR = WORKDIR / &amp;quot;skills&amp;quot;&lt;br /&gt;
TRANSCRIPT_DIR = WORKDIR / &amp;quot;.transcripts&amp;quot;&lt;br /&gt;
TOKEN_THRESHOLD = 100000&lt;br /&gt;
POLL_INTERVAL = 5&lt;br /&gt;
IDLE_TIMEOUT = 60&lt;br /&gt;
&lt;br /&gt;
VALID_MSG_TYPES = {&amp;quot;message&amp;quot;, &amp;quot;broadcast&amp;quot;, &amp;quot;shutdown_request&amp;quot;,&lt;br /&gt;
                   &amp;quot;shutdown_response&amp;quot;, &amp;quot;plan_approval_response&amp;quot;}&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
kimi 提示顺序：&lt;br /&gt;
system:.....&lt;br /&gt;
user: .....&lt;br /&gt;
assistant: .....&lt;br /&gt;
tool: .....&lt;br /&gt;
tool: .....&lt;br /&gt;
assistant: .....&#039;&#039;&#039;&lt;br /&gt;
# === SECTION: base_tools ===&lt;br /&gt;
def safe_path(p: str) -&amp;gt; Path:&lt;br /&gt;
    path = (WORKDIR / p).resolve()&lt;br /&gt;
    if not path.is_relative_to(WORKDIR):&lt;br /&gt;
        raise ValueError(f&amp;quot;Path escapes workspace: {p}&amp;quot;)&lt;br /&gt;
    return path&lt;br /&gt;
&lt;br /&gt;
def run_bash(command: str) -&amp;gt; str:&lt;br /&gt;
    dangerous = [&amp;quot;rm -rf /&amp;quot;, &amp;quot;sudo&amp;quot;, &amp;quot;shutdown&amp;quot;, &amp;quot;reboot&amp;quot;, &amp;quot;&amp;gt; /dev/&amp;quot;]&lt;br /&gt;
    if any(d in command for d in dangerous):&lt;br /&gt;
        return &amp;quot;Error: Dangerous command blocked&amp;quot;&lt;br /&gt;
    try:&lt;br /&gt;
        r = subprocess.run(command, shell=True, cwd=WORKDIR,&lt;br /&gt;
                           capture_output=True, text=True, timeout=120)&lt;br /&gt;
        out = (r.stdout + r.stderr).strip()&lt;br /&gt;
        return out[:50000] if out else &amp;quot;(no output)&amp;quot;&lt;br /&gt;
    except subprocess.TimeoutExpired:&lt;br /&gt;
        return &amp;quot;Error: Timeout (120s)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def run_read(path: str, limit: int = None) -&amp;gt; str:&lt;br /&gt;
    try:&lt;br /&gt;
        lines = safe_path(path).read_text().splitlines()&lt;br /&gt;
        if limit and limit &amp;lt; len(lines):&lt;br /&gt;
            lines = lines[:limit] + [f&amp;quot;... ({len(lines) - limit} more)&amp;quot;]&lt;br /&gt;
        return &amp;quot;\n&amp;quot;.join(lines)[:50000]&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        return f&amp;quot;Error: {e}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def run_write(path: str, content: str) -&amp;gt; str:&lt;br /&gt;
    try:&lt;br /&gt;
        fp = safe_path(path)&lt;br /&gt;
        fp.parent.mkdir(parents=True, exist_ok=True)&lt;br /&gt;
        fp.write_text(content)&lt;br /&gt;
        return f&amp;quot;Wrote {len(content)} bytes to {path}&amp;quot;&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        return f&amp;quot;Error: {e}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def run_edit(path: str, old_text: str, new_text: str) -&amp;gt; str:&lt;br /&gt;
    try:&lt;br /&gt;
        fp = safe_path(path)&lt;br /&gt;
        c = fp.read_text()&lt;br /&gt;
        if old_text not in c:&lt;br /&gt;
            return f&amp;quot;Error: Text not found in {path}&amp;quot;&lt;br /&gt;
        fp.write_text(c.replace(old_text, new_text, 1))&lt;br /&gt;
        return f&amp;quot;Edited {path}&amp;quot;&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        return f&amp;quot;Error: {e}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# === SECTION: todos (s03) ===&lt;br /&gt;
class TodoManager:&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        self.items = []&lt;br /&gt;
&lt;br /&gt;
    def update(self, items: list) -&amp;gt; str:&lt;br /&gt;
        validated, ip = [], 0&lt;br /&gt;
        for i, item in enumerate(items):&lt;br /&gt;
            content = str(item.get(&amp;quot;content&amp;quot;, &amp;quot;&amp;quot;)).strip()&lt;br /&gt;
            status = str(item.get(&amp;quot;status&amp;quot;, &amp;quot;pending&amp;quot;)).lower()&lt;br /&gt;
            af = str(item.get(&amp;quot;activeForm&amp;quot;, &amp;quot;&amp;quot;)).strip()&lt;br /&gt;
            if not content: raise ValueError(f&amp;quot;Item {i}: content required&amp;quot;)&lt;br /&gt;
            if status not in (&amp;quot;pending&amp;quot;, &amp;quot;in_progress&amp;quot;, &amp;quot;completed&amp;quot;):&lt;br /&gt;
                raise ValueError(f&amp;quot;Item {i}: invalid status &#039;{status}&#039;&amp;quot;)&lt;br /&gt;
            if not af: raise ValueError(f&amp;quot;Item {i}: activeForm required&amp;quot;)&lt;br /&gt;
            if status == &amp;quot;in_progress&amp;quot;: ip += 1&lt;br /&gt;
            validated.append({&amp;quot;content&amp;quot;: content, &amp;quot;status&amp;quot;: status, &amp;quot;activeForm&amp;quot;: af})&lt;br /&gt;
        if len(validated) &amp;gt; 20: raise ValueError(&amp;quot;Max 20 todos&amp;quot;)&lt;br /&gt;
        if ip &amp;gt; 1: raise ValueError(&amp;quot;Only one in_progress allowed&amp;quot;)&lt;br /&gt;
        self.items = validated&lt;br /&gt;
        return self.render()&lt;br /&gt;
&lt;br /&gt;
    def render(self) -&amp;gt; str:&lt;br /&gt;
        if not self.items: return &amp;quot;No todos.&amp;quot;&lt;br /&gt;
        lines = []&lt;br /&gt;
        for item in self.items:&lt;br /&gt;
            m = {&amp;quot;completed&amp;quot;: &amp;quot;[x]&amp;quot;, &amp;quot;in_progress&amp;quot;: &amp;quot;[&amp;gt;]&amp;quot;, &amp;quot;pending&amp;quot;: &amp;quot;[ ]&amp;quot;}.get(item[&amp;quot;status&amp;quot;], &amp;quot;[?]&amp;quot;)&lt;br /&gt;
            suffix = f&amp;quot; &amp;lt;- {item[&#039;activeForm&#039;]}&amp;quot; if item[&amp;quot;status&amp;quot;] == &amp;quot;in_progress&amp;quot; else &amp;quot;&amp;quot;&lt;br /&gt;
            lines.append(f&amp;quot;{m} {item[&#039;content&#039;]}{suffix}&amp;quot;)&lt;br /&gt;
        done = sum(1 for t in self.items if t[&amp;quot;status&amp;quot;] == &amp;quot;completed&amp;quot;)&lt;br /&gt;
        lines.append(f&amp;quot;\n({done}/{len(self.items)} completed)&amp;quot;)&lt;br /&gt;
        return &amp;quot;\n&amp;quot;.join(lines)&lt;br /&gt;
&lt;br /&gt;
    def has_open_items(self) -&amp;gt; bool:&lt;br /&gt;
        return any(item.get(&amp;quot;status&amp;quot;) != &amp;quot;completed&amp;quot; for item in self.items)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# === SECTION: subagent (s04) ===&lt;br /&gt;
def run_subagent(prompt: str, agent_type: str = &amp;quot;Explore&amp;quot;) -&amp;gt; str:&lt;br /&gt;
    sub_tools = [&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;bash&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;Run command.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {&amp;quot;command&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}},&lt;br /&gt;
                &amp;quot;required&amp;quot;: [&amp;quot;command&amp;quot;]&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;read_file&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;Read file.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {&amp;quot;path&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}},&lt;br /&gt;
                &amp;quot;required&amp;quot;: [&amp;quot;path&amp;quot;]&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }]&lt;br /&gt;
    if agent_type != &amp;quot;Explore&amp;quot;:&lt;br /&gt;
        sub_tools += [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
            &amp;quot;function&amp;quot;: {&lt;br /&gt;
                &amp;quot;name&amp;quot;: &amp;quot;write_file&amp;quot;,&lt;br /&gt;
                &amp;quot;description&amp;quot;: &amp;quot;Write file.&amp;quot;,&lt;br /&gt;
                &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                    &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                    &amp;quot;properties&amp;quot;: {&lt;br /&gt;
                        &amp;quot;path&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;},&lt;br /&gt;
                        &amp;quot;content&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}&lt;br /&gt;
                    },&lt;br /&gt;
                    &amp;quot;required&amp;quot;: [&amp;quot;path&amp;quot;, &amp;quot;content&amp;quot;]&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
            &amp;quot;function&amp;quot;: {&lt;br /&gt;
                &amp;quot;name&amp;quot;: &amp;quot;edit_file&amp;quot;,&lt;br /&gt;
                &amp;quot;description&amp;quot;: &amp;quot;Edit file.&amp;quot;,&lt;br /&gt;
                &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                    &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                    &amp;quot;properties&amp;quot;: {&lt;br /&gt;
                        &amp;quot;path&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;},&lt;br /&gt;
                        &amp;quot;old_text&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;},&lt;br /&gt;
                        &amp;quot;new_text&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}&lt;br /&gt;
                    },&lt;br /&gt;
                    &amp;quot;required&amp;quot;: [&amp;quot;path&amp;quot;, &amp;quot;old_text&amp;quot;, &amp;quot;new_text&amp;quot;]&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }]&lt;br /&gt;
    sub_handlers = {&lt;br /&gt;
        &amp;quot;bash&amp;quot;: lambda **kw: run_bash(kw[&amp;quot;command&amp;quot;]),&lt;br /&gt;
        &amp;quot;read_file&amp;quot;: lambda **kw: run_read(kw[&amp;quot;path&amp;quot;]),&lt;br /&gt;
        &amp;quot;write_file&amp;quot;: lambda **kw: run_write(kw[&amp;quot;path&amp;quot;], kw[&amp;quot;content&amp;quot;]),&lt;br /&gt;
        &amp;quot;edit_file&amp;quot;: lambda **kw: run_edit(kw[&amp;quot;path&amp;quot;], kw[&amp;quot;old_text&amp;quot;], kw[&amp;quot;new_text&amp;quot;]),&lt;br /&gt;
    }&lt;br /&gt;
    sub_msgs = [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: prompt}]&lt;br /&gt;
    resp = None&lt;br /&gt;
    for _ in range(30):&lt;br /&gt;
        resp = client.chat.completions.create(model=MODEL, messages=sub_msgs, tools=sub_tools)&lt;br /&gt;
        msg = resp.choices[0].message&lt;br /&gt;
        sub_msgs.append(msg)&lt;br /&gt;
        if resp.choices[0].finish_reason != &amp;quot;tool_calls&amp;quot;:&lt;br /&gt;
            break&lt;br /&gt;
        for b in msg.tool_calls or []:&lt;br /&gt;
            if b.type == &amp;quot;function&amp;quot;:&lt;br /&gt;
                h = sub_handlers.get(b.function.name, lambda **kw: &amp;quot;Unknown tool&amp;quot;)&lt;br /&gt;
                output = h(**json.loads(b.function.arguments))&lt;br /&gt;
                sub_msgs.append({&amp;quot;role&amp;quot;: &amp;quot;tool&amp;quot;, &amp;quot;tool_call_id&amp;quot;: b.id, &amp;quot;name&amp;quot;: b.function.name, &amp;quot;content&amp;quot;: json.dumps({&amp;quot;result&amp;quot;: str(output)})})&lt;br /&gt;
    if resp:&lt;br /&gt;
        return resp.choices[0].message.content or &amp;quot;(no summary)&amp;quot;&lt;br /&gt;
    return &amp;quot;(subagent failed)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# === SECTION: skills (s05) ===&lt;br /&gt;
class SkillLoader:&lt;br /&gt;
    def __init__(self, skills_dir: Path):&lt;br /&gt;
        self.skills = {}&lt;br /&gt;
        if skills_dir.exists():&lt;br /&gt;
            for f in sorted(skills_dir.rglob(&amp;quot;SKILL.md&amp;quot;)):&lt;br /&gt;
                text = f.read_text()&lt;br /&gt;
                match = re.match(r&amp;quot;^---\n(.*?)\n---\n(.*)&amp;quot;, text, re.DOTALL)&lt;br /&gt;
                meta, body = {}, text&lt;br /&gt;
                if match:&lt;br /&gt;
                    for line in match.group(1).strip().splitlines():&lt;br /&gt;
                        if &amp;quot;:&amp;quot; in line:&lt;br /&gt;
                            k, v = line.split(&amp;quot;:&amp;quot;, 1)&lt;br /&gt;
                            meta[k.strip()] = v.strip()&lt;br /&gt;
                    body = match.group(2).strip()&lt;br /&gt;
                name = meta.get(&amp;quot;name&amp;quot;, f.parent.name)&lt;br /&gt;
                self.skills[name] = {&amp;quot;meta&amp;quot;: meta, &amp;quot;body&amp;quot;: body}&lt;br /&gt;
&lt;br /&gt;
    def descriptions(self) -&amp;gt; str:&lt;br /&gt;
        if not self.skills: return &amp;quot;(no skills)&amp;quot;&lt;br /&gt;
        return &amp;quot;\n&amp;quot;.join(f&amp;quot;  - {n}: {s[&#039;meta&#039;].get(&#039;description&#039;, &#039;-&#039;)}&amp;quot; for n, s in self.skills.items())&lt;br /&gt;
&lt;br /&gt;
    def load(self, name: str) -&amp;gt; str:&lt;br /&gt;
        s = self.skills.get(name)&lt;br /&gt;
        if not s: return f&amp;quot;Error: Unknown skill &#039;{name}&#039;. Available: {&#039;, &#039;.join(self.skills.keys())}&amp;quot;&lt;br /&gt;
        return f&amp;quot;&amp;lt;skill name=\&amp;quot;{name}\&amp;quot;&amp;gt;\n{s[&#039;body&#039;]}\n&amp;lt;/skill&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# === SECTION: compression (s06) ===&lt;br /&gt;
def estimate_tokens(messages: list) -&amp;gt; int:&lt;br /&gt;
    return len(json.dumps(messages, default=str)) // 4&lt;br /&gt;
&lt;br /&gt;
def microcompact(messages: list):&lt;br /&gt;
    indices = []&lt;br /&gt;
    return&lt;br /&gt;
    for i, msg in enumerate(messages):&lt;br /&gt;
        if msg[&amp;quot;role&amp;quot;] == &amp;quot;user&amp;quot; and isinstance(msg.get(&amp;quot;content&amp;quot;), list):&lt;br /&gt;
            for part in msg[&amp;quot;content&amp;quot;]:&lt;br /&gt;
                if isinstance(part, dict) and part.get(&amp;quot;type&amp;quot;) == &amp;quot;tool_result&amp;quot;:&lt;br /&gt;
                    indices.append(part)&lt;br /&gt;
    if len(indices) &amp;lt;= 3:&lt;br /&gt;
        return&lt;br /&gt;
    for part in indices[:-3]:&lt;br /&gt;
        if isinstance(part.get(&amp;quot;content&amp;quot;), str) and len(part[&amp;quot;content&amp;quot;]) &amp;gt; 100:&lt;br /&gt;
            part[&amp;quot;content&amp;quot;] = &amp;quot;[cleared]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def auto_compact(messages: list) -&amp;gt; list:&lt;br /&gt;
    TRANSCRIPT_DIR.mkdir(exist_ok=True)&lt;br /&gt;
    path = TRANSCRIPT_DIR / f&amp;quot;transcript_{int(time.time())}.jsonl&amp;quot;&lt;br /&gt;
    with open(path, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
        for msg in messages:&lt;br /&gt;
            f.write(json.dumps(msg, default=str) + &amp;quot;\n&amp;quot;)&lt;br /&gt;
    conv_text = json.dumps(messages, default=str)[:80000]&lt;br /&gt;
    resp = client.chat.completions.create(&lt;br /&gt;
        model=MODEL,&lt;br /&gt;
        messages=[{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: f&amp;quot;Summarize for continuity:\n{conv_text}&amp;quot;}],&lt;br /&gt;
        max_tokens=2000,&lt;br /&gt;
    )&lt;br /&gt;
    summary = resp.choices[0].message.content&lt;br /&gt;
    return [&lt;br /&gt;
        {&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: f&amp;quot;[Compressed. Transcript: {path}]\n{summary}&amp;quot;},&lt;br /&gt;
        {&amp;quot;role&amp;quot;: &amp;quot;assistant&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;Understood. Continuing with summary context.&amp;quot;},&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# === SECTION: file_tasks (s07) ===&lt;br /&gt;
class TaskManager:&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        TASKS_DIR.mkdir(exist_ok=True)&lt;br /&gt;
&lt;br /&gt;
    def _next_id(self) -&amp;gt; int:&lt;br /&gt;
        ids = [int(f.stem.split(&amp;quot;_&amp;quot;)[1]) for f in TASKS_DIR.glob(&amp;quot;task_*.json&amp;quot;)]&lt;br /&gt;
        return max(ids, default=0) + 1&lt;br /&gt;
&lt;br /&gt;
    def _load(self, tid: int) -&amp;gt; dict:&lt;br /&gt;
        p = TASKS_DIR / f&amp;quot;task_{tid}.json&amp;quot;&lt;br /&gt;
        if not p.exists(): raise ValueError(f&amp;quot;Task {tid} not found&amp;quot;)&lt;br /&gt;
        return json.loads(p.read_text())&lt;br /&gt;
&lt;br /&gt;
    def _save(self, task: dict):&lt;br /&gt;
        (TASKS_DIR / f&amp;quot;task_{task[&#039;id&#039;]}.json&amp;quot;).write_text(json.dumps(task, indent=2))&lt;br /&gt;
&lt;br /&gt;
    def create(self, subject: str, description: str = &amp;quot;&amp;quot;) -&amp;gt; str:&lt;br /&gt;
        task = {&amp;quot;id&amp;quot;: self._next_id(), &amp;quot;subject&amp;quot;: subject, &amp;quot;description&amp;quot;: description,&lt;br /&gt;
                &amp;quot;status&amp;quot;: &amp;quot;pending&amp;quot;, &amp;quot;owner&amp;quot;: None, &amp;quot;blockedBy&amp;quot;: [], &amp;quot;blocks&amp;quot;: []}&lt;br /&gt;
        self._save(task)&lt;br /&gt;
        return json.dumps(task, indent=2)&lt;br /&gt;
&lt;br /&gt;
    def get(self, tid: int) -&amp;gt; str:&lt;br /&gt;
        return json.dumps(self._load(tid), indent=2)&lt;br /&gt;
&lt;br /&gt;
    def update(self, tid: int, status: str = None,&lt;br /&gt;
               add_blocked_by: list = None, add_blocks: list = None) -&amp;gt; str:&lt;br /&gt;
        task = self._load(tid)&lt;br /&gt;
        if status:&lt;br /&gt;
            task[&amp;quot;status&amp;quot;] = status&lt;br /&gt;
            if status == &amp;quot;completed&amp;quot;:&lt;br /&gt;
                for f in TASKS_DIR.glob(&amp;quot;task_*.json&amp;quot;):&lt;br /&gt;
                    t = json.loads(f.read_text())&lt;br /&gt;
                    if tid in t.get(&amp;quot;blockedBy&amp;quot;, []):&lt;br /&gt;
                        t[&amp;quot;blockedBy&amp;quot;].remove(tid)&lt;br /&gt;
                        self._save(t)&lt;br /&gt;
            if status == &amp;quot;deleted&amp;quot;:&lt;br /&gt;
                (TASKS_DIR / f&amp;quot;task_{tid}.json&amp;quot;).unlink(missing_ok=True)&lt;br /&gt;
                return f&amp;quot;Task {tid} deleted&amp;quot;&lt;br /&gt;
        if add_blocked_by:&lt;br /&gt;
            task[&amp;quot;blockedBy&amp;quot;] = list(set(task[&amp;quot;blockedBy&amp;quot;] + add_blocked_by))&lt;br /&gt;
        if add_blocks:&lt;br /&gt;
            task[&amp;quot;blocks&amp;quot;] = list(set(task[&amp;quot;blocks&amp;quot;] + add_blocks))&lt;br /&gt;
        self._save(task)&lt;br /&gt;
        return json.dumps(task, indent=2)&lt;br /&gt;
&lt;br /&gt;
    def list_all(self) -&amp;gt; str:&lt;br /&gt;
        tasks = [json.loads(f.read_text()) for f in sorted(TASKS_DIR.glob(&amp;quot;task_*.json&amp;quot;))]&lt;br /&gt;
        if not tasks: return &amp;quot;No tasks.&amp;quot;&lt;br /&gt;
        lines = []&lt;br /&gt;
        for t in tasks:&lt;br /&gt;
            m = {&amp;quot;pending&amp;quot;: &amp;quot;[ ]&amp;quot;, &amp;quot;in_progress&amp;quot;: &amp;quot;[&amp;gt;]&amp;quot;, &amp;quot;completed&amp;quot;: &amp;quot;[x]&amp;quot;}.get(t[&amp;quot;status&amp;quot;], &amp;quot;[?]&amp;quot;)&lt;br /&gt;
            owner = f&amp;quot; @{t[&#039;owner&#039;]}&amp;quot; if t.get(&amp;quot;owner&amp;quot;) else &amp;quot;&amp;quot;&lt;br /&gt;
            blocked = f&amp;quot; (blocked by: {t[&#039;blockedBy&#039;]})&amp;quot; if t.get(&amp;quot;blockedBy&amp;quot;) else &amp;quot;&amp;quot;&lt;br /&gt;
            lines.append(f&amp;quot;{m} #{t[&#039;id&#039;]}: {t[&#039;subject&#039;]}{owner}{blocked}&amp;quot;)&lt;br /&gt;
        return &amp;quot;\n&amp;quot;.join(lines)&lt;br /&gt;
&lt;br /&gt;
    def claim(self, tid: int, owner: str) -&amp;gt; str:&lt;br /&gt;
        task = self._load(tid)&lt;br /&gt;
        task[&amp;quot;owner&amp;quot;] = owner&lt;br /&gt;
        task[&amp;quot;status&amp;quot;] = &amp;quot;in_progress&amp;quot;&lt;br /&gt;
        self._save(task)&lt;br /&gt;
        return f&amp;quot;Claimed task #{tid} for {owner}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# === SECTION: background (s08) ===&lt;br /&gt;
class BackgroundManager:&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        self.tasks = {}&lt;br /&gt;
        self.notifications = Queue()&lt;br /&gt;
&lt;br /&gt;
    def run(self, command: str, timeout: int = 120) -&amp;gt; str:&lt;br /&gt;
        tid = str(uuid.uuid4())[:8]&lt;br /&gt;
        self.tasks[tid] = {&amp;quot;status&amp;quot;: &amp;quot;running&amp;quot;, &amp;quot;command&amp;quot;: command, &amp;quot;result&amp;quot;: None}&lt;br /&gt;
        threading.Thread(target=self._exec, args=(tid, command, timeout), daemon=True).start()&lt;br /&gt;
        return f&amp;quot;Background task {tid} started: {command[:80]}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    def _exec(self, tid: str, command: str, timeout: int):&lt;br /&gt;
        try:&lt;br /&gt;
            r = subprocess.run(command, shell=True, cwd=WORKDIR,&lt;br /&gt;
                               capture_output=True, text=True, timeout=timeout)&lt;br /&gt;
            output = (r.stdout + r.stderr).strip()[:50000]&lt;br /&gt;
            self.tasks[tid].update({&amp;quot;status&amp;quot;: &amp;quot;completed&amp;quot;, &amp;quot;result&amp;quot;: output or &amp;quot;(no output)&amp;quot;})&lt;br /&gt;
        except Exception as e:&lt;br /&gt;
            self.tasks[tid].update({&amp;quot;status&amp;quot;: &amp;quot;error&amp;quot;, &amp;quot;result&amp;quot;: str(e)})&lt;br /&gt;
        self.notifications.put({&amp;quot;task_id&amp;quot;: tid, &amp;quot;status&amp;quot;: self.tasks[tid][&amp;quot;status&amp;quot;],&lt;br /&gt;
                                &amp;quot;result&amp;quot;: self.tasks[tid][&amp;quot;result&amp;quot;][:500]})&lt;br /&gt;
&lt;br /&gt;
    def check(self, tid: str = None) -&amp;gt; str:&lt;br /&gt;
        if tid:&lt;br /&gt;
            t = self.tasks.get(tid)&lt;br /&gt;
            return f&amp;quot;[{t[&#039;status&#039;]}] {t.get(&#039;result&#039;, &#039;(running)&#039;)}&amp;quot; if t else f&amp;quot;Unknown: {tid}&amp;quot;&lt;br /&gt;
        return &amp;quot;\n&amp;quot;.join(f&amp;quot;{k}: [{v[&#039;status&#039;]}] {v[&#039;command&#039;][:60]}&amp;quot; for k, v in self.tasks.items()) or &amp;quot;No bg tasks.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    def drain(self) -&amp;gt; list:&lt;br /&gt;
        notifs = []&lt;br /&gt;
        while not self.notifications.empty():&lt;br /&gt;
            notifs.append(self.notifications.get_nowait())&lt;br /&gt;
        return notifs&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# === SECTION: messaging (s09) ===&lt;br /&gt;
class MessageBus:&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        INBOX_DIR.mkdir(parents=True, exist_ok=True)&lt;br /&gt;
&lt;br /&gt;
    def send(self, sender: str, to: str, content: str,&lt;br /&gt;
             msg_type: str = &amp;quot;message&amp;quot;, extra: dict = None) -&amp;gt; str:&lt;br /&gt;
        msg = {&amp;quot;type&amp;quot;: msg_type, &amp;quot;from&amp;quot;: sender, &amp;quot;content&amp;quot;: content,&lt;br /&gt;
               &amp;quot;timestamp&amp;quot;: time.time()}&lt;br /&gt;
        if extra: msg.update(extra)&lt;br /&gt;
        with open(INBOX_DIR / f&amp;quot;{to}.jsonl&amp;quot;, &amp;quot;a&amp;quot;) as f:&lt;br /&gt;
            f.write(json.dumps(msg) + &amp;quot;\n&amp;quot;)&lt;br /&gt;
        return f&amp;quot;Sent {msg_type} to {to}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    def read_inbox(self, name: str) -&amp;gt; list:&lt;br /&gt;
        path = INBOX_DIR / f&amp;quot;{name}.jsonl&amp;quot;&lt;br /&gt;
        if not path.exists(): return []&lt;br /&gt;
        msgs = [json.loads(l) for l in path.read_text().strip().splitlines() if l]&lt;br /&gt;
        path.write_text(&amp;quot;&amp;quot;)&lt;br /&gt;
        return msgs&lt;br /&gt;
&lt;br /&gt;
    def broadcast(self, sender: str, content: str, names: list) -&amp;gt; str:&lt;br /&gt;
        count = 0&lt;br /&gt;
        for n in names:&lt;br /&gt;
            if n != sender:&lt;br /&gt;
                self.send(sender, n, content, &amp;quot;broadcast&amp;quot;)&lt;br /&gt;
                count += 1&lt;br /&gt;
        return f&amp;quot;Broadcast to {count} teammates&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# === SECTION: shutdown + plan tracking (s10) ===&lt;br /&gt;
shutdown_requests = {}&lt;br /&gt;
plan_requests = {}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# === SECTION: team (s09/s11) ===&lt;br /&gt;
class TeammateManager:&lt;br /&gt;
    def __init__(self, bus: MessageBus, task_mgr: TaskManager):&lt;br /&gt;
        TEAM_DIR.mkdir(exist_ok=True)&lt;br /&gt;
        self.bus = bus&lt;br /&gt;
        self.task_mgr = task_mgr&lt;br /&gt;
        self.config_path = TEAM_DIR / &amp;quot;config.json&amp;quot;&lt;br /&gt;
        self.config = self._load()&lt;br /&gt;
        self.threads = {}&lt;br /&gt;
&lt;br /&gt;
    def _load(self) -&amp;gt; dict:&lt;br /&gt;
        if self.config_path.exists():&lt;br /&gt;
            return json.loads(self.config_path.read_text())&lt;br /&gt;
        return {&amp;quot;team_name&amp;quot;: &amp;quot;default&amp;quot;, &amp;quot;members&amp;quot;: []}&lt;br /&gt;
&lt;br /&gt;
    def _save(self):&lt;br /&gt;
        self.config_path.write_text(json.dumps(self.config, indent=2))&lt;br /&gt;
&lt;br /&gt;
    def _find(self, name: str) -&amp;gt; dict:&lt;br /&gt;
        for m in self.config[&amp;quot;members&amp;quot;]:&lt;br /&gt;
            if m[&amp;quot;name&amp;quot;] == name: return m&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
    def spawn(self, name: str, role: str, prompt: str) -&amp;gt; str:&lt;br /&gt;
        member = self._find(name)&lt;br /&gt;
        if member:&lt;br /&gt;
            if member[&amp;quot;status&amp;quot;] not in (&amp;quot;idle&amp;quot;, &amp;quot;shutdown&amp;quot;):&lt;br /&gt;
                return f&amp;quot;Error: &#039;{name}&#039; is currently {member[&#039;status&#039;]}&amp;quot;&lt;br /&gt;
            member[&amp;quot;status&amp;quot;] = &amp;quot;working&amp;quot;&lt;br /&gt;
            member[&amp;quot;role&amp;quot;] = role&lt;br /&gt;
        else:&lt;br /&gt;
            member = {&amp;quot;name&amp;quot;: name, &amp;quot;role&amp;quot;: role, &amp;quot;status&amp;quot;: &amp;quot;working&amp;quot;}&lt;br /&gt;
            self.config[&amp;quot;members&amp;quot;].append(member)&lt;br /&gt;
        self._save()&lt;br /&gt;
        threading.Thread(target=self._loop, args=(name, role, prompt), daemon=True).start()&lt;br /&gt;
        return f&amp;quot;Spawned &#039;{name}&#039; (role: {role})&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    def _set_status(self, name: str, status: str):&lt;br /&gt;
        member = self._find(name)&lt;br /&gt;
        if member:&lt;br /&gt;
            member[&amp;quot;status&amp;quot;] = status&lt;br /&gt;
            self._save()&lt;br /&gt;
&lt;br /&gt;
    def _loop(self, name: str, role: str, prompt: str):&lt;br /&gt;
        team_name = self.config[&amp;quot;team_name&amp;quot;]&lt;br /&gt;
        sys_prompt = (f&amp;quot;You are &#039;{name}&#039;, role: {role}, team: {team_name}, at {WORKDIR}. &amp;quot;&lt;br /&gt;
                      f&amp;quot;Use idle when done with current work. You may auto-claim tasks.&amp;quot;)&lt;br /&gt;
        messages = [{&amp;quot;role&amp;quot;: &amp;quot;system&amp;quot;, &amp;quot;content&amp;quot;: sys_prompt}, {&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: prompt}]&lt;br /&gt;
        tools = [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
                &amp;quot;function&amp;quot;: {&amp;quot;name&amp;quot;: &amp;quot;bash&amp;quot;, &amp;quot;description&amp;quot;: &amp;quot;Run command.&amp;quot;,&lt;br /&gt;
                             &amp;quot;parameters&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;, &amp;quot;properties&amp;quot;: {&amp;quot;command&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}}, &amp;quot;required&amp;quot;: [&amp;quot;command&amp;quot;]}}&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
                &amp;quot;function&amp;quot;: {&amp;quot;name&amp;quot;: &amp;quot;read_file&amp;quot;, &amp;quot;description&amp;quot;: &amp;quot;Read file.&amp;quot;,&lt;br /&gt;
                             &amp;quot;parameters&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;, &amp;quot;properties&amp;quot;: {&amp;quot;path&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}}, &amp;quot;required&amp;quot;: [&amp;quot;path&amp;quot;]}}&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
                &amp;quot;function&amp;quot;: {&amp;quot;name&amp;quot;: &amp;quot;write_file&amp;quot;, &amp;quot;description&amp;quot;: &amp;quot;Write file.&amp;quot;,&lt;br /&gt;
                             &amp;quot;parameters&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;, &amp;quot;properties&amp;quot;: {&amp;quot;path&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}, &amp;quot;content&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}}, &amp;quot;required&amp;quot;: [&amp;quot;path&amp;quot;, &amp;quot;content&amp;quot;]}}&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
                &amp;quot;function&amp;quot;: {&amp;quot;name&amp;quot;: &amp;quot;edit_file&amp;quot;, &amp;quot;description&amp;quot;: &amp;quot;Edit file.&amp;quot;,&lt;br /&gt;
                             &amp;quot;parameters&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;, &amp;quot;properties&amp;quot;: {&amp;quot;path&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}, &amp;quot;old_text&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}, &amp;quot;new_text&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}}, &amp;quot;required&amp;quot;: [&amp;quot;path&amp;quot;, &amp;quot;old_text&amp;quot;, &amp;quot;new_text&amp;quot;]}}&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
                &amp;quot;function&amp;quot;: {&amp;quot;name&amp;quot;: &amp;quot;send_message&amp;quot;, &amp;quot;description&amp;quot;: &amp;quot;Send message.&amp;quot;,&lt;br /&gt;
                             &amp;quot;parameters&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;, &amp;quot;properties&amp;quot;: {&amp;quot;to&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}, &amp;quot;content&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}}, &amp;quot;required&amp;quot;: [&amp;quot;to&amp;quot;, &amp;quot;content&amp;quot;]}}&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
                &amp;quot;function&amp;quot;: {&amp;quot;name&amp;quot;: &amp;quot;idle&amp;quot;, &amp;quot;description&amp;quot;: &amp;quot;Signal no more work.&amp;quot;,&lt;br /&gt;
                             &amp;quot;parameters&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;, &amp;quot;properties&amp;quot;: {}}}&lt;br /&gt;
            },&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
                &amp;quot;function&amp;quot;: {&amp;quot;name&amp;quot;: &amp;quot;claim_task&amp;quot;, &amp;quot;description&amp;quot;: &amp;quot;Claim task by ID.&amp;quot;,&lt;br /&gt;
                             &amp;quot;parameters&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;, &amp;quot;properties&amp;quot;: {&amp;quot;task_id&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;integer&amp;quot;}}, &amp;quot;required&amp;quot;: [&amp;quot;task_id&amp;quot;]}}&lt;br /&gt;
            },&lt;br /&gt;
        ]&lt;br /&gt;
        while True:&lt;br /&gt;
            # -- WORK PHASE --&lt;br /&gt;
            for _ in range(50):&lt;br /&gt;
                inbox = self.bus.read_inbox(name)&lt;br /&gt;
                for msg in inbox:&lt;br /&gt;
                    if msg.get(&amp;quot;type&amp;quot;) == &amp;quot;shutdown_request&amp;quot;:&lt;br /&gt;
                        self._set_status(name, &amp;quot;shutdown&amp;quot;)&lt;br /&gt;
                        return&lt;br /&gt;
                    messages.append({&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: json.dumps(msg)})&lt;br /&gt;
                try:&lt;br /&gt;
                    response = client.chat.completions.create(&lt;br /&gt;
                        model=MODEL, messages=messages,&lt;br /&gt;
                        tools=tools, max_tokens=8000)&lt;br /&gt;
                except Exception:&lt;br /&gt;
                    self._set_status(name, &amp;quot;shutdown&amp;quot;)&lt;br /&gt;
                    return&lt;br /&gt;
                msg = response.choices[0].message&lt;br /&gt;
                messages.append(msg)&lt;br /&gt;
                if response.choices[0].finish_reason != &amp;quot;tool_calls&amp;quot;:&lt;br /&gt;
                    break&lt;br /&gt;
                idle_requested = False&lt;br /&gt;
                for block in msg.tool_calls or []:&lt;br /&gt;
                    if block.type == &amp;quot;function&amp;quot;:&lt;br /&gt;
                        if block.function.name == &amp;quot;idle&amp;quot;:&lt;br /&gt;
                            idle_requested = True&lt;br /&gt;
                            output = &amp;quot;Entering idle phase.&amp;quot;&lt;br /&gt;
                        elif block.function.name == &amp;quot;claim_task&amp;quot;:&lt;br /&gt;
                            args = json.loads(block.function.arguments)&lt;br /&gt;
                            output = self.task_mgr.claim(args[&amp;quot;task_id&amp;quot;], name)&lt;br /&gt;
                        elif block.function.name == &amp;quot;send_message&amp;quot;:&lt;br /&gt;
                            args = json.loads(block.function.arguments)&lt;br /&gt;
                            output = self.bus.send(name, args[&amp;quot;to&amp;quot;], args[&amp;quot;content&amp;quot;])&lt;br /&gt;
                        else:&lt;br /&gt;
                            args = json.loads(block.function.arguments)&lt;br /&gt;
                            dispatch = {&amp;quot;bash&amp;quot;: lambda **kw: run_bash(kw[&amp;quot;command&amp;quot;]),&lt;br /&gt;
                                        &amp;quot;read_file&amp;quot;: lambda **kw: run_read(kw[&amp;quot;path&amp;quot;]),&lt;br /&gt;
                                        &amp;quot;write_file&amp;quot;: lambda **kw: run_write(kw[&amp;quot;path&amp;quot;], kw[&amp;quot;content&amp;quot;]),&lt;br /&gt;
                                        &amp;quot;edit_file&amp;quot;: lambda **kw: run_edit(kw[&amp;quot;path&amp;quot;], kw[&amp;quot;old_text&amp;quot;], kw[&amp;quot;new_text&amp;quot;])}&lt;br /&gt;
                            output = dispatch.get(block.function.name, lambda **kw: &amp;quot;Unknown&amp;quot;)(**args)&lt;br /&gt;
                        print(f&amp;quot;  [{name}] {block.function.name}: {str(output)[:120]}&amp;quot;)&lt;br /&gt;
                        messages.append({&amp;quot;role&amp;quot;: &amp;quot;tool&amp;quot;, &amp;quot;tool_call_id&amp;quot;: block.id, &amp;quot;name&amp;quot;: block.function.name, &amp;quot;content&amp;quot;: json.dumps({&amp;quot;result&amp;quot;: str(output)})})&lt;br /&gt;
                if idle_requested:&lt;br /&gt;
                    break&lt;br /&gt;
            # -- IDLE PHASE: poll for messages and unclaimed tasks --&lt;br /&gt;
            self._set_status(name, &amp;quot;idle&amp;quot;)&lt;br /&gt;
            resume = False&lt;br /&gt;
            for _ in range(IDLE_TIMEOUT // max(POLL_INTERVAL, 1)):&lt;br /&gt;
                time.sleep(POLL_INTERVAL)&lt;br /&gt;
                inbox = self.bus.read_inbox(name)&lt;br /&gt;
                if inbox:&lt;br /&gt;
                    for msg in inbox:&lt;br /&gt;
                        if msg.get(&amp;quot;type&amp;quot;) == &amp;quot;shutdown_request&amp;quot;:&lt;br /&gt;
                            self._set_status(name, &amp;quot;shutdown&amp;quot;)&lt;br /&gt;
                            return&lt;br /&gt;
                        messages.append({&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: json.dumps(msg)})&lt;br /&gt;
                    resume = True&lt;br /&gt;
                    break&lt;br /&gt;
                unclaimed = []&lt;br /&gt;
                for f in sorted(TASKS_DIR.glob(&amp;quot;task_*.json&amp;quot;)):&lt;br /&gt;
                    t = json.loads(f.read_text())&lt;br /&gt;
                    if t.get(&amp;quot;status&amp;quot;) == &amp;quot;pending&amp;quot; and not t.get(&amp;quot;owner&amp;quot;) and not t.get(&amp;quot;blockedBy&amp;quot;):&lt;br /&gt;
                        unclaimed.append(t)&lt;br /&gt;
                if unclaimed:&lt;br /&gt;
                    task = unclaimed[0]&lt;br /&gt;
                    self.task_mgr.claim(task[&amp;quot;id&amp;quot;], name)&lt;br /&gt;
                    # Identity re-injection for compressed contexts&lt;br /&gt;
                    if len(messages) &amp;lt;= 3:&lt;br /&gt;
                        messages.insert(0, {&amp;quot;role&amp;quot;: &amp;quot;system&amp;quot;, &amp;quot;content&amp;quot;:&lt;br /&gt;
                            f&amp;quot;&amp;lt;identity&amp;gt;You are &#039;{name}&#039;, role: {role}, team: {team_name}.&amp;lt;/identity&amp;gt;&amp;quot;})&lt;br /&gt;
                        messages.insert(1, {&amp;quot;role&amp;quot;: &amp;quot;assistant&amp;quot;, &amp;quot;content&amp;quot;: f&amp;quot;I am {name}. Continuing.&amp;quot;})&lt;br /&gt;
                    messages.append({&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;:&lt;br /&gt;
                        f&amp;quot;&amp;lt;auto-claimed&amp;gt;Task #{task[&#039;id&#039;]}: {task[&#039;subject&#039;]}\n{task.get(&#039;description&#039;, &#039;&#039;)}&amp;lt;/auto-claimed&amp;gt;&amp;quot;})&lt;br /&gt;
                    messages.append({&amp;quot;role&amp;quot;: &amp;quot;assistant&amp;quot;, &amp;quot;content&amp;quot;: f&amp;quot;Claimed task #{task[&#039;id&#039;]}. Working on it.&amp;quot;})&lt;br /&gt;
                    resume = True&lt;br /&gt;
                    break&lt;br /&gt;
            if not resume:&lt;br /&gt;
                self._set_status(name, &amp;quot;shutdown&amp;quot;)&lt;br /&gt;
                return&lt;br /&gt;
            self._set_status(name, &amp;quot;working&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    def list_all(self) -&amp;gt; str:&lt;br /&gt;
        if not self.config[&amp;quot;members&amp;quot;]: return &amp;quot;No teammates.&amp;quot;&lt;br /&gt;
        lines = [f&amp;quot;Team: {self.config[&#039;team_name&#039;]}&amp;quot;]&lt;br /&gt;
        for m in self.config[&amp;quot;members&amp;quot;]:&lt;br /&gt;
            lines.append(f&amp;quot;  {m[&#039;name&#039;]} ({m[&#039;role&#039;]}): {m[&#039;status&#039;]}&amp;quot;)&lt;br /&gt;
        return &amp;quot;\n&amp;quot;.join(lines)&lt;br /&gt;
&lt;br /&gt;
    def member_names(self) -&amp;gt; list:&lt;br /&gt;
        return [m[&amp;quot;name&amp;quot;] for m in self.config[&amp;quot;members&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# === SECTION: global_instances ===&lt;br /&gt;
TODO = TodoManager()&lt;br /&gt;
SKILLS = SkillLoader(SKILLS_DIR)&lt;br /&gt;
TASK_MGR = TaskManager()&lt;br /&gt;
BG = BackgroundManager()&lt;br /&gt;
BUS = MessageBus()&lt;br /&gt;
TEAM = TeammateManager(BUS, TASK_MGR)&lt;br /&gt;
&lt;br /&gt;
# === SECTION: system_prompt ===&lt;br /&gt;
SYSTEM = f&amp;quot;&amp;quot;&amp;quot;You are a coding agent at {WORKDIR}. Use tools to solve tasks.&lt;br /&gt;
Prefer task_create/task_update/task_list for multi-step work. Use TodoWrite for short checklists.&lt;br /&gt;
Use task for subagent delegation. Use load_skill for specialized knowledge.&lt;br /&gt;
Skills: {SKILLS.descriptions()}&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# === SECTION: shutdown_protocol (s10) ===&lt;br /&gt;
def handle_shutdown_request(teammate: str) -&amp;gt; str:&lt;br /&gt;
    req_id = str(uuid.uuid4())[:8]&lt;br /&gt;
    shutdown_requests[req_id] = {&amp;quot;target&amp;quot;: teammate, &amp;quot;status&amp;quot;: &amp;quot;pending&amp;quot;}&lt;br /&gt;
    BUS.send(&amp;quot;lead&amp;quot;, teammate, &amp;quot;Please shut down.&amp;quot;, &amp;quot;shutdown_request&amp;quot;, {&amp;quot;request_id&amp;quot;: req_id})&lt;br /&gt;
    return f&amp;quot;Shutdown request {req_id} sent to &#039;{teammate}&#039;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# === SECTION: plan_approval (s10) ===&lt;br /&gt;
def handle_plan_review(request_id: str, approve: bool, feedback: str = &amp;quot;&amp;quot;) -&amp;gt; str:&lt;br /&gt;
    req = plan_requests.get(request_id)&lt;br /&gt;
    if not req: return f&amp;quot;Error: Unknown plan request_id &#039;{request_id}&#039;&amp;quot;&lt;br /&gt;
    req[&amp;quot;status&amp;quot;] = &amp;quot;approved&amp;quot; if approve else &amp;quot;rejected&amp;quot;&lt;br /&gt;
    BUS.send(&amp;quot;lead&amp;quot;, req[&amp;quot;from&amp;quot;], feedback, &amp;quot;plan_approval_response&amp;quot;,&lt;br /&gt;
             {&amp;quot;request_id&amp;quot;: request_id, &amp;quot;approve&amp;quot;: approve, &amp;quot;feedback&amp;quot;: feedback})&lt;br /&gt;
    return f&amp;quot;Plan {req[&#039;status&#039;]} for &#039;{req[&#039;from&#039;]}&#039;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# === SECTION: tool_dispatch (s02) ===&lt;br /&gt;
TOOL_HANDLERS = {&lt;br /&gt;
    &amp;quot;bash&amp;quot;:             lambda **kw: run_bash(kw[&amp;quot;command&amp;quot;]),&lt;br /&gt;
    &amp;quot;read_file&amp;quot;:        lambda **kw: run_read(kw[&amp;quot;path&amp;quot;], kw.get(&amp;quot;limit&amp;quot;)),&lt;br /&gt;
    &amp;quot;write_file&amp;quot;:       lambda **kw: run_write(kw[&amp;quot;path&amp;quot;], kw[&amp;quot;content&amp;quot;]),&lt;br /&gt;
    &amp;quot;edit_file&amp;quot;:        lambda **kw: run_edit(kw[&amp;quot;path&amp;quot;], kw[&amp;quot;old_text&amp;quot;], kw[&amp;quot;new_text&amp;quot;]),&lt;br /&gt;
    &amp;quot;TodoWrite&amp;quot;:        lambda **kw: TODO.update(kw[&amp;quot;items&amp;quot;]),&lt;br /&gt;
    &amp;quot;task&amp;quot;:             lambda **kw: run_subagent(kw[&amp;quot;prompt&amp;quot;], kw.get(&amp;quot;agent_type&amp;quot;, &amp;quot;Explore&amp;quot;)),&lt;br /&gt;
    &amp;quot;load_skill&amp;quot;:       lambda **kw: SKILLS.load(kw[&amp;quot;name&amp;quot;]),&lt;br /&gt;
    &amp;quot;compress&amp;quot;:         lambda **kw: &amp;quot;Compressing...&amp;quot;,&lt;br /&gt;
    &amp;quot;background_run&amp;quot;:   lambda **kw: BG.run(kw[&amp;quot;command&amp;quot;], kw.get(&amp;quot;timeout&amp;quot;, 120)),&lt;br /&gt;
    &amp;quot;check_background&amp;quot;: lambda **kw: BG.check(kw.get(&amp;quot;task_id&amp;quot;)),&lt;br /&gt;
    &amp;quot;task_create&amp;quot;:      lambda **kw: TASK_MGR.create(kw[&amp;quot;subject&amp;quot;], kw.get(&amp;quot;description&amp;quot;, &amp;quot;&amp;quot;)),&lt;br /&gt;
    &amp;quot;task_get&amp;quot;:         lambda **kw: TASK_MGR.get(kw[&amp;quot;task_id&amp;quot;]),&lt;br /&gt;
    &amp;quot;task_update&amp;quot;:      lambda **kw: TASK_MGR.update(kw[&amp;quot;task_id&amp;quot;], kw.get(&amp;quot;status&amp;quot;), kw.get(&amp;quot;add_blocked_by&amp;quot;), kw.get(&amp;quot;add_blocks&amp;quot;)),&lt;br /&gt;
    &amp;quot;task_list&amp;quot;:        lambda **kw: TASK_MGR.list_all(),&lt;br /&gt;
    &amp;quot;spawn_teammate&amp;quot;:   lambda **kw: TEAM.spawn(kw[&amp;quot;name&amp;quot;], kw[&amp;quot;role&amp;quot;], kw[&amp;quot;prompt&amp;quot;]),&lt;br /&gt;
    &amp;quot;list_teammates&amp;quot;:   lambda **kw: TEAM.list_all(),&lt;br /&gt;
    &amp;quot;send_message&amp;quot;:     lambda **kw: BUS.send(&amp;quot;lead&amp;quot;, kw[&amp;quot;to&amp;quot;], kw[&amp;quot;content&amp;quot;], kw.get(&amp;quot;msg_type&amp;quot;, &amp;quot;message&amp;quot;)),&lt;br /&gt;
    &amp;quot;read_inbox&amp;quot;:       lambda **kw: json.dumps(BUS.read_inbox(&amp;quot;lead&amp;quot;), indent=2),&lt;br /&gt;
    &amp;quot;broadcast&amp;quot;:        lambda **kw: BUS.broadcast(&amp;quot;lead&amp;quot;, kw[&amp;quot;content&amp;quot;], TEAM.member_names()),&lt;br /&gt;
    &amp;quot;shutdown_request&amp;quot;: lambda **kw: handle_shutdown_request(kw[&amp;quot;teammate&amp;quot;]),&lt;br /&gt;
    &amp;quot;plan_approval&amp;quot;:    lambda **kw: handle_plan_review(kw[&amp;quot;request_id&amp;quot;], kw[&amp;quot;approve&amp;quot;], kw.get(&amp;quot;feedback&amp;quot;, &amp;quot;&amp;quot;)),&lt;br /&gt;
    &amp;quot;idle&amp;quot;:             lambda **kw: &amp;quot;Lead does not idle.&amp;quot;,&lt;br /&gt;
    &amp;quot;claim_task&amp;quot;:       lambda **kw: TASK_MGR.claim(kw[&amp;quot;task_id&amp;quot;], &amp;quot;lead&amp;quot;),&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
TOOLS = [&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;bash&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;Run a shell command.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {&amp;quot;command&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}},&lt;br /&gt;
                &amp;quot;required&amp;quot;: [&amp;quot;command&amp;quot;]&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;read_file&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;Read file contents.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {&lt;br /&gt;
                    &amp;quot;path&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;},&lt;br /&gt;
                    &amp;quot;limit&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;integer&amp;quot;}&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;required&amp;quot;: [&amp;quot;path&amp;quot;]&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;write_file&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;Write content to file.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {&lt;br /&gt;
                    &amp;quot;path&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;},&lt;br /&gt;
                    &amp;quot;content&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;required&amp;quot;: [&amp;quot;path&amp;quot;, &amp;quot;content&amp;quot;]&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;edit_file&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;Replace exact text in file.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {&lt;br /&gt;
                    &amp;quot;path&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;},&lt;br /&gt;
                    &amp;quot;old_text&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;},&lt;br /&gt;
                    &amp;quot;new_text&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;required&amp;quot;: [&amp;quot;path&amp;quot;, &amp;quot;old_text&amp;quot;, &amp;quot;new_text&amp;quot;]&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;TodoWrite&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;Update task tracking list.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {&lt;br /&gt;
                    &amp;quot;items&amp;quot;: {&lt;br /&gt;
                        &amp;quot;type&amp;quot;: &amp;quot;array&amp;quot;,&lt;br /&gt;
                        &amp;quot;items&amp;quot;: {&lt;br /&gt;
                            &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                            &amp;quot;properties&amp;quot;: {&lt;br /&gt;
                                &amp;quot;content&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;},&lt;br /&gt;
                                &amp;quot;status&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;, &amp;quot;enum&amp;quot;: [&amp;quot;pending&amp;quot;, &amp;quot;in_progress&amp;quot;, &amp;quot;completed&amp;quot;]},&lt;br /&gt;
                                &amp;quot;activeForm&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}&lt;br /&gt;
                            },&lt;br /&gt;
                            &amp;quot;required&amp;quot;: [&amp;quot;content&amp;quot;, &amp;quot;status&amp;quot;, &amp;quot;activeForm&amp;quot;]&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;required&amp;quot;: [&amp;quot;items&amp;quot;]&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;task&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;Spawn a subagent for isolated exploration or work.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {&lt;br /&gt;
                    &amp;quot;prompt&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;},&lt;br /&gt;
                    &amp;quot;agent_type&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;, &amp;quot;enum&amp;quot;: [&amp;quot;Explore&amp;quot;, &amp;quot;general-purpose&amp;quot;]}&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;required&amp;quot;: [&amp;quot;prompt&amp;quot;]&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;load_skill&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;Load specialized knowledge by name.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {&amp;quot;name&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}},&lt;br /&gt;
                &amp;quot;required&amp;quot;: [&amp;quot;name&amp;quot;]&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;compress&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;Manually compress conversation context.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {}&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;background_run&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;Run command in background thread.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {&lt;br /&gt;
                    &amp;quot;command&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;},&lt;br /&gt;
                    &amp;quot;timeout&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;integer&amp;quot;}&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;required&amp;quot;: [&amp;quot;command&amp;quot;]&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;check_background&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;Check background task status.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {&amp;quot;task_id&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}}&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;task_create&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;Create a persistent file task.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {&lt;br /&gt;
                    &amp;quot;subject&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;},&lt;br /&gt;
                    &amp;quot;description&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;required&amp;quot;: [&amp;quot;subject&amp;quot;]&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;task_get&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;Get task details by ID.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {&amp;quot;task_id&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;integer&amp;quot;}},&lt;br /&gt;
                &amp;quot;required&amp;quot;: [&amp;quot;task_id&amp;quot;]&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;task_update&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;Update task status or dependencies.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {&lt;br /&gt;
                    &amp;quot;task_id&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;integer&amp;quot;},&lt;br /&gt;
                    &amp;quot;status&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;, &amp;quot;enum&amp;quot;: [&amp;quot;pending&amp;quot;, &amp;quot;in_progress&amp;quot;, &amp;quot;completed&amp;quot;, &amp;quot;deleted&amp;quot;]},&lt;br /&gt;
                    &amp;quot;add_blocked_by&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;array&amp;quot;, &amp;quot;items&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;integer&amp;quot;}},&lt;br /&gt;
                    &amp;quot;add_blocks&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;array&amp;quot;, &amp;quot;items&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;integer&amp;quot;}}&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;required&amp;quot;: [&amp;quot;task_id&amp;quot;]&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;task_list&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;List all tasks.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {}&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;spawn_teammate&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;Spawn a persistent autonomous teammate.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {&lt;br /&gt;
                    &amp;quot;name&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;},&lt;br /&gt;
                    &amp;quot;role&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;},&lt;br /&gt;
                    &amp;quot;prompt&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;required&amp;quot;: [&amp;quot;name&amp;quot;, &amp;quot;role&amp;quot;, &amp;quot;prompt&amp;quot;]&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;list_teammates&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;List all teammates.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {}&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;send_message&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;Send a message to a teammate.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {&lt;br /&gt;
                    &amp;quot;to&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;},&lt;br /&gt;
                    &amp;quot;content&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;},&lt;br /&gt;
                    &amp;quot;msg_type&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;, &amp;quot;enum&amp;quot;: list(VALID_MSG_TYPES)}&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;required&amp;quot;: [&amp;quot;to&amp;quot;, &amp;quot;content&amp;quot;]&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;read_inbox&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;Read and drain the lead&#039;s inbox.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {}&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;broadcast&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;Send message to all teammates.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {&amp;quot;content&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}},&lt;br /&gt;
                &amp;quot;required&amp;quot;: [&amp;quot;content&amp;quot;]&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;shutdown_request&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;Request a teammate to shut down.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {&amp;quot;teammate&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}},&lt;br /&gt;
                &amp;quot;required&amp;quot;: [&amp;quot;teammate&amp;quot;]&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;plan_approval&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;Approve or reject a teammate&#039;s plan.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {&lt;br /&gt;
                    &amp;quot;request_id&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;},&lt;br /&gt;
                    &amp;quot;approve&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;boolean&amp;quot;},&lt;br /&gt;
                    &amp;quot;feedback&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;required&amp;quot;: [&amp;quot;request_id&amp;quot;, &amp;quot;approve&amp;quot;]&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;idle&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;Enter idle state.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {}&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;function&amp;quot;,&lt;br /&gt;
        &amp;quot;function&amp;quot;: {&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;claim_task&amp;quot;,&lt;br /&gt;
            &amp;quot;description&amp;quot;: &amp;quot;Claim a task from the board.&amp;quot;,&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: {&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
                &amp;quot;properties&amp;quot;: {&amp;quot;task_id&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;integer&amp;quot;}},&lt;br /&gt;
                &amp;quot;required&amp;quot;: [&amp;quot;task_id&amp;quot;]&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# === SECTION: agent_loop ===&lt;br /&gt;
def agent_loop(messages: list):&lt;br /&gt;
    rounds_without_todo = 0&lt;br /&gt;
    while True:&lt;br /&gt;
        # s06: compression pipeline&lt;br /&gt;
        microcompact(messages)&lt;br /&gt;
        if estimate_tokens(messages) &amp;gt; TOKEN_THRESHOLD:&lt;br /&gt;
            print(&amp;quot;[auto-compact triggered]&amp;quot;)&lt;br /&gt;
            messages[:] = auto_compact(messages)&lt;br /&gt;
        # s08: drain background notifications&lt;br /&gt;
        notifs = BG.drain()&lt;br /&gt;
        if notifs:&lt;br /&gt;
            txt = &amp;quot;\n&amp;quot;.join(f&amp;quot;[bg:{n[&#039;task_id&#039;]}] {n[&#039;status&#039;]}: {n[&#039;result&#039;]}&amp;quot; for n in notifs)&lt;br /&gt;
            messages.append({&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: f&amp;quot;&amp;lt;background-results&amp;gt;\n{txt}\n&amp;lt;/background-results&amp;gt;&amp;quot;})&lt;br /&gt;
        # s10: check lead inbox&lt;br /&gt;
        inbox = BUS.read_inbox(&amp;quot;lead&amp;quot;)&lt;br /&gt;
        if inbox:&lt;br /&gt;
            messages.append({&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: f&amp;quot;&amp;lt;inbox&amp;gt;{json.dumps(inbox, indent=2)}&amp;lt;/inbox&amp;gt;&amp;quot;})&lt;br /&gt;
        # LLM call&lt;br /&gt;
        response = client.chat.completions.create(&lt;br /&gt;
            model=MODEL, messages=messages,&lt;br /&gt;
            tools=TOOLS # , max_tokens=8000,&lt;br /&gt;
        )&lt;br /&gt;
        msg = response.choices[0].message&lt;br /&gt;
        messages.append(msg)&lt;br /&gt;
        if response.choices[0].finish_reason != &amp;quot;tool_calls&amp;quot;:&lt;br /&gt;
            return&lt;br /&gt;
        # Tool execution&lt;br /&gt;
        used_todo = False&lt;br /&gt;
        manual_compress = False&lt;br /&gt;
        for block in msg.tool_calls or []:&lt;br /&gt;
            if block.type == &amp;quot;function&amp;quot;:&lt;br /&gt;
                if block.function.name == &amp;quot;compress&amp;quot;:&lt;br /&gt;
                    manual_compress = True&lt;br /&gt;
                    output = &amp;quot;Compressing...&amp;quot;&lt;br /&gt;
                else:&lt;br /&gt;
                    handler = TOOL_HANDLERS.get(block.function.name)&lt;br /&gt;
                    try:&lt;br /&gt;
                        args = json.loads(block.function.arguments)&lt;br /&gt;
                        output = handler(**args) if handler else f&amp;quot;Unknown tool: {block.function.name}&amp;quot;&lt;br /&gt;
                    except Exception as e:&lt;br /&gt;
                        output = f&amp;quot;Error: {e}&amp;quot;&lt;br /&gt;
                print(f&amp;quot;&amp;gt; {block.function.name}: {str(output)[:200]}&amp;quot;)&lt;br /&gt;
                messages.append({&amp;quot;role&amp;quot;: &amp;quot;tool&amp;quot;, &amp;quot;tool_call_id&amp;quot;: block.id, &amp;quot;name&amp;quot;: block.function.name, &amp;quot;content&amp;quot;: json.dumps({&amp;quot;result&amp;quot;: str(output)})})&lt;br /&gt;
                if block.function.name == &amp;quot;TodoWrite&amp;quot;:&lt;br /&gt;
                    used_todo = True&lt;br /&gt;
        # s03: nag reminder (only when todo workflow is active)&lt;br /&gt;
        rounds_without_todo = 0 if used_todo else rounds_without_todo + 1&lt;br /&gt;
        if TODO.has_open_items() and rounds_without_todo &amp;gt;= 3:&lt;br /&gt;
            messages.append({&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;&amp;lt;reminder&amp;gt;Update your todos.&amp;lt;/reminder&amp;gt;&amp;quot;})&lt;br /&gt;
            rounds_without_todo = 0&lt;br /&gt;
        # s06: manual compress&lt;br /&gt;
        if manual_compress:&lt;br /&gt;
            print(&amp;quot;[manual compact]&amp;quot;)&lt;br /&gt;
            messages[:] = auto_compact(messages)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# === SECTION: repl ===&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    history = []&lt;br /&gt;
    while True:&lt;br /&gt;
        try:&lt;br /&gt;
            query = input(&amp;quot;\033[36ms_full &amp;gt;&amp;gt; \033[0m&amp;quot;)&lt;br /&gt;
        except (EOFError, KeyboardInterrupt):&lt;br /&gt;
            break&lt;br /&gt;
        if query.strip().lower() in (&amp;quot;q&amp;quot;, &amp;quot;exit&amp;quot;, &amp;quot;&amp;quot;):&lt;br /&gt;
            break&lt;br /&gt;
        if query.strip() == &amp;quot;/compact&amp;quot;:&lt;br /&gt;
            if history:&lt;br /&gt;
                print(&amp;quot;[manual compact via /compact]&amp;quot;)&lt;br /&gt;
                history[:] = auto_compact(history)&lt;br /&gt;
            continue&lt;br /&gt;
        if query.strip() == &amp;quot;/tasks&amp;quot;:&lt;br /&gt;
            print(TASK_MGR.list_all())&lt;br /&gt;
            continue&lt;br /&gt;
        if query.strip() == &amp;quot;/team&amp;quot;:&lt;br /&gt;
            print(TEAM.list_all())&lt;br /&gt;
            continue&lt;br /&gt;
        if query.strip() == &amp;quot;/inbox&amp;quot;:&lt;br /&gt;
            print(json.dumps(BUS.read_inbox(&amp;quot;lead&amp;quot;), indent=2))&lt;br /&gt;
            continue&lt;br /&gt;
        history.append({&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: query})&lt;br /&gt;
        # system=SYSTEM, &lt;br /&gt;
        agent_loop(history)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E5%88%86%E7%B1%BB:AI&amp;diff=121</id>
		<title>分类:AI</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E5%88%86%E7%B1%BB:AI&amp;diff=121"/>
		<updated>2026-04-08T05:00:37Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[构建自己的Harness系统--基于Kimi2.5大模型]]&lt;br /&gt;
&lt;br /&gt;
[[多智能体协作实践：从单打独斗到团队作战（构建自己的AI Agent)]]&lt;br /&gt;
&lt;br /&gt;
[[任务系统与依赖管理：让目标超越对话(构建自己的AI Agent）]]&lt;br /&gt;
&lt;br /&gt;
[[子智能体与上下文隔离：保持思维清晰的关键]]&lt;br /&gt;
&lt;br /&gt;
[[让AI Agent不再迷失：规划的艺术]]&lt;br /&gt;
&lt;br /&gt;
[[30行代码构建你的第一个AI Agent]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[[什么是真正的 AI Agent？模型即智能体的深度解析]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Transformer架构如何驱动现代大语言模型：深入解析AI核心技术]]&lt;br /&gt;
&lt;br /&gt;
[[大语言模型评估指南]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E5%A4%9A%E6%99%BA%E8%83%BD%E4%BD%93%E5%8D%8F%E4%BD%9C%E5%AE%9E%E8%B7%B5%EF%BC%9A%E4%BB%8E%E5%8D%95%E6%89%93%E7%8B%AC%E6%96%97%E5%88%B0%E5%9B%A2%E9%98%9F%E4%BD%9C%E6%88%98%EF%BC%88%E6%9E%84%E5%BB%BA%E8%87%AA%E5%B7%B1%E7%9A%84AI_Agent)&amp;diff=120</id>
		<title>多智能体协作实践：从单打独斗到团队作战（构建自己的AI Agent)</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E5%A4%9A%E6%99%BA%E8%83%BD%E4%BD%93%E5%8D%8F%E4%BD%9C%E5%AE%9E%E8%B7%B5%EF%BC%9A%E4%BB%8E%E5%8D%95%E6%89%93%E7%8B%AC%E6%96%97%E5%88%B0%E5%9B%A2%E9%98%9F%E4%BD%9C%E6%88%98%EF%BC%88%E6%9E%84%E5%BB%BA%E8%87%AA%E5%B7%B1%E7%9A%84AI_Agent)&amp;diff=120"/>
		<updated>2026-03-23T05:04:36Z</updated>

		<summary type="html">&lt;p&gt;Admin：​创建页面，内容为“&amp;lt;blockquote&amp;gt;&amp;quot;任务太大一个人干不完，要能分给队友&amp;quot; —— 持久化队友 + JSONL 邮箱。&amp;lt;/blockquote&amp;gt;前面的子智能体是一次性的：生成、干活、返回摘要、消亡。没有身份，没有跨调用的记忆。  真正的团队协作需要三样东西：  # &amp;#039;&amp;#039;&amp;#039;能跨多轮对话存活的持久智能体&amp;#039;&amp;#039;&amp;#039; # &amp;#039;&amp;#039;&amp;#039;身份和生命周期管理&amp;#039;&amp;#039;&amp;#039; # &amp;#039;&amp;#039;&amp;#039;智能体之间的通信通道&amp;#039;&amp;#039;&amp;#039;  == 一、团队架构 ==  &amp;lt;code&amp;gt;Teammate lifecycle…”&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;blockquote&amp;gt;&amp;quot;任务太大一个人干不完，要能分给队友&amp;quot; —— 持久化队友 + JSONL 邮箱。&amp;lt;/blockquote&amp;gt;前面的子智能体是一次性的：生成、干活、返回摘要、消亡。没有身份，没有跨调用的记忆。&lt;br /&gt;
&lt;br /&gt;
真正的团队协作需要三样东西：&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;能跨多轮对话存活的持久智能体&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;身份和生命周期管理&#039;&#039;&#039;&lt;br /&gt;
# &#039;&#039;&#039;智能体之间的通信通道&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== 一、团队架构 ==&lt;br /&gt;
 &amp;lt;code&amp;gt;Teammate lifecycle:&lt;br /&gt;
   spawn -&amp;gt; WORKING -&amp;gt; IDLE -&amp;gt; WORKING -&amp;gt; ... -&amp;gt; SHUTDOWN&lt;br /&gt;
 &lt;br /&gt;
 Communication:&lt;br /&gt;
   .team/&lt;br /&gt;
     config.json           &amp;lt;- 团队名册 + 状态&lt;br /&gt;
     inbox/&lt;br /&gt;
       alice.jsonl         &amp;lt;- 追加式，读取即清空&lt;br /&gt;
       bob.jsonl&lt;br /&gt;
       lead.jsonl&lt;br /&gt;
 &lt;br /&gt;
               +--------+    send(&amp;quot;alice&amp;quot;,&amp;quot;bob&amp;quot;,&amp;quot;...&amp;quot;)    +--------+&lt;br /&gt;
               | alice  | -----------------------------&amp;gt; |  bob   |&lt;br /&gt;
               | loop   |    bob.jsonl &amp;lt;&amp;lt; {json_line}    |  loop  |&lt;br /&gt;
               +--------+                                +--------+&lt;br /&gt;
                    ^                                         |&lt;br /&gt;
                    |        BUS.read_inbox(&amp;quot;alice&amp;quot;)          |&lt;br /&gt;
                    +---- alice.jsonl -&amp;gt; read + drain ---------+&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 二、核心组件 ==&lt;br /&gt;
&lt;br /&gt;
=== 1. TeammateManager ===&lt;br /&gt;
通过 &amp;lt;code&amp;gt;config.json&amp;lt;/code&amp;gt; 维护团队名册：&lt;br /&gt;
 &amp;lt;code&amp;gt;class TeammateManager:&lt;br /&gt;
     def __init__(self, team_dir: Path):&lt;br /&gt;
         self.dir = team_dir&lt;br /&gt;
         self.dir.mkdir(exist_ok=True)&lt;br /&gt;
         self.config_path = self.dir / &amp;quot;config.json&amp;quot;&lt;br /&gt;
         self.config = self._load_config()&lt;br /&gt;
         self.threads = {}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2. 生成队友 ===&lt;br /&gt;
&amp;lt;code&amp;gt;spawn()&amp;lt;/code&amp;gt; 创建队友并在线程中启动 Agent 循环：&lt;br /&gt;
 &amp;lt;code&amp;gt;def spawn(self, name: str, role: str, prompt: str) -&amp;gt; str:&lt;br /&gt;
     member = {&lt;br /&gt;
         &amp;quot;name&amp;quot;: name,&lt;br /&gt;
         &amp;quot;role&amp;quot;: role,&lt;br /&gt;
         &amp;quot;status&amp;quot;: &amp;quot;working&amp;quot;&lt;br /&gt;
     }&lt;br /&gt;
     self.config[&amp;quot;members&amp;quot;].append(member)&lt;br /&gt;
     self._save_config()&lt;br /&gt;
     &lt;br /&gt;
     thread = threading.Thread(&lt;br /&gt;
         target=self._teammate_loop,&lt;br /&gt;
         args=(name, role, prompt),&lt;br /&gt;
         daemon=True&lt;br /&gt;
     )&lt;br /&gt;
     thread.start()&lt;br /&gt;
     return f&amp;quot;Spawned teammate &#039;{name}&#039; (role: {role})&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 3. MessageBus ===&lt;br /&gt;
追加式 JSONL 收件箱：&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;send()&amp;lt;/code&amp;gt; 追加一行&lt;br /&gt;
* &amp;lt;code&amp;gt;read_inbox()&amp;lt;/code&amp;gt; 读取全部并清空&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;code&amp;gt;class MessageBus:&lt;br /&gt;
     def send(self, sender, to, content, &lt;br /&gt;
              msg_type=&amp;quot;message&amp;quot;, extra=None):&lt;br /&gt;
         msg = {&lt;br /&gt;
             &amp;quot;type&amp;quot;: msg_type,&lt;br /&gt;
             &amp;quot;from&amp;quot;: sender,&lt;br /&gt;
             &amp;quot;content&amp;quot;: content,&lt;br /&gt;
             &amp;quot;timestamp&amp;quot;: time.time()&lt;br /&gt;
         }&lt;br /&gt;
         if extra:&lt;br /&gt;
             msg.update(extra)&lt;br /&gt;
         with open(self.dir / f&amp;quot;{to}.jsonl&amp;quot;, &amp;quot;a&amp;quot;) as f:&lt;br /&gt;
             f.write(json.dumps(msg) + &amp;quot;\n&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
     def read_inbox(self, name):&lt;br /&gt;
         path = self.dir / f&amp;quot;{name}.jsonl&amp;quot;&lt;br /&gt;
         if not path.exists():&lt;br /&gt;
             return &amp;quot;[]&amp;quot;&lt;br /&gt;
         msgs = [json.loads(l) for l in &lt;br /&gt;
                 path.read_text().strip().splitlines() if l]&lt;br /&gt;
         path.write_text(&amp;quot;&amp;quot;)  &#039;&#039;# drain&#039;&#039;&lt;br /&gt;
         return json.dumps(msgs, indent=2)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 4. 队友循环 ===&lt;br /&gt;
每个队友在每次 LLM 调用前检查收件箱：&lt;br /&gt;
 &amp;lt;code&amp;gt;def _teammate_loop(self, name, role, prompt):&lt;br /&gt;
     messages = [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: prompt}]&lt;br /&gt;
     for _ in range(50):&lt;br /&gt;
         &#039;&#039;# 检查收件箱&#039;&#039;&lt;br /&gt;
         inbox = BUS.read_inbox(name)&lt;br /&gt;
         if inbox != &amp;quot;[]&amp;quot;:&lt;br /&gt;
             messages.append({&lt;br /&gt;
                 &amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;,&lt;br /&gt;
                 &amp;quot;content&amp;quot;: f&amp;quot;&amp;lt;inbox&amp;gt;{inbox}&amp;lt;/inbox&amp;gt;&amp;quot;&lt;br /&gt;
             })&lt;br /&gt;
             messages.append({&lt;br /&gt;
                 &amp;quot;role&amp;quot;: &amp;quot;assistant&amp;quot;,&lt;br /&gt;
                 &amp;quot;content&amp;quot;: &amp;quot;Noted inbox messages.&amp;quot;&lt;br /&gt;
             })&lt;br /&gt;
         &lt;br /&gt;
         &#039;&#039;# 调用 LLM&#039;&#039;&lt;br /&gt;
         response = client.messages.create(...)&lt;br /&gt;
         &lt;br /&gt;
         if response.stop_reason != &amp;quot;tool_use&amp;quot;:&lt;br /&gt;
             break&lt;br /&gt;
         &#039;&#039;# 执行工具，追加结果...&#039;&#039;&lt;br /&gt;
     &lt;br /&gt;
     self._find_member(name)[&amp;quot;status&amp;quot;] = &amp;quot;idle&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 三、试一试 ==&lt;br /&gt;
 &amp;lt;code&amp;gt;cd learn-claude-code&lt;br /&gt;
 python agents/s09_agent_teams.py&amp;lt;/code&amp;gt;&lt;br /&gt;
试试这些 prompt：&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;code&amp;gt;Spawn alice (coder) and bob (tester). Have alice send bob a message.&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;Broadcast &amp;quot;status update: phase 1 complete&amp;quot; to all teammates&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;Check the lead inbox for any messages&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
也可以使用快捷命令：&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;/team&amp;lt;/code&amp;gt; 查看团队名册和状态&lt;br /&gt;
* &amp;lt;code&amp;gt;/inbox&amp;lt;/code&amp;gt; 手动检查领导的收件箱&lt;br /&gt;
&lt;br /&gt;
== 四、团队协作模式 ==&lt;br /&gt;
&lt;br /&gt;
=== 模式 1：领导指派 ===&lt;br /&gt;
 &amp;lt;code&amp;gt;Leader: Spawn alice (coder) and bob (reviewer)&lt;br /&gt;
 Leader: Send alice &amp;quot;Implement user authentication&amp;quot;&lt;br /&gt;
 Alice:  (works on task)&lt;br /&gt;
 Alice:  Send leader &amp;quot;Task complete, needs review&amp;quot;&lt;br /&gt;
 Leader: Send bob &amp;quot;Review alice&#039;s auth implementation&amp;quot;&lt;br /&gt;
 Bob:    (reviews code)&lt;br /&gt;
 Bob:    Send leader &amp;quot;Review complete, 2 issues found&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 模式 2：广播通知 ===&lt;br /&gt;
 &amp;lt;code&amp;gt;Leader: Broadcast &amp;quot;Phase 1 complete, starting Phase 2&amp;quot;&lt;br /&gt;
 Alice:  (receives broadcast)&lt;br /&gt;
 Bob:    (receives broadcast)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 模式 3：点对点协作 ===&lt;br /&gt;
 &amp;lt;code&amp;gt;Alice: Send bob &amp;quot;Can you check the API spec?&amp;quot;&lt;br /&gt;
 Bob:   (checks spec)&lt;br /&gt;
 Bob:   Send alice &amp;quot;Spec says POST /api/v1/users&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 五、进阶：自治智能体 ==&lt;br /&gt;
s09 的队友只在被明确指派时才动。领导得给每个队友写 prompt。&lt;br /&gt;
&lt;br /&gt;
在 s11 中，我们将升级到&#039;&#039;&#039;自治智能体&#039;&#039;&#039;：&amp;lt;blockquote&amp;gt;&amp;quot;队友自己看看板，有活就认领&amp;quot;&amp;lt;/blockquote&amp;gt;队友自己扫描任务看板，认领没人做的任务，做完再找下一个。&lt;br /&gt;
&lt;br /&gt;
=== 空闲阶段轮询 ===&lt;br /&gt;
 &amp;lt;code&amp;gt;def _idle_poll(self, name, messages):&lt;br /&gt;
     for _ in range(IDLE_TIMEOUT // POLL_INTERVAL):&lt;br /&gt;
         time.sleep(POLL_INTERVAL)&lt;br /&gt;
         &lt;br /&gt;
         &#039;&#039;# 检查收件箱&#039;&#039;&lt;br /&gt;
         inbox = BUS.read_inbox(name)&lt;br /&gt;
         if inbox:&lt;br /&gt;
             messages.append({&lt;br /&gt;
                 &amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;,&lt;br /&gt;
                 &amp;quot;content&amp;quot;: f&amp;quot;&amp;lt;inbox&amp;gt;{inbox}&amp;lt;/inbox&amp;gt;&amp;quot;&lt;br /&gt;
             })&lt;br /&gt;
             return True&lt;br /&gt;
         &lt;br /&gt;
         &#039;&#039;# 扫描未认领任务&#039;&#039;&lt;br /&gt;
         unclaimed = scan_unclaimed_tasks()&lt;br /&gt;
         if unclaimed:&lt;br /&gt;
             claim_task(unclaimed[0][&amp;quot;id&amp;quot;], name)&lt;br /&gt;
             messages.append({&lt;br /&gt;
                 &amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;,&lt;br /&gt;
                 &amp;quot;content&amp;quot;: f&amp;quot;&amp;lt;auto-claimed&amp;gt;Task #{unclaimed[0][&#039;id&#039;]}&amp;lt;/auto-claimed&amp;gt;&amp;quot;&lt;br /&gt;
             })&lt;br /&gt;
             return True&lt;br /&gt;
     &lt;br /&gt;
     return False  &#039;&#039;# timeout -&amp;gt; shutdown&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 自组织工作流 ===&lt;br /&gt;
 &amp;lt;code&amp;gt;1. 创建任务看板&lt;br /&gt;
 2. 生成多个队友&lt;br /&gt;
 3. 队友自动扫描看板&lt;br /&gt;
 4. 认领可执行任务&lt;br /&gt;
 5. 完成后继续扫描&lt;br /&gt;
 6. 60秒空闲后自动关闭&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;不需要领导逐个分配，真正的自组织。&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== 六、试一试（自治版） ==&lt;br /&gt;
 &amp;lt;code&amp;gt;cd learn-claude-code&lt;br /&gt;
 python agents/s11_autonomous_agents.py&amp;lt;/code&amp;gt;&lt;br /&gt;
试试这些 prompt：&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;code&amp;gt;Create 3 tasks on the board, then spawn alice and bob. Watch them auto-claim.&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;Spawn a coder teammate and let it find work from the task board itself&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;Create tasks with dependencies. Watch teammates respect the blocked order.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
快捷命令：&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;/tasks&amp;lt;/code&amp;gt; 查看带 owner 的任务看板&lt;br /&gt;
* &amp;lt;code&amp;gt;/team&amp;lt;/code&amp;gt; 监控谁在工作、谁在空闲&lt;br /&gt;
&lt;br /&gt;
== 七、设计哲学 ==&lt;br /&gt;
&#039;&#039;&#039;多模型，通过文件协调。&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
这是 Harness 工程的精髓：&lt;br /&gt;
&lt;br /&gt;
* 不共享内存，避免竞态条件&lt;br /&gt;
* 通过文件系统通信，天然持久化&lt;br /&gt;
* JSONL 格式简单、可扩展&lt;br /&gt;
* 每个 Agent 独立运行，松耦合&lt;br /&gt;
&lt;br /&gt;
这种模式不仅适用于编程，也适用于：&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;客服团队&#039;&#039;&#039;：不同专长的 Agent 处理不同类型的工单&lt;br /&gt;
* &#039;&#039;&#039;研究团队&#039;&#039;&#039;：文献检索、实验设计、数据分析分工协作&lt;br /&gt;
* &#039;&#039;&#039;创意团队&#039;&#039;&#039;：头脑风暴、方案评估、细节执行分层处理&lt;br /&gt;
&lt;br /&gt;
== 八、总结 ==&lt;br /&gt;
从单 Agent → 子 Agent → 多 Agent 团队 → 自治 Agent，Harness 的复杂度逐步提升，但核心原则不变：&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Harness 提供机制，模型决定策略。&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Harness 提供 spawn、send、inbox 工具&lt;br /&gt;
* 模型决定什么时候生成队友、给谁发消息&lt;br /&gt;
* 模型决定认领哪个任务、如何协作&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;优秀的 Harness 工程师是环境设计师&#039;&#039;&#039;——创造能让智能高效协作的基础设施。&lt;br /&gt;
----&#039;&#039;Bash 就够了。真正的 Agent 是宇宙所需要的全部。&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E5%88%86%E7%B1%BB:AI&amp;diff=119</id>
		<title>分类:AI</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E5%88%86%E7%B1%BB:AI&amp;diff=119"/>
		<updated>2026-03-23T05:04:07Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[多智能体协作实践：从单打独斗到团队作战（构建自己的AI Agent)]]&lt;br /&gt;
&lt;br /&gt;
[[任务系统与依赖管理：让目标超越对话(构建自己的AI Agent）]]&lt;br /&gt;
&lt;br /&gt;
[[子智能体与上下文隔离：保持思维清晰的关键]]&lt;br /&gt;
&lt;br /&gt;
[[让AI Agent不再迷失：规划的艺术]]&lt;br /&gt;
&lt;br /&gt;
[[30行代码构建你的第一个AI Agent]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[[什么是真正的 AI Agent？模型即智能体的深度解析]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Transformer架构如何驱动现代大语言模型：深入解析AI核心技术]]&lt;br /&gt;
&lt;br /&gt;
[[大语言模型评估指南]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E5%88%86%E7%B1%BB:AI&amp;diff=118</id>
		<title>分类:AI</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E5%88%86%E7%B1%BB:AI&amp;diff=118"/>
		<updated>2026-03-23T05:03:51Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;多智能体协作实践：从单打独斗到团队作战（构建自己的AI Agent)&lt;br /&gt;
&lt;br /&gt;
[[任务系统与依赖管理：让目标超越对话(构建自己的AI Agent）]]&lt;br /&gt;
&lt;br /&gt;
[[子智能体与上下文隔离：保持思维清晰的关键]]&lt;br /&gt;
&lt;br /&gt;
[[让AI Agent不再迷失：规划的艺术]]&lt;br /&gt;
&lt;br /&gt;
[[30行代码构建你的第一个AI Agent]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[[什么是真正的 AI Agent？模型即智能体的深度解析]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Transformer架构如何驱动现代大语言模型：深入解析AI核心技术]]&lt;br /&gt;
&lt;br /&gt;
[[大语言模型评估指南]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E4%BB%BB%E5%8A%A1%E7%B3%BB%E7%BB%9F%E4%B8%8E%E4%BE%9D%E8%B5%96%E7%AE%A1%E7%90%86%EF%BC%9A%E8%AE%A9%E7%9B%AE%E6%A0%87%E8%B6%85%E8%B6%8A%E5%AF%B9%E8%AF%9D(%E6%9E%84%E5%BB%BA%E8%87%AA%E5%B7%B1%E7%9A%84AI_Agent%EF%BC%89&amp;diff=117</id>
		<title>任务系统与依赖管理：让目标超越对话(构建自己的AI Agent）</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E4%BB%BB%E5%8A%A1%E7%B3%BB%E7%BB%9F%E4%B8%8E%E4%BE%9D%E8%B5%96%E7%AE%A1%E7%90%86%EF%BC%9A%E8%AE%A9%E7%9B%AE%E6%A0%87%E8%B6%85%E8%B6%8A%E5%AF%B9%E8%AF%9D(%E6%9E%84%E5%BB%BA%E8%87%AA%E5%B7%B1%E7%9A%84AI_Agent%EF%BC%89&amp;diff=117"/>
		<updated>2026-03-23T05:02:35Z</updated>

		<summary type="html">&lt;p&gt;Admin：​创建页面，内容为“&amp;lt;blockquote&amp;gt;&amp;quot;大目标要拆成小任务，排好序，记在磁盘上&amp;quot; —— 文件持久化的任务图，为多 Agent 协作打基础。&amp;lt;/blockquote&amp;gt;前面的 TodoManager 是内存中的扁平清单：没有顺序、没有依赖、状态只有做完没做完。  真实的目标是有结构的——任务 B 依赖任务 A，任务 C 和 D 可以并行，任务 E 要等 C 和 D 都完成。  没有显式的关系，Agent 分不清什么能做、什么被卡…”&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;blockquote&amp;gt;&amp;quot;大目标要拆成小任务，排好序，记在磁盘上&amp;quot; —— 文件持久化的任务图，为多 Agent 协作打基础。&amp;lt;/blockquote&amp;gt;前面的 TodoManager 是内存中的扁平清单：没有顺序、没有依赖、状态只有做完没做完。&lt;br /&gt;
&lt;br /&gt;
真实的目标是有结构的——任务 B 依赖任务 A，任务 C 和 D 可以并行，任务 E 要等 C 和 D 都完成。&lt;br /&gt;
&lt;br /&gt;
没有显式的关系，Agent 分不清什么能做、什么被卡住、什么能同时跑。&lt;br /&gt;
&lt;br /&gt;
== 一、从清单到图 ==&lt;br /&gt;
我们需要把扁平清单升级为&#039;&#039;&#039;持久化到磁盘的任务图&#039;&#039;&#039;。&lt;br /&gt;
 &amp;lt;code&amp;gt;.tasks/&lt;br /&gt;
   task_1.json  {&amp;quot;id&amp;quot;:1, &amp;quot;status&amp;quot;:&amp;quot;completed&amp;quot;}&lt;br /&gt;
   task_2.json  {&amp;quot;id&amp;quot;:2, &amp;quot;blockedBy&amp;quot;:[1], &amp;quot;status&amp;quot;:&amp;quot;pending&amp;quot;}&lt;br /&gt;
   task_3.json  {&amp;quot;id&amp;quot;:3, &amp;quot;blockedBy&amp;quot;:[1], &amp;quot;status&amp;quot;:&amp;quot;pending&amp;quot;}&lt;br /&gt;
   task_4.json  {&amp;quot;id&amp;quot;:4, &amp;quot;blockedBy&amp;quot;:[2,3], &amp;quot;status&amp;quot;:&amp;quot;pending&amp;quot;}&lt;br /&gt;
 &lt;br /&gt;
 任务图 (DAG):&lt;br /&gt;
                  +----------+&lt;br /&gt;
             +--&amp;gt; | task 2   | --+&lt;br /&gt;
             |    | pending  |   |&lt;br /&gt;
 +----------+     +----------+    +--&amp;gt; +----------+&lt;br /&gt;
 | task 1   |                          | task 4   |&lt;br /&gt;
 | completed| --&amp;gt; +----------+    +--&amp;gt; | blocked  |&lt;br /&gt;
 +----------+     | task 3   | --+     +----------+&lt;br /&gt;
                  | pending  |&lt;br /&gt;
                  +----------+&lt;br /&gt;
 &lt;br /&gt;
 顺序:   task 1 必须先完成, 才能开始 2 和 3&lt;br /&gt;
 并行:   task 2 和 3 可以同时执行&lt;br /&gt;
 依赖:   task 4 要等 2 和 3 都完成&lt;br /&gt;
 状态:   pending -&amp;gt; in_progress -&amp;gt; completed&amp;lt;/code&amp;gt;&lt;br /&gt;
这个任务图是后续所有机制的协调骨架：后台执行、多 Agent 团队、工作区隔离都读写这同一个结构。&lt;br /&gt;
&lt;br /&gt;
== 二、核心能力 ==&lt;br /&gt;
任务图随时回答三个问题：&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;什么可以做？&#039;&#039;&#039; —— 状态为 &amp;lt;code&amp;gt;pending&amp;lt;/code&amp;gt; 且 &amp;lt;code&amp;gt;blockedBy&amp;lt;/code&amp;gt; 为空的任务&lt;br /&gt;
# &#039;&#039;&#039;什么被卡住？&#039;&#039;&#039; —— 等待前置任务完成的任务&lt;br /&gt;
# &#039;&#039;&#039;什么做完了？&#039;&#039;&#039; —— 状态为 &amp;lt;code&amp;gt;completed&amp;lt;/code&amp;gt; 的任务，完成时自动解锁后续任务&lt;br /&gt;
&lt;br /&gt;
== 三、核心机制 ==&lt;br /&gt;
&lt;br /&gt;
=== 1. TaskManager ===&lt;br /&gt;
每个任务一个 JSON 文件，支持 CRUD + 依赖图：&lt;br /&gt;
 &amp;lt;code&amp;gt;class TaskManager:&lt;br /&gt;
     def __init__(self, tasks_dir: Path):&lt;br /&gt;
         self.dir = tasks_dir&lt;br /&gt;
         self.dir.mkdir(exist_ok=True)&lt;br /&gt;
         self._next_id = self._max_id() + 1&lt;br /&gt;
 &lt;br /&gt;
     def create(self, subject, description=&amp;quot;&amp;quot;):&lt;br /&gt;
         task = {&lt;br /&gt;
             &amp;quot;id&amp;quot;: self._next_id,&lt;br /&gt;
             &amp;quot;subject&amp;quot;: subject,&lt;br /&gt;
             &amp;quot;status&amp;quot;: &amp;quot;pending&amp;quot;,&lt;br /&gt;
             &amp;quot;blockedBy&amp;quot;: [],&lt;br /&gt;
             &amp;quot;blocks&amp;quot;: [],&lt;br /&gt;
             &amp;quot;owner&amp;quot;: &amp;quot;&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
         self._save(task)&lt;br /&gt;
         self._next_id += 1&lt;br /&gt;
         return json.dumps(task, indent=2)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2. 依赖解除 ===&lt;br /&gt;
完成任务时，自动将其 ID 从其他任务的 &amp;lt;code&amp;gt;blockedBy&amp;lt;/code&amp;gt; 中移除：&lt;br /&gt;
 &amp;lt;code&amp;gt;def _clear_dependency(self, completed_id):&lt;br /&gt;
     for f in self.dir.glob(&amp;quot;task_*.json&amp;quot;):&lt;br /&gt;
         task = json.loads(f.read_text())&lt;br /&gt;
         if completed_id in task.get(&amp;quot;blockedBy&amp;quot;, []):&lt;br /&gt;
             task[&amp;quot;blockedBy&amp;quot;].remove(completed_id)&lt;br /&gt;
             self._save(task)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 3. 状态变更 + 依赖关联 ===&lt;br /&gt;
&amp;lt;code&amp;gt;update&amp;lt;/code&amp;gt; 处理状态转换和依赖边：&lt;br /&gt;
 &amp;lt;code&amp;gt;def update(self, task_id, status=None,&lt;br /&gt;
            add_blocked_by=None, add_blocks=None):&lt;br /&gt;
     task = self._load(task_id)&lt;br /&gt;
     if status:&lt;br /&gt;
         task[&amp;quot;status&amp;quot;] = status&lt;br /&gt;
         if status == &amp;quot;completed&amp;quot;:&lt;br /&gt;
             self._clear_dependency(task_id)&lt;br /&gt;
     self._save(task)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 4. 工具集成 ===&lt;br /&gt;
四个任务工具加入调度映射：&lt;br /&gt;
 &amp;lt;code&amp;gt;TOOL_HANDLERS = {&lt;br /&gt;
     &#039;&#039;# ...基础工具...&#039;&#039;&lt;br /&gt;
     &amp;quot;task_create&amp;quot;: lambda **kw: TASKS.create(kw[&amp;quot;subject&amp;quot;]),&lt;br /&gt;
     &amp;quot;task_update&amp;quot;: lambda **kw: TASKS.update(&lt;br /&gt;
         kw[&amp;quot;task_id&amp;quot;], kw.get(&amp;quot;status&amp;quot;)&lt;br /&gt;
     ),&lt;br /&gt;
     &amp;quot;task_list&amp;quot;:   lambda **kw: TASKS.list_all(),&lt;br /&gt;
     &amp;quot;task_get&amp;quot;:    lambda **kw: TASKS.get(kw[&amp;quot;task_id&amp;quot;]),&lt;br /&gt;
 }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 四、实际工作流程 ==&lt;br /&gt;
 &amp;lt;code&amp;gt;1. 创建任务&lt;br /&gt;
    task_create: &amp;quot;Setup project&amp;quot;&lt;br /&gt;
    task_create: &amp;quot;Write code&amp;quot;&lt;br /&gt;
    task_create: &amp;quot;Write tests&amp;quot;&lt;br /&gt;
    task_create: &amp;quot;Deploy&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 2. 设置依赖&lt;br /&gt;
    task_update: task 2, add_blocked_by=[1]&lt;br /&gt;
    task_update: task 3, add_blocked_by=[1]&lt;br /&gt;
    task_update: task 4, add_blocked_by=[2,3]&lt;br /&gt;
 &lt;br /&gt;
 3. 查看可执行任务&lt;br /&gt;
    task_list -&amp;gt; [task 1] (pending, no blockedBy)&lt;br /&gt;
 &lt;br /&gt;
 4. 开始执行&lt;br /&gt;
    task_update: task 1, status=&amp;quot;in_progress&amp;quot;&lt;br /&gt;
    # ... work ...&lt;br /&gt;
    task_update: task 1, status=&amp;quot;completed&amp;quot;&lt;br /&gt;
    # 自动解锁 task 2 和 3&lt;br /&gt;
 &lt;br /&gt;
 5. 并行执行&lt;br /&gt;
    task_update: task 2, status=&amp;quot;in_progress&amp;quot;&lt;br /&gt;
    task_update: task 3, status=&amp;quot;in_progress&amp;quot;&lt;br /&gt;
    # ... work ...&lt;br /&gt;
    task_update: task 2, status=&amp;quot;completed&amp;quot;&lt;br /&gt;
    task_update: task 3, status=&amp;quot;completed&amp;quot;&lt;br /&gt;
    # 自动解锁 task 4&lt;br /&gt;
 &lt;br /&gt;
 6. 完成&lt;br /&gt;
    task_update: task 4, status=&amp;quot;completed&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 五、试一试 ==&lt;br /&gt;
 &amp;lt;code&amp;gt;cd learn-claude-code&lt;br /&gt;
 python agents/s07_task_system.py&amp;lt;/code&amp;gt;&lt;br /&gt;
试试这些 prompt：&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;code&amp;gt;Create 3 tasks: &amp;quot;Setup project&amp;quot;, &amp;quot;Write code&amp;quot;, &amp;quot;Write tests&amp;quot;. Make them depend on each other in order.&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;List all tasks and show the dependency graph&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;Complete task 1 and then list tasks to see task 2 unblocked&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;Create a task board for refactoring: parse -&amp;gt; transform -&amp;gt; emit -&amp;gt; test, where transform and emit can run in parallel after parse&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 六、与 TodoManager 的区别 ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!特性&lt;br /&gt;
!TodoManager (s03)&lt;br /&gt;
!TaskManager (s07)&lt;br /&gt;
|-&lt;br /&gt;
|存储&lt;br /&gt;
|内存&lt;br /&gt;
|磁盘 (JSON 文件)&lt;br /&gt;
|-&lt;br /&gt;
|结构&lt;br /&gt;
|扁平清单&lt;br /&gt;
|依赖图 (DAG)&lt;br /&gt;
|-&lt;br /&gt;
|依赖&lt;br /&gt;
|无&lt;br /&gt;
|&amp;lt;code&amp;gt;blockedBy&amp;lt;/code&amp;gt; + &amp;lt;code&amp;gt;blocks&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|并行&lt;br /&gt;
|不支持&lt;br /&gt;
|支持&lt;br /&gt;
|-&lt;br /&gt;
|持久化&lt;br /&gt;
|重启丢失&lt;br /&gt;
|跨会话保存&lt;br /&gt;
|-&lt;br /&gt;
|适用场景&lt;br /&gt;
|单次会话快速清单&lt;br /&gt;
|复杂多步目标&lt;br /&gt;
|}&lt;br /&gt;
从 s07 起，任务图是多步工作的默认选择。s03 的 Todo 仍可用于单次会话内的快速清单。&lt;br /&gt;
&lt;br /&gt;
== 七、设计哲学 ==&lt;br /&gt;
&#039;&#039;&#039;持久化任务比任何一次对话都长命。&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
这是 Harness 工程的核心原则：&lt;br /&gt;
&lt;br /&gt;
* 对话会结束，但目标可能延续&lt;br /&gt;
* 上下文可能被压缩，但任务状态始终完整&lt;br /&gt;
* 多个 Agent 可以协作同一个任务图&lt;br /&gt;
* 重启后可以从断点继续&lt;br /&gt;
&lt;br /&gt;
== 八、进阶应用 ==&lt;br /&gt;
任务系统是以下高级功能的基础：&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;后台执行 (s08)&#039;&#039;&#039;：任务在后台运行，Agent 继续思考&lt;br /&gt;
* &#039;&#039;&#039;Agent 团队 (s09+)&#039;&#039;&#039;：多个 Agent 协作处理任务图&lt;br /&gt;
* &#039;&#039;&#039;自治 Agent (s11)&#039;&#039;&#039;：Agent 自己扫描看板、认领任务&lt;br /&gt;
* &#039;&#039;&#039;工作区隔离 (s12)&#039;&#039;&#039;：每个任务在自己的目录执行&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;没有任务系统，就没有真正的多 Agent 协作。&#039;&#039;&#039;&lt;br /&gt;
----&#039;&#039;Bash 就够了。真正的 Agent 是宇宙所需要的全部。&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;延伸阅读&#039;&#039;&#039;：learn-claude-code 开源项目，12 个渐进式教程，完整教授 Harness 工程。&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E5%88%86%E7%B1%BB:AI&amp;diff=116</id>
		<title>分类:AI</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E5%88%86%E7%B1%BB:AI&amp;diff=116"/>
		<updated>2026-03-23T05:02:04Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[任务系统与依赖管理：让目标超越对话(构建自己的AI Agent）]]&lt;br /&gt;
&lt;br /&gt;
[[子智能体与上下文隔离：保持思维清晰的关键]]&lt;br /&gt;
&lt;br /&gt;
[[让AI Agent不再迷失：规划的艺术]]&lt;br /&gt;
&lt;br /&gt;
[[30行代码构建你的第一个AI Agent]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[[什么是真正的 AI Agent？模型即智能体的深度解析]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Transformer架构如何驱动现代大语言模型：深入解析AI核心技术]]&lt;br /&gt;
&lt;br /&gt;
[[大语言模型评估指南]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E5%88%86%E7%B1%BB:AI&amp;diff=115</id>
		<title>分类:AI</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E5%88%86%E7%B1%BB:AI&amp;diff=115"/>
		<updated>2026-03-23T05:01:51Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;任务系统与依赖管理：让目标超越对话(构建自己的AI Agent）&lt;br /&gt;
&lt;br /&gt;
[[子智能体与上下文隔离：保持思维清晰的关键]]&lt;br /&gt;
&lt;br /&gt;
[[让AI Agent不再迷失：规划的艺术]]&lt;br /&gt;
&lt;br /&gt;
[[30行代码构建你的第一个AI Agent]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[[什么是真正的 AI Agent？模型即智能体的深度解析]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Transformer架构如何驱动现代大语言模型：深入解析AI核心技术]]&lt;br /&gt;
&lt;br /&gt;
[[大语言模型评估指南]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E5%AD%90%E6%99%BA%E8%83%BD%E4%BD%93%E4%B8%8E%E4%B8%8A%E4%B8%8B%E6%96%87%E9%9A%94%E7%A6%BB%EF%BC%9A%E4%BF%9D%E6%8C%81%E6%80%9D%E7%BB%B4%E6%B8%85%E6%99%B0%E7%9A%84%E5%85%B3%E9%94%AE&amp;diff=114</id>
		<title>子智能体与上下文隔离：保持思维清晰的关键</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E5%AD%90%E6%99%BA%E8%83%BD%E4%BD%93%E4%B8%8E%E4%B8%8A%E4%B8%8B%E6%96%87%E9%9A%94%E7%A6%BB%EF%BC%9A%E4%BF%9D%E6%8C%81%E6%80%9D%E7%BB%B4%E6%B8%85%E6%99%B0%E7%9A%84%E5%85%B3%E9%94%AE&amp;diff=114"/>
		<updated>2026-03-23T05:00:00Z</updated>

		<summary type="html">&lt;p&gt;Admin：​创建页面，内容为“&amp;lt;blockquote&amp;gt;&amp;quot;大任务拆小，每个小任务干净的上下文&amp;quot; —— 子智能体用独立 messages[]，不污染主对话。&amp;lt;/blockquote&amp;gt;随着 Agent 工作，messages 数组越来越胖。每次读文件、跑命令的输出都永久留在上下文里。  &amp;#039;&amp;#039;&amp;#039;&amp;quot;这个项目用什么测试框架？&amp;quot;&amp;#039;&amp;#039;&amp;#039; 这个问题可能需要读 5 个文件，但父智能体只需要一个词：&amp;#039;&amp;#039;&amp;#039;&amp;quot;pytest&amp;quot;&amp;#039;&amp;#039;&amp;#039;。  如何把探索的细节隔离，只把结论带回？  ==…”&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;blockquote&amp;gt;&amp;quot;大任务拆小，每个小任务干净的上下文&amp;quot; —— 子智能体用独立 messages[]，不污染主对话。&amp;lt;/blockquote&amp;gt;随着 Agent 工作，messages 数组越来越胖。每次读文件、跑命令的输出都永久留在上下文里。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;quot;这个项目用什么测试框架？&amp;quot;&#039;&#039;&#039; 这个问题可能需要读 5 个文件，但父智能体只需要一个词：&#039;&#039;&#039;&amp;quot;pytest&amp;quot;&#039;&#039;&#039;。&lt;br /&gt;
&lt;br /&gt;
如何把探索的细节隔离，只把结论带回？&lt;br /&gt;
&lt;br /&gt;
== 一、问题：上下文膨胀 ==&lt;br /&gt;
想象这个场景：&lt;br /&gt;
&lt;br /&gt;
父 Agent 正在做大型重构，上下文里已经累积了：&lt;br /&gt;
&lt;br /&gt;
* 20 个文件的读取结果&lt;br /&gt;
* 10 次测试运行输出&lt;br /&gt;
* 5 次 Git 状态检查&lt;br /&gt;
* 各种中间文件的 diff&lt;br /&gt;
&lt;br /&gt;
现在它想知道：&#039;&#039;&#039;&amp;quot; utils.py 里的 &amp;lt;code&amp;gt;parse_data&amp;lt;/code&amp;gt; 函数是做什么的？&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
为此它需要：&lt;br /&gt;
&lt;br /&gt;
# 读取 utils.py&lt;br /&gt;
# 查看相关依赖&lt;br /&gt;
# 分析函数逻辑&lt;br /&gt;
# 返回结论&lt;br /&gt;
&lt;br /&gt;
这些探索过程会进一步膨胀父 Agent 的上下文，稀释真正重要的信息。&lt;br /&gt;
&lt;br /&gt;
== 二、解决方案：子智能体 ==&lt;br /&gt;
 &amp;lt;code&amp;gt;Parent agent                     Subagent&lt;br /&gt;
 +------------------+             +------------------+&lt;br /&gt;
 | messages=[...]   |             | messages=[]      | &amp;lt;-- fresh&lt;br /&gt;
 |                  |  dispatch   |                  |&lt;br /&gt;
 | tool: task       | ----------&amp;gt; | while tool_use:  |&lt;br /&gt;
 |   prompt=&amp;quot;...&amp;quot;   |             |   call tools     |&lt;br /&gt;
 |                  |  summary    |   append results |&lt;br /&gt;
 |   result = &amp;quot;...&amp;quot; | &amp;lt;---------- | return last text |&lt;br /&gt;
 +------------------+             +------------------+&lt;br /&gt;
 &lt;br /&gt;
 Parent context stays clean. Subagent context is discarded.&amp;lt;/code&amp;gt;&lt;br /&gt;
父智能体有一个 &amp;lt;code&amp;gt;task&amp;lt;/code&amp;gt; 工具。子智能体运行自己的循环，只有最终文本返回给父智能体。&lt;br /&gt;
&lt;br /&gt;
== 三、核心机制 ==&lt;br /&gt;
&lt;br /&gt;
=== 1. 工具分离 ===&lt;br /&gt;
父智能体拥有所有基础工具 + &amp;lt;code&amp;gt;task&amp;lt;/code&amp;gt;：&lt;br /&gt;
 &amp;lt;code&amp;gt;PARENT_TOOLS = CHILD_TOOLS + [&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   {&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       &amp;quot;name&amp;quot;: &amp;quot;task&amp;quot;,&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       &amp;quot;description&amp;quot;: &amp;quot;Spawn a subagent with fresh context.&amp;quot;,&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       &amp;quot;input_schema&amp;quot;: {&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           &amp;quot;type&amp;quot;: &amp;quot;object&amp;quot;,&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           &amp;quot;properties&amp;quot;: {&amp;quot;prompt&amp;quot;: {&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;}},&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           &amp;quot;required&amp;quot;: [&amp;quot;prompt&amp;quot;],&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       }&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   },&lt;br /&gt;
 ]&amp;lt;/code&amp;gt;&lt;br /&gt;
子智能体拥有除 &amp;lt;code&amp;gt;task&amp;lt;/code&amp;gt; 外的所有基础工具（禁止递归生成）。&lt;br /&gt;
&lt;br /&gt;
=== 2. 独立循环 ===&lt;br /&gt;
子智能体以 &amp;lt;code&amp;gt;messages=[]&amp;lt;/code&amp;gt; 启动，运行自己的循环：&lt;br /&gt;
 &amp;lt;code&amp;gt;def run_subagent(prompt: str) -&amp;gt; str:&lt;br /&gt;
     sub_messages = [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: prompt}]&lt;br /&gt;
     for _ in range(30):  &#039;&#039;# 安全限制&#039;&#039;&lt;br /&gt;
         response = client.messages.create(&lt;br /&gt;
             model=MODEL, system=SUBAGENT_SYSTEM,&lt;br /&gt;
             messages=sub_messages,&lt;br /&gt;
             tools=CHILD_TOOLS, max_tokens=8000,&lt;br /&gt;
         )&lt;br /&gt;
         sub_messages.append({&lt;br /&gt;
             &amp;quot;role&amp;quot;: &amp;quot;assistant&amp;quot;,&lt;br /&gt;
             &amp;quot;content&amp;quot;: response.content&lt;br /&gt;
         })&lt;br /&gt;
         if response.stop_reason != &amp;quot;tool_use&amp;quot;:&lt;br /&gt;
             break&lt;br /&gt;
         results = []&lt;br /&gt;
         for block in response.content:&lt;br /&gt;
             if block.type == &amp;quot;tool_use&amp;quot;:&lt;br /&gt;
                 handler = TOOL_HANDLERS.get(block.name)&lt;br /&gt;
                 output = handler(**block.input)&lt;br /&gt;
                 results.append({&lt;br /&gt;
                     &amp;quot;type&amp;quot;: &amp;quot;tool_result&amp;quot;,&lt;br /&gt;
                     &amp;quot;tool_use_id&amp;quot;: block.id,&lt;br /&gt;
                     &amp;quot;content&amp;quot;: str(output)[:50000],&lt;br /&gt;
                 })&lt;br /&gt;
         sub_messages.append({&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: results})&lt;br /&gt;
     &lt;br /&gt;
     &#039;&#039;# 只返回摘要文本&#039;&#039;&lt;br /&gt;
     return &amp;quot;&amp;quot;.join(&lt;br /&gt;
         b.text for b in response.content if hasattr(b, &amp;quot;text&amp;quot;)&lt;br /&gt;
     ) or &amp;quot;(no summary)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 3. 上下文隔离 ===&lt;br /&gt;
子智能体可能跑了 30+ 次工具调用，但&#039;&#039;&#039;整个消息历史直接丢弃&#039;&#039;&#039;。父智能体收到的只是一段摘要文本，作为普通 &amp;lt;code&amp;gt;tool_result&amp;lt;/code&amp;gt; 返回。&lt;br /&gt;
&lt;br /&gt;
== 四、使用场景 ==&lt;br /&gt;
&lt;br /&gt;
=== 场景 1：信息检索 ===&lt;br /&gt;
 &amp;lt;code&amp;gt;父 Agent：这个项目用什么测试框架？&lt;br /&gt;
 ↓&lt;br /&gt;
 子 Agent（独立上下文）：&lt;br /&gt;
   - 读取 pytest.ini&lt;br /&gt;
   - 读取 setup.py&lt;br /&gt;
   - 检查测试目录结构&lt;br /&gt;
   - 分析依赖&lt;br /&gt;
 ↓&lt;br /&gt;
 返回：&amp;quot;pytest&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
父 Agent 的上下文保持干净，只有结论。&lt;br /&gt;
&lt;br /&gt;
=== 场景 2：多文件分析 ===&lt;br /&gt;
 &amp;lt;code&amp;gt;父 Agent：分析所有 Python 文件的依赖关系&lt;br /&gt;
 ↓&lt;br /&gt;
 子 Agent：&lt;br /&gt;
   - 遍历所有 .py 文件&lt;br /&gt;
   - 提取 import 语句&lt;br /&gt;
   - 构建依赖图&lt;br /&gt;
   - 生成报告&lt;br /&gt;
 ↓&lt;br /&gt;
 返回：精简的依赖关系摘要&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 场景 3：代码生成 ===&lt;br /&gt;
 &amp;lt;code&amp;gt;父 Agent：创建一个数据处理模块&lt;br /&gt;
 ↓&lt;br /&gt;
 子 Agent：&lt;br /&gt;
   - 设计 API&lt;br /&gt;
   - 实现核心函数&lt;br /&gt;
   - 添加错误处理&lt;br /&gt;
   - 编写测试&lt;br /&gt;
 ↓&lt;br /&gt;
 返回：模块完成确认 + 文件路径&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 五、试一试 ==&lt;br /&gt;
 &amp;lt;code&amp;gt;cd learn-claude-code&lt;br /&gt;
 python agents/s04_subagent.py&amp;lt;/code&amp;gt;&lt;br /&gt;
试试这些 prompt：&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;code&amp;gt;Use a subtask to find what testing framework this project uses&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;Delegate: read all .py files and summarize what each one does&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;Use a task to create a new module, then verify it from here&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
观察父 Agent 如何派发子任务，子 Agent 独立工作，最后只返回简洁的结果。&lt;br /&gt;
&lt;br /&gt;
== 六、对比无隔离 vs 有隔离 ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!场景&lt;br /&gt;
!无子智能体&lt;br /&gt;
!有子智能体&lt;br /&gt;
|-&lt;br /&gt;
|探索性任务&lt;br /&gt;
|上下文膨胀，主任务迷失&lt;br /&gt;
|探索细节隔离，主任务清晰&lt;br /&gt;
|-&lt;br /&gt;
|多文件分析&lt;br /&gt;
|所有文件内容留在上下文&lt;br /&gt;
|只保留分析结论&lt;br /&gt;
|-&lt;br /&gt;
|长对话&lt;br /&gt;
|后期上下文窗口溢出&lt;br /&gt;
|定期清理，保持高效&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 七、进阶：递归与层级 ==&lt;br /&gt;
本文的子智能体是单层的。更复杂的系统可以支持：&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;递归子智能体&#039;&#039;&#039;：子智能体也可以派发孙智能体&lt;br /&gt;
* &#039;&#039;&#039;层级架构&#039;&#039;&#039;：父-子-孙三级结构，每层有不同职责&lt;br /&gt;
* &#039;&#039;&#039;并行子智能体&#039;&#039;&#039;：同时派发多个子任务，聚合结果&lt;br /&gt;
&lt;br /&gt;
但要注意：&#039;&#039;&#039;层级越深，协调成本越高&#039;&#039;&#039;。对于多数场景，单层子智能体已经足够。&lt;br /&gt;
&lt;br /&gt;
== 八、Harness 层的职责 ==&lt;br /&gt;
&#039;&#039;&#039;守护模型的思维清晰度&#039;&#039;&#039;——这是 Harness 的核心职责之一。&lt;br /&gt;
&lt;br /&gt;
* 子智能体隔离是机制&lt;br /&gt;
* 模型决定什么时候用、用来做什么&lt;br /&gt;
* Harness 保证隔离的执行&lt;br /&gt;
&lt;br /&gt;
这种设计模式不仅适用于编程 Agent，也适用于任何需要复杂推理的场景：&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;研究 Agent&#039;&#039;&#039;：主 Agent 协调，子 Agent 深入具体领域&lt;br /&gt;
* &#039;&#039;&#039;客服 Agent&#039;&#039;&#039;：主 Agent 处理对话，子 Agent 查询知识库&lt;br /&gt;
* &#039;&#039;&#039;创意 Agent&#039;&#039;&#039;：主 Agent 把控方向，子 Agent 探索具体方案&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;好的 Harness 像一个好的工作环境——提供清晰的边界，让智能高效运转。&#039;&#039;&#039;&lt;br /&gt;
----&#039;&#039;Bash 就够了。真正的 Agent 是宇宙所需要的全部。&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E5%88%86%E7%B1%BB:AI&amp;diff=113</id>
		<title>分类:AI</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E5%88%86%E7%B1%BB:AI&amp;diff=113"/>
		<updated>2026-03-23T04:59:34Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[子智能体与上下文隔离：保持思维清晰的关键]]&lt;br /&gt;
&lt;br /&gt;
[[让AI Agent不再迷失：规划的艺术]]&lt;br /&gt;
&lt;br /&gt;
[[30行代码构建你的第一个AI Agent]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[[什么是真正的 AI Agent？模型即智能体的深度解析]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Transformer架构如何驱动现代大语言模型：深入解析AI核心技术]]&lt;br /&gt;
&lt;br /&gt;
[[大语言模型评估指南]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E8%AE%A9AI_Agent%E4%B8%8D%E5%86%8D%E8%BF%B7%E5%A4%B1%EF%BC%9A%E8%A7%84%E5%88%92%E7%9A%84%E8%89%BA%E6%9C%AF&amp;diff=112</id>
		<title>让AI Agent不再迷失：规划的艺术</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E8%AE%A9AI_Agent%E4%B8%8D%E5%86%8D%E8%BF%B7%E5%A4%B1%EF%BC%9A%E8%A7%84%E5%88%92%E7%9A%84%E8%89%BA%E6%9C%AF&amp;diff=112"/>
		<updated>2026-03-23T04:58:23Z</updated>

		<summary type="html">&lt;p&gt;Admin：​创建页面，内容为“&amp;lt;blockquote&amp;gt;&amp;quot;没有计划的 Agent 走哪算哪&amp;quot; —— 先列步骤再动手，完成率翻倍。&amp;lt;/blockquote&amp;gt;在前面文章中，我们构建了最简单的 Agent 循环。今天我们来解决一个实际问题：&amp;#039;&amp;#039;&amp;#039;多步任务中，Agent 会丢失进度&amp;#039;&amp;#039;&amp;#039;。  重复做过的事、跳步、跑偏——对话越长越严重。一个 10 步重构可能做完 1-3 步就开始即兴发挥，因为 4-10 步已经被挤出注意力了。  == 一、问题：长…”&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;blockquote&amp;gt;&amp;quot;没有计划的 Agent 走哪算哪&amp;quot; —— 先列步骤再动手，完成率翻倍。&amp;lt;/blockquote&amp;gt;在前面文章中，我们构建了最简单的 Agent 循环。今天我们来解决一个实际问题：&#039;&#039;&#039;多步任务中，Agent 会丢失进度&#039;&#039;&#039;。&lt;br /&gt;
&lt;br /&gt;
重复做过的事、跳步、跑偏——对话越长越严重。一个 10 步重构可能做完 1-3 步就开始即兴发挥，因为 4-10 步已经被挤出注意力了。&lt;br /&gt;
&lt;br /&gt;
== 一、问题：长对话中的迷失 ==&lt;br /&gt;
想象一下这个场景：&lt;br /&gt;
&lt;br /&gt;
你让 Agent 重构一个项目：&lt;br /&gt;
&lt;br /&gt;
# 添加类型注解&lt;br /&gt;
# 补充文档字符串&lt;br /&gt;
# 添加主函数保护&lt;br /&gt;
# 运行测试验证&lt;br /&gt;
# 提交更改&lt;br /&gt;
&lt;br /&gt;
Agent 开始工作，读取文件、修改代码、运行测试...但到第 4 步时，上下文已经被工具结果填满，系统提示的影响力逐渐被稀释。Agent &amp;quot;忘记&amp;quot;了还有第 5 步，或者以为第 2 步还没做，又做了一遍。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;这不是模型的错，是 Harness 的问题。&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== 二、解决方案：TodoManager ==&lt;br /&gt;
给 Agent 一个带状态的待办清单，并强制它定期更新进度。&lt;br /&gt;
 &amp;lt;code&amp;gt;+--------+      +-------+      +---------+&lt;br /&gt;
 |  User  | ---&amp;gt; |  LLM  | ---&amp;gt; | Tools   |&lt;br /&gt;
 | prompt |      |       |      | + todo  |&lt;br /&gt;
 +--------+      +---+---+      +----+----+&lt;br /&gt;
                     ^                |&lt;br /&gt;
                     |   tool_result  |&lt;br /&gt;
                     +----------------+&lt;br /&gt;
                           |&lt;br /&gt;
               +-----------+-----------+&lt;br /&gt;
               | TodoManager state     |&lt;br /&gt;
               | [ ] task A            |&lt;br /&gt;
               | [&amp;gt;] task B  &amp;lt;- doing  |&lt;br /&gt;
               | [x] task C            |&lt;br /&gt;
               +-----------------------+&lt;br /&gt;
                           |&lt;br /&gt;
               if rounds_since_todo &amp;gt;= 3:&lt;br /&gt;
                 inject &amp;lt;reminder&amp;gt; into tool_result&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 三、核心机制 ==&lt;br /&gt;
&lt;br /&gt;
=== 1. 状态管理 ===&lt;br /&gt;
同一时间只允许一个 &amp;lt;code&amp;gt;in_progress&amp;lt;/code&amp;gt;：&lt;br /&gt;
 &amp;lt;code&amp;gt;class TodoManager:&lt;br /&gt;
     def update(self, items: list) -&amp;gt; str:&lt;br /&gt;
         validated, in_progress_count = [], 0&lt;br /&gt;
         for item in items:&lt;br /&gt;
             status = item.get(&amp;quot;status&amp;quot;, &amp;quot;pending&amp;quot;)&lt;br /&gt;
             if status == &amp;quot;in_progress&amp;quot;:&lt;br /&gt;
                 in_progress_count += 1&lt;br /&gt;
             validated.append({&lt;br /&gt;
                 &amp;quot;id&amp;quot;: item[&amp;quot;id&amp;quot;],&lt;br /&gt;
                 &amp;quot;text&amp;quot;: item[&amp;quot;text&amp;quot;],&lt;br /&gt;
                 &amp;quot;status&amp;quot;: status&lt;br /&gt;
             })&lt;br /&gt;
         if in_progress_count &amp;gt; 1:&lt;br /&gt;
             raise ValueError(&amp;quot;Only one task can be in_progress&amp;quot;)&lt;br /&gt;
         self.items = validated&lt;br /&gt;
         return self.render()&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;quot;同时只能有一个 in_progress&amp;quot;&#039;&#039;&#039; 强制顺序聚焦。&lt;br /&gt;
&lt;br /&gt;
=== 2. 工具集成 ===&lt;br /&gt;
&amp;lt;code&amp;gt;todo&amp;lt;/code&amp;gt; 工具和其他工具一样加入调度映射：&lt;br /&gt;
 &amp;lt;code&amp;gt;TOOL_HANDLERS = {&lt;br /&gt;
     &#039;&#039;# ...基础工具...&#039;&#039;&lt;br /&gt;
     &amp;quot;todo&amp;quot;: lambda **kw: TODO.update(kw[&amp;quot;items&amp;quot;]),&lt;br /&gt;
 }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 3. 提醒机制（Nag Reminder） ===&lt;br /&gt;
模型连续 3 轮以上不调用 &amp;lt;code&amp;gt;todo&amp;lt;/code&amp;gt; 时，系统主动注入提醒：&lt;br /&gt;
 &amp;lt;code&amp;gt;if rounds_since_todo &amp;gt;= 3 and messages:&lt;br /&gt;
     last = messages[-1]&lt;br /&gt;
     if last[&amp;quot;role&amp;quot;] == &amp;quot;user&amp;quot; and isinstance(last.get(&amp;quot;content&amp;quot;), list):&lt;br /&gt;
         last[&amp;quot;content&amp;quot;].insert(0, {&lt;br /&gt;
             &amp;quot;type&amp;quot;: &amp;quot;text&amp;quot;,&lt;br /&gt;
             &amp;quot;text&amp;quot;: &amp;quot;&amp;lt;reminder&amp;gt;Update your todos.&amp;lt;/reminder&amp;gt;&amp;quot;,&lt;br /&gt;
         })&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;问责压力&#039;&#039;&#039;——你不更新计划，系统就追着你问。&lt;br /&gt;
&lt;br /&gt;
== 四、实际效果 ==&lt;br /&gt;
对比无规划 vs 有规划的 Agent：&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!场景&lt;br /&gt;
!无规划&lt;br /&gt;
!有规划&lt;br /&gt;
|-&lt;br /&gt;
|10步重构&lt;br /&gt;
|经常重复或遗漏步骤&lt;br /&gt;
|按顺序完成，状态清晰&lt;br /&gt;
|-&lt;br /&gt;
|多文件编辑&lt;br /&gt;
|上下文混乱&lt;br /&gt;
|每一步聚焦单一目标&lt;br /&gt;
|-&lt;br /&gt;
|长对话&lt;br /&gt;
|后期偏离主题&lt;br /&gt;
|始终围绕待办清单&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 五、完整示例 ==&lt;br /&gt;
 &amp;lt;code&amp;gt;&#039;&#039;# Agent 首先创建计划&#039;&#039;&lt;br /&gt;
 todo.update([&lt;br /&gt;
     {&amp;quot;id&amp;quot;: 1, &amp;quot;text&amp;quot;: &amp;quot;读取并分析当前代码&amp;quot;, &amp;quot;status&amp;quot;: &amp;quot;in_progress&amp;quot;},&lt;br /&gt;
     {&amp;quot;id&amp;quot;: 2, &amp;quot;text&amp;quot;: &amp;quot;添加类型注解&amp;quot;, &amp;quot;status&amp;quot;: &amp;quot;pending&amp;quot;},&lt;br /&gt;
     {&amp;quot;id&amp;quot;: 3, &amp;quot;text&amp;quot;: &amp;quot;补充文档字符串&amp;quot;, &amp;quot;status&amp;quot;: &amp;quot;pending&amp;quot;},&lt;br /&gt;
     {&amp;quot;id&amp;quot;: 4, &amp;quot;text&amp;quot;: &amp;quot;添加主函数保护&amp;quot;, &amp;quot;status&amp;quot;: &amp;quot;pending&amp;quot;},&lt;br /&gt;
     {&amp;quot;id&amp;quot;: 5, &amp;quot;text&amp;quot;: &amp;quot;运行测试验证&amp;quot;, &amp;quot;status&amp;quot;: &amp;quot;pending&amp;quot;},&lt;br /&gt;
 ])&lt;br /&gt;
 &lt;br /&gt;
 &#039;&#039;# 完成第一步后更新&#039;&#039;&lt;br /&gt;
 todo.update([&lt;br /&gt;
     {&amp;quot;id&amp;quot;: 1, &amp;quot;text&amp;quot;: &amp;quot;读取并分析当前代码&amp;quot;, &amp;quot;status&amp;quot;: &amp;quot;completed&amp;quot;},&lt;br /&gt;
     {&amp;quot;id&amp;quot;: 2, &amp;quot;text&amp;quot;: &amp;quot;添加类型注解&amp;quot;, &amp;quot;status&amp;quot;: &amp;quot;in_progress&amp;quot;},&lt;br /&gt;
     &#039;&#039;# ...其他不变&#039;&#039;&lt;br /&gt;
 ])&lt;br /&gt;
 &lt;br /&gt;
 &#039;&#039;# 如此继续，直到全部完成&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 六、试一试 ==&lt;br /&gt;
 &amp;lt;code&amp;gt;cd learn-claude-code&lt;br /&gt;
 python agents/s03_todo_write.py&amp;lt;/code&amp;gt;&lt;br /&gt;
试试这些 prompt：&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;code&amp;gt;Refactor the file hello.py: add type hints, docstrings, and a main guard&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;Create a Python package with __init__.py, utils.py, and tests/test_utils.py&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;Review all Python files and fix any style issues&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
观察 Agent 如何先创建待办清单，然后一步步执行，定期更新进度。&lt;br /&gt;
&lt;br /&gt;
== 七、设计哲学 ==&lt;br /&gt;
&#039;&#039;&#039;Harness 层应该提供规划结构，但不替模型画航线。&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Harness 提供 Todo 工具和管理器&lt;br /&gt;
* 模型自己决定任务是什么、如何排序&lt;br /&gt;
* Harness 强制&amp;quot;一次只做一件事&amp;quot;和&amp;quot;定期更新&amp;quot;&lt;br /&gt;
* 但不规定具体怎么做&lt;br /&gt;
&lt;br /&gt;
这种&#039;&#039;&#039;约束与自由&#039;&#039;&#039;的平衡是关键：&lt;br /&gt;
&lt;br /&gt;
* 太松：模型迷失在细节中&lt;br /&gt;
* 太紧：模型变成脚本执行器&lt;br /&gt;
&lt;br /&gt;
== 八、进阶思考 ==&lt;br /&gt;
TodoManager 是内存中的扁平清单，适合单次会话。对于更复杂的场景，我们需要：&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;依赖关系&#039;&#039;&#039;：任务 B 依赖任务 A&lt;br /&gt;
* &#039;&#039;&#039;并行执行&#039;&#039;&#039;：任务 C 和 D 可以同时进行&lt;br /&gt;
* &#039;&#039;&#039;持久化&#039;&#039;&#039;：跨会话保存任务状态&lt;br /&gt;
&lt;br /&gt;
这将在后续文章中介绍，进化成完整的&#039;&#039;&#039;任务系统（Task System）&#039;&#039;&#039;。&lt;br /&gt;
&lt;br /&gt;
但即使在那之前，简单的 Todo 已经能大幅提升 Agent 的可靠性。&#039;&#039;&#039;先列步骤再动手，完成率翻倍&#039;&#039;&#039;。&lt;br /&gt;
----&#039;&#039;Bash 就够了。真正的 Agent 是宇宙所需要的全部。&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E5%88%86%E7%B1%BB:AI&amp;diff=111</id>
		<title>分类:AI</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E5%88%86%E7%B1%BB:AI&amp;diff=111"/>
		<updated>2026-03-23T04:57:58Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[让AI Agent不再迷失：规划的艺术]]&lt;br /&gt;
&lt;br /&gt;
[[30行代码构建你的第一个AI Agent]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[[什么是真正的 AI Agent？模型即智能体的深度解析]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Transformer架构如何驱动现代大语言模型：深入解析AI核心技术]]&lt;br /&gt;
&lt;br /&gt;
[[大语言模型评估指南]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=30%E8%A1%8C%E4%BB%A3%E7%A0%81%E6%9E%84%E5%BB%BA%E4%BD%A0%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AAAI_Agent&amp;diff=110</id>
		<title>30行代码构建你的第一个AI Agent</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=30%E8%A1%8C%E4%BB%A3%E7%A0%81%E6%9E%84%E5%BB%BA%E4%BD%A0%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AAAI_Agent&amp;diff=110"/>
		<updated>2026-03-23T04:56:27Z</updated>

		<summary type="html">&lt;p&gt;Admin：​创建页面，内容为“&amp;lt;blockquote&amp;gt;&amp;quot;One loop &amp;amp; Bash is all you need&amp;quot; —— 一个工具 + 一个循环 = 一个智能体。&amp;lt;/blockquote&amp;gt;在前一篇文章中，我们理解了 Agent 的本质：&amp;#039;&amp;#039;&amp;#039;Agent 是模型，Harness 是框架&amp;#039;&amp;#039;&amp;#039;。今天，让我们动手构建最简单的 Agent Harness。  只需要 30 行 Python 代码，你就能拥有一个真正能与现实世界交互的 AI Agent。  == 一、问题：模型被困在象牙塔里 == 大语言模型能推理代码，但…”&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;blockquote&amp;gt;&amp;quot;One loop &amp;amp; Bash is all you need&amp;quot; —— 一个工具 + 一个循环 = 一个智能体。&amp;lt;/blockquote&amp;gt;在前一篇文章中，我们理解了 Agent 的本质：&#039;&#039;&#039;Agent 是模型，Harness 是框架&#039;&#039;&#039;。今天，让我们动手构建最简单的 Agent Harness。&lt;br /&gt;
&lt;br /&gt;
只需要 30 行 Python 代码，你就能拥有一个真正能与现实世界交互的 AI Agent。&lt;br /&gt;
&lt;br /&gt;
== 一、问题：模型被困在象牙塔里 ==&lt;br /&gt;
大语言模型能推理代码，但碰不到真实世界——不能读文件、跑测试、看报错。&lt;br /&gt;
&lt;br /&gt;
没有循环，每次工具调用你都得手动把结果粘回去。&#039;&#039;&#039;你自己就是那个循环。&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
这既不优雅，也不可扩展。我们需要让模型能够自主地与工具交互，形成一个闭环。&lt;br /&gt;
&lt;br /&gt;
== 二、解决方案：Agent 循环 ==&lt;br /&gt;
核心思想很简单：&lt;br /&gt;
 &amp;lt;code&amp;gt;+--------+      +-------+      +---------+&lt;br /&gt;
 |  User  | ---&amp;gt; |  LLM  | ---&amp;gt; |  Tool   |&lt;br /&gt;
 | prompt |      |       |      | execute |&lt;br /&gt;
 +--------+      +---+---+      +----+----+&lt;br /&gt;
                     ^                |&lt;br /&gt;
                     |   tool_result  |&lt;br /&gt;
                     +----------------+&lt;br /&gt;
               (loop until stop_reason != &amp;quot;tool_use&amp;quot;)&amp;lt;/code&amp;gt;&lt;br /&gt;
一个退出条件控制整个流程。循环持续运行，直到模型不再调用工具。&lt;br /&gt;
&lt;br /&gt;
== 三、工作原理 ==&lt;br /&gt;
&lt;br /&gt;
=== 1. 用户 prompt 作为第一条消息 ===&lt;br /&gt;
 &amp;lt;code&amp;gt;messages.append({&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: query})&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2. 将消息和工具定义一起发给 LLM ===&lt;br /&gt;
 &amp;lt;code&amp;gt;response = client.messages.create(&lt;br /&gt;
     model=MODEL, system=SYSTEM, messages=messages,&lt;br /&gt;
     tools=TOOLS, max_tokens=8000,&lt;br /&gt;
 )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 3. 追加助手响应，检查 stop_reason ===&lt;br /&gt;
 &amp;lt;code&amp;gt;messages.append({&amp;quot;role&amp;quot;: &amp;quot;assistant&amp;quot;, &amp;quot;content&amp;quot;: response.content})&lt;br /&gt;
 if response.stop_reason != &amp;quot;tool_use&amp;quot;:&lt;br /&gt;
     return&amp;lt;/code&amp;gt;&lt;br /&gt;
如果模型没有调用工具，任务完成。&lt;br /&gt;
&lt;br /&gt;
=== 4. 执行每个工具调用，收集结果，作为 user 消息追加，回到第 2 步 ===&lt;br /&gt;
 &amp;lt;code&amp;gt;results = []&lt;br /&gt;
 for block in response.content:&lt;br /&gt;
     if block.type == &amp;quot;tool_use&amp;quot;:&lt;br /&gt;
         output = run_bash(block.input[&amp;quot;command&amp;quot;])&lt;br /&gt;
         results.append({&lt;br /&gt;
             &amp;quot;type&amp;quot;: &amp;quot;tool_result&amp;quot;,&lt;br /&gt;
             &amp;quot;tool_use_id&amp;quot;: block.id,&lt;br /&gt;
             &amp;quot;content&amp;quot;: output,&lt;br /&gt;
         })&lt;br /&gt;
 messages.append({&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: results})&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 四、完整代码 ==&lt;br /&gt;
组装为一个完整函数：&lt;br /&gt;
 &amp;lt;code&amp;gt;def agent_loop(query):&lt;br /&gt;
     messages = [{&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: query}]&lt;br /&gt;
     while True:&lt;br /&gt;
         response = client.messages.create(&lt;br /&gt;
             model=MODEL, system=SYSTEM, messages=messages,&lt;br /&gt;
             tools=TOOLS, max_tokens=8000,&lt;br /&gt;
         )&lt;br /&gt;
         messages.append({&amp;quot;role&amp;quot;: &amp;quot;assistant&amp;quot;, &amp;quot;content&amp;quot;: response.content})&lt;br /&gt;
 &lt;br /&gt;
         if response.stop_reason != &amp;quot;tool_use&amp;quot;:&lt;br /&gt;
             return&lt;br /&gt;
 &lt;br /&gt;
         results = []&lt;br /&gt;
         for block in response.content:&lt;br /&gt;
             if block.type == &amp;quot;tool_use&amp;quot;:&lt;br /&gt;
                 output = run_bash(block.input[&amp;quot;command&amp;quot;])&lt;br /&gt;
                 results.append({&lt;br /&gt;
                     &amp;quot;type&amp;quot;: &amp;quot;tool_result&amp;quot;,&lt;br /&gt;
                     &amp;quot;tool_use_id&amp;quot;: block.id,&lt;br /&gt;
                     &amp;quot;content&amp;quot;: output,&lt;br /&gt;
                 })&lt;br /&gt;
         messages.append({&amp;quot;role&amp;quot;: &amp;quot;user&amp;quot;, &amp;quot;content&amp;quot;: results})&amp;lt;/code&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;不到 30 行，这就是整个智能体。&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
后面所有复杂的机制（规划、子 Agent、任务系统、团队协作）都是在这个循环上叠加的——&#039;&#039;&#039;循环本身始终不变&#039;&#039;&#039;。&lt;br /&gt;
&lt;br /&gt;
== 五、核心组件 ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!组件&lt;br /&gt;
!作用&lt;br /&gt;
|-&lt;br /&gt;
|Agent loop&lt;br /&gt;
|&amp;lt;code&amp;gt;while True&amp;lt;/code&amp;gt; + &amp;lt;code&amp;gt;stop_reason&amp;lt;/code&amp;gt; 检查&lt;br /&gt;
|-&lt;br /&gt;
|Tools&lt;br /&gt;
|从 &amp;lt;code&amp;gt;bash&amp;lt;/code&amp;gt; 开始，单一工具足矣&lt;br /&gt;
|-&lt;br /&gt;
|Messages&lt;br /&gt;
|累积式消息列表，记录完整对话历史&lt;br /&gt;
|-&lt;br /&gt;
|Control flow&lt;br /&gt;
|&amp;lt;code&amp;gt;stop_reason != &amp;quot;tool_use&amp;quot;&amp;lt;/code&amp;gt; 决定退出&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== 六、试一试 ==&lt;br /&gt;
 &amp;lt;code&amp;gt;git clone &amp;lt;nowiki&amp;gt;https://github.com/shareAI-lab/learn-claude-code&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 cd learn-claude-code&lt;br /&gt;
 python agents/s01_agent_loop.py&amp;lt;/code&amp;gt;&lt;br /&gt;
试试这些 prompt：&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;code&amp;gt;Create a file called hello.py that prints &amp;quot;Hello, World!&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;List all Python files in this directory&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;What is the current git branch?&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;Create a directory called test_output and write 3 files in it&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
你会看到 Agent 自主地调用 Bash 工具，执行命令，读取结果，然后决定下一步做什么，直到任务完成。&lt;br /&gt;
&lt;br /&gt;
== 七、关键洞察 ==&lt;br /&gt;
&#039;&#039;&#039;模型决定什么时候调用工具，什么时候停止。&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
代码只是执行模型要求做的事。这个循环属于 Agent，机制属于 Harness。&lt;br /&gt;
&lt;br /&gt;
这个看似简单的循环是所有现代 AI Agent（包括 Claude Code、Devin、OpenCode）的基础。无论 Agent 多复杂，核心都是这个循环：&lt;br /&gt;
 &amp;lt;code&amp;gt;messages[] --&amp;gt; LLM --&amp;gt; response&lt;br /&gt;
                |&lt;br /&gt;
       stop_reason == &amp;quot;tool_use&amp;quot;?&lt;br /&gt;
          /         \&lt;br /&gt;
       yes            no&lt;br /&gt;
        |              |&lt;br /&gt;
   执行工具       返回文本&lt;br /&gt;
   追加结果&lt;br /&gt;
   循环回去 ----------&amp;gt; messages[]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 八、下一步 ==&lt;br /&gt;
这只是一个开始。在这个基础上，我们将逐步添加：&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;工具扩展&#039;&#039;&#039;：不只 Bash，还有文件读写、代码编辑、搜索&lt;br /&gt;
* &#039;&#039;&#039;规划能力&#039;&#039;&#039;：让 Agent 列步骤再执行&lt;br /&gt;
* &#039;&#039;&#039;子 Agent&#039;&#039;&#039;：大任务拆小，上下文隔离&lt;br /&gt;
* &#039;&#039;&#039;知识加载&#039;&#039;&#039;：按需注入领域知识&lt;br /&gt;
* &#039;&#039;&#039;上下文压缩&#039;&#039;&#039;：处理长对话&lt;br /&gt;
* &#039;&#039;&#039;任务系统&#039;&#039;&#039;：持久化的目标管理&lt;br /&gt;
* &#039;&#039;&#039;团队协作&#039;&#039;&#039;：多 Agent 并行工作&lt;br /&gt;
&lt;br /&gt;
但在那之前，&#039;&#039;&#039;先掌握这个循环&#039;&#039;&#039;。理解它，你就理解了 Agent 的本质。&lt;br /&gt;
----&#039;&#039;Bash 就够了。真正的 Agent 是宇宙所需要的全部。&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;延伸阅读&#039;&#039;&#039;：learn-claude-code 开源项目，12 个渐进式教程，从简单循环到隔离式自主执行。&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E5%88%86%E7%B1%BB:AI&amp;diff=109</id>
		<title>分类:AI</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E5%88%86%E7%B1%BB:AI&amp;diff=109"/>
		<updated>2026-03-23T04:55:49Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[30行代码构建你的第一个AI Agent]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[[什么是真正的 AI Agent？模型即智能体的深度解析]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Transformer架构如何驱动现代大语言模型：深入解析AI核心技术]]&lt;br /&gt;
&lt;br /&gt;
[[大语言模型评估指南]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E9%A6%96%E9%A1%B5&amp;diff=108</id>
		<title>首页</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E9%A6%96%E9%A1%B5&amp;diff=108"/>
		<updated>2026-03-23T04:54:30Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[分类:Kivy]]&lt;br /&gt;
[[分类:C/C++]]&lt;br /&gt;
[[分类:Linux操作系统]]&lt;br /&gt;
[[分类:算法]]&lt;br /&gt;
&lt;br /&gt;
[[什么是真正的 AI Agent？模型即智能体的深度解析]]&lt;br /&gt;
&lt;br /&gt;
[[软件工程师必知的软件架构模式]]&lt;br /&gt;
&lt;br /&gt;
[http://www.anwsome.com//index.php/%E6%9E%84%E5%BB%BA%E5%AE%89%E5%85%A8%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E7%9A%84%E9%A1%B6%E7%BA%A7%E8%BA%AB%E4%BB%BD%E9%AA%8C%E8%AF%81%E6%8A%80%E6%9C%AF 构建安全应用程序的顶级身份验证技术]&lt;br /&gt;
&lt;br /&gt;
[[Transformer架构如何驱动现代大语言模型：深入解析AI核心技术]]&lt;br /&gt;
&lt;br /&gt;
[[大语言模型评估指南]]&lt;br /&gt;
&lt;br /&gt;
[[谷歌的张量处理器（TPU）是如何工作的？]]&lt;br /&gt;
&lt;br /&gt;
[[动手做系列：使用Apache2服务器，通过Let&#039;s Encrypt申请网站免费https证书]]&lt;br /&gt;
&lt;br /&gt;
[[编写一个TCP/IP栈3-TCP基础与握手|动手做系列：编写一个TCP/IP栈3-TCP基础与握手]]&lt;br /&gt;
&lt;br /&gt;
[[编写一个TCP/IP栈2-IPv4和ICMPv4|动手做系列：编写一个TCP/IP栈2-IPv4和ICMPv4]]&lt;br /&gt;
&lt;br /&gt;
[[编写一个TCP/IP栈1-以太网和ARP|动手做系列：编写一个TCP/IP栈1-以太网和ARP]]&lt;br /&gt;
&lt;br /&gt;
[[构建自己的区块链|动手做系列：构建自己的区块链]]&lt;br /&gt;
&lt;br /&gt;
[[500行代码构建自己的数据库 DBDB|动手做系列：500行代码构建自己的数据库 DBDB: Dog Bed Database]]&lt;br /&gt;
[[分类:Web3]]&lt;br /&gt;
[[分类:动手做系列]]&lt;br /&gt;
[[分类:资讯]]&lt;br /&gt;
[[分类:AI]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E4%BB%80%E4%B9%88%E6%98%AF%E7%9C%9F%E6%AD%A3%E7%9A%84_AI_Agent%EF%BC%9F%E6%A8%A1%E5%9E%8B%E5%8D%B3%E6%99%BA%E8%83%BD%E4%BD%93%E7%9A%84%E6%B7%B1%E5%BA%A6%E8%A7%A3%E6%9E%90&amp;diff=107</id>
		<title>什么是真正的 AI Agent？模型即智能体的深度解析</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E4%BB%80%E4%B9%88%E6%98%AF%E7%9C%9F%E6%AD%A3%E7%9A%84_AI_Agent%EF%BC%9F%E6%A8%A1%E5%9E%8B%E5%8D%B3%E6%99%BA%E8%83%BD%E4%BD%93%E7%9A%84%E6%B7%B1%E5%BA%A6%E8%A7%A3%E6%9E%90&amp;diff=107"/>
		<updated>2026-03-23T04:53:38Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;blockquote&amp;gt;&amp;quot;Agent 是模型，不是框架，不是提示链，不是拖拽式工作流。&amp;quot;&amp;lt;/blockquote&amp;gt;过去一年，AI 领域最热的词莫过于 &amp;quot;Agent&amp;quot;。但当你听到这个词时，你想到的是什么？&lt;br /&gt;
&lt;br /&gt;
是 LangChain 的流程图？是扣子（Coze）的节点编排？还是各种 &amp;quot;AI Agent 开发平台&amp;quot; 的可视化界面？&lt;br /&gt;
&lt;br /&gt;
如果你的答案是以上任何一种，那么这篇文章将彻底改变你的认知。&lt;br /&gt;
&lt;br /&gt;
== 一、Agent 是什么？ ==&lt;br /&gt;
让我们回到源头。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Agent（智能体）是一个神经网络&#039;&#039;&#039;——Transformer、RNN，或者任何通过梯度更新训练出来的函数。它通过数十亿次在动作序列数据上的训练，学会了感知环境、推理目标并采取行动。&lt;br /&gt;
&lt;br /&gt;
Agent 这个词在 AI 领域一直就是这个意思：&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;人类是 Agent&#039;&#039;&#039; —— 生物神经网络，经过数百万年进化训练，通过感官感知世界，通过大脑推理，通过身体行动&lt;br /&gt;
* &#039;&#039;&#039;DQN 是 Agent&#039;&#039;&#039; —— 2013 年 DeepMind 的单个神经网络，仅凭原始像素和游戏分数，学会了玩 7 款雅达利游戏，超越所有先前算法&lt;br /&gt;
* &#039;&#039;&#039;OpenAI Five 是 Agent&#039;&#039;&#039; —— 五个神经网络，通过 10 个月内 45,000 年的自我对战，击败 Dota 2 世界冠军&lt;br /&gt;
* &#039;&#039;&#039;AlphaStar 是 Agent&#039;&#039;&#039; —— 在《星际争霸 II》中达到宗师段位，超越 90,000 名玩家中的前 0.15%&lt;br /&gt;
&lt;br /&gt;
这些里程碑共享同一个真理：&#039;&#039;&#039;&amp;quot;Agent&amp;quot; 从来不是周围的代码，Agent 永远是模型本身。&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== 二、Agent 不是什么？ ==&lt;br /&gt;
不幸的是，&amp;quot;Agent&amp;quot; 这个词已经被一整个提示工程产业劫持了。&lt;br /&gt;
&lt;br /&gt;
拖拽式工作流构建器。低代码 &amp;quot;AI Agent&amp;quot; 平台。提示链编排库。它们共享同一个幻觉：认为用 if-else 分支、节点图和硬编码路由逻辑把 LLM API 调用串联起来，就是在 &amp;quot;构建 Agent&amp;quot;。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;这不是在构建 Agent，这是在搭建鲁布·戈德堡机械&#039;&#039;&#039;——一种过度工程化、脆弱的程序化规则管道，把一个 LLM 塞进作为华丽文本补全节点的位置。&lt;br /&gt;
&lt;br /&gt;
提示工程 &amp;quot;Agent&amp;quot; 是不会训练模型的人的幻想。他们试图通过堆砌程序化逻辑来暴力破解智能——庞大的规则树、节点图、提示链瀑布——祈祷足够多的胶水代码能以某种方式涌现出自主行为。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;这是死路一条&#039;&#039;&#039;：脆弱、不可扩展、从根本上无法泛化。这是 GOFAI（经典人工智能）的现代复活——几十年前该领域就已经抛弃的符号规则系统，现在只是喷了一层 LLM 的漆。&lt;br /&gt;
&lt;br /&gt;
== 三、心智转变：从&amp;quot;开发 Agent&amp;quot;到开发 Harness ==&lt;br /&gt;
当有人说&amp;quot;我在开发 Agent&amp;quot;时，他们只可能指两件事之一：&lt;br /&gt;
&lt;br /&gt;
=== 1. 训练模型 ===&lt;br /&gt;
通过强化学习、微调、RLHF 或其他基于梯度的方法调整权重。收集任务过程数据——真实领域中感知、推理和动作的实际序列——并用它来塑造模型行为。&lt;br /&gt;
&lt;br /&gt;
这是 DeepMind、OpenAI、腾讯 AI Lab 和 Anthropic 在做的事。这是最严格意义上的 Agent 开发。&lt;br /&gt;
&lt;br /&gt;
=== 2. 构建 Harness（控制框架） ===&lt;br /&gt;
编写代码，给模型一个在特定领域运作的环境。这是大多数人（包括你）在做的事，也是本文的重点。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Harness = 工具 + 知识 + 观察 + 动作接口 + 权限&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;工具&#039;&#039;&#039;：文件 I/O、Shell、网络、数据库、浏览器&lt;br /&gt;
* &#039;&#039;&#039;知识&#039;&#039;&#039;：产品文档、领域参考资料、API 规范、风格指南&lt;br /&gt;
* &#039;&#039;&#039;观察&#039;&#039;&#039;：Git diff、错误日志、浏览器状态、传感器数据&lt;br /&gt;
* &#039;&#039;&#039;动作&#039;&#039;&#039;：CLI 命令、API 调用、UI 交互&lt;br /&gt;
* &#039;&#039;&#039;权限&#039;&#039;&#039;：沙箱、审批工作流、信任边界&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;模型做决定，Harness 执行。&#039;&#039;&#039; &#039;&#039;&#039;模型推理，Harness 提供上下文。&#039;&#039;&#039; &#039;&#039;&#039;模型是司机，Harness 是车。&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== 四、Harness 工程师的真正工作 ==&lt;br /&gt;
如果你正在阅读这篇文章，你很可能是 Harness 工程师——而这是一件很有力量的事。&lt;br /&gt;
&lt;br /&gt;
你的真正工作是：&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1. 实现工具&#039;&#039;&#039; 给 Agent 手。文件读写、Shell 执行、API 调用、浏览器控制、数据库查询。每个工具都是 Agent 可以在环境中采取的动作。设计它们时要原子化、可组合、描述清晰。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;2. 整理知识&#039;&#039;&#039; 给 Agent 领域专长。产品文档、架构决策记录、风格指南、监管要求。按需加载（而不是预加载）。Agent 应该知道有什么可用，并在需要时拉取。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;3. 管理上下文&#039;&#039;&#039; 给 Agent 干净的记忆。子 Agent 隔离防止噪音泄漏。上下文压缩防止历史压垮。任务系统让目标超越单次对话。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;4. 控制权限&#039;&#039;&#039; 给 Agent 边界。沙箱文件访问。破坏性操作需要审批。强制执行 Agent 和外部系统之间的信任边界。这是安全工程与 Harness 工程的交汇点。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;5. 收集任务过程数据&#039;&#039;&#039; Agent 在你的 Harness 中执行的每个动作序列都是训练信号。真实部署中的感知-推理-动作痕迹是微调下一代 Agent 模型的原材料。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;你不是在编写智能，你是在构建智能栖息的世界。&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
这个世界的质量——Agent 能多么清晰地感知、能多么精确地行动、可用知识有多丰富——直接决定了智能能多么有效地表达自己。&lt;br /&gt;
&lt;br /&gt;
构建伟大的 Harness，Agent 会完成剩下的事。&lt;br /&gt;
&lt;br /&gt;
== 五、Claude Code：Harness 工程的杰作 ==&lt;br /&gt;
为什么我们要专门研究 Claude Code？&lt;br /&gt;
&lt;br /&gt;
因为 Claude Code 是我们见过的最优雅、最完全实现的 Agent Harness。不是因为某个巧妙的技巧，而是因为它&#039;&#039;&#039;不做什么&#039;&#039;&#039;：它不试图成为 Agent，它不强加刚性工作流，它不用精心设计的决策树来质疑模型。&lt;br /&gt;
&lt;br /&gt;
它给模型提供工具、知识、上下文管理和权限边界——然后让开。&lt;br /&gt;
&lt;br /&gt;
看看 Claude Code 的本质：&lt;br /&gt;
 &amp;lt;code&amp;gt;Claude Code = 一个 Agent 循环&lt;br /&gt;
     + 工具（Bash、Read、Write、Edit、Glob、Grep、Browser...）&lt;br /&gt;
     + 按需技能加载&lt;br /&gt;
     + 上下文压缩&lt;br /&gt;
     + 子 Agent 生成&lt;br /&gt;
     + 带依赖图的任务系统&lt;br /&gt;
     + 带异步邮箱的团队协调&lt;br /&gt;
     + 用于并行执行的工作区隔离&lt;br /&gt;
     + 权限治理&amp;lt;/code&amp;gt;&lt;br /&gt;
就这些。这就是整个架构。&lt;br /&gt;
&lt;br /&gt;
每个组件都是 Harness 机制——为 Agent 栖息而构建的世界的一部分。Agent 本身？是 Claude。一个由 Anthropic 训练、基于人类全部推理和代码的模型。Harness 并没有让 Claude 变聪明，Claude 本来就聪明。Harness 给了 Claude 手、眼睛和工作空间。&lt;br /&gt;
&lt;br /&gt;
这就是 Claude Code 是理想教学对象的原因：它展示了当你信任模型并专注于 Harness 工程时会发生什么。&lt;br /&gt;
&lt;br /&gt;
== 六、愿景：让宇宙中充满真正的 Agent ==&lt;br /&gt;
这不仅仅是关于编程 Agent。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;每个领域，只要人类执行复杂、多步骤、需要判断的工作，Agent 就可以在正确的 Harness 下运作。&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
本文中的模式是通用的：&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;房地产管理 Agent&#039;&#039;&#039; = 模型 + 房产传感器 + 维护工具 + 租户沟通&lt;br /&gt;
* &#039;&#039;&#039;农业 Agent&#039;&#039;&#039; = 模型 + 土壤/天气数据 + 灌溉控制 + 作物知识&lt;br /&gt;
* &#039;&#039;&#039;酒店运营 Agent&#039;&#039;&#039; = 模型 + 预订系统 + 客户渠道 + 设施 API&lt;br /&gt;
* &#039;&#039;&#039;医学研究 Agent&#039;&#039;&#039; = 模型 + 文献搜索 + 实验室仪器 + 协议文档&lt;br /&gt;
* &#039;&#039;&#039;制造业 Agent&#039;&#039;&#039; = 模型 + 生产线传感器 + 质量控制 + 物流&lt;br /&gt;
* &#039;&#039;&#039;教育 Agent&#039;&#039;&#039; = 模型 + 课程知识 + 学生进度 + 评估工具&lt;br /&gt;
&lt;br /&gt;
循环永远相同。工具改变。知识改变。权限改变。&#039;&#039;&#039;Agent——模型——泛化。&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
每个阅读本文的 Harness 工程师都在学习远远超越软件工程的模式。你在学习构建智能化、自动化未来的基础设施。每个在真实领域部署的精心设计的 Harness，都是 Agent 可以感知、推理和行动的另一个地方。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;先从车间开始。然后是农场、医院、工厂。然后是城市。然后是整个星球。&#039;&#039;&#039;&lt;br /&gt;
----&#039;&#039;Bash 就够了。真正的 Agent 是宇宙所需要的全部。&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E4%BB%80%E4%B9%88%E6%98%AF%E7%9C%9F%E6%AD%A3%E7%9A%84_AI_Agent%EF%BC%9F%E6%A8%A1%E5%9E%8B%E5%8D%B3%E6%99%BA%E8%83%BD%E4%BD%93%E7%9A%84%E6%B7%B1%E5%BA%A6%E8%A7%A3%E6%9E%90&amp;diff=106</id>
		<title>什么是真正的 AI Agent？模型即智能体的深度解析</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E4%BB%80%E4%B9%88%E6%98%AF%E7%9C%9F%E6%AD%A3%E7%9A%84_AI_Agent%EF%BC%9F%E6%A8%A1%E5%9E%8B%E5%8D%B3%E6%99%BA%E8%83%BD%E4%BD%93%E7%9A%84%E6%B7%B1%E5%BA%A6%E8%A7%A3%E6%9E%90&amp;diff=106"/>
		<updated>2026-03-23T04:52:01Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;gt; &amp;quot;Agent 是模型，不是框架，不是提示链，不是拖拽式工作流。&amp;quot;&lt;br /&gt;
&lt;br /&gt;
过去一年，AI 领域最热的词莫过于 &amp;quot;Agent&amp;quot;。但当你听到这个词时，你想到的是什么？&lt;br /&gt;
&lt;br /&gt;
是 LangChain 的流程图？是扣子（Coze）的节点编排？还是各种 &amp;quot;AI Agent 开发平台&amp;quot; 的可视化界面？&lt;br /&gt;
&lt;br /&gt;
如果你的答案是以上任何一种，那么这篇文章将彻底改变你的认知。&lt;br /&gt;
&lt;br /&gt;
## 一、Agent 是什么？&lt;br /&gt;
&lt;br /&gt;
让我们回到源头。&lt;br /&gt;
&lt;br /&gt;
**Agent（智能体）是一个神经网络**——Transformer、RNN，或者任何通过梯度更新训练出来的函数。它通过数十亿次在动作序列数据上的训练，学会了感知环境、推理目标并采取行动。&lt;br /&gt;
&lt;br /&gt;
Agent 这个词在 AI 领域一直就是这个意思：&lt;br /&gt;
&lt;br /&gt;
- **人类是 Agent** —— 生物神经网络，经过数百万年进化训练，通过感官感知世界，通过大脑推理，通过身体行动&lt;br /&gt;
&lt;br /&gt;
- **DQN 是 Agent** —— 2013 年 DeepMind 的单个神经网络，仅凭原始像素和游戏分数，学会了玩 7 款雅达利游戏，超越所有先前算法&lt;br /&gt;
&lt;br /&gt;
- **OpenAI Five 是 Agent** —— 五个神经网络，通过 10 个月内 45,000 年的自我对战，击败 Dota 2 世界冠军&lt;br /&gt;
&lt;br /&gt;
- **AlphaStar 是 Agent** —— 在《星际争霸 II》中达到宗师段位，超越 90,000 名玩家中的前 0.15%&lt;br /&gt;
&lt;br /&gt;
这些里程碑共享同一个真理：**&amp;quot;Agent&amp;quot; 从来不是周围的代码，Agent 永远是模型本身。**&lt;br /&gt;
&lt;br /&gt;
## 二、Agent 不是什么？&lt;br /&gt;
&lt;br /&gt;
不幸的是，&amp;quot;Agent&amp;quot; 这个词已经被一整个提示工程产业劫持了。&lt;br /&gt;
&lt;br /&gt;
拖拽式工作流构建器。低代码 &amp;quot;AI Agent&amp;quot; 平台。提示链编排库。它们共享同一个幻觉：认为用 if-else 分支、节点图和硬编码路由逻辑把 LLM API 调用串联起来，就是在 &amp;quot;构建 Agent&amp;quot;。&lt;br /&gt;
&lt;br /&gt;
**这不是在构建 Agent，这是在搭建鲁布·戈德堡机械**——一种过度工程化、脆弱的程序化规则管道，把一个 LLM 塞进作为华丽文本补全节点的位置。&lt;br /&gt;
&lt;br /&gt;
提示工程 &amp;quot;Agent&amp;quot; 是不会训练模型的人的幻想。他们试图通过堆砌程序化逻辑来暴力破解智能——庞大的规则树、节点图、提示链瀑布——祈祷足够多的胶水代码能以某种方式涌现出自主行为。&lt;br /&gt;
&lt;br /&gt;
**这是死路一条**：脆弱、不可扩展、从根本上无法泛化。这是 GOFAI（经典人工智能）的现代复活——几十年前该领域就已经抛弃的符号规则系统，现在只是喷了一层 LLM 的漆。&lt;br /&gt;
&lt;br /&gt;
## 三、心智转变：从&amp;quot;开发 Agent&amp;quot;到开发 Harness&lt;br /&gt;
&lt;br /&gt;
当有人说&amp;quot;我在开发 Agent&amp;quot;时，他们只可能指两件事之一：&lt;br /&gt;
&lt;br /&gt;
### 1. 训练模型&lt;br /&gt;
&lt;br /&gt;
通过强化学习、微调、RLHF 或其他基于梯度的方法调整权重。收集任务过程数据——真实领域中感知、推理和动作的实际序列——并用它来塑造模型行为。&lt;br /&gt;
&lt;br /&gt;
这是 DeepMind、OpenAI、腾讯 AI Lab 和 Anthropic 在做的事。这是最严格意义上的 Agent 开发。&lt;br /&gt;
&lt;br /&gt;
### 2. 构建 Harness（控制框架）&lt;br /&gt;
&lt;br /&gt;
编写代码，给模型一个在特定领域运作的环境。这是大多数人（包括你）在做的事，也是本文的重点。&lt;br /&gt;
&lt;br /&gt;
**Harness = 工具 + 知识 + 观察 + 动作接口 + 权限**&lt;br /&gt;
&lt;br /&gt;
- **工具**：文件 I/O、Shell、网络、数据库、浏览器&lt;br /&gt;
&lt;br /&gt;
- **知识**：产品文档、领域参考资料、API 规范、风格指南&lt;br /&gt;
&lt;br /&gt;
- **观察**：Git diff、错误日志、浏览器状态、传感器数据&lt;br /&gt;
&lt;br /&gt;
- **动作**：CLI 命令、API 调用、UI 交互&lt;br /&gt;
&lt;br /&gt;
- **权限**：沙箱、审批工作流、信任边界&lt;br /&gt;
&lt;br /&gt;
**模型做决定，Harness 执行。**&lt;br /&gt;
&lt;br /&gt;
**模型推理，Harness 提供上下文。**&lt;br /&gt;
&lt;br /&gt;
**模型是司机，Harness 是车。**&lt;br /&gt;
&lt;br /&gt;
## 四、Harness 工程师的真正工作&lt;br /&gt;
&lt;br /&gt;
如果你正在阅读这篇文章，你很可能是 Harness 工程师——而这是一件很有力量的事。&lt;br /&gt;
&lt;br /&gt;
你的真正工作是：&lt;br /&gt;
&lt;br /&gt;
**1. 实现工具**&lt;br /&gt;
&lt;br /&gt;
给 Agent 手。文件读写、Shell 执行、API 调用、浏览器控制、数据库查询。每个工具都是 Agent 可以在环境中采取的动作。设计它们时要原子化、可组合、描述清晰。&lt;br /&gt;
&lt;br /&gt;
**2. 整理知识**&lt;br /&gt;
&lt;br /&gt;
给 Agent 领域专长。产品文档、架构决策记录、风格指南、监管要求。按需加载（而不是预加载）。Agent 应该知道有什么可用，并在需要时拉取。&lt;br /&gt;
&lt;br /&gt;
**3. 管理上下文**&lt;br /&gt;
&lt;br /&gt;
给 Agent 干净的记忆。子 Agent 隔离防止噪音泄漏。上下文压缩防止历史压垮。任务系统让目标超越单次对话。&lt;br /&gt;
&lt;br /&gt;
**4. 控制权限**&lt;br /&gt;
&lt;br /&gt;
给 Agent 边界。沙箱文件访问。破坏性操作需要审批。强制执行 Agent 和外部系统之间的信任边界。这是安全工程与 Harness 工程的交汇点。&lt;br /&gt;
&lt;br /&gt;
**5. 收集任务过程数据**&lt;br /&gt;
&lt;br /&gt;
Agent 在你的 Harness 中执行的每个动作序列都是训练信号。真实部署中的感知-推理-动作痕迹是微调下一代 Agent 模型的原材料。&lt;br /&gt;
&lt;br /&gt;
**你不是在编写智能，你是在构建智能栖息的世界。**&lt;br /&gt;
&lt;br /&gt;
这个世界的质量——Agent 能多么清晰地感知、能多么精确地行动、可用知识有多丰富——直接决定了智能能多么有效地表达自己。&lt;br /&gt;
&lt;br /&gt;
构建伟大的 Harness，Agent 会完成剩下的事。&lt;br /&gt;
&lt;br /&gt;
## 五、Claude Code：Harness 工程的杰作&lt;br /&gt;
&lt;br /&gt;
为什么我们要专门研究 Claude Code？&lt;br /&gt;
&lt;br /&gt;
因为 Claude Code 是我们见过的最优雅、最完全实现的 Agent Harness。不是因为某个巧妙的技巧，而是因为它**不做什么**：它不试图成为 Agent，它不强加刚性工作流，它不用精心设计的决策树来质疑模型。&lt;br /&gt;
&lt;br /&gt;
它给模型提供工具、知识、上下文管理和权限边界——然后让开。&lt;br /&gt;
&lt;br /&gt;
看看 Claude Code 的本质：&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Claude Code = 一个 Agent 循环&lt;br /&gt;
&lt;br /&gt;
    + 工具（Bash、Read、Write、Edit、Glob、Grep、Browser...）&lt;br /&gt;
&lt;br /&gt;
    + 按需技能加载&lt;br /&gt;
&lt;br /&gt;
    + 上下文压缩&lt;br /&gt;
&lt;br /&gt;
    + 子 Agent 生成&lt;br /&gt;
&lt;br /&gt;
    + 带依赖图的任务系统&lt;br /&gt;
&lt;br /&gt;
    + 带异步邮箱的团队协调&lt;br /&gt;
&lt;br /&gt;
    + 用于并行执行的工作区隔离&lt;br /&gt;
&lt;br /&gt;
    + 权限治理&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
就这些。这就是整个架构。&lt;br /&gt;
&lt;br /&gt;
每个组件都是 Harness 机制——为 Agent 栖息而构建的世界的一部分。Agent 本身？是 Claude。一个由 Anthropic 训练、基于人类全部推理和代码的模型。Harness 并没有让 Claude 变聪明，Claude 本来就聪明。Harness 给了 Claude 手、眼睛和工作空间。&lt;br /&gt;
&lt;br /&gt;
这就是 Claude Code 是理想教学对象的原因：它展示了当你信任模型并专注于 Harness 工程时会发生什么。&lt;br /&gt;
&lt;br /&gt;
## 六、愿景：让宇宙中充满真正的 Agent&lt;br /&gt;
&lt;br /&gt;
这不仅仅是关于编程 Agent。&lt;br /&gt;
&lt;br /&gt;
**每个领域，只要人类执行复杂、多步骤、需要判断的工作，Agent 就可以在正确的 Harness 下运作。**&lt;br /&gt;
&lt;br /&gt;
本文中的模式是通用的：&lt;br /&gt;
&lt;br /&gt;
- **房地产管理 Agent** = 模型 + 房产传感器 + 维护工具 + 租户沟通&lt;br /&gt;
&lt;br /&gt;
- **农业 Agent** = 模型 + 土壤/天气数据 + 灌溉控制 + 作物知识&lt;br /&gt;
&lt;br /&gt;
- **酒店运营 Agent** = 模型 + 预订系统 + 客户渠道 + 设施 API&lt;br /&gt;
&lt;br /&gt;
- **医学研究 Agent** = 模型 + 文献搜索 + 实验室仪器 + 协议文档&lt;br /&gt;
&lt;br /&gt;
- **制造业 Agent** = 模型 + 生产线传感器 + 质量控制 + 物流&lt;br /&gt;
&lt;br /&gt;
- **教育 Agent** = 模型 + 课程知识 + 学生进度 + 评估工具&lt;br /&gt;
&lt;br /&gt;
循环永远相同。工具改变。知识改变。权限改变。**Agent——模型——泛化。**&lt;br /&gt;
&lt;br /&gt;
每个阅读本文的 Harness 工程师都在学习远远超越软件工程的模式。你在学习构建智能化、自动化未来的基础设施。每个在真实领域部署的精心设计的 Harness，都是 Agent 可以感知、推理和行动的另一个地方。&lt;br /&gt;
&lt;br /&gt;
**先从车间开始。然后是农场、医院、工厂。然后是城市。然后是整个星球。**&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
*Bash 就够了。真正的 Agent 是宇宙所需要的全部。*&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E4%BB%80%E4%B9%88%E6%98%AF%E7%9C%9F%E6%AD%A3%E7%9A%84_AI_Agent%EF%BC%9F%E6%A8%A1%E5%9E%8B%E5%8D%B3%E6%99%BA%E8%83%BD%E4%BD%93%E7%9A%84%E6%B7%B1%E5%BA%A6%E8%A7%A3%E6%9E%90&amp;diff=105</id>
		<title>什么是真正的 AI Agent？模型即智能体的深度解析</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E4%BB%80%E4%B9%88%E6%98%AF%E7%9C%9F%E6%AD%A3%E7%9A%84_AI_Agent%EF%BC%9F%E6%A8%A1%E5%9E%8B%E5%8D%B3%E6%99%BA%E8%83%BD%E4%BD%93%E7%9A%84%E6%B7%B1%E5%BA%A6%E8%A7%A3%E6%9E%90&amp;diff=105"/>
		<updated>2026-03-23T04:51:44Z</updated>

		<summary type="html">&lt;p&gt;Admin：​清空全部内容&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E4%BB%80%E4%B9%88%E6%98%AF%E7%9C%9F%E6%AD%A3%E7%9A%84_AI_Agent%EF%BC%9F%E6%A8%A1%E5%9E%8B%E5%8D%B3%E6%99%BA%E8%83%BD%E4%BD%93%E7%9A%84%E6%B7%B1%E5%BA%A6%E8%A7%A3%E6%9E%90&amp;diff=104</id>
		<title>什么是真正的 AI Agent？模型即智能体的深度解析</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E4%BB%80%E4%B9%88%E6%98%AF%E7%9C%9F%E6%AD%A3%E7%9A%84_AI_Agent%EF%BC%9F%E6%A8%A1%E5%9E%8B%E5%8D%B3%E6%99%BA%E8%83%BD%E4%BD%93%E7%9A%84%E6%B7%B1%E5%BA%A6%E8%A7%A3%E6%9E%90&amp;diff=104"/>
		<updated>2026-03-23T04:50:49Z</updated>

		<summary type="html">&lt;p&gt;Admin：​创建页面，内容为“&amp;gt; &amp;quot;Agent 是模型，不是框架，不是提示链，不是拖拽式工作流。&amp;quot;  过去一年，AI 领域最热的词莫过于 &amp;quot;Agent&amp;quot;。但当你听到这个词时，你想到的是什么？  是 LangChain 的流程图？是扣子（Coze）的节点编排？还是各种 &amp;quot;AI Agent 开发平台&amp;quot; 的可视化界面？  如果你的答案是以上任何一种，那么这篇文章将彻底改变你的认知。  &amp;#039;&amp;#039;&amp;#039;## 一、Agent 是什么？&amp;#039;&amp;#039;&amp;#039;  让我们回到…”&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;gt; &amp;quot;Agent 是模型，不是框架，不是提示链，不是拖拽式工作流。&amp;quot;&lt;br /&gt;
&lt;br /&gt;
过去一年，AI 领域最热的词莫过于 &amp;quot;Agent&amp;quot;。但当你听到这个词时，你想到的是什么？&lt;br /&gt;
&lt;br /&gt;
是 LangChain 的流程图？是扣子（Coze）的节点编排？还是各种 &amp;quot;AI Agent 开发平台&amp;quot; 的可视化界面？&lt;br /&gt;
&lt;br /&gt;
如果你的答案是以上任何一种，那么这篇文章将彻底改变你的认知。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;## 一、Agent 是什么？&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
让我们回到源头。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;**Agent（智能体）是一个神经网络**&#039;&#039;&#039;——Transformer、RNN，或者任何通过梯度更新训练出来的函数。它通过数十亿次在动作序列数据上的训练，学会了感知环境、推理目标并采取行动。&lt;br /&gt;
&lt;br /&gt;
Agent 这个词在 AI 领域一直就是这个意思：&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;**人类是 Agent**&#039;&#039;&#039; —— 生物神经网络，经过数百万年进化训练，通过感官感知世界，通过大脑推理，通过身体行动&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;**DQN 是 Agent**&#039;&#039;&#039; —— 2013 年 DeepMind 的单个神经网络，仅凭原始像素和游戏分数，学会了玩 7 款雅达利游戏，超越所有先前算法&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;**OpenAI Five 是 Agent**&#039;&#039;&#039; —— 五个神经网络，通过 10 个月内 45,000 年的自我对战，击败 Dota 2 世界冠军&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;**AlphaStar 是 Agent**&#039;&#039;&#039; —— 在《星际争霸 II》中达到宗师段位，超越 90,000 名玩家中的前 0.15%&lt;br /&gt;
&lt;br /&gt;
这些里程碑共享同一个真理：&#039;&#039;&#039;**&amp;quot;Agent&amp;quot; 从来不是周围的代码，Agent 永远是模型本身。**&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;## 二、Agent 不是什么？&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
不幸的是，&amp;quot;Agent&amp;quot; 这个词已经被一整个提示工程产业劫持了。&lt;br /&gt;
&lt;br /&gt;
拖拽式工作流构建器。低代码 &amp;quot;AI Agent&amp;quot; 平台。提示链编排库。它们共享同一个幻觉：认为用 if-else 分支、节点图和硬编码路由逻辑把 LLM API 调用串联起来，就是在 &amp;quot;构建 Agent&amp;quot;。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;**这不是在构建 Agent，这是在搭建鲁布·戈德堡机械**&#039;&#039;&#039;——一种过度工程化、脆弱的程序化规则管道，把一个 LLM 塞进作为华丽文本补全节点的位置。&lt;br /&gt;
&lt;br /&gt;
提示工程 &amp;quot;Agent&amp;quot; 是不会训练模型的人的幻想。他们试图通过堆砌程序化逻辑来暴力破解智能——庞大的规则树、节点图、提示链瀑布——祈祷足够多的胶水代码能以某种方式涌现出自主行为。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;**这是死路一条**&#039;&#039;&#039;：脆弱、不可扩展、从根本上无法泛化。这是 GOFAI（经典人工智能）的现代复活——几十年前该领域就已经抛弃的符号规则系统，现在只是喷了一层 LLM 的漆。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;## 三、心智转变：从&amp;quot;开发 Agent&amp;quot;到开发 Harness&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
当有人说&amp;quot;我在开发 Agent&amp;quot;时，他们只可能指两件事之一：&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;### 1. 训练模型&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
通过强化学习、微调、RLHF 或其他基于梯度的方法调整权重。收集任务过程数据——真实领域中感知、推理和动作的实际序列——并用它来塑造模型行为。&lt;br /&gt;
&lt;br /&gt;
这是 DeepMind、OpenAI、腾讯 AI Lab 和 Anthropic 在做的事。这是最严格意义上的 Agent 开发。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;### 2. 构建 Harness（控制框架）&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
编写代码，给模型一个在特定领域运作的环境。这是大多数人（包括你）在做的事，也是本文的重点。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;**Harness = 工具 + 知识 + 观察 + 动作接口 + 权限**&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;**工具**&#039;&#039;&#039;：文件 I/O、Shell、网络、数据库、浏览器&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;**知识**&#039;&#039;&#039;：产品文档、领域参考资料、API 规范、风格指南&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;**观察**&#039;&#039;&#039;：Git diff、错误日志、浏览器状态、传感器数据&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;**动作**&#039;&#039;&#039;：CLI 命令、API 调用、UI 交互&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;**权限**&#039;&#039;&#039;：沙箱、审批工作流、信任边界&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;**模型做决定，Harness 执行。**&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;**模型推理，Harness 提供上下文。**&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;**模型是司机，Harness 是车。**&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;## 四、Harness 工程师的真正工作&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
如果你正在阅读这篇文章，你很可能是 Harness 工程师——而这是一件很有力量的事。&lt;br /&gt;
&lt;br /&gt;
你的真正工作是：&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;**1. 实现工具**&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
给 Agent 手。文件读写、Shell 执行、API 调用、浏览器控制、数据库查询。每个工具都是 Agent 可以在环境中采取的动作。设计它们时要原子化、可组合、描述清晰。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;**2. 整理知识**&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
给 Agent 领域专长。产品文档、架构决策记录、风格指南、监管要求。按需加载（而不是预加载）。Agent 应该知道有什么可用，并在需要时拉取。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;**3. 管理上下文**&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
给 Agent 干净的记忆。子 Agent 隔离防止噪音泄漏。上下文压缩防止历史压垮。任务系统让目标超越单次对话。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;**4. 控制权限**&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
给 Agent 边界。沙箱文件访问。破坏性操作需要审批。强制执行 Agent 和外部系统之间的信任边界。这是安全工程与 Harness 工程的交汇点。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;**5. 收集任务过程数据**&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Agent 在你的 Harness 中执行的每个动作序列都是训练信号。真实部署中的感知-推理-动作痕迹是微调下一代 Agent 模型的原材料。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;**你不是在编写智能，你是在构建智能栖息的世界。**&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
这个世界的质量——Agent 能多么清晰地感知、能多么精确地行动、可用知识有多丰富——直接决定了智能能多么有效地表达自己。&lt;br /&gt;
&lt;br /&gt;
构建伟大的 Harness，Agent 会完成剩下的事。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;## 五、Claude Code：Harness 工程的杰作&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
为什么我们要专门研究 Claude Code？&lt;br /&gt;
&lt;br /&gt;
因为 Claude Code 是我们见过的最优雅、最完全实现的 Agent Harness。不是因为某个巧妙的技巧，而是因为它&#039;&#039;&#039;**不做什么**&#039;&#039;&#039;：它不试图成为 Agent，它不强加刚性工作流，它不用精心设计的决策树来质疑模型。&lt;br /&gt;
&lt;br /&gt;
它给模型提供工具、知识、上下文管理和权限边界——然后让开。&lt;br /&gt;
&lt;br /&gt;
看看 Claude Code 的本质：&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Claude Code = 一个 Agent 循环&lt;br /&gt;
&lt;br /&gt;
    + 工具（Bash、Read、Write、Edit、Glob、Grep、Browser...）&lt;br /&gt;
&lt;br /&gt;
    + 按需技能加载&lt;br /&gt;
&lt;br /&gt;
    + 上下文压缩&lt;br /&gt;
&lt;br /&gt;
    + 子 Agent 生成&lt;br /&gt;
&lt;br /&gt;
    + 带依赖图的任务系统&lt;br /&gt;
&lt;br /&gt;
    + 带异步邮箱的团队协调&lt;br /&gt;
&lt;br /&gt;
    + 用于并行执行的工作区隔离&lt;br /&gt;
&lt;br /&gt;
    + 权限治理&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
就这些。这就是整个架构。&lt;br /&gt;
&lt;br /&gt;
每个组件都是 Harness 机制——为 Agent 栖息而构建的世界的一部分。Agent 本身？是 Claude。一个由 Anthropic 训练、基于人类全部推理和代码的模型。Harness 并没有让 Claude 变聪明，Claude 本来就聪明。Harness 给了 Claude 手、眼睛和工作空间。&lt;br /&gt;
&lt;br /&gt;
这就是 Claude Code 是理想教学对象的原因：它展示了当你信任模型并专注于 Harness 工程时会发生什么。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;## 六、愿景：让宇宙中充满真正的 Agent&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
这不仅仅是关于编程 Agent。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;**每个领域，只要人类执行复杂、多步骤、需要判断的工作，Agent 就可以在正确的 Harness 下运作。**&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
本文中的模式是通用的：&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;**房地产管理 Agent**&#039;&#039;&#039; = 模型 + 房产传感器 + 维护工具 + 租户沟通&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;**农业 Agent**&#039;&#039;&#039; = 模型 + 土壤/天气数据 + 灌溉控制 + 作物知识&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;**酒店运营 Agent**&#039;&#039;&#039; = 模型 + 预订系统 + 客户渠道 + 设施 API&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;**医学研究 Agent**&#039;&#039;&#039; = 模型 + 文献搜索 + 实验室仪器 + 协议文档&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;**制造业 Agent**&#039;&#039;&#039; = 模型 + 生产线传感器 + 质量控制 + 物流&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;**教育 Agent**&#039;&#039;&#039; = 模型 + 课程知识 + 学生进度 + 评估工具&lt;br /&gt;
&lt;br /&gt;
循环永远相同。工具改变。知识改变。权限改变。&#039;&#039;&#039;**Agent——模型——泛化。**&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
每个阅读本文的 Harness 工程师都在学习远远超越软件工程的模式。你在学习构建智能化、自动化未来的基础设施。每个在真实领域部署的精心设计的 Harness，都是 Agent 可以感知、推理和行动的另一个地方。&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;**先从车间开始。然后是农场、医院、工厂。然后是城市。然后是整个星球。**&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;*Bash 就够了。真正的 Agent 是宇宙所需要的全部。*&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E5%88%86%E7%B1%BB:AI&amp;diff=103</id>
		<title>分类:AI</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E5%88%86%E7%B1%BB:AI&amp;diff=103"/>
		<updated>2026-03-23T04:50:01Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;[[什么是真正的 AI Agent？模型即智能体的深度解析]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Transformer架构如何驱动现代大语言模型：深入解析AI核心技术]]&lt;br /&gt;
&lt;br /&gt;
[[大语言模型评估指南]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B%E5%B8%88%E5%BF%85%E7%9F%A5%E7%9A%84%E8%BD%AF%E4%BB%B6%E6%9E%B6%E6%9E%84%E6%A8%A1%E5%BC%8F&amp;diff=102</id>
		<title>软件工程师必知的软件架构模式</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B%E5%B8%88%E5%BF%85%E7%9F%A5%E7%9A%84%E8%BD%AF%E4%BB%B6%E6%9E%B6%E6%9E%84%E6%A8%A1%E5%BC%8F&amp;diff=102"/>
		<updated>2026-02-13T14:06:34Z</updated>

		<summary type="html">&lt;p&gt;Admin：​创建空白页面&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E9%A6%96%E9%A1%B5&amp;diff=101</id>
		<title>首页</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E9%A6%96%E9%A1%B5&amp;diff=101"/>
		<updated>2026-02-13T14:03:59Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[分类:Kivy]]&lt;br /&gt;
[[分类:C/C++]]&lt;br /&gt;
[[分类:Linux操作系统]]&lt;br /&gt;
[[分类:算法]]&lt;br /&gt;
&lt;br /&gt;
[[软件工程师必知的软件架构模式]]&lt;br /&gt;
&lt;br /&gt;
[http://www.anwsome.com//index.php/%E6%9E%84%E5%BB%BA%E5%AE%89%E5%85%A8%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E7%9A%84%E9%A1%B6%E7%BA%A7%E8%BA%AB%E4%BB%BD%E9%AA%8C%E8%AF%81%E6%8A%80%E6%9C%AF 构建安全应用程序的顶级身份验证技术]&lt;br /&gt;
&lt;br /&gt;
[[Transformer架构如何驱动现代大语言模型：深入解析AI核心技术]]&lt;br /&gt;
&lt;br /&gt;
[[大语言模型评估指南]]&lt;br /&gt;
&lt;br /&gt;
[[谷歌的张量处理器（TPU）是如何工作的？]]&lt;br /&gt;
&lt;br /&gt;
[[动手做系列：使用Apache2服务器，通过Let&#039;s Encrypt申请网站免费https证书]]&lt;br /&gt;
&lt;br /&gt;
[[编写一个TCP/IP栈3-TCP基础与握手|动手做系列：编写一个TCP/IP栈3-TCP基础与握手]]&lt;br /&gt;
&lt;br /&gt;
[[编写一个TCP/IP栈2-IPv4和ICMPv4|动手做系列：编写一个TCP/IP栈2-IPv4和ICMPv4]]&lt;br /&gt;
&lt;br /&gt;
[[编写一个TCP/IP栈1-以太网和ARP|动手做系列：编写一个TCP/IP栈1-以太网和ARP]]&lt;br /&gt;
&lt;br /&gt;
[[构建自己的区块链|动手做系列：构建自己的区块链]]&lt;br /&gt;
&lt;br /&gt;
[[500行代码构建自己的数据库 DBDB|动手做系列：500行代码构建自己的数据库 DBDB: Dog Bed Database]]&lt;br /&gt;
[[分类:Web3]]&lt;br /&gt;
[[分类:动手做系列]]&lt;br /&gt;
[[分类:资讯]]&lt;br /&gt;
[[分类:AI]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E9%A6%96%E9%A1%B5&amp;diff=100</id>
		<title>首页</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E9%A6%96%E9%A1%B5&amp;diff=100"/>
		<updated>2026-02-07T14:32:37Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[分类:Kivy]]&lt;br /&gt;
[[分类:C/C++]]&lt;br /&gt;
[[分类:Linux操作系统]]&lt;br /&gt;
[[分类:算法]]&lt;br /&gt;
&lt;br /&gt;
[http://www.anwsome.com//index.php/%E6%9E%84%E5%BB%BA%E5%AE%89%E5%85%A8%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E7%9A%84%E9%A1%B6%E7%BA%A7%E8%BA%AB%E4%BB%BD%E9%AA%8C%E8%AF%81%E6%8A%80%E6%9C%AF 构建安全应用程序的顶级身份验证技术]&lt;br /&gt;
&lt;br /&gt;
[[Transformer架构如何驱动现代大语言模型：深入解析AI核心技术]]&lt;br /&gt;
&lt;br /&gt;
[[大语言模型评估指南]]&lt;br /&gt;
&lt;br /&gt;
[[谷歌的张量处理器（TPU）是如何工作的？]]&lt;br /&gt;
&lt;br /&gt;
[[动手做系列：使用Apache2服务器，通过Let&#039;s Encrypt申请网站免费https证书]]&lt;br /&gt;
&lt;br /&gt;
[[编写一个TCP/IP栈3-TCP基础与握手|动手做系列：编写一个TCP/IP栈3-TCP基础与握手]]&lt;br /&gt;
&lt;br /&gt;
[[编写一个TCP/IP栈2-IPv4和ICMPv4|动手做系列：编写一个TCP/IP栈2-IPv4和ICMPv4]]&lt;br /&gt;
&lt;br /&gt;
[[编写一个TCP/IP栈1-以太网和ARP|动手做系列：编写一个TCP/IP栈1-以太网和ARP]]&lt;br /&gt;
&lt;br /&gt;
[[构建自己的区块链|动手做系列：构建自己的区块链]]&lt;br /&gt;
&lt;br /&gt;
[[500行代码构建自己的数据库 DBDB|动手做系列：500行代码构建自己的数据库 DBDB: Dog Bed Database]]&lt;br /&gt;
[[分类:Web3]]&lt;br /&gt;
[[分类:动手做系列]]&lt;br /&gt;
[[分类:资讯]]&lt;br /&gt;
[[分类:AI]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E6%9E%84%E5%BB%BA%E5%AE%89%E5%85%A8%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E7%9A%84%E9%A1%B6%E7%BA%A7%E8%BA%AB%E4%BB%BD%E9%AA%8C%E8%AF%81%E6%8A%80%E6%9C%AF&amp;diff=99</id>
		<title>构建安全应用程序的顶级身份验证技术</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E6%9E%84%E5%BB%BA%E5%AE%89%E5%85%A8%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E7%9A%84%E9%A1%B6%E7%BA%A7%E8%BA%AB%E4%BB%BD%E9%AA%8C%E8%AF%81%E6%8A%80%E6%9C%AF&amp;diff=99"/>
		<updated>2026-02-07T14:31:20Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
身份验证是确保应用程序及其处理的敏感数据安全的第一道防线。无论是个人银行应用程序、企业平台还是电子商务网站，都需要有效的身份验证机制来验证用户身份并保障其对资源的访问权限。&lt;br /&gt;
&lt;br /&gt;
如果没有适当的身份验证，应用程序容易受到未经授权的访问、数据泄露和恶意攻击，可能导致重大的经济损失、声誉损害和隐私侵犯。&lt;br /&gt;
&lt;br /&gt;
除了安全性之外，身份验证在用户体验中也扮演着至关重要的角色。通过识别用户，应用程序可以提供个性化服务、记住用户偏好，并启用跨平台的单点登录 (SSO) 等功能。&lt;br /&gt;
&lt;br /&gt;
随着威胁的不断演变，实现安全高效的身份验证比以往任何时候都更具挑战性。开发人员必须在相互冲突的优先事项之间寻求平衡，例如安全性（确保抵御不同类型的攻击，例如会话劫持、令牌窃取和重放攻击）、可扩展性（在不影响性能的前提下支持数百万用户）和用户体验（在应用强大的安全措施的同时保持易用性）。&lt;br /&gt;
&lt;br /&gt;
为了应对这些挑战，开发人员依赖于各种身份验证技术。在本文中，我们将探讨应用程序中使用的多种身份验证技术，并了解它们的优缺点。 &lt;br /&gt;
[[文件:Goujiananquanyinngyongchengxu.png|居中|缩略图|720x720像素]]&lt;br /&gt;
&lt;br /&gt;
== 身份验证基础知识 ==&lt;br /&gt;
身份验证是指验证尝试访问应用程序的用户、设备或系统的身份的过程。简单来说，就是应用程序如何确保访问者或系统的身份与其声称的身份相符。它通常涉及验证用户名、密码、生物识别数据或令牌等凭证。&lt;br /&gt;
&lt;br /&gt;
例如，当我们使用密码登录网站时，应用程序会将我们输入的密码与存储的凭据进行比较，以确认我们的身份。在基于 API 的系统中，应用程序可能会使用令牌来验证调用服务是否有权与后端交互。 &lt;br /&gt;
&lt;br /&gt;
=== 身份验证与授权 ===&lt;br /&gt;
身份验证和授权是密切相关但又不同的过程。&lt;br /&gt;
&lt;br /&gt;
身份验证回答“你是谁？”这个问题，侧重于验证身份。授权则回答“你被允许做什么？”这个问题，通过确定授予已验证用户的权限或访问级别来实现。&lt;br /&gt;
&lt;br /&gt;
例如，身份验证用于确认我们是否是电子商务平台的注册用户。授权则决定我们是否可以查看订单历史记录或以管理员身份管理库存。换句话说，身份验证用于确认身份，而授权则基于该身份实施访问控制。 &lt;br /&gt;
&lt;br /&gt;
== 使用 Cookie 和会话进行身份验证 ==&lt;br /&gt;
接下来，我们将探讨 cookie 和会话在身份验证方面的应用： &lt;br /&gt;
&lt;br /&gt;
=== Cookie ===&lt;br /&gt;
Cookie 是由 Web 服务器存储在客户端浏览器上的小型数据文件。它们在原本无状态的 HTTP 通信中扮演着关键角色，使 Web 应用程序能够在多个请求中记住信息，从而维护通信状态。&lt;br /&gt;
&lt;br /&gt;
Cookie 允许 Web 服务器存储请求之间持久存在的数据，使其可用于各种用途，例如会话管理（使用会话 ID 跟踪已登录用户）、个性化（存储用户偏好或设置）以及分析和跟踪（记录用户行为以进行分析或定向广告）。&lt;br /&gt;
&lt;br /&gt;
在身份验证中，Cookie 通常用于存储会话令牌或标识符，以验证用户的身份。 &lt;br /&gt;
&lt;br /&gt;
=== Cookie 在身份验证中的工作原理 ===&lt;br /&gt;
该过程通常包含两个部分。用户登录时，用户提供用户名和密码等凭据。服务器验证这些凭据并生成会话 ID 或令牌。此会话 ID 会发送到浏览器并存储在 cookie 中。&lt;br /&gt;
&lt;br /&gt;
对于后续请求，浏览器会自动将 cookie 添加到每个 HTTP 请求的 Cookie 标头中。服务器会从 cookie 中读取会话 ID，对其进行验证，并识别用户。&lt;br /&gt;
&lt;br /&gt;
请看下图： &lt;br /&gt;
[[文件:Shefenzhouqun2.png|居中|缩略图|568x568像素]]&lt;br /&gt;
&lt;br /&gt;
=== Cookie 属性 ===&lt;br /&gt;
Cookie 具有多种属性，用于控制其行为和安全性： &lt;br /&gt;
&lt;br /&gt;
* HttpOnly 属性可阻止 JavaScript 访问 cookie，从而缓解跨站脚本 (XSS) 攻击。Secure 属性可确保 cookie 仅通过 HTTPS 连接发送，从而防止中间人攻击。 &lt;br /&gt;
* SameSite 属性有助于防止跨站请求伪造 (CSRF) 攻击。它有三个值：Strict（cookie 永远不会在跨站请求中发送）、Lax（cookie 仅在顶级导航中发送）和 None（cookie 随所有请求发送，但需要 Secure 属性）。 &lt;br /&gt;
* Domain 属性指定哪些主机可以接收 cookie。例如，设置 Domain= example.com允许将 cookie 发送到example.com及其所有子域。Path 属性将 cookie 限制在特定的 URL 路径中。 &lt;br /&gt;
* 对于过期时间，我们可以使用 Max-Age（指定有效期，单位为秒）或 Expires（设置绝对过期日期）。如果两者都未设置，则该 cookie 将成为会话 cookie，并在浏览器关闭时被删除。 &lt;br /&gt;
&lt;br /&gt;
=== 第一方 Cookie 与第三方 Cookie ===&lt;br /&gt;
第一方 Cookie 由我们当前访问的域名设置。&lt;br /&gt;
&lt;br /&gt;
当我们访问 example[dot]com 时，如果该网站设置了 cookie，那就是第一方 cookie。这些 cookie 用于网站的基本功能，例如身份验证和用户偏好设置。&lt;br /&gt;
&lt;br /&gt;
第三方 Cookie 由与我们正在访问的网站不同的域名设置。例如，如果我们访问 example[dot]com，而该网站加载了来自ads.com的广告，则ads.com域名可以设置一个 Cookie。这些 Cookie 通常用于跨多个网站跟踪用户行为，以达到广告投放的目的。&lt;br /&gt;
&lt;br /&gt;
出于隐私考虑，现代浏览器对第三方 Cookie 的限制日益增多。有些浏览器甚至默认阻止第三方 Cookie。为了确保身份验证在所有浏览器上都能可靠运行，我们应该始终使用第一方 Cookie。 &lt;br /&gt;
&lt;br /&gt;
=== 使用 Cookie 的挑战 ===&lt;br /&gt;
Cookie面临多项安全挑战： &lt;br /&gt;
&lt;br /&gt;
* 如果恶意脚本通过跨站脚本攻击 (XSS) 注入到网站中，它就可以访问包含敏感数据的 cookie。设置 HttpOnly 标志可以防止这种情况发生。 &lt;br /&gt;
* 如果 Cookie 通过未加密的 HTTP 协议传输，则可能在中间人攻击中被拦截。“安全”标志可确保 Cookie 仅通过 HTTPS 协议发送。 &lt;br /&gt;
* 请求中自动发送的 Cookie 可能被 CSRF 攻击利用来执行未经授权的操作。实施 CSRF 令牌并使用 SameSite 属性有助于缓解这种情况。 &lt;br /&gt;
* 浏览器对 Cookie 的大小有限制，通常每个 Cookie 为 4KB，并且每个域的 Cookie 数量也有限制。过多的 Cookie 会导致性能问题或请求被拒绝。&lt;br /&gt;
&lt;br /&gt;
以下是一些安全处理 Cookie 的最佳实践： &lt;br /&gt;
&lt;br /&gt;
* 我们应该始终设置 HttpOnly 标志来阻止 JavaScript 访问并降低 XSS 风险。Secure 标志可确保 cookie 仅通过 HTTPS 发送。 &lt;br /&gt;
* 使用 SameSite 属性（SameSite=Strict 或 SameSite=Lax）可以限制跨站点请求并降低 CSRF 风险。 &lt;br /&gt;
* 我们应该对敏感数据使用较短的过期时间，避免在 cookie 中存储密码或信用卡号等敏感信息，而只存储令牌或标识符。 &lt;br /&gt;
&lt;br /&gt;
== 会话 ==&lt;br /&gt;
会话是一种服务器端机制，用于在用户与应用程序进行交互期间存储和管理用户身份验证数据。与将数据存储在客户端的 Cookie 不同，会话将数据安全地保存在服务器端，客户端仅持有一个引用，通常是会话 ID。&lt;br /&gt;
&lt;br /&gt;
使用会话进行身份验证的流程包括以下几个步骤： &lt;br /&gt;
&lt;br /&gt;
* 用户登录时，用户提交登录凭据。服务器验证凭据并为用户创建一个会话，通常用唯一的会话 ID 表示。 &lt;br /&gt;
* 为了生成会话 ID，服务器会创建一个与存储在服务器上的用户会话数据关联的随机唯一标识符。此会话 ID 会通过 cookie 或其他传输机制发送给客户端。 &lt;br /&gt;
* 服务器将会话数据（例如用户 ID、角色和偏好）存储在内存、数据库或其他存储系统中。 &lt;br /&gt;
* 会话 ID 充当检索此数据的密钥。对于每个后续请求，客户端都会发送会话 ID，通常通过 cookie 发送。服务器验证会话 ID，检索关联数据，并使用它来处理请求。&lt;br /&gt;
&lt;br /&gt;
请看下图： &lt;br /&gt;
[[文件:Howitworkforauth.png|居中|缩略图|649x649像素]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
会话可以设置生存时间 (TTL)，在一段时间不活动或达到最大持续时间后自动过期。当用户注销或出于安全考虑撤销会话时，会话数据将从服务器中删除，会话 ID 也将失效。 &lt;br /&gt;
&lt;br /&gt;
=== 会话与 Cookie 之间的关系 ===&lt;br /&gt;
Cookie 和会话通常协同工作。&lt;br /&gt;
&lt;br /&gt;
Cookie 存储着客户端的会话 ID。每次请求时，浏览器都会将 cookie 发送到服务器，以便服务器识别用户的会话。&lt;br /&gt;
&lt;br /&gt;
以下是一个简单的代码示例，展示了如何将会话 ID 设置到 cookie 中： &lt;br /&gt;
  &amp;lt;code&amp;gt;app.post (&#039;/login&#039;, (req, res) =&amp;gt; { const sessionId = createSession(req.body.username); res.cookie(&#039;session_id&#039;, sessionId, { httpOnly: true, secure: true, maxAge: 3600000 }); res.send(&#039;Login successful&#039;); });&amp;lt;/code&amp;gt;&lt;br /&gt;
对于传入的请求，服务器可以读取存储在 cookie 中的会话 ID： &lt;br /&gt;
  &amp;lt;code&amp;gt;app.get(&#039;/profile&#039;, (req, res) =&amp;gt; { const sessionId = req.cookies[&#039;session_id&#039;]; if (isValidSession(sessionId)) { res.send(&#039;Profile page&#039;); } else { res.status(401).send(&#039;Unauthorized&#039;); } });&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== 会话存储选项 ===&lt;br /&gt;
选择合适的会话存储机制对于性能和可扩展性至关重要。 &lt;br /&gt;
&lt;br /&gt;
* 内存存储将会话保存在服务器的 RAM 中，从而提供最快的性能。但是，它不适用于生产环境，因为服务器重启时会话数据会丢失。此外，它还将应用程序限制在单个服务器上，因此不适用于分布式系统。&lt;br /&gt;
* 数据库存储使用关系型数据库（例如 PostgreSQL 或 MySQL）或 NoSQL 数据库（例如 MongoDB）。这种方法提供持久可靠的会话存储。但是，我们需要考虑性能影响，并确保对会话 ID 列进行适当的索引以实现快速查找。数据库存储虽然可靠，但速度可能比基于缓存的解决方案慢。&lt;br /&gt;
* 分布式缓存系统（例如 Redis 或 Memcached）是专为会话管理而构建的高性能键值存储系统。它们提供卓越的性能、内置的生存时间 (TTL) 支持（用于自动会话过期）以及横向扩展能力。由于其速度和可靠性，Redis 在生产环境中尤其适用于会话存储。&lt;br /&gt;
&lt;br /&gt;
内存存储仅应用于开发或测试。对于单服务器的生产应用，数据库存储就足够了。对于分布式系统或需要高性能和可扩展性的应用，建议选择 Redis 或 Memcached。 &lt;br /&gt;
&lt;br /&gt;
=== 分布式会话策略 ===&lt;br /&gt;
当在负载均衡器后运行多个服务器时，我们面临的挑战是如何确保所有服务器都能访问相同的会话数据。&lt;br /&gt;
&lt;br /&gt;
粘性会话（也称会话亲和性）是一种负载均衡方法，它将来自特定用户的所有请求路由到同一台服务器。这种方法易于实现，因为会话无需在服务器之间共享。然而，它可能导致负载分布不均，并且如果服务器发生故障，用户的会话将会丢失。&lt;br /&gt;
&lt;br /&gt;
请看下图：  &lt;br /&gt;
&lt;br /&gt;
[[文件:Anquanshouquan3.png|居中|无框|501x501像素]]&lt;br /&gt;
会话复制是指将会话数据复制到集群中的所有服务器。这提供了高可用性，因为即使一台服务器发生故障，其他服务器也能获取会话数据。然而，由于会话需要持续同步，这会带来显著的网络开销，而且在大型集群中维护跨服务器的一致性可能极具挑战性。&lt;br /&gt;
&lt;br /&gt;
集中式会话存储使用单一数据源（通常是 Redis 集群），所有服务器都从该数据源读取和写入会话数据。这种方法具有高度可扩展性，并能确保所有服务器之间的数据一致性。主要问题在于会话存储可能成为单点故障，但可以通过使用 Redis 集群或复制来缓解。这种策略推荐用于微服务架构。 &lt;br /&gt;
&lt;br /&gt;
=== 使用会话的挑战 ===&lt;br /&gt;
在微服务等分布式系统中，会话数据必须在服务器之间共享，这就需要额外的基础设施，例如集中式数据库或粘性会话。这些解决方案会增加复杂性并可能造成瓶颈。&lt;br /&gt;
&lt;br /&gt;
此外，如果攻击者窃取了会话 ID，他们就有可能冒充用户。可以通过使用 HTTPS 加密传输中的数据并实施会话超时来缓解这种情况。&lt;br /&gt;
&lt;br /&gt;
大量的活跃会话会消耗大量的服务器资源，不过这可以通过使用像 Redis 这样的高效会话存储来解决。 &lt;br /&gt;
&lt;br /&gt;
== 使用 JWT 进行身份验证 ==&lt;br /&gt;
JSON Web Tokens (JWT) 是一种紧凑、URL 安全、自包含的令牌格式，用于在各方之间安全地传输信息。&lt;br /&gt;
&lt;br /&gt;
JWT 是无状态的，这意味着服务器无需存储会话数据。所有用户相关信息都包含在令牌中。服务器只需要签名密钥即可验证令牌，这使得 JWT 非常适合多个服务交互的分布式系统。&lt;br /&gt;
&lt;br /&gt;
这就是为什么 JWT 经常被用于身份验证和授权，以实现无状态和可扩展的系统。 &lt;br /&gt;
&lt;br /&gt;
=== JWT的结构 ===&lt;br /&gt;
JWT 由三部分组成：头部、有效载荷和签名。每一部分都采用 Base64 编码。 &lt;br /&gt;
[[文件:Imagehwitjwt.png|居中|缩略图|582x582像素]] &lt;br /&gt;
头部包含令牌的元数据，包括令牌类型（JWT）和签名算法，例如 HS256 或 RS256。以下是一个示例： &lt;br /&gt;
  &amp;lt;code&amp;gt;{ “alg”: “HS256”, “typ”: “JWT” }&amp;lt;/code&amp;gt;&lt;br /&gt;
有效负载包含声明，这些声明是关于用户或令牌的陈述。声明可以是已注册声明（预定义，例如 iss 表示发行者，exp 表示过期时间，sub 表示主体），公共声明（应用程序定义的自定义声明），或私有声明（发行者和消费者共享的自定义声明）。以下是一个示例： &lt;br /&gt;
  &amp;lt;code&amp;gt;{ “sub”: “1234567890”, “name”: “John Doe”, “admin”: true, “iat”: 1516239022 }&amp;lt;/code&amp;gt;&lt;br /&gt;
最后，签名确保令牌的完整性并验证发送者的真实性。它是通过对头部和有效负载进行编码，并使用密钥或私钥对其进行签名而生成的： &lt;br /&gt;
  &amp;lt;code&amp;gt;HMACSHA256( base64UrlEncode(header) + “.” + base64UrlEncode(payload), secret )&amp;lt;/code&amp;gt;&lt;br /&gt;
以下是 JWT 在典型身份验证流程中的工作原理： &lt;br /&gt;
&lt;br /&gt;
* 用户登录后，服务器验证凭据并生成包含用户声明（例如用户 ID 和角色）的 JWT。 &lt;br /&gt;
* JWT 使用密钥（对称签名）或私钥（非对称签名）进行签名。签名后的令牌通常通过响应体或 cookie 发送给客户端。 &lt;br /&gt;
* 对于后续请求，客户端会将 JWT 作为 Bearer 令牌包含在 Authorization 标头中。 &lt;br /&gt;
* 服务器通过验证签名和检查过期时间 (exp) 或受众 (aud) 等声明来验证令牌。 &lt;br /&gt;
* 如果令牌有效，服务器将允许访问所请求的资源。&lt;br /&gt;
&lt;br /&gt;
请看下图： &lt;br /&gt;
[[文件:Imagejwtauthenprotoco.png|居中|缩略图|658x658像素]] &lt;br /&gt;
=== 刷新令牌流 ===&lt;br /&gt;
JWT 的一个常见挑战是，出于安全考虑，访问令牌的有效期应该很短，通常为 15 分钟到 1 小时。然而，强制用户反复登录会造成糟糕的用户体验。&lt;br /&gt;
&lt;br /&gt;
刷新令牌通过实现无缝重新身份验证来解决这个问题，无需用户再次输入凭据。该模式使用两种类型的令牌。 &lt;br /&gt;
&lt;br /&gt;
* 访问令牌有效期很短，用于验证 API 请求。 &lt;br /&gt;
* 刷新令牌的有效期很长（数天到数周），仅用于获取新的访问令牌。刷新令牌通常安全地存储在 HttpOnly Cookie 或移动设备的安全存储中，以防止被盗。&lt;br /&gt;
&lt;br /&gt;
完整的流程如下： &lt;br /&gt;
&lt;br /&gt;
* 用户使用凭据登录，服务器验证凭据。 &lt;br /&gt;
* 服务器会颁发访问令牌和刷新令牌。 &lt;br /&gt;
* 客户端安全地存储了这两个令牌。 &lt;br /&gt;
* 对于后续请求，客户端使用 Authorization 标头中的访问令牌。 &lt;br /&gt;
* 当访问令牌过期时，客户端会向刷新端点发送带有刷新令牌的请求。 &lt;br /&gt;
* 服务器验证刷新令牌，检查其是否仍然有效且未被撤销。 &lt;br /&gt;
* 如果有效，服务器将颁发新的访问令牌（并可选择颁发新的刷新令牌）。 &lt;br /&gt;
* 客户端使用新的访问令牌进行后续请求。&lt;br /&gt;
&lt;br /&gt;
这种方法兼顾了安全性和用户体验。有效期较短的访问令牌可以在被盗时最大限度地减少损失，而刷新令牌则允许用户保持身份验证状态，无需不断重新输入凭据。 &lt;br /&gt;
&lt;br /&gt;
== PASETO ==&lt;br /&gt;
PASETO，即平台无关安全令牌（Platform-Agnostic Security Tokens）的缩写，是 JWT 的一种现代替代方案，其设计重点在于安全性、简洁性和加密最佳实践。&lt;br /&gt;
&lt;br /&gt;
PASETO 解决了与 JWT 相关的一些常见漏洞和滥用问题，同时保持了各种身份验证和授权场景所需的灵活性。&lt;br /&gt;
&lt;br /&gt;
与允许灵活选择算法（有时会导致不安全的配置）的 JWT 不同，PASETO 强制使用强大且密码学上可靠的算法，从而降低了因配置错误而导致漏洞的风险。JWT 允许开发者使用像 HS256 或臭名昭著的 none 算法这样的弱算法，而 PASETO 则将选择限制在像 AES-GCM（用于对称加密）和 Ed25519（用于非对称签名）这样强大的算法上。&lt;br /&gt;
&lt;br /&gt;
PASETO 令牌分为本地令牌（加密）和公共令牌（签名），确保敏感数据要么经过安全加密，要么经过签名验证。相比之下，JWT 令牌即使经过签名也始终以明文形式存在，因此容易发生意外的信息泄露。 &lt;br /&gt;
&lt;br /&gt;
=== PASETO 的结构 ===&lt;br /&gt;
PASETO 令牌由三到四个主要部分组成，具体取决于它是本地令牌还是公共令牌。这些部分之间用点号分隔。 &lt;br /&gt;
&lt;br /&gt;
* 版本号表示所使用的 PASETO 协议版本。例如，v1 版本使用较旧的加密标准，而 v2 版本使用现代、安全的加密标准。 &lt;br /&gt;
* 用途指定令牌的类型，即是否需要加密或签名。选项包括本地（加密令牌）和公共（签名令牌）。 &lt;br /&gt;
* 有效载荷包含令牌内的实际数据或声明。对于本地令牌，有效载荷经过加密，并以不透明的 Base64Url 编码字符串的形式呈现。对于公共令牌，有效载荷以明文形式呈现，并经过 Base64Url 编码。 &lt;br /&gt;
* 页脚包含有效负载中未包含的可选元数据，例如受众（aud）或发行者（iss）。 &lt;br /&gt;
&lt;br /&gt;
=== 本地 PASETO 与公共 PASETO ===&lt;br /&gt;
本地 PASETO 令牌经过加密，确保令牌内数据的机密性。它们适用于需要对敏感信息保密的场景，防止未经授权的第三方访问。这些令牌使用对称加密算法来保证有效载荷的机密性。只有拥有共享密钥的各方才能解密并访问令牌的内容。 &lt;br /&gt;
[[文件:Pastetogangingpasto.png|居中|缩略图|462x462像素]] &lt;br /&gt;
公钥 PASETO 令牌经过签名。它们确保数据的完整性，但不保证数据的机密性。这些令牌是透明的，任何人都可以读取，但只有签名密钥的持有者才能验证。换句话说，任何篡改令牌的行为都会使签名失效。它们使用非对称加密算法（例如 ED25519）对令牌进行签名。公钥用于验证令牌，而私钥用于签名。它们适用于客户端需要读取有效载荷但又必须保持防篡改的场景。 &lt;br /&gt;
[[文件:Image2pasteo棉铃调整.png|居中|缩略图|502x502像素]] &lt;br /&gt;
=== PASETO面临的挑战 ===&lt;br /&gt;
与应用广泛的 JWT 相比，PASETO 相对较新，采用率也较低。这意味着可用的库、工具和社区支持也相对较少。&lt;br /&gt;
&lt;br /&gt;
熟悉 JWT 的开发者可能需要一些时间来理解和适应 PASETO 的原理和特性。虽然 PASETO 标准定义完善，但其生态系统缺乏 JWT 那样丰富的中间件和框架集成。 &lt;br /&gt;
&lt;br /&gt;
== 概括 ==&lt;br /&gt;
本文详细介绍了多种身份验证技术。以下是主要学习要点的简要概述： &lt;br /&gt;
&lt;br /&gt;
* 身份验证是验证用户身份的过程，是应用程序安全的基础。它与授权不同，授权决定了已验证用户可以执行哪些操作。 &lt;br /&gt;
* Cookie 在客户端存储少量数据，并使用 HttpOnly、Secure 和 SameSite 等属性来控制安全性和行为。 &lt;br /&gt;
* 第一方 Cookie 由我们访问的域设置，对于身份验证至关重要；而第三方 Cookie 由外部域设置，并且越来越受到浏览器的限制。 &lt;br /&gt;
* 会话将身份验证数据存储在服务器端，并使用 cookie 仅保存会话 ID 引用，与在客户端存储敏感数据相比，安全性更高。 &lt;br /&gt;
* 会话存储选项包括内存存储（仅限开发）、数据库存储（单服务器）和分布式缓存（如 Redis，用于生产和分布式系统）。 &lt;br /&gt;
* 分布式会话策略包括粘性会话（简单但存在问题）、会话复制（开销高）和集中式会话存储（推荐用于微服务）。 &lt;br /&gt;
* JWT 是一种自包含的、无状态的令牌格式，由三部分组成（标头、有效负载、签名），无需服务器端会话存储。 &lt;br /&gt;
* 刷新令牌通过使用有效期短的访问令牌进行请求，并使用有效期长的刷新令牌来获取新的访问令牌，从而解决了 JWT 过期问题。 &lt;br /&gt;
* JWT 代币一旦发行就不容易撤销，需要额外的机制，例如代币黑名单或较短的过期时间，来管理安全性。 &lt;br /&gt;
* PASETO 通过强制执行强大的加密算法，并提供加密（本地）和签名（公共）令牌类型，改进了 JWT。 &lt;br /&gt;
* PASETO 通过移除算法协商并使用预设的安全默认值，消除了 JWT 算法混淆的漏洞。 &lt;br /&gt;
* 在 cookie/session（传统 Web 应用程序）、JWT（分布式系统和 API）或 PASETO（安全关键型应用程序）之间进行选择，取决于我们具体的可扩展性、安全性和架构要求。&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Image2pasteo%E6%A3%89%E9%93%83%E8%B0%83%E6%95%B4.png&amp;diff=98</id>
		<title>文件:Image2pasteo棉铃调整.png</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Image2pasteo%E6%A3%89%E9%93%83%E8%B0%83%E6%95%B4.png&amp;diff=98"/>
		<updated>2026-02-07T14:30:50Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;33&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Pastetogangingpasto.png&amp;diff=97</id>
		<title>文件:Pastetogangingpasto.png</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Pastetogangingpasto.png&amp;diff=97"/>
		<updated>2026-02-07T14:29:49Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;afe&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Imagejwtauthenprotoco.png&amp;diff=96</id>
		<title>文件:Imagejwtauthenprotoco.png</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Imagejwtauthenprotoco.png&amp;diff=96"/>
		<updated>2026-02-07T14:27:25Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;33&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Imagehwitjwt.png&amp;diff=95</id>
		<title>文件:Imagehwitjwt.png</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Imagehwitjwt.png&amp;diff=95"/>
		<updated>2026-02-07T14:25:59Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;2&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Howitworkforauth.png&amp;diff=94</id>
		<title>文件:Howitworkforauth.png</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Howitworkforauth.png&amp;diff=94"/>
		<updated>2026-02-07T14:24:56Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;how3&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E5%88%86%E7%B1%BB:%E8%B5%84%E8%AE%AF&amp;diff=93</id>
		<title>分类:资讯</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E5%88%86%E7%B1%BB:%E8%B5%84%E8%AE%AF&amp;diff=93"/>
		<updated>2026-02-07T14:16:16Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[构建安全应用程序的顶级身份验证技术]]&lt;br /&gt;
&lt;br /&gt;
[[谷歌的张量处理器（TPU）是如何工作的？]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E6%9E%84%E5%BB%BA%E5%AE%89%E5%85%A8%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E7%9A%84%E9%A1%B6%E7%BA%A7%E8%BA%AB%E4%BB%BD%E9%AA%8C%E8%AF%81%E6%8A%80%E6%9C%AF&amp;diff=92</id>
		<title>构建安全应用程序的顶级身份验证技术</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E6%9E%84%E5%BB%BA%E5%AE%89%E5%85%A8%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E7%9A%84%E9%A1%B6%E7%BA%A7%E8%BA%AB%E4%BB%BD%E9%AA%8C%E8%AF%81%E6%8A%80%E6%9C%AF&amp;diff=92"/>
		<updated>2026-02-07T14:15:48Z</updated>

		<summary type="html">&lt;p&gt;Admin：​创建页面，内容为“ 身份验证是确保应用程序及其处理的敏感数据安全的第一道防线。无论是个人银行应用程序、企业平台还是电子商务网站，都需要有效的身份验证机制来验证用户身份并保障其对资源的访问权限。  如果没有适当的身份验证，应用程序容易受到未经授权的访问、数据泄露和恶意攻击，可能导致重大的经济损失、声誉损害和隐私侵犯。  除了安全性之外…”&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
身份验证是确保应用程序及其处理的敏感数据安全的第一道防线。无论是个人银行应用程序、企业平台还是电子商务网站，都需要有效的身份验证机制来验证用户身份并保障其对资源的访问权限。&lt;br /&gt;
&lt;br /&gt;
如果没有适当的身份验证，应用程序容易受到未经授权的访问、数据泄露和恶意攻击，可能导致重大的经济损失、声誉损害和隐私侵犯。&lt;br /&gt;
&lt;br /&gt;
除了安全性之外，身份验证在用户体验中也扮演着至关重要的角色。通过识别用户，应用程序可以提供个性化服务、记住用户偏好，并启用跨平台的单点登录 (SSO) 等功能。&lt;br /&gt;
&lt;br /&gt;
随着威胁的不断演变，实现安全高效的身份验证比以往任何时候都更具挑战性。开发人员必须在相互冲突的优先事项之间寻求平衡，例如安全性（确保抵御不同类型的攻击，例如会话劫持、令牌窃取和重放攻击）、可扩展性（在不影响性能的前提下支持数百万用户）和用户体验（在应用强大的安全措施的同时保持易用性）。&lt;br /&gt;
&lt;br /&gt;
为了应对这些挑战，开发人员依赖于各种身份验证技术。在本文中，我们将探讨应用程序中使用的多种身份验证技术，并了解它们的优缺点。 &lt;br /&gt;
[[文件:Goujiananquanyinngyongchengxu.png|居中|缩略图|720x720像素]]&lt;br /&gt;
&lt;br /&gt;
== 身份验证基础知识 ==&lt;br /&gt;
身份验证是指验证尝试访问应用程序的用户、设备或系统的身份的过程。简单来说，就是应用程序如何确保访问者或系统的身份与其声称的身份相符。它通常涉及验证用户名、密码、生物识别数据或令牌等凭证。&lt;br /&gt;
&lt;br /&gt;
例如，当我们使用密码登录网站时，应用程序会将我们输入的密码与存储的凭据进行比较，以确认我们的身份。在基于 API 的系统中，应用程序可能会使用令牌来验证调用服务是否有权与后端交互。 &lt;br /&gt;
&lt;br /&gt;
=== 身份验证与授权 ===&lt;br /&gt;
身份验证和授权是密切相关但又不同的过程。&lt;br /&gt;
&lt;br /&gt;
身份验证回答“你是谁？”这个问题，侧重于验证身份。授权则回答“你被允许做什么？”这个问题，通过确定授予已验证用户的权限或访问级别来实现。&lt;br /&gt;
&lt;br /&gt;
例如，身份验证用于确认我们是否是电子商务平台的注册用户。授权则决定我们是否可以查看订单历史记录或以管理员身份管理库存。换句话说，身份验证用于确认身份，而授权则基于该身份实施访问控制。 &lt;br /&gt;
&lt;br /&gt;
== 使用 Cookie 和会话进行身份验证 ==&lt;br /&gt;
接下来，我们将探讨 cookie 和会话在身份验证方面的应用： &lt;br /&gt;
&lt;br /&gt;
=== Cookie ===&lt;br /&gt;
Cookie 是由 Web 服务器存储在客户端浏览器上的小型数据文件。它们在原本无状态的 HTTP 通信中扮演着关键角色，使 Web 应用程序能够在多个请求中记住信息，从而维护通信状态。&lt;br /&gt;
&lt;br /&gt;
Cookie 允许 Web 服务器存储请求之间持久存在的数据，使其可用于各种用途，例如会话管理（使用会话 ID 跟踪已登录用户）、个性化（存储用户偏好或设置）以及分析和跟踪（记录用户行为以进行分析或定向广告）。&lt;br /&gt;
&lt;br /&gt;
在身份验证中，Cookie 通常用于存储会话令牌或标识符，以验证用户的身份。 &lt;br /&gt;
&lt;br /&gt;
=== Cookie 在身份验证中的工作原理 ===&lt;br /&gt;
该过程通常包含两个部分。用户登录时，用户提供用户名和密码等凭据。服务器验证这些凭据并生成会话 ID 或令牌。此会话 ID 会发送到浏览器并存储在 cookie 中。&lt;br /&gt;
&lt;br /&gt;
对于后续请求，浏览器会自动将 cookie 添加到每个 HTTP 请求的 Cookie 标头中。服务器会从 cookie 中读取会话 ID，对其进行验证，并识别用户。&lt;br /&gt;
&lt;br /&gt;
请看下图： &lt;br /&gt;
[[文件:Shefenzhouqun2.png|居中|缩略图|568x568像素]]&lt;br /&gt;
&lt;br /&gt;
=== Cookie 属性 ===&lt;br /&gt;
Cookie 具有多种属性，用于控制其行为和安全性： &lt;br /&gt;
&lt;br /&gt;
* HttpOnly 属性可阻止 JavaScript 访问 cookie，从而缓解跨站脚本 (XSS) 攻击。Secure 属性可确保 cookie 仅通过 HTTPS 连接发送，从而防止中间人攻击。 &lt;br /&gt;
* SameSite 属性有助于防止跨站请求伪造 (CSRF) 攻击。它有三个值：Strict（cookie 永远不会在跨站请求中发送）、Lax（cookie 仅在顶级导航中发送）和 None（cookie 随所有请求发送，但需要 Secure 属性）。 &lt;br /&gt;
* Domain 属性指定哪些主机可以接收 cookie。例如，设置 Domain= example.com允许将 cookie 发送到example.com及其所有子域。Path 属性将 cookie 限制在特定的 URL 路径中。 &lt;br /&gt;
* 对于过期时间，我们可以使用 Max-Age（指定有效期，单位为秒）或 Expires（设置绝对过期日期）。如果两者都未设置，则该 cookie 将成为会话 cookie，并在浏览器关闭时被删除。 &lt;br /&gt;
&lt;br /&gt;
=== 第一方 Cookie 与第三方 Cookie ===&lt;br /&gt;
第一方 Cookie 由我们当前访问的域名设置。&lt;br /&gt;
&lt;br /&gt;
当我们访问 example[dot]com 时，如果该网站设置了 cookie，那就是第一方 cookie。这些 cookie 用于网站的基本功能，例如身份验证和用户偏好设置。&lt;br /&gt;
&lt;br /&gt;
第三方 Cookie 由与我们正在访问的网站不同的域名设置。例如，如果我们访问 example[dot]com，而该网站加载了来自ads.com的广告，则ads.com域名可以设置一个 Cookie。这些 Cookie 通常用于跨多个网站跟踪用户行为，以达到广告投放的目的。&lt;br /&gt;
&lt;br /&gt;
出于隐私考虑，现代浏览器对第三方 Cookie 的限制日益增多。有些浏览器甚至默认阻止第三方 Cookie。为了确保身份验证在所有浏览器上都能可靠运行，我们应该始终使用第一方 Cookie。 &lt;br /&gt;
&lt;br /&gt;
=== 使用 Cookie 的挑战 ===&lt;br /&gt;
Cookie面临多项安全挑战： &lt;br /&gt;
&lt;br /&gt;
* 如果恶意脚本通过跨站脚本攻击 (XSS) 注入到网站中，它就可以访问包含敏感数据的 cookie。设置 HttpOnly 标志可以防止这种情况发生。 &lt;br /&gt;
* 如果 Cookie 通过未加密的 HTTP 协议传输，则可能在中间人攻击中被拦截。“安全”标志可确保 Cookie 仅通过 HTTPS 协议发送。 &lt;br /&gt;
* 请求中自动发送的 Cookie 可能被 CSRF 攻击利用来执行未经授权的操作。实施 CSRF 令牌并使用 SameSite 属性有助于缓解这种情况。 &lt;br /&gt;
* 浏览器对 Cookie 的大小有限制，通常每个 Cookie 为 4KB，并且每个域的 Cookie 数量也有限制。过多的 Cookie 会导致性能问题或请求被拒绝。&lt;br /&gt;
&lt;br /&gt;
以下是一些安全处理 Cookie 的最佳实践： &lt;br /&gt;
&lt;br /&gt;
* 我们应该始终设置 HttpOnly 标志来阻止 JavaScript 访问并降低 XSS 风险。Secure 标志可确保 cookie 仅通过 HTTPS 发送。 &lt;br /&gt;
* 使用 SameSite 属性（SameSite=Strict 或 SameSite=Lax）可以限制跨站点请求并降低 CSRF 风险。 &lt;br /&gt;
* 我们应该对敏感数据使用较短的过期时间，避免在 cookie 中存储密码或信用卡号等敏感信息，而只存储令牌或标识符。 &lt;br /&gt;
&lt;br /&gt;
== 会话 ==&lt;br /&gt;
会话是一种服务器端机制，用于在用户与应用程序进行交互期间存储和管理用户身份验证数据。与将数据存储在客户端的 Cookie 不同，会话将数据安全地保存在服务器端，客户端仅持有一个引用，通常是会话 ID。&lt;br /&gt;
&lt;br /&gt;
使用会话进行身份验证的流程包括以下几个步骤： &lt;br /&gt;
&lt;br /&gt;
* 用户登录时，用户提交登录凭据。服务器验证凭据并为用户创建一个会话，通常用唯一的会话 ID 表示。 &lt;br /&gt;
* 为了生成会话 ID，服务器会创建一个与存储在服务器上的用户会话数据关联的随机唯一标识符。此会话 ID 会通过 cookie 或其他传输机制发送给客户端。 &lt;br /&gt;
* 服务器将会话数据（例如用户 ID、角色和偏好）存储在内存、数据库或其他存储系统中。 &lt;br /&gt;
* 会话 ID 充当检索此数据的密钥。对于每个后续请求，客户端都会发送会话 ID，通常通过 cookie 发送。服务器验证会话 ID，检索关联数据，并使用它来处理请求。&lt;br /&gt;
&lt;br /&gt;
请看下图： &lt;br /&gt;
[[文件:Anquanshouquan3.png|居中|无框|501x501像素]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
会话可以设置生存时间 (TTL)，在一段时间不活动或达到最大持续时间后自动过期。当用户注销或出于安全考虑撤销会话时，会话数据将从服务器中删除，会话 ID 也将失效。 &lt;br /&gt;
&lt;br /&gt;
=== 会话与 Cookie 之间的关系 ===&lt;br /&gt;
Cookie 和会话通常协同工作。&lt;br /&gt;
&lt;br /&gt;
Cookie 存储着客户端的会话 ID。每次请求时，浏览器都会将 cookie 发送到服务器，以便服务器识别用户的会话。&lt;br /&gt;
&lt;br /&gt;
以下是一个简单的代码示例，展示了如何将会话 ID 设置到 cookie 中： &lt;br /&gt;
  &amp;lt;code&amp;gt;app.post (&#039;/login&#039;, (req, res) =&amp;gt; { const sessionId = createSession(req.body.username); res.cookie(&#039;session_id&#039;, sessionId, { httpOnly: true, secure: true, maxAge: 3600000 }); res.send(&#039;Login successful&#039;); });&amp;lt;/code&amp;gt;&lt;br /&gt;
对于传入的请求，服务器可以读取存储在 cookie 中的会话 ID： &lt;br /&gt;
  &amp;lt;code&amp;gt;app.get(&#039;/profile&#039;, (req, res) =&amp;gt; { const sessionId = req.cookies[&#039;session_id&#039;]; if (isValidSession(sessionId)) { res.send(&#039;Profile page&#039;); } else { res.status(401).send(&#039;Unauthorized&#039;); } });&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== 会话存储选项 ===&lt;br /&gt;
选择合适的会话存储机制对于性能和可扩展性至关重要。 &lt;br /&gt;
&lt;br /&gt;
* 内存存储将会话保存在服务器的 RAM 中，从而提供最快的性能。但是，它不适用于生产环境，因为服务器重启时会话数据会丢失。此外，它还将应用程序限制在单个服务器上，因此不适用于分布式系统。 &lt;br /&gt;
* 数据库存储使用关系型数据库（例如 PostgreSQL 或 MySQL）或 NoSQL 数据库（例如 MongoDB）。这种方法提供持久可靠的会话存储。但是，我们需要考虑性能影响，并确保对会话 ID 列进行适当的索引以实现快速查找。数据库存储虽然可靠，但速度可能比基于缓存的解决方案慢。 &lt;br /&gt;
* 分布式缓存系统（例如 Redis 或 Memcached）是专为会话管理而构建的高性能键值存储系统。它们提供卓越的性能、内置的生存时间 (TTL) 支持（用于自动会话过期）以及横向扩展能力。由于其速度和可靠性，Redis 在生产环境中尤其适用于会话存储。&lt;br /&gt;
&lt;br /&gt;
内存存储仅应用于开发或测试。对于单服务器的生产应用，数据库存储就足够了。对于分布式系统或需要高性能和可扩展性的应用，建议选择 Redis 或 Memcached。 &lt;br /&gt;
&lt;br /&gt;
=== 分布式会话策略 ===&lt;br /&gt;
当在负载均衡器后运行多个服务器时，我们面临的挑战是如何确保所有服务器都能访问相同的会话数据。&lt;br /&gt;
&lt;br /&gt;
粘性会话（也称会话亲和性）是一种负载均衡方法，它将来自特定用户的所有请求路由到同一台服务器。这种方法易于实现，因为会话无需在服务器之间共享。然而，它可能导致负载分布不均，并且如果服务器发生故障，用户的会话将会丢失。&lt;br /&gt;
&lt;br /&gt;
请看下图： &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
会话复制是指将会话数据复制到集群中的所有服务器。这提供了高可用性，因为即使一台服务器发生故障，其他服务器也能获取会话数据。然而，由于会话需要持续同步，这会带来显著的网络开销，而且在大型集群中维护跨服务器的一致性可能极具挑战性。&lt;br /&gt;
&lt;br /&gt;
集中式会话存储使用单一数据源（通常是 Redis 集群），所有服务器都从该数据源读取和写入会话数据。这种方法具有高度可扩展性，并能确保所有服务器之间的数据一致性。主要问题在于会话存储可能成为单点故障，但可以通过使用 Redis 集群或复制来缓解。这种策略推荐用于微服务架构。 &lt;br /&gt;
&lt;br /&gt;
=== 使用会话的挑战 ===&lt;br /&gt;
在微服务等分布式系统中，会话数据必须在服务器之间共享，这就需要额外的基础设施，例如集中式数据库或粘性会话。这些解决方案会增加复杂性并可能造成瓶颈。&lt;br /&gt;
&lt;br /&gt;
此外，如果攻击者窃取了会话 ID，他们就有可能冒充用户。可以通过使用 HTTPS 加密传输中的数据并实施会话超时来缓解这种情况。&lt;br /&gt;
&lt;br /&gt;
大量的活跃会话会消耗大量的服务器资源，不过这可以通过使用像 Redis 这样的高效会话存储来解决。 &lt;br /&gt;
&lt;br /&gt;
== 使用 JWT 进行身份验证 ==&lt;br /&gt;
JSON Web Tokens (JWT) 是一种紧凑、URL 安全、自包含的令牌格式，用于在各方之间安全地传输信息。&lt;br /&gt;
&lt;br /&gt;
JWT 是无状态的，这意味着服务器无需存储会话数据。所有用户相关信息都包含在令牌中。服务器只需要签名密钥即可验证令牌，这使得 JWT 非常适合多个服务交互的分布式系统。&lt;br /&gt;
&lt;br /&gt;
这就是为什么 JWT 经常被用于身份验证和授权，以实现无状态和可扩展的系统。 &lt;br /&gt;
&lt;br /&gt;
=== JWT的结构 ===&lt;br /&gt;
JWT 由三部分组成：头部、有效载荷和签名。每一部分都采用 Base64 编码。 &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
头部包含令牌的元数据，包括令牌类型（JWT）和签名算法，例如 HS256 或 RS256。以下是一个示例： &lt;br /&gt;
  &amp;lt;code&amp;gt;{ “alg”: “HS256”, “typ”: “JWT” }&amp;lt;/code&amp;gt;&lt;br /&gt;
有效负载包含声明，这些声明是关于用户或令牌的陈述。声明可以是已注册声明（预定义，例如 iss 表示发行者，exp 表示过期时间，sub 表示主体），公共声明（应用程序定义的自定义声明），或私有声明（发行者和消费者共享的自定义声明）。以下是一个示例： &lt;br /&gt;
  &amp;lt;code&amp;gt;{ “sub”: “1234567890”, “name”: “John Doe”, “admin”: true, “iat”: 1516239022 }&amp;lt;/code&amp;gt;&lt;br /&gt;
最后，签名确保令牌的完整性并验证发送者的真实性。它是通过对头部和有效负载进行编码，并使用密钥或私钥对其进行签名而生成的： &lt;br /&gt;
  &amp;lt;code&amp;gt;HMACSHA256( base64UrlEncode(header) + “.” + base64UrlEncode(payload), secret )&amp;lt;/code&amp;gt;&lt;br /&gt;
以下是 JWT 在典型身份验证流程中的工作原理： &lt;br /&gt;
&lt;br /&gt;
* 用户登录后，服务器验证凭据并生成包含用户声明（例如用户 ID 和角色）的 JWT。 &lt;br /&gt;
* JWT 使用密钥（对称签名）或私钥（非对称签名）进行签名。签名后的令牌通常通过响应体或 cookie 发送给客户端。 &lt;br /&gt;
* 对于后续请求，客户端会将 JWT 作为 Bearer 令牌包含在 Authorization 标头中。 &lt;br /&gt;
* 服务器通过验证签名和检查过期时间 (exp) 或受众 (aud) 等声明来验证令牌。 &lt;br /&gt;
* 如果令牌有效，服务器将允许访问所请求的资源。&lt;br /&gt;
&lt;br /&gt;
请看下图： &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== 刷新令牌流 ===&lt;br /&gt;
JWT 的一个常见挑战是，出于安全考虑，访问令牌的有效期应该很短，通常为 15 分钟到 1 小时。然而，强制用户反复登录会造成糟糕的用户体验。&lt;br /&gt;
&lt;br /&gt;
刷新令牌通过实现无缝重新身份验证来解决这个问题，无需用户再次输入凭据。该模式使用两种类型的令牌。 &lt;br /&gt;
&lt;br /&gt;
* 访问令牌有效期很短，用于验证 API 请求。 &lt;br /&gt;
* 刷新令牌的有效期很长（数天到数周），仅用于获取新的访问令牌。刷新令牌通常安全地存储在 HttpOnly Cookie 或移动设备的安全存储中，以防止被盗。&lt;br /&gt;
&lt;br /&gt;
完整的流程如下： &lt;br /&gt;
&lt;br /&gt;
* 用户使用凭据登录，服务器验证凭据。 &lt;br /&gt;
* 服务器会颁发访问令牌和刷新令牌。 &lt;br /&gt;
* 客户端安全地存储了这两个令牌。 &lt;br /&gt;
* 对于后续请求，客户端使用 Authorization 标头中的访问令牌。 &lt;br /&gt;
* 当访问令牌过期时，客户端会向刷新端点发送带有刷新令牌的请求。 &lt;br /&gt;
* 服务器验证刷新令牌，检查其是否仍然有效且未被撤销。 &lt;br /&gt;
* 如果有效，服务器将颁发新的访问令牌（并可选择颁发新的刷新令牌）。 &lt;br /&gt;
* 客户端使用新的访问令牌进行后续请求。&lt;br /&gt;
&lt;br /&gt;
这种方法兼顾了安全性和用户体验。有效期较短的访问令牌可以在被盗时最大限度地减少损失，而刷新令牌则允许用户保持身份验证状态，无需不断重新输入凭据。 &lt;br /&gt;
&lt;br /&gt;
== 帕塞托 ==&lt;br /&gt;
PASETO，即平台无关安全令牌（Platform-Agnostic Security Tokens）的缩写，是 JWT 的一种现代替代方案，其设计重点在于安全性、简洁性和加密最佳实践。&lt;br /&gt;
&lt;br /&gt;
PASETO 解决了与 JWT 相关的一些常见漏洞和滥用问题，同时保持了各种身份验证和授权场景所需的灵活性。&lt;br /&gt;
&lt;br /&gt;
与允许灵活选择算法（有时会导致不安全的配置）的 JWT 不同，PASETO 强制使用强大且密码学上可靠的算法，从而降低了因配置错误而导致漏洞的风险。JWT 允许开发者使用像 HS256 或臭名昭著的 none 算法这样的弱算法，而 PASETO 则将选择限制在像 AES-GCM（用于对称加密）和 Ed25519（用于非对称签名）这样强大的算法上。&lt;br /&gt;
&lt;br /&gt;
PASETO 令牌分为本地令牌（加密）和公共令牌（签名），确保敏感数据要么经过安全加密，要么经过签名验证。相比之下，JWT 令牌即使经过签名也始终以明文形式存在，因此容易发生意外的信息泄露。 &lt;br /&gt;
&lt;br /&gt;
=== PASETO 的结构 ===&lt;br /&gt;
PASETO 令牌由三到四个主要部分组成，具体取决于它是本地令牌还是公共令牌。这些部分之间用点号分隔。 &lt;br /&gt;
&lt;br /&gt;
* 版本号表示所使用的 PASETO 协议版本。例如，v1 版本使用较旧的加密标准，而 v2 版本使用现代、安全的加密标准。 &lt;br /&gt;
* 用途指定令牌的类型，即是否需要加密或签名。选项包括本地（加密令牌）和公共（签名令牌）。 &lt;br /&gt;
* 有效载荷包含令牌内的实际数据或声明。对于本地令牌，有效载荷经过加密，并以不透明的 Base64Url 编码字符串的形式呈现。对于公共令牌，有效载荷以明文形式呈现，并经过 Base64Url 编码。 &lt;br /&gt;
* 页脚包含有效负载中未包含的可选元数据，例如受众（aud）或发行者（iss）。 &lt;br /&gt;
&lt;br /&gt;
=== 本地 PASETO 与公共 PASETO ===&lt;br /&gt;
本地 PASETO 令牌经过加密，确保令牌内数据的机密性。它们适用于需要对敏感信息保密的场景，防止未经授权的第三方访问。这些令牌使用对称加密算法来保证有效载荷的机密性。只有拥有共享密钥的各方才能解密并访问令牌的内容。 &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
公钥 PASETO 令牌经过签名。它们确保数据的完整性，但不保证数据的机密性。这些令牌是透明的，任何人都可以读取，但只有签名密钥的持有者才能验证。换句话说，任何篡改令牌的行为都会使签名失效。它们使用非对称加密算法（例如 ED25519）对令牌进行签名。公钥用于验证令牌，而私钥用于签名。它们适用于客户端需要读取有效载荷但又必须保持防篡改的场景。 &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
| align=&amp;quot;left&amp;quot; |&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== PASETO面临的挑战 ===&lt;br /&gt;
与应用广泛的 JWT 相比，PASETO 相对较新，采用率也较低。这意味着可用的库、工具和社区支持也相对较少。&lt;br /&gt;
&lt;br /&gt;
熟悉 JWT 的开发者可能需要一些时间来理解和适应 PASETO 的原理和特性。虽然 PASETO 标准定义完善，但其生态系统缺乏 JWT 那样丰富的中间件和框架集成。 &lt;br /&gt;
&lt;br /&gt;
== 概括 ==&lt;br /&gt;
本文详细介绍了多种身份验证技术。以下是主要学习要点的简要概述： &lt;br /&gt;
&lt;br /&gt;
* 身份验证是验证用户身份的过程，是应用程序安全的基础。它与授权不同，授权决定了已验证用户可以执行哪些操作。 &lt;br /&gt;
* Cookie 在客户端存储少量数据，并使用 HttpOnly、Secure 和 SameSite 等属性来控制安全性和行为。 &lt;br /&gt;
* 第一方 Cookie 由我们访问的域设置，对于身份验证至关重要；而第三方 Cookie 由外部域设置，并且越来越受到浏览器的限制。 &lt;br /&gt;
* 会话将身份验证数据存储在服务器端，并使用 cookie 仅保存会话 ID 引用，与在客户端存储敏感数据相比，安全性更高。 &lt;br /&gt;
* 会话存储选项包括内存存储（仅限开发）、数据库存储（单服务器）和分布式缓存（如 Redis，用于生产和分布式系统）。 &lt;br /&gt;
* 分布式会话策略包括粘性会话（简单但存在问题）、会话复制（开销高）和集中式会话存储（推荐用于微服务）。 &lt;br /&gt;
* JWT 是一种自包含的、无状态的令牌格式，由三部分组成（标头、有效负载、签名），无需服务器端会话存储。 &lt;br /&gt;
* 刷新令牌通过使用有效期短的访问令牌进行请求，并使用有效期长的刷新令牌来获取新的访问令牌，从而解决了 JWT 过期问题。 &lt;br /&gt;
* JWT 代币一旦发行就不容易撤销，需要额外的机制，例如代币黑名单或较短的过期时间，来管理安全性。 &lt;br /&gt;
* PASETO 通过强制执行强大的加密算法，并提供加密（本地）和签名（公共）令牌类型，改进了 JWT。 &lt;br /&gt;
* PASETO 通过移除算法协商并使用预设的安全默认值，消除了 JWT 算法混淆的漏洞。 &lt;br /&gt;
* 在 cookie/session（传统 Web 应用程序）、JWT（分布式系统和 API）或 PASETO（安全关键型应用程序）之间进行选择，取决于我们具体的可扩展性、安全性和架构要求。&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Anquanshouquan3.png&amp;diff=91</id>
		<title>文件:Anquanshouquan3.png</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Anquanshouquan3.png&amp;diff=91"/>
		<updated>2026-02-07T14:15:01Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;auth&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Shefenzhouqun2.png&amp;diff=90</id>
		<title>文件:Shefenzhouqun2.png</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Shefenzhouqun2.png&amp;diff=90"/>
		<updated>2026-02-07T14:12:49Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;auth&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Goujiananquanyinngyongchengxu.png&amp;diff=89</id>
		<title>文件:Goujiananquanyinngyongchengxu.png</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Goujiananquanyinngyongchengxu.png&amp;diff=89"/>
		<updated>2026-02-07T14:09:45Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;goujjian1&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E9%A6%96%E9%A1%B5&amp;diff=88</id>
		<title>首页</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E9%A6%96%E9%A1%B5&amp;diff=88"/>
		<updated>2026-02-06T05:48:27Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[分类:Kivy]]&lt;br /&gt;
[[分类:C/C++]]&lt;br /&gt;
[[分类:Linux操作系统]]&lt;br /&gt;
[[分类:算法]]&lt;br /&gt;
&lt;br /&gt;
[[Transformer架构如何驱动现代大语言模型：深入解析AI核心技术]]&lt;br /&gt;
&lt;br /&gt;
[[大语言模型评估指南]]&lt;br /&gt;
&lt;br /&gt;
[[谷歌的张量处理器（TPU）是如何工作的？]]&lt;br /&gt;
&lt;br /&gt;
[[动手做系列：使用Apache2服务器，通过Let&#039;s Encrypt申请网站免费https证书]]&lt;br /&gt;
&lt;br /&gt;
[[编写一个TCP/IP栈3-TCP基础与握手|动手做系列：编写一个TCP/IP栈3-TCP基础与握手]]&lt;br /&gt;
&lt;br /&gt;
[[编写一个TCP/IP栈2-IPv4和ICMPv4|动手做系列：编写一个TCP/IP栈2-IPv4和ICMPv4]]&lt;br /&gt;
&lt;br /&gt;
[[编写一个TCP/IP栈1-以太网和ARP|动手做系列：编写一个TCP/IP栈1-以太网和ARP]]&lt;br /&gt;
&lt;br /&gt;
[[构建自己的区块链|动手做系列：构建自己的区块链]]&lt;br /&gt;
&lt;br /&gt;
[[500行代码构建自己的数据库 DBDB|动手做系列：500行代码构建自己的数据库 DBDB: Dog Bed Database]]&lt;br /&gt;
[[分类:Web3]]&lt;br /&gt;
[[分类:动手做系列]]&lt;br /&gt;
[[分类:资讯]]&lt;br /&gt;
[[分类:AI]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=Transformer%E6%9E%B6%E6%9E%84%E5%A6%82%E4%BD%95%E9%A9%B1%E5%8A%A8%E7%8E%B0%E4%BB%A3%E5%A4%A7%E8%AF%AD%E8%A8%80%E6%A8%A1%E5%9E%8B%EF%BC%9A%E6%B7%B1%E5%85%A5%E8%A7%A3%E6%9E%90AI%E6%A0%B8%E5%BF%83%E6%8A%80%E6%9C%AF&amp;diff=87</id>
		<title>Transformer架构如何驱动现代大语言模型：深入解析AI核心技术</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=Transformer%E6%9E%B6%E6%9E%84%E5%A6%82%E4%BD%95%E9%A9%B1%E5%8A%A8%E7%8E%B0%E4%BB%A3%E5%A4%A7%E8%AF%AD%E8%A8%80%E6%A8%A1%E5%9E%8B%EF%BC%9A%E6%B7%B1%E5%85%A5%E8%A7%A3%E6%9E%90AI%E6%A0%B8%E5%BF%83%E6%8A%80%E6%9C%AF&amp;diff=87"/>
		<updated>2026-02-06T05:47:44Z</updated>

		<summary type="html">&lt;p&gt;Admin：​创建页面，内容为“ == 前言 == 当我们与GPT、Claude或Gemini等现代大语言模型互动时，我们正在见证一个与人类形成句子过程根本不同的过程。虽然我们自然地构建思想并将它们转化为文字，但大语言模型通过循环转换过程运行。理解这个过程揭示了这些强大系统的能力和局限性。  == 2026年AI预测：上下文成为关键瓶颈 == 根据最新的AI发展趋势预测，到2026年，模型本身不会…”&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== 前言 ==&lt;br /&gt;
当我们与GPT、Claude或Gemini等现代大语言模型互动时，我们正在见证一个与人类形成句子过程根本不同的过程。虽然我们自然地构建思想并将它们转化为文字，但大语言模型通过循环转换过程运行。理解这个过程揭示了这些强大系统的能力和局限性。&lt;br /&gt;
&lt;br /&gt;
== 2026年AI预测：上下文成为关键瓶颈 ==&lt;br /&gt;
根据最新的AI发展趋势预测，到2026年，模型本身不会成为瓶颈，而上下文获取将成为关键挑战。随着AI代理从向量存储、会话状态、长期记忆、SQL数据库等拉取数据，找到正确的数据变得困难。错过关键上下文会导致响应崩溃，发送过多信息则会使延迟和成本飙升。因此，上下文引擎作为解决方案应运而生——一个单一的层来存储、索引和提供结构化和非结构化数据，涵盖短期和长期记忆，从而实现更快的响应、更低的成本和更实用的AI应用程序。&lt;br /&gt;
&lt;br /&gt;
== Transformer架构的核心组成 ==&lt;br /&gt;
现代大多数大语言模型的核心是一种称为Transformer的架构。该架构于2017年引入，是由神经网络层构建的序列预测算法。该架构有三个基本组成部分：&lt;br /&gt;
&lt;br /&gt;
# 嵌入层：将标记转换为数值表示&lt;br /&gt;
# 多层Transformer层：进行实际计算的地方&lt;br /&gt;
# 输出层：将结果转换回文本&lt;br /&gt;
&lt;br /&gt;
Transformer能够同时处理所有单词，而不是一次处理一个，使它们能够从大量文本数据集中学习并捕捉复杂的单词关系。&lt;br /&gt;
&lt;br /&gt;
== 详细工作流程解析 ==&lt;br /&gt;
&lt;br /&gt;
=== 第一步：标记化（Tokenization） ===&lt;br /&gt;
在任何计算发生之前，模型必须将文本转换为可处理的形式。这从标记化开始，文本被分解为基本单位称为标记。这些并不总是完整的单词，可能是子词、词片段甚至单个字符。&lt;br /&gt;
&lt;br /&gt;
例如输入：&amp;quot;I love transformers!&amp;quot;，分词器可能会将其分解为：[&amp;quot;I&amp;quot;, &amp;quot; love&amp;quot;, &amp;quot; transform&amp;quot;, &amp;quot;ers&amp;quot;, &amp;quot;!&amp;quot;]。注意&amp;quot;transformers&amp;quot;变成了两个单独的标记。每个词汇表中的唯一标记都被分配一个唯一的整数ID：&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;I&amp;quot; 可能是标记150&lt;br /&gt;
* &amp;quot;love&amp;quot; 可能是标记8942&lt;br /&gt;
* &amp;quot;transform&amp;quot; 可能是标记3301&lt;br /&gt;
* &amp;quot;ers&amp;quot; 可能是标记1847&lt;br /&gt;
* &amp;quot;!&amp;quot; 可能是标记254&lt;br /&gt;
&lt;br /&gt;
这些ID是任意标识符，没有固有的关系。标记150和151并不因为数字接近而相似。整体词汇表通常包含50,000到100,000个模型在训练期间学到的唯一标记。&lt;br /&gt;
&lt;br /&gt;
=== 第二步：嵌入（Embedding） ===&lt;br /&gt;
神经网络无法直接处理标记ID，因为它们只是固定的标识符。每个标记ID被映射到一个向量，即一个包含数百或数千个维度的连续数字列表。这些被称为嵌入。&lt;br /&gt;
&lt;br /&gt;
[[文件:Imageshenrulijieaihexinjishu.png|无|缩略图|604x604像素]]&lt;br /&gt;
以下是带有五个维度的简化示例（真实模型可能使用768到4096维）：&lt;br /&gt;
&lt;br /&gt;
* 标记&amp;quot;dog&amp;quot;变成 [0.23, -0.67, 0.45, 0.89, -0.12]&lt;br /&gt;
* 标记&amp;quot;wolf&amp;quot;变成 [0.25, -0.65, 0.47, 0.91, -0.10]&lt;br /&gt;
* 标记&amp;quot;car&amp;quot;变成 [-0.82, 0.34, -0.56, 0.12, 0.78]&lt;br /&gt;
&lt;br /&gt;
注意&amp;quot;dog&amp;quot;和&amp;quot;wolf&amp;quot;具有相似的数字，而&amp;quot;car&amp;quot;完全不同。这创建了一个语义空间，相关概念聚集在一起。&lt;br /&gt;
&lt;br /&gt;
为什么需要多个维度？这是因为如果每个词只有一个数字，我们可能会遇到矛盾。例如：&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;stock&amp;quot; 等于 5.2（金融术语）&lt;br /&gt;
* &amp;quot;capital&amp;quot; 等于 5.3（类似的金融术语）&lt;br /&gt;
* &amp;quot;rare&amp;quot; 等于 -5.2（反义词：不常见）&lt;br /&gt;
* &amp;quot;debt&amp;quot; 等于 -5.3（&amp;quot;capital&amp;quot;的反义词）&lt;br /&gt;
&lt;br /&gt;
现在，&amp;quot;rare&amp;quot;和&amp;quot;debt&amp;quot;都具有相似的负值，暗示它们相关，这毫无意义。数百个维度允许模型在没有这种矛盾的情况下表示复杂的关系。&lt;br /&gt;
&lt;br /&gt;
在这个空间中，我们可以执行数学运算。&amp;quot;king&amp;quot;的嵌入减去&amp;quot;man&amp;quot;再加上&amp;quot;woman&amp;quot;大约等于&amp;quot;queen&amp;quot;。这些关系在训练期间从文本数据中的模式中产生。&lt;br /&gt;
&lt;br /&gt;
=== 第三步：位置编码（Positional Encoding） ===&lt;br /&gt;
Transformer并不天然理解词序。如果没有额外信息，&amp;quot;The dog chased the cat&amp;quot;和&amp;quot;The cat chased the dog&amp;quot;看起来相同，因为两者包含相同的标记。&lt;br /&gt;
&lt;br /&gt;
解决方案是位置嵌入。每个位置都被映射到一个位置向量，就像标记被映射到意义向量一样。&lt;br /&gt;
&lt;br /&gt;
对于出现在第2位的标记&amp;quot;dog&amp;quot;，可能是这样的：&lt;br /&gt;
&lt;br /&gt;
* 词嵌入：[0.23, -0.67, 0.45, 0.89, -0.12]&lt;br /&gt;
* 位置2嵌入：[0.05, 0.12, -0.08, 0.03, 0.02]&lt;br /&gt;
* 组合（元素级求和）：[0.28, -0.55, 0.37, 0.92, -0.10]&lt;br /&gt;
&lt;br /&gt;
这个组合嵌入捕获了词的意义和使用语境。这也是流向Transformer层的内容。&lt;br /&gt;
&lt;br /&gt;
=== 第四步：注意力机制（Attention Mechanism） ===&lt;br /&gt;
Transformer层实现了注意力机制，这是使这些模型如此强大的关键创新。每个Transformer层对每个标记使用三个组件：查询（queries）、键（keys）和值（values）。我们可以将其视为模糊字典查找，其中模型比较它寻找的内容（查询）与所有可能的答案（键）并返回相应值的加权组合。&lt;br /&gt;
[[文件:Shenrujiexiaihexinjishu2.png|居中|缩略图|681x681像素]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
让我们看一个具体的例子。考虑句子：&amp;quot;The cat sat on the mat because it was comfortable.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
当模型处理单词&amp;quot;it&amp;quot;时，它需要确定&amp;quot;it&amp;quot;指代什么。以下是发生的情况：&lt;br /&gt;
&lt;br /&gt;
# 首先，&amp;quot;it&amp;quot;的嵌入生成一个查询向量，本质上询问&amp;quot;我指的是哪个名词？&amp;quot;&lt;br /&gt;
# 接下来，此查询与所有先前标记的键进行比较。每次比较产生一个相似度分数。例如：&lt;br /&gt;
#* &amp;quot;The&amp;quot;（冠词）生成分数：0.05&lt;br /&gt;
#* &amp;quot;cat&amp;quot;（名词）生成分数：8.3&lt;br /&gt;
#* &amp;quot;sat&amp;quot;（动词）生成分数：0.2&lt;br /&gt;
#* &amp;quot;on&amp;quot;（介词）生成分数：0.03&lt;br /&gt;
#* &amp;quot;the&amp;quot;（冠词）生成分数：0.04&lt;br /&gt;
#* &amp;quot;mat&amp;quot;（名词）生成分数：4.1&lt;br /&gt;
#* &amp;quot;because&amp;quot;（连词）生成分数：0.1&lt;br /&gt;
# 原始分数然后转换为总和为1.0的注意力权重。例如：&lt;br /&gt;
#* &amp;quot;cat&amp;quot;接收注意力权重：0.75（75%）&lt;br /&gt;
#* &amp;quot;mat&amp;quot;接收注意力权重：0.20（20%）&lt;br /&gt;
#* 所有其他标记：0.05总计（5%合计）&lt;br /&gt;
# 最后，模型获取每个标记的值向量并使用这些权重组合它们。例如：  输出 = (0.75 × Value_cat) + (0.20 × Value_mat) + (0.03 × Value_the) + ...&lt;br /&gt;
&lt;br /&gt;
&amp;quot;cat&amp;quot;的值贡献75%，&amp;quot;mat&amp;quot;贡献20%，其他一切几乎被忽略。这个加权组合成为&amp;quot;it&amp;quot;的新表示，捕获了语境理解，即&amp;quot;it&amp;quot;最有可能指代&amp;quot;cat&amp;quot;。&lt;br /&gt;
&lt;br /&gt;
这个注意力过程发生在每个Transformer层中，但每层学会检测不同的模式：&lt;br /&gt;
&lt;br /&gt;
* 早期层学习基本模式，如语法和常见词对。处理&amp;quot;cat&amp;quot;时，这些层可能高度关注&amp;quot;The&amp;quot;，因为它们学会了冠词和其名词相关。&lt;br /&gt;
* 中间层学习句子结构和短语间关系。它们可能弄清楚&amp;quot;cat&amp;quot;是&amp;quot;sat&amp;quot;的主语，&amp;quot;on the mat&amp;quot;形成表示位置的介词短语。&lt;br /&gt;
* 深层提取抽象含义。它们可能理解这个句子描述物理情况并暗示猫舒适或休息。&lt;br /&gt;
&lt;br /&gt;
每层逐步优化表示。一层的输出成为下一层的输入，每层添加更多语境理解。&lt;br /&gt;
&lt;br /&gt;
重要的是，只有最终Transformer层需要预测实际标记。所有中间层执行相同的注意力操作，但仅转换表示以对下游层更有用。中间层不输出标记预测，而是输出流向下一层的优化向量表示。&lt;br /&gt;
&lt;br /&gt;
这种堆叠多层，每层专精于语言理解的不同方面，是使大语言模型能够捕捉复杂模式并生成连贯文本的原因。&lt;br /&gt;
&lt;br /&gt;
=== 第五步：输出转换 ===&lt;br /&gt;
经过所有层流动后，最终向量必须转换为文本。解嵌入层将此向量与每个标记嵌入比较并产生分数。&lt;br /&gt;
&lt;br /&gt;
例如，完成&amp;quot;I love to eat&amp;quot;，解嵌入可能产生：&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;pizza&amp;quot;: 65.2&lt;br /&gt;
* &amp;quot;tacos&amp;quot;: 64.8&lt;br /&gt;
* &amp;quot;sushi&amp;quot;: 64.1&lt;br /&gt;
* &amp;quot;food&amp;quot;: 58.3&lt;br /&gt;
* &amp;quot;barbeque&amp;quot;: 57.9&lt;br /&gt;
* &amp;quot;car&amp;quot;: -12.4&lt;br /&gt;
* &amp;quot;42&amp;quot;: -45.8&lt;br /&gt;
&lt;br /&gt;
这些任意分数使用softmax转换为概率：&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;pizza&amp;quot;: 28.3%&lt;br /&gt;
* &amp;quot;tacos&amp;quot;: 24.1%&lt;br /&gt;
* &amp;quot;sushi&amp;quot;: 18.9%&lt;br /&gt;
* &amp;quot;food&amp;quot;: 7.2%&lt;br /&gt;
* &amp;quot;barbeque&amp;quot;: 6.1%&lt;br /&gt;
* &amp;quot;car&amp;quot;: 0.0001%&lt;br /&gt;
* &amp;quot;42&amp;quot;: 0.0000001%&lt;br /&gt;
&lt;br /&gt;
得分相似的标记（65.2对比64.8）接收相似的概率（28.3%对比24.1%），而低分标记获得接近零的概率。&lt;br /&gt;
&lt;br /&gt;
模型不选择最高概率标记。相反，它从此分布中随机采样。想象一个轮盘赌轮，每个标记获得与其概率成比例的切片。披萨获得28.3%，塔可获得24.1%，42获得微观切片。&lt;br /&gt;
&lt;br /&gt;
这样随机性的原因是，总是选择特定值如&amp;quot;pizza&amp;quot;会产生重复、不自然的输出。按概率加权的随机采样允许选择&amp;quot;tacos&amp;quot;、&amp;quot;sushi&amp;quot;或&amp;quot;barbeque&amp;quot;，产生多样化、自然的响应。偶尔会选择较低概率标记，导致创造性输出。&lt;br /&gt;
&lt;br /&gt;
== 生成过程详解 ==&lt;br /&gt;
生成过程对每个标记重复。让我们看一个例子，初始提示是&amp;quot;The capital of France.&amp;quot;：&lt;br /&gt;
&lt;br /&gt;
循环1：&lt;br /&gt;
&lt;br /&gt;
* 输入：[&amp;quot;The&amp;quot;, &amp;quot;capital&amp;quot;, &amp;quot;of&amp;quot;, &amp;quot;France&amp;quot;]&lt;br /&gt;
* 通过所有层处理&lt;br /&gt;
* 采样：&amp;quot;is&amp;quot;（80%）&lt;br /&gt;
* 当前输出：&amp;quot;The capital of France is&amp;quot;&lt;br /&gt;
&lt;br /&gt;
循环2：&lt;br /&gt;
&lt;br /&gt;
* 输入：[&amp;quot;The&amp;quot;, &amp;quot;capital&amp;quot;, &amp;quot;of&amp;quot;, &amp;quot;France&amp;quot;, &amp;quot;is&amp;quot;]（包含新标记）&lt;br /&gt;
* 通过所有层处理（现在5个标记）&lt;br /&gt;
* 采样：&amp;quot;Paris&amp;quot;（92%）&lt;br /&gt;
* 当前输出：&amp;quot;The capital of France is Paris&amp;quot;&lt;br /&gt;
&lt;br /&gt;
循环3：&lt;br /&gt;
&lt;br /&gt;
* 输入：[&amp;quot;The&amp;quot;, &amp;quot;capital&amp;quot;, &amp;quot;of&amp;quot;, &amp;quot;France&amp;quot;, &amp;quot;is&amp;quot;, &amp;quot;Paris&amp;quot;]（6个标记）&lt;br /&gt;
* 通过所有层处理&lt;br /&gt;
* 采样：&amp;quot;.&amp;quot;（65%）&lt;br /&gt;
* 当前输出：&amp;quot;The capital of France is Paris.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
循环4：&lt;br /&gt;
&lt;br /&gt;
* 输入：[&amp;quot;The&amp;quot;, &amp;quot;capital&amp;quot;, &amp;quot;of&amp;quot;, &amp;quot;France&amp;quot;, &amp;quot;is&amp;quot;, &amp;quot;Paris&amp;quot;, &amp;quot;.&amp;quot;]（7个标记）&lt;br /&gt;
* 通过所有层处理&lt;br /&gt;
* 采样：[EoS]标记（88%）&lt;br /&gt;
* 停止循环&lt;br /&gt;
* 最终输出：&amp;quot;The capital of France is Paris.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
[EoS]或序列结束标记发出完成信号。每个循环处理所有先前标记。这就是为什么响应变长时生成会变慢的原因。&lt;br /&gt;
&lt;br /&gt;
这被称为自回归生成，因为每个输出依赖于所有先前输出。如果选择了异常标记（也许在&amp;quot;I love to eat chalk&amp;quot;中&amp;quot;chalk&amp;quot;有0.01%概率），所有后续标记都将受此选择影响。&lt;br /&gt;
&lt;br /&gt;
== 训练与推理阶段 ==&lt;br /&gt;
Transformer流在两个环境中运行：训练和推理。&lt;br /&gt;
&lt;br /&gt;
=== 训练阶段 ===&lt;br /&gt;
在训练期间，模型从数十亿文本示例中学习语言模式。它从随机权重开始并逐渐调整它们。以下是训练如何工作的：&lt;br /&gt;
&lt;br /&gt;
* 训练文本：&amp;quot;The cat sat on the mat.&amp;quot;&lt;br /&gt;
* 模型接收：&amp;quot;The cat sat on the&amp;quot;&lt;br /&gt;
* 具有随机初始权重，模型可能预测：&lt;br /&gt;
** &amp;quot;banana&amp;quot;: 25%&lt;br /&gt;
** &amp;quot;car&amp;quot;: 22%&lt;br /&gt;
** &amp;quot;mat&amp;quot;: 3%（正确答案概率低）&lt;br /&gt;
** &amp;quot;elephant&amp;quot;: 18%&lt;br /&gt;
&lt;br /&gt;
训练过程计算误差（&amp;quot;mat&amp;quot;应该更高）并使用反向传播调整每个权重：&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;on&amp;quot;和&amp;quot;the&amp;quot;的嵌入被调整&lt;br /&gt;
* 所有96层的注意力权重被调整&lt;br /&gt;
* 解嵌入层被调整&lt;br /&gt;
&lt;br /&gt;
每次调整都很小（0.245到0.247），但在数十亿示例中累积。在不同语境中看到&amp;quot;sat on the&amp;quot;跟随&amp;quot;mat&amp;quot;数千次后，模型学会此模式。训练在数千GPU上花费数周并花费数百万美元。完成后，权重被冻结。&lt;br /&gt;
&lt;br /&gt;
=== 推理阶段 ===&lt;br /&gt;
在推理期间，Transformer使用冻结权重运行：&lt;br /&gt;
&lt;br /&gt;
* 用户查询：&amp;quot;Complete this: The cat sat on the&amp;quot;&lt;br /&gt;
* 模型使用其学习的权重处理输入并输出：&amp;quot;mat&amp;quot;（85%），&amp;quot;floor&amp;quot;（8%），&amp;quot;chair&amp;quot;（3%）。采样&amp;quot;mat&amp;quot;并返回。不发生权重更改。&lt;br /&gt;
&lt;br /&gt;
模型使用了其学习的知识但没有学习任何新内容。对话不会更新模型权重。要教模型新信息，我们需要使用新数据重新训练，这需要大量计算资源。&lt;br /&gt;
[[文件:ShenrulijiejiexiAIhexinjishu3.png|居中|缩略图|657x657像素]]&lt;br /&gt;
&lt;br /&gt;
== 总结 ==&lt;br /&gt;
Transformer架构为理解和生成人类语言提供了优雅的解决方案。通过将文本转换为数值表示，使用注意力机制捕捉单词间的关系，并堆叠多层以学习越来越抽象的模式，Transformer使现代大语言模型能够产生连贯有用的文本。&lt;br /&gt;
&lt;br /&gt;
这个过程涉及七个关键步骤，对每个生成的标记重复：标记化、嵌入创建、位置编码、通过具有注意力机制的Transformer层处理、解嵌入到分数、从概率中采样和解码回文本。每个步骤建立在前一个基础上，将原始文本转换为模型可以操作的数学表示，然后转换回人类可读输出。&lt;br /&gt;
&lt;br /&gt;
理解这个过程揭示了这些系统的功能和局限性。本质上，大语言模型是复杂模式匹配机器，根据从大规模数据集中学到的模式预测最可能的下一个标记。&lt;br /&gt;
&lt;br /&gt;
这个七步过程重复进行，每一步都建立在前一步的基础上，将原始文本转换为模型可以操作的数学表示，然后转换回人类可读的输出。&lt;br /&gt;
----&#039;&#039;本文详细解析了Transformer架构的工作原理，希望对您理解AI核心技术有所帮助。欢迎关注我们的公众号，获取更多前沿科技资讯！&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:ShenrulijiejiexiAIhexinjishu3.png&amp;diff=86</id>
		<title>文件:ShenrulijiejiexiAIhexinjishu3.png</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:ShenrulijiejiexiAIhexinjishu3.png&amp;diff=86"/>
		<updated>2026-02-06T05:47:25Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;steps&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Shenrujiexiaihexinjishu2.png&amp;diff=85</id>
		<title>文件:Shenrujiexiaihexinjishu2.png</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Shenrujiexiaihexinjishu2.png&amp;diff=85"/>
		<updated>2026-02-06T05:45:42Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;2&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Imageshenrulijieaihexinjishu.png&amp;diff=84</id>
		<title>文件:Imageshenrulijieaihexinjishu.png</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Imageshenrulijieaihexinjishu.png&amp;diff=84"/>
		<updated>2026-02-06T05:42:51Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;embed&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E5%88%86%E7%B1%BB:AI&amp;diff=83</id>
		<title>分类:AI</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E5%88%86%E7%B1%BB:AI&amp;diff=83"/>
		<updated>2026-02-06T05:38:30Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Transformer架构如何驱动现代大语言模型：深入解析AI核心技术]]&lt;br /&gt;
&lt;br /&gt;
[[大语言模型评估指南]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E9%A6%96%E9%A1%B5&amp;diff=82</id>
		<title>首页</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E9%A6%96%E9%A1%B5&amp;diff=82"/>
		<updated>2026-01-17T14:07:27Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[分类:Kivy]]&lt;br /&gt;
[[分类:C/C++]]&lt;br /&gt;
[[分类:Linux操作系统]]&lt;br /&gt;
[[分类:算法]]&lt;br /&gt;
&lt;br /&gt;
[[大语言模型评估指南]]&lt;br /&gt;
&lt;br /&gt;
[[谷歌的张量处理器（TPU）是如何工作的？]]&lt;br /&gt;
&lt;br /&gt;
[[动手做系列：使用Apache2服务器，通过Let&#039;s Encrypt申请网站免费https证书]]&lt;br /&gt;
&lt;br /&gt;
[[编写一个TCP/IP栈3-TCP基础与握手|动手做系列：编写一个TCP/IP栈3-TCP基础与握手]]&lt;br /&gt;
&lt;br /&gt;
[[编写一个TCP/IP栈2-IPv4和ICMPv4|动手做系列：编写一个TCP/IP栈2-IPv4和ICMPv4]]&lt;br /&gt;
&lt;br /&gt;
[[编写一个TCP/IP栈1-以太网和ARP|动手做系列：编写一个TCP/IP栈1-以太网和ARP]]&lt;br /&gt;
&lt;br /&gt;
[[构建自己的区块链|动手做系列：构建自己的区块链]]&lt;br /&gt;
&lt;br /&gt;
[[500行代码构建自己的数据库 DBDB|动手做系列：500行代码构建自己的数据库 DBDB: Dog Bed Database]]&lt;br /&gt;
[[分类:Web3]]&lt;br /&gt;
[[分类:动手做系列]]&lt;br /&gt;
[[分类:资讯]]&lt;br /&gt;
[[分类:AI]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E5%A4%A7%E8%AF%AD%E8%A8%80%E6%A8%A1%E5%9E%8B%E8%AF%84%E4%BC%B0%E6%8C%87%E5%8D%97&amp;diff=81</id>
		<title>大语言模型评估指南</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E5%A4%A7%E8%AF%AD%E8%A8%80%E6%A8%A1%E5%9E%8B%E8%AF%84%E4%BC%B0%E6%8C%87%E5%8D%97&amp;diff=81"/>
		<updated>2026-01-17T14:06:29Z</updated>

		<summary type="html">&lt;p&gt;Admin：​创建页面，内容为“大型语言模型（LLM）已以惊人的速度从研究实验室走向生产应用。开发人员正在将其应用于各种领域，从客户支持聊天机器人到代码生成工具，再到内容创作系统。然而，这种快速普及带来了一个重要问题：我们如何知道我们的LLM是否真的有效？  与传统软件不同，传统软件可以通过编写单元测试来检查确切的输出，而逻辑学习模型（LLM）是概率系统…”&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;大型语言模型（LLM）已以惊人的速度从研究实验室走向生产应用。开发人员正在将其应用于各种领域，从客户支持聊天机器人到代码生成工具，再到内容创作系统。然而，这种快速普及带来了一个重要问题：我们如何知道我们的LLM是否真的有效？&lt;br /&gt;
&lt;br /&gt;
与传统软件不同，传统软件可以通过编写单元测试来检查确切的输出，而逻辑学习模型（LLM）是概率系统。即使提出同一个问题两次，模型也可能给出不同的答案，而这两个答案都可能完全有效。这种不确定性使得评估充满挑战，但又绝对必要。&lt;br /&gt;
[[文件:Llm-evaluation-1.png|居中|无框|633x633像素]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
这就是“评估”发挥作用的地方。评估是评价的简称，它是我们用来衡量LLM性能的系统方法。如果没有适当的评估，我们就如同盲人摸象，无法知道最新的提示更改是让情况更好了还是更糟了，我们的模型是否已准备好投入生产，以及它是否能正确处理边界情况。&lt;br /&gt;
&lt;br /&gt;
在本文中，我们将探讨为什么LLM评估具有挑战性，可用的不同评估类型，需要理解的关键概念，以及建立评估流程的实用指导。&lt;br /&gt;
&lt;br /&gt;
== 为什么LLM评估具有挑战性 ==&lt;br /&gt;
如果我们习惯于测试传统软件，LLM 评估会给我们带来截然不同的体验。在传统编程中，我们编写一个函数，该函数接收输入并产生确定性的输出。测试过程也很简单。给定输入 X，我们预期输出 Y。如果得到 Y，则测试通过；否则，测试失败。&lt;br /&gt;
&lt;br /&gt;
LLMs 在几个方面打破了这种模式。&lt;br /&gt;
&lt;br /&gt;
* 首先，语言本身就具有主观性。什么样的回答才算“好”？有的回答简洁明了，有的则全面详尽。根据语境的不同，两者都可能恰当。与检查函数是否返回数字 42 不同，判断一段文字的质量需要细致入微的考量。&lt;br /&gt;
* 其次，大多数问题或提示都有多个有效答案。例如，如果我们要求语言学习模型（LLM）总结一篇文章，那么有无数种正确的总结方法。即使模型能够生成优秀的摘要，如果评估方法仅仅检查文本是否完全匹配，也会失败。&lt;br /&gt;
* 第三，语言具有很强的语境依赖性。同样的词语在不同的语境下可能意味着不同的东西。讽刺、幽默、文化典故和隐含意义都增加了语言的复杂性，而简单的模式匹配无法捕捉到这些复杂性。&lt;br /&gt;
* 最后，令人印象深刻的演示和稳定的生产性能之间存在显著差距。LLM 或许能够完美处理我们精心设计的测试用例，但却难以应对真实用户提供的混乱且不可预测的输入。&lt;br /&gt;
&lt;br /&gt;
传统的软件测试方法，例如单元测试和集成测试，对于我们LLM模型的代码仍然很有价值，但它们并不能完全用于评估模型的语言理解和生成能力。我们需要不同的工具和框架来应对这一新挑战。&lt;br /&gt;
&lt;br /&gt;
== LLM评估类型 ==&lt;br /&gt;
在评估LLM时，我们有几种方法可供选择，每种方法都有不同的优势和不足。让我们来探讨一下主要类别。&lt;br /&gt;
&lt;br /&gt;
=== 自动评估 ===&lt;br /&gt;
自动评估是指无需人工干预即可运行的程序化评估。&lt;br /&gt;
&lt;br /&gt;
最简单的形式是精确匹配，即检查模型的输出是否与预期字符串完全匹配。这种方法适用于结构化输出（例如 JSON）或确实只有一个正确答案的情况，但对于大多数自然语言处理任务来说过于死板。&lt;br /&gt;
&lt;br /&gt;
关键词匹配稍微灵活一些。我们会检查输出结果是否包含某些必需的关键词或短语，而无需完全匹配。这样既能捕捉到一些变化，又能保证结果的确定性，而且易于实现。&lt;br /&gt;
&lt;br /&gt;
语义相似度衡量的是模型输出与参考答案在意义上的接近程度，即使词语有所不同。这类指标通常使用词嵌入模型来比较语义内容，而非文本表面含义。&lt;br /&gt;
&lt;br /&gt;
一种日益流行的评估方法是基于模型的评估，即使用另一个逻辑逻辑模型（LLM）作为评判者。在这种方法中，我们可以让像 GPT-4 或 Claude 这样强大的模型，根据诸如实用性、准确性或相关性等标准，对目标模型的输出进行评分。这种方法可以捕捉到简单指标无法捕捉到的细微差别，但它也引入了自身的复杂性。&lt;br /&gt;
&lt;br /&gt;
请看下图：&lt;br /&gt;
[[文件:Llm-evaluation-img2.png|居中|无框|762x762像素]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
自动评估在我们需要发现明显的错误、运行回归测试以确保更改不会破坏现有功能或快速迭代提示时表现出色。然而，它们可能会忽略一些只有人工判断才能发现的细微问题。&lt;br /&gt;
&lt;br /&gt;
=== 人工评价 ===&lt;br /&gt;
尽管自动化测试取得了进步，但人工评估仍然是衡量学习领导力（LLM）表现各个细微方面的黄金标准。人类能够判断语气、恰当性、实用性以及回答是否真正回应了问题的根本意图等主观因素。&lt;br /&gt;
&lt;br /&gt;
人工评价有多种形式。在偏好排序中，评价者比较多个结果并选择他们更偏好的结果。李克特量表要求评分者根据不同维度，用数值量表对结果进行评分。任务完成度评价则检验结果是否达到了特定目标。&lt;br /&gt;
&lt;br /&gt;
人工评估的主要权衡之处在于成本和速度与准确性之间的取舍。高质量的人工评分成本高昂且耗时，但对于许多应用而言，这是真正验证性能的唯一途径。例如，当我们处理主观性较强的任务、安全关键型应用或需要验证自动评估结果时，人工评估就显得至关重要。&lt;br /&gt;
&lt;br /&gt;
=== 基于基准的评估 ===&lt;br /&gt;
机器学习研究界已经开发出用于评估语言学习模型的标准化基准数据集。这些数据集包括用于通用知识的 MMLU（大规模多任务语言理解）、用于常识推理的 HellaSwag 以及用于代码生成的 HumanEval。&lt;br /&gt;
&lt;br /&gt;
基准测试的优势在于可比性。我们可以了解我们的模型与其他模型相比如何，并利用既定的基准来跟踪进展。它们还提供了涵盖各种场景的现成测试集。&lt;br /&gt;
&lt;br /&gt;
然而，基准测试存在局限性。它们可能无法反映我们的具体用例。在学术基准测试中得分很高的模型，在我们的客户支持应用程序中可能仍然表现不佳。此外，随着基准测试的广泛传播，模型可能会被专门针对这些基准测试进行优化，而不是针对通用功能进行优化。&lt;br /&gt;
&lt;br /&gt;
== LLM评估中的关键概念 ==&lt;br /&gt;
要构建有效的评估体系，我们需要理解几个核心概念：&lt;br /&gt;
&lt;br /&gt;
=== 评估指标 ===&lt;br /&gt;
不同的任务需要不同的评价指标。对于分类任务，我们可以使用准确率或 F1 分数。对于文本生成，BLEU 和 ROUGE 等指标衡量文本与参考文本的重叠度，但它们也存在一些已知的局限性。对于代码生成，我们可以检查代码是否正确执行并产生预期的输出。&lt;br /&gt;
&lt;br /&gt;
除了特定任务的指标之外，我们通常还关注贯穿各个任务的质量维度。&lt;br /&gt;
&lt;br /&gt;
* 输出与输入相关吗？&lt;br /&gt;
* 它是否逻辑清晰、结构严谨？它的事实是否准确？&lt;br /&gt;
* 对用户有帮助吗？&lt;br /&gt;
* 它是否避免有害内容？&lt;br /&gt;
&lt;br /&gt;
=== 评估数据集 ===&lt;br /&gt;
我们的评估质量很大程度上取决于测试数据集的质量。我们需要能够代表真实使用场景、足够多样化以涵盖不同应用场景，并且包含模型可能失效的极端情况的测试用例。&lt;br /&gt;
&lt;br /&gt;
一个常见的陷阱是数据污染，即测试样本与模型的训练数据重叠。这会导致模型在全新输入数据上的性能看起来比实际更好。使用预留数据或创建新的测试用例有助于避免这个问题。&lt;br /&gt;
&lt;br /&gt;
=== 统计学考量 ===&lt;br /&gt;
由于LLM的输出结果可能因运行而异（尤其是在较高温度设置下），我们需要从统计学的角度进行评估。单次测试结果可能不具有代表性。样本量至关重要，因为仅测试十个样本的置信度远低于测试一千个样本。&lt;br /&gt;
&lt;br /&gt;
我们还需要考虑模型输出的差异。多次运行相同的提示并取平均值可以让我们更稳定地了解模型的性能。理解并控制温度、top-p 值和随机种子等参数有助于提高评估结果的可复现性。&lt;br /&gt;
&lt;br /&gt;
== 建立评估流程 ==&lt;br /&gt;
以下是构建评估流程的一种实用方法。&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;针对我们的用例，如何定义成功：&#039;&#039;&#039;对于我们特定的应用来说，“好”意味着什么？如果我们正在构建一个客户支持机器人，那么“好”可能意味着准确回答问题、保持友好的语气，并在适当的时候转接给人工客服。&lt;br /&gt;
* &#039;&#039;&#039;创建初始评估集&#039;&#039;&#039;：先从 50-100 个涵盖常见情况、极端情况和已知故障模式的多样化示例入手。我们不需要成千上万个示例就能开始获得价值。&lt;br /&gt;
* &#039;&#039;&#039;选择我们的评估方法：&#039;&#039;&#039;如果资源有限，先采用自动评估。如果质量至关重要且预算充足，则加入人工评估。通常，混合方法效果最佳，即先使用自动评估进行广泛覆盖并快速迭代，最后用人工评估进行最终验证。&lt;br /&gt;
* &#039;&#039;&#039;建立迭代周期：&#039;&#039;&#039;运行评估，找出模型的不足之处，进行改进（更好的提示、不同的模型、微调等），然后重新评估。我们正是通过这个周期逐步提高性能。&lt;br /&gt;
* &#039;&#039;&#039;跟踪性能变化：&#039;&#039;&#039;记录不同版本的评估分数。这有助于我们了解更改是否有效，以及是否能防止性能下降。&lt;br /&gt;
* &#039;&#039;&#039;对所有内容进行版本控制：&#039;&#039;&#039;记录每个结果对应的模型版本、提示符版本和评估数据集版本。这大大简化了调试和复现过程。&lt;br /&gt;
&lt;br /&gt;
关键在于从简单的入手，不断迭代。不要等待完美的评估设置。一个定期运行的基础评估程序，其价值远远高于一个从未实现的复杂评估程序。&lt;br /&gt;
[[文件:Llm-evalution3-img3.png|居中|无框|530x530像素]]&lt;br /&gt;
&lt;br /&gt;
== 常见误区和最佳实践 ==&lt;br /&gt;
在建立评估实践的过程中，最好注意以下这些常见错误：&lt;br /&gt;
&lt;br /&gt;
* 对评估集过度拟合是一个真实存在的风险。如果我们反复使用相同的测试用例进行优化，可能会提高模型得分，但实际性能却没有提升。定期更新评估集，添加新的测试用例，有助于避免这种情况。&lt;br /&gt;
* 我们还可能陷入操纵指标的陷阱。仅仅因为某个模型在特定指标上得分高，并不意味着它实际上更好。务必将定量指标与对实际输出的定性评估结合起来。&lt;br /&gt;
* 许多团队忽略了极端情况和对抗性示例。真实用户总会找到我们意想不到的系统漏洞。主动寻找并测试这些棘手案例，能使我们的评估更加可靠。&lt;br /&gt;
* 另一方面，仅仅依靠感觉和轶事是有问题的。人的直觉固然宝贵，但也可能误导人。系统性的评估能够为我们提供数据，从而做出明智的决策。&lt;br /&gt;
* 或许最大的陷阱就是完全不做评估。在急于发布功能的过程中，评估往往被忽视。但如果不进行评估就发布，我们就根本不知道我们是在改进还是在恶化产品。&lt;br /&gt;
&lt;br /&gt;
最佳实践是维护一个多样化且不断演进的评估套件，使其与我们的产品共同成长。随着我们发现新的故障模式或扩展到新的用例，可以将其添加到评估套件中。&lt;br /&gt;
&lt;br /&gt;
== 结论 ==&lt;br /&gt;
LLM评估是一个持续的过程，应该融入到我们的开发工作流程中。正如我们不会在没有测试的情况下发布传统软件一样，我们也不应该在没有进行适当评估的情况下部署LLM应用程序。&lt;br /&gt;
&lt;br /&gt;
良好的评估让我们更有信心快速迭代并安全部署。它们帮助我们了解哪些有效、哪些无效，同时提供客观的衡量标准来比较不同的方法。它们甚至能在用户发现问题之前就发现回归错误。&lt;br /&gt;
&lt;br /&gt;
好消息是，我们不需要一开始就搭建复杂的系统。先从少量测试用例和基本指标入手，定期运行评估，并密切关注失败案例。随着我们对应用程序需求的了解不断加深，逐步扩展和完善评估套件。&lt;br /&gt;
&lt;br /&gt;
学习领导力模型（LLM）评估领域仍在不断发展，新的工具、框架和最佳实践层出不穷。但其基本原则始终不变：不进行测量就无法改进。通过将评估纳入LLM开发流程的核心环节，我们可以将原本可能只是猜测的事情转化为切实可行的方案。&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Llm-evalution3-img3.png&amp;diff=80</id>
		<title>文件:Llm-evalution3-img3.png</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Llm-evalution3-img3.png&amp;diff=80"/>
		<updated>2026-01-17T14:05:59Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;llm大语言模型评估3-图片&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Llm-evaluation-img2.png&amp;diff=79</id>
		<title>文件:Llm-evaluation-img2.png</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Llm-evaluation-img2.png&amp;diff=79"/>
		<updated>2026-01-17T14:01:05Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;大语言评估模型img2&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Llm-evaluation-1.png&amp;diff=78</id>
		<title>文件:Llm-evaluation-1.png</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E6%96%87%E4%BB%B6:Llm-evaluation-1.png&amp;diff=78"/>
		<updated>2026-01-17T13:53:38Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;llm评估指南1&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E5%88%86%E7%B1%BB:AI&amp;diff=77</id>
		<title>分类:AI</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E5%88%86%E7%B1%BB:AI&amp;diff=77"/>
		<updated>2026-01-17T13:51:20Z</updated>

		<summary type="html">&lt;p&gt;Admin：​创建页面，内容为“大语言模型评估指南”&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[大语言模型评估指南]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E9%A6%96%E9%A1%B5&amp;diff=76</id>
		<title>首页</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E9%A6%96%E9%A1%B5&amp;diff=76"/>
		<updated>2026-01-17T13:49:51Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[分类:Kivy]]&lt;br /&gt;
[[分类:C/C++]]&lt;br /&gt;
[[分类:Linux操作系统]]&lt;br /&gt;
[[分类:算法]]&lt;br /&gt;
&lt;br /&gt;
[[谷歌的张量处理器（TPU）是如何工作的？]]&lt;br /&gt;
&lt;br /&gt;
[[动手做系列：使用Apache2服务器，通过Let&#039;s Encrypt申请网站免费https证书]]&lt;br /&gt;
&lt;br /&gt;
[[编写一个TCP/IP栈3-TCP基础与握手|动手做系列：编写一个TCP/IP栈3-TCP基础与握手]]&lt;br /&gt;
&lt;br /&gt;
[[编写一个TCP/IP栈2-IPv4和ICMPv4|动手做系列：编写一个TCP/IP栈2-IPv4和ICMPv4]]&lt;br /&gt;
&lt;br /&gt;
[[编写一个TCP/IP栈1-以太网和ARP|动手做系列：编写一个TCP/IP栈1-以太网和ARP]]&lt;br /&gt;
&lt;br /&gt;
[[构建自己的区块链|动手做系列：构建自己的区块链]]&lt;br /&gt;
&lt;br /&gt;
[[500行代码构建自己的数据库 DBDB|动手做系列：500行代码构建自己的数据库 DBDB: Dog Bed Database]]&lt;br /&gt;
[[分类:Web3]]&lt;br /&gt;
[[分类:动手做系列]]&lt;br /&gt;
[[分类:资讯]]&lt;br /&gt;
[[分类:AI]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E9%A6%96%E9%A1%B5&amp;diff=75</id>
		<title>首页</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E9%A6%96%E9%A1%B5&amp;diff=75"/>
		<updated>2026-01-17T09:43:38Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[分类:Kivy]]&lt;br /&gt;
[[分类:C/C++]]&lt;br /&gt;
[[分类:Linux操作系统]]&lt;br /&gt;
[[分类:算法]]&lt;br /&gt;
&lt;br /&gt;
[[谷歌的张量处理器（TPU）是如何工作的？]]&lt;br /&gt;
&lt;br /&gt;
[[动手做系列：使用Apache2服务器，通过Let&#039;s Encrypt申请网站免费https证书]]&lt;br /&gt;
&lt;br /&gt;
[[编写一个TCP/IP栈3-TCP基础与握手|动手做系列：编写一个TCP/IP栈3-TCP基础与握手]]&lt;br /&gt;
&lt;br /&gt;
[[编写一个TCP/IP栈2-IPv4和ICMPv4|动手做系列：编写一个TCP/IP栈2-IPv4和ICMPv4]]&lt;br /&gt;
&lt;br /&gt;
[[编写一个TCP/IP栈1-以太网和ARP|动手做系列：编写一个TCP/IP栈1-以太网和ARP]]&lt;br /&gt;
&lt;br /&gt;
[[构建自己的区块链|动手做系列：构建自己的区块链]]&lt;br /&gt;
&lt;br /&gt;
[[500行代码构建自己的数据库 DBDB|动手做系列：500行代码构建自己的数据库 DBDB: Dog Bed Database]]&lt;br /&gt;
[[分类:Web3]]&lt;br /&gt;
[[分类:动手做系列]]&lt;br /&gt;
[[分类:资讯]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E8%B0%B7%E6%AD%8C%E7%9A%84%E5%BC%A0%E9%87%8F%E5%A4%84%E7%90%86%E5%99%A8%EF%BC%88TPU%EF%BC%89%E6%98%AF%E5%A6%82%E4%BD%95%E5%B7%A5%E4%BD%9C%E7%9A%84%EF%BC%9F&amp;diff=74</id>
		<title>谷歌的张量处理器（TPU）是如何工作的？</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E8%B0%B7%E6%AD%8C%E7%9A%84%E5%BC%A0%E9%87%8F%E5%A4%84%E7%90%86%E5%99%A8%EF%BC%88TPU%EF%BC%89%E6%98%AF%E5%A6%82%E4%BD%95%E5%B7%A5%E4%BD%9C%E7%9A%84%EF%BC%9F&amp;diff=74"/>
		<updated>2026-01-17T09:42:19Z</updated>

		<summary type="html">&lt;p&gt;Admin：​/* 脉动阵列：一种不同的计算方法 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;2016年3月，DeepMind的AlphaGo击败围棋世界冠军李世石，这在人工智能领域具有里程碑式的意义。而这场比赛所使用的硬件，谷歌已经投入生产运行一年多，但从未公开承认过。&lt;br /&gt;
&lt;br /&gt;
张量处理单元（TPU）的意义远不止于一款高速芯片。它标志着计算理念的根本性转变：有时少即是多。&lt;br /&gt;
&lt;br /&gt;
自 2015 年以来，谷歌的 TPU 系列芯片已发展了七代，从最初处理图像识别查询的单芯片扩展到如今拥有 9216 个芯片的超级计算机，用于训练目前规模最大的语言模型。本文将探讨谷歌为何要打造定制芯片，以及其工作原理，并揭示他们必须面对的物理限制和工程权衡。 &lt;br /&gt;
&lt;br /&gt;
== 对TPU的需求 ==&lt;br /&gt;
2013年，谷歌的基础设施团队进行了一项计算。如果安卓用户像谷歌预期的那样大规模使用语音搜索，即使每天只使用三分钟，其计算需求也需要谷歌将其全球数据中心的规模扩大一倍。&lt;br /&gt;
&lt;br /&gt;
当时这个问题似乎没有明显的解决方案。建造更多配备传统处理器的数据中心在经济上不可行。更重要的是，摩尔定律多年来一直在放缓。几十年来，半导体行业一直依赖于晶体管密度大约每两年翻一番的观察结果，从而在不改变架构的情况下实现性能的持续提升。然而，到了2013年，这种趋势开始减弱。谷歌不能仅仅等待英特尔的下一代CPU来解决它的问题。&lt;br /&gt;
&lt;br /&gt;
造成这种情况的根本原因在于架构。传统计算机遵循冯·诺依曼架构，其中处理器和内存通过共享总线进行通信。要执行任何计算，CPU 必须先获取指令，然后从内存中检索数据，执行运算，最后将结果写回内存。处理器和内存之间这种持续不断的信息传输，造成了计算机科学家所说的冯·诺依曼瓶颈。  &lt;br /&gt;
[[文件:Image.png|居中|缩略图|480x480像素]]在总线上传输数据所需的能量通常超过计算本身所需的能量。例如，想象一下一位厨师正在准备一道菜，但他必须走到很远的储藏室去取每种食材。烹饪只需几秒钟，但走动却要花费数小时。对于文字处理或网页浏览等通用计算任务来说，这种设计是合理的，因为工作负载是不可预测的。然而，神经网络的情况则不同。&lt;br /&gt;
&lt;br /&gt;
深度学习模型执行的操作几乎全部都是矩阵乘法。神经网络通过将输入数据与学习到的权重矩阵相乘、加上偏置值并应用激活函数来处理信息。对于单个预测，这个过程会重复数十亿次。拥有数千亿个参数的现代语言模型，每次查询都需要数千亿次乘加运算。关键在于，这些运算是可预测的、并行的和确定性的。&lt;br /&gt;
&lt;br /&gt;
CPU 将大量处理能力用于分支预测和乱序执行等功能，旨在处理不可预测的代码。图形处理器 (GPU) 通过数千个核心并行工作改善了这种情况，但它们仍然继承了图形处理方面的架构开销。谷歌的远见卓识在于制造只执行神经网络所需功能的芯片，并去除所有其他功能。&lt;br /&gt;
&lt;br /&gt;
== 脉动阵列：一种不同的计算方法 ==&lt;br /&gt;
TPU 的核心是一种名为脉动阵列的架构。这个名称源自希腊语中“心跳”一词，指的是数据在芯片内有节奏地脉动传输。为了理解这一点的重要性，我们可以思考不同的处理器是如何处理同一任务的。&lt;br /&gt;
&lt;br /&gt;
* CPU 的运行就像一个工人来回奔波于水井和火堆之间，一次只装满一个桶。&lt;br /&gt;
* GPU 部署数千个工作进程同时执行相同的任务。吞吐量增加，但水井和火源之间的流量变得混乱且耗能。&lt;br /&gt;
* 循环式灌溉系统采用了一种截然不同的方法。工人们排成一列，手拉手传递水桶。水在链条中流动，直到工作完成，期间无人返回水源。&lt;br /&gt;
&lt;br /&gt;
在 TPU 中，工作单元是排列成密集网格的简单乘加运算单元。第一代 TPU 使用 256×256 的阵列，这意味着 65,536 个计算器同时运行。计算过程如下：&lt;br /&gt;
&lt;br /&gt;
* 神经网络权重从上方加载到每个计算器中，并保持不变。&lt;br /&gt;
* 输入数据从左侧逐行流入。&lt;br /&gt;
* 数据经过每个计算器时，都会乘以居民体重。&lt;br /&gt;
* 该乘积会累加到累计总和中，然后向右传递给下一个计算器。&lt;br /&gt;
* 部分结果会累积并向下传递。&lt;br /&gt;
* 所有计算完成后，最终结果将从底部得出。&lt;br /&gt;
&lt;br /&gt;
请看下图：&lt;br /&gt;
[[文件:Tpu-2.png|居中|无框|542x542像素]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
这种设计意味着数据只需从内存中读取一次，但在遍历阵列的过程中会被使用数千次。传统处理器几乎每次操作都需要访问内存。而脉动阵列消除了这一瓶颈。数据仅在空间上相邻的计算器之间通过短导线传输，从而显著降低了能耗。&lt;br /&gt;
&lt;br /&gt;
数据有力地证明了这种方法的合理性。&lt;br /&gt;
&lt;br /&gt;
* TPU v1 的 256×256 阵列每个时钟周期可以执行 65536 次乘加运算。在 700 MHz 的运行频率下，它每秒可完成 92 万亿次 8 位运算，而功耗仅为 40 瓦。&lt;br /&gt;
* 现代 GPU 每个周期可能执行数万次运算，而 TPU 则执行数十万次运算。&lt;br /&gt;
* 超过 90% 的硅片执行了有效的计算，而 GPU 中只有大约 30% 的硅片执行了有效的计算。&lt;br /&gt;
&lt;br /&gt;
这里的权衡之处在于绝对的专业化。脉动阵列只能高效地执行矩阵乘法，而无法渲染图形、浏览网页或运行电子表格。谷歌接受了这一限制，因为神经网络推理本质上就是多次重复的矩阵乘法。&lt;br /&gt;
&lt;br /&gt;
== 支持架构 ==&lt;br /&gt;
脉动阵列需要精心协调的辅助组件才能发挥其性能。每个组件都解决了从原始数据到人工智能预测流程中的特定瓶颈。&lt;br /&gt;
[[文件:Tpu-jiagou.png|居中|无框|563x563像素]]&lt;br /&gt;
&lt;br /&gt;
让我们来看看最重要的组成部分：&lt;br /&gt;
&lt;br /&gt;
=== 矩阵乘法单元 ===&lt;br /&gt;
矩阵乘法单元（MXU）就是脉动阵列本身。&lt;br /&gt;
&lt;br /&gt;
TPU v1 使用单个 256×256 数组，处理 8 位整数。后续版本采用 128×128 数组，并使用 Google 的 BFloat16 格式处理训练工作负载，然后在 v6 版本中又回归到 256×256 数组，吞吐量提升了四倍。这种权重固定设计最大限度地减少了数据移动，而数据移动是计算中主要的能耗来源。&lt;br /&gt;
[[文件:Tpu-mutiple-unit.png|居中|无框|663x663像素]]&lt;br /&gt;
&lt;br /&gt;
=== 统一缓冲区 ===&lt;br /&gt;
统一缓冲区提供 24 兆字节的片上 SRAM，作为速度较慢的外部存储器和容量较大的 MXU 之间的高速过渡区域。&lt;br /&gt;
&lt;br /&gt;
该缓冲区存储来自主机的输入激活值、神经网络层之间的中间结果以及传输前的最终输出。由于该存储器直接位于芯片上，因此其带宽高于外部存储器。这种带宽差异对于保持 MXU 持续接收数据至关重要，避免其闲置等待内存访问。&lt;br /&gt;
&lt;br /&gt;
=== 矢量处理单元 ===&lt;br /&gt;
向量处理单元 (VPU) 可以处理 MXU 无法处理的操作，包括 ReLU、sigmoid 和 tanh 等激活函数。&lt;br /&gt;
&lt;br /&gt;
神经网络需要非线性运算来学习复杂的模式。如果没有非线性运算，多层神经网络在数学上就会简化为单一的线性变换。TPU 没有采用软件实现这些功能，而是使用专用的硬件电路在一个周期内计算激活值。数据通常从 MXU 流向 VPU 进行激活值处理，然后再传递到下一层。&lt;br /&gt;
&lt;br /&gt;
=== 累加器 ===&lt;br /&gt;
累加器收集来自 MXU 的 32 位结果。&lt;br /&gt;
&lt;br /&gt;
当 8 位输入相乘时，乘积为 16 位，但累加和会因重复加法而不断增大。使用 32 位累加器可以防止矩阵乘法所需的多次加法运算过程中发生溢出。累加器内存总共占用 4 兆字节，分布在 4096 个向量中，每个向量包含 256 个元素。&lt;br /&gt;
&lt;br /&gt;
=== 重量先进先出缓冲 ===&lt;br /&gt;
权重 FIFO 缓冲区使用称为双缓冲的技术在外部存储器和 MXU 之间暂存权重。&lt;br /&gt;
&lt;br /&gt;
MXU 存储两组权重块：一组正在实时计算，另一组则从内存加载。这种重叠存储方式完全消除了内存延迟，确保计算单元无需等待数据。&lt;br /&gt;
&lt;br /&gt;
=== 高带宽内存 ===&lt;br /&gt;
高带宽内存随着TPU的代际发展而不断演进。&lt;br /&gt;
&lt;br /&gt;
最初的v1版本采用DDR3内存，传输速度为34GB/s。而现代的Ironwood TPU则达到了7.4TB/s，速度提升了217倍。HBM通过将多个DRAM芯片垂直堆叠，并在芯片间建立数千个连接来实现如此高的带宽，这是传统内存封装方式无法实现的。&lt;br /&gt;
&lt;br /&gt;
== 精准优势 ==&lt;br /&gt;
TPU 通过量化显著提升效率，使用比传统浮点运算精度更低的数字。这种选择对硬件有着深远的影响，并波及整个设计。&lt;br /&gt;
&lt;br /&gt;
科学计算通常需要高精度。例如，将圆周率计算到小数点后十位需要精确表示极小的差异。然而，神经网络的运行方式不同。它们计算的是概率和模式。例如，模型预测图像是猫的概率是 85% 还是 85.3472%，对分类结果实际上没有区别。&lt;br /&gt;
&lt;br /&gt;
乘法器电路的硅片面积与位宽的平方成正比。一个 8 位乘法器大约需要 64 个硅片面积单位，而一个 32 位乘法器则需要大约 576 个硅片面积单位。这种数学关系解释了为什么 TPU v1 可以在一块尺寸适中的芯片上集成 65,536 个乘加单元，而 GPU 包含的浮点运算单元数量则少得多。更多的乘法器意味着每个周期可以执行更多的并行运算。&lt;br /&gt;
&lt;br /&gt;
第一代TPU使用8位整数进行推理，与32位浮点数相比，内存需求减少了四倍。一个91兆字节的模型量化后变为23兆字节。研究表明，推理很少需要32位精度。额外的小数位对预测结果几乎没有影响。&lt;br /&gt;
&lt;br /&gt;
由于微小的梯度更新会在数百万次迭代中累积，训练需要更高的精度。谷歌通过发明 BFloat16（即 Brain Floating-Point 16）解决了这个问题。这种格式与 32 位浮点数一样保留了 8 位指数，但尾数仅使用 7 位。其关键在于，神经网络对由指数控制的动态范围比对由尾数控制的精度更为敏感。BFloat16 以一半的位数提供了多种浮点格式，从而实现了高效的训练，避免了其他 16 位格式常见的溢出问题。&lt;br /&gt;
&lt;br /&gt;
请看下图：&lt;br /&gt;
[[文件:Tpu-fp32-16.png|居中|无框|603x603像素]]&lt;br /&gt;
&lt;br /&gt;
现代TPU支持多种精度模式。&lt;br /&gt;
&lt;br /&gt;
* BFloat16 用于训练。&lt;br /&gt;
* 在 TPU v5e 上，INT8 推理的运行速度提高了一倍。&lt;br /&gt;
* 最新的FP8格式。&lt;br /&gt;
&lt;br /&gt;
Ironwood 是首款原生支持 FP8 的 TPU，避免了早期几代产品中的模拟开销。&lt;br /&gt;
&lt;br /&gt;
== 进化之旅 ==&lt;br /&gt;
TPU 的发展遵循着清晰的轨迹。&lt;br /&gt;
&lt;br /&gt;
每一代人工智能都在提升性能的同时提高了能效。这一演变过程揭示了随着模型规模的扩大，人工智能硬件需求是如何变化的。&lt;br /&gt;
&lt;br /&gt;
* TPU v1 于 2015 年秘密发布，专注于推理。它采用 28 纳米制程工艺，功耗仅为 40 瓦，每秒可执行 92 万亿次 8 位运算。该芯片通过 PCIe 连接到标准服务器，并在谷歌以外的任何人知晓其存在之前，就开始为谷歌搜索、照片、翻译和 YouTube 等应用提供技术支持。2016 年 3 月，TPU v1 助力 AlphaGo 战胜李世石，证明专用芯片在速度上可以比通用 GPU 快 15 到 30 倍，在能效上可以快 30 到 80 倍。&lt;br /&gt;
* TPU v2 于 2017 年发布，其架构进行了根本性变革以支持训练。它用两个 128 x 128 的 BFloat16 阵列取代了原有的 256 x 256 8 位阵列，从而实现了训练所需的浮点精度。此外，它还增加了 16 GB、600 GB/s 的高带宽内存，彻底解决了 v1 版本中存在的内存瓶颈问题。更重要的是，v2 引入了芯片间互连技术，这是一种定制的高速链路，可将各个 TPU 直接连接起来。这使得 TPU Pod 成为可能，其中 256 个芯片作为一个独立的加速器运行，可提供 11.5 petaflops 的性能。&lt;br /&gt;
* 2018 年推出的 TPU v3 将性能提升了一倍，单芯片性能达到 420 万亿次浮点运算，并引入了液冷技术以应对更高的功率密度。Pod 的芯片数量扩展到 1024 个，性能超过 100 千万亿次浮点运算，足以在合理的时间范围内训练当时规模最大的 AI 模型。&lt;br /&gt;
* 2021 年发布的 TPU v4 带来了多项创新。SparseCores 技术仅占用芯片面积的 5%，就将推荐系统和语言模型的关键嵌入操作速度提升了 5 到 7 倍。光路交换机实现了动态网络拓扑重构。它不再使用固定电缆，而是利用机械反射镜在光纤间引导光束。这使得互连能够绕过故障，并可扩展至 4,096 个芯片的 Pod，性能接近 1 exaflop。3D 环面拓扑结构中，每个芯片连接到六个相邻芯片而非四个，从而降低了分布式训练的通信延迟。&lt;br /&gt;
* Ironwood（或称 TPU v7）将于 2025 年发布，代表着迄今为止最重大的飞跃。它专为推理时代而设计，在这个时代，大规模部署 AI 比训练更为重要。每颗芯片可提供 4,614 万亿次浮点运算的性能，配备 192 GB 的 HBM 显存，带宽高达 7.4 TB/s。&lt;br /&gt;
&lt;br /&gt;
== 最后 ==&lt;br /&gt;
TPU部署在各种应用中都展现出了实际效果。&lt;br /&gt;
&lt;br /&gt;
作为参考，单个 TPU 每天可处理超过 1 亿张 Google Photos 照片。AlphaFold 团队利用 TPU 解决了困扰人们 50 年的蛋白质折叠难题，并因此荣获 2024 年诺贝尔化学奖。PaLM 是一个拥有 5400 亿个参数的语言模型，在 6144 个 TPU v4 芯片上训练，50 天内硬件利用率达到 57.8%，如此大规模的分布式训练效率令人瞩目。除了 Google 之外，TPU 还为 Anthropic 的 Claude 助手、Midjourney 的图像生成模型以及众多研究突破提供支持。&lt;br /&gt;
&lt;br /&gt;
然而，TPU并非在所有方面都优于GPU。它们在处理大规模语言模型训练和推理、需要大量矩阵运算的CNN和Transformer模型、高吞吐量批量处理以及优先考虑能效的工作负载方面表现出色。另一方面，对于PyTorch原生开发而言，GPU仍然是更好的选择，因为原生开发需要PyTorch/XLA桥接，而这会带来一些不便。小批量处理、混合AI和图形工作负载、多云部署以及快速原型开发通常更适合使用GPU。&lt;br /&gt;
&lt;br /&gt;
TPU 代表着整个行业向特定领域加速器转变的趋势。&lt;br /&gt;
&lt;br /&gt;
通用计算模型（即CPU能够相当流畅地运行任何程序）在工作负载扩展到每次查询数万亿次运算时，就会达到物理极限。而牺牲灵活性以换取效率的专用芯片，则能带来数量级的性能提升，这是任何通用处理器优化都无法比拟的。&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>http://www.anwsome.com//index.php?title=%E8%B0%B7%E6%AD%8C%E7%9A%84%E5%BC%A0%E9%87%8F%E5%A4%84%E7%90%86%E5%99%A8%EF%BC%88TPU%EF%BC%89%E6%98%AF%E5%A6%82%E4%BD%95%E5%B7%A5%E4%BD%9C%E7%9A%84%EF%BC%9F&amp;diff=73</id>
		<title>谷歌的张量处理器（TPU）是如何工作的？</title>
		<link rel="alternate" type="text/html" href="http://www.anwsome.com//index.php?title=%E8%B0%B7%E6%AD%8C%E7%9A%84%E5%BC%A0%E9%87%8F%E5%A4%84%E7%90%86%E5%99%A8%EF%BC%88TPU%EF%BC%89%E6%98%AF%E5%A6%82%E4%BD%95%E5%B7%A5%E4%BD%9C%E7%9A%84%EF%BC%9F&amp;diff=73"/>
		<updated>2026-01-17T09:29:19Z</updated>

		<summary type="html">&lt;p&gt;Admin：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;2016年3月，DeepMind的AlphaGo击败围棋世界冠军李世石，这在人工智能领域具有里程碑式的意义。而这场比赛所使用的硬件，谷歌已经投入生产运行一年多，但从未公开承认过。&lt;br /&gt;
&lt;br /&gt;
张量处理单元（TPU）的意义远不止于一款高速芯片。它标志着计算理念的根本性转变：有时少即是多。&lt;br /&gt;
&lt;br /&gt;
自 2015 年以来，谷歌的 TPU 系列芯片已发展了七代，从最初处理图像识别查询的单芯片扩展到如今拥有 9216 个芯片的超级计算机，用于训练目前规模最大的语言模型。本文将探讨谷歌为何要打造定制芯片，以及其工作原理，并揭示他们必须面对的物理限制和工程权衡。 &lt;br /&gt;
&lt;br /&gt;
== 对TPU的需求 ==&lt;br /&gt;
2013年，谷歌的基础设施团队进行了一项计算。如果安卓用户像谷歌预期的那样大规模使用语音搜索，即使每天只使用三分钟，其计算需求也需要谷歌将其全球数据中心的规模扩大一倍。&lt;br /&gt;
&lt;br /&gt;
当时这个问题似乎没有明显的解决方案。建造更多配备传统处理器的数据中心在经济上不可行。更重要的是，摩尔定律多年来一直在放缓。几十年来，半导体行业一直依赖于晶体管密度大约每两年翻一番的观察结果，从而在不改变架构的情况下实现性能的持续提升。然而，到了2013年，这种趋势开始减弱。谷歌不能仅仅等待英特尔的下一代CPU来解决它的问题。&lt;br /&gt;
&lt;br /&gt;
造成这种情况的根本原因在于架构。传统计算机遵循冯·诺依曼架构，其中处理器和内存通过共享总线进行通信。要执行任何计算，CPU 必须先获取指令，然后从内存中检索数据，执行运算，最后将结果写回内存。处理器和内存之间这种持续不断的信息传输，造成了计算机科学家所说的冯·诺依曼瓶颈。  &lt;br /&gt;
[[文件:Image.png|居中|缩略图|480x480像素]]在总线上传输数据所需的能量通常超过计算本身所需的能量。例如，想象一下一位厨师正在准备一道菜，但他必须走到很远的储藏室去取每种食材。烹饪只需几秒钟，但走动却要花费数小时。对于文字处理或网页浏览等通用计算任务来说，这种设计是合理的，因为工作负载是不可预测的。然而，神经网络的情况则不同。&lt;br /&gt;
&lt;br /&gt;
深度学习模型执行的操作几乎全部都是矩阵乘法。神经网络通过将输入数据与学习到的权重矩阵相乘、加上偏置值并应用激活函数来处理信息。对于单个预测，这个过程会重复数十亿次。拥有数千亿个参数的现代语言模型，每次查询都需要数千亿次乘加运算。关键在于，这些运算是可预测的、并行的和确定性的。&lt;br /&gt;
&lt;br /&gt;
CPU 将大量处理能力用于分支预测和乱序执行等功能，旨在处理不可预测的代码。图形处理器 (GPU) 通过数千个核心并行工作改善了这种情况，但它们仍然继承了图形处理方面的架构开销。谷歌的远见卓识在于制造只执行神经网络所需功能的芯片，并去除所有其他功能。&lt;br /&gt;
&lt;br /&gt;
== 脉动阵列：一种不同的计算方法 ==&lt;br /&gt;
TPU 的核心是一种名为脉动阵列的架构。这个名称源自希腊语中“心跳”一词，指的是数据在芯片内有节奏地脉动传输。为了理解这一点的重要性，我们可以思考不同的处理器是如何处理同一任务的。&lt;br /&gt;
&lt;br /&gt;
* CPU 的运行就像一个工人来回奔波于水井和火堆之间，一次只装满一个桶。&lt;br /&gt;
* GPU 部署数千个工作进程同时执行相同的任务。吞吐量增加，但油井和火源之间的流量变得混乱且耗能。&lt;br /&gt;
* 循环式灌溉系统采用了一种截然不同的方法。工人们排成一列，手拉手传递水桶。水在链条中流动，直到工作完成，期间无人返回水源。&lt;br /&gt;
&lt;br /&gt;
在 TPU 中，工作单元是排列成密集网格的简单乘加运算单元。第一代 TPU 使用 256×256 的阵列，这意味着 65,536 个计算器同时运行。计算过程如下：&lt;br /&gt;
&lt;br /&gt;
* 神经网络权重从上方加载到每个计算器中，并保持不变。&lt;br /&gt;
* 输入数据从左侧逐行流入。&lt;br /&gt;
* 数据经过每个计算器时，都会乘以居民体重。&lt;br /&gt;
* 该乘积会累加到累计总和中，然后向右传递给下一个计算器。&lt;br /&gt;
* 部分结果会累积并向下传递。&lt;br /&gt;
* 所有计算完成后，最终结果将从底部得出。&lt;br /&gt;
&lt;br /&gt;
请看下图：&lt;br /&gt;
[[文件:Tpu-2.png|居中|无框|542x542像素]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
这种设计意味着数据只需从内存中读取一次，但在遍历阵列的过程中会被使用数千次。传统处理器几乎每次操作都需要访问内存。而脉动阵列消除了这一瓶颈。数据仅在空间上相邻的计算器之间通过短导线传输，从而显著降低了能耗。&lt;br /&gt;
&lt;br /&gt;
数据有力地证明了这种方法的合理性。&lt;br /&gt;
&lt;br /&gt;
* TPU v1 的 256×256 阵列每个时钟周期可以执行 65536 次乘加运算。在 700 MHz 的运行频率下，它每秒可完成 92 万亿次 8 位运算，而功耗仅为 40 瓦。&lt;br /&gt;
* 现代 GPU 每个周期可能执行数万次运算，而 TPU 则执行数十万次运算。&lt;br /&gt;
* 超过 90% 的硅片执行了有效的计算，而 GPU 中只有大约 30% 的硅片执行了有效的计算。&lt;br /&gt;
&lt;br /&gt;
这里的权衡之处在于绝对的专业化。脉动阵列只能高效地执行矩阵乘法，而无法渲染图形、浏览网页或运行电子表格。谷歌接受了这一限制，因为神经网络推理本质上就是多次重复的矩阵乘法。&lt;br /&gt;
&lt;br /&gt;
== 支持架构 ==&lt;br /&gt;
脉动阵列需要精心协调的辅助组件才能发挥其性能。每个组件都解决了从原始数据到人工智能预测流程中的特定瓶颈。&lt;br /&gt;
[[文件:Tpu-jiagou.png|居中|无框|563x563像素]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
让我们来看看最重要的组成部分：&lt;br /&gt;
&lt;br /&gt;
=== 矩阵乘法单元 ===&lt;br /&gt;
矩阵乘法单元（MXU）就是脉动阵列本身。&lt;br /&gt;
&lt;br /&gt;
TPU v1 使用单个 256×256 数组，处理 8 位整数。后续版本采用 128×128 数组，并使用 Google 的 BFloat16 格式处理训练工作负载，然后在 v6 版本中又回归到 256×256 数组，吞吐量提升了四倍。这种权重固定设计最大限度地减少了数据移动，而数据移动是计算中主要的能耗来源。&lt;br /&gt;
[[文件:Tpu-mutiple-unit.png|居中|无框|663x663像素]]&lt;br /&gt;
&lt;br /&gt;
=== 统一缓冲区 ===&lt;br /&gt;
统一缓冲区提供 24 兆字节的片上 SRAM，作为速度较慢的外部存储器和容量较大的 MXU 之间的高速过渡区域。&lt;br /&gt;
&lt;br /&gt;
该缓冲区存储来自主机的输入激活值、神经网络层之间的中间结果以及传输前的最终输出。由于该存储器直接位于芯片上，因此其带宽高于外部存储器。这种带宽差异对于保持 MXU 持续接收数据至关重要，避免其闲置等待内存访问。&lt;br /&gt;
&lt;br /&gt;
=== 矢量处理单元 ===&lt;br /&gt;
向量处理单元 (VPU) 可以处理 MXU 无法处理的操作，包括 ReLU、sigmoid 和 tanh 等激活函数。&lt;br /&gt;
&lt;br /&gt;
神经网络需要非线性运算来学习复杂的模式。如果没有非线性运算，多层神经网络在数学上就会简化为单一的线性变换。TPU 没有采用软件实现这些功能，而是使用专用的硬件电路在一个周期内计算激活值。数据通常从 MXU 流向 VPU 进行激活值处理，然后再传递到下一层。&lt;br /&gt;
&lt;br /&gt;
=== 累加器 ===&lt;br /&gt;
累加器收集来自 MXU 的 32 位结果。&lt;br /&gt;
&lt;br /&gt;
当 8 位输入相乘时，乘积为 16 位，但累加和会因重复加法而不断增大。使用 32 位累加器可以防止矩阵乘法所需的多次加法运算过程中发生溢出。累加器内存总共占用 4 兆字节，分布在 4096 个向量中，每个向量包含 256 个元素。&lt;br /&gt;
&lt;br /&gt;
=== 重量先进先出缓冲 ===&lt;br /&gt;
权重 FIFO 缓冲区使用称为双缓冲的技术在外部存储器和 MXU 之间暂存权重。&lt;br /&gt;
&lt;br /&gt;
MXU 存储两组权重块：一组正在实时计算，另一组则从内存加载。这种重叠存储方式完全消除了内存延迟，确保计算单元无需等待数据。&lt;br /&gt;
&lt;br /&gt;
=== 高带宽内存 ===&lt;br /&gt;
高带宽内存随着TPU的代际发展而不断演进。&lt;br /&gt;
&lt;br /&gt;
最初的v1版本采用DDR3内存，传输速度为34GB/s。而现代的Ironwood TPU则达到了7.4TB/s，速度提升了217倍。HBM通过将多个DRAM芯片垂直堆叠，并在芯片间建立数千个连接来实现如此高的带宽，这是传统内存封装方式无法实现的。&lt;br /&gt;
&lt;br /&gt;
== 精准优势 ==&lt;br /&gt;
TPU 通过量化显著提升效率，使用比传统浮点运算精度更低的数字。这种选择对硬件有着深远的影响，并波及整个设计。&lt;br /&gt;
&lt;br /&gt;
科学计算通常需要高精度。例如，将圆周率计算到小数点后十位需要精确表示极小的差异。然而，神经网络的运行方式不同。它们计算的是概率和模式。例如，模型预测图像是猫的概率是 85% 还是 85.3472%，对分类结果实际上没有区别。&lt;br /&gt;
&lt;br /&gt;
乘法器电路的硅片面积与位宽的平方成正比。一个 8 位乘法器大约需要 64 个硅片面积单位，而一个 32 位乘法器则需要大约 576 个硅片面积单位。这种数学关系解释了为什么 TPU v1 可以在一块尺寸适中的芯片上集成 65,536 个乘加单元，而 GPU 包含的浮点运算单元数量则少得多。更多的乘法器意味着每个周期可以执行更多的并行运算。&lt;br /&gt;
&lt;br /&gt;
第一代TPU使用8位整数进行推理，与32位浮点数相比，内存需求减少了四倍。一个91兆字节的模型量化后变为23兆字节。研究表明，推理很少需要32位精度。额外的小数位对预测结果几乎没有影响。&lt;br /&gt;
&lt;br /&gt;
由于微小的梯度更新会在数百万次迭代中累积，训练需要更高的精度。谷歌通过发明 BFloat16（即 Brain Floating-Point 16）解决了这个问题。这种格式与 32 位浮点数一样保留了 8 位指数，但尾数仅使用 7 位。其关键在于，神经网络对由指数控制的动态范围比对由尾数控制的精度更为敏感。BFloat16 以一半的位数提供了多种浮点格式，从而实现了高效的训练，避免了其他 16 位格式常见的溢出问题。&lt;br /&gt;
&lt;br /&gt;
请看下图：&lt;br /&gt;
[[文件:Tpu-fp32-16.png|居中|无框|603x603像素]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
现代TPU支持多种精度模式。&lt;br /&gt;
&lt;br /&gt;
* BFloat16 用于训练。&lt;br /&gt;
* 在 TPU v5e 上，INT8 推理的运行速度提高了一倍。&lt;br /&gt;
* 最新的FP8格式。&lt;br /&gt;
&lt;br /&gt;
Ironwood 是首款原生支持 FP8 的 TPU，避免了早期几代产品中的模拟开销。&lt;br /&gt;
&lt;br /&gt;
== 进化之旅 ==&lt;br /&gt;
TPU 的发展遵循着清晰的轨迹。&lt;br /&gt;
&lt;br /&gt;
每一代人工智能都在提升性能的同时提高了能效。这一演变过程揭示了随着模型规模的扩大，人工智能硬件需求是如何变化的。&lt;br /&gt;
&lt;br /&gt;
* TPU v1 于 2015 年秘密发布，专注于推理。它采用 28 纳米制程工艺，功耗仅为 40 瓦，每秒可执行 92 万亿次 8 位运算。该芯片通过 PCIe 连接到标准服务器，并在谷歌以外的任何人知晓其存在之前，就开始为谷歌搜索、照片、翻译和 YouTube 等应用提供技术支持。2016 年 3 月，TPU v1 助力 AlphaGo 战胜李世石，证明专用芯片在速度上可以比通用 GPU 快 15 到 30 倍，在能效上可以快 30 到 80 倍。&lt;br /&gt;
* TPU v2 于 2017 年发布，其架构进行了根本性变革以支持训练。它用两个 128 x 128 的 BFloat16 阵列取代了原有的 256 x 256 8 位阵列，从而实现了训练所需的浮点精度。此外，它还增加了 16 GB、600 GB/s 的高带宽内存，彻底解决了 v1 版本中存在的内存瓶颈问题。更重要的是，v2 引入了芯片间互连技术，这是一种定制的高速链路，可将各个 TPU 直接连接起来。这使得 TPU Pod 成为可能，其中 256 个芯片作为一个独立的加速器运行，可提供 11.5 petaflops 的性能。&lt;br /&gt;
* 2018 年推出的 TPU v3 将性能提升了一倍，单芯片性能达到 420 万亿次浮点运算，并引入了液冷技术以应对更高的功率密度。Pod 的芯片数量扩展到 1024 个，性能超过 100 千万亿次浮点运算，足以在合理的时间范围内训练当时规模最大的 AI 模型。&lt;br /&gt;
* 2021 年发布的 TPU v4 带来了多项创新。SparseCores 技术仅占用芯片面积的 5%，就将推荐系统和语言模型的关键嵌入操作速度提升了 5 到 7 倍。光路交换机实现了动态网络拓扑重构。它不再使用固定电缆，而是利用机械反射镜在光纤间引导光束。这使得互连能够绕过故障，并可扩展至 4,096 个芯片的 Pod，性能接近 1 exaflop。3D 环面拓扑结构中，每个芯片连接到六个相邻芯片而非四个，从而降低了分布式训练的通信延迟。&lt;br /&gt;
* Ironwood（或称 TPU v7）将于 2025 年发布，代表着迄今为止最重大的飞跃。它专为推理时代而设计，在这个时代，大规模部署 AI 比训练更为重要。每颗芯片可提供 4,614 万亿次浮点运算的性能，配备 192 GB 的 HBM 显存，带宽高达 7.4 TB/s。&lt;br /&gt;
&lt;br /&gt;
== 结论 ==&lt;br /&gt;
TPU部署在各种应用中都展现出了实际效果。&lt;br /&gt;
&lt;br /&gt;
作为参考，单个 TPU 每天可处理超过 1 亿张 Google Photos 照片。AlphaFold 团队利用 TPU 解决了困扰人们 50 年的蛋白质折叠难题，并因此荣获 2024 年诺贝尔化学奖。PaLM 是一个拥有 5400 亿个参数的语言模型，在 6144 个 TPU v4 芯片上训练，50 天内硬件利用率达到 57.8%，如此大规模的分布式训练效率令人瞩目。除了 Google 之外，TPU 还为 Anthropic 的 Claude 助手、Midjourney 的图像生成模型以及众多研究突破提供支持。&lt;br /&gt;
&lt;br /&gt;
然而，TPU并非在所有方面都优于GPU。它们在处理大规模语言模型训练和推理、需要大量矩阵运算的CNN和Transformer模型、高吞吐量批量处理以及优先考虑能效的工作负载方面表现出色。另一方面，对于PyTorch原生开发而言，GPU仍然是更好的选择，因为原生开发需要PyTorch/XLA桥接，而这会带来一些不便。小批量处理、混合AI和图形工作负载、多云部署以及快速原型开发通常更适合使用GPU。&lt;br /&gt;
&lt;br /&gt;
TPU 代表着整个行业向特定领域加速器转变的趋势。&lt;br /&gt;
&lt;br /&gt;
通用计算模型（即CPU能够相当流畅地运行任何程序）在工作负载扩展到每次查询数万亿次运算时，就会达到物理极限。而牺牲灵活性以换取效率的专用芯片，则能带来数量级的性能提升，这是任何通用处理器优化都无法比拟的。&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
</feed>