중요하다
2026년 1월 기준으로 AI 셸 프로젝트는 더 이상 활발히 유지보수되지 않고 있습니다. 이 프로젝트는 공학적 관점에서 보관된 것으로 간주되어야 합니다.
에이전트는 AI Shell과 인터페이스하여 특정 대규모 언어 모델 또는 기타 지원 공급자와 통신하는 코드 라이브러리입니다. 사용자는 자연어를 사용하여 에이전트와 채팅하여 원하는 출력 또는 지원을 받습니다. 에이전트는 ILLMAgent 패키지에서 AIShell.Abstraction 인터페이스를 구현하는 C# 클래스로 구현됩니다.
AIShell.Abstraction 계층 및 AIShell.Kernel대한 자세한 내용은 AI Shell 아키텍처 설명서를 참조하세요.
이 문서는 Ollama 언어 모델용 에이전트를 만드는 단계별 가이드입니다. 이 문서의 목적은 에이전트를 만드는 방법에 대한 간단한 예제를 제공하는 것입니다. 리포지토리의 폴더에 Ollama 에이전트의 보다 강력한 구현이 AIShell.Ollama.Agent 있습니다.
필수 구성 요소
- .NET 8 SDK 이상
- PowerShell 7.4.6 이상
에이전트를 만드는 단계
이 예제에서는 phi3를 사용하여 언어 모델과 통신하는 에이전트를 만듭니다. Ollama는 로컬에서 빌드된 LLM/SLM을 관리하고 사용하기 위한 CLI 도구입니다.
1단계: 새 프로젝트 만들기
첫 번째 단계는 새 classlib 프로젝트를 만드는 것입니다.
OllamaAgent이라는 새 폴더 만들기다음 명령을 실행하여 새 프로젝트를 만듭니다.
dotnet new classlib
2단계: 필요한 패키지 추가
새로 만든 프로젝트 내에서 NuGet 갤러리에서 AIShell.Abstraction 패키지를 설치해야 합니다. 다음 명령을 사용하여 NuGet 패키지를 설치합니다.
dotnet add package AIShell.Abstraction --version 1.0.0-preview.2
이 명령은 .csproj 파일에 패키지를 추가합니다.
.csproj 파일에는 다음 XML이 포함되어야 합니다.
<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>
중요하다
NuGet 갤러리의 최신 버전에 있는지 확인해야 합니다.
3단계: 에이전트 클래스 구현
ILLMAgent 인터페이스를 구현하려면 Class1.cs 파일을 수정합니다.
- 파일 이름을
OllamaAgent.cs - 클래스 이름을
OllamaAgent - 구현의 코드에서 사용하는 .NET 네임스페이스 추가
using System.Diagnostics;
using System.Text;
using System.Text.Json;
using AIShell.Abstraction;
namespace AIShell.Ollama.Agent;
public sealed class OllamaAgent : ILLMAgent
{
}
4단계: 필요한 클래스 멤버 및 메서드 추가
다음으로, 에이전트 클래스의 필요한 변수 및 메서드를 구현합니다. 주석은 OllamaAgent 클래스의 멤버에 대한 설명을 제공합니다. 멤버는 _chatService 이후 단계에서 구현하는 OllamaChatService 클래스의 인스턴스입니다.
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)
{
}
}
초기 구현의 경우 에이전트는 "Hello World!"를 반환하여 올바른 인터페이스를 만들었음을 증명합니다. 또한 사용자가 작업을 취소하려고 할 때 예외를 catch하고 처리하기 위해 블록을 추가해야 try-catch 합니다.
Chat 메서드에 다음 코드를 추가합니다.
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;
}
5단계: Ollama 검사 추가
다음으로 Ollama가 실행 중인지 확인해야 합니다.
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;
}
6단계: 채팅 서비스와 데이터를 교환하는 데이터 구조 만들기
Ollama API를 사용하려면 Ollama API에서 입력을 보내고 응답을 받는 클래스를 만들어야 합니다. 다음 Ollama 예제 입력 형식과 에이전트의 응답을 보여 드립니다.
이 예제에서는 스트리밍을 사용하지 않도록 설정된 Ollama API를 호출합니다. Ollama는 고정된 단일 응답을 생성합니다. 나중에 에이전트가 수신할 때 응답을 실시간으로 렌더링할 수 있도록 스트리밍 기능을 추가할 수 있습니다.
데이터 구조를 정의하려면 OllamaSchema.cs같은 폴더에 새 파일을 만듭니다. 다음 코드를 파일에 복사합니다.
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; }
}
이제 Ollama API를 사용하는 채팅 서비스를 구성하는 데 필요한 부분이 있습니다. 별도의 채팅 서비스 클래스는 필요하지 않지만 API에 대한 호출을 추상화할 때 유용합니다.
에이전트와 동일한 폴더에 OllamaChatService.cs이라는 새 파일을 만듭니다. 예제 코드를 파일에 복사합니다.
팁
이 예제에서는 Ollama API에 하드 코딩된 엔드포인트 및 언어 모델을 사용합니다. 나중에 에이전트 구성 파일에서 구성 가능한 매개 변수를 정의할 수 있습니다.
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;
}
}
7단계: 채팅 서비스 호출
다음으로, 주 에이전트 클래스에서 채팅 서비스를 호출해야 합니다. 채팅 서비스를 호출하고 사용자에게 응답을 렌더링하도록 Chat() 메서드를 수정합니다. 다음 예제에서는 완료된 Chat() 메서드를 보여줍니다.
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;
}
에이전트 코드가 완료되었습니다.
8단계: 에이전트 빌드 및 테스트
다음으로 코드가 예상대로 작동하는지 빌드하고 테스트해야 합니다. 다음 명령을 실행합니다.
dotnet build
이 명령은 프로젝트의 \bin\Debug\net8.0 폴더에 필요한 모든 패키지를 빌드합니다.
에이전트를 aish 로드하려면 .dll 파일을 Agents 폴더의 폴더에 복사해야 합니다.
폴더 이름은 에이전트 이름과 동일해야 합니다.
다음 두 위치 중 하나에 에이전트를 설치할 수 있습니다.
-
Agents설치한 위치 아래의aish.exe폴더에 있습니다. AI Shell용 [install script][08]은%LOCALAPPDATA%\Programs\AIShell설치됩니다.%LOCALAPPDATA%\Programs\AIShell\Agents\OllamaAgent폴더를 만듭니다. - 또는
%USERPROFILE%\.aish\Agents에이전트를 설치합니다.%USERPROFILE%\.aish\Agents\OllamaAgent폴더를 만듭니다.
.dll 파일을 만든 에이전트 폴더에 복사합니다.
aish시작할 때 에이전트가 표시됩니다.
AI Shell
v1.0.0-preview.2
Please select an agent to use:
azure
>ollama
openai-gpt
내 에이전트를 공유하려면 어떻게 해야 하나요?
중앙 집중식 리포지토리에서 에이전트를 공유할 수 있는 방법은 없습니다. 사용자 고유의 에이전트 개발을 위해 이 리포지토리를 포크하는 것이 좋습니다. 이 리포지토리의 Agent Sharing 탭의 섹션에서 포크 링크를 공유할 수 있습니다. 에이전트를 사용하려면 의 기본 디렉토리 dll폴더에 에이전트 agents 파일을 aish.exe 넣습니다. AI Shell은 해당 폴더에서 에이전트를 자동으로 로드합니다.