エクセルでローカルLLMをやってみました!
.NET(C#)でxllをつくってVBAから使います。
LLamaSharpというのを使っています。
完成したのを以下です。
準備
環境
- windows11
- NVIDIA GeForce RTX 3060 VRAM 12GB
- excel2019 64bit
- .net8 vscode
ライブライの準備など
- dotnet new classlib -n ExcelAddinLLM
- dotnet add package ExcelDna.Addin
Excel-DNAを使ってxllにします - dotnet add package LLamaSharp --version 0.19.0
LLamaSharpでLLamaを使います - dotnet add package LLamaSharp.Backend.Cuda12 --version 0.19.0
CPUだけなどでこれは変える必要があります
使用するモデル
モデルは以下を使用してみました。
cudaを使えるようにする
- CUDA Toolkitをインストールしておく必要があるようでした
コード内容
Excel-Dnaでの呼び出し
Excel-Dnaはデバッグとかするための準備が少し必要です。
ExcelAddonFunctions.cs
using ExcelAddinLLM.Utils;
using ExcelDna.Integration;
namespace ExcelAddinLLM;
public static class ExcelAddonFunctions
{
private static readonly object ReturnNA = new();
[ExcelFunction(Description = "ローカルLLM")]
public static string SayLLM(string targetValue, int row, int col)
{
try
{
var functionName = nameof(SayLLM);
var parameters = new object[] { targetValue, row, col };
var result = AsyncTaskUtil.RunTask(functionName, parameters, async () =>
{
return await LLamaAddin.LLamaChatAsync(targetValue, row, col);
});
if (result.Equals(ReturnNA))
return ExcelError.ExcelErrorNA.ToString();
if (result.Equals(ExcelError.ExcelErrorNA))
return "Busy...";
else
return "true";
}
catch (Exception ex)
{
return ex.ToString();
}
}
}
LLamaSharpの処理
ExampleからInstruct executor - basicの内容を使っています。
LLamaAddin.cs
using LLama.Common;
using LLama;
using ExcelDna.Integration;
namespace ExcelAddinLLM;
public static class LLamaAddin
{
public static async Task<string> LLamaChatAsync(string inputText, int row, int col)
{
ExcelAsyncUtil.QueueAsMacro(() =>
{
var cellRef = new ExcelReference(row - 1, row - 1, col - 1, col - 1);
cellRef.SetValue("");
});
try
{
DirectoryInfo DirectoryInfo = new(Path.GetDirectoryName(ExcelDnaUtil.XllPath)
?? new(AppDomain.CurrentDomain.BaseDirectory));
string modelPath = Path.Combine(DirectoryInfo.FullName, @"Llama-3-ELYZA-JP-8B-q4_k_m.gguf");
var prompt = @"以下はタスクを記述した指示である。要求を適切に完了する応答を書きなさい。";
prompt += inputText;
var parameters = new ModelParams(modelPath)
{
ContextSize = 1024,
GpuLayerCount = 20
};
using var model = LLamaWeights.LoadFromFile(parameters);
using var context = model.CreateContext(parameters);
var executor = new InstructExecutor(context);
var inferenceParams = new InferenceParams() { MaxTokens = 600 };
var resultText = "";
await foreach (var text in executor.InferAsync(prompt, inferenceParams))
{
resultText += text;
ExcelAsyncUtil.QueueAsMacro(() =>
{
var cellRef = new ExcelReference(row - 1, row - 1, col - 1, col - 1);
cellRef.SetValue(resultText);
});
}
return "true";
}
catch (Exception ex)
{
return ex.ToString();
}
}
}
vbaから呼び出す
ggufなど必要なファイルはxllと同じ場所に保存しておきます。
引数は以下のように指定します。
(LLMに聞きたい内容, 出力行,出力列)
Sub llm()
Debug.Print Application.Run("SayLLM", ActiveSheet.Range("B3").Value, 3, 4)
End Sub
完成!
その他
DeepSeekできなかった
DeepSeekの日本語学習したggufを使ってみましたができなかった。
Excel-DnaじゃなくてLLamasharpだけのチャットになら使えました。
llamasharpのバージョン
LLamaSharpの最新バージョンは0.21.0ですが、ExcelDnaだと0.19.0でしか使えませんでした。
dllファイルが2つから4つに変わっているようですが、ちゃんとコピーしてるのにダメでした。
モデルがよみこめない
ggufを保存しているパスに日本語があると読み込めないようです。
なにか変換とかできるのかは分からない。
参考
- 日本語のローカルLLM(文章生成AI)をWindowsで動かす
- 「GPT-4」を上回る日本語性能のLLM「Llama-3-ELYZA-JP」を開発しました
- llama.cppでGGUF形式のモデルファイルを読み込み、チャットする