
这篇论文不是某个开源工具也不是热点模型而是 AI 历史上绕不开的一份思想源头。John McCarthy 被称为“人工智能之父”之一1956 年达特茅斯会议他是发起人之一后来又发明了 Lisp 语言。而他长期坚持的一个核心判断是人工智能不能只靠算法在具体问题上跑出结果还需要让机器拥有“常识”并且常识本身可以形式化、可以写成逻辑表达式。这个判断在他 1959 年的论文《Programs with Common Sense》里已经出现1990 年又以《Formalizing Common Sense: Papers by John McCarthy》合集形式集中呈现。我们今天用一篇文章把它讲清楚。这篇文章最值得关注的点有三个第一McCarthy 不是泛泛谈“AI 要理解世界”而是给出了可操作的表示工具也就是一阶谓词逻辑和限定逻辑第二他提出了“默认规则”的思想今天很多知识工程的异常处理、例外传播都从这里来第三他面对的核心问题“框架问题”今天依然存在只是换了个名字出现在大模型身上比如幻觉、上下文不一致、常识缺失。理解了 McCarthy你就会理解为什么现在的 Agent 系统总需要加一层规则校验而不是纯靠大模型输出。本文会带你做这几件事先拆解 McCarthy 论文里的几个关键概念然后给一段可运行的最小常识推理 Demo覆盖默认规则和异常修正再把它和当前的大模型、知识图谱、神经符号计算对照起来。整个过程不需要 GPU不需要安装重型框架一台普通电脑加一个 Python 解释器就够。这类内容适合谁如果你是做 NLP、知识图谱、Agent 编排、规则引擎的工程师或者正在纠结“大模型输出到底要不要再套一层逻辑校验”这篇可以仔细看。下面我们从核心思想开始。1. 核心思想速览能力项说明提出者John McCarthy人工智能先驱之一Lisp 语言发明者核心问题如何让机器拥有常识并将常识表示为可计算逻辑主要工具一阶谓词逻辑、限定逻辑Circumscription、环世界假设关键应用常识推理、行动推理、非单调逻辑、知识表示经典论文《Programs with Common Sense》1959、《Formalizing Common Sense》1990 合集硬件要求无特殊要求普通 CPU 即可运行教学 Demo运行环境Python 3.8或 SWI-Prolog可选适合场景规则引擎设计、知识图谱建模、Agent 约束层、逻辑推理学习这个表格看起来很简单但 McCarthy 的问题远没有这么轻松。他问的是一个人走进餐厅他知道桌子、椅子、菜单、服务员、结账这些概念之间是什么关系也知道“拿起杯子喝水”通常不会导致杯子爆炸。这些知识对成年人来说不言自明但对计算机来说几乎没有一样是显式给定的。McCarthy 想找到一种方式把这种“不言自明”的常识变成机器可推理的形式。他的回答不是去构建一个巨大的、包含所有事实的知识库而是用逻辑规则把常识组织起来默认什么成立、什么条件下例外、行动之后哪些属性保持不变。这些规则不需要穷举世界只需要在特定上下文中足够好用。这就是“环世界假设”和“默认推理”的朴素动机。今天很多本体建模工具、知识图谱推理引擎依然沿用这种思路。2. 背景AI 为什么需要常识形式化2.1 从“计算程序”到“咨询程序”McCarthy 在 1959 年的文章里区分了两类程序。一类是“计算程序”你输入数值它返回运算结果比如一个求平方根的函数。另一类是他设想的“咨询程序”它接收的不是数字而是关于世界的描述然后根据描述给出行动建议。咨询程序要想有用就必须理解常识它要知道“人通常有两只眼睛”“鸟通常会飞”“车在没油时不会走”。这些知识不是某个具体问题的答案而是推理的背景。当计算机只做数值计算时背景知识多余但当计算机要参与决策、理解语言、执行任务时背景知识就成了刚需。McCarthy 的远见在于他 1959 年就把这个需求提出来了并且坚持认为逻辑是满足这个需求的最佳载体。这不是“逻辑万能论”而是一种工程判断逻辑表达式可组合、可验证、可修改适合做长期积累的常识库。2.2 常识不是“完整世界模型”很多人对常识形式化的第一反应是要在知识库里塞进数亿条事实比如“猫有四条腿”“苹果可以吃”“太阳从东边升起”。这既不现实也不符合 McCarthy 的思路。他真正关心的是推理结构而不是百科条目数量。更准确的描述是常识推理大量使用“默认规则”。所谓默认规则是说“在没有任何反证的情况下可以认为 X 成立”。比如“鸟会飞”这是一个默认但“企鹅不会飞”是一个反例“受伤的鸟不会飞”是另一个反例。形式化系统要能表达“默认成立 可被反例推翻”这正是非单调逻辑的起点。经典一阶逻辑是单调的已知事实增加结论只会增加不会删掉。但常识推理不是这样新事实可能让旧结论作废。2.3 环世界假设解决了什么问题环世界假设Circumscription是 McCarthy 提出的一种推理策略在不知道异常存在的情况下尽量把“异常对象”限制在已知范围内。说得直白一点就是“没听说过的异常默认不存在”。还是用鸟的例子。知识库里说“图图是一只鸟”没有说“图图是企鹅”也没有说“图图受伤了”。那么系统会推出“图图会飞”。这是一个默认结论。如果后来新增“图图受伤了”系统就应该收回“图图会飞”这个结论。这不是经典逻辑的推导方式经典逻辑里一旦推出结论就是永久的但环世界假设允许结论被新证据推翻。这个特性让逻辑系统从“静态推导”走向了“可修正推理”。3. 核心技术拆解McCarthy 的逻辑工具箱3.1 一阶谓词逻辑作为表示语言McCarthy 选择一阶谓词逻辑作为常识表示的基础原因不只是数学严谨性更重要的是一阶逻辑可以表达“对象 关系 量词”。例如“图图是一只鸟”bird(tutu)。“大明是一只企鹅”penguin(pengy)。“所有企鹅都是鸟”∀x(penguin(x) → bird(x))。这看起来很朴素但它提供了一个关键能力知识可以模块化。你新增一条规则不需要改动其他规则你新增一个对象不需要重写整个库。这一点对常识这种“持续增长”的知识域极其重要。3.2 环世界假设不是闭世界假设这里必须做一个区分。数据库里的“闭世界假设”是凡是数据库里没有的事实都视为假。McCarthy 的环世界假设不是这个意思它说的是在推理时尽量缩小异常谓词的外延只把已知的异常对象当作异常。区别在哪闭世界假设直接判断真假环世界假设控制的是“异常”范围。系统默认大部分鸟正常只在明确知道异常时才把对应的鸟归入异常集合。这种“默认 可修正”的结构构成了 McCarthy 非单调推理的核心。3.3 限定逻辑与异常最小化限定逻辑是环世界假设的形式化落地。它在逻辑系统中增加了一个偏好原则在所有满足已知事实的模型中优先选择“异常对象集合最小”的那个模型。听起来抽象但它的用途很具体。比如规划一个机器人从 A 点走到 B 点过程中它推着箱子。框架问题问的是机器人执行完移动动作之后箱子的颜色变了吗桌子的位置变了吗如果没有特殊说明常识告诉我们它们都没变。但逻辑系统怎么知道“没变”呢限定逻辑的做法是把“变化”当作异常默认一切属性在动作前后保持不变只有被明确声明为变化的内容才发生变化。这样一来系统不需要为每个属性都写一条“动作后仍然成立”的公理常识推理的计算量被大幅压缩。3.4 框架问题为什么重要框架问题最早由 McCarthy 和 Patrick Hayes 在 1969 年的论文中明确提出。它表面上是“行动推理中哪些属性不变”的技术问题实质上是“如何高效表示常态”的根本问题。如果你要描述一个动态世界每个动作发生之后有无数个事实没有变化。如果不处理框架问题系统必须显式维护所有事实这会让推理复杂度爆炸。McCarthy 用默认规则来解决一个动作发生后默认所有属性保持不变除非这个属性出现在该动作的影响列表里。用逻辑语言表达就是“变化需要理由不变不需要理由”。这个思想后来被大量继承包括事件演算、流演算、乃至现代游戏引擎里的状态系统都能看到“变化即异常”的影子。3.5 资格条件运动能力不是绝对的McCarthy 还提出了“资格条件”的概念。一个动作可以被执行通常需要满足一些默认条件但这些条件可以被特殊情况打破。例如“鸟可以飞”前提是“鸟没有受伤”“鸟不是企鹅”“鸟没有被关在笼子里”。这些前提不是说每条都要写出来而是通过默认规则“没有例外时默认成立”。放到现代 Agent 系统里这个思想极其重要。一个大模型 Agent 决定调用一个工具时必须知道工具是否可用、网络是否正常、权限是否足够。这些东西如果全部显式枚举规则会爆炸如果完全靠模型自己猜又会不稳定。McCarthy 的解法是用规则层描述“默认可用 异常阻断”把异常条件单独维护。4. 最小可运行 Demo把常识规则写成代码理论讲完进入落地环节。下面这段代码把所有 McCarthy 的概念浓缩成一个可运行的例子默认规则“鸟会飞”异常规则“企鹅不会飞”和“受伤的鸟不会飞”。我们用 Python 实现一个简单的闭包式推理。4.1 环境准备Python 3.8 以上即可不需要任何第三方库。一台普通电脑CPU 运行内存占用可忽略。可选安装 SWI-Prolog用于第四节后续对照。4.2 Python 前向推理演示# 文件: common_sense_demo.py facts { bird(tutu), injured(tutu), bird(amy), penguin(pengy), } def extract_objects(predicate: str, fact_set: set): 从 fact_set 中提取指定谓词涉及的对象名。 例如 bird(tutu) 在 predicatebird 时返回 {tutu}。 objs set() prefix predicate ( for fact in fact_set: if fact.startswith(prefix) and fact.endswith()): objs.add(fact[len(prefix):-1]) return objs def closure(init_facts: set) - set: 反复应用规则直到事实集合不再变化。 facts set(init_facts) changed True while changed: changed False # 规则 1企鹅是鸟 for obj in extract_objects(penguin, facts): new_fact fbird({obj}) if new_fact not in facts: facts.add(new_fact) changed True # 规则 2企鹅是异常不能飞 for obj in extract_objects(penguin, facts): new_fact fabnormal({obj}) if new_fact not in facts: facts.add(new_fact) changed True # 规则 3受伤的鸟是异常不能飞 # 注意只有同时是鸟和受伤时才产生异常 injured_objs extract_objects(injured, facts) bird_objs extract_objects(bird, facts) for obj in injured_objs: if obj in bird_objs: new_fact fabnormal({obj}) if new_fact not in facts: facts.add(new_fact) changed True # 规则 4默认规则鸟会飞除非该对象是异常 for obj in extract_objects(bird, facts): if fabnormal({obj}) not in facts: new_fact fcan_fly({obj}) if new_fact not in facts: facts.add(new_fact) changed True return facts result closure(facts) for fact in sorted(result): print(fact)4.3 Prolog 表达失败即否定如果你装了 SWI-Prolog可以用更接近 McCarthy 原意的写法% 规则与事实 bird(X) :- penguin(X). can_fly(X) :- bird(X), \ abnormal(X). abnormal(X) :- penguin(X). abnormal(X) :- injured(X). bird(tutu). injured(tutu). bird(amy). penguin(pengy).保存为common_sense.pl然后在 SWI-Prolog 中执行查询?- [common_sense]. ?- can_fly(amy). true. ?- can_fly(tutu). false. ?- can_fly(pengy). false.4.4 运行结果与判断标准运行 Python 脚本后输出应该包含四类事实abnormal(pengy) abnormal(tutu) bird(amy) bird(pengy) bird(tutu) can_fly(amy) injured(tutu) penguin(pengy)判断成功的标准有三个can_fly(amy)出现说明默认规则生效普通鸟会飞。abnormal(pengy)出现说明企鹅被识别为异常因而不会推出can_fly(pengy)。abnormal(tutu)出现说明受伤的鸟被识别为异常因而不会推出can_fly(tutu)。这正好展示了 McCarthy 所说的“默认规则 异常修正”。如果结果里can_fly(tutu)仍然出现说明异常规则没有生效要检查规则 3 中“同时是鸟和受伤”的条件是否成立。因为示例里tutu同时满足bird(tutu)和injured(tutu)所以它应该落入异常集合。需要注意的是这个 Python Demo 不是完整的非单调逻辑引擎它通过“先推异常再推飞行”的顺序模拟了“默认 可修正”。真实的限定逻辑要比这复杂但教学场景里这个小 Demo 已经足以表达核心思想。5. McCarthy 思想与现代 AI 的对照5.1 大模型的常识为什么还不够今天的大模型通过海量文本学到了大量统计规律能回答“鸟会飞”这类问题。但它的推理方式不是逻辑推导而是概率预测。一旦遇到需要回溯、修正、处理异常的复杂推理模型经常会给出看似合理但前后矛盾的答案这也就是常说的“幻觉”。McCarthy 的角度看大模型缺少一个“显式的常识约束层”系统应该知道默认结论是什么也应该知道什么条件下要撤回结论。所以你会看到现在很多 Agent 框架都要在模型输出之后接一层“检查器”或“守卫”把工具调用结果、权限范围、上下文一致性拿规则再校验一遍。这种做法本质上就是给统计模型补一个符号逻辑层方向与 McCarthy 的设想一致只是实现载体从手工规则变成了代码函数。5.2 知识图谱与本体的延续知识图谱里的本体层几乎就是 McCarthy 思路的工程化延续。一个本体通常包含类、属性、公理、约束比如“人类是哺乳动物的子类”“一个人只有一个出生日期”。用描述逻辑推理时系统可以根据公理自动推断新事实也能检测不一致。这里的“不一致检测”对应到 McCarthy 那里就是异常规则在起作用。5.3 神经符号混合路线最近几年越来越多工作在尝试“神经符号”混合大模型负责从文本中抽取候选事实符号推理引擎负责验证和补全。典型做法是先把文本转成语义三元组再丢进规则引擎做一致性检查或者让大模型生成代码形式的规则再交给约束求解器处理。这条路线能成立的原因与 McCarthy 当初坚持逻辑的动机一脉相承统计模型擅长感知和生成但不擅长保证一致性逻辑系统擅长一致性和可解释性但不擅长处理模糊信息。两者结合正好弥补各自的短板。如果你在做 Agent 相关的项目这个方向值得认真考虑。6. 资源占用与性能观察McCarthy 这篇论文讨论的不是深度学习模型所以不存在显存占用问题。运行本文的 Python 推理 Demo在普通 CPU 上耗时通常以毫秒为单位内存占用可以忽略。真正影响性能的是知识库规模和推理算法复杂度。如果知识库里有 1 万个事实闭包推理通常在可接受范围内。如果事实规模到百万级就要考虑使用专门的推理引擎比如 Datalog、Prolog、ASP 求解器。如果逻辑规则里包含大量递归和回溯性能会显著下降需要考虑缓存和剪枝。如果系统需要持续维护“默认规则”和“异常修正”最好把规则与事实分开存储方便在推理时动态加载。实际项目里我建议先跑通最小闭环再用性能测试数据决定是否引入重型推理框架。不要一开始就上分布式知识库多数场景到不了那个规模。7. 常见误区与排查方法McCarthy 的逻辑 AI 思想中有几个高频误区这里统一清理一下。问题现象可能原因排查方式解决方案把环世界假设当成闭世界假设概念没有区分开对比两者的定义环世界假设限定“异常”范围闭世界假设判定真假Python Demo 里 can_fly(tutu) 仍能推出异常规则没有先生效检查规则 3 的对象提取条件确保 injured 对象同时是 bird 对象时才生成 abnormalProlog 查询结果与预期不一致规则顺序和否定查询时机问题检查是否导入正确文件确认\ abnormal(X)是失败即否定认为 McCarthy 否定统计方法把逻辑 AI 与统计学派对立化阅读 McCarthy 后续论文他主张逻辑作为知识表示工具并不完全排斥其他方法认为框架问题已经彻底解决混淆局部任务与通用常识推理查看现代 Agent 的一致性维护方案框架问题依然活跃只是以新形式存在把异常规则写进默认规则内部知识组织混乱检查规则是否分层默认规则和异常规则分开定义异常在先默认在后如果你跑 Prolog最常遇到的是 “Singleton variables” 警告这通常不影响运行但值得检查是否存在变量名字拼写不一致。如果查询返回 “false” 而不是 “true”先看事实里对象名是否一致再检查是否缺失bird(tutu)之类的必要前提。8. 实践建议与扩展路径8.1 从一阶逻辑到非单调逻辑建议的学习顺序是先掌握一阶谓词逻辑的语法和真值表再理解 Horn 子句和 Prolog 的执行机制然后进入非单调逻辑领域接触限定逻辑、默认逻辑、真值维护系统。每一步都配合一个最小 Demo 验证概念不要一上来就读哲学性的长篇论文。8.2 工具推荐SWI-Prolog最好入门的逻辑编程环境适合验证规则和查询。Potassco Clingo基于 Answer Set Programming 的求解器适合复杂约束和组合搜索。RDFLib / OWL-RL适合做知识图谱本体推理。Python 自研闭包引擎适合快速原型验证不依赖外部系统。8.3 工程化建议做 Agent 或知识系统时可以这样落地 McCarthy 的思想为每一个默认规则设计对应的“异常规则”并放到单独的规则文件里。在系统启动时先加载事实再按“异常规则优先默认规则其次”的顺序执行推理。给每条规则标注来源和置信度便于后续维护。大模型输出进入业务逻辑前先过一遍规则层过滤明显违背常识的结果。8.4 合规与安全边界如果你把这类逻辑推理能力接入人脸识别、声音处理、自动决策等真实业务要特别注意涉及个人肖像和声音的授权必须合法合规涉及自动化决策的系统需要保留完整的规则审计日志涉及公共安全场景不能只依赖默认规则做最终判断。任何系统在正式商用前都要用真实数据做效果复核最好有人工兜底环节。9. 总结与下一步McCarthy 这篇论文真正值得读的地方不在于它给出了多少现成的算法而在于它把一个极其困难的问题坚持形式化了半个世纪常识不是“感觉”而是可以被描述为默认规则和异常修正的结构。今天我们遇到的 Agent 工具调用不稳定、大模型输出幻觉、知识图谱一致性差本质上都和“缺少一层常识约束”有关。如果只想做一件事验证理解建议先跑一遍本文的 Python Demo把can_fly(amy)和abnormal(tutu)这两个结果看明白你就摸到了 McCarthy 思想的入口。最容易踩的坑是把默认规则写成绝对规则忘记异常规则的存在。后续扩展方向可以是把这段最小推理放到一个 FastAPI 服务里接收事实列表并返回推理结论再逐步接入你自己的业务规则库。