问题
使用了 LangChain4j 的 InMemoryEmbeddingStore,并使用了serializeToFile 将数据持久化到了文件;再重新从文件构建 InMemoryEmbeddingStore 时,则报错:
Exception in thread "Thread-3" java.lang.RuntimeException: com.fasterxml.jackson.databind.JsonMappingException: Unrecognized character escape '鏂' (code 37826 / 0x93c2)
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 23117814] (through reference chain: dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore["entries"]->java.util.concurrent.CopyOnWriteArrayList[3110]->dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore$Entry["embedded"]->dev.langchain4j.data.segment.TextSegment["text"])
at dev.langchain4j.store.embedding.inmemory.JacksonInMemoryEmbeddingStoreJsonCodec.fromJson(JacksonInMemoryEmbeddingStoreJsonCodec.java:35)
然而,我直接在 idea 中运行又不报错,只有运行通过 mvn clean package 生成的 jar 包才报错。
解决
排查了好久,最终发现是编码问题导致。
java -Dfile.encoding=UTF-8 -jar your-app.jar
运行时指定文件编码即可解决。
核心原因
查看 InMemoryEmbeddingStore#fromFile(Path) 方法:
public static InMemoryEmbeddingStore<TextSegment> fromFile(Path filePath) {
try {
String json = new String(Files.readAllBytes(filePath));
return fromJson(json);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
发现其使用了默认的 String 构造方法,具体实现为:
public String(byte[] bytes) {
this(Charset.defaultCharset(), bytes, 0, bytes.length);
}
这里就用到了 Charset.defaultCharset(),因此当在 idea 中运行时序列化的文件,再在 mvn clean package 生成的 jar 包中读取该文件,可能导致出错,统一使用 utf-8 编码即可。