mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-08-11 17:32:11 +00:00
Codex-based code review
This commit is contained in:
parent
c827ba2cd8
commit
c13255fe77
@ -2,6 +2,7 @@ using System.Globalization;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
using AIStudio.Components;
|
||||
using AIStudio.Provider;
|
||||
using AIStudio.Settings;
|
||||
using AIStudio.Settings.DataModel;
|
||||
using AIStudio.Tools;
|
||||
@ -79,6 +80,18 @@ public sealed record ChatThread
|
||||
/// </summary>
|
||||
public DataSourceSecurity DataSecurity { get; set; } = DataSourceSecurity.NOT_SPECIFIED;
|
||||
|
||||
/// <summary>
|
||||
/// The minimum confidence required for providers that continue this chat after a tool returned sensitive data.
|
||||
/// </summary>
|
||||
[JsonInclude]
|
||||
public ConfidenceLevel RequiredProviderConfidence { get; private set; } = ConfidenceLevel.NONE;
|
||||
|
||||
public void RequireProviderConfidence(ConfidenceLevel minimumProviderConfidence)
|
||||
{
|
||||
if (minimumProviderConfidence > this.RequiredProviderConfidence)
|
||||
this.RequiredProviderConfidence = minimumProviderConfidence;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The name of the chat thread. Usually generated by an AI model or manually edited by the user.
|
||||
/// </summary>
|
||||
|
||||
@ -27,6 +27,17 @@ public static class ChatThreadExtensions
|
||||
if (chatThread is null)
|
||||
return true;
|
||||
|
||||
var settingsManager = Program.SERVICE_PROVIDER.GetRequiredService<SettingsManager>();
|
||||
var providerConfidence = provider switch
|
||||
{
|
||||
IProvider p => p.Provider.GetConfidence(settingsManager).Level,
|
||||
AIStudio.Settings.Provider p => p.UsedLLMProvider.GetConfidence(settingsManager).Level,
|
||||
|
||||
_ => ConfidenceLevel.UNKNOWN,
|
||||
};
|
||||
if (providerConfidence < chatThread.RequiredProviderConfidence)
|
||||
return false;
|
||||
|
||||
// The chat thread is available, but the data security is not specified.
|
||||
// Means, we never used RAG or RAG was enabled, but no data sources were selected.
|
||||
// That's fine as well:
|
||||
@ -36,7 +47,6 @@ public static class ChatThreadExtensions
|
||||
//
|
||||
// Is the provider trusted for data-source security checks?
|
||||
//
|
||||
var settingsManager = Program.SERVICE_PROVIDER.GetRequiredService<SettingsManager>();
|
||||
var isTrustedProvider = provider switch
|
||||
{
|
||||
IProvider p => p.IsTrustedForDataSourceSecurityChecks(settingsManager),
|
||||
@ -57,4 +67,4 @@ public static class ChatThreadExtensions
|
||||
false => chatThread.DataSecurity is not DataSourceSecurity.SELF_HOSTED,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
}
|
||||
|
||||
<SettingsPanelApp AvailableLLMProvidersFunc="@(() => this.availableLLMProviders)"/>
|
||||
|
||||
|
||||
<SettingsPanelTools />
|
||||
|
||||
@if (PreviewFeatures.PRE_RAG_2024.IsEnabled(this.SettingsManager))
|
||||
|
||||
@ -1083,48 +1083,54 @@ public abstract class BaseProvider : IProvider, ISecretId
|
||||
yield break;
|
||||
}
|
||||
|
||||
await ShowToolRuntimeStatusAsync(toolCalls
|
||||
.Select(x => runnableTools.FirstOrDefault(tool => tool.Definition.Function.Name.Equals(x.Function.Name, StringComparison.Ordinal)).Implementation?.GetDisplayName() ?? x.Function.Name));
|
||||
|
||||
internalMessages.Add(new AssistantToolCallMessage
|
||||
try
|
||||
{
|
||||
Content = responseMessage.Content,
|
||||
ToolCalls = toolCalls,
|
||||
});
|
||||
await ShowToolRuntimeStatusAsync(toolCalls
|
||||
.Select(x => runnableTools.FirstOrDefault(tool => tool.Definition.Function.Name.Equals(x.Function.Name, StringComparison.Ordinal)).Implementation?.GetDisplayName() ?? x.Function.Name));
|
||||
|
||||
foreach (var toolCall in toolCalls)
|
||||
{
|
||||
if (toolCallCount >= ToolSelectionRules.MAX_TOOL_CALLS)
|
||||
internalMessages.Add(new AssistantToolCallMessage
|
||||
{
|
||||
var finalResponseInstruction = ToolSelectionRules.GetMaxToolCallsFinalResponseInstruction();
|
||||
Content = responseMessage.Content,
|
||||
ToolCalls = toolCalls,
|
||||
});
|
||||
|
||||
foreach (var toolCall in toolCalls)
|
||||
{
|
||||
if (toolCallCount >= ToolSelectionRules.MAX_TOOL_CALLS)
|
||||
{
|
||||
var finalResponseInstruction = ToolSelectionRules.GetMaxToolCallsFinalResponseInstruction();
|
||||
internalMessages.Add(new ToolResultMessage
|
||||
{
|
||||
Content = finalResponseInstruction,
|
||||
ToolCallId = toolCall.Id,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
toolCallCount++;
|
||||
var (toolContent, trace, requiredProviderConfidence) = await toolExecutor.ExecuteAsync(
|
||||
toolCall.Id,
|
||||
toolCall.Function.Name,
|
||||
toolCall.Function.Arguments,
|
||||
runnableTools,
|
||||
this.Provider.GetConfidence(settingsManager).Level,
|
||||
toolCallCount,
|
||||
token);
|
||||
|
||||
chatThread.RequireProviderConfidence(requiredProviderConfidence);
|
||||
currentAssistantContent?.ToolInvocations.Add(trace);
|
||||
internalMessages.Add(new ToolResultMessage
|
||||
{
|
||||
Content = finalResponseInstruction,
|
||||
Content = toolContent,
|
||||
ToolCallId = toolCall.Id,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
toolCallCount++;
|
||||
var (toolContent, trace) = await toolExecutor.ExecuteAsync(
|
||||
toolCall.Id,
|
||||
toolCall.Function.Name,
|
||||
toolCall.Function.Arguments,
|
||||
runnableTools,
|
||||
this.Provider.GetConfidence(settingsManager).Level,
|
||||
toolCallCount,
|
||||
token);
|
||||
|
||||
currentAssistantContent?.ToolInvocations.Add(trace);
|
||||
internalMessages.Add(new ToolResultMessage
|
||||
{
|
||||
Content = toolContent,
|
||||
ToolCallId = toolCall.Id,
|
||||
});
|
||||
}
|
||||
|
||||
if (currentAssistantContent is not null)
|
||||
await currentAssistantContent.StreamingEvent();
|
||||
finally
|
||||
{
|
||||
await ResetToolRuntimeStatusAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -227,8 +227,10 @@ public sealed class ProviderOpenAI() : BaseProvider(LLMProviders.OPEN_AI, new Ur
|
||||
{
|
||||
await foreach (var content in this.StreamResponsesWithLocalTools(
|
||||
chatModel,
|
||||
chatThread,
|
||||
baseInput,
|
||||
apiParameters,
|
||||
providerTools,
|
||||
runnableTools,
|
||||
toolExecutor,
|
||||
currentAssistantContent,
|
||||
@ -308,8 +310,10 @@ public sealed class ProviderOpenAI() : BaseProvider(LLMProviders.OPEN_AI, new Ur
|
||||
|
||||
private async IAsyncEnumerable<ContentStreamChunk> StreamResponsesWithLocalTools(
|
||||
Model chatModel,
|
||||
ChatThread chatThread,
|
||||
IList<object> baseInput,
|
||||
IDictionary<string, object> apiParameters,
|
||||
IList<object> providerTools,
|
||||
IReadOnlyList<(ToolDefinition Definition, IToolImplementation Implementation)> runnableTools,
|
||||
ToolExecutor toolExecutor,
|
||||
ContentText? currentAssistantContent,
|
||||
@ -317,9 +321,16 @@ public sealed class ProviderOpenAI() : BaseProvider(LLMProviders.OPEN_AI, new Ur
|
||||
ConfidenceLevel providerConfidence,
|
||||
[EnumeratorCancellation] CancellationToken token)
|
||||
{
|
||||
var providerTools = runnableTools
|
||||
var localProviderTools = runnableTools
|
||||
.Select(x => (object)ProviderToolAdapters.ToResponsesTool(x.Definition))
|
||||
.ToList();
|
||||
var localFunctionNames = runnableTools
|
||||
.Select(x => x.Definition.Function.Name)
|
||||
.ToHashSet(StringComparer.Ordinal);
|
||||
var effectiveProviderTools = providerTools
|
||||
.Where(x => x is not ProviderTool providerTool || !localFunctionNames.Contains(providerTool.Type))
|
||||
.Concat(localProviderTools)
|
||||
.ToList();
|
||||
// Preserve every output item required to continue the response, including
|
||||
// reasoning items emitted alongside function calls.
|
||||
var internalItems = new List<object>();
|
||||
@ -344,7 +355,7 @@ public sealed class ProviderOpenAI() : BaseProvider(LLMProviders.OPEN_AI, new Ur
|
||||
Input = requestInput,
|
||||
Stream = false,
|
||||
Store = false,
|
||||
Tools = finalResponseRequired ? [] : providerTools,
|
||||
Tools = finalResponseRequired ? [] : effectiveProviderTools,
|
||||
AdditionalApiParameters = apiParameters,
|
||||
};
|
||||
var response = await this.ExecuteResponsesRequest(requestDto, requestedSecret, token);
|
||||
@ -381,45 +392,51 @@ public sealed class ProviderOpenAI() : BaseProvider(LLMProviders.OPEN_AI, new Ur
|
||||
yield break;
|
||||
}
|
||||
|
||||
await ShowToolRuntimeStatusAsync(currentAssistantContent, functionCalls
|
||||
.Select(x => runnableTools.FirstOrDefault(tool => tool.Definition.Function.Name.Equals(x.Name, StringComparison.Ordinal)).Implementation?.GetDisplayName() ?? x.Name));
|
||||
|
||||
foreach (var outputItem in response.Output)
|
||||
internalItems.Add(outputItem);
|
||||
|
||||
foreach (var functionCall in functionCalls)
|
||||
try
|
||||
{
|
||||
if (toolCallCount >= ToolSelectionRules.MAX_TOOL_CALLS)
|
||||
await ShowToolRuntimeStatusAsync(currentAssistantContent, functionCalls
|
||||
.Select(x => runnableTools.FirstOrDefault(tool => tool.Definition.Function.Name.Equals(x.Name, StringComparison.Ordinal)).Implementation?.GetDisplayName() ?? x.Name));
|
||||
|
||||
foreach (var outputItem in response.Output)
|
||||
internalItems.Add(outputItem);
|
||||
|
||||
foreach (var functionCall in functionCalls)
|
||||
{
|
||||
var finalResponseInstruction = ToolSelectionRules.GetMaxToolCallsFinalResponseInstruction();
|
||||
if (toolCallCount >= ToolSelectionRules.MAX_TOOL_CALLS)
|
||||
{
|
||||
var finalResponseInstruction = ToolSelectionRules.GetMaxToolCallsFinalResponseInstruction();
|
||||
internalItems.Add(new ResponsesFunctionCallOutputItem
|
||||
{
|
||||
CallId = functionCall.CallId,
|
||||
Output = finalResponseInstruction,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
toolCallCount++;
|
||||
var (toolContent, trace, requiredProviderConfidence) = await toolExecutor.ExecuteAsync(
|
||||
functionCall.CallId,
|
||||
functionCall.Name,
|
||||
functionCall.Arguments,
|
||||
runnableTools,
|
||||
providerConfidence,
|
||||
toolCallCount,
|
||||
token);
|
||||
|
||||
chatThread.RequireProviderConfidence(requiredProviderConfidence);
|
||||
currentAssistantContent?.ToolInvocations.Add(trace);
|
||||
internalItems.Add(new ResponsesFunctionCallOutputItem
|
||||
{
|
||||
CallId = functionCall.CallId,
|
||||
Output = finalResponseInstruction,
|
||||
Output = toolContent,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
toolCallCount++;
|
||||
var (toolContent, trace) = await toolExecutor.ExecuteAsync(
|
||||
functionCall.CallId,
|
||||
functionCall.Name,
|
||||
functionCall.Arguments,
|
||||
runnableTools,
|
||||
providerConfidence,
|
||||
toolCallCount,
|
||||
token);
|
||||
|
||||
currentAssistantContent?.ToolInvocations.Add(trace);
|
||||
internalItems.Add(new ResponsesFunctionCallOutputItem
|
||||
{
|
||||
CallId = functionCall.CallId,
|
||||
Output = toolContent,
|
||||
});
|
||||
}
|
||||
|
||||
if (currentAssistantContent is not null)
|
||||
await currentAssistantContent.StreamingEvent();
|
||||
finally
|
||||
{
|
||||
await ResetToolRuntimeStatusAsync(currentAssistantContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -769,7 +769,7 @@ public static partial class ManagedConfiguration
|
||||
|
||||
var successful = false;
|
||||
var configuredValue = CloneStringDictionary(configMeta.Default);
|
||||
|
||||
|
||||
// Step 1 -- try to read the Lua value (we expect a table) out of the Lua table:
|
||||
if (settings.TryGetValue(SettingsManager.ToSettingName(propertyExpression), out var configuredLuaList) &&
|
||||
configuredLuaList.Type is LuaValueType.Table &&
|
||||
|
||||
@ -136,7 +136,8 @@ public sealed class ReadWebPageTool(WebPageRetrievalService webPageRetrievalServ
|
||||
|
||||
return new ToolExecutionResult
|
||||
{
|
||||
JsonContent = BuildModelContent(page, extractedPage, retrievedPage.RetrievedAtUtc, markdown, originalContentCharacters, contentTruncated, warnings)
|
||||
JsonContent = BuildModelContent(page, extractedPage, retrievedPage.RetrievedAtUtc, markdown, originalContentCharacters, contentTruncated, warnings),
|
||||
RequiredProviderConfidence = retrievedPage.RequiredProviderConfidence,
|
||||
};
|
||||
}
|
||||
|
||||
@ -161,7 +162,7 @@ public sealed class ReadWebPageTool(WebPageRetrievalService webPageRetrievalServ
|
||||
var warningArray = new JsonArray();
|
||||
foreach (var warning in warnings)
|
||||
warningArray.Add(warning);
|
||||
|
||||
|
||||
AddIfNotEmpty(metadata, "language", extractedPage.Language);
|
||||
AddIfNotEmpty(metadata, "published_time", extractedPage.PublishedTime);
|
||||
AddIfNotEmpty(metadata, "modified_time", extractedPage.ModifiedTime);
|
||||
@ -172,16 +173,16 @@ public sealed class ReadWebPageTool(WebPageRetrievalService webPageRetrievalServ
|
||||
metadata["original_content_characters"] = originalContentCharacters;
|
||||
metadata["returned_content_characters"] = websiteContentAsMarkdown.Length;
|
||||
}
|
||||
|
||||
|
||||
var content = new JsonObject
|
||||
{
|
||||
["text_content"] = websiteContentAsMarkdown,
|
||||
};
|
||||
|
||||
|
||||
AddIfNotEmpty(content, "title", extractedPage.Title);
|
||||
AddIfNotEmpty(content, "description", extractedPage.Description);
|
||||
AddStringArrayIfNotEmpty(content, "authors", extractedPage.Authors);
|
||||
|
||||
|
||||
|
||||
var result = new JsonObject
|
||||
{
|
||||
@ -191,7 +192,7 @@ public sealed class ReadWebPageTool(WebPageRetrievalService webPageRetrievalServ
|
||||
["content"] = content,
|
||||
["metadata"] = metadata,
|
||||
};
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -24,6 +24,8 @@ public sealed class ToolExecutionResult
|
||||
|
||||
public JsonNode? JsonContent { get; init; }
|
||||
|
||||
public ConfidenceLevel RequiredProviderConfidence { get; init; } = ConfidenceLevel.NONE;
|
||||
|
||||
public string ToModelContent()
|
||||
{
|
||||
if (this.JsonContent is not null)
|
||||
|
||||
@ -9,7 +9,7 @@ namespace AIStudio.Tools.ToolCallingSystem;
|
||||
|
||||
public sealed class ToolExecutor(ToolSettingsService toolSettingsService, ILogger<ToolExecutor> logger)
|
||||
{
|
||||
public async Task<(string Content, ToolInvocationTrace Trace)> ExecuteAsync(
|
||||
public async Task<(string Content, ToolInvocationTrace Trace, ConfidenceLevel RequiredProviderConfidence)> ExecuteAsync(
|
||||
string toolCallId,
|
||||
string toolName,
|
||||
string argumentsJson,
|
||||
@ -49,7 +49,7 @@ public sealed class ToolExecutor(ToolSettingsService toolSettingsService, ILogge
|
||||
StatusMessage = "Tool is not available in the current context.",
|
||||
Arguments = formattedArguments,
|
||||
Result = error,
|
||||
});
|
||||
}, ConfidenceLevel.NONE);
|
||||
}
|
||||
|
||||
var definition = runnableTool.Definition;
|
||||
@ -66,7 +66,7 @@ public sealed class ToolExecutor(ToolSettingsService toolSettingsService, ILogge
|
||||
ProviderConfidence = providerConfidence,
|
||||
}, token);
|
||||
logger.LogInformation("Completed tool execution. ToolName={ToolName}, ToolCallId={ToolCallId}, DurationMs={DurationMs}, Status={Status}", toolName, toolCallId, stopwatch.ElapsedMilliseconds, ToolInvocationTraceStatus.SUCCESS);
|
||||
|
||||
|
||||
var resultModelContent = result.ToModelContent();
|
||||
var toolInvocationTrace = new ToolInvocationTrace
|
||||
{
|
||||
@ -82,8 +82,8 @@ public sealed class ToolExecutor(ToolSettingsService toolSettingsService, ILogge
|
||||
Result =
|
||||
implementation.FormatTraceResult(result.ToModelContent()),
|
||||
};
|
||||
|
||||
return (resultModelContent, toolInvocationTrace);
|
||||
|
||||
return (resultModelContent, toolInvocationTrace, result.RequiredProviderConfidence);
|
||||
}
|
||||
catch (OperationCanceledException) when (token.IsCancellationRequested)
|
||||
{
|
||||
@ -104,9 +104,9 @@ public sealed class ToolExecutor(ToolSettingsService toolSettingsService, ILogge
|
||||
StatusMessage = exception.Message,
|
||||
Arguments = formattedArguments,
|
||||
Result = exception.Message,
|
||||
};
|
||||
|
||||
return (exception.Message, toolInvocationTrace);
|
||||
};
|
||||
|
||||
return (exception.Message, toolInvocationTrace, ConfidenceLevel.NONE);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
@ -125,8 +125,8 @@ public sealed class ToolExecutor(ToolSettingsService toolSettingsService, ILogge
|
||||
Arguments = formattedArguments,
|
||||
Result = error,
|
||||
};
|
||||
|
||||
return (error, toolInvocationTrace);
|
||||
|
||||
return (error, toolInvocationTrace, ConfidenceLevel.NONE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -37,7 +37,7 @@ public static class ToolSelectionRules
|
||||
var toolPolicyPrompt = $"""
|
||||
# Tool usage instructions:
|
||||
You have multiple tools available. Each tool has a different purpose and usage policy. Choose wisely and if you are not sure, always ask the user for clarification. You must follow the usage policy of each tool to ensure accurate and reliable results. Here are the usage policies for each tool:
|
||||
|
||||
|
||||
{string.Join(Environment.NewLine+Environment.NewLine, policySections)}
|
||||
""";
|
||||
|
||||
|
||||
@ -14,6 +14,7 @@ public sealed class WebPageRetrievalService(HTMLParser htmlParser)
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var triedOsSso = false;
|
||||
var requiredProviderConfidence = ConfidenceLevel.NONE;
|
||||
HTMLParserWebPage page;
|
||||
try
|
||||
{
|
||||
@ -21,7 +22,14 @@ public sealed class WebPageRetrievalService(HTMLParser htmlParser)
|
||||
url,
|
||||
token,
|
||||
options.TimeoutSeconds,
|
||||
async (candidateUrl, validationToken) => await ResolveValidatedUrlAddressesAsync(candidateUrl, options, validationToken),
|
||||
async (candidateUrl, validationToken) =>
|
||||
{
|
||||
var addresses = await ResolveValidatedUrlAddressesAsync(candidateUrl, options, validationToken);
|
||||
if (addresses.Any(IsNonPublicAddress))
|
||||
requiredProviderConfidence = ConfidenceLevel.HIGH;
|
||||
|
||||
return addresses;
|
||||
},
|
||||
MAX_RESPONSE_BYTES,
|
||||
options.UseOsSso ? ExternalWebAuthenticationMode.OS_DEFAULT_CREDENTIALS : ExternalWebAuthenticationMode.NONE,
|
||||
shouldUseDefaultCredentials: (candidateUrl, addresses) =>
|
||||
@ -58,6 +66,7 @@ public sealed class WebPageRetrievalService(HTMLParser htmlParser)
|
||||
Page = page,
|
||||
ExtractedPage = WebPageContentExtractor.Extract(htmlParser, page.Document, page.FinalUrl),
|
||||
RetrievedAtUtc = DateTimeOffset.UtcNow,
|
||||
RequiredProviderConfidence = requiredProviderConfidence,
|
||||
};
|
||||
}
|
||||
|
||||
@ -245,4 +254,6 @@ public sealed class RetrievedWebPage
|
||||
public required ExtractedWebPage ExtractedPage { get; init; }
|
||||
|
||||
public required DateTimeOffset RetrievedAtUtc { get; init; }
|
||||
|
||||
public ConfidenceLevel RequiredProviderConfidence { get; init; } = ConfidenceLevel.NONE;
|
||||
}
|
||||
|
||||
@ -41,9 +41,9 @@
|
||||
},
|
||||
"Microsoft.NET.ILLink.Tasks": {
|
||||
"type": "Direct",
|
||||
"requested": "[9.0.12, )",
|
||||
"resolved": "9.0.12",
|
||||
"contentHash": "StA3kyImQHqDo8A8ZHaSxgASbEuT5UIqgeCvK5SzUPj//xE1QSys421J9pEs4cYuIVwq7CJvWSKxtyH7aPr1LA=="
|
||||
"requested": "[9.0.18, )",
|
||||
"resolved": "9.0.18",
|
||||
"contentHash": "ztGVXB28bi8SeplFmAx+4MkqP1ieA4UNzj/M3qyyz5tLa37Ln8x8LuaXdxzzoOdaucjQBKXSdCMFSbpQaNGIEg=="
|
||||
},
|
||||
"MudBlazor": {
|
||||
"type": "Direct",
|
||||
@ -212,6 +212,6 @@
|
||||
"type": "Project"
|
||||
}
|
||||
},
|
||||
"net9.0/win-x64": {}
|
||||
"net9.0/osx-arm64": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
# v26.7.4, build 249 (2026-07-xx xx:xx UTC)
|
||||
|
||||
- Added model-driven Web Search and Read Web Page tools for supported AI models.
|
||||
- Added organization-wide management for tool availability and all Web Search and Read Web Page settings.
|
||||
|
||||
@ -78,7 +78,7 @@ Example:
|
||||
"demoLabel"
|
||||
]
|
||||
},
|
||||
"policyInstructions": "Use this tool only when the user asks for current weather conditions.",
|
||||
"systemPromptInstructions": "Use this tool only when the user asks for current weather conditions.",
|
||||
"function": {
|
||||
"name": "get_current_weather",
|
||||
"descriptionForLLM": "Get the current weather in a given location.",
|
||||
@ -116,7 +116,7 @@ Example:
|
||||
|
||||
Use stable lower-case IDs with underscores. Keep `id`, `implementationKey`, and `function.name` identical unless there is a clear compatibility reason not to.
|
||||
|
||||
Keep `function.descriptionForLLM` focused on what the tool does. This value is mapped to the provider's function `description` field and is only shown to the LLM. Put sequencing rules, answer-format guidance, or other behavior instructions in `policyInstructions`. When runnable tools are selected, their non-empty policy text is combined centrally and appended to the effective system prompt.
|
||||
Keep `function.descriptionForLLM` focused on what the tool does. This value is mapped to the provider's function `description` field and is only shown to the LLM. Put sequencing rules, answer-format guidance, or other behavior instructions in `systemPromptInstructions`. When runnable tools are selected, their non-empty policy text is combined centrally and appended to the effective system prompt.
|
||||
|
||||
## Implementation
|
||||
|
||||
@ -189,6 +189,8 @@ Use `ValidateConfigurationAsync` when a setting needs more than "required field
|
||||
|
||||
Use `SensitiveTraceArgumentNames` for model-provided arguments that must not be shown in tool traces. Do not return secrets in `TextContent`, `JsonContent`, exception messages, logs, or trace formatting.
|
||||
|
||||
When a tool returns data that future messages must only send to providers at or above a specific confidence level, set `ToolExecutionResult.RequiredProviderConfidence`. AI Studio persists the highest requirement reached by the chat and applies it to later provider checks.
|
||||
|
||||
## Security
|
||||
|
||||
Treat model-provided tool arguments as untrusted input.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user