-
Notifications
You must be signed in to change notification settings - Fork 66
Implement conversation context and streaming with OllamaSharp #310
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 12 commits
24b9e88
f5c0ee4
cdcc98e
c0f8389
0899ddb
bcc5d1e
9c358b8
336a3c3
9b57754
d9d6fac
464d633
fe68d94
fd95d98
ee76005
a217daa
cdbee04
29b4c49
b798172
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,10 +1,32 @@ | ||||||
| using System.Diagnostics; | ||||||
| using System.Text; | ||||||
| using System.Text.Json; | ||||||
| using AIShell.Abstraction; | ||||||
| using OllamaSharp; | ||||||
| using OllamaSharp.Models; | ||||||
|
|
||||||
| namespace AIShell.Ollama.Agent; | ||||||
|
|
||||||
| public sealed class OllamaAgent : ILLMAgent | ||||||
| { | ||||||
| private bool _reloadSettings; | ||||||
| private bool _isDisposed; | ||||||
| private string _configRoot; | ||||||
| private Settings _settings; | ||||||
| private OllamaApiClient _client; | ||||||
| private GenerateRequest _request; | ||||||
| private FileSystemWatcher _watcher; | ||||||
|
|
||||||
| /// <summary> | ||||||
| /// The name of setting file | ||||||
| /// </summary> | ||||||
| private const string SettingFileName = "ollama.config.json"; | ||||||
|
|
||||||
| /// <summary> | ||||||
| /// Gets the settings. | ||||||
| /// </summary> | ||||||
| internal Settings Settings => _settings; | ||||||
|
|
||||||
| /// <summary> | ||||||
| /// The name of the agent | ||||||
| /// </summary> | ||||||
|
|
@@ -13,7 +35,7 @@ public sealed class OllamaAgent : ILLMAgent | |||||
| /// <summary> | ||||||
| /// The description of the agent to be shown at start up | ||||||
| /// </summary> | ||||||
| public string Description => "This is an AI assistant to interact with a language model running locally by utilizing the Ollama CLI tool. Be sure to follow all prerequisites in aka.ms/aish/ollama"; | ||||||
| public string Description => "This is an AI assistant to interact with a language model running locally by utilizing the Ollama CLI tool. Be sure to follow all prerequisites in https://github.com/PowerShell/AIShell/tree/main/shell/agents/AIShell.Ollama.Agent"; | ||||||
|
|
||||||
| /// <summary> | ||||||
| /// This is the company added to /like and /dislike verbiage for who the telemetry helps. | ||||||
|
|
@@ -30,19 +52,25 @@ public sealed class OllamaAgent : ILLMAgent | |||||
| /// <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; | ||||||
| public Dictionary<string, string> LegalLinks { private set; get; } = new(StringComparer.OrdinalIgnoreCase) | ||||||
| { | ||||||
| ["Ollama Docs"] = "https://github.com/ollama/ollama", | ||||||
| ["Prerequisites"] = "https://github.com/PowerShell/AIShell/tree/main/shell/agents/AIShell.Ollama.Agent" | ||||||
| }; | ||||||
|
|
||||||
| /// <summary> | ||||||
| /// Dispose method to clean up the unmanaged resource of the chatService | ||||||
| /// </summary> | ||||||
| public void Dispose() | ||||||
| { | ||||||
| _chatService?.Dispose(); | ||||||
| if (_isDisposed) | ||||||
| { | ||||||
| return; | ||||||
| } | ||||||
|
|
||||||
| GC.SuppressFinalize(this); | ||||||
| _watcher.Dispose(); | ||||||
| _isDisposed = true; | ||||||
| } | ||||||
|
|
||||||
| /// <summary> | ||||||
|
|
@@ -51,13 +79,30 @@ public void Dispose() | |||||
| /// <param name="config">Agent configuration for any configuration file and other settings</param> | ||||||
| public void Initialize(AgentConfig config) | ||||||
| { | ||||||
| _chatService = new OllamaChatService(); | ||||||
| _configRoot = config.ConfigurationRoot; | ||||||
|
|
||||||
| SettingFile = Path.Combine(_configRoot, SettingFileName); | ||||||
| _settings = ReadSettings(); | ||||||
|
|
||||||
| if (_settings is null) | ||||||
| { | ||||||
| // Create the setting file with examples to serve as a template for user to update. | ||||||
| NewExampleSettingFile(); | ||||||
| _settings = ReadSettings(); | ||||||
| } | ||||||
|
|
||||||
| _request = new GenerateRequest() | ||||||
| { | ||||||
| Model = _settings.Model, | ||||||
| Stream = _settings.Stream | ||||||
| }; | ||||||
kborowinski marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
|
|
||||||
| LegalLinks = new(StringComparer.OrdinalIgnoreCase) | ||||||
| _watcher = new FileSystemWatcher(_configRoot, SettingFileName) | ||||||
| { | ||||||
| ["Ollama Docs"] = "https://github.com/ollama/ollama", | ||||||
| ["Prerequisites"] = "https://aka.ms/ollama/readme" | ||||||
| NotifyFilter = NotifyFilters.LastWrite, | ||||||
| EnableRaisingEvents = true, | ||||||
| }; | ||||||
| _watcher.Changed += OnSettingFileChange; | ||||||
| } | ||||||
|
|
||||||
| /// <summary> | ||||||
|
|
@@ -68,7 +113,7 @@ public void Initialize(AgentConfig config) | |||||
| /// <summary> | ||||||
| /// Gets the path to the setting file of the agent. | ||||||
| /// </summary> | ||||||
| public string SettingFile { private set; get; } = null; | ||||||
| public string SettingFile { private set; get; } | ||||||
|
|
||||||
| /// <summary> | ||||||
| /// Gets a value indicating whether the agent accepts a specific user action feedback. | ||||||
|
|
@@ -87,7 +132,19 @@ public void OnUserAction(UserActionPayload actionPayload) {} | |||||
| /// Refresh the current chat by starting a new chat session. | ||||||
| /// This method allows an agent to reset chat states, interact with user for authentication, print welcome message, and more. | ||||||
| /// </summary> | ||||||
| public Task RefreshChatAsync(IShell shell, bool force) => Task.CompletedTask; | ||||||
| public Task RefreshChatAsync(IShell shell, bool force) | ||||||
| { | ||||||
| if (force) | ||||||
| { | ||||||
| // Reload the setting file if needed. | ||||||
| ReloadSettings(); | ||||||
|
|
||||||
| // Reset context | ||||||
| _request.Context = null; | ||||||
| } | ||||||
|
|
||||||
| return Task.CompletedTask; | ||||||
| } | ||||||
|
|
||||||
| /// <summary> | ||||||
| /// Main chat function that takes the users input and passes it to the LLM and renders it. | ||||||
|
|
@@ -103,23 +160,169 @@ public async Task<bool> ChatAsync(string input, IShell shell) | |||||
| // get the cancellation token | ||||||
| CancellationToken token = shell.CancellationToken; | ||||||
|
|
||||||
| // Reload the setting file if needed. | ||||||
| ReloadSettings(); | ||||||
|
|
||||||
| if (Process.GetProcessesByName("ollama").Length is 0) | ||||||
| { | ||||||
| host.RenderFullResponse("Please be sure the Ollama is installed and server is running. Check all the prerequisites in the README of this agent are met."); | ||||||
| host.MarkupWarningLine($"[[{Name}]]: Please be sure the Ollama is installed and server is running. Check all the prerequisites in the README of this agent are met."); | ||||||
|
||||||
| host.MarkupWarningLine($"[[{Name}]]: Please be sure the Ollama is installed and server is running. Check all the prerequisites in the README of this agent are met."); | |
| host.WriteErrorLine($"[{Name}]: Please be sure the Ollama is installed and server is running. Check all the prerequisites in the README of this agent are met."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, given that the prompt will be @ollama when the agent is in use, maybe we don't need to include the [{Name}] part in the error message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, I think we should check if ollama is running only when the Endpoint is set to localhost. This will enable support for remote ollama endpoints.
if (IsLocalHost().IsMatch(_client.Uri.Host) && Process.GetProcessesByName("ollama").Length is 0)
{
host.WriteErrorLine("Please be sure the Ollama is installed and server is running. Check all the prerequisites in the README of this agent are met.");
return false;
}and
/// <summary>
/// Defines a generated regular expression to match localhost addresses
/// "localhost", "127.0.0.1" and "[::1]" with case-insensitivity.
/// </summary>
[GeneratedRegex("^(localhost|127\\.0\\.0\\.1|\\[::1\\])$", RegexOptions.IgnoreCase)]
internal partial Regex IsLocalHost();
Uh oh!
There was an error while loading. Please reload this page.