升级 LangChain4j 到 1.x 后编译报
cannot find symbol: class ChatLanguageModel,这不是依赖没引进来。1.x 统一了接口:ChatLanguageModel改名成ChatModel,generate(...)改名成chat(...)。改完名字还可能撞上第二个坑——core 升到 1.x,集成模块还停在 0.x,编译能过,运行期抛NoClassDefFoundError。
Issue & Env(案发现场与环境)
- 业务场景:项目从 LangChain4j 0.x 升到 1.x。升级后要么
mvn compile直接失败,要么编译通过、启动时报错。 - 环境:LangChain4j 1.x,
langchain4j-core与各 provider 模块、第三方集成(quarkus-langchain4j)版本不一致,JDK 17。
StackTrace(堆栈日志)
编译期是 javac 的标准文案:
java: cannot find symbol
symbol: class ChatLanguageModel
location: package dev.langchain4j.model.chat
运行期是 issue #2873 的原文,core 从 1.0.0-beta2 升到 beta3 时触发:
java.lang.RuntimeException: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
[error]: Build step io.quarkiverse.langchain4j.deployment.AiServicesProcessor#watchResourceFiles threw an exception: java.lang.NoClassDefFoundError: dev/langchain4j/model/chat/TokenCountEstimator
at io.quarkiverse.langchain4j.deployment.LangChain4jDotNames.<clinit>(LangChain4jDotNames.java:49)
at io.quarkiverse.langchain4j.deployment.AiServicesProcessor.watchResourceFiles(AiServicesProcessor.java:942)
两条报错长得不一样,指向同一类问题:一个是符号没了,一个是类没加载到。
Reproduce(复现代码)
第一种,直接沿用 0.x 写法:
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
Response<AiMessage> response = model.generate("你好");
ChatLanguageModel 与 generate 在 1.x 都不存在了。第二种是依赖版本参差:
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-core</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>0.35.0</version>
</dependency>
core 是 1.x,provider 还是 0.x,两代 API 拼在一起。
Root Cause(根因分析)
接口统一是源码级改名
0.x 里最常用的 ChatLanguageModel,在 1.x 统一成了 ChatModel;流式接口 StreamingChatLanguageModel 统一成 StreamingChatModel。方法名也换了:0.x 的 generate(...) 变成 chat(...),返回值从 Response<AiMessage> 变成 ChatResponse。
所以「找不到符号」是编译器在说:这个名字在新的包结构里已经没有了,跟依赖有没有下载下来无关。看到 cannot find symbol 就去查依赖,方向会偏。
core 与集成模块版本不齐,运行期才炸
langchain4j-core 是底座,provider 模块和第三方集成(Quarkus、Spring 扩展、社区 provider)都编译在它之上。core 升到 1.x,某个模块还停在 0.x 或 beta 版,编译期往往看不出来:引用的符号可能在别处还在。问题留到运行期才暴露,表现为 NoClassDefFoundError 或 NoSuchMethodError。
issue #2873 就是这个形态。core 从 1.0.0-beta2 升到 1.0.0-beta3,类 TokenCountEstimator 被移除,Quarkus 扩展启动时去加载它,直接抛 NoClassDefFoundError。注意这是同一个大版本内的 beta 升级,说明 patch/minor 升级也可能删类。
The Fix(解决方案)
先确认是不是改名。全局搜 ChatLanguageModel 和 generate(,按 1.x 写法替换:
// 1.x 写法
ChatModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
ChatResponse response = model.chat("你好");
流式侧对应改成 StreamingChatModel,用 chat(...) 的重载。
再治版本参差。用 langchain4j-bom 统一版本,别逐个手写:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
然后检查有没有多个 langchain4j 版本混进来:
mvn dependency:tree -Dincludes=dev.langchain4j
Gradle 用:
./gradlew dependencies | grep langchain4j
输出里出现两个及以上版本号,就是参差的源头。把 core、各 provider、第三方集成版本对齐到同一代。具体版本号去 Maven Central 核对。
最后一条经验:升级前读 release notes。core 的小版本也可能删类,beta2→beta3 就删掉了 TokenCountEstimator。可参考 1.0.0 release notes。
小结
- 编译报
ChatLanguageModel找不到,是 1.x 改名,改成ChatModel/chat(...)。 - 版本不齐的报错在运行期,表现为
NoClassDefFoundError/NoSuchMethodError。 - 用
langchain4j-bom统一版本,dependency:tree查重复版本。 - core 的小版本升级也可能删类,升级前必读 release notes。
