03-模块一-全景认知 第03讲-架构决策为什么不能交给 AI - 人类判断力的不可替代性

2 阅读13分钟

模块一-全景认知 | 第03讲:架构决策为什么不能交给 AI - 人类判断力的不可替代性


开场:如果 AI 能解释 CAP,为什么你还不能把它踢出架构评审?

有一个在团队里反复出现的「聪明误会」:某人让大模型解释 CAP、BASE、两阶段提交、Outbox 模式,模型回答得头头是道,于是得出结论——架构这件事已经可以外包给 AI 了。随后在一次关键评审里,AI 给出了一份看似均衡的方案:加缓存、加消息队列、加读写分离、再加一个搜索索引。每个单点听起来都合理,拼在一起却可能让运维复杂度、成本曲线与故障爆炸半径同步失控。

本讲要澄清一个边界:AI 擅长生产与解释模式(pattern),人类擅长在约束条件下做不可逆选择(decision)。架构决策之所以难,不在于「懂不懂名词」,而在于你是否掌握 业务上下文、组织能力与风险接受度,并愿意为结果负责。

我们会用真实世界里常见的决策类型说明 AI 为什么容易「错得自信」,并引入一个贯穿本课程工程实践的概念:概率性外壳问题——LLM 的输出本质是概率性生成,而线上系统的大部分关键属性必须确定性满足。最后,我们会把 Clean Architecture 重新表述为:在概率性执行周围构建确定性边界,并解释 CodeSentinel 为何要把人类裁决与规则门禁放在中心位置。


全局视角:AI 的能力边界不是「智商边界」,而是「责任边界」

从「问答正确」到「决策正确」:中间隔着一整条组织链

当你问 AI「什么是幂等」,它往往能答对;但当你问「我们这次改动要不要保证强一致性」,正确答案取决于:

  • 业务是否能接受短暂不一致的用户体验
  • 财务/合规是否要求强审计
  • 团队是否能运维得住相应的基础设施
  • 当前阶段是验证期还是规模化期

这些信息通常分散在产品经理、法务、财务、SRE 与业务负责人的脑子里,并不在代码仓库的上下文窗口里。因此,AI 很容易用「通用最佳实践」填补缺失上下文,而通用最佳实践在特定公司里常常是错的。

Mermaid:AI 与人类在软件生命周期中的分工(全局)

flowchart TB
  subgraph AIStrong["AI 更强:高带宽模式任务"]
    A1[代码生成与改写]
    A2[测试样例与脚手架]
    A3[文档草稿与知识摘要]
    A4[静态缺陷模式识别辅助]
    A5[检索增强的规范对照(在证据充分时)]
  end

  subgraph HumanStrong["人类更强:不可逆权衡"]
    H1[业务目标与优先级]
    H2[风险接受度与合规]
    H3[组织协作与政治成本]
    H4[长期演进与迁移策略]
    H5[最终合入裁决与责任承担]
  end

  subgraph CodeSentinel["CodeSentinel:把分工产品化"]
    C1[规则引擎:确定性门禁]
    C2[LLM:语义审计(带引用与校验)]
    C3[报告:证据链 + 待裁决项]
    C4[看板:债务与趋势度量]
  end

  AIStrong --> C2
  HumanStrong --> H5
  C1 --> C3
  C2 --> C3
  C3 --> H5
  C4 --> HumanStrong

Mermaid:何时用 AI、何时必须人类裁决(决策树)

flowchart TD
  Start([遇到一个架构/质量问题]) --> Q1{是否有明确可执行规则?}
  Q1 -->|是| R1[优先静态规则/自动化门禁]
  Q1 -->|否| Q2{是否缺少关键业务上下文?}
  Q2 -->|是| H1[人类补齐上下文与目标函数]
  Q2 -->|否| Q3{失败后果是否高且不可逆?}
  Q3 -->|是| H2[人类做权衡并留ADR证据]
  Q3 -->|否| Q4{是否需要创造性探索多种方案?}
  Q4 -->|是| A1[AI生成方案草案+对比表]
  A1 --> H3[人类选方案并定义约束]
  Q4 -->|否| A2[AI辅助实现/审计]
  A2 --> R2[输出结构化findings]
  R2 --> H4[人类最终裁决合入]

核心知识点:AI 擅长什么(把它用对地方)

1)模式匹配与局部重构

在明确的文件、明确的函数、明确的风格指南下,AI 能快速完成重复性高、模式清晰的工作,例如:

  • 把一组类迁移到新的包结构(在规则清晰时)
  • 按统一模板补全异常处理与日志字段
  • 生成与接口契约一致的 stub 测试

2)代码生成与「从 0 到可运行」的加速

对原型系统、内部工具、数据管道脚本,AI 能显著缩短路径。但要注意:可运行 ≠ 可维护 ≠ 安全

3)缺陷模式的辅助发现(在提供足够上下文时)

例如:明显的 SQL 拼接、敏感信息打印、不安全的临时文件写入。这里的关键词是 辅助:它应当作为 CodeSentinel 的一个信号源,而不是唯一真理。

4)文档化与知识压缩

把冗长讨论压缩成 ADR 草案、把复杂模块生成阅读笔记,能提升团队带宽。但要警惕 幻觉型引用:需要 RAG 与人工核对。


核心知识点:AI 不擅长什么(这些正是架构师阵地)

1)权衡分析(trade-off):不是计算题,是价值判断

典型权衡包括:

  • 一致性 vs 可用性 vs 延迟
  • 成本 vs 性能 vs 交付速度
  • 可维护性 vs 短期功能冲刺
  • 安全默认 vs 业务摩擦

AI 可以列出表格,但 无法替你回答「我们此刻更在乎什么」

2)业务语境:同一技术选择在不同商业模式下完全相反

举例:一个内容平台与一个金融支付系统在「最终一致性容忍度」上可能截然相反。模型若缺失语境,会倾向输出「中庸方案」,而中庸往往意味着 复杂度上升但关键属性不突出

3)长期演进规划:涉及迁移、组织节奏与学习能力

架构决策必须考虑:

  • 团队是否能掌握新栈
  • 是否有培训与值班体系
  • 是否存在历史包袱与迁移窗口

AI 很难准确获取这些「软约束」,除非你把它们结构化写进规范库——这又回到了人类治理。

4)组织动态:谁支持、谁反对、如何推进

技术里最难的部分经常是人:推动规则落地、处理例外、协调多团队接口。这不是 LLM 的强项。


核心知识点:真实案例切片——AI 很容易「错得自信」的架构决策

说明:以下案例为教学合成,来源于常见工程模式与公开讨论中反复出现的失误类型,不指向特定公司。

案例 A:为「性能」引入分布式缓存,却扩大了一致命名空间

团队遇到读多写少瓶颈,AI 建议加 Redis 缓存。实现上却把 用户会话、权限、业务实体 混在同一 key 命名体系里,TTL 策略不一致,导致偶发 读到过期权限 的事故。架构师本应先定义:

  • 缓存对象的 一致性模型
  • key 规范与 失效策略
  • 命中失败时的 降级路径

AI 能给代码,但很难自动推导出你们公司对「安全默认」的底线。

案例 B:微服务拆分「看起来很专业」,实际形成分布式单体

AI 按领域名词生成了多个服务,但共享数据库、共享库版本、同步链式调用一样不少。结果是:发布仍要协调、故障仍互相牵连,复杂度却上升。人类架构师需要判断拆分是否满足:

  • 独立部署
  • 独立扩展
  • 故障隔离
  • 团队边界匹配

案例 C:技术债务「先合并再重构」滚雪球

AI 倾向于给出最短路径补丁让测试通过,这在高压迭代里很受欢迎。但累积的临时方案如果没有 债务台账与偿还节奏,会在六个月后变成「无人敢动」的核心模块。债务决策需要业务参与:哪些债可以欠,哪些债不能欠

案例 D:安全与合规的「文字正确」与「系统正确」

AI 可能生成看似完善的权限检查,但遗漏了 管理后台路径内部接口多租户隔离 的特殊规则。此类错误往往不是语法问题,而是 威胁模型 问题——威胁模型必须人类主导。


核心知识点:CAP 定理作为试金石——AI 能讲清楚,但不能替你选

CAP 的经典解释这里不重复。关键结论是:分布式系统必须在分区发生时做选择倾向,而「你的系统到底更需要 CP 还是 AP,抑或在业务细分上分别处理」取决于:

  • 用户可接受的错误类型(不可用 vs 不一致)
  • 数据类别的监管强度
  • 是否已有成熟的冲突解决策略

AI 可以给你一份「通用建议」,但真正的架构产出应是:

  • 明确分区场景下的行为
  • 明确监控与告警如何证明系统处在哪种模式
  • 明确回滚与数据修复预案

这正是人类架构师要把 决策写进 ADR 的原因:决策不是信息,而是承诺


核心知识点:技术债务决策需要业务上下文,AI 默认缺失

技术债务可以分为:

  • 有意识的债:为抢占窗口,明确记录利息与偿还计划
  • 无意识的债:在不知不觉中腐蚀架构

AI 更容易加剧第二类:因为它优化的是 当下可运行,而不是 组织长期成本。因此 CodeSentinel 的设计里,我们会强调:

  • findings 不仅指出问题,还要标注 债务类型建议偿还路径
  • 对「临时方案」要求附带 到期条件(例如下个季度必须重构)

核心知识点:概率性外壳问题(Probabilistic Shell)

我们可以把 LLM 视作一个 概率性执行核:在相似提示下也可能输出不同细节。工程系统的大多数关键属性却需要确定性:

  • 鉴权必须确定
  • 计费必须确定
  • 数据完整性约束必须确定
  • 关键审计日志必须确定

如果让概率性执行核直接触碰这些区域,你会得到 偶发正确、难以追责 的系统行为。解决思路不是「不用 AI」,而是:

  • 把 AI 放在 明确的输入输出契约
  • 对外部世界的作用通过 确定性网关(规则、校验、人工裁决)完成

核心知识点:Clean Architecture 的一种新表述

本课程采用的表述是:

Clean Architecture 是在概率性智能(模型)之外,为系统建立确定性边界与依赖方向,使关键规则可测试、可审计、可替换。

这意味着:

  • 领域规则尽量不依赖框架
  • 外部交互通过接口隔离
  • 「AI 生成的实现」如果进入核心层,必须经过更严格门禁

CodeSentinel 自身也应当遵循这一原则:审核编排可以复杂,但鉴权、审计、密钥与持久化策略必须清晰可控


代码实战:用「确定性外壳」包裹一次 LLM 调用(教学示例)

下面示例展示一个常见的反模式与改进模式对比:绝不要把 LLM 的原始输出直接当作 blocker 结论;应通过 schema 校验、证据字段与非 LLM 规则交叉验证。

反模式(不要在生产使用)

import json

def bad_review(diff_text: str, llm_client) -> dict:
    raw = llm_client.complete(f"请审核以下diff并返回JSON:\n{diff_text}")
    return json.loads(raw)  # 可能抛异常,也可能结构不对,更可能胡编字段

改进模式:Pydantic 校验 + 严重级别策略 + 人工裁决入口

from __future__ import annotations

import json
from typing import Any

from pydantic import BaseModel, Field, ValidationError


class LLMFindingModel(BaseModel):
    severity: str = Field(pattern="^(info|warn|suggested_blocker)$")
    title: str
    evidence: str = Field(min_length=8)


class LLMReviewPacket(BaseModel):
    findings: list[LLMFindingModel]
    needs_human: bool = True


class DeterministicShell:
    """
    CodeSentinel 设计哲学示例:
    - 模型只能输出 suggested_blocker,最终 blocker 需要规则/人工确认
    - 任何解析失败都必须可观测、可重试、可降级
    """

    def __init__(self, llm_complete_fn):
        self._llm_complete_fn = llm_complete_fn

    async def review(self, diff_text: str) -> LLMReviewPacket:
        prompt = (
            "你是代码审核助手。请仅输出 JSON(不要Markdown),schema如下:\n"
            '{"findings":[{"severity":"info|warn|suggested_blocker",'
            '"title":"...", "evidence":"必须包含定位信息,如文件路径/函数名/片段"}],'
            '"needs_human":true}\n'
            f"DIFF:\n{diff_text}\n"
        )
        raw_text: str = await self._llm_complete_fn(prompt)

        try:
            data: Any = json.loads(raw_text)
            packet = LLMReviewPacket.model_validate(data)
        except (json.JSONDecodeError, ValidationError) as exc:
            # 生产环境:记录 task_id、模型版本、提示哈希;这里教学省略
            return LLMReviewPacket(
                findings=[
                    LLMFindingModel(
                        severity="warn",
                        title="LLM 输出未通过结构化校验",
                        evidence=f"解析/校验失败:{type(exc).__name__}",
                    )
                ],
                needs_human=True,
            )

        # 关键:即使模型给了 suggested_blocker,也默认需要人类复核
        if any(f.severity == "suggested_blocker" for f in packet.findings):
            packet = packet.model_copy(update={"needs_human": True})

        return packet

从这段代码你可以读出三条工程原则,它们会直接写进 CodeSentinel 的后续实现:

  • 结构化输出是第一道门
  • 模型的 blocker 只是建议,不是裁决
  • 解析失败本身也是一个可审计事件

生产环境实战:把「人类判断力在中心」落实为平台机制

1)ADR + CodeSentinel:决策与审查要互相引用

建议在团队流程里规定:

  • 影响架构红线的改动必须关联 ADR 编号或链接
  • CodeSentinel 报告里出现 suggested_blocker 时,PR 模板要求填写 人类结论

2)双轨发布:模型升级不应悄悄改变门禁语义

生产常见问题:换了一个模型版本,审核口径漂移。应对:

  • 提示模板版本化
  • 模型路由配置可回滚
  • 对门禁结果做 回归集(固定 diff 样本)

3)成本与延迟:把 AI 用在「最值得语义理解」的地方

确定性规则能解决的,不要浪费 token。CodeSentinel 的推荐顺序:

  • import 图 / 静态规则 / 单测
  • 低成本模型初筛
  • 高成本模型仅在疑似高风险且证据链不足时触发

4)数据边界:审核系统也是高敏感系统

CodeSentinel 会接触代码与评审讨论,必须:

  • 最小化留存
  • 脱敏与访问控制
  • 审计日志记录谁触发了哪些外呼

CodeSentinel 设计哲学(本讲结论句)

CodeSentinel 不是「让 AI 当架构师」,而是 把人类架构判断流程工程化

  • 规则引擎承担确定性门禁与可重复证据
  • LLM承担高带宽语义分析与草案生成
  • 人类承担上下文补齐、权衡裁决与责任承担
  • 看板与度量让治理从个人习惯变成组织系统

换句话说:CodeSentinel 是 AI 时代 Reviewer 工作台 的平台化。


本讲小结:记住三句话就够用了

mindmap
  root((第03讲小结))
    AI强处
      模式与生成
      文档与检索辅助
    人类强处
      权衡与责任
      业务与组织上下文
    关键概念
      概率性外壳
      确定性边界
      CleanArch新表述
    平台落点
      CodeSentinel分层
      suggested_blocker机制
      ADR与门禁联动

思考题

  1. 回顾你们最近一个线上事故:如果当时让 AI 做架构选择,它更可能给哪种「中庸方案」?人类实际应该选择哪种取舍?
  2. 你认为哪些审核结论 永远不应 由 LLM 直接关闭(例如直接 approve)?请列出清单并说明理由。
  3. 如果把 CodeSentinel 接入你们 CI,你最先想固化哪三条 确定性规则?它们能否在不使用 LLM 的情况下独立运行?

下一讲预告

模块一将继续把全景认知落到工程骨架:我们将进入 CodeSentinel 项目启动与仓库治理(环境与目录结构、依赖注入雏形、最小 CI 门禁),并开始把「给 AI 立规矩」的规范文件与审核输入字段对齐,为模块二的架构基础功与模块四的 AI 审核实战打地基。


附录:建议你今天完成的 30 分钟练习

  • 选一个你正在维护的模块,写一段 ADR 草案:只回答三个问题——我们为什么这样做?备选方案是什么?我们接受了哪些代价?
  • 列出你团队中 3 个高频 AI 生成走捷径点(例如随意跨层 import),把它们改写成可检测的约束句子,准备未来写进 CodeSentinel 策略包。