如果你在搜索引擎里输入 Logic大概率会看到两类完全不同的结果一类是 Saleae 逻辑分析仪、PADS Logic 的原理图设计、示波器抓波形的硬件教程另一类则通向人工智能历史中最古老也最棘手的问题——机器如何像人一样在信息不完整时做出合理判断。前者是数字电路里的布尔逻辑关注电平高低结论确定后者是 John McCarthy 从上世纪五十年代开始反复追问的常识逻辑关注“缺省情况下应该怎么想”结论随时可能被新事实推翻。今天大部分 AI 从业者熟悉前者却对后者极为陌生。但这恰恰是当前大模型落地时最需要补上的一块拼图。这篇文章不打算复述 McCarthy 的生平而是想讲清楚三件事第一他提出的“常识形式化”为什么至今仍是 AI 的底层难题第二传统逻辑和人类常识推理之间到底差在哪一步第三用一个可运行的 Python 最小示例把“默认推理”和“非单调逻辑”从论文概念变成你能亲手验证的代码。读完你会明白为什么符号逻辑在大模型时代不但没有过时反而成为让 AI 变得更可靠的关键一环。1. 为什么现在还要讨论 McCarthy 的常识形式化John McCarthy 在 1955 年正式提出 “Artificial Intelligence” 这个术语后来又设计了 Lisp 语言并在 1958 年提出 Advice Taker 设想——一个能够接收“以逻辑语句表示的建议”、然后据此推理行动后果的通用程序。这些工作让他被称为“人工智能之父”之一但如果你只记住这个称号其实错过了他最核心的技术判断。McCarthy 真正想解决的问题是计算机怎样才能拥有常识更准确地说计算机需要一种形式语言把人类那些不言自明的知识表达出来并且在这种语言之上定义推理规则让机器能够从已有知识推出新结论。他在 1980 年代进一步提出限定逻辑把“默认推理”引入一阶逻辑试图让机器在信息不完整时也能做出合理假设。这件事的难度远超想象。人类常识知识有两个突出特点一是规模巨大二是充满例外。比如“鸟会飞”这条常识遇到企鹅、鸵鸟、受伤的鸟就会失效。传统逻辑系统要求所有前提都明确成立而人类的日常推理却大量依赖“默认成立除非有例外”的模式。在大模型时代重新讨论 McCarthy是因为我们遇到了非常具体的工程问题LLM 很擅长语言生成但对于多步逻辑推理、事实一致性、约束满足结果往往不稳定。同一个问题换个问法结论可能完全相反。为了让 AI 在金融、医疗、法律等高风险场景中可靠落地工程师们开始重新把符号推理、规则引擎、知识图谱请回来这实际上就是 McCarthy 路线的延续。换句话说McCarthy 留下的不是一段过时的历史而是一组至今没有完全解决、却越来越重要的问题什么是常识如何把它形式化推理系统如何允许例外这些问题的答案直接决定我们能否构建真正可信的 AI 系统。2. 常识为什么难默认推理与经典逻辑的冲突要理解 McCarthy 的工作先要搞清楚一个核心矛盾经典逻辑是单调的而人类常识推理是非单调的。2.1 单调性与非单调性一阶逻辑具有单调性。意思是如果从一组公理中可以推出某个结论那么无论你再添加多少新公理这个结论仍然成立。定理一旦被证明就永远有效。这在数学上是优点但在常识推理中却是缺陷。假设你知道“Tweety 是一只鸟”并且人类默认“鸟会飞”你会很自然地认为“Tweety 会飞”。可如果第二天你得知“Tweety 其实是一只企鹅”这个结论就必须收回。新的信息让旧结论失效了这就是非单调推理。经典逻辑无法优雅地处理这种情况。如果你把“鸟会飞”写成一条严格的全称规则∀x(bird(x) - fly(x))那么当 Tweety 被声明为企鹅时逻辑系统会同时得到“Tweety 会飞”和“Tweety 不会飞”的矛盾如果你把规则写成带例外的形式就必须把企鹅、鸵鸟、死鸟、受伤的鸟全部列举出来而现实世界的例外永远列举不完。2.2 数据库里的封闭世界假设很多人第一次接触非单调思想其实是在数据库系统里。关系数据库遵循封闭世界假设凡是没有显式存储在数据库中的事实都被默认视为假。比如系统里没有张三的处罚记录就可以默认张三没有违法记录。这个假设非常实用让数据库查询变得简单高效。但从逻辑学角度看它并不是经典一阶逻辑的必然结果——一个模型可能包含数据库中不存在的额外事实。要让数据库的查询语义成立必须在推理机制上加入“默认不存在”的特殊规则。这与 McCarthy 处理常识问题的方法本质上是同一条路用默认假设补全不完整信息。2.3 最小模型与默认假设McCarthy 的限定逻辑给出了一个数学化的解决方案在满足已知条件的模型中选择最小的那个。所谓“最小”可以理解为“不必要就不假设存在”。如果知识库只声明了 Tweety 是鸟那么最小模型会默认 Tweety 具有鸟的典型属性——会飞当新事实“Tweety 是企鹅”加入后知识库的最小模型发生了变化之前的默认结论被推翻。这个概念看似抽象但它的工程价值非常明确它允许系统在新信息到来时优雅地撤回旧结论而不是陷入矛盾、直接崩溃。一个能“收回结论”的系统比一个“假装什么都确定”的系统更接近人类智能。3. 从建议逻辑到限定逻辑一个可以计算的常识模型McCarthy 的路线可以概括为三步先选择一种表达能力足够的逻辑语言再把常识知识编写成逻辑语句最后设计推理规则让系统能从“已知”出发推导出“默认成立”的结论。3.1 为什么不能直接使用一阶逻辑一阶逻辑表达能力很强可以表示个体、性质、关系也支持量词。但它有两个工程上的硬伤。第一一阶逻辑的推理是不可判定的不存在一个通用算法能在有限时间内判断任意命题是否可推出。第二即使在可判定的子集内直接推理的复杂度也往往非常高。因此 McCarty 之后的研究者包括描述逻辑、可编程逻辑语言等方向都在做同一件事对一阶逻辑做“可控的限制”牺牲部分表达能力换取可计算的推理。这正是 OWL 本体语言、Datalog、Prolog 等现代知识表示工具背后的逻辑。3.2 限定逻辑的核心思想限定逻辑的精髓是把“默认”变成一种经过严格定义的推理机制。它不是简单地在规则后面加一个“通常”标记而是通过最小模型语义让系统自动选择“最保守”的结论。通俗地理解系统只相信必须相信的事实不主动假设多余的实体和关系。这个原则在实际工程中非常重要因为它能减少幻觉般的臆测让知识库的结论更可控。从 Advice Taker 到限定逻辑McCarthy 都在尝试回答一个问题如何让逻辑系统既保持严格性又具备人类那样的弹性当时的计算条件无法支撑他的设想但这个框架本身没有过时它只是等待更好的工程实现。4. 符号主义与联结主义两条路线如何走到今天讨论 McCarthy 的常识形式化绕不开人工智能历史上两大技术路线的分与合。4.1 符号主义时期在人工智能早期符号主义占据主流。研究者相信智能的核心是符号操作只要把知识写成逻辑规则再配上推理引擎机器就能表现出智能。专家系统在 1980 年代一度非常成功例如医疗诊断系统 MYCIN能够根据症状规则给出治疗方案。但专家系统的瓶颈很快暴露知识获取需要大量人工访谈和规则编写难以规模化规则越多冲突越多系统越脆弱一旦遇到规则之外的输入系统完全没有应变能力。这导致符号主义在 1990 年代之后受到冷落。4.2 联结主义与深度学习的崛起联结主义路线不依赖人工规则而是从数据中学习参数。神经网络通过大规模样本自动提取特征在图像识别、语音识别、自然语言理解等领域取得了远远超过符号主义的效果。特别是大模型出现后模型可以生成流畅的文本、回答问题、编写代码让很多人觉得“只要数据够多、参数够大常识也许可以自动涌现”。但现实是大模型仍然经常出现事实性错误在需要精确计算、多步推理、严格约束的场景下并不可靠。幻觉问题本质上就是“统计相关性”与“逻辑必然性”之间的差距。4.3 当下的混合趋势最近一两年工程界逐渐形成共识单纯依赖神经网络或单纯依赖符号规则都不够最佳方案是两者结合。比如 RAG 架构让模型先检索知识库再生成回答NL2SQL 把自然语言转换成严格的 SQL 查询Agent 工具调用让模型把不确定的语义问题转化为确定性的函数执行。这些做法都是把“不可靠的直觉”交给神经网络把“需要保证的正确性”交给符号系统。严格来说这并没有推翻 McCarthy 的方向而是把他主张的符号推理放在了组合系统的一个关键位置当系统需要可验证、可解释、可回滚时符号层兜底当系统需要理解开放语义时神经网络负责启发式猜测。5. 把理论变成工程知识图谱、规则引擎与逻辑推理McCarthy 的常识形式化思想落到现代工程里大致对应三类基础设施知识图谱、规则引擎和逻辑推理语言。5.1 知识图谱把常识结构化知识图谱用“实体-关系-实体”三元组表达知识。比如“Tweety 属于 Bird”“Bird 通常具有 Fly 属性”。这种表达方式本质上就是逻辑中的谓词和关系只是更贴近工程实现。现代知识图谱通常基于 RDF/OWL 标准构建支持机器可读的语义和自动推理。5.2 规则引擎把业务知识变成可执行规则规则引擎如 Drools允许开发者声明“当条件满足时执行动作”的规则实现业务逻辑与代码分离。它的底层推理机制与专家系统一脉相承只是加上了冲突消解、优先级、动态更新等工程化能力。5.3 逻辑编程语言声明式推理Prolog 和 Datalog 是更接近 McCarthy 愿景的工具。开发者只需声明事实和规则推理引擎负责寻找结论。Prolog 支持回溯和复杂查询Datalog 则牺牲部分表达能力换取更好的可判定性和性能优化。5.4 什么时候需要用符号推理理解这一点可以帮助避免“拿着锤子到处找钉子”。如果需求是一个开放域对话系统用户的问法千变万化这时候应该优先考虑大模型如果需求是“根据一系列固定规则判断贷款申请是否通过并追溯到每一笔审批依据”那么符号规则引擎几乎是不可替代的选择。简单判断标准只要你的系统需要“给出理由、可审计、绝不允许违反硬约束”就必须引入符号推理层。反之如果只是生成建议、辅助创作、理解模糊问题可以让模型自由发挥。6. 完整示例用 Python 实现一个最小常识推理系统下面用纯 Python 实现一个极简的常识知识库演示三个关键能力默认推理、例外优先、非单调更新。这个示例不依赖任何第三方库Python 3.8 即可运行。6.1 代码实现# 文件路径common_sense_kb.py 一个极简常识知识库 - 支持正向断言某个个体属于某个类别 - 支持默认规则类别通常具备某属性但可排除某些类别 - 查询时返回 True / False / None True 表示成立False 表示不成立None 表示知识不足 class CommonSenseKB: def __init__(self): self.instances {} # 个体 - 类别集合 self.defaults [] # (类别, 属性, 排除类别集合) def add_instance(self, instance, categories): 添加个体及其类别例如 tweety 属于 bird。 self.instances.setdefault(instance, set()).update(categories) def add_default(self, category, prop, exclusionsNone): 添加默认规则某类别通常具备某属性排除类别除外。 self.defaults.append((category, prop, exclusions or set())) def query(self, instance, prop): 查询某个个体是否具备某属性。 cats self.instances.get(instance, set()) if not cats: return None for category, default_prop, exclusions in self.defaults: if category in cats and default_prop prop: if cats exclusions: return False # 属于例外类别默认不成立 return True # 默认成立 return None # 知识不足无法判断这段代码的核心逻辑非常直观。add_instance负责录入事实add_default负责录入默认规则query在查询时先检查个体是否属于某个适用默认规则的类别如果该个体还属于排除类别就返回 False。这样就把“通常”和“例外”同时建模进来了。6.2 运行演示# 文件路径demo.py from common_sense_kb import CommonSenseKB kb CommonSenseKB() # 默认规则鸟通常会飞但企鹅是例外 kb.add_default(bird, fly, exclusions{penguin}) # 已知事实 kb.add_instance(tweety, {bird}) kb.add_instance(polly, {bird, penguin}) kb.add_instance(robot01, {machine}) print(Tweety 会飞吗, kb.query(tweety, fly)) # True print(Polly 会飞吗, kb.query(polly, fly)) # False print(robot01 会飞吗, kb.query(robot01, fly)) # None # 非单调更新tweety 后来被证明是企鹅 kb.add_instance(tweety, {penguin}) print(得知 tweety 是企鹅后Tweety 会飞吗, kb.query(tweety, fly)) # False运行这段代码预期输出如下Tweety 会飞吗 True Polly 会飞吗 False robot01 会飞吗 None 得知 tweety 是企鹅后Tweety 会飞吗 False输出里最值得关注的是最后一行同一个查询在没有新信息时返回 True加入新事实后返回 False。这就是非单调推理的最小可运行演示。None是系统的正常返回表示知识库不足以做出判断这不是 bug反而是知识库系统的重要设计——它拒绝假装知道。6.3 规则推导示例默认推理只是常识推理的一部分另一部分是规则链推导。下面这个例子演示“从已知事实出发通过规则不断推导出新事实”的前向链算法# 文件路径forward_chain.py from collections import defaultdict # 规则如果个体是哲学家那么他是人如果他是人那么他会死 rules [ {if: philosopher, then: human}, {if: human, then: mortal}, ] def forward_chaining(initial_facts): derived set(initial_facts) changed True while changed: changed False for rule in rules: if rule[if] in derived and rule[then] not in derived: derived.add(rule[then]) changed True return derived if __name__ __main__: facts forward_chaining({socrates_philosopher}) print(sorted(facts)) # 输出示例[human_socrates, mortal_socrates, socrates_philosopher]注意这里使用了socrates_philosopher这种整体式的原子事实是为了简化单个个体的规则推导演示方便你理解前向链的机制。如果能推导出mortal_socrates就说明规则链从“哲学家”推到了“会死”。这个机制和专家系统中事实传播、知识图谱中的类层次推理是同构的。6.4 如何验证和排错直接用命令行运行python demo.py python forward_chain.py如果 demo.py 输出和预期不一致首先检查 Python 版本是否符合要求然后确认common_sense_kb.py和demo.py在同一目录下。如果 forward_chain.py 没有输出mortal_socrates检查规则字典中的键名是否拼写一致这类问题大多是“if”和“then”的值不匹配造成的。7. 常见问题与排查思路前面的代码能跑通只是一个开始。真正把推理系统做到生产级会遇到更多工程问题。下表整理了实际项目中最常见的几类问题问题现象可能原因排查方式解决方案推理结论与业务预期不一致默认规则覆盖顺序不明确或例外类别表不完整打印知识库中的所有默认规则检查每条规则对应的例外集合调整规则优先级补全例外类别必要时把“默认”改为“严格”规则知识量很小但查询极慢规则链过长前向链产生大量中间结论观察中间结果规模统计每次循环新增事实数改用后向链推理只计算与目标相关的规则为已推导结论建立缓存规则之间存在循环依赖规则集出现自指例如 A 依赖 BB 又依赖 A用依赖图检查规则之间的引用关系检测环增加规则优先级限制推导深度或重新设计规则层次大模型输出与符号推理结果冲突分工不清晰模型既生成事实又下结论记录冲突案例检查模型抽取的事实是否准确让模型只负责文本抽取和生成最终结论由符号引擎给出知识库维护困难规则随意堆叠规则与代码耦合没有版本管理和测试评估当前规则数量统计修改规则是否影响历史结论规则配置化建立知识库回归测试集真正容易踩坑的地方是很多人把默认规则当成普通规则来写忽略了例外优先级。一旦出现“鸟会飞”和“企鹅不会飞”同时成立而系统又无法判断哪个应该优先就会产生大量矛盾结论。解决方式其实很简单先定义例外再定义默认让例外永远压过默认。另一个常见误区是认为None代表系统出错。实际上在开放知识库中无法判断才是常态。如果系统对每个问题都强行给一个 True 或 False反而说明知识库被过度填充了。保留“未知”状态是常识推理系统的基本素养。8. 工程实践建议McCarthy 的常识形式化思想要落地最后拼的其实是工程纪律。以下几点建议来自实践中的共性经验值得认真对待。8.1 先定义知识边界不要试图一开始就建模整个世界的常识。先划清系统解决什么问题、需要哪些知识、哪些知识可以规则化、哪些必须留给算法或人工判断。垂直领域的小型常识库比追求全面但漏洞百出的通用常识库可靠得多。8.2 把知识分层一个可维护的知识系统至少应该分四层词汇层定义概念和关系规则层定义推理逻辑事实层保存具体实体数据校验层维护冲突检测和一致性检查。分层的价值在于当某一层发生变化时不会连锁影响其他层。8.3 规则与代码分离把规则写在代码里是最差的选择。推荐的做法是将规则保存为外部配置例如 YAML 或 JSON 文件让业务人员也能参与维护。修改规则不需要重新编译和发布系统这是规则引擎之所以存在的根本原因。示例规则配置文件# 文件路径rules.yaml defaults: - category: bird prop: fly exclusions: - penguin rules: - if: philosopher then: human - if: human then: mortal8.4 用回归测试保障知识库稳定知识库也有 bug而且规则冲突比代码缺陷更难发现。最有效的方式是建立“期望结论”测试集把真实业务场景中的输入和预期输出固化为自动化测试用例。每次改动规则前先跑一遍回归测试确保旧的正确结论没有被动摇。8.5 保留推理路径生产系统需要可解释性。每条推理结论都应该能够回溯到“使用了哪些事实、哪些规则、结论是怎么得出的”。这一机制在企业审计、医疗决策、金融风控等场景中是刚需也是符号推理系统相对神经网络最明显的优势。8.6 与 LLM 组合的标准模式目前工程上比较成熟的模式是先用大模型从非结构化文本中抽取事实并转换为结构化数据再由规则引擎或逻辑推理系统基于这些事实做精确推导最后再让大模型把推理结果翻译成自然语言解释给用户。分工原则很明确模型负责“理解语言”符号系统负责“保证正确”。8.7 关注性能与扩展性当事实规模达到百万级时简单的 Python 循环会非常吃力。此时应该考虑引入图数据库例如 Neo4j或者使用 Datalog 引擎。图数据库天然适合表达实体关系而且支持对子图进行高效遍历这是常识推理在大规模数据场景下的重要底座。9. 你还需要警惕的边界符号推理系统不是万能的它有自己的局限和适用边界。谨慎地意识到这些边界能帮你避免很多不必要的坑。第一规则库的构建成本极高。即使是一个垂直领域的中型知识库也需要大量人力去整理领域专家的思维过程并把它写成规则。如果只是通用问答或内容生成盲目引入规则层会让项目很快僵化。第二一阶逻辑的推理存在不可判定性。这意味着不是所有推理问题都能在有限时间内得到答案。工程上必须限定推理子集例如使用描述逻辑或 Datalog或者设置推理深度和超时时间防止系统卡死在枚举循环里。第三离散的符号推理难以处理模糊性。人类语言充满歧义而符号系统要求精确的输入。这就是为什么在端到端的自然语言理解任务中大模型仍然占据优势。两者结合时输入转换这一步的质量决定了整个系统的天花板。第四常识本身会随文化和时代变化。今天被视为常识的规则明天可能被推翻。知识库必须支持版本化迭代定期更新默认规则和例外集合。没有演进机制的知识库最终会成为系统的技术债。10. 总结与后续学习方向John McCarthy 提出的“常识形式化”不是一个失败的假设而是一个被提前提出的工程挑战。他真正预见到的是符号逻辑系统需要处理“默认成立但有例外”的推理方式。今天大模型时代面临的幻觉、不可解释、无法追溯等问题恰恰说明这一挑战依然没有完全解决只是换了一种方式呈现在我们面前。本文的核心收获有三个第一理解了经典逻辑的单调性与常识推理的非单调性之间的本质矛盾第二了解了 McCarthy 如何通过最小模型和默认假设把“常识”变成可计算的逻辑机制第三通过一个可运行的 Python 示例亲手验证了默认推理和非单调更新的完整流程。这套思想在知识图谱、规则引擎、Agent 工具调用、LLM 可靠化改造等技术方向中都有直接应用价值。如果你想继续深入下一步可以按这个路径学习先掌握一阶逻辑和归结原理再学习 Prolog 或 Datalog 的基本语法然后尝试用开源工具构建一个垂直领域的知识图谱最后研究如何把大模型和一个规则引擎组合成混合架构。推荐在本地环境尝试本文的代码把它扩展成一个支持文件存储和规则导入的小型知识库再加入一个简单的理由回溯功能你会对“推理系统为什么这么做”有完全不同的理解。最后一个提醒当你的系统需要给用户一个明确理由、需要审计每一步决策、需要保证硬约束永远不被打破时不要只依赖大模型把 McCarthy 的逻辑工具箱重新打开。它可能不性感到让人兴奋但它能让你的系统真正可靠。