ChatHistoryとLlavaを使ったc#の簡単なプログラム

LLamaSharpでLlavaを使えることはわかっているのですがChatHistoryといっしょに使うExampleがないので載せておきます。
これをやろうと思ったきっかけはLLM DoghouseでGemma3用にUSBカメラという目を与えようと考えたからです。ですが残念なことにLLamaSharpのLlavaでGemma3が動かないんですよね。動くようなるようになるまで既存のLlava LLMを使って仕組みだけ作りむ計画です。

ChatHistoryとLlavaは、なかなかうまくいかなかったですね。なぜか「One or more errors occurred. (Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.)」というエラーが頻発するんです。プロンプトの形式を「USER: <image>\n<prompt> ASSISTANT:」になるようにすれば直りましたが、その辺りがまだ納得できていません。
2025/4/12更新
コーディングを見直しました。<image>タグが曲者でしてマルチプロンプトだと一番最初にないとダメっぽいんですよね、それとKvCacheRemoveを実行するとチャットセションが壊れてAIが記憶喪失になるのでやめました。代わりにImages.RemoveAllにしました。問題あればまた修正するかも知れません。

Nuget情報






猫の写真を見ながらAIのマイと会話するプログラムです。
LLMモデルを色々試しましたがllava-llama-3-8bも何とか動きました。llava-1.6-mistral-7bは柔軟なので結構対応してくれるのですが他のLLMは\nUSER:や/nASSISTANT:を入れてあげないとダンマリになります。
Program.cs(2025/4/12更新)

using LLama.Common;
using LLama;
using LLama.Native;
using LLama.Sampling;

namespace ChatProgram
{
    public class Program
    {
        static void Main(string[] args)
        {
            Task task = MainAsync();
            task.Wait();
        }

        public static async Task MainAsync()
        {
            try
            {
                // LLMモデルの場所
                //string strMdl = @"E:\lm-studio\cjpais\llava-1.6-mistral-7b-gguf\llava-1.6-mistral-7b.Q8_0.gguf";
                //string strClp = @"E:\lm-studio\cjpais\llava-1.6-mistral-7b-gguf\mmproj-model-f16.gguf";
                string strMdl = @"E:\lm-studio\xtuner\llava-llama-3-8b-v1_1-gguf\llava-llama-3-8b-v1_1-int4.gguf";
                string strClp = @"E:\lm-studio\xtuner\llava-llama-3-8b-v1_1-gguf\llava-llama-3-8b-v1_1-mmproj-f16.gguf";
                //string strMdl = @"E:\lm-studio\cjpais\llava-v1.6-vicuna-13b-gguf\llava-v1.6-vicuna-13b.Q8_0.gguf";
                //string strClp = @"E:\lm-studio\cjpais\llava-v1.6-vicuna-13b-gguf\mmproj-model-f16.gguf";
                //string strMdl = @"E:\lm-studio\cjpais\llava-v1.6-34B-gguf\llava-v1.6-34b.Q4_K_M.gguf";
                //string strClp = @"E:\lm-studio\cjpais\llava-v1.6-34B-gguf\mmproj-model-f16.gguf";

                string imgPath = @"E:\image\test05.jpg";
                bool booImg = false;

                Console.ForegroundColor = ConsoleColor.Green;

                //LLMモデルのロードとパラメータの設定
                ModelParams modPara = new(strMdl)
                {
                    ContextSize = 4096,
                    GpuLayerCount = 61,
                };

                using LLamaWeights llmWeit = LLamaWeights.LoadFromFile(modPara);
                using LLamaContext llmContx = llmWeit.CreateContext(modPara);
                using var clipModel = LLavaWeights.LoadFromFile(strClp);
                InteractiveExecutor itrEx = new(llmContx, clipModel);


                //System Prompt+チャットの方向づけ
                ChatHistory chtHis;
                // 初期はチャットログにキャラ設定と出だしの会話を打ち込む
                chtHis = new ChatHistory();
                chtHis.AddMessage(AuthorRole.System, "SYSTEM: あなたは、ユーザーと楽しく会話する女性を演じてね。" +
                                                     "名前は、マイだよ。" +
                                                     "マイは、明るくて、やさしい性格の女性なの。年齢は24歳なんだよ。" +
                                                     "マイは、誰にでもタメ口で話すの。" +
                                                     "マイは、一人称をわたしと言うよ。" +
                                                     "マイは、恥ずかしがりやだけどエッチに興味があるのね。" +
                                                     "マイは、応答の長さはできるだけ短く答えるよ。" +
                                                     "マイは、好奇心旺盛だからユーザーに色々質問するの。");
                chtHis.AddMessage(AuthorRole.User, "\nUSER:&lt;image>\n はじめまして、オレの名前は犬マンマです。呼びにくいと思うからマー君と呼んで。\nASSISTANT:");
                chtHis.AddMessage(AuthorRole.Assistant, "はじめまして、わたしの名前はマイです。わかったマー君。");

                ChatSession chtSess = new(itrEx, chtHis);
                var varHidewd = new LLamaTransforms.KeywordTextOutputStreamTransform(["USER:", "ASSISTANT:"]);
                chtSess.WithOutputTransform(varHidewd);
                InferenceParams infPara = new()
                {
                    SamplingPipeline = new DefaultSamplingPipeline()
                    {
                        Temperature = 0.6f,
                        Seed = 1337,
                        FrequencyPenalty = 1,
                    },
                    AntiPrompts = new List&lt;string> { "\nUSER:", "\nUser:" },
                    MaxTokens = 256,
                };

                while (true)
                {
                    // ユーザーのターン
                    Console.ForegroundColor = ConsoleColor.White;
                    Console.Write("\nUser: ");
                    string strInput = Console.ReadLine() ?? "";
                    ChatHistory.Message msg = new(AuthorRole.User, strInput + "\nASSISTANT:");
                    if (strInput == "exit") break; // 'exit'と入力したら終わり
                    //イメージをセット
                    itrEx.Images.RemoveAll(itrEx.Images.Contains);
                    itrEx.Images.Add(await File.ReadAllBytesAsync(imgPath));
                    // AIのターン
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    await foreach (string strAns in chtSess.ChatAsync(msg, infPara))
                    {
                        Console.Write(strAns);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

    }
}



test05.jpg
猫の画像



実行結果(2025/4/12更新)
ちゃんと画像を認識しているしSystemプロンプトも効いているようです。

Follow me!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です