乐于分享
好东西不私藏

Revit 插件 AI 代码的幻觉:根因不是模型笨,是它在"猜" API

Revit 插件 AI 代码的幻觉:根因不是模型笨,是它在"猜" API
Revit 插件 AI 代码的幻觉

Revit 插件 AI 代码的幻觉:根因不是模型笨,是它在"猜" API

上一篇聊了知识库规划,这篇往下扎一层——为什么 AI 写 Revit 插件代码总在"编",以及我们跑通的一条真正能降幻觉的路。

先说结论:换更强的模型没用,给 RAG 才有用。


一、幻觉长什么样

幻觉

如果你用 AI 写过 Revit 插件,下面这些场景应该不陌生:

  • 让它生成一段创建轴网削弱的代码,它给你写了 Grid.Create(document, line)——2024 版确实有这个方法,但你的项目锁定 2020 API,编译直接报红。
  • 让它读取参数,它写了 element.GetParameters("长度") 返回 IList<Parameter>——看起来没毛病,但它不知道你项目里根本不用原生 GetParameters,而是用扩展方法 ParameterEx.GetAsDouble(element, "长度"),返回值都不同。
  • 更离谱的,让它写事务包裹逻辑,它给你编了一个 TransactionGroup.CommitWithStatus()——这个方法不存在,是它把 Transaction.Commit() 和 TransactionGroup 的记忆拼在一起"创造"出来的。

这就是幻觉。不是语法错误,是事实性错误——API 方法名、签名、版本归属,全靠猜,而且猜得理直气壮。


二、根因:Revit API 是 LLM 的"噩梦数据源"

为什么 Revit API 特别容易让 AI 产生幻觉?三个结构性原因,叠在一起就是灾难。

数据源

2.1 版本碎:2020 / 2021 / 2022 / 2024 差异一大堆

Revit API 从 2014 到 2024,十几个版本,大量方法签名变了、废弃了、新增了。比如:

  • FilteredElementCollector 的某些 LINQ 扩展在不同版本行为不同
  • DirectShape 在 2015 引入,但创建 API 在后续版本改过签名
  • CurveLoop.Create() 在旧版本不存在,需要用构造函数绕

AI 的训练数据混着各版本——它见过 2019 的写法、见过 2022 的写法,生成时按概率拼,结果给你一段"语法合法、版本非法"的代码。它不是不知道有版本差异,是它分不清哪个方法属于哪个版本

2.2 私有封装多:UBIMApp、ExtensionMethods,AI 没见过

你的项目不是从零写原生 API,而是有一层封装:

  • UBIMApp 封装了 UIApplication 的取值逻辑
  • ParameterEx 扩展方法统一了取参方式
  • BaseCommand 基类处理了事务、异常、日志
  • FamilyLoader 封装了族加载+版本兼容逻辑

这些封装代码不在 AI 训练数据里。它不知道你项目里有 UBIMApp,更不知道 ParameterEx.GetAsDouble 和原生 get_AsDouble() 的区别。它会自作主张给你写原生调用,跟你现有架构完全脱节。

2.3 官方文档不全:大量 API 靠社区经验和逆向

Revit API 的官方文档以"简陋"著称。很多类和方法只有一行签名说明,没有用法示例,没有版本标注,没有注意事项。像 CurveLoopSolidSolidCutUtilsPartUtils 这些类,关键用法散落在论坛帖子和博客里。

AI 学到的 API 知识本来就不完整,文档缺的地方它就靠"脑补"——把相似类的方法签名迁移过来,赌一个能用。赌赢了是你的运气,赌输了就是线上 bug。


三、换更强的模型能解决吗?

不能。

GPT-4o、Claude 3.5、DeepSeek V3,模型越来越强,但幻觉的本质没变——LLM 是概率模型,生成代码时它做的是"下一个 token 最可能是什么"的预测,不是"API 文档里这个方法到底长什么样"的检索。

模型越强,它"编"得越流畅、越自信、越难辨真伪。GPT-3.5 编错 API 你一眼能看出来(语法都怪怪的),GPT-4o 编错 API 你得编译才发现(语法完美,方法不存在)。

这不是能力问题,是机制问题。 只要它靠训练记忆生成 API 调用,就一定有概率串版本、编方法名。概率可以降低,但无法消除。


四、降幻觉的唯一可靠路径:RAG + 编译门禁

逻辑很简单:不让 AI 凭记忆写 API,让它只能凭检索到的事实写。

这条路径分两层:

4.1 RAG:把真实代码 + 功能规格做成唯一事实源

把你的项目代码、API 文档、版本差异说明、踩坑记录,全部向量化存进知识库。AI 写代码前先检索,只能基于检索到的原文生成,不能凭记忆编。

检索到什么,它就写什么。检索不到的 API,它就得说"没找到",而不是硬编一个。

4.2 编译门禁:最后一道墙

RAG 能降 90% 的幻觉,但不是 100%——偶尔检索到相似但不完全匹配的片段,AI 还是可能误用。这时候编译器是兜底:

  • 生成的代码必须过 dotnet build 编译
  • 编译失败 → 错误信息回喂给 AI → AI 基于错误重试
  • 三轮编译不过 → 人工介入

RAG 管"别瞎编",编译器管"编了也能挡住"。两层叠加,幻觉基本无路可走。


五、我们跑通的架构:RevitKBAgent

不是纸上谈兵。我们自己的 RevitKBAgent 已经按这条路线跑通,下面是架构细节,可以直接照做。

5.1 数据层:8301 条向量,全是真实代码

数据源
内容
向量数
项目源码
YLIB 插件全量代码(Command / Service / Extension)
~5200
Revit API 文档
官方文档 + 版本差异说明 + 常用类说明
~2100
踩坑记录
崩溃案例、事务陷阱、性能坑
~600
代码模板
IExternalCommand 骨架、事务写法、选择器写法
~400

总计 8301 条向量。每条向量是代码片段或文档段落的 embedding,带原文回传。

5.2 检索层:bge-m3 + 1024 维 + score 0.7 阈值

配置项
为什么这么选
Embedding 模型
bge-m3
中英混合(代码英文+注释/文档中文)效果最好,支持长文本
向量维度
1024
bge-m3 默认维度,精度和性能平衡点
相似度阈值
score ≥ 0.7
低于 0.7 的检索结果不回传——宁可说"没找到",不给模糊匹配
回传格式
原文 + 出处路径
AI 生成的代码能追溯来源,不信可以查

关键设计:score 0.7 是硬门槛。 低于阈值的检索结果直接丢弃,AI 拿到的是高置信度的真实代码片段,不是"大概相关"的噪声。这一条砍掉了大量"似是而非"的幻觉来源。

5.3 生成层:带原文生成,不允许凭记忆

AI 的 system prompt 长这样(简化版):

你是一个 Revit 插件开发助手。你只能基于以下检索到的代码和文档生成回答。
如果检索结果中没有相关 API 信息,明确回答"未找到相关代码",不要编造方法名。
检索结果:
{retrieved_chunks_with_source}

核心原则:检索到什么,用什么。 检索到 ParameterEx.GetAsDouble,它就写 ParameterEx;检索不到,它就别编。这比"你是一个资深 Revit 开发者,请根据你的知识生成代码"靠谱十倍——后者等于鼓励它翻训练记忆。

5.4 编译门禁:三轮重试

生成代码 → dotnet build →
  编译通过 → 交付
  编译失败 → 错误信息回喂 → AI 修正 → 重试(最多3轮)
  3轮不过 → 标记需人工处理

实测下来,加上 RAG 之后,一次编译通过率从 30% 左右升到 75% 以上。剩下 25% 大部分一轮修正就过,需要三轮以上的极少。


六、效果:从"看着对、编译崩"到"拿来就能用"

上 RAG 前后的对比(同项目、同任务,"生成一个创建墙上开洞的 Command"):

维度
无 RAG
有 RAG + 编译门禁
API 版本正确率
~40%(经常串版本)
~95%(检索到的代码自带版本信息)
私有封装使用率
~10%(几乎全写原生 API)
~85%(检索到 BaseCommand / ParameterEx 就跟着用)
一次编译通过率
~30%
~75%
方法名编造率
高(TransactionGroup.CommitWithStatus 这种)
极低(检索不到就不写)

最直观的感受:以前 AI 写的代码要改一半,现在改两行。


七、别指望 RAG 解决一切

说点清醒的。

RAG + 编译门禁解决的是"API 层面的事实性幻觉"——方法名编造、版本串位、封装缺失。这类幻觉占 Revit 插件 AI 代码问题的 80% 以上,RAG 是目前最有效的解法。

但有两类问题 RAG 管不了:

  1. 业务逻辑错误。 AI 代码编译过了、API 全对,但开洞逻辑本身不对——该扣减的面没扣减、该处理的相交没处理。这是业务判断,不是事实检索能解决的。
  2. 知识库需要持续维护。 项目加了新封装、改了基类、踩了新坑,都要回填向量库。不维护的知识库,三个月就过期。

所以 RAG 不是银弹,但它是目前**唯一能把幻觉从"高频致命"压到"低频可控"**的手段。不上的话,AI 写 Revit 代码就是在赌——赌它训练记忆里恰好有你这个版本的 API。


八、收个尾

Revit 插件开发的幻觉,根因不在模型笨,在模型"猜"。它没有你的代码、没有你的版本约束、没有你的私有封装,只能靠训练记忆赌一个答案。

解法不是等一个更强的模型,是把你的真实代码和 API 文档做成事实源,让 AI 只能基于事实生成,再用编译器兜底。 这条路我们已经跑通了,8301 条向量、bge-m3 检索、score 0.7 硬门槛、编译门禁三轮重试——拿来就能用。

知识库是资产。模型可以换、工具可以换,但你项目的代码和踩坑记录,是你真正的壁垒。


优易科技 | 优易BIM助手

欢迎转发