Przejdź do treści

Phi-3/ONNX i C#

  • przez

Pewnie słyszałeś o chat gpt, bo kto nie słyszał 😀 W tym poście chciałbym zaprezentować LLM a właściwie SLM stworzony przez Microsoft. Model ten nazywa się Phi-3.

Może najpierw zacznę od tego, czym różnią się modele SLM (Small Language Model) od LLM (Large Language Model). Nazwą – to po pierwsze 😉 SLM mają mniejsze wymagania obliczeniowe, ale podobnie jak LLM mogą być używane w NLP (Natural Language Processing). Przykład LLM to GPT-4. Ciężko byłoby używać LLM na laptopie lokalnie. SLM jak za chwilę się przekonasz, możemy używać na laptopie (na stacjonarnym chyba też 😀).

Phi-3 powstał w trzech wersjach:
Phi-3-mini (3.8B). Dostępny w dwóch wariantach różniących się liczbą tokenów: 4K oraz 128K
Phi-3-small (7B)
Phi-3-medium (14B)

W internecie można znaleźć informacje, że Phi-3 nie jest najlepszy jeśli chodzi o testy z wiedzy ogólnej. Natomiast dość dobrze radzi sobie z tworzeniem postów w social mediach, streszczeniami, analizą tekstów i w marketingu. Zamierzam sprawdzić kilka jego umiejętności.

Aby zacząć musimy najpierw pobrać nasz model:

git lfs install
git clone https://huggingface.co/microsoft/Phi-3-mini-4k-instruct-onnx

💡 git lfs install aktywuje Git Large File Storage (LFS) w naszym repozytorium.

Napiszę prostą aplikację konsolową .NET, która pomoże mi przetestować Phi-3. Kod znajduje się tutaj. Aplikacja używa Microsoft.ML.OnnxRuntimeGenAI, którą możesz dodać do swojego projektu tak jak poniżej. ONNX pozwala w łatwy sposób uruchamiać modele ML. Nie jest zależna od innych treningowych frameworków.

dotnet add package "Microsoft.ML.OnnxRuntimeGenAI"

🚨Jeśli będziesz testować aplikację lokalnie to pamiętaj o ustawieniu ścieżki do modelu (w appsettings.json), który sklonowałaś/sklonowałeś wcześniej, np.

{
    "AppSettings": {
        "ModelPath": "C:\\ml-models\\Phi-3-mini-4k-instruct-onnx\\cpu_and_mobile\\cpu-int4-rtn-block-32"
    }
}

W celu przetestowania tworzę klasę PhiPrompt, która odpowiada za interakcję z użytkownikiem. Działanie jest proste: pytamy użytkownika i zwracamy odpowiedź.

using Microsoft.ML.OnnxRuntimeGenAI;

namespace PhiOnxDemoApp;

public class PhiPrompt
{
    private readonly Model _model;
    private readonly Tokenizer _tokenizer;
    private readonly string _systemPrompt =
        @"As an AI assistant answer questions using a direct style.";

    public PhiPrompt(AppSettings settings)
    {
        _model = new Model(settings.ModelPath);
        _tokenizer = new Tokenizer(_model);
    }

    public void Run()
    {
        Console.WriteLine("Hello, how can I help you today?");

        while (true)
        {
            if (!TryGetUserQuestion(out var question))
            {
                Console.WriteLine("See you next time :-)");
                break;
            }

            ShowAnswer(question!);
        }
    }

    private static bool TryGetUserQuestion(out string? question)
    {
        Console.WriteLine();
        Console.Write(@"Question (press ENTER to finish): ");
        question = Console.ReadLine();
        return !string.IsNullOrWhiteSpace(question);
    }

    private void ShowAnswer(string question)
    {
        Console.WriteLine();
        Console.Write("Answer: ");
        Console.WriteLine();
        var fullPrompt = $"<|system|>{_systemPrompt}<|end|><|user|>{question}<|end|><|assistant|>";
        var tokens = _tokenizer.Encode(fullPrompt);

        var generatorParams = new GeneratorParams(_model);
        generatorParams.SetSearchOption("max_length", 2048);
        generatorParams.SetSearchOption("past_present_share_buffer", false);
        generatorParams.SetInputSequences(tokens);

        var generator = new Generator(_model, generatorParams);
        while (!generator.IsDone())
        {
            generator.ComputeLogits();
            generator.GenerateNextToken();
            var outputTokens = generator.GetSequence(0);
            var newToken = outputTokens.Slice(outputTokens.Length - 1, 1);
            var output = _tokenizer.Decode(newToken);
            Console.Write(output);
        }

        Console.WriteLine();
        Console.WriteLine();
        Console.WriteLine(new string('-', Console.WindowWidth));
    }
}

Czas na testowanie. Najpierw sprawdzę, czy dostanę slogan na stronę. Zadaję pytanie give me 5 slogans for website about AI i oto efekt:

Myślę, że gdybym tworzył taką stronę, to coś bym wybrał. To może teraz coś związanego z marketingiem. Zapytam o reklamę dla roweru (give me short ads about road bike).

Jak widać dostaliśmy odpowiedzi. Jeśli nie podamy ilości odpowiedzi to dostaniemy tyle ile ONNX&Phi-3 uzna za słuszne 😉

To teraz przetestuję jak poradzi sobie ze streszczeniem jakiegoś nudnego i długiego tekstu. Moja praca dyplomowa byłaby idealna, ale nie wiem gdzie mam cyfrową wersję 🙂 Wybiorę coś z artykułu z wikipedii https://en.wikipedia.org/wiki/Large_language_model.

No to może teraz coś związanego z historią i takim językiem ogólnym (nietechnicznym). Posłużę się kolejnym artykułem https://en.wikipedia.org/wiki/Marie_Curie. Zamierzam otrzymać 3 zdania streszczające dłuższy tekst.

Moim zdaniem to podsumowanie jest zadowalające (dostaliśmy jeszcze jedno zdanie gratis). No to sprawdźmy jak poradzi sobie z wiedzą ogólną.

Dwie pierwsze odpowiedzi są poprawne. Odpowiedź o pierwiastek też wygląda na poprawną. Ale sprawdziłem i nie jest poprawna. Czyli do liczenia nie za bardzo się nadaje 🙂 Sprawdźmy, czy poradzi sobie z zagadką z serialu/książki „Ślepnąc od świateł”.

I niespodzianka, poradził sobie 😮 Więc jakby to powiedział Jacek: „dobry jest, umie liczyć” 😀

Zamierzam się jeszcze pobawić Phi-3 i może jeszcze opublikuję jakiś post. Przykłady od Microsoft znajdziesz tutaj. Z tego video dowiedziałem się, że jest już Phi-3.5, więc może ten następny post będzie już o nim. Modele znajdują się tutaj.