前言
時間過得飛快,一轉眼國慶假期也要過去了,再不更新部落格就太鹹魚了……
最近在開發AIHub的時候想找個C#能用的命名實體識別庫,但一直沒找到,AI生態方面C#確實不太豐富,這塊還是得Python,但我又不想跟LLM一樣用gRPC的方式來呼叫,感覺有點麻煩。
這時候發現好像JVM生態有不少這類NLP工具,比如 Standford NLP 、HanLP這類。所以就想到之前在網上看到的iKvm,我直接把JVM生態白嫖來使用?
關於iKvm
看官方的介紹
IKVM is an implementation of Java for the Microsoft .NET platform. It can be used to quickly and easily:
- Execute compiled Java code (bytecode) on .NET Framework or .NET Core
- Convert bytecode to a .NET assembly to directly access its API in a .NET project
These tasks can be done without porting source code to .NET.
有兩種工作方式:
- 直接在C#裡呼叫 jar 包執行
- 將 jar 包轉譯為 .Net 平臺的 dll ,然後引用執行
一般選第二種就行,第一種就是動態呼叫,根本沒程式碼提示,不想考慮這種方式。
iKvm 其實是一套體系來的,裡面包含了完整的 JDK 標準庫和執行時啥的,我粗略看了下,什麼 swing、xml、media啥的一應俱全,還能支援 jdk 的反射。
並且還附帶有現代的構建工具 maven!
PS: gradle 不知道有沒有,我還沒試過。
關於依賴處理
雖說 iKvm 支援 maven 非常的方便,但是它並不能處理一個包中的依賴關係!
例如引用了 StarAI 這個包,它又依賴於 Transformer 這個庫,在maven中會自動下載所有依賴進行 build
但是 iKvm 的 maven 沒辦法自動處理依賴,所以只能手動把 StarAI 和 transformer 這倆庫都新增到配置裡。
開始使用
本文以 HanLP 為例
依賴準備
首先新增倆 nuget 依賴
dotnet add package IKVM
dotnet add package IKVM.Maven.Sdk
或者直接編輯專案檔案
<ItemGroup>
<PackageReference Include="IKVM" Version="8.6.4" />
<PackageReference Include="IKVM.Maven.Sdk" Version="1.5.5" />
</ItemGroup>
然後再專案檔案裡面新增 maven 依賴,直接從 mvn repository 上覆制下來就完事了,非常的方便!
給不熟悉 Java 的同學指個路: https://mvnrepository.com/
<ItemGroup>
<MavenReference Include="hanlp">
<groupId>com.hankcs</groupId>
<artifactId>hanlp</artifactId>
<version>portable-1.8.4</version>
</MavenReference>
</ItemGroup>
儲存,之後IDE會自動執行操作,會自動下載 iKvm 需要的依賴,各平臺的 JDK 和 runtime 之類的,並且會自動從 maven 上把 jar 包下載下來並轉譯成 .Net 平臺的 dll
這個過程需要一段時間,請耐心等待。
如果沒有自動執行請手動執行
dotnet restore
dotnet build
開始編碼
這裡以 HanLP 的句子成分分析功能為例
using com.hankcs.hanlp.model.crf;
using com.hankcs.hanlp.model.perceptron;
using com.hankcs.hanlp.seg;
using com.hankcs.hanlp.seg.common;
namespace AIHub.Algo.HanLP;
public class NER {
private readonly string _modelPath;
public NER(string modelPath) {
_modelPath = modelPath;
}
public void Recognize(string input) {
PerceptronLexicalAnalyzer analyzer = new PerceptronLexicalAnalyzer(
Path.Combine(_modelPath, "cws.bin"),
Path.Combine(_modelPath, "pos.bin"),
Path.Combine(_modelPath, "ner.bin")
);
var result = analyzer.analyze(input);
Console.WriteLine(result);
}
}
測試時直接呼叫 Recognize
方法即可。