diff options
| author | tanaka takashi <isazaka@gmail.com> | 2026-08-11 00:15:54 +0900 |
|---|---|---|
| committer | tanaka takashi <isazaka@gmail.com> | 2026-08-11 00:15:54 +0900 |
| commit | d5d0a84e573c833843279c520ce2d5765425ba93 (patch) | |
| tree | b6ce997a545749578f565cfe5a4b31e8d16b5199 /src/Agent.Core/Ollama/OllamaClient.cs | |
| parent | d5b3cb20c6dacd31bb54c52a30a0f64487e30215 (diff) | |
feat: implement LLM skill selection with Ollama structured output
P5残件3項目を実装:
1. Ollama structured output (format param):
- OllamaChatRequestへFormat プロパティ追加 (JsonElement?)
- IOllamaClientへChatStructuredAsync メソッド追加
- OllamaClient.ChatCoreAsync へformat パラメータ追加
- ChatStructuredAsync はtoolsなし、format指定でJSON構造化出力を要求
2. AgentRuntime skill selection step:
- SelectSkillsAsync メソッド追加: メインループ前にOllamaへskill catalogを送信
- structured output で {"selected_skills": ["name"]} を取得
- ParseSelectedSkills: JSON解析、unknown skill名排除、重複排除、最大10件
- structured output非対応モデルはfallback空リスト
- 選択されたskillのInstructionsのみPromptContext.SelectedSkillsへ設定
- Progressive Disclosure Stage 2→3 が完了
3. Skill security/path validation:
- SelectSkillsAsync でsettings.Skillsからのみ選択(unknown name排除)
- SkillLoader でreparse point skip済み(既存実装)
- 選択数上限10件でDoS防止
- Skill load != permission grant 維持: allowed-toolsはSandbox permissionに影響しない
変更対象:
- OllamaModels.cs: OllamaChatRequest.Format プロパティ追加
- IOllamaClient.cs: ChatStructuredAsync メソッド追加
- OllamaClient.cs: ChatCoreAsync へformat パラメータ追加、ChatStructuredAsync 実装
- AgentRuntime.cs: SelectSkillsAsync + ParseSelectedSkills、メインループ前の選択ステップ
検証結果:
- Release build: 警告0、エラー0
- Core tests: 61/61 PASS、skip 0
- Planner tests: 10/10 PASS、skip 0
Diffstat (limited to 'src/Agent.Core/Ollama/OllamaClient.cs')
| -rw-r--r-- | src/Agent.Core/Ollama/OllamaClient.cs | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/src/Agent.Core/Ollama/OllamaClient.cs b/src/Agent.Core/Ollama/OllamaClient.cs index bfd2210..c761081 100644 --- a/src/Agent.Core/Ollama/OllamaClient.cs +++ b/src/Agent.Core/Ollama/OllamaClient.cs @@ -22,10 +22,13 @@ public sealed class OllamaClient : IOllamaClient } public async Task<OllamaResult> ChatAsync(IReadOnlyList<OllamaMessage> messages, double? temperatureOverride, CancellationToken cancellationToken) - => await ChatCoreAsync(messages, temperatureOverride, null, cancellationToken).ConfigureAwait(false); + => await ChatCoreAsync(messages, temperatureOverride, null, null, cancellationToken).ConfigureAwait(false); public async Task<OllamaResult> ChatWithToolsAsync(IReadOnlyList<OllamaMessage> messages, double? temperatureOverride, IReadOnlyList<InternalToolDefinition> tools, CancellationToken cancellationToken) - => await ChatCoreAsync(messages, temperatureOverride, tools, cancellationToken).ConfigureAwait(false); + => await ChatCoreAsync(messages, temperatureOverride, tools, null, cancellationToken).ConfigureAwait(false); + + public async Task<OllamaResult> ChatStructuredAsync(IReadOnlyList<OllamaMessage> messages, double? temperatureOverride, JsonElement format, CancellationToken cancellationToken) + => await ChatCoreAsync(messages, temperatureOverride, null, format, cancellationToken).ConfigureAwait(false); public async Task<bool?> SupportsVisionAsync(CancellationToken cancellationToken) { @@ -42,7 +45,7 @@ public sealed class OllamaClient : IOllamaClient catch (HttpRequestException) { return null; } } - private async Task<OllamaResult> ChatCoreAsync(IReadOnlyList<OllamaMessage> messages, double? temperatureOverride, IReadOnlyList<InternalToolDefinition>? tools, CancellationToken cancellationToken) + private async Task<OllamaResult> ChatCoreAsync(IReadOnlyList<OllamaMessage> messages, double? temperatureOverride, IReadOnlyList<InternalToolDefinition>? tools, JsonElement? format, CancellationToken cancellationToken) { Dictionary<string, JsonElement> options = _settings.Options.ToDictionary(static pair => pair.Key, static pair => pair.Value, StringComparer.Ordinal); if (temperatureOverride is not null) options["temperature"] = JsonSerializer.SerializeToElement(temperatureOverride.Value); @@ -54,7 +57,8 @@ public sealed class OllamaClient : IOllamaClient Think = _settings.Think, KeepAlive = _settings.KeepAlive, Options = options, - Tools = tools?.Select(static tool => new OllamaToolDefinition("function", new OllamaFunctionDefinition(tool.Name, tool.Description, tool.Parameters))).ToArray() + Tools = tools?.Select(static tool => new OllamaToolDefinition("function", new OllamaFunctionDefinition(tool.Name, tool.Description, tool.Parameters))).ToArray(), + Format = format }; for (int attempt = 0; ; attempt++) |
