Erstellen eines Agents

Wichtig

Seit Januar 2026 wird das AI-Shell-Projekt nicht mehr aktiv gewartet. Dieses Projekt sollte aus ingenieurtechnischer Sicht als archiviert betrachtet werden.

Ein Agent ist eine Codebibliothek, die mit der KI-Shell mit einem bestimmten großen Sprachmodell oder einem anderen Unterstützungsanbieter kommunizieren kann. Benutzer chatten mit den Agents mit natürlicher Sprache, um die gewünschte Ausgabe oder Unterstützung zu erhalten. Agents werden als C#-Klassen implementiert, die die ILLMAgent Schnittstelle aus dem AIShell.Abstraction-Paket implementieren.

Ausführliche Informationen zur AIShell.Abstraction Ebene und AIShell.Kernelfinden Sie in der AI Shell-Architektur Dokumentation.

Dieser Artikel ist eine Schritt-für-Schritt-Anleitung zum Erstellen eines Agents für das Ollama-Sprachmodell . In diesem Artikel wird ein einfaches Beispiel für das Erstellen eines Agents gegeben. Es gibt eine robustere Implementierung des Ollama-Agents im AIShell.Ollama.Agent Ordner des Repositorys.

Voraussetzungen

  • .NET 8 SDK oder höher
  • PowerShell 7.4.6 oder höher

Schritte zum Erstellen eines Agents

In diesem Beispiel erstellen wir einen Agenten, um mithilfe von phi3 mit dem Sprachmodell zu kommunizieren. Ollama ist ein CLI-Tool zum Verwalten und Verwenden lokal erstellter LLM/SLMs.

Schritt 1: Erstellen eines neuen Projekts

Der erste Schritt besteht darin, ein neues classlib-Projekt zu erstellen.

  1. Erstellen eines neuen Ordners mit dem Namen OllamaAgent

  2. Führen Sie den folgenden Befehl aus, um ein neues Projekt zu erstellen:

    dotnet new classlib
    

Schritt 2: Hinzufügen der erforderlichen Pakete

Innerhalb des neu erstellten Projekts müssen Sie das AIShell.Abstraction Paket aus dem NuGet-Katalog installieren. Installieren Sie das NuGet-Paket mit dem folgenden Befehl:

dotnet add package AIShell.Abstraction --version 1.0.0-preview.2

Mit diesem Befehl wird das Paket ihrer .csproj Datei hinzugefügt. Ihre .csproj Datei sollte den folgenden XML-Code enthalten:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <SuppressNETCoreSdkPreviewMessage>true</SuppressNETCoreSdkPreviewMessage>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="AIShell.Abstraction" Version="1.0.0-preview.2" />
  </ItemGroup>
</Project>

Wichtig

Vergewissern Sie sich, dass Sie die neueste Version aus dem NuGet-Katalog verwenden.

Schritt 3: Implementieren der Agentklasse

Um die ILLMAgent Schnittstelle zu implementieren, ändern Sie die Class1.cs Datei.

  1. Umbenennen der Datei in OllamaAgent.cs
  2. Benennen Sie die Klasse in OllamaAgent um.
  3. Fügen Sie die .NET-Namespaces hinzu, die vom Code in der Implementierung verwendet werden.
using System.Diagnostics;
using System.Text;
using System.Text.Json;
using AIShell.Abstraction;

namespace AIShell.Ollama.Agent;

public sealed class OllamaAgent : ILLMAgent
{

}

Schritt 4: Hinzufügen erforderlicher Klassenmmber und -methoden

Implementieren Sie als Nächstes die erforderlichen Variablen und Methoden der Agentklasse. Die Kommentare enthalten Beschreibungen der Member der OllamaAgent Klasse. Der _chatService Member ist eine Instanz der OllamaChatService-Klasse , die Sie in einem späteren Schritt implementieren.

public sealed class OllamaAgent : ILLMAgent
{
    /// <summary>
    /// The name of the agent
    /// </summary>
    public string Name => "ollama";

    /// <summary>
    /// The description of the agent to be shown at start up
    /// </summary>
    public string Description => "This is an AI assistant that uses the Ollama CLI tool. Be sure to follow all prerequisites in https://aka.ms/ollama/readme";

    /// <summary>
    /// This is the company added to `/like` and `/dislike` verbiage for who the telemetry helps.
    /// </summary>
    public string Company => "Microsoft";

    /// <summary>
    /// These are samples that are shown at start up for good questions to ask the agent
    /// </summary>
    public List<string> SampleQueries => [
        "How do I list files in a given directory?"
    ];

    /// <summary>
    /// These are any optional legal/additional information links you want to provide at start up
    /// </summary>
    public Dictionary<string, string> LegalLinks { private set; get; }

    /// <summary>
    /// This is the chat service to call the API from
    /// </summary>
    private OllamaChatService _chatService;

    /// <summary>
    /// A string builder to render the text at the end
    /// </summary>
    private StringBuilder _text;

    /// <summary>
    /// Dispose method to clean up the unmanaged resource of the chatService
    /// </summary>
    public void Dispose()
    {
        _chatService?.Dispose();
    }

    /// <summary>
    /// Initializing function for the class when the shell registers an agent
    /// </summary>
    /// <param name="config">Agent configuration for any configuration file and other settings</param>
    public void Initialize(AgentConfig config)
    {
        _text = new StringBuilder();
        _chatService = new OllamaChatService();

        LegalLinks = new(StringComparer.OrdinalIgnoreCase)
        {
            ["Ollama Docs"] = "https://github.com/ollama/ollama",
            ["Prerequisites"] = "https://aka.ms/ollama/readme"
        };

    }

    /// <summary>
    /// Get commands that an agent can register to the shell when being loaded
    /// </summary>
    public IEnumerable<CommandBase> GetCommands() => null;

    /// <summary>
    /// Gets the path to the setting file of the agent.
    /// </summary>
    public string SettingFile { private set; get; } = null;

    /// <summary>
    /// Refresh the current chat by starting a new chat session.
    /// An agent can reset chat states in this method.
    /// </summary>
    public void RefreshChat() {}

    /// <summary>
    /// Gets a value indicating whether the agent accepts a specific user action feedback.
    /// </summary>
    /// <param name="action">The user action.</param>
    public bool CanAcceptFeedback(UserAction action) => false;

    /// <summary>
    /// A user action was taken against the last response from this agent.
    /// </summary>
    /// <param name="action">Type of the action.</param>
    /// <param name="actionPayload"></param>
    public void OnUserAction(UserActionPayload actionPayload) {}

    /// <summary>
    /// Main chat function that takes
    /// </summary>
    /// <param name="input">The user input from the chat experience</param>
    /// <param name="shell">The shell that provides host functionality</param>
    /// <returns>Task Boolean that indicates whether the query was served by the agent.</returns>
    public async Task<bool> Chat(string input, IShell shell)
    {

    }
}

Bei der ersten Implementierung gibt der Agent to "Hello World!" zurück, um zu beweisen, dass Sie die richtigen Schnittstellen erstellt haben. Sie müssen auch einen try-catch Block hinzufügen, um Ausnahmen abzufangen und zu behandeln, wenn der Benutzer versucht, den Vorgang abzubrechen.

Fügen Sie der Chat-Methode den folgenden Code hinzu.

public async Task<bool> Chat(string input, IShell shell)
{
    // Get the shell host
    IHost host = shell.Host;

    // get the cancellation token
    CancellationToken token = shell.CancellationToken;

    try
    {
       host.RenderFullResponse("Hello World!");
    }
    catch (OperationCanceledException e)
    {
        _text.AppendLine(e.ToString());

        host.RenderFullResponse(_text.ToString());

        return false;
    }

    return true;
}

Schritt 5: Hinzufügen von Ollama Check

Als Nächstes müssen Sie sicherstellen, dass Ollama ausgeführt wird.

public async Task<bool> Chat(string input, IShell shell)
{
    // Get the shell host
    IHost host = shell.Host;

    // get the cancellation token
    CancellationToken token = shell.CancellationToken;

    if (Process.GetProcessesByName("ollama").Length is 0)
    {
        host.RenderFullResponse("Please be sure that Ollama is installed and the server is running. Ensure that you have met all the prerequisites in the README for this agent.");
        return false;
    }

    // Calls to the API will go here

    return true;
}

Schritt 6: Erstellen von Datenstrukturen zum Austauschen von Daten mit dem Chatdienst

Bevor Sie die Ollama-API verwenden können, müssen Sie Klassen erstellen, die Eingaben senden und Antworten von der Ollama-API empfangen. Das folgende Ollama-Beispiel zeigt das Format der Eingabe und die Antwort des Agents.

In diesem Beispiel wird die Ollama-API mit deaktiviertem Streaming aufgerufen. Ollama generiert eine einzelne, feste Antwort. In Zukunft könnten Sie Streamingfunktionen hinzufügen, damit Antworten in Echtzeit gerendert werden können, da der Agent sie empfängt.

Um die Datenstrukturen zu definieren, erstellen Sie eine neue Datei im selben Ordner namens OllamaSchema.cs. Kopieren Sie den folgenden Code in die Datei.

namespace AIShell.Ollama.Agent;

// Query class for the data to send to the endpoint
internal class Query
{
    public string prompt { get; set; }
    public string model { get; set; }

    public bool stream { get; set; }
}

// Response data schema
internal class ResponseData
{
    public string model { get; set; }
    public string created_at { get; set; }
    public string response { get; set; }
    public bool done { get; set; }
    public string done_reason { get; set; }
    public int[] context { get; set; }
    public double total_duration { get; set; }
    public long load_duration { get; set; }
    public int prompt_eval_count { get; set; }
    public int prompt_eval_duration { get; set; }
    public int eval_count { get; set; }
    public long eval_duration { get; set; }
}

internal class OllamaResponse
{
    public int Status { get; set; }
    public string Error { get; set; }
    public string Api_version { get; set; }
    public ResponseData Data { get; set; }
}

Jetzt haben Sie die Teile, die zum Erstellen eines Chatdiensts erforderlich sind, der die Ollama-API verwendet. Eine separate Chatdienstklasse ist nicht erforderlich, aber es ist nützlich, die Aufrufe der API abstrahieren.

Erstellen Sie eine neue Datei namens OllamaChatService.cs im selben Ordner wie der Agent. Kopieren Sie den Beispielcode in die Datei.

Tipp

In diesem Beispiel wird ein hartcodierter Endpunkt und ein Sprachmodell für die Ollama-API verwendet. In Zukunft können Sie konfigurierbare Parameter in einer Agent-Konfigurationsdatei definieren.

using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;

using AIShell.Abstraction;

namespace AIShell.Ollama.Agent;

internal class OllamaChatService : IDisposable
{
    /// <summary>
    /// Ollama endpoint to call to generate a response
    /// </summary>
    internal const string Endpoint = "http://localhost:11434/api/generate";

    /// <summary>
    /// Http client
    /// </summary>
    private readonly HttpClient _client;

    /// <summary>
    /// Initialization method to initialize the http client
    /// </summary>

    internal OllamaChatService()
    {
        _client = new HttpClient();
    }

    /// <summary>
    /// Dispose of the http client
    /// </summary>
    public void Dispose()
    {
        _client.Dispose();
    }

    /// <summary>
    /// Preparing chat with data to be sent
    /// </summary>
    /// <param name="input">The user input from the chat experience</param>
    /// <returns>The HTTP request message</returns>
    private HttpRequestMessage PrepareForChat(string input)
    {
        // Main data to send to the endpoint
        var requestData = new Query
        {
            model = "phi3",
            prompt = input,
            stream = false
        };

        var json = JsonSerializer.Serialize(requestData);

        var data = new StringContent(json, Encoding.UTF8, "application/json");
        var request = new HttpRequestMessage(HttpMethod.Post, Endpoint) { Content = data };

        return request;
    }

    /// <summary>
    /// Getting the chat response async
    /// </summary>
    /// <param name="context">Interface for the status context used when displaying a spinner.</param>
    /// <param name="input">The user input from the chat experience</param>
    /// <param name="cancellationToken">The cancellation token to exit out of request</param>
    /// <returns>Response data from the API call</returns>
    internal async Task<ResponseData> GetChatResponseAsync(IStatusContext context, string input, CancellationToken cancellationToken)
    {
        try
        {
            HttpRequestMessage request = PrepareForChat(input);
            HttpResponseMessage response = await _client.SendAsync(request, cancellationToken);
            response.EnsureSuccessStatusCode();

            context?.Status("Receiving Payload ...");
            Console.Write(response.Content);
            var content = await response.Content.ReadAsStreamAsync(cancellationToken);
            return JsonSerializer.Deserialize<ResponseData>(content);
        }
        catch (OperationCanceledException)
        {
            // Operation was cancelled by user.
        }

        return null;
    }
}

Schritt 7: Anrufen des Chatdiensts

Als Nächstes müssen Sie den Chatdienst in der Haupt-Agent-Klasse anrufen. Ändern Sie die Chat()-Methode, um den Chatdienst aufzurufen und die Antwort auf den Benutzer zu rendern. Das folgende Beispiel zeigt die abgeschlossene Chat()-Methode.

public async Task<bool> Chat(string input, IShell shell)
{
    // Get the shell host
    IHost host = shell.Host;

    // get the cancellation token
    CancellationToken token = shell.CancellationToken;

    if (Process.GetProcessesByName("ollama").Length is 0)
    {
        host.RenderFullResponse("Please be sure that Ollama is installed and the server is running. Ensure that you have met all the prerequisites in the README for this agent.");
        return false;
    }

    ResponseData ollamaResponse = await host.RunWithSpinnerAsync(
        status: "Thinking ...",
        func: async context => await _chatService.GetChatResponseAsync(context, input, token)
    ).ConfigureAwait(false);

    if (ollamaResponse is not null)
    {
        // render the content
        host.RenderFullResponse(ollamaResponse.response);
    }

    return true;
}

Der Agentcode ist abgeschlossen.

Schritt 8: Erstellen und Testen des Agents

Als Nächstes müssen Sie erstellen und testen, dass der Code wie erwartet funktioniert. Führen Sie den folgenden Befehl aus:

dotnet build

Mit diesem Befehl werden alle erforderlichen Pakete im Ordner \bin\Debug\net8.0 des Projekts erstellt.

Damit aish Agent geladen werden kann, müssen Sie die .dll Dateien in einen Ordner im ordner Agents kopieren. Der Ordnername sollte mit dem Agentnamen identisch sein.

Sie können Agents an einem von zwei Speicherorten installieren:

  • Im Ordner Agents unter dem Speicherort, an dem Sie aish.exeinstalliert haben. Das [installationsskript][08] für AI Shell wird in %LOCALAPPDATA%\Programs\AIShellinstalliert. Erstellen Sie den ordner "%LOCALAPPDATA%\Programs\AIShell\Agents\OllamaAgent".
  • Alternativ installieren Sie Agents in %USERPROFILE%\.aish\Agents. Erstellen Sie den ordner "%USERPROFILE%\.aish\Agents\OllamaAgent".

Kopieren Sie die .dll Dateien in den von Ihnen erstellten Agentordner. Sie sollten den Agent sehen, wenn Sie aishstarten.

AI Shell
v1.0.0-preview.2

Please select an agent to use:

    azure
   >ollama
    openai-gpt

Wie kann ich meinen eigenen Agenten teilen?

Es gibt keine Möglichkeit, Ihre Agenten in einem zentralen Repository freizugeben. Wir empfehlen, dieses Repository für die Entwicklung Ihres eigenen Agents zu erstellen. Sie können im Abschnitt Agent Sharing des Diskussionen Registerkarte dieses Repositorys einen Link freigeben, den Sie freizugeben haben. Um einen Agenten zu verwenden, legen Sie die Agent-Dateien dll im agents Ordner des Basisverzeichnisses von aish.exeab. AI Shell lädt die Agents automatisch aus diesem Ordner.